1use crate::client::{Client, ClientType, CryptoClient};
2use crate::types::{Amount, ClientOptions, Currency, Symbol, SyncItem, SyncStats, WalletBalance};
3use crate::Result;
4use async_trait::async_trait;
5use num_bigint::BigInt;
6use std::str::FromStr;
7
8#[derive(Clone)]
9pub struct SiacoinClient {
10 url: String,
11}
12
13pub fn get_client(client_type: ClientType, options: ClientOptions) -> crate::Result<Box<Client>> {
14 match client_type {
15 ClientType::HTTP => Ok(Box::new(SiacoinClient::new(options))),
17 ClientType::RPC => Ok(Box::new(SiacoinClient::new(options))),
19 _ => Err(crate::error::ClientError::UnsupportedType(client_type)),
20 }
21}
22
23impl SiacoinClient {
24 pub fn new(options: ClientOptions) -> Self {
25 SiacoinClient {
26 url: options.url.clone(),
27 }
28 }
29}
30
31#[async_trait]
32impl CryptoClient for SiacoinClient {
33 async fn sync_stats(&self) -> SyncStats {
34 let result: serde_json::Value = match surf::get(&self.url)
35 .header("User-Agent", "Sia-Agent")
36 .recv_json()
37 .await
38 {
39 Ok(r) => r,
40 Err(_e) => {
41 async_std::task::sleep(std::time::Duration::from_secs(60)).await;
45 return SyncStats {
47 current_block: 0,
48 syncing: true,
49 sync_item: SyncItem::VerificationProgress,
50 estimated_sync_item_remaining: 0.0,
51 };
52 }
53 };
54
55 let syncing = result
56 .as_object()
57 .unwrap()
58 .get("synced")
59 .unwrap()
60 .as_bool()
61 .unwrap();
62 let height = result
63 .as_object()
64 .unwrap()
65 .get("height")
66 .unwrap()
67 .as_u64()
68 .unwrap();
69
70 SyncStats {
71 current_block: height,
72 syncing,
73 sync_item: SyncItem::VerificationProgress,
74 estimated_sync_item_remaining: 0.0,
75 }
76 }
77
78 async fn wallet_balance(&self, _identifier: &str) -> Result<WalletBalance> {
79 let result: serde_json::Value = surf::get(format!("{}/{}", &self.url, "wallet"))
80 .header("User-Agent", "Sia-Agent")
81 .recv_json()
82 .await?;
83
84 let mut siacoin_multipler = BigInt::from(10);
85 siacoin_multipler = siacoin_multipler.pow(24);
86
87 let mut confirmed_balance =
88 BigInt::from_str(result["confirmedsiacoinbalance"].as_str().unwrap()).unwrap();
89 confirmed_balance = confirmed_balance * siacoin_multipler.clone();
90
91 let mut unconfirmed_outgoing =
92 BigInt::from_str(result["unconfirmedoutgoingsiacoins"].as_str().unwrap()).unwrap();
93 unconfirmed_outgoing = unconfirmed_outgoing * siacoin_multipler.clone();
94
95 let mut unconfirmed_incoming =
96 BigInt::from_str(result["unconfirmedincomingsiacoins"].as_str().unwrap()).unwrap();
97 unconfirmed_incoming = unconfirmed_incoming * siacoin_multipler;
98
99 let unconfirmed_balance =
100 confirmed_balance.clone() - unconfirmed_incoming - unconfirmed_outgoing;
101
102 Ok(WalletBalance {
103 confirmed_balance: Amount {
105 value: confirmed_balance,
106 currency: Currency {
107 symbol: Symbol::SIA,
108 decimals: 24,
109 },
110 },
111 unconfirmed_balance: Amount {
112 value: unconfirmed_balance,
113 currency: Currency {
114 symbol: Symbol::SIA,
115 decimals: 24,
116 },
117 },
118 })
119 }
120
121 fn client_type(&self) -> ClientType {
122 ClientType::HTTP
123 }
124}