tob 0.2.13

A helper library that makes calling various nodes easier
Documentation
use crate::client::{Client, ClientType, CryptoClient};
use crate::types::{Amount, ClientOptions, Currency, Symbol, SyncItem, SyncStats, WalletBalance};
use crate::Result;
use async_trait::async_trait;
use num_bigint::BigInt;
use std::str::FromStr;

#[derive(Clone)]
pub struct ChiaClient {
    url: String,
}

pub fn get_client(client_type: ClientType, options: ClientOptions) -> crate::Result<Box<Client>> {
    match client_type {
        //@todo need url to come as well.
        ClientType::HTTP => Ok(Box::new(ChiaClient::new(options))),
        //Hack for here.
        ClientType::RPC => Ok(Box::new(ChiaClient::new(options))),
        _ => Err(crate::error::ClientError::UnsupportedType(client_type)),
    }
}

impl ChiaClient {
    pub fn new(options: ClientOptions) -> Self {
        ChiaClient {
            url: options.url.clone(),
        }
    }
}

#[async_trait]
impl CryptoClient for ChiaClient {
    async fn sync_stats(&self) -> SyncStats {
        let result: serde_json::Value =
            match surf::get(format!("{}{}", &self.url, "/get_blockchain_state"))
                .recv_json()
                .await
            {
                Ok(r) => r,
                Err(_e) => {
                    //@todo completely revamp this section should probably return a error like I say
                    //below, but we want to make sure that the monitor understands to re-try.
                    // info!("Node appeared to not be ready yet. Sleeping for 60 seconds");
                    async_std::task::sleep(std::time::Duration::from_secs(60)).await;
                    //We should return an error here... but oh well
                    return SyncStats {
                        current_block: 0,
                        syncing: true,
                        sync_item: SyncItem::VerificationProgress,
                        estimated_sync_item_remaining: 0.0,
                    };
                }
            };

        dbg!(result);

        // let syncing = result
        //     .as_object()
        //     .unwrap()
        //     .get("synced")
        //     .unwrap()
        //     .as_bool()
        //     .unwrap();
        // let height = result
        //     .as_object()
        //     .unwrap()
        //     .get("height")
        //     .unwrap()
        //     .as_u64()
        //     .unwrap();

        SyncStats {
            current_block: 0,
            syncing: true,
            sync_item: SyncItem::VerificationProgress,
            estimated_sync_item_remaining: 0.0,
        }
    }

    async fn wallet_balance(&self, _identifier: &str) -> Result<WalletBalance> {
        let result: serde_json::Value = surf::get(format!("{}/{}", &self.url, "wallet"))
            .header("User-Agent", "Sia-Agent")
            .recv_json()
            .await?;

        let mut siacoin_multipler = BigInt::from(10);
        siacoin_multipler = siacoin_multipler.pow(24);

        let mut confirmed_balance =
            BigInt::from_str(result["confirmedsiacoinbalance"].as_str().unwrap()).unwrap();
        confirmed_balance = confirmed_balance * siacoin_multipler.clone();

        let mut unconfirmed_outgoing =
            BigInt::from_str(result["unconfirmedoutgoingsiacoins"].as_str().unwrap()).unwrap();
        unconfirmed_outgoing = unconfirmed_outgoing * siacoin_multipler.clone();

        let mut unconfirmed_incoming =
            BigInt::from_str(result["unconfirmedincomingsiacoins"].as_str().unwrap()).unwrap();
        unconfirmed_incoming = unconfirmed_incoming * siacoin_multipler;

        let unconfirmed_balance =
            confirmed_balance.clone() - unconfirmed_incoming - unconfirmed_outgoing;

        Ok(WalletBalance {
            //We need bigints here actually.
            confirmed_balance: Amount {
                value: confirmed_balance,
                currency: Currency {
                    symbol: Symbol::SIA,
                    decimals: 24,
                },
            },
            unconfirmed_balance: Amount {
                value: unconfirmed_balance,
                currency: Currency {
                    symbol: Symbol::SIA,
                    decimals: 24,
                },
            },
        })
    }

    fn client_type(&self) -> ClientType {
        ClientType::HTTP
    }
}