Skip to main content

binance_sdk/c2c/rest_api/apis/
c2_c_api.rs

1/*
2 * Binance C2C REST API
3 *
4 * OpenAPI Specification for the Binance C2C REST API
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::c2c::rest_api::models;
24use crate::common::{
25    config::ConfigurationRestApi,
26    models::{ParamBuildError, RestApiResponse},
27    utils::send_request,
28};
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait C2CApi: Send + Sync {
34    async fn get_c2_c_trade_history(
35        &self,
36        params: GetC2CTradeHistoryParams,
37    ) -> anyhow::Result<RestApiResponse<models::GetC2CTradeHistoryResponse>>;
38}
39
40#[derive(Debug, Clone)]
41pub struct C2CApiClient {
42    configuration: ConfigurationRestApi,
43}
44
45impl C2CApiClient {
46    pub fn new(configuration: ConfigurationRestApi) -> Self {
47        Self { configuration }
48    }
49}
50
51/// Request parameters for the [`get_c2_c_trade_history`] operation.
52///
53/// This struct holds all of the inputs you can pass when calling
54/// [`get_c2_c_trade_history`](#method.get_c2_c_trade_history).
55#[derive(Clone, Debug, Builder, Default)]
56#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
57pub struct GetC2CTradeHistoryParams {
58    /// BUY, SELL
59    ///
60    /// This field is **optional.
61    #[builder(setter(into), default)]
62    pub trade_type: Option<String>,
63    ///
64    /// The `start_timestamp` parameter.
65    ///
66    /// This field is **optional.
67    #[builder(setter(into), default)]
68    pub start_timestamp: Option<i64>,
69    ///
70    /// The `end_timestamp` parameter.
71    ///
72    /// This field is **optional.
73    #[builder(setter(into), default)]
74    pub end_timestamp: Option<i64>,
75    /// Default 1
76    ///
77    /// This field is **optional.
78    #[builder(setter(into), default)]
79    pub page: Option<i64>,
80    /// default 100, max 100
81    ///
82    /// This field is **optional.
83    #[builder(setter(into), default)]
84    pub rows: Option<i64>,
85    ///
86    /// The `recv_window` parameter.
87    ///
88    /// This field is **optional.
89    #[builder(setter(into), default)]
90    pub recv_window: Option<i64>,
91}
92
93impl GetC2CTradeHistoryParams {
94    /// Create a builder for [`get_c2_c_trade_history`].
95    ///
96    #[must_use]
97    pub fn builder() -> GetC2CTradeHistoryParamsBuilder {
98        GetC2CTradeHistoryParamsBuilder::default()
99    }
100}
101
102#[async_trait]
103impl C2CApi for C2CApiClient {
104    async fn get_c2_c_trade_history(
105        &self,
106        params: GetC2CTradeHistoryParams,
107    ) -> anyhow::Result<RestApiResponse<models::GetC2CTradeHistoryResponse>> {
108        let GetC2CTradeHistoryParams {
109            trade_type,
110            start_timestamp,
111            end_timestamp,
112            page,
113            rows,
114            recv_window,
115        } = params;
116
117        let mut query_params = BTreeMap::new();
118        let body_params = BTreeMap::new();
119
120        if let Some(rw) = trade_type {
121            query_params.insert("tradeType".to_string(), json!(rw));
122        }
123
124        if let Some(rw) = start_timestamp {
125            query_params.insert("startTimestamp".to_string(), json!(rw));
126        }
127
128        if let Some(rw) = end_timestamp {
129            query_params.insert("endTimestamp".to_string(), json!(rw));
130        }
131
132        if let Some(rw) = page {
133            query_params.insert("page".to_string(), json!(rw));
134        }
135
136        if let Some(rw) = rows {
137            query_params.insert("rows".to_string(), json!(rw));
138        }
139
140        if let Some(rw) = recv_window {
141            query_params.insert("recvWindow".to_string(), json!(rw));
142        }
143
144        send_request::<models::GetC2CTradeHistoryResponse>(
145            &self.configuration,
146            "/sapi/v1/c2c/orderMatch/listUserOrderHistory",
147            reqwest::Method::GET,
148            query_params,
149            body_params,
150            if HAS_TIME_UNIT {
151                self.configuration.time_unit
152            } else {
153                None
154            },
155            true,
156        )
157        .await
158    }
159}
160
161#[cfg(all(test, feature = "c2c"))]
162mod tests {
163    use super::*;
164    use crate::TOKIO_SHARED_RT;
165    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
166    use async_trait::async_trait;
167    use std::collections::HashMap;
168
169    struct DummyRestApiResponse<T> {
170        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
171        status: u16,
172        headers: HashMap<String, String>,
173        rate_limits: Option<Vec<RestApiRateLimit>>,
174    }
175
176    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
177        fn from(dummy: DummyRestApiResponse<T>) -> Self {
178            Self {
179                data_fn: dummy.inner,
180                status: dummy.status,
181                headers: dummy.headers,
182                rate_limits: dummy.rate_limits,
183            }
184        }
185    }
186
187    struct MockC2CApiClient {
188        force_error: bool,
189    }
190
191    #[async_trait]
192    impl C2CApi for MockC2CApiClient {
193        async fn get_c2_c_trade_history(
194            &self,
195            _params: GetC2CTradeHistoryParams,
196        ) -> anyhow::Result<RestApiResponse<models::GetC2CTradeHistoryResponse>> {
197            if self.force_error {
198                return Err(ConnectorError::ConnectorClientError {
199                    msg: "ResponseError".to_string(),
200                    code: None,
201                }
202                .into());
203            }
204
205            let resp_json: Value = serde_json::from_str(r#"{"orderNumber":"20219644646554779648","advNo":"11218246497340923904","tradeType":"SELL","asset":"USDT","fiat":"CNY","fiatSymbol":"¥","amount":"343.40000000","totalPrice":"2500.00000000","unitPrice":"7.28","orderStatus":"COMPLETED","createTime":1722997599534,"commission":"0","takerCommissionRate":"0","takerCommission":"0","takerAmount":"343.4","counterPartNickName":"aaa-***","payMethodName":"BANK","additionalKycVerify":0}"#).unwrap();
206            let dummy_response: models::GetC2CTradeHistoryResponse =
207                serde_json::from_value(resp_json.clone())
208                    .expect("should parse into models::GetC2CTradeHistoryResponse");
209
210            let dummy = DummyRestApiResponse {
211                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
212                status: 200,
213                headers: HashMap::new(),
214                rate_limits: None,
215            };
216
217            Ok(dummy.into())
218        }
219    }
220
221    #[test]
222    fn get_c2_c_trade_history_required_params_success() {
223        TOKIO_SHARED_RT.block_on(async {
224            let client = MockC2CApiClient { force_error: false };
225
226            let params = GetC2CTradeHistoryParams::builder().build().unwrap();
227
228            let resp_json: Value = serde_json::from_str(r#"{"orderNumber":"20219644646554779648","advNo":"11218246497340923904","tradeType":"SELL","asset":"USDT","fiat":"CNY","fiatSymbol":"¥","amount":"343.40000000","totalPrice":"2500.00000000","unitPrice":"7.28","orderStatus":"COMPLETED","createTime":1722997599534,"commission":"0","takerCommissionRate":"0","takerCommission":"0","takerAmount":"343.4","counterPartNickName":"aaa-***","payMethodName":"BANK","additionalKycVerify":0}"#).unwrap();
229            let expected_response : models::GetC2CTradeHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetC2CTradeHistoryResponse");
230
231            let resp = client.get_c2_c_trade_history(params).await.expect("Expected a response");
232            let data_future = resp.data();
233            let actual_response = data_future.await.unwrap();
234            assert_eq!(actual_response, expected_response);
235        });
236    }
237
238    #[test]
239    fn get_c2_c_trade_history_optional_params_success() {
240        TOKIO_SHARED_RT.block_on(async {
241            let client = MockC2CApiClient { force_error: false };
242
243            let params = GetC2CTradeHistoryParams::builder().trade_type("trade_type_example".to_string()).start_timestamp(789).end_timestamp(789).page(1).rows(100).recv_window(5000).build().unwrap();
244
245            let resp_json: Value = serde_json::from_str(r#"{"orderNumber":"20219644646554779648","advNo":"11218246497340923904","tradeType":"SELL","asset":"USDT","fiat":"CNY","fiatSymbol":"¥","amount":"343.40000000","totalPrice":"2500.00000000","unitPrice":"7.28","orderStatus":"COMPLETED","createTime":1722997599534,"commission":"0","takerCommissionRate":"0","takerCommission":"0","takerAmount":"343.4","counterPartNickName":"aaa-***","payMethodName":"BANK","additionalKycVerify":0}"#).unwrap();
246            let expected_response : models::GetC2CTradeHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetC2CTradeHistoryResponse");
247
248            let resp = client.get_c2_c_trade_history(params).await.expect("Expected a response");
249            let data_future = resp.data();
250            let actual_response = data_future.await.unwrap();
251            assert_eq!(actual_response, expected_response);
252        });
253    }
254
255    #[test]
256    fn get_c2_c_trade_history_response_error() {
257        TOKIO_SHARED_RT.block_on(async {
258            let client = MockC2CApiClient { force_error: true };
259
260            let params = GetC2CTradeHistoryParams::builder().build().unwrap();
261
262            match client.get_c2_c_trade_history(params).await {
263                Ok(_) => panic!("Expected an error"),
264                Err(err) => {
265                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
266                }
267            }
268        });
269    }
270}