Skip to main content

binance_sdk/margin_trading/rest_api/apis/
risk_data_stream_api.rs

1/*
2 * Binance Margin Trading REST API
3 *
4 * OpenAPI Specification for the Binance Margin Trading 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::common::{
24    config::ConfigurationRestApi,
25    models::{ParamBuildError, RestApiResponse},
26    utils::send_request,
27};
28use crate::margin_trading::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait RiskDataStreamApi: Send + Sync {
34    async fn close_user_data_stream(&self) -> anyhow::Result<RestApiResponse<Value>>;
35    async fn keepalive_user_data_stream(
36        &self,
37        params: KeepaliveUserDataStreamParams,
38    ) -> anyhow::Result<RestApiResponse<Value>>;
39    async fn start_user_data_stream(
40        &self,
41    ) -> anyhow::Result<RestApiResponse<models::StartUserDataStreamResponse>>;
42}
43
44#[derive(Debug, Clone)]
45pub struct RiskDataStreamApiClient {
46    configuration: ConfigurationRestApi,
47}
48
49impl RiskDataStreamApiClient {
50    pub fn new(configuration: ConfigurationRestApi) -> Self {
51        Self { configuration }
52    }
53}
54
55/// Request parameters for the [`keepalive_user_data_stream`] operation.
56///
57/// This struct holds all of the inputs you can pass when calling
58/// [`keepalive_user_data_stream`](#method.keepalive_user_data_stream).
59#[derive(Clone, Debug, Builder)]
60#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
61pub struct KeepaliveUserDataStreamParams {
62    ///
63    /// The `listen_key` parameter.
64    ///
65    /// This field is **required.
66    #[builder(setter(into))]
67    pub listen_key: String,
68}
69
70impl KeepaliveUserDataStreamParams {
71    /// Create a builder for [`keepalive_user_data_stream`].
72    ///
73    /// Required parameters:
74    ///
75    /// * `listen_key` — String
76    ///
77    #[must_use]
78    pub fn builder(listen_key: String) -> KeepaliveUserDataStreamParamsBuilder {
79        KeepaliveUserDataStreamParamsBuilder::default().listen_key(listen_key)
80    }
81}
82
83#[async_trait]
84impl RiskDataStreamApi for RiskDataStreamApiClient {
85    async fn close_user_data_stream(&self) -> anyhow::Result<RestApiResponse<Value>> {
86        let query_params = BTreeMap::new();
87        let body_params = BTreeMap::new();
88
89        send_request::<Value>(
90            &self.configuration,
91            "/sapi/v1/margin/listen-key",
92            reqwest::Method::DELETE,
93            query_params,
94            body_params,
95            if HAS_TIME_UNIT {
96                self.configuration.time_unit
97            } else {
98                None
99            },
100            false,
101        )
102        .await
103    }
104
105    async fn keepalive_user_data_stream(
106        &self,
107        params: KeepaliveUserDataStreamParams,
108    ) -> anyhow::Result<RestApiResponse<Value>> {
109        let KeepaliveUserDataStreamParams { listen_key } = params;
110
111        let mut query_params = BTreeMap::new();
112        let body_params = BTreeMap::new();
113
114        query_params.insert("listenKey".to_string(), json!(listen_key));
115
116        send_request::<Value>(
117            &self.configuration,
118            "/sapi/v1/margin/listen-key",
119            reqwest::Method::PUT,
120            query_params,
121            body_params,
122            if HAS_TIME_UNIT {
123                self.configuration.time_unit
124            } else {
125                None
126            },
127            false,
128        )
129        .await
130    }
131
132    async fn start_user_data_stream(
133        &self,
134    ) -> anyhow::Result<RestApiResponse<models::StartUserDataStreamResponse>> {
135        let query_params = BTreeMap::new();
136        let body_params = BTreeMap::new();
137
138        send_request::<models::StartUserDataStreamResponse>(
139            &self.configuration,
140            "/sapi/v1/margin/listen-key",
141            reqwest::Method::POST,
142            query_params,
143            body_params,
144            if HAS_TIME_UNIT {
145                self.configuration.time_unit
146            } else {
147                None
148            },
149            false,
150        )
151        .await
152    }
153}
154
155#[cfg(all(test, feature = "margin_trading"))]
156mod tests {
157    use super::*;
158    use crate::TOKIO_SHARED_RT;
159    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
160    use async_trait::async_trait;
161    use std::collections::HashMap;
162
163    struct DummyRestApiResponse<T> {
164        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
165        status: u16,
166        headers: HashMap<String, String>,
167        rate_limits: Option<Vec<RestApiRateLimit>>,
168    }
169
170    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
171        fn from(dummy: DummyRestApiResponse<T>) -> Self {
172            Self {
173                data_fn: dummy.inner,
174                status: dummy.status,
175                headers: dummy.headers,
176                rate_limits: dummy.rate_limits,
177            }
178        }
179    }
180
181    struct MockRiskDataStreamApiClient {
182        force_error: bool,
183    }
184
185    #[async_trait]
186    impl RiskDataStreamApi for MockRiskDataStreamApiClient {
187        async fn close_user_data_stream(&self) -> anyhow::Result<RestApiResponse<Value>> {
188            if self.force_error {
189                return Err(ConnectorError::ConnectorClientError {
190                    msg: "ResponseError".to_string(),
191                    code: None,
192                }
193                .into());
194            }
195
196            let dummy_response = Value::Null;
197
198            let dummy = DummyRestApiResponse {
199                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
200                status: 200,
201                headers: HashMap::new(),
202                rate_limits: None,
203            };
204
205            Ok(dummy.into())
206        }
207
208        async fn keepalive_user_data_stream(
209            &self,
210            _params: KeepaliveUserDataStreamParams,
211        ) -> anyhow::Result<RestApiResponse<Value>> {
212            if self.force_error {
213                return Err(ConnectorError::ConnectorClientError {
214                    msg: "ResponseError".to_string(),
215                    code: None,
216                }
217                .into());
218            }
219
220            let dummy_response = Value::Null;
221
222            let dummy = DummyRestApiResponse {
223                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
224                status: 200,
225                headers: HashMap::new(),
226                rate_limits: None,
227            };
228
229            Ok(dummy.into())
230        }
231
232        async fn start_user_data_stream(
233            &self,
234        ) -> anyhow::Result<RestApiResponse<models::StartUserDataStreamResponse>> {
235            if self.force_error {
236                return Err(ConnectorError::ConnectorClientError {
237                    msg: "ResponseError".to_string(),
238                    code: None,
239                }
240                .into());
241            }
242
243            let resp_json: Value = serde_json::from_str(
244                r#"{"listenKey":"T3ee22BIYuWqmvne0HNq2A2WsFlEtLhvWCtItw6ffhhd"}"#,
245            )
246            .unwrap();
247            let dummy_response: models::StartUserDataStreamResponse =
248                serde_json::from_value(resp_json.clone())
249                    .expect("should parse into models::StartUserDataStreamResponse");
250
251            let dummy = DummyRestApiResponse {
252                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
253                status: 200,
254                headers: HashMap::new(),
255                rate_limits: None,
256            };
257
258            Ok(dummy.into())
259        }
260    }
261
262    #[test]
263    fn close_user_data_stream_required_params_success() {
264        TOKIO_SHARED_RT.block_on(async {
265            let client = MockRiskDataStreamApiClient { force_error: false };
266
267            let expected_response = Value::Null;
268
269            let resp = client
270                .close_user_data_stream()
271                .await
272                .expect("Expected a response");
273            let data_future = resp.data();
274            let actual_response = data_future.await.unwrap();
275            assert_eq!(actual_response, expected_response);
276        });
277    }
278
279    #[test]
280    fn close_user_data_stream_optional_params_success() {
281        TOKIO_SHARED_RT.block_on(async {
282            let client = MockRiskDataStreamApiClient { force_error: false };
283
284            let expected_response = Value::Null;
285
286            let resp = client
287                .close_user_data_stream()
288                .await
289                .expect("Expected a response");
290            let data_future = resp.data();
291            let actual_response = data_future.await.unwrap();
292            assert_eq!(actual_response, expected_response);
293        });
294    }
295
296    #[test]
297    fn close_user_data_stream_response_error() {
298        TOKIO_SHARED_RT.block_on(async {
299            let client = MockRiskDataStreamApiClient { force_error: true };
300
301            match client.close_user_data_stream().await {
302                Ok(_) => panic!("Expected an error"),
303                Err(err) => {
304                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
305                }
306            }
307        });
308    }
309
310    #[test]
311    fn keepalive_user_data_stream_required_params_success() {
312        TOKIO_SHARED_RT.block_on(async {
313            let client = MockRiskDataStreamApiClient { force_error: false };
314
315            let params = KeepaliveUserDataStreamParams::builder("listen_key_example".to_string())
316                .build()
317                .unwrap();
318
319            let expected_response = Value::Null;
320
321            let resp = client
322                .keepalive_user_data_stream(params)
323                .await
324                .expect("Expected a response");
325            let data_future = resp.data();
326            let actual_response = data_future.await.unwrap();
327            assert_eq!(actual_response, expected_response);
328        });
329    }
330
331    #[test]
332    fn keepalive_user_data_stream_optional_params_success() {
333        TOKIO_SHARED_RT.block_on(async {
334            let client = MockRiskDataStreamApiClient { force_error: false };
335
336            let params = KeepaliveUserDataStreamParams::builder("listen_key_example".to_string())
337                .build()
338                .unwrap();
339
340            let expected_response = Value::Null;
341
342            let resp = client
343                .keepalive_user_data_stream(params)
344                .await
345                .expect("Expected a response");
346            let data_future = resp.data();
347            let actual_response = data_future.await.unwrap();
348            assert_eq!(actual_response, expected_response);
349        });
350    }
351
352    #[test]
353    fn keepalive_user_data_stream_response_error() {
354        TOKIO_SHARED_RT.block_on(async {
355            let client = MockRiskDataStreamApiClient { force_error: true };
356
357            let params = KeepaliveUserDataStreamParams::builder("listen_key_example".to_string())
358                .build()
359                .unwrap();
360
361            match client.keepalive_user_data_stream(params).await {
362                Ok(_) => panic!("Expected an error"),
363                Err(err) => {
364                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
365                }
366            }
367        });
368    }
369
370    #[test]
371    fn start_user_data_stream_required_params_success() {
372        TOKIO_SHARED_RT.block_on(async {
373            let client = MockRiskDataStreamApiClient { force_error: false };
374
375            let resp_json: Value = serde_json::from_str(
376                r#"{"listenKey":"T3ee22BIYuWqmvne0HNq2A2WsFlEtLhvWCtItw6ffhhd"}"#,
377            )
378            .unwrap();
379            let expected_response: models::StartUserDataStreamResponse =
380                serde_json::from_value(resp_json.clone())
381                    .expect("should parse into models::StartUserDataStreamResponse");
382
383            let resp = client
384                .start_user_data_stream()
385                .await
386                .expect("Expected a response");
387            let data_future = resp.data();
388            let actual_response = data_future.await.unwrap();
389            assert_eq!(actual_response, expected_response);
390        });
391    }
392
393    #[test]
394    fn start_user_data_stream_optional_params_success() {
395        TOKIO_SHARED_RT.block_on(async {
396            let client = MockRiskDataStreamApiClient { force_error: false };
397
398            let resp_json: Value = serde_json::from_str(
399                r#"{"listenKey":"T3ee22BIYuWqmvne0HNq2A2WsFlEtLhvWCtItw6ffhhd"}"#,
400            )
401            .unwrap();
402            let expected_response: models::StartUserDataStreamResponse =
403                serde_json::from_value(resp_json.clone())
404                    .expect("should parse into models::StartUserDataStreamResponse");
405
406            let resp = client
407                .start_user_data_stream()
408                .await
409                .expect("Expected a response");
410            let data_future = resp.data();
411            let actual_response = data_future.await.unwrap();
412            assert_eq!(actual_response, expected_response);
413        });
414    }
415
416    #[test]
417    fn start_user_data_stream_response_error() {
418        TOKIO_SHARED_RT.block_on(async {
419            let client = MockRiskDataStreamApiClient { force_error: true };
420
421            match client.start_user_data_stream().await {
422                Ok(_) => panic!("Expected an error"),
423                Err(err) => {
424                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
425                }
426            }
427        });
428    }
429}