crypto_pay_api/api/
balance.rs

1use async_trait::async_trait;
2
3use crate::{
4    client::CryptoBot,
5    error::CryptoBotError,
6    models::{APIEndpoint, APIMethod, Balance, Method},
7};
8
9use super::BalanceAPI;
10
11pub struct GetBalanceBuilder<'a> {
12    client: &'a CryptoBot,
13}
14
15impl<'a> GetBalanceBuilder<'a> {
16    pub fn new(client: &'a CryptoBot) -> Self {
17        Self { client }
18    }
19
20    /// Executes the request to get current balance
21    pub async fn execute(self) -> Result<Vec<Balance>, CryptoBotError> {
22        self.client
23            .make_request(
24                &APIMethod {
25                    endpoint: APIEndpoint::GetBalance,
26                    method: Method::GET,
27                },
28                None::<&()>,
29            )
30            .await
31    }
32}
33
34#[async_trait]
35impl BalanceAPI for CryptoBot {
36    /// Gets current balance for all supported cryptocurrencies in your CryptoBot wallet
37    ///
38    /// This method returns the current balance for all cryptocurrencies that are
39    /// available in your CryptoBot wallet, including both crypto and test currencies.
40    ///
41    /// # Returns
42    /// * `GetBalanceBuilder` - A builder to execute the request
43    fn get_balance(&self) -> GetBalanceBuilder<'_> {
44        GetBalanceBuilder::new(self)
45    }
46}
47
48#[cfg(test)]
49mod tests {
50    use mockito::Mock;
51    use rust_decimal_macros::dec;
52    use serde_json::json;
53
54    use crate::{models::CryptoCurrencyCode, utils::test_utils::TestContext};
55
56    use super::*;
57
58    impl TestContext {
59        pub fn mock_balance_response(&mut self) -> Mock {
60            self.server
61                .mock("GET", "/getBalance")
62                .with_header("content-type", "application/json")
63                .with_header("Crypto-Pay-API-Token", "test_token")
64                .with_body(
65                    json!({
66                        "ok": true,
67                        "result": [
68                        {
69                            "currency_code": "TON",
70                            "available": "100.5",
71                            "onhold": "0.0"
72                        },
73                        {
74                            "currency_code": "SEND",
75                            "available": "10.5",
76                            "onhold": "0.0"
77                        }
78                        ]
79                    })
80                    .to_string(),
81                )
82                .create()
83        }
84    }
85
86    #[test]
87    fn test_get_balance() {
88        let mut ctx = TestContext::new();
89        let _m = ctx.mock_balance_response();
90
91        let client = CryptoBot::builder()
92            .api_token("api_token")
93            .base_url(ctx.server.url())
94            .build()
95            .unwrap();
96
97        let result = ctx.run(async { client.get_balance().execute().await });
98
99        assert!(result.is_ok());
100        let balances = result.unwrap();
101        assert_eq!(balances.len(), 2);
102        assert_eq!(balances[0].currency_code, CryptoCurrencyCode::Ton);
103        assert_eq!(balances[0].available, dec!(100.5));
104        assert_eq!(balances[1].currency_code, CryptoCurrencyCode::Send);
105        assert_eq!(balances[1].available, dec!(10.5));
106    }
107}