Skip to main content

binance_sdk/wallet/rest_api/apis/
account_api.rs

1/*
2 * Binance Wallet REST API
3 *
4 * OpenAPI Specification for the Binance Wallet 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::wallet::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait AccountApi: Send + Sync {
34    async fn account_api_trading_status(
35        &self,
36        params: AccountApiTradingStatusParams,
37    ) -> anyhow::Result<RestApiResponse<models::AccountApiTradingStatusResponse>>;
38    async fn account_info(
39        &self,
40        params: AccountInfoParams,
41    ) -> anyhow::Result<RestApiResponse<models::AccountInfoResponse>>;
42    async fn account_status(
43        &self,
44        params: AccountStatusParams,
45    ) -> anyhow::Result<RestApiResponse<models::AccountStatusResponse>>;
46    async fn daily_account_snapshot(
47        &self,
48        params: DailyAccountSnapshotParams,
49    ) -> anyhow::Result<RestApiResponse<models::DailyAccountSnapshotResponse>>;
50    async fn disable_fast_withdraw_switch(
51        &self,
52        params: DisableFastWithdrawSwitchParams,
53    ) -> anyhow::Result<RestApiResponse<Value>>;
54    async fn enable_fast_withdraw_switch(
55        &self,
56        params: EnableFastWithdrawSwitchParams,
57    ) -> anyhow::Result<RestApiResponse<Value>>;
58    async fn get_api_key_permission(
59        &self,
60        params: GetApiKeyPermissionParams,
61    ) -> anyhow::Result<RestApiResponse<models::GetApiKeyPermissionResponse>>;
62}
63
64#[derive(Debug, Clone)]
65pub struct AccountApiClient {
66    configuration: ConfigurationRestApi,
67}
68
69impl AccountApiClient {
70    pub fn new(configuration: ConfigurationRestApi) -> Self {
71        Self { configuration }
72    }
73}
74
75/// Request parameters for the [`account_api_trading_status`] operation.
76///
77/// This struct holds all of the inputs you can pass when calling
78/// [`account_api_trading_status`](#method.account_api_trading_status).
79#[derive(Clone, Debug, Builder, Default)]
80#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
81pub struct AccountApiTradingStatusParams {
82    ///
83    /// The `recv_window` parameter.
84    ///
85    /// This field is **optional.
86    #[builder(setter(into), default)]
87    pub recv_window: Option<i64>,
88}
89
90impl AccountApiTradingStatusParams {
91    /// Create a builder for [`account_api_trading_status`].
92    ///
93    #[must_use]
94    pub fn builder() -> AccountApiTradingStatusParamsBuilder {
95        AccountApiTradingStatusParamsBuilder::default()
96    }
97}
98/// Request parameters for the [`account_info`] operation.
99///
100/// This struct holds all of the inputs you can pass when calling
101/// [`account_info`](#method.account_info).
102#[derive(Clone, Debug, Builder, Default)]
103#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
104pub struct AccountInfoParams {
105    ///
106    /// The `recv_window` parameter.
107    ///
108    /// This field is **optional.
109    #[builder(setter(into), default)]
110    pub recv_window: Option<i64>,
111}
112
113impl AccountInfoParams {
114    /// Create a builder for [`account_info`].
115    ///
116    #[must_use]
117    pub fn builder() -> AccountInfoParamsBuilder {
118        AccountInfoParamsBuilder::default()
119    }
120}
121/// Request parameters for the [`account_status`] operation.
122///
123/// This struct holds all of the inputs you can pass when calling
124/// [`account_status`](#method.account_status).
125#[derive(Clone, Debug, Builder, Default)]
126#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
127pub struct AccountStatusParams {
128    ///
129    /// The `recv_window` parameter.
130    ///
131    /// This field is **optional.
132    #[builder(setter(into), default)]
133    pub recv_window: Option<i64>,
134}
135
136impl AccountStatusParams {
137    /// Create a builder for [`account_status`].
138    ///
139    #[must_use]
140    pub fn builder() -> AccountStatusParamsBuilder {
141        AccountStatusParamsBuilder::default()
142    }
143}
144/// Request parameters for the [`daily_account_snapshot`] operation.
145///
146/// This struct holds all of the inputs you can pass when calling
147/// [`daily_account_snapshot`](#method.daily_account_snapshot).
148#[derive(Clone, Debug, Builder)]
149#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
150pub struct DailyAccountSnapshotParams {
151    ///
152    /// The `r#type` parameter.
153    ///
154    /// This field is **required.
155    #[builder(setter(into))]
156    pub r#type: String,
157    ///
158    /// The `start_time` parameter.
159    ///
160    /// This field is **optional.
161    #[builder(setter(into), default)]
162    pub start_time: Option<i64>,
163    ///
164    /// The `end_time` parameter.
165    ///
166    /// This field is **optional.
167    #[builder(setter(into), default)]
168    pub end_time: Option<i64>,
169    /// min 7, max 30, default 7
170    ///
171    /// This field is **optional.
172    #[builder(setter(into), default)]
173    pub limit: Option<i64>,
174    ///
175    /// The `recv_window` parameter.
176    ///
177    /// This field is **optional.
178    #[builder(setter(into), default)]
179    pub recv_window: Option<i64>,
180}
181
182impl DailyAccountSnapshotParams {
183    /// Create a builder for [`daily_account_snapshot`].
184    ///
185    /// Required parameters:
186    ///
187    /// * `r#type` — String
188    ///
189    #[must_use]
190    pub fn builder(r#type: String) -> DailyAccountSnapshotParamsBuilder {
191        DailyAccountSnapshotParamsBuilder::default().r#type(r#type)
192    }
193}
194/// Request parameters for the [`disable_fast_withdraw_switch`] operation.
195///
196/// This struct holds all of the inputs you can pass when calling
197/// [`disable_fast_withdraw_switch`](#method.disable_fast_withdraw_switch).
198#[derive(Clone, Debug, Builder, Default)]
199#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
200pub struct DisableFastWithdrawSwitchParams {
201    ///
202    /// The `recv_window` parameter.
203    ///
204    /// This field is **optional.
205    #[builder(setter(into), default)]
206    pub recv_window: Option<i64>,
207}
208
209impl DisableFastWithdrawSwitchParams {
210    /// Create a builder for [`disable_fast_withdraw_switch`].
211    ///
212    #[must_use]
213    pub fn builder() -> DisableFastWithdrawSwitchParamsBuilder {
214        DisableFastWithdrawSwitchParamsBuilder::default()
215    }
216}
217/// Request parameters for the [`enable_fast_withdraw_switch`] operation.
218///
219/// This struct holds all of the inputs you can pass when calling
220/// [`enable_fast_withdraw_switch`](#method.enable_fast_withdraw_switch).
221#[derive(Clone, Debug, Builder, Default)]
222#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
223pub struct EnableFastWithdrawSwitchParams {
224    ///
225    /// The `recv_window` parameter.
226    ///
227    /// This field is **optional.
228    #[builder(setter(into), default)]
229    pub recv_window: Option<i64>,
230}
231
232impl EnableFastWithdrawSwitchParams {
233    /// Create a builder for [`enable_fast_withdraw_switch`].
234    ///
235    #[must_use]
236    pub fn builder() -> EnableFastWithdrawSwitchParamsBuilder {
237        EnableFastWithdrawSwitchParamsBuilder::default()
238    }
239}
240/// Request parameters for the [`get_api_key_permission`] operation.
241///
242/// This struct holds all of the inputs you can pass when calling
243/// [`get_api_key_permission`](#method.get_api_key_permission).
244#[derive(Clone, Debug, Builder, Default)]
245#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
246pub struct GetApiKeyPermissionParams {
247    ///
248    /// The `recv_window` parameter.
249    ///
250    /// This field is **optional.
251    #[builder(setter(into), default)]
252    pub recv_window: Option<i64>,
253}
254
255impl GetApiKeyPermissionParams {
256    /// Create a builder for [`get_api_key_permission`].
257    ///
258    #[must_use]
259    pub fn builder() -> GetApiKeyPermissionParamsBuilder {
260        GetApiKeyPermissionParamsBuilder::default()
261    }
262}
263
264#[async_trait]
265impl AccountApi for AccountApiClient {
266    async fn account_api_trading_status(
267        &self,
268        params: AccountApiTradingStatusParams,
269    ) -> anyhow::Result<RestApiResponse<models::AccountApiTradingStatusResponse>> {
270        let AccountApiTradingStatusParams { recv_window } = params;
271
272        let mut query_params = BTreeMap::new();
273        let body_params = BTreeMap::new();
274
275        if let Some(rw) = recv_window {
276            query_params.insert("recvWindow".to_string(), json!(rw));
277        }
278
279        send_request::<models::AccountApiTradingStatusResponse>(
280            &self.configuration,
281            "/sapi/v1/account/apiTradingStatus",
282            reqwest::Method::GET,
283            query_params,
284            body_params,
285            if HAS_TIME_UNIT {
286                self.configuration.time_unit
287            } else {
288                None
289            },
290            true,
291        )
292        .await
293    }
294
295    async fn account_info(
296        &self,
297        params: AccountInfoParams,
298    ) -> anyhow::Result<RestApiResponse<models::AccountInfoResponse>> {
299        let AccountInfoParams { recv_window } = params;
300
301        let mut query_params = BTreeMap::new();
302        let body_params = BTreeMap::new();
303
304        if let Some(rw) = recv_window {
305            query_params.insert("recvWindow".to_string(), json!(rw));
306        }
307
308        send_request::<models::AccountInfoResponse>(
309            &self.configuration,
310            "/sapi/v1/account/info",
311            reqwest::Method::GET,
312            query_params,
313            body_params,
314            if HAS_TIME_UNIT {
315                self.configuration.time_unit
316            } else {
317                None
318            },
319            true,
320        )
321        .await
322    }
323
324    async fn account_status(
325        &self,
326        params: AccountStatusParams,
327    ) -> anyhow::Result<RestApiResponse<models::AccountStatusResponse>> {
328        let AccountStatusParams { recv_window } = params;
329
330        let mut query_params = BTreeMap::new();
331        let body_params = BTreeMap::new();
332
333        if let Some(rw) = recv_window {
334            query_params.insert("recvWindow".to_string(), json!(rw));
335        }
336
337        send_request::<models::AccountStatusResponse>(
338            &self.configuration,
339            "/sapi/v1/account/status",
340            reqwest::Method::GET,
341            query_params,
342            body_params,
343            if HAS_TIME_UNIT {
344                self.configuration.time_unit
345            } else {
346                None
347            },
348            true,
349        )
350        .await
351    }
352
353    async fn daily_account_snapshot(
354        &self,
355        params: DailyAccountSnapshotParams,
356    ) -> anyhow::Result<RestApiResponse<models::DailyAccountSnapshotResponse>> {
357        let DailyAccountSnapshotParams {
358            r#type,
359            start_time,
360            end_time,
361            limit,
362            recv_window,
363        } = params;
364
365        let mut query_params = BTreeMap::new();
366        let body_params = BTreeMap::new();
367
368        query_params.insert("type".to_string(), json!(r#type));
369
370        if let Some(rw) = start_time {
371            query_params.insert("startTime".to_string(), json!(rw));
372        }
373
374        if let Some(rw) = end_time {
375            query_params.insert("endTime".to_string(), json!(rw));
376        }
377
378        if let Some(rw) = limit {
379            query_params.insert("limit".to_string(), json!(rw));
380        }
381
382        if let Some(rw) = recv_window {
383            query_params.insert("recvWindow".to_string(), json!(rw));
384        }
385
386        send_request::<models::DailyAccountSnapshotResponse>(
387            &self.configuration,
388            "/sapi/v1/accountSnapshot",
389            reqwest::Method::GET,
390            query_params,
391            body_params,
392            if HAS_TIME_UNIT {
393                self.configuration.time_unit
394            } else {
395                None
396            },
397            true,
398        )
399        .await
400    }
401
402    async fn disable_fast_withdraw_switch(
403        &self,
404        params: DisableFastWithdrawSwitchParams,
405    ) -> anyhow::Result<RestApiResponse<Value>> {
406        let DisableFastWithdrawSwitchParams { recv_window } = params;
407
408        let mut query_params = BTreeMap::new();
409        let body_params = BTreeMap::new();
410
411        if let Some(rw) = recv_window {
412            query_params.insert("recvWindow".to_string(), json!(rw));
413        }
414
415        send_request::<Value>(
416            &self.configuration,
417            "/sapi/v1/account/disableFastWithdrawSwitch",
418            reqwest::Method::POST,
419            query_params,
420            body_params,
421            if HAS_TIME_UNIT {
422                self.configuration.time_unit
423            } else {
424                None
425            },
426            true,
427        )
428        .await
429    }
430
431    async fn enable_fast_withdraw_switch(
432        &self,
433        params: EnableFastWithdrawSwitchParams,
434    ) -> anyhow::Result<RestApiResponse<Value>> {
435        let EnableFastWithdrawSwitchParams { recv_window } = params;
436
437        let mut query_params = BTreeMap::new();
438        let body_params = BTreeMap::new();
439
440        if let Some(rw) = recv_window {
441            query_params.insert("recvWindow".to_string(), json!(rw));
442        }
443
444        send_request::<Value>(
445            &self.configuration,
446            "/sapi/v1/account/enableFastWithdrawSwitch",
447            reqwest::Method::POST,
448            query_params,
449            body_params,
450            if HAS_TIME_UNIT {
451                self.configuration.time_unit
452            } else {
453                None
454            },
455            true,
456        )
457        .await
458    }
459
460    async fn get_api_key_permission(
461        &self,
462        params: GetApiKeyPermissionParams,
463    ) -> anyhow::Result<RestApiResponse<models::GetApiKeyPermissionResponse>> {
464        let GetApiKeyPermissionParams { recv_window } = params;
465
466        let mut query_params = BTreeMap::new();
467        let body_params = BTreeMap::new();
468
469        if let Some(rw) = recv_window {
470            query_params.insert("recvWindow".to_string(), json!(rw));
471        }
472
473        send_request::<models::GetApiKeyPermissionResponse>(
474            &self.configuration,
475            "/sapi/v1/account/apiRestrictions",
476            reqwest::Method::GET,
477            query_params,
478            body_params,
479            if HAS_TIME_UNIT {
480                self.configuration.time_unit
481            } else {
482                None
483            },
484            true,
485        )
486        .await
487    }
488}
489
490#[cfg(all(test, feature = "wallet"))]
491mod tests {
492    use super::*;
493    use crate::TOKIO_SHARED_RT;
494    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
495    use async_trait::async_trait;
496    use std::collections::HashMap;
497
498    struct DummyRestApiResponse<T> {
499        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
500        status: u16,
501        headers: HashMap<String, String>,
502        rate_limits: Option<Vec<RestApiRateLimit>>,
503    }
504
505    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
506        fn from(dummy: DummyRestApiResponse<T>) -> Self {
507            Self {
508                data_fn: dummy.inner,
509                status: dummy.status,
510                headers: dummy.headers,
511                rate_limits: dummy.rate_limits,
512            }
513        }
514    }
515
516    struct MockAccountApiClient {
517        force_error: bool,
518    }
519
520    #[async_trait]
521    impl AccountApi for MockAccountApiClient {
522        async fn account_api_trading_status(
523            &self,
524            _params: AccountApiTradingStatusParams,
525        ) -> anyhow::Result<RestApiResponse<models::AccountApiTradingStatusResponse>> {
526            if self.force_error {
527                return Err(ConnectorError::ConnectorClientError {
528                    msg: "ResponseError".to_string(),
529                    code: None,
530                }
531                .into());
532            }
533
534            let resp_json: Value = serde_json::from_str(r#"{"data":{"isLocked":false,"plannedRecoverTime":0,"triggerCondition":{"GCR":150,"IFER":150,"UFR":300},"updateTime":1547630471725}}"#).unwrap();
535            let dummy_response: models::AccountApiTradingStatusResponse =
536                serde_json::from_value(resp_json.clone())
537                    .expect("should parse into models::AccountApiTradingStatusResponse");
538
539            let dummy = DummyRestApiResponse {
540                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
541                status: 200,
542                headers: HashMap::new(),
543                rate_limits: None,
544            };
545
546            Ok(dummy.into())
547        }
548
549        async fn account_info(
550            &self,
551            _params: AccountInfoParams,
552        ) -> anyhow::Result<RestApiResponse<models::AccountInfoResponse>> {
553            if self.force_error {
554                return Err(ConnectorError::ConnectorClientError {
555                    msg: "ResponseError".to_string(),
556                    code: None,
557                }
558                .into());
559            }
560
561            let resp_json: Value = serde_json::from_str(r#"{"vipLevel":0,"isMarginEnabled":true,"isFutureEnabled":true,"isOptionsEnabled":true,"isPortfolioMarginRetailEnabled":true}"#).unwrap();
562            let dummy_response: models::AccountInfoResponse =
563                serde_json::from_value(resp_json.clone())
564                    .expect("should parse into models::AccountInfoResponse");
565
566            let dummy = DummyRestApiResponse {
567                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
568                status: 200,
569                headers: HashMap::new(),
570                rate_limits: None,
571            };
572
573            Ok(dummy.into())
574        }
575
576        async fn account_status(
577            &self,
578            _params: AccountStatusParams,
579        ) -> anyhow::Result<RestApiResponse<models::AccountStatusResponse>> {
580            if self.force_error {
581                return Err(ConnectorError::ConnectorClientError {
582                    msg: "ResponseError".to_string(),
583                    code: None,
584                }
585                .into());
586            }
587
588            let resp_json: Value = serde_json::from_str(r#"{"data":"Normal"}"#).unwrap();
589            let dummy_response: models::AccountStatusResponse =
590                serde_json::from_value(resp_json.clone())
591                    .expect("should parse into models::AccountStatusResponse");
592
593            let dummy = DummyRestApiResponse {
594                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
595                status: 200,
596                headers: HashMap::new(),
597                rate_limits: None,
598            };
599
600            Ok(dummy.into())
601        }
602
603        async fn daily_account_snapshot(
604            &self,
605            _params: DailyAccountSnapshotParams,
606        ) -> anyhow::Result<RestApiResponse<models::DailyAccountSnapshotResponse>> {
607            if self.force_error {
608                return Err(ConnectorError::ConnectorClientError {
609                    msg: "ResponseError".to_string(),
610                    code: None,
611                }
612                .into());
613            }
614
615            let resp_json: Value = serde_json::from_str(r#"{"code":200,"msg":"","snapshotVos":[{"data":{"balances":[{"asset":"BTC","free":"0.09905021","locked":"0.00000000"},{"asset":"USDT","free":"1.89109409","locked":"0.00000000"}],"totalAssetOfBtc":"0.09942700"},"type":"spot","updateTime":1576281599000},{"data":{"marginLevel":"2748.02909813","totalAssetOfBtc":"0.00274803","totalLiabilityOfBtc":"0.00000100","totalNetAssetOfBtc":"0.00274750","userAssets":[{"asset":"XRP","borrowed":"0.00000000","free":"1.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"1.00000000"}]},"type":"margin","updateTime":1576281599000},{"data":{"assets":[{"asset":"USDT","marginBalance":"118.99782335","walletBalance":"120.23811389"}],"position":[{"entryPrice":"7130.41000000","markPrice":"7257.66239673","positionAmt":"0.01000000","symbol":"BTCUSDT","unRealizedProfit":"1.24029054"}]},"type":"futures","updateTime":1576281599000}]}"#).unwrap();
616            let dummy_response: models::DailyAccountSnapshotResponse =
617                serde_json::from_value(resp_json.clone())
618                    .expect("should parse into models::DailyAccountSnapshotResponse");
619
620            let dummy = DummyRestApiResponse {
621                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
622                status: 200,
623                headers: HashMap::new(),
624                rate_limits: None,
625            };
626
627            Ok(dummy.into())
628        }
629
630        async fn disable_fast_withdraw_switch(
631            &self,
632            _params: DisableFastWithdrawSwitchParams,
633        ) -> anyhow::Result<RestApiResponse<Value>> {
634            if self.force_error {
635                return Err(ConnectorError::ConnectorClientError {
636                    msg: "ResponseError".to_string(),
637                    code: None,
638                }
639                .into());
640            }
641
642            let dummy_response = Value::Null;
643
644            let dummy = DummyRestApiResponse {
645                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
646                status: 200,
647                headers: HashMap::new(),
648                rate_limits: None,
649            };
650
651            Ok(dummy.into())
652        }
653
654        async fn enable_fast_withdraw_switch(
655            &self,
656            _params: EnableFastWithdrawSwitchParams,
657        ) -> anyhow::Result<RestApiResponse<Value>> {
658            if self.force_error {
659                return Err(ConnectorError::ConnectorClientError {
660                    msg: "ResponseError".to_string(),
661                    code: None,
662                }
663                .into());
664            }
665
666            let dummy_response = Value::Null;
667
668            let dummy = DummyRestApiResponse {
669                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
670                status: 200,
671                headers: HashMap::new(),
672                rate_limits: None,
673            };
674
675            Ok(dummy.into())
676        }
677
678        async fn get_api_key_permission(
679            &self,
680            _params: GetApiKeyPermissionParams,
681        ) -> anyhow::Result<RestApiResponse<models::GetApiKeyPermissionResponse>> {
682            if self.force_error {
683                return Err(ConnectorError::ConnectorClientError {
684                    msg: "ResponseError".to_string(),
685                    code: None,
686                }
687                .into());
688            }
689
690            let resp_json: Value = serde_json::from_str(r#"{"ipRestrict":false,"createTime":1698645219000,"enableReading":true,"enableWithdrawals":false,"enableInternalTransfer":false,"enableMargin":false,"enableFutures":false,"permitsUniversalTransfer":false,"enableVanillaOptions":false,"enableFixApiTrade":false,"enableFixReadOnly":true,"enableSpotAndMarginTrading":false,"enablePortfolioMarginTrading":true}"#).unwrap();
691            let dummy_response: models::GetApiKeyPermissionResponse =
692                serde_json::from_value(resp_json.clone())
693                    .expect("should parse into models::GetApiKeyPermissionResponse");
694
695            let dummy = DummyRestApiResponse {
696                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
697                status: 200,
698                headers: HashMap::new(),
699                rate_limits: None,
700            };
701
702            Ok(dummy.into())
703        }
704    }
705
706    #[test]
707    fn account_api_trading_status_required_params_success() {
708        TOKIO_SHARED_RT.block_on(async {
709            let client = MockAccountApiClient { force_error: false };
710
711            let params = AccountApiTradingStatusParams::builder().build().unwrap();
712
713            let resp_json: Value = serde_json::from_str(r#"{"data":{"isLocked":false,"plannedRecoverTime":0,"triggerCondition":{"GCR":150,"IFER":150,"UFR":300},"updateTime":1547630471725}}"#).unwrap();
714            let expected_response : models::AccountApiTradingStatusResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountApiTradingStatusResponse");
715
716            let resp = client.account_api_trading_status(params).await.expect("Expected a response");
717            let data_future = resp.data();
718            let actual_response = data_future.await.unwrap();
719            assert_eq!(actual_response, expected_response);
720        });
721    }
722
723    #[test]
724    fn account_api_trading_status_optional_params_success() {
725        TOKIO_SHARED_RT.block_on(async {
726            let client = MockAccountApiClient { force_error: false };
727
728            let params = AccountApiTradingStatusParams::builder().recv_window(5000).build().unwrap();
729
730            let resp_json: Value = serde_json::from_str(r#"{"data":{"isLocked":false,"plannedRecoverTime":0,"triggerCondition":{"GCR":150,"IFER":150,"UFR":300},"updateTime":1547630471725}}"#).unwrap();
731            let expected_response : models::AccountApiTradingStatusResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountApiTradingStatusResponse");
732
733            let resp = client.account_api_trading_status(params).await.expect("Expected a response");
734            let data_future = resp.data();
735            let actual_response = data_future.await.unwrap();
736            assert_eq!(actual_response, expected_response);
737        });
738    }
739
740    #[test]
741    fn account_api_trading_status_response_error() {
742        TOKIO_SHARED_RT.block_on(async {
743            let client = MockAccountApiClient { force_error: true };
744
745            let params = AccountApiTradingStatusParams::builder().build().unwrap();
746
747            match client.account_api_trading_status(params).await {
748                Ok(_) => panic!("Expected an error"),
749                Err(err) => {
750                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
751                }
752            }
753        });
754    }
755
756    #[test]
757    fn account_info_required_params_success() {
758        TOKIO_SHARED_RT.block_on(async {
759            let client = MockAccountApiClient { force_error: false };
760
761            let params = AccountInfoParams::builder().build().unwrap();
762
763            let resp_json: Value = serde_json::from_str(r#"{"vipLevel":0,"isMarginEnabled":true,"isFutureEnabled":true,"isOptionsEnabled":true,"isPortfolioMarginRetailEnabled":true}"#).unwrap();
764            let expected_response : models::AccountInfoResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountInfoResponse");
765
766            let resp = client.account_info(params).await.expect("Expected a response");
767            let data_future = resp.data();
768            let actual_response = data_future.await.unwrap();
769            assert_eq!(actual_response, expected_response);
770        });
771    }
772
773    #[test]
774    fn account_info_optional_params_success() {
775        TOKIO_SHARED_RT.block_on(async {
776            let client = MockAccountApiClient { force_error: false };
777
778            let params = AccountInfoParams::builder().recv_window(5000).build().unwrap();
779
780            let resp_json: Value = serde_json::from_str(r#"{"vipLevel":0,"isMarginEnabled":true,"isFutureEnabled":true,"isOptionsEnabled":true,"isPortfolioMarginRetailEnabled":true}"#).unwrap();
781            let expected_response : models::AccountInfoResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AccountInfoResponse");
782
783            let resp = client.account_info(params).await.expect("Expected a response");
784            let data_future = resp.data();
785            let actual_response = data_future.await.unwrap();
786            assert_eq!(actual_response, expected_response);
787        });
788    }
789
790    #[test]
791    fn account_info_response_error() {
792        TOKIO_SHARED_RT.block_on(async {
793            let client = MockAccountApiClient { force_error: true };
794
795            let params = AccountInfoParams::builder().build().unwrap();
796
797            match client.account_info(params).await {
798                Ok(_) => panic!("Expected an error"),
799                Err(err) => {
800                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
801                }
802            }
803        });
804    }
805
806    #[test]
807    fn account_status_required_params_success() {
808        TOKIO_SHARED_RT.block_on(async {
809            let client = MockAccountApiClient { force_error: false };
810
811            let params = AccountStatusParams::builder().build().unwrap();
812
813            let resp_json: Value = serde_json::from_str(r#"{"data":"Normal"}"#).unwrap();
814            let expected_response: models::AccountStatusResponse =
815                serde_json::from_value(resp_json.clone())
816                    .expect("should parse into models::AccountStatusResponse");
817
818            let resp = client
819                .account_status(params)
820                .await
821                .expect("Expected a response");
822            let data_future = resp.data();
823            let actual_response = data_future.await.unwrap();
824            assert_eq!(actual_response, expected_response);
825        });
826    }
827
828    #[test]
829    fn account_status_optional_params_success() {
830        TOKIO_SHARED_RT.block_on(async {
831            let client = MockAccountApiClient { force_error: false };
832
833            let params = AccountStatusParams::builder()
834                .recv_window(5000)
835                .build()
836                .unwrap();
837
838            let resp_json: Value = serde_json::from_str(r#"{"data":"Normal"}"#).unwrap();
839            let expected_response: models::AccountStatusResponse =
840                serde_json::from_value(resp_json.clone())
841                    .expect("should parse into models::AccountStatusResponse");
842
843            let resp = client
844                .account_status(params)
845                .await
846                .expect("Expected a response");
847            let data_future = resp.data();
848            let actual_response = data_future.await.unwrap();
849            assert_eq!(actual_response, expected_response);
850        });
851    }
852
853    #[test]
854    fn account_status_response_error() {
855        TOKIO_SHARED_RT.block_on(async {
856            let client = MockAccountApiClient { force_error: true };
857
858            let params = AccountStatusParams::builder().build().unwrap();
859
860            match client.account_status(params).await {
861                Ok(_) => panic!("Expected an error"),
862                Err(err) => {
863                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
864                }
865            }
866        });
867    }
868
869    #[test]
870    fn daily_account_snapshot_required_params_success() {
871        TOKIO_SHARED_RT.block_on(async {
872            let client = MockAccountApiClient { force_error: false };
873
874            let params = DailyAccountSnapshotParams::builder("r#type_example".to_string(),).build().unwrap();
875
876            let resp_json: Value = serde_json::from_str(r#"{"code":200,"msg":"","snapshotVos":[{"data":{"balances":[{"asset":"BTC","free":"0.09905021","locked":"0.00000000"},{"asset":"USDT","free":"1.89109409","locked":"0.00000000"}],"totalAssetOfBtc":"0.09942700"},"type":"spot","updateTime":1576281599000},{"data":{"marginLevel":"2748.02909813","totalAssetOfBtc":"0.00274803","totalLiabilityOfBtc":"0.00000100","totalNetAssetOfBtc":"0.00274750","userAssets":[{"asset":"XRP","borrowed":"0.00000000","free":"1.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"1.00000000"}]},"type":"margin","updateTime":1576281599000},{"data":{"assets":[{"asset":"USDT","marginBalance":"118.99782335","walletBalance":"120.23811389"}],"position":[{"entryPrice":"7130.41000000","markPrice":"7257.66239673","positionAmt":"0.01000000","symbol":"BTCUSDT","unRealizedProfit":"1.24029054"}]},"type":"futures","updateTime":1576281599000}]}"#).unwrap();
877            let expected_response : models::DailyAccountSnapshotResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DailyAccountSnapshotResponse");
878
879            let resp = client.daily_account_snapshot(params).await.expect("Expected a response");
880            let data_future = resp.data();
881            let actual_response = data_future.await.unwrap();
882            assert_eq!(actual_response, expected_response);
883        });
884    }
885
886    #[test]
887    fn daily_account_snapshot_optional_params_success() {
888        TOKIO_SHARED_RT.block_on(async {
889            let client = MockAccountApiClient { force_error: false };
890
891            let params = DailyAccountSnapshotParams::builder("r#type_example".to_string(),).start_time(1623319461670).end_time(1641782889000).limit(7).recv_window(5000).build().unwrap();
892
893            let resp_json: Value = serde_json::from_str(r#"{"code":200,"msg":"","snapshotVos":[{"data":{"balances":[{"asset":"BTC","free":"0.09905021","locked":"0.00000000"},{"asset":"USDT","free":"1.89109409","locked":"0.00000000"}],"totalAssetOfBtc":"0.09942700"},"type":"spot","updateTime":1576281599000},{"data":{"marginLevel":"2748.02909813","totalAssetOfBtc":"0.00274803","totalLiabilityOfBtc":"0.00000100","totalNetAssetOfBtc":"0.00274750","userAssets":[{"asset":"XRP","borrowed":"0.00000000","free":"1.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"1.00000000"}]},"type":"margin","updateTime":1576281599000},{"data":{"assets":[{"asset":"USDT","marginBalance":"118.99782335","walletBalance":"120.23811389"}],"position":[{"entryPrice":"7130.41000000","markPrice":"7257.66239673","positionAmt":"0.01000000","symbol":"BTCUSDT","unRealizedProfit":"1.24029054"}]},"type":"futures","updateTime":1576281599000}]}"#).unwrap();
894            let expected_response : models::DailyAccountSnapshotResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DailyAccountSnapshotResponse");
895
896            let resp = client.daily_account_snapshot(params).await.expect("Expected a response");
897            let data_future = resp.data();
898            let actual_response = data_future.await.unwrap();
899            assert_eq!(actual_response, expected_response);
900        });
901    }
902
903    #[test]
904    fn daily_account_snapshot_response_error() {
905        TOKIO_SHARED_RT.block_on(async {
906            let client = MockAccountApiClient { force_error: true };
907
908            let params = DailyAccountSnapshotParams::builder("r#type_example".to_string())
909                .build()
910                .unwrap();
911
912            match client.daily_account_snapshot(params).await {
913                Ok(_) => panic!("Expected an error"),
914                Err(err) => {
915                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
916                }
917            }
918        });
919    }
920
921    #[test]
922    fn disable_fast_withdraw_switch_required_params_success() {
923        TOKIO_SHARED_RT.block_on(async {
924            let client = MockAccountApiClient { force_error: false };
925
926            let params = DisableFastWithdrawSwitchParams::builder().build().unwrap();
927
928            let expected_response = Value::Null;
929
930            let resp = client
931                .disable_fast_withdraw_switch(params)
932                .await
933                .expect("Expected a response");
934            let data_future = resp.data();
935            let actual_response = data_future.await.unwrap();
936            assert_eq!(actual_response, expected_response);
937        });
938    }
939
940    #[test]
941    fn disable_fast_withdraw_switch_optional_params_success() {
942        TOKIO_SHARED_RT.block_on(async {
943            let client = MockAccountApiClient { force_error: false };
944
945            let params = DisableFastWithdrawSwitchParams::builder()
946                .recv_window(5000)
947                .build()
948                .unwrap();
949
950            let expected_response = Value::Null;
951
952            let resp = client
953                .disable_fast_withdraw_switch(params)
954                .await
955                .expect("Expected a response");
956            let data_future = resp.data();
957            let actual_response = data_future.await.unwrap();
958            assert_eq!(actual_response, expected_response);
959        });
960    }
961
962    #[test]
963    fn disable_fast_withdraw_switch_response_error() {
964        TOKIO_SHARED_RT.block_on(async {
965            let client = MockAccountApiClient { force_error: true };
966
967            let params = DisableFastWithdrawSwitchParams::builder().build().unwrap();
968
969            match client.disable_fast_withdraw_switch(params).await {
970                Ok(_) => panic!("Expected an error"),
971                Err(err) => {
972                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
973                }
974            }
975        });
976    }
977
978    #[test]
979    fn enable_fast_withdraw_switch_required_params_success() {
980        TOKIO_SHARED_RT.block_on(async {
981            let client = MockAccountApiClient { force_error: false };
982
983            let params = EnableFastWithdrawSwitchParams::builder().build().unwrap();
984
985            let expected_response = Value::Null;
986
987            let resp = client
988                .enable_fast_withdraw_switch(params)
989                .await
990                .expect("Expected a response");
991            let data_future = resp.data();
992            let actual_response = data_future.await.unwrap();
993            assert_eq!(actual_response, expected_response);
994        });
995    }
996
997    #[test]
998    fn enable_fast_withdraw_switch_optional_params_success() {
999        TOKIO_SHARED_RT.block_on(async {
1000            let client = MockAccountApiClient { force_error: false };
1001
1002            let params = EnableFastWithdrawSwitchParams::builder()
1003                .recv_window(5000)
1004                .build()
1005                .unwrap();
1006
1007            let expected_response = Value::Null;
1008
1009            let resp = client
1010                .enable_fast_withdraw_switch(params)
1011                .await
1012                .expect("Expected a response");
1013            let data_future = resp.data();
1014            let actual_response = data_future.await.unwrap();
1015            assert_eq!(actual_response, expected_response);
1016        });
1017    }
1018
1019    #[test]
1020    fn enable_fast_withdraw_switch_response_error() {
1021        TOKIO_SHARED_RT.block_on(async {
1022            let client = MockAccountApiClient { force_error: true };
1023
1024            let params = EnableFastWithdrawSwitchParams::builder().build().unwrap();
1025
1026            match client.enable_fast_withdraw_switch(params).await {
1027                Ok(_) => panic!("Expected an error"),
1028                Err(err) => {
1029                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1030                }
1031            }
1032        });
1033    }
1034
1035    #[test]
1036    fn get_api_key_permission_required_params_success() {
1037        TOKIO_SHARED_RT.block_on(async {
1038            let client = MockAccountApiClient { force_error: false };
1039
1040            let params = GetApiKeyPermissionParams::builder().build().unwrap();
1041
1042            let resp_json: Value = serde_json::from_str(r#"{"ipRestrict":false,"createTime":1698645219000,"enableReading":true,"enableWithdrawals":false,"enableInternalTransfer":false,"enableMargin":false,"enableFutures":false,"permitsUniversalTransfer":false,"enableVanillaOptions":false,"enableFixApiTrade":false,"enableFixReadOnly":true,"enableSpotAndMarginTrading":false,"enablePortfolioMarginTrading":true}"#).unwrap();
1043            let expected_response : models::GetApiKeyPermissionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetApiKeyPermissionResponse");
1044
1045            let resp = client.get_api_key_permission(params).await.expect("Expected a response");
1046            let data_future = resp.data();
1047            let actual_response = data_future.await.unwrap();
1048            assert_eq!(actual_response, expected_response);
1049        });
1050    }
1051
1052    #[test]
1053    fn get_api_key_permission_optional_params_success() {
1054        TOKIO_SHARED_RT.block_on(async {
1055            let client = MockAccountApiClient { force_error: false };
1056
1057            let params = GetApiKeyPermissionParams::builder().recv_window(5000).build().unwrap();
1058
1059            let resp_json: Value = serde_json::from_str(r#"{"ipRestrict":false,"createTime":1698645219000,"enableReading":true,"enableWithdrawals":false,"enableInternalTransfer":false,"enableMargin":false,"enableFutures":false,"permitsUniversalTransfer":false,"enableVanillaOptions":false,"enableFixApiTrade":false,"enableFixReadOnly":true,"enableSpotAndMarginTrading":false,"enablePortfolioMarginTrading":true}"#).unwrap();
1060            let expected_response : models::GetApiKeyPermissionResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetApiKeyPermissionResponse");
1061
1062            let resp = client.get_api_key_permission(params).await.expect("Expected a response");
1063            let data_future = resp.data();
1064            let actual_response = data_future.await.unwrap();
1065            assert_eq!(actual_response, expected_response);
1066        });
1067    }
1068
1069    #[test]
1070    fn get_api_key_permission_response_error() {
1071        TOKIO_SHARED_RT.block_on(async {
1072            let client = MockAccountApiClient { force_error: true };
1073
1074            let params = GetApiKeyPermissionParams::builder().build().unwrap();
1075
1076            match client.get_api_key_permission(params).await {
1077                Ok(_) => panic!("Expected an error"),
1078                Err(err) => {
1079                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1080                }
1081            }
1082        });
1083    }
1084}