Skip to main content

binance_sdk/sub_account/rest_api/apis/
account_management_api.rs

1/*
2 * Binance Sub Account REST API
3 *
4 * OpenAPI Specification for the Binance Sub Account 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::sub_account::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait AccountManagementApi: Send + Sync {
34    async fn create_a_virtual_sub_account(
35        &self,
36        params: CreateAVirtualSubAccountParams,
37    ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>>;
38    async fn enable_futures_for_sub_account(
39        &self,
40        params: EnableFuturesForSubAccountParams,
41    ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>>;
42    async fn enable_options_for_sub_account(
43        &self,
44        params: EnableOptionsForSubAccountParams,
45    ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>>;
46    async fn get_futures_position_risk_of_sub_account(
47        &self,
48        params: GetFuturesPositionRiskOfSubAccountParams,
49    ) -> anyhow::Result<
50        RestApiResponse<
51            Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>,
52        >,
53    >;
54    async fn get_futures_position_risk_of_sub_account_v2(
55        &self,
56        params: GetFuturesPositionRiskOfSubAccountV2Params,
57    ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>>;
58    async fn get_sub_accounts_status_on_margin_or_futures(
59        &self,
60        params: GetSubAccountsStatusOnMarginOrFuturesParams,
61    ) -> anyhow::Result<
62        RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
63    >;
64    async fn query_sub_account_list(
65        &self,
66        params: QuerySubAccountListParams,
67    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>>;
68    async fn query_sub_account_transaction_statistics(
69        &self,
70        params: QuerySubAccountTransactionStatisticsParams,
71    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>>;
72}
73
74#[derive(Debug, Clone)]
75pub struct AccountManagementApiClient {
76    configuration: ConfigurationRestApi,
77}
78
79impl AccountManagementApiClient {
80    pub fn new(configuration: ConfigurationRestApi) -> Self {
81        Self { configuration }
82    }
83}
84
85/// Request parameters for the [`create_a_virtual_sub_account`] operation.
86///
87/// This struct holds all of the inputs you can pass when calling
88/// [`create_a_virtual_sub_account`](#method.create_a_virtual_sub_account).
89#[derive(Clone, Debug, Builder)]
90#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
91pub struct CreateAVirtualSubAccountParams {
92    /// Please input a string. We will create a virtual email using that string for you to register
93    ///
94    /// This field is **required.
95    #[builder(setter(into))]
96    pub sub_account_string: String,
97    ///
98    /// The `recv_window` parameter.
99    ///
100    /// This field is **optional.
101    #[builder(setter(into), default)]
102    pub recv_window: Option<i64>,
103}
104
105impl CreateAVirtualSubAccountParams {
106    /// Create a builder for [`create_a_virtual_sub_account`].
107    ///
108    /// Required parameters:
109    ///
110    /// * `sub_account_string` — Please input a string. We will create a virtual email using that string for you to register
111    ///
112    #[must_use]
113    pub fn builder(sub_account_string: String) -> CreateAVirtualSubAccountParamsBuilder {
114        CreateAVirtualSubAccountParamsBuilder::default().sub_account_string(sub_account_string)
115    }
116}
117/// Request parameters for the [`enable_futures_for_sub_account`] operation.
118///
119/// This struct holds all of the inputs you can pass when calling
120/// [`enable_futures_for_sub_account`](#method.enable_futures_for_sub_account).
121#[derive(Clone, Debug, Builder)]
122#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
123pub struct EnableFuturesForSubAccountParams {
124    /// [Sub-account email](#email-address)
125    ///
126    /// This field is **required.
127    #[builder(setter(into))]
128    pub email: String,
129    ///
130    /// The `recv_window` parameter.
131    ///
132    /// This field is **optional.
133    #[builder(setter(into), default)]
134    pub recv_window: Option<i64>,
135}
136
137impl EnableFuturesForSubAccountParams {
138    /// Create a builder for [`enable_futures_for_sub_account`].
139    ///
140    /// Required parameters:
141    ///
142    /// * `email` — [Sub-account email](#email-address)
143    ///
144    #[must_use]
145    pub fn builder(email: String) -> EnableFuturesForSubAccountParamsBuilder {
146        EnableFuturesForSubAccountParamsBuilder::default().email(email)
147    }
148}
149/// Request parameters for the [`enable_options_for_sub_account`] operation.
150///
151/// This struct holds all of the inputs you can pass when calling
152/// [`enable_options_for_sub_account`](#method.enable_options_for_sub_account).
153#[derive(Clone, Debug, Builder)]
154#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
155pub struct EnableOptionsForSubAccountParams {
156    /// [Sub-account email](#email-address)
157    ///
158    /// This field is **required.
159    #[builder(setter(into))]
160    pub email: String,
161    ///
162    /// The `recv_window` parameter.
163    ///
164    /// This field is **optional.
165    #[builder(setter(into), default)]
166    pub recv_window: Option<i64>,
167}
168
169impl EnableOptionsForSubAccountParams {
170    /// Create a builder for [`enable_options_for_sub_account`].
171    ///
172    /// Required parameters:
173    ///
174    /// * `email` — [Sub-account email](#email-address)
175    ///
176    #[must_use]
177    pub fn builder(email: String) -> EnableOptionsForSubAccountParamsBuilder {
178        EnableOptionsForSubAccountParamsBuilder::default().email(email)
179    }
180}
181/// Request parameters for the [`get_futures_position_risk_of_sub_account`] operation.
182///
183/// This struct holds all of the inputs you can pass when calling
184/// [`get_futures_position_risk_of_sub_account`](#method.get_futures_position_risk_of_sub_account).
185#[derive(Clone, Debug, Builder)]
186#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
187pub struct GetFuturesPositionRiskOfSubAccountParams {
188    /// [Sub-account email](#email-address)
189    ///
190    /// This field is **required.
191    #[builder(setter(into))]
192    pub email: String,
193    ///
194    /// The `recv_window` parameter.
195    ///
196    /// This field is **optional.
197    #[builder(setter(into), default)]
198    pub recv_window: Option<i64>,
199}
200
201impl GetFuturesPositionRiskOfSubAccountParams {
202    /// Create a builder for [`get_futures_position_risk_of_sub_account`].
203    ///
204    /// Required parameters:
205    ///
206    /// * `email` — [Sub-account email](#email-address)
207    ///
208    #[must_use]
209    pub fn builder(email: String) -> GetFuturesPositionRiskOfSubAccountParamsBuilder {
210        GetFuturesPositionRiskOfSubAccountParamsBuilder::default().email(email)
211    }
212}
213/// Request parameters for the [`get_futures_position_risk_of_sub_account_v2`] operation.
214///
215/// This struct holds all of the inputs you can pass when calling
216/// [`get_futures_position_risk_of_sub_account_v2`](#method.get_futures_position_risk_of_sub_account_v2).
217#[derive(Clone, Debug, Builder)]
218#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
219pub struct GetFuturesPositionRiskOfSubAccountV2Params {
220    /// [Sub-account email](#email-address)
221    ///
222    /// This field is **required.
223    #[builder(setter(into))]
224    pub email: String,
225    /// 1:USDT-margined Futures,2: Coin-margined Futures
226    ///
227    /// This field is **required.
228    #[builder(setter(into))]
229    pub futures_type: i64,
230    ///
231    /// The `recv_window` parameter.
232    ///
233    /// This field is **optional.
234    #[builder(setter(into), default)]
235    pub recv_window: Option<i64>,
236}
237
238impl GetFuturesPositionRiskOfSubAccountV2Params {
239    /// Create a builder for [`get_futures_position_risk_of_sub_account_v2`].
240    ///
241    /// Required parameters:
242    ///
243    /// * `email` — [Sub-account email](#email-address)
244    /// * `futures_type` — 1:USDT-margined Futures,2: Coin-margined Futures
245    ///
246    #[must_use]
247    pub fn builder(
248        email: String,
249        futures_type: i64,
250    ) -> GetFuturesPositionRiskOfSubAccountV2ParamsBuilder {
251        GetFuturesPositionRiskOfSubAccountV2ParamsBuilder::default()
252            .email(email)
253            .futures_type(futures_type)
254    }
255}
256/// Request parameters for the [`get_sub_accounts_status_on_margin_or_futures`] operation.
257///
258/// This struct holds all of the inputs you can pass when calling
259/// [`get_sub_accounts_status_on_margin_or_futures`](#method.get_sub_accounts_status_on_margin_or_futures).
260#[derive(Clone, Debug, Builder, Default)]
261#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
262pub struct GetSubAccountsStatusOnMarginOrFuturesParams {
263    /// Managed sub-account email
264    ///
265    /// This field is **optional.
266    #[builder(setter(into), default)]
267    pub email: Option<String>,
268    ///
269    /// The `recv_window` parameter.
270    ///
271    /// This field is **optional.
272    #[builder(setter(into), default)]
273    pub recv_window: Option<i64>,
274}
275
276impl GetSubAccountsStatusOnMarginOrFuturesParams {
277    /// Create a builder for [`get_sub_accounts_status_on_margin_or_futures`].
278    ///
279    #[must_use]
280    pub fn builder() -> GetSubAccountsStatusOnMarginOrFuturesParamsBuilder {
281        GetSubAccountsStatusOnMarginOrFuturesParamsBuilder::default()
282    }
283}
284/// Request parameters for the [`query_sub_account_list`] operation.
285///
286/// This struct holds all of the inputs you can pass when calling
287/// [`query_sub_account_list`](#method.query_sub_account_list).
288#[derive(Clone, Debug, Builder, Default)]
289#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
290pub struct QuerySubAccountListParams {
291    /// Managed sub-account email
292    ///
293    /// This field is **optional.
294    #[builder(setter(into), default)]
295    pub email: Option<String>,
296    /// true or false
297    ///
298    /// This field is **optional.
299    #[builder(setter(into), default)]
300    pub is_freeze: Option<String>,
301    /// Default value: 1
302    ///
303    /// This field is **optional.
304    #[builder(setter(into), default)]
305    pub page: Option<i64>,
306    /// Default value: 1, Max value: 200
307    ///
308    /// This field is **optional.
309    #[builder(setter(into), default)]
310    pub limit: Option<i64>,
311    ///
312    /// The `recv_window` parameter.
313    ///
314    /// This field is **optional.
315    #[builder(setter(into), default)]
316    pub recv_window: Option<i64>,
317}
318
319impl QuerySubAccountListParams {
320    /// Create a builder for [`query_sub_account_list`].
321    ///
322    #[must_use]
323    pub fn builder() -> QuerySubAccountListParamsBuilder {
324        QuerySubAccountListParamsBuilder::default()
325    }
326}
327/// Request parameters for the [`query_sub_account_transaction_statistics`] operation.
328///
329/// This struct holds all of the inputs you can pass when calling
330/// [`query_sub_account_transaction_statistics`](#method.query_sub_account_transaction_statistics).
331#[derive(Clone, Debug, Builder, Default)]
332#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
333pub struct QuerySubAccountTransactionStatisticsParams {
334    /// Managed sub-account email
335    ///
336    /// This field is **optional.
337    #[builder(setter(into), default)]
338    pub email: Option<String>,
339    ///
340    /// The `recv_window` parameter.
341    ///
342    /// This field is **optional.
343    #[builder(setter(into), default)]
344    pub recv_window: Option<i64>,
345}
346
347impl QuerySubAccountTransactionStatisticsParams {
348    /// Create a builder for [`query_sub_account_transaction_statistics`].
349    ///
350    #[must_use]
351    pub fn builder() -> QuerySubAccountTransactionStatisticsParamsBuilder {
352        QuerySubAccountTransactionStatisticsParamsBuilder::default()
353    }
354}
355
356#[async_trait]
357impl AccountManagementApi for AccountManagementApiClient {
358    async fn create_a_virtual_sub_account(
359        &self,
360        params: CreateAVirtualSubAccountParams,
361    ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>> {
362        let CreateAVirtualSubAccountParams {
363            sub_account_string,
364            recv_window,
365        } = params;
366
367        let mut query_params = BTreeMap::new();
368        let body_params = BTreeMap::new();
369
370        query_params.insert("subAccountString".to_string(), json!(sub_account_string));
371
372        if let Some(rw) = recv_window {
373            query_params.insert("recvWindow".to_string(), json!(rw));
374        }
375
376        send_request::<models::CreateAVirtualSubAccountResponse>(
377            &self.configuration,
378            "/sapi/v1/sub-account/virtualSubAccount",
379            reqwest::Method::POST,
380            query_params,
381            body_params,
382            if HAS_TIME_UNIT {
383                self.configuration.time_unit
384            } else {
385                None
386            },
387            true,
388        )
389        .await
390    }
391
392    async fn enable_futures_for_sub_account(
393        &self,
394        params: EnableFuturesForSubAccountParams,
395    ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>> {
396        let EnableFuturesForSubAccountParams { email, recv_window } = params;
397
398        let mut query_params = BTreeMap::new();
399        let body_params = BTreeMap::new();
400
401        query_params.insert("email".to_string(), json!(email));
402
403        if let Some(rw) = recv_window {
404            query_params.insert("recvWindow".to_string(), json!(rw));
405        }
406
407        send_request::<models::EnableFuturesForSubAccountResponse>(
408            &self.configuration,
409            "/sapi/v1/sub-account/futures/enable",
410            reqwest::Method::POST,
411            query_params,
412            body_params,
413            if HAS_TIME_UNIT {
414                self.configuration.time_unit
415            } else {
416                None
417            },
418            true,
419        )
420        .await
421    }
422
423    async fn enable_options_for_sub_account(
424        &self,
425        params: EnableOptionsForSubAccountParams,
426    ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>> {
427        let EnableOptionsForSubAccountParams { email, recv_window } = params;
428
429        let mut query_params = BTreeMap::new();
430        let body_params = BTreeMap::new();
431
432        query_params.insert("email".to_string(), json!(email));
433
434        if let Some(rw) = recv_window {
435            query_params.insert("recvWindow".to_string(), json!(rw));
436        }
437
438        send_request::<models::EnableOptionsForSubAccountResponse>(
439            &self.configuration,
440            "/sapi/v1/sub-account/eoptions/enable",
441            reqwest::Method::POST,
442            query_params,
443            body_params,
444            if HAS_TIME_UNIT {
445                self.configuration.time_unit
446            } else {
447                None
448            },
449            true,
450        )
451        .await
452    }
453
454    async fn get_futures_position_risk_of_sub_account(
455        &self,
456        params: GetFuturesPositionRiskOfSubAccountParams,
457    ) -> anyhow::Result<
458        RestApiResponse<
459            Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>,
460        >,
461    > {
462        let GetFuturesPositionRiskOfSubAccountParams { email, recv_window } = params;
463
464        let mut query_params = BTreeMap::new();
465        let body_params = BTreeMap::new();
466
467        query_params.insert("email".to_string(), json!(email));
468
469        if let Some(rw) = recv_window {
470            query_params.insert("recvWindow".to_string(), json!(rw));
471        }
472
473        send_request::<
474            Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>,
475        >(
476            &self.configuration,
477            "/sapi/v1/sub-account/futures/positionRisk",
478            reqwest::Method::GET,
479            query_params,
480            body_params,
481            if HAS_TIME_UNIT {
482                self.configuration.time_unit
483            } else {
484                None
485            },
486            true,
487        )
488        .await
489    }
490
491    async fn get_futures_position_risk_of_sub_account_v2(
492        &self,
493        params: GetFuturesPositionRiskOfSubAccountV2Params,
494    ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>> {
495        let GetFuturesPositionRiskOfSubAccountV2Params {
496            email,
497            futures_type,
498            recv_window,
499        } = params;
500
501        let mut query_params = BTreeMap::new();
502        let body_params = BTreeMap::new();
503
504        query_params.insert("email".to_string(), json!(email));
505
506        query_params.insert("futuresType".to_string(), json!(futures_type));
507
508        if let Some(rw) = recv_window {
509            query_params.insert("recvWindow".to_string(), json!(rw));
510        }
511
512        send_request::<models::GetFuturesPositionRiskOfSubAccountV2Response>(
513            &self.configuration,
514            "/sapi/v2/sub-account/futures/positionRisk",
515            reqwest::Method::GET,
516            query_params,
517            body_params,
518            if HAS_TIME_UNIT {
519                self.configuration.time_unit
520            } else {
521                None
522            },
523            true,
524        )
525        .await
526    }
527
528    async fn get_sub_accounts_status_on_margin_or_futures(
529        &self,
530        params: GetSubAccountsStatusOnMarginOrFuturesParams,
531    ) -> anyhow::Result<
532        RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
533    > {
534        let GetSubAccountsStatusOnMarginOrFuturesParams { email, recv_window } = params;
535
536        let mut query_params = BTreeMap::new();
537        let body_params = BTreeMap::new();
538
539        if let Some(rw) = email {
540            query_params.insert("email".to_string(), json!(rw));
541        }
542
543        if let Some(rw) = recv_window {
544            query_params.insert("recvWindow".to_string(), json!(rw));
545        }
546
547        send_request::<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>(
548            &self.configuration,
549            "/sapi/v1/sub-account/status",
550            reqwest::Method::GET,
551            query_params,
552            body_params,
553            if HAS_TIME_UNIT {
554                self.configuration.time_unit
555            } else {
556                None
557            },
558            true,
559        )
560        .await
561    }
562
563    async fn query_sub_account_list(
564        &self,
565        params: QuerySubAccountListParams,
566    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>> {
567        let QuerySubAccountListParams {
568            email,
569            is_freeze,
570            page,
571            limit,
572            recv_window,
573        } = params;
574
575        let mut query_params = BTreeMap::new();
576        let body_params = BTreeMap::new();
577
578        if let Some(rw) = email {
579            query_params.insert("email".to_string(), json!(rw));
580        }
581
582        if let Some(rw) = is_freeze {
583            query_params.insert("isFreeze".to_string(), json!(rw));
584        }
585
586        if let Some(rw) = page {
587            query_params.insert("page".to_string(), json!(rw));
588        }
589
590        if let Some(rw) = limit {
591            query_params.insert("limit".to_string(), json!(rw));
592        }
593
594        if let Some(rw) = recv_window {
595            query_params.insert("recvWindow".to_string(), json!(rw));
596        }
597
598        send_request::<models::QuerySubAccountListResponse>(
599            &self.configuration,
600            "/sapi/v1/sub-account/list",
601            reqwest::Method::GET,
602            query_params,
603            body_params,
604            if HAS_TIME_UNIT {
605                self.configuration.time_unit
606            } else {
607                None
608            },
609            true,
610        )
611        .await
612    }
613
614    async fn query_sub_account_transaction_statistics(
615        &self,
616        params: QuerySubAccountTransactionStatisticsParams,
617    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>> {
618        let QuerySubAccountTransactionStatisticsParams { email, recv_window } = params;
619
620        let mut query_params = BTreeMap::new();
621        let body_params = BTreeMap::new();
622
623        if let Some(rw) = email {
624            query_params.insert("email".to_string(), json!(rw));
625        }
626
627        if let Some(rw) = recv_window {
628            query_params.insert("recvWindow".to_string(), json!(rw));
629        }
630
631        send_request::<models::QuerySubAccountTransactionStatisticsResponse>(
632            &self.configuration,
633            "/sapi/v1/sub-account/transaction-statistics",
634            reqwest::Method::GET,
635            query_params,
636            body_params,
637            if HAS_TIME_UNIT {
638                self.configuration.time_unit
639            } else {
640                None
641            },
642            true,
643        )
644        .await
645    }
646}
647
648#[cfg(all(test, feature = "sub_account"))]
649mod tests {
650    use super::*;
651    use crate::TOKIO_SHARED_RT;
652    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
653    use async_trait::async_trait;
654    use std::collections::HashMap;
655
656    struct DummyRestApiResponse<T> {
657        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
658        status: u16,
659        headers: HashMap<String, String>,
660        rate_limits: Option<Vec<RestApiRateLimit>>,
661    }
662
663    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
664        fn from(dummy: DummyRestApiResponse<T>) -> Self {
665            Self {
666                data_fn: dummy.inner,
667                status: dummy.status,
668                headers: dummy.headers,
669                rate_limits: dummy.rate_limits,
670            }
671        }
672    }
673
674    struct MockAccountManagementApiClient {
675        force_error: bool,
676    }
677
678    #[async_trait]
679    impl AccountManagementApi for MockAccountManagementApiClient {
680        async fn create_a_virtual_sub_account(
681            &self,
682            _params: CreateAVirtualSubAccountParams,
683        ) -> anyhow::Result<RestApiResponse<models::CreateAVirtualSubAccountResponse>> {
684            if self.force_error {
685                return Err(ConnectorError::ConnectorClientError {
686                    msg: "ResponseError".to_string(),
687                    code: None,
688                }
689                .into());
690            }
691
692            let resp_json: Value =
693                serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#).unwrap();
694            let dummy_response: models::CreateAVirtualSubAccountResponse =
695                serde_json::from_value(resp_json.clone())
696                    .expect("should parse into models::CreateAVirtualSubAccountResponse");
697
698            let dummy = DummyRestApiResponse {
699                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
700                status: 200,
701                headers: HashMap::new(),
702                rate_limits: None,
703            };
704
705            Ok(dummy.into())
706        }
707
708        async fn enable_futures_for_sub_account(
709            &self,
710            _params: EnableFuturesForSubAccountParams,
711        ) -> anyhow::Result<RestApiResponse<models::EnableFuturesForSubAccountResponse>> {
712            if self.force_error {
713                return Err(ConnectorError::ConnectorClientError {
714                    msg: "ResponseError".to_string(),
715                    code: None,
716                }
717                .into());
718            }
719
720            let resp_json: Value =
721                serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
722                    .unwrap();
723            let dummy_response: models::EnableFuturesForSubAccountResponse =
724                serde_json::from_value(resp_json.clone())
725                    .expect("should parse into models::EnableFuturesForSubAccountResponse");
726
727            let dummy = DummyRestApiResponse {
728                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
729                status: 200,
730                headers: HashMap::new(),
731                rate_limits: None,
732            };
733
734            Ok(dummy.into())
735        }
736
737        async fn enable_options_for_sub_account(
738            &self,
739            _params: EnableOptionsForSubAccountParams,
740        ) -> anyhow::Result<RestApiResponse<models::EnableOptionsForSubAccountResponse>> {
741            if self.force_error {
742                return Err(ConnectorError::ConnectorClientError {
743                    msg: "ResponseError".to_string(),
744                    code: None,
745                }
746                .into());
747            }
748
749            let resp_json: Value =
750                serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
751                    .unwrap();
752            let dummy_response: models::EnableOptionsForSubAccountResponse =
753                serde_json::from_value(resp_json.clone())
754                    .expect("should parse into models::EnableOptionsForSubAccountResponse");
755
756            let dummy = DummyRestApiResponse {
757                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
758                status: 200,
759                headers: HashMap::new(),
760                rate_limits: None,
761            };
762
763            Ok(dummy.into())
764        }
765
766        async fn get_futures_position_risk_of_sub_account(
767            &self,
768            _params: GetFuturesPositionRiskOfSubAccountParams,
769        ) -> anyhow::Result<
770            RestApiResponse<
771                Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>,
772            >,
773        > {
774            if self.force_error {
775                return Err(ConnectorError::ConnectorClientError {
776                    msg: "ResponseError".to_string(),
777                    code: None,
778                }
779                .into());
780            }
781
782            let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap();
783            let dummy_response : Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>");
784
785            let dummy = DummyRestApiResponse {
786                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
787                status: 200,
788                headers: HashMap::new(),
789                rate_limits: None,
790            };
791
792            Ok(dummy.into())
793        }
794
795        async fn get_futures_position_risk_of_sub_account_v2(
796            &self,
797            _params: GetFuturesPositionRiskOfSubAccountV2Params,
798        ) -> anyhow::Result<RestApiResponse<models::GetFuturesPositionRiskOfSubAccountV2Response>>
799        {
800            if self.force_error {
801                return Err(ConnectorError::ConnectorClientError {
802                    msg: "ResponseError".to_string(),
803                    code: None,
804                }
805                .into());
806            }
807
808            let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap();
809            let dummy_response: models::GetFuturesPositionRiskOfSubAccountV2Response =
810                serde_json::from_value(resp_json.clone()).expect(
811                    "should parse into models::GetFuturesPositionRiskOfSubAccountV2Response",
812                );
813
814            let dummy = DummyRestApiResponse {
815                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
816                status: 200,
817                headers: HashMap::new(),
818                rate_limits: None,
819            };
820
821            Ok(dummy.into())
822        }
823
824        async fn get_sub_accounts_status_on_margin_or_futures(
825            &self,
826            _params: GetSubAccountsStatusOnMarginOrFuturesParams,
827        ) -> anyhow::Result<
828            RestApiResponse<Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>>,
829        > {
830            if self.force_error {
831                return Err(ConnectorError::ConnectorClientError {
832                    msg: "ResponseError".to_string(),
833                    code: None,
834                }
835                .into());
836            }
837
838            let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap();
839            let dummy_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
840
841            let dummy = DummyRestApiResponse {
842                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
843                status: 200,
844                headers: HashMap::new(),
845                rate_limits: None,
846            };
847
848            Ok(dummy.into())
849        }
850
851        async fn query_sub_account_list(
852            &self,
853            _params: QuerySubAccountListParams,
854        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountListResponse>> {
855            if self.force_error {
856                return Err(ConnectorError::ConnectorClientError {
857                    msg: "ResponseError".to_string(),
858                    code: None,
859                }
860                .into());
861            }
862
863            let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false},{"subUserId":1234567,"email":"virtual@oxebmvfonoemail.com","remark":"remarks","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap();
864            let dummy_response: models::QuerySubAccountListResponse =
865                serde_json::from_value(resp_json.clone())
866                    .expect("should parse into models::QuerySubAccountListResponse");
867
868            let dummy = DummyRestApiResponse {
869                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
870                status: 200,
871                headers: HashMap::new(),
872                rate_limits: None,
873            };
874
875            Ok(dummy.into())
876        }
877
878        async fn query_sub_account_transaction_statistics(
879            &self,
880            _params: QuerySubAccountTransactionStatisticsParams,
881        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountTransactionStatisticsResponse>>
882        {
883            if self.force_error {
884                return Err(ConnectorError::ConnectorClientError {
885                    msg: "ResponseError".to_string(),
886                    code: None,
887                }
888                .into());
889            }
890
891            let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677110400000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677369600000}]}"#).unwrap();
892            let dummy_response: models::QuerySubAccountTransactionStatisticsResponse =
893                serde_json::from_value(resp_json.clone()).expect(
894                    "should parse into models::QuerySubAccountTransactionStatisticsResponse",
895                );
896
897            let dummy = DummyRestApiResponse {
898                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
899                status: 200,
900                headers: HashMap::new(),
901                rate_limits: None,
902            };
903
904            Ok(dummy.into())
905        }
906    }
907
908    #[test]
909    fn create_a_virtual_sub_account_required_params_success() {
910        TOKIO_SHARED_RT.block_on(async {
911            let client = MockAccountManagementApiClient { force_error: false };
912
913            let params =
914                CreateAVirtualSubAccountParams::builder("sub_account_string_example".to_string())
915                    .build()
916                    .unwrap();
917
918            let resp_json: Value =
919                serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#).unwrap();
920            let expected_response: models::CreateAVirtualSubAccountResponse =
921                serde_json::from_value(resp_json.clone())
922                    .expect("should parse into models::CreateAVirtualSubAccountResponse");
923
924            let resp = client
925                .create_a_virtual_sub_account(params)
926                .await
927                .expect("Expected a response");
928            let data_future = resp.data();
929            let actual_response = data_future.await.unwrap();
930            assert_eq!(actual_response, expected_response);
931        });
932    }
933
934    #[test]
935    fn create_a_virtual_sub_account_optional_params_success() {
936        TOKIO_SHARED_RT.block_on(async {
937            let client = MockAccountManagementApiClient { force_error: false };
938
939            let params =
940                CreateAVirtualSubAccountParams::builder("sub_account_string_example".to_string())
941                    .recv_window(5000)
942                    .build()
943                    .unwrap();
944
945            let resp_json: Value =
946                serde_json::from_str(r#"{"email":"addsdd_virtual@aasaixwqnoemail.com"}"#).unwrap();
947            let expected_response: models::CreateAVirtualSubAccountResponse =
948                serde_json::from_value(resp_json.clone())
949                    .expect("should parse into models::CreateAVirtualSubAccountResponse");
950
951            let resp = client
952                .create_a_virtual_sub_account(params)
953                .await
954                .expect("Expected a response");
955            let data_future = resp.data();
956            let actual_response = data_future.await.unwrap();
957            assert_eq!(actual_response, expected_response);
958        });
959    }
960
961    #[test]
962    fn create_a_virtual_sub_account_response_error() {
963        TOKIO_SHARED_RT.block_on(async {
964            let client = MockAccountManagementApiClient { force_error: true };
965
966            let params =
967                CreateAVirtualSubAccountParams::builder("sub_account_string_example".to_string())
968                    .build()
969                    .unwrap();
970
971            match client.create_a_virtual_sub_account(params).await {
972                Ok(_) => panic!("Expected an error"),
973                Err(err) => {
974                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
975                }
976            }
977        });
978    }
979
980    #[test]
981    fn enable_futures_for_sub_account_required_params_success() {
982        TOKIO_SHARED_RT.block_on(async {
983            let client = MockAccountManagementApiClient { force_error: false };
984
985            let params = EnableFuturesForSubAccountParams::builder(
986                "sub-account-email@email.com".to_string(),
987            )
988            .build()
989            .unwrap();
990
991            let resp_json: Value =
992                serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
993                    .unwrap();
994            let expected_response: models::EnableFuturesForSubAccountResponse =
995                serde_json::from_value(resp_json.clone())
996                    .expect("should parse into models::EnableFuturesForSubAccountResponse");
997
998            let resp = client
999                .enable_futures_for_sub_account(params)
1000                .await
1001                .expect("Expected a response");
1002            let data_future = resp.data();
1003            let actual_response = data_future.await.unwrap();
1004            assert_eq!(actual_response, expected_response);
1005        });
1006    }
1007
1008    #[test]
1009    fn enable_futures_for_sub_account_optional_params_success() {
1010        TOKIO_SHARED_RT.block_on(async {
1011            let client = MockAccountManagementApiClient { force_error: false };
1012
1013            let params = EnableFuturesForSubAccountParams::builder(
1014                "sub-account-email@email.com".to_string(),
1015            )
1016            .recv_window(5000)
1017            .build()
1018            .unwrap();
1019
1020            let resp_json: Value =
1021                serde_json::from_str(r#"{"email":"123@test.com","isFuturesEnabled":true}"#)
1022                    .unwrap();
1023            let expected_response: models::EnableFuturesForSubAccountResponse =
1024                serde_json::from_value(resp_json.clone())
1025                    .expect("should parse into models::EnableFuturesForSubAccountResponse");
1026
1027            let resp = client
1028                .enable_futures_for_sub_account(params)
1029                .await
1030                .expect("Expected a response");
1031            let data_future = resp.data();
1032            let actual_response = data_future.await.unwrap();
1033            assert_eq!(actual_response, expected_response);
1034        });
1035    }
1036
1037    #[test]
1038    fn enable_futures_for_sub_account_response_error() {
1039        TOKIO_SHARED_RT.block_on(async {
1040            let client = MockAccountManagementApiClient { force_error: true };
1041
1042            let params = EnableFuturesForSubAccountParams::builder(
1043                "sub-account-email@email.com".to_string(),
1044            )
1045            .build()
1046            .unwrap();
1047
1048            match client.enable_futures_for_sub_account(params).await {
1049                Ok(_) => panic!("Expected an error"),
1050                Err(err) => {
1051                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1052                }
1053            }
1054        });
1055    }
1056
1057    #[test]
1058    fn enable_options_for_sub_account_required_params_success() {
1059        TOKIO_SHARED_RT.block_on(async {
1060            let client = MockAccountManagementApiClient { force_error: false };
1061
1062            let params = EnableOptionsForSubAccountParams::builder(
1063                "sub-account-email@email.com".to_string(),
1064            )
1065            .build()
1066            .unwrap();
1067
1068            let resp_json: Value =
1069                serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
1070                    .unwrap();
1071            let expected_response: models::EnableOptionsForSubAccountResponse =
1072                serde_json::from_value(resp_json.clone())
1073                    .expect("should parse into models::EnableOptionsForSubAccountResponse");
1074
1075            let resp = client
1076                .enable_options_for_sub_account(params)
1077                .await
1078                .expect("Expected a response");
1079            let data_future = resp.data();
1080            let actual_response = data_future.await.unwrap();
1081            assert_eq!(actual_response, expected_response);
1082        });
1083    }
1084
1085    #[test]
1086    fn enable_options_for_sub_account_optional_params_success() {
1087        TOKIO_SHARED_RT.block_on(async {
1088            let client = MockAccountManagementApiClient { force_error: false };
1089
1090            let params = EnableOptionsForSubAccountParams::builder(
1091                "sub-account-email@email.com".to_string(),
1092            )
1093            .recv_window(5000)
1094            .build()
1095            .unwrap();
1096
1097            let resp_json: Value =
1098                serde_json::from_str(r#"{"email":"123@test.com","isEOptionsEnabled":true}"#)
1099                    .unwrap();
1100            let expected_response: models::EnableOptionsForSubAccountResponse =
1101                serde_json::from_value(resp_json.clone())
1102                    .expect("should parse into models::EnableOptionsForSubAccountResponse");
1103
1104            let resp = client
1105                .enable_options_for_sub_account(params)
1106                .await
1107                .expect("Expected a response");
1108            let data_future = resp.data();
1109            let actual_response = data_future.await.unwrap();
1110            assert_eq!(actual_response, expected_response);
1111        });
1112    }
1113
1114    #[test]
1115    fn enable_options_for_sub_account_response_error() {
1116        TOKIO_SHARED_RT.block_on(async {
1117            let client = MockAccountManagementApiClient { force_error: true };
1118
1119            let params = EnableOptionsForSubAccountParams::builder(
1120                "sub-account-email@email.com".to_string(),
1121            )
1122            .build()
1123            .unwrap();
1124
1125            match client.enable_options_for_sub_account(params).await {
1126                Ok(_) => panic!("Expected an error"),
1127                Err(err) => {
1128                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1129                }
1130            }
1131        });
1132    }
1133
1134    #[test]
1135    fn get_futures_position_risk_of_sub_account_required_params_success() {
1136        TOKIO_SHARED_RT.block_on(async {
1137            let client = MockAccountManagementApiClient { force_error: false };
1138
1139            let params = GetFuturesPositionRiskOfSubAccountParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();
1140
1141            let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap();
1142            let expected_response : Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>");
1143
1144            let resp = client.get_futures_position_risk_of_sub_account(params).await.expect("Expected a response");
1145            let data_future = resp.data();
1146            let actual_response = data_future.await.unwrap();
1147            assert_eq!(actual_response, expected_response);
1148        });
1149    }
1150
1151    #[test]
1152    fn get_futures_position_risk_of_sub_account_optional_params_success() {
1153        TOKIO_SHARED_RT.block_on(async {
1154            let client = MockAccountManagementApiClient { force_error: false };
1155
1156            let params = GetFuturesPositionRiskOfSubAccountParams::builder("sub-account-email@email.com".to_string(),).recv_window(5000).build().unwrap();
1157
1158            let resp_json: Value = serde_json::from_str(r#"[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}]"#).unwrap();
1159            let expected_response : Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetFuturesPositionRiskOfSubAccountV2ResponseFuturePositionRiskVosInner>");
1160
1161            let resp = client.get_futures_position_risk_of_sub_account(params).await.expect("Expected a response");
1162            let data_future = resp.data();
1163            let actual_response = data_future.await.unwrap();
1164            assert_eq!(actual_response, expected_response);
1165        });
1166    }
1167
1168    #[test]
1169    fn get_futures_position_risk_of_sub_account_response_error() {
1170        TOKIO_SHARED_RT.block_on(async {
1171            let client = MockAccountManagementApiClient { force_error: true };
1172
1173            let params = GetFuturesPositionRiskOfSubAccountParams::builder(
1174                "sub-account-email@email.com".to_string(),
1175            )
1176            .build()
1177            .unwrap();
1178
1179            match client
1180                .get_futures_position_risk_of_sub_account(params)
1181                .await
1182            {
1183                Ok(_) => panic!("Expected an error"),
1184                Err(err) => {
1185                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1186                }
1187            }
1188        });
1189    }
1190
1191    #[test]
1192    fn get_futures_position_risk_of_sub_account_v2_required_params_success() {
1193        TOKIO_SHARED_RT.block_on(async {
1194            let client = MockAccountManagementApiClient { force_error: false };
1195
1196            let params = GetFuturesPositionRiskOfSubAccountV2Params::builder("sub-account-email@email.com".to_string(),789,).build().unwrap();
1197
1198            let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap();
1199            let expected_response : models::GetFuturesPositionRiskOfSubAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetFuturesPositionRiskOfSubAccountV2Response");
1200
1201            let resp = client.get_futures_position_risk_of_sub_account_v2(params).await.expect("Expected a response");
1202            let data_future = resp.data();
1203            let actual_response = data_future.await.unwrap();
1204            assert_eq!(actual_response, expected_response);
1205        });
1206    }
1207
1208    #[test]
1209    fn get_futures_position_risk_of_sub_account_v2_optional_params_success() {
1210        TOKIO_SHARED_RT.block_on(async {
1211            let client = MockAccountManagementApiClient { force_error: false };
1212
1213            let params = GetFuturesPositionRiskOfSubAccountV2Params::builder("sub-account-email@email.com".to_string(),789,).recv_window(5000).build().unwrap();
1214
1215            let resp_json: Value = serde_json::from_str(r#"{"futurePositionRiskVos":[{"entryPrice":"9975.12000","leverage":"50","maxNotional":"1000000","liquidationPrice":"7963.54","markPrice":"9973.50770517","positionAmount":"0.010","symbol":"BTCUSDT","unrealizedProfit":"-0.01612295"}],"deliveryPositionRiskVos":[{"entryPrice":"9975.12000","markPrice":"9973.50770517","leverage":"20","isolated":"false","isolatedWallet":"9973.50770517","isolatedMargin":"0.00000000","isAutoAddMargin":"false","positionSide":"BOTH","positionAmount":"1.230","symbol":"BTCUSD_201225","unrealizedProfit":"-0.01612295"}]}"#).unwrap();
1216            let expected_response : models::GetFuturesPositionRiskOfSubAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetFuturesPositionRiskOfSubAccountV2Response");
1217
1218            let resp = client.get_futures_position_risk_of_sub_account_v2(params).await.expect("Expected a response");
1219            let data_future = resp.data();
1220            let actual_response = data_future.await.unwrap();
1221            assert_eq!(actual_response, expected_response);
1222        });
1223    }
1224
1225    #[test]
1226    fn get_futures_position_risk_of_sub_account_v2_response_error() {
1227        TOKIO_SHARED_RT.block_on(async {
1228            let client = MockAccountManagementApiClient { force_error: true };
1229
1230            let params = GetFuturesPositionRiskOfSubAccountV2Params::builder(
1231                "sub-account-email@email.com".to_string(),
1232                789,
1233            )
1234            .build()
1235            .unwrap();
1236
1237            match client
1238                .get_futures_position_risk_of_sub_account_v2(params)
1239                .await
1240            {
1241                Ok(_) => panic!("Expected an error"),
1242                Err(err) => {
1243                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1244                }
1245            }
1246        });
1247    }
1248
1249    #[test]
1250    fn get_sub_accounts_status_on_margin_or_futures_required_params_success() {
1251        TOKIO_SHARED_RT.block_on(async {
1252            let client = MockAccountManagementApiClient { force_error: false };
1253
1254            let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder().build().unwrap();
1255
1256            let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap();
1257            let expected_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
1258
1259            let resp = client.get_sub_accounts_status_on_margin_or_futures(params).await.expect("Expected a response");
1260            let data_future = resp.data();
1261            let actual_response = data_future.await.unwrap();
1262            assert_eq!(actual_response, expected_response);
1263        });
1264    }
1265
1266    #[test]
1267    fn get_sub_accounts_status_on_margin_or_futures_optional_params_success() {
1268        TOKIO_SHARED_RT.block_on(async {
1269            let client = MockAccountManagementApiClient { force_error: false };
1270
1271            let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder().email("email_example".to_string()).recv_window(5000).build().unwrap();
1272
1273            let resp_json: Value = serde_json::from_str(r#"[{"email":"123@test.com","isSubUserEnabled":true,"isUserActive":true,"insertTime":1570791523523,"isMarginEnabled":true,"isFutureEnabled":true,"mobile":1570791523523}]"#).unwrap();
1274            let expected_response : Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountsStatusOnMarginOrFuturesResponseInner>");
1275
1276            let resp = client.get_sub_accounts_status_on_margin_or_futures(params).await.expect("Expected a response");
1277            let data_future = resp.data();
1278            let actual_response = data_future.await.unwrap();
1279            assert_eq!(actual_response, expected_response);
1280        });
1281    }
1282
1283    #[test]
1284    fn get_sub_accounts_status_on_margin_or_futures_response_error() {
1285        TOKIO_SHARED_RT.block_on(async {
1286            let client = MockAccountManagementApiClient { force_error: true };
1287
1288            let params = GetSubAccountsStatusOnMarginOrFuturesParams::builder()
1289                .build()
1290                .unwrap();
1291
1292            match client
1293                .get_sub_accounts_status_on_margin_or_futures(params)
1294                .await
1295            {
1296                Ok(_) => panic!("Expected an error"),
1297                Err(err) => {
1298                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1299                }
1300            }
1301        });
1302    }
1303
1304    #[test]
1305    fn query_sub_account_list_required_params_success() {
1306        TOKIO_SHARED_RT.block_on(async {
1307            let client = MockAccountManagementApiClient { force_error: false };
1308
1309            let params = QuerySubAccountListParams::builder().build().unwrap();
1310
1311            let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false},{"subUserId":1234567,"email":"virtual@oxebmvfonoemail.com","remark":"remarks","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap();
1312            let expected_response : models::QuerySubAccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountListResponse");
1313
1314            let resp = client.query_sub_account_list(params).await.expect("Expected a response");
1315            let data_future = resp.data();
1316            let actual_response = data_future.await.unwrap();
1317            assert_eq!(actual_response, expected_response);
1318        });
1319    }
1320
1321    #[test]
1322    fn query_sub_account_list_optional_params_success() {
1323        TOKIO_SHARED_RT.block_on(async {
1324            let client = MockAccountManagementApiClient { force_error: false };
1325
1326            let params = QuerySubAccountListParams::builder().email("email_example".to_string()).is_freeze("is_freeze_example".to_string()).page(1).limit(1).recv_window(5000).build().unwrap();
1327
1328            let resp_json: Value = serde_json::from_str(r#"{"subAccounts":[{"subUserId":123456,"email":"testsub@gmail.com","remark":"remark","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false},{"subUserId":1234567,"email":"virtual@oxebmvfonoemail.com","remark":"remarks","isFreeze":false,"createTime":1544433328000,"isManagedSubAccount":false,"isAssetManagementSubAccount":false}]}"#).unwrap();
1329            let expected_response : models::QuerySubAccountListResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountListResponse");
1330
1331            let resp = client.query_sub_account_list(params).await.expect("Expected a response");
1332            let data_future = resp.data();
1333            let actual_response = data_future.await.unwrap();
1334            assert_eq!(actual_response, expected_response);
1335        });
1336    }
1337
1338    #[test]
1339    fn query_sub_account_list_response_error() {
1340        TOKIO_SHARED_RT.block_on(async {
1341            let client = MockAccountManagementApiClient { force_error: true };
1342
1343            let params = QuerySubAccountListParams::builder().build().unwrap();
1344
1345            match client.query_sub_account_list(params).await {
1346                Ok(_) => panic!("Expected an error"),
1347                Err(err) => {
1348                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1349                }
1350            }
1351        });
1352    }
1353
1354    #[test]
1355    fn query_sub_account_transaction_statistics_required_params_success() {
1356        TOKIO_SHARED_RT.block_on(async {
1357            let client = MockAccountManagementApiClient { force_error: false };
1358
1359            let params = QuerySubAccountTransactionStatisticsParams::builder().build().unwrap();
1360
1361            let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677110400000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677369600000}]}"#).unwrap();
1362            let expected_response : models::QuerySubAccountTransactionStatisticsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountTransactionStatisticsResponse");
1363
1364            let resp = client.query_sub_account_transaction_statistics(params).await.expect("Expected a response");
1365            let data_future = resp.data();
1366            let actual_response = data_future.await.unwrap();
1367            assert_eq!(actual_response, expected_response);
1368        });
1369    }
1370
1371    #[test]
1372    fn query_sub_account_transaction_statistics_optional_params_success() {
1373        TOKIO_SHARED_RT.block_on(async {
1374            let client = MockAccountManagementApiClient { force_error: false };
1375
1376            let params = QuerySubAccountTransactionStatisticsParams::builder().email("email_example".to_string()).recv_window(5000).build().unwrap();
1377
1378            let resp_json: Value = serde_json::from_str(r#"{"recent30BtcTotal":"0","recent30BtcFuturesTotal":"0","recent30BtcMarginTotal":"0","recent30BusdTotal":"0","recent30BusdFuturesTotal":"0","recent30BusdMarginTotal":"0","tradeInfoVos":[{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1676851200000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677110400000},{"userId":1000138138384,"btc":0,"btcFutures":0,"btcMargin":0,"busd":0,"busdFutures":0,"busdMargin":0,"date":1677369600000}]}"#).unwrap();
1379            let expected_response : models::QuerySubAccountTransactionStatisticsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountTransactionStatisticsResponse");
1380
1381            let resp = client.query_sub_account_transaction_statistics(params).await.expect("Expected a response");
1382            let data_future = resp.data();
1383            let actual_response = data_future.await.unwrap();
1384            assert_eq!(actual_response, expected_response);
1385        });
1386    }
1387
1388    #[test]
1389    fn query_sub_account_transaction_statistics_response_error() {
1390        TOKIO_SHARED_RT.block_on(async {
1391            let client = MockAccountManagementApiClient { force_error: true };
1392
1393            let params = QuerySubAccountTransactionStatisticsParams::builder()
1394                .build()
1395                .unwrap();
1396
1397            match client
1398                .query_sub_account_transaction_statistics(params)
1399                .await
1400            {
1401                Ok(_) => panic!("Expected an error"),
1402                Err(err) => {
1403                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1404                }
1405            }
1406        });
1407    }
1408}