Skip to main content

binance_core/client/
asynchronous.rs

1use crate::signer::signature::Signature;
2use binance_common::error::BinanceError;
3use binance_common::url::UrlEncoded;
4use reqwest::{Method, RequestBuilder, Response, StatusCode};
5use serde::de::DeserializeOwned;
6
7pub struct Client<'a, S>
8where
9    S: Signature<'a>,
10{
11    host: &'a str,
12    signature: S,
13    inner_client: reqwest::Client,
14}
15
16impl<'a, S> Client<'a, S>
17where
18    S: Signature<'a>,
19{
20    pub fn new(host: &'a impl AsRef<str>, signature: S) -> Client<'a, S> {
21        Client {
22            host: host.as_ref(),
23            signature,
24            inner_client: reqwest::Client::new(),
25        }
26    }
27
28    pub async fn get<T>(
29        &self,
30        path: impl AsRef<str>,
31        params: impl UrlEncoded,
32    ) -> Result<T, BinanceError>
33    where
34        T: DeserializeOwned,
35    {
36        let endpoint = format!("{}{}{}", self.host, path.as_ref(), params.to_url_encoded());
37
38        let response = self.inner_client.get(endpoint).send().await?;
39
40        self.handle::<T>(response).await
41    }
42
43    pub async fn send<T>(
44        &self,
45        path: impl AsRef<str>,
46        params: impl UrlEncoded,
47        method: Method,
48    ) -> Result<T, BinanceError>
49    where
50        T: DeserializeOwned,
51    {
52        let request = self.signature.build_request(
53            &self.inner_client,
54            self.host,
55            path.as_ref(),
56            params.to_url_encoded().as_str(),
57            method,
58        )?;
59
60        let response = RequestBuilder::send(request).await?;
61        self.handle::<T>(response).await
62    }
63
64    pub async fn handle<T: DeserializeOwned>(&self, response: Response) -> Result<T, BinanceError> {
65        let status = response.status();
66        let body = response.bytes().await?;
67
68        match status {
69            StatusCode::BAD_REQUEST => {
70                let api_error: binance_common::error::ApiError =
71                    serde_json::from_slice(&body).map_err(BinanceError::Deserialize)?;
72                Err(BinanceError::Api(api_error))
73            }
74
75            StatusCode::IM_A_TEAPOT => Err(BinanceError::IpBanned),
76
77            StatusCode::INTERNAL_SERVER_ERROR => Err(BinanceError::InternalServer),
78
79            StatusCode::OK => {
80                Ok(serde_json::from_slice::<T>(&body).map_err(BinanceError::Deserialize)?)
81            }
82
83            StatusCode::REQUEST_TIMEOUT => Err(BinanceError::RequestTimeout),
84            StatusCode::UNAUTHORIZED => {
85                let api_error: binance_common::error::ApiError =
86                    serde_json::from_slice(&body).map_err(BinanceError::Deserialize)?;
87
88                Err(BinanceError::Api(api_error))
89            }
90            StatusCode::TOO_MANY_REQUESTS => Err(BinanceError::TooManyRequest),
91            status_code => Err(BinanceError::Unknown(format!(
92                "Response Status Code: {}",
93                status_code
94            ))),
95        }
96    }
97}