Skip to main content

binance_core/client/
synchronous.rs

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