tob/clients/
siacoin.rs

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        //@todo need url to come as well.
16        ClientType::HTTP => Ok(Box::new(SiacoinClient::new(options))),
17        //Hack for here.
18        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                //@todo completely revamp this section should probably return a error like I say
42                //below, but we want to make sure that the monitor understands to re-try.
43                // info!("Node appeared to not be ready yet. Sleeping for 60 seconds");
44                async_std::task::sleep(std::time::Duration::from_secs(60)).await;
45                //We should return an error here... but oh well
46                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            //We need bigints here actually.
104            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}