Skip to main content

binance_sdk/sub_account/rest_api/apis/
asset_management_api.rs

1/*
2 * Sub Account REST API
3 *
4 * Create and manage sub-accounts, control permissions, and transfer assets via the Sub Account 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 AssetManagementApi: Send + Sync {
34    async fn futures_transfer_for_sub_account(
35        &self,
36        params: FuturesTransferForSubAccountParams,
37    ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>>;
38    async fn get_detail_on_sub_accounts_futures_account(
39        &self,
40        params: GetDetailOnSubAccountsFuturesAccountParams,
41    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>>;
42    async fn get_detail_on_sub_accounts_futures_account_v2(
43        &self,
44        params: GetDetailOnSubAccountsFuturesAccountV2Params,
45    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>;
46    async fn get_detail_on_sub_accounts_margin_account(
47        &self,
48        params: GetDetailOnSubAccountsMarginAccountParams,
49    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>>;
50    async fn get_move_position_history_for_sub_account(
51        &self,
52        params: GetMovePositionHistoryForSubAccountParams,
53    ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>>;
54    async fn get_sub_account_deposit_address(
55        &self,
56        params: GetSubAccountDepositAddressParams,
57    ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>>;
58    async fn get_sub_account_deposit_history(
59        &self,
60        params: GetSubAccountDepositHistoryParams,
61    ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>;
62    async fn get_summary_of_sub_accounts_futures_account(
63        &self,
64        params: GetSummaryOfSubAccountsFuturesAccountParams,
65    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>;
66    async fn get_summary_of_sub_accounts_futures_account_v2(
67        &self,
68        params: GetSummaryOfSubAccountsFuturesAccountV2Params,
69    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>;
70    async fn get_summary_of_sub_accounts_margin_account(
71        &self,
72        params: GetSummaryOfSubAccountsMarginAccountParams,
73    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>>;
74    async fn margin_transfer_for_sub_account(
75        &self,
76        params: MarginTransferForSubAccountParams,
77    ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>>;
78    async fn move_position_for_sub_account(
79        &self,
80        params: MovePositionForSubAccountParams,
81    ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>>;
82    async fn query_sub_account_assets(
83        &self,
84        params: QuerySubAccountAssetsParams,
85    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>>;
86    async fn query_sub_account_assets_asset_management(
87        &self,
88        params: QuerySubAccountAssetsAssetManagementParams,
89    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>>;
90    async fn query_sub_account_futures_asset_transfer_history(
91        &self,
92        params: QuerySubAccountFuturesAssetTransferHistoryParams,
93    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>>;
94    async fn query_sub_account_spot_asset_transfer_history(
95        &self,
96        params: QuerySubAccountSpotAssetTransferHistoryParams,
97    ) -> anyhow::Result<
98        RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
99    >;
100    async fn query_sub_account_spot_assets_summary(
101        &self,
102        params: QuerySubAccountSpotAssetsSummaryParams,
103    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>>;
104    async fn query_universal_transfer_history(
105        &self,
106        params: QueryUniversalTransferHistoryParams,
107    ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>>;
108    async fn sub_account_futures_asset_transfer(
109        &self,
110        params: SubAccountFuturesAssetTransferParams,
111    ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>>;
112    async fn sub_account_transfer_history(
113        &self,
114        params: SubAccountTransferHistoryParams,
115    ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>>;
116    async fn transfer_to_master(
117        &self,
118        params: TransferToMasterParams,
119    ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>>;
120    async fn transfer_to_sub_account_of_same_master(
121        &self,
122        params: TransferToSubAccountOfSameMasterParams,
123    ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>>;
124    async fn universal_transfer(
125        &self,
126        params: UniversalTransferParams,
127    ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>>;
128}
129
130#[derive(Debug, Clone)]
131pub struct AssetManagementApiClient {
132    configuration: ConfigurationRestApi,
133}
134
135impl AssetManagementApiClient {
136    pub fn new(configuration: ConfigurationRestApi) -> Self {
137        Self { configuration }
138    }
139}
140
141#[allow(non_camel_case_types)]
142#[derive(Debug, Clone, Serialize, Deserialize)]
143pub enum GetMovePositionHistoryForSubAccountProductTypeEnum {
144    #[serde(rename = "UM")]
145    Um,
146    #[serde(rename = "OPTION")]
147    Option,
148}
149
150impl GetMovePositionHistoryForSubAccountProductTypeEnum {
151    #[must_use]
152    pub fn as_str(&self) -> &'static str {
153        match self {
154            Self::Um => "UM",
155            Self::Option => "OPTION",
156        }
157    }
158}
159
160impl std::str::FromStr for GetMovePositionHistoryForSubAccountProductTypeEnum {
161    type Err = Box<dyn std::error::Error + Send + Sync>;
162
163    fn from_str(s: &str) -> Result<Self, Self::Err> {
164        match s {
165            "UM" => Ok(Self::Um),
166            "OPTION" => Ok(Self::Option),
167            other => Err(format!(
168                "invalid GetMovePositionHistoryForSubAccountProductTypeEnum: {}",
169                other
170            )
171            .into()),
172        }
173    }
174}
175
176#[allow(non_camel_case_types)]
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub enum MovePositionForSubAccountProductTypeEnum {
179    #[serde(rename = "UM")]
180    Um,
181    #[serde(rename = "OPTION")]
182    Option,
183}
184
185impl MovePositionForSubAccountProductTypeEnum {
186    #[must_use]
187    pub fn as_str(&self) -> &'static str {
188        match self {
189            Self::Um => "UM",
190            Self::Option => "OPTION",
191        }
192    }
193}
194
195impl std::str::FromStr for MovePositionForSubAccountProductTypeEnum {
196    type Err = Box<dyn std::error::Error + Send + Sync>;
197
198    fn from_str(s: &str) -> Result<Self, Self::Err> {
199        match s {
200            "UM" => Ok(Self::Um),
201            "OPTION" => Ok(Self::Option),
202            other => Err(format!(
203                "invalid MovePositionForSubAccountProductTypeEnum: {}",
204                other
205            )
206            .into()),
207        }
208    }
209}
210
211#[allow(non_camel_case_types)]
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub enum UniversalTransferFromAccountTypeEnum {
214    #[serde(rename = "SPOT")]
215    Spot,
216    #[serde(rename = "USDT_FUTURE")]
217    UsdtFuture,
218    #[serde(rename = "COIN_FUTURE")]
219    CoinFuture,
220    #[serde(rename = "MARGIN")]
221    Margin,
222    #[serde(rename = "ISOLATED_MARGIN")]
223    IsolatedMargin,
224}
225
226impl UniversalTransferFromAccountTypeEnum {
227    #[must_use]
228    pub fn as_str(&self) -> &'static str {
229        match self {
230            Self::Spot => "SPOT",
231            Self::UsdtFuture => "USDT_FUTURE",
232            Self::CoinFuture => "COIN_FUTURE",
233            Self::Margin => "MARGIN",
234            Self::IsolatedMargin => "ISOLATED_MARGIN",
235        }
236    }
237}
238
239impl std::str::FromStr for UniversalTransferFromAccountTypeEnum {
240    type Err = Box<dyn std::error::Error + Send + Sync>;
241
242    fn from_str(s: &str) -> Result<Self, Self::Err> {
243        match s {
244            "SPOT" => Ok(Self::Spot),
245            "USDT_FUTURE" => Ok(Self::UsdtFuture),
246            "COIN_FUTURE" => Ok(Self::CoinFuture),
247            "MARGIN" => Ok(Self::Margin),
248            "ISOLATED_MARGIN" => Ok(Self::IsolatedMargin),
249            other => Err(format!("invalid UniversalTransferFromAccountTypeEnum: {}", other).into()),
250        }
251    }
252}
253
254#[allow(non_camel_case_types)]
255#[derive(Debug, Clone, Serialize, Deserialize)]
256pub enum UniversalTransferToAccountTypeEnum {
257    #[serde(rename = "SPOT")]
258    Spot,
259    #[serde(rename = "USDT_FUTURE")]
260    UsdtFuture,
261    #[serde(rename = "COIN_FUTURE")]
262    CoinFuture,
263    #[serde(rename = "MARGIN")]
264    Margin,
265    #[serde(rename = "ISOLATED_MARGIN")]
266    IsolatedMargin,
267}
268
269impl UniversalTransferToAccountTypeEnum {
270    #[must_use]
271    pub fn as_str(&self) -> &'static str {
272        match self {
273            Self::Spot => "SPOT",
274            Self::UsdtFuture => "USDT_FUTURE",
275            Self::CoinFuture => "COIN_FUTURE",
276            Self::Margin => "MARGIN",
277            Self::IsolatedMargin => "ISOLATED_MARGIN",
278        }
279    }
280}
281
282impl std::str::FromStr for UniversalTransferToAccountTypeEnum {
283    type Err = Box<dyn std::error::Error + Send + Sync>;
284
285    fn from_str(s: &str) -> Result<Self, Self::Err> {
286        match s {
287            "SPOT" => Ok(Self::Spot),
288            "USDT_FUTURE" => Ok(Self::UsdtFuture),
289            "COIN_FUTURE" => Ok(Self::CoinFuture),
290            "MARGIN" => Ok(Self::Margin),
291            "ISOLATED_MARGIN" => Ok(Self::IsolatedMargin),
292            other => Err(format!("invalid UniversalTransferToAccountTypeEnum: {}", other).into()),
293        }
294    }
295}
296
297/// Request parameters for the [`futures_transfer_for_sub_account`] operation.
298///
299/// This struct holds all of the inputs you can pass when calling
300/// [`futures_transfer_for_sub_account`](#method.futures_transfer_for_sub_account).
301#[derive(Clone, Debug, Builder, Deserialize)]
302#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
303pub struct FuturesTransferForSubAccountParams {
304    ///
305    /// The `email` parameter.
306    ///
307    /// This field is **required.
308    #[builder(setter(into))]
309    #[serde(rename = "email")]
310    pub email: String,
311    /// The asset being transferred
312    ///
313    /// This field is **required.
314    #[builder(setter(into))]
315    #[serde(rename = "asset")]
316    pub asset: String,
317    /// The amount to be transferred
318    ///
319    /// This field is **required.
320    #[builder(setter(into))]
321    #[serde(rename = "amount")]
322    pub amount: rust_decimal::Decimal,
323    /// 1: transfer from subaccount's spot account to its USDT-margined futures account 2: transfer from
324    /// subaccount's USDT-margined futures account to its spot account 3: transfer from subaccount's spot
325    /// account to its COIN-margined futures account 4:transfer from subaccount's COIN-margined futures
326    /// account to its spot account
327    ///
328    /// This field is **required.
329    #[builder(setter(into))]
330    #[serde(rename = "type")]
331    pub r#type: i64,
332    ///
333    /// The `recv_window` parameter.
334    ///
335    /// This field is **optional.
336    #[builder(setter(into), default)]
337    #[serde(rename = "recvWindow", default)]
338    pub recv_window: Option<i64>,
339}
340
341impl FuturesTransferForSubAccountParams {
342    /// Create a builder for [`futures_transfer_for_sub_account`].
343    ///
344    /// Required parameters:
345    ///
346    /// * `email` — String
347    /// * `asset` — The asset being transferred
348    /// * `amount` — The amount to be transferred
349    /// * `r#type` — 1: transfer from subaccount's spot account to its USDT-margined futures account 2: transfer from subaccount's USDT-margined futures account to its spot account 3: transfer from subaccount's spot account to its COIN-margined futures account 4:transfer from subaccount's COIN-margined futures account to its spot account
350    ///
351    #[must_use]
352    pub fn builder(
353        email: String,
354        asset: String,
355        amount: rust_decimal::Decimal,
356        r#type: i64,
357    ) -> FuturesTransferForSubAccountParamsBuilder {
358        FuturesTransferForSubAccountParamsBuilder::default()
359            .email(email)
360            .asset(asset)
361            .amount(amount)
362            .r#type(r#type)
363    }
364}
365/// Request parameters for the [`get_detail_on_sub_accounts_futures_account`] operation.
366///
367/// This struct holds all of the inputs you can pass when calling
368/// [`get_detail_on_sub_accounts_futures_account`](#method.get_detail_on_sub_accounts_futures_account).
369#[derive(Clone, Debug, Builder, Deserialize)]
370#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
371pub struct GetDetailOnSubAccountsFuturesAccountParams {
372    ///
373    /// The `email` parameter.
374    ///
375    /// This field is **required.
376    #[builder(setter(into))]
377    #[serde(rename = "email")]
378    pub email: String,
379    ///
380    /// The `recv_window` parameter.
381    ///
382    /// This field is **optional.
383    #[builder(setter(into), default)]
384    #[serde(rename = "recvWindow", default)]
385    pub recv_window: Option<i64>,
386}
387
388impl GetDetailOnSubAccountsFuturesAccountParams {
389    /// Create a builder for [`get_detail_on_sub_accounts_futures_account`].
390    ///
391    /// Required parameters:
392    ///
393    /// * `email` — String
394    ///
395    #[must_use]
396    pub fn builder(email: String) -> GetDetailOnSubAccountsFuturesAccountParamsBuilder {
397        GetDetailOnSubAccountsFuturesAccountParamsBuilder::default().email(email)
398    }
399}
400/// Request parameters for the [`get_detail_on_sub_accounts_futures_account_v2`] operation.
401///
402/// This struct holds all of the inputs you can pass when calling
403/// [`get_detail_on_sub_accounts_futures_account_v2`](#method.get_detail_on_sub_accounts_futures_account_v2).
404#[derive(Clone, Debug, Builder, Deserialize)]
405#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
406pub struct GetDetailOnSubAccountsFuturesAccountV2Params {
407    ///
408    /// The `email` parameter.
409    ///
410    /// This field is **required.
411    #[builder(setter(into))]
412    #[serde(rename = "email")]
413    pub email: String,
414    /// 1:USDT-margined Futures,2: Coin-margined Futures
415    ///
416    /// This field is **required.
417    #[builder(setter(into))]
418    #[serde(rename = "futuresType")]
419    pub futures_type: i64,
420    ///
421    /// The `recv_window` parameter.
422    ///
423    /// This field is **optional.
424    #[builder(setter(into), default)]
425    #[serde(rename = "recvWindow", default)]
426    pub recv_window: Option<i64>,
427}
428
429impl GetDetailOnSubAccountsFuturesAccountV2Params {
430    /// Create a builder for [`get_detail_on_sub_accounts_futures_account_v2`].
431    ///
432    /// Required parameters:
433    ///
434    /// * `email` — String
435    /// * `futures_type` — 1:USDT-margined Futures,2: Coin-margined Futures
436    ///
437    #[must_use]
438    pub fn builder(
439        email: String,
440        futures_type: i64,
441    ) -> GetDetailOnSubAccountsFuturesAccountV2ParamsBuilder {
442        GetDetailOnSubAccountsFuturesAccountV2ParamsBuilder::default()
443            .email(email)
444            .futures_type(futures_type)
445    }
446}
447/// Request parameters for the [`get_detail_on_sub_accounts_margin_account`] operation.
448///
449/// This struct holds all of the inputs you can pass when calling
450/// [`get_detail_on_sub_accounts_margin_account`](#method.get_detail_on_sub_accounts_margin_account).
451#[derive(Clone, Debug, Builder, Deserialize)]
452#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
453pub struct GetDetailOnSubAccountsMarginAccountParams {
454    ///
455    /// The `email` parameter.
456    ///
457    /// This field is **required.
458    #[builder(setter(into))]
459    #[serde(rename = "email")]
460    pub email: String,
461    ///
462    /// The `recv_window` parameter.
463    ///
464    /// This field is **optional.
465    #[builder(setter(into), default)]
466    #[serde(rename = "recvWindow", default)]
467    pub recv_window: Option<i64>,
468}
469
470impl GetDetailOnSubAccountsMarginAccountParams {
471    /// Create a builder for [`get_detail_on_sub_accounts_margin_account`].
472    ///
473    /// Required parameters:
474    ///
475    /// * `email` — String
476    ///
477    #[must_use]
478    pub fn builder(email: String) -> GetDetailOnSubAccountsMarginAccountParamsBuilder {
479        GetDetailOnSubAccountsMarginAccountParamsBuilder::default().email(email)
480    }
481}
482/// Request parameters for the [`get_move_position_history_for_sub_account`] operation.
483///
484/// This struct holds all of the inputs you can pass when calling
485/// [`get_move_position_history_for_sub_account`](#method.get_move_position_history_for_sub_account).
486#[derive(Clone, Debug, Builder, Deserialize)]
487#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
488pub struct GetMovePositionHistoryForSubAccountParams {
489    ///
490    /// The `symbol` parameter.
491    ///
492    /// This field is **required.
493    #[builder(setter(into))]
494    #[serde(rename = "symbol")]
495    pub symbol: String,
496    ///
497    /// The `page` parameter.
498    ///
499    /// This field is **required.
500    #[builder(setter(into))]
501    #[serde(rename = "page")]
502    pub page: i64,
503    /// Max 100.
504    ///
505    /// This field is **required.
506    #[builder(setter(into))]
507    #[serde(rename = "rows")]
508    pub rows: i64,
509    /// Default UM.
510    ///
511    /// This field is **optional.
512    #[builder(setter(into), default)]
513    #[serde(rename = "productType", default)]
514    pub product_type: Option<GetMovePositionHistoryForSubAccountProductTypeEnum>,
515    ///
516    /// The `start_time` parameter.
517    ///
518    /// This field is **optional.
519    #[builder(setter(into), default)]
520    #[serde(rename = "startTime", default)]
521    pub start_time: Option<i64>,
522    ///
523    /// The `end_time` parameter.
524    ///
525    /// This field is **optional.
526    #[builder(setter(into), default)]
527    #[serde(rename = "endTime", default)]
528    pub end_time: Option<i64>,
529    ///
530    /// The `recv_window` parameter.
531    ///
532    /// This field is **optional.
533    #[builder(setter(into), default)]
534    #[serde(rename = "recvWindow", default)]
535    pub recv_window: Option<i64>,
536}
537
538impl GetMovePositionHistoryForSubAccountParams {
539    /// Create a builder for [`get_move_position_history_for_sub_account`].
540    ///
541    /// Required parameters:
542    ///
543    /// * `symbol` — String
544    /// * `page` — i64
545    /// * `rows` — Max 100.
546    ///
547    #[must_use]
548    pub fn builder(
549        symbol: String,
550        page: i64,
551        rows: i64,
552    ) -> GetMovePositionHistoryForSubAccountParamsBuilder {
553        GetMovePositionHistoryForSubAccountParamsBuilder::default()
554            .symbol(symbol)
555            .page(page)
556            .rows(rows)
557    }
558}
559/// Request parameters for the [`get_sub_account_deposit_address`] operation.
560///
561/// This struct holds all of the inputs you can pass when calling
562/// [`get_sub_account_deposit_address`](#method.get_sub_account_deposit_address).
563#[derive(Clone, Debug, Builder, Deserialize)]
564#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
565pub struct GetSubAccountDepositAddressParams {
566    ///
567    /// The `email` parameter.
568    ///
569    /// This field is **required.
570    #[builder(setter(into))]
571    #[serde(rename = "email")]
572    pub email: String,
573    ///
574    /// The `coin` parameter.
575    ///
576    /// This field is **required.
577    #[builder(setter(into))]
578    #[serde(rename = "coin")]
579    pub coin: String,
580    /// networks can be found in `GET /sapi/v1/capital/deposit/address`
581    ///
582    /// This field is **optional.
583    #[builder(setter(into), default)]
584    #[serde(rename = "network", default)]
585    pub network: Option<String>,
586    ///
587    /// The `amount` parameter.
588    ///
589    /// This field is **optional.
590    #[builder(setter(into), default)]
591    #[serde(rename = "amount", default)]
592    pub amount: Option<rust_decimal::Decimal>,
593    ///
594    /// The `recv_window` parameter.
595    ///
596    /// This field is **optional.
597    #[builder(setter(into), default)]
598    #[serde(rename = "recvWindow", default)]
599    pub recv_window: Option<i64>,
600}
601
602impl GetSubAccountDepositAddressParams {
603    /// Create a builder for [`get_sub_account_deposit_address`].
604    ///
605    /// Required parameters:
606    ///
607    /// * `email` — String
608    /// * `coin` — String
609    ///
610    #[must_use]
611    pub fn builder(email: String, coin: String) -> GetSubAccountDepositAddressParamsBuilder {
612        GetSubAccountDepositAddressParamsBuilder::default()
613            .email(email)
614            .coin(coin)
615    }
616}
617/// Request parameters for the [`get_sub_account_deposit_history`] operation.
618///
619/// This struct holds all of the inputs you can pass when calling
620/// [`get_sub_account_deposit_history`](#method.get_sub_account_deposit_history).
621#[derive(Clone, Debug, Builder, Deserialize)]
622#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
623pub struct GetSubAccountDepositHistoryParams {
624    ///
625    /// The `email` parameter.
626    ///
627    /// This field is **required.
628    #[builder(setter(into))]
629    #[serde(rename = "email")]
630    pub email: String,
631    /// Default `false`, return `sourceAddress` field when set to `true`
632    ///
633    /// This field is **optional.
634    #[builder(setter(into), default)]
635    #[serde(rename = "includeSource", default)]
636    pub include_source: Option<bool>,
637    ///
638    /// The `coin` parameter.
639    ///
640    /// This field is **optional.
641    #[builder(setter(into), default)]
642    #[serde(rename = "coin", default)]
643    pub coin: Option<String>,
644    /// Deposit status: 0=pending, 6=credited but cannot withdraw, 7=wrong deposit, 8=waiting user confirmation, 1=success.
645    ///
646    /// This field is **optional.
647    #[builder(setter(into), default)]
648    #[serde(rename = "status", default)]
649    pub status: Option<i64>,
650    ///
651    /// The `start_time` parameter.
652    ///
653    /// This field is **optional.
654    #[builder(setter(into), default)]
655    #[serde(rename = "startTime", default)]
656    pub start_time: Option<i64>,
657    ///
658    /// The `end_time` parameter.
659    ///
660    /// This field is **optional.
661    #[builder(setter(into), default)]
662    #[serde(rename = "endTime", default)]
663    pub end_time: Option<i64>,
664    ///
665    /// The `limit` parameter.
666    ///
667    /// This field is **optional.
668    #[builder(setter(into), default)]
669    #[serde(rename = "limit", default)]
670    pub limit: Option<i64>,
671    ///
672    /// The `offset` parameter.
673    ///
674    /// This field is **optional.
675    #[builder(setter(into), default)]
676    #[serde(rename = "offset", default)]
677    pub offset: Option<i64>,
678    ///
679    /// The `recv_window` parameter.
680    ///
681    /// This field is **optional.
682    #[builder(setter(into), default)]
683    #[serde(rename = "recvWindow", default)]
684    pub recv_window: Option<i64>,
685    ///
686    /// The `tx_id` parameter.
687    ///
688    /// This field is **optional.
689    #[builder(setter(into), default)]
690    #[serde(rename = "txId", default)]
691    pub tx_id: Option<String>,
692}
693
694impl GetSubAccountDepositHistoryParams {
695    /// Create a builder for [`get_sub_account_deposit_history`].
696    ///
697    /// Required parameters:
698    ///
699    /// * `email` — String
700    ///
701    #[must_use]
702    pub fn builder(email: String) -> GetSubAccountDepositHistoryParamsBuilder {
703        GetSubAccountDepositHistoryParamsBuilder::default().email(email)
704    }
705}
706/// Request parameters for the [`get_summary_of_sub_accounts_futures_account`] operation.
707///
708/// This struct holds all of the inputs you can pass when calling
709/// [`get_summary_of_sub_accounts_futures_account`](#method.get_summary_of_sub_accounts_futures_account).
710#[derive(Clone, Debug, Builder, Deserialize)]
711#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
712pub struct GetSummaryOfSubAccountsFuturesAccountParams {
713    ///
714    /// The `page` parameter.
715    ///
716    /// This field is **required.
717    #[builder(setter(into))]
718    #[serde(rename = "page")]
719    pub page: i64,
720    ///
721    /// The `limit` parameter.
722    ///
723    /// This field is **required.
724    #[builder(setter(into))]
725    #[serde(rename = "limit")]
726    pub limit: i64,
727    ///
728    /// The `recv_window` parameter.
729    ///
730    /// This field is **optional.
731    #[builder(setter(into), default)]
732    #[serde(rename = "recvWindow", default)]
733    pub recv_window: Option<i64>,
734}
735
736impl GetSummaryOfSubAccountsFuturesAccountParams {
737    /// Create a builder for [`get_summary_of_sub_accounts_futures_account`].
738    ///
739    /// Required parameters:
740    ///
741    /// * `page` — i64
742    /// * `limit` — i64
743    ///
744    #[must_use]
745    pub fn builder(page: i64, limit: i64) -> GetSummaryOfSubAccountsFuturesAccountParamsBuilder {
746        GetSummaryOfSubAccountsFuturesAccountParamsBuilder::default()
747            .page(page)
748            .limit(limit)
749    }
750}
751/// Request parameters for the [`get_summary_of_sub_accounts_futures_account_v2`] operation.
752///
753/// This struct holds all of the inputs you can pass when calling
754/// [`get_summary_of_sub_accounts_futures_account_v2`](#method.get_summary_of_sub_accounts_futures_account_v2).
755#[derive(Clone, Debug, Builder, Deserialize)]
756#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
757pub struct GetSummaryOfSubAccountsFuturesAccountV2Params {
758    /// 1:USDT-margined Futures,2: Coin-margined Futures
759    ///
760    /// This field is **required.
761    #[builder(setter(into))]
762    #[serde(rename = "futuresType")]
763    pub futures_type: i64,
764    ///
765    /// The `page` parameter.
766    ///
767    /// This field is **optional.
768    #[builder(setter(into), default)]
769    #[serde(rename = "page", default)]
770    pub page: Option<i64>,
771    ///
772    /// The `limit` parameter.
773    ///
774    /// This field is **optional.
775    #[builder(setter(into), default)]
776    #[serde(rename = "limit", default)]
777    pub limit: Option<i64>,
778    ///
779    /// The `recv_window` parameter.
780    ///
781    /// This field is **optional.
782    #[builder(setter(into), default)]
783    #[serde(rename = "recvWindow", default)]
784    pub recv_window: Option<i64>,
785}
786
787impl GetSummaryOfSubAccountsFuturesAccountV2Params {
788    /// Create a builder for [`get_summary_of_sub_accounts_futures_account_v2`].
789    ///
790    /// Required parameters:
791    ///
792    /// * `futures_type` — 1:USDT-margined Futures,2: Coin-margined Futures
793    ///
794    #[must_use]
795    pub fn builder(futures_type: i64) -> GetSummaryOfSubAccountsFuturesAccountV2ParamsBuilder {
796        GetSummaryOfSubAccountsFuturesAccountV2ParamsBuilder::default().futures_type(futures_type)
797    }
798}
799/// Request parameters for the [`get_summary_of_sub_accounts_margin_account`] operation.
800///
801/// This struct holds all of the inputs you can pass when calling
802/// [`get_summary_of_sub_accounts_margin_account`](#method.get_summary_of_sub_accounts_margin_account).
803#[derive(Clone, Debug, Builder, Deserialize, Default)]
804#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
805pub struct GetSummaryOfSubAccountsMarginAccountParams {
806    ///
807    /// The `recv_window` parameter.
808    ///
809    /// This field is **optional.
810    #[builder(setter(into), default)]
811    #[serde(rename = "recvWindow", default)]
812    pub recv_window: Option<i64>,
813}
814
815impl GetSummaryOfSubAccountsMarginAccountParams {
816    /// Create a builder for [`get_summary_of_sub_accounts_margin_account`].
817    ///
818    #[must_use]
819    pub fn builder() -> GetSummaryOfSubAccountsMarginAccountParamsBuilder {
820        GetSummaryOfSubAccountsMarginAccountParamsBuilder::default()
821    }
822}
823/// Request parameters for the [`margin_transfer_for_sub_account`] operation.
824///
825/// This struct holds all of the inputs you can pass when calling
826/// [`margin_transfer_for_sub_account`](#method.margin_transfer_for_sub_account).
827#[derive(Clone, Debug, Builder, Deserialize)]
828#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
829pub struct MarginTransferForSubAccountParams {
830    ///
831    /// The `email` parameter.
832    ///
833    /// This field is **required.
834    #[builder(setter(into))]
835    #[serde(rename = "email")]
836    pub email: String,
837    /// The asset being transferred
838    ///
839    /// This field is **required.
840    #[builder(setter(into))]
841    #[serde(rename = "asset")]
842    pub asset: String,
843    /// The amount to be transferred
844    ///
845    /// This field is **required.
846    #[builder(setter(into))]
847    #[serde(rename = "amount")]
848    pub amount: rust_decimal::Decimal,
849    /// 1: transfer from subaccount's spot account to margin account 2: transfer from subaccount's margin
850    /// account to its spot account
851    ///
852    /// This field is **required.
853    #[builder(setter(into))]
854    #[serde(rename = "type")]
855    pub r#type: i64,
856    ///
857    /// The `recv_window` parameter.
858    ///
859    /// This field is **optional.
860    #[builder(setter(into), default)]
861    #[serde(rename = "recvWindow", default)]
862    pub recv_window: Option<i64>,
863}
864
865impl MarginTransferForSubAccountParams {
866    /// Create a builder for [`margin_transfer_for_sub_account`].
867    ///
868    /// Required parameters:
869    ///
870    /// * `email` — String
871    /// * `asset` — The asset being transferred
872    /// * `amount` — The amount to be transferred
873    /// * `r#type` — 1: transfer from subaccount's spot account to margin account 2: transfer from subaccount's margin account to its spot account
874    ///
875    #[must_use]
876    pub fn builder(
877        email: String,
878        asset: String,
879        amount: rust_decimal::Decimal,
880        r#type: i64,
881    ) -> MarginTransferForSubAccountParamsBuilder {
882        MarginTransferForSubAccountParamsBuilder::default()
883            .email(email)
884            .asset(asset)
885            .amount(amount)
886            .r#type(r#type)
887    }
888}
889/// Request parameters for the [`move_position_for_sub_account`] operation.
890///
891/// This struct holds all of the inputs you can pass when calling
892/// [`move_position_for_sub_account`](#method.move_position_for_sub_account).
893#[derive(Clone, Debug, Builder, Deserialize)]
894#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
895pub struct MovePositionForSubAccountParams {
896    ///
897    /// The `from_user_email` parameter.
898    ///
899    /// This field is **required.
900    #[builder(setter(into))]
901    #[serde(rename = "fromUserEmail")]
902    pub from_user_email: String,
903    ///
904    /// The `to_user_email` parameter.
905    ///
906    /// This field is **required.
907    #[builder(setter(into))]
908    #[serde(rename = "toUserEmail")]
909    pub to_user_email: String,
910    /// A single request cannot mix UM and OPTION positions.
911    ///
912    /// This field is **required.
913    #[builder(setter(into))]
914    #[serde(rename = "productType")]
915    pub product_type: MovePositionForSubAccountProductTypeEnum,
916    /// Max 10 positions supported. When input request parameter,orderArgs.symbol should be STRING,
917    /// orderArgs.quantity should be BIGDECIMAL, and orderArgs.positionSide should be STRING, positionSide
918    /// support BOTH,LONG and SHORT. Each entry should be like
919    /// orderArgs[0].symbol=BTCUSDT,orderArgs[0].quantity=0.001,orderArgs[0].positionSide=BOTH. Example of
920    /// the request parameter array: orderArgs[0].symbol=BTCUSDT orderArgs[0].quantity=0.001
921    /// orderArgs[0].positionSide=BOTH orderArgs[1].symbol=ETHUSDT orderArgs[1].quantity=0.01
922    /// orderArgs[1].positionSide=BOTH
923    ///
924    /// This field is **required.
925    #[builder(setter(into))]
926    #[serde(rename = "orderArgs")]
927    pub order_args: Vec<models::MovePositionForSubAccountOrderArgsParameterInner>,
928    ///
929    /// The `recv_window` parameter.
930    ///
931    /// This field is **optional.
932    #[builder(setter(into), default)]
933    #[serde(rename = "recvWindow", default)]
934    pub recv_window: Option<i64>,
935}
936
937impl MovePositionForSubAccountParams {
938    /// Create a builder for [`move_position_for_sub_account`].
939    ///
940    /// Required parameters:
941    ///
942    /// * `from_user_email` — String
943    /// * `to_user_email` — String
944    /// * `product_type` — A single request cannot mix UM and OPTION positions.
945    /// * `order_args` — Max 10 positions supported. When input request parameter,orderArgs.symbol should be STRING, orderArgs.quantity should be BIGDECIMAL, and orderArgs.positionSide should be STRING, positionSide support BOTH,LONG and SHORT. Each entry should be like orderArgs[0].symbol=BTCUSDT,orderArgs[0].quantity=0.001,orderArgs[0].positionSide=BOTH. Example of the request parameter array: orderArgs[0].symbol=BTCUSDT orderArgs[0].quantity=0.001 orderArgs[0].positionSide=BOTH orderArgs[1].symbol=ETHUSDT orderArgs[1].quantity=0.01 orderArgs[1].positionSide=BOTH
946    ///
947    #[must_use]
948    pub fn builder(
949        from_user_email: String,
950        to_user_email: String,
951        product_type: MovePositionForSubAccountProductTypeEnum,
952        order_args: Vec<models::MovePositionForSubAccountOrderArgsParameterInner>,
953    ) -> MovePositionForSubAccountParamsBuilder {
954        MovePositionForSubAccountParamsBuilder::default()
955            .from_user_email(from_user_email)
956            .to_user_email(to_user_email)
957            .product_type(product_type)
958            .order_args(order_args)
959    }
960}
961/// Request parameters for the [`query_sub_account_assets`] operation.
962///
963/// This struct holds all of the inputs you can pass when calling
964/// [`query_sub_account_assets`](#method.query_sub_account_assets).
965#[derive(Clone, Debug, Builder, Deserialize)]
966#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
967pub struct QuerySubAccountAssetsParams {
968    ///
969    /// The `email` parameter.
970    ///
971    /// This field is **required.
972    #[builder(setter(into))]
973    #[serde(rename = "email")]
974    pub email: String,
975    ///
976    /// The `recv_window` parameter.
977    ///
978    /// This field is **optional.
979    #[builder(setter(into), default)]
980    #[serde(rename = "recvWindow", default)]
981    pub recv_window: Option<i64>,
982}
983
984impl QuerySubAccountAssetsParams {
985    /// Create a builder for [`query_sub_account_assets`].
986    ///
987    /// Required parameters:
988    ///
989    /// * `email` — String
990    ///
991    #[must_use]
992    pub fn builder(email: String) -> QuerySubAccountAssetsParamsBuilder {
993        QuerySubAccountAssetsParamsBuilder::default().email(email)
994    }
995}
996/// Request parameters for the [`query_sub_account_assets_asset_management`] operation.
997///
998/// This struct holds all of the inputs you can pass when calling
999/// [`query_sub_account_assets_asset_management`](#method.query_sub_account_assets_asset_management).
1000#[derive(Clone, Debug, Builder, Deserialize)]
1001#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1002pub struct QuerySubAccountAssetsAssetManagementParams {
1003    ///
1004    /// The `email` parameter.
1005    ///
1006    /// This field is **required.
1007    #[builder(setter(into))]
1008    #[serde(rename = "email")]
1009    pub email: String,
1010    ///
1011    /// The `recv_window` parameter.
1012    ///
1013    /// This field is **optional.
1014    #[builder(setter(into), default)]
1015    #[serde(rename = "recvWindow", default)]
1016    pub recv_window: Option<i64>,
1017}
1018
1019impl QuerySubAccountAssetsAssetManagementParams {
1020    /// Create a builder for [`query_sub_account_assets_asset_management`].
1021    ///
1022    /// Required parameters:
1023    ///
1024    /// * `email` — String
1025    ///
1026    #[must_use]
1027    pub fn builder(email: String) -> QuerySubAccountAssetsAssetManagementParamsBuilder {
1028        QuerySubAccountAssetsAssetManagementParamsBuilder::default().email(email)
1029    }
1030}
1031/// Request parameters for the [`query_sub_account_futures_asset_transfer_history`] operation.
1032///
1033/// This struct holds all of the inputs you can pass when calling
1034/// [`query_sub_account_futures_asset_transfer_history`](#method.query_sub_account_futures_asset_transfer_history).
1035#[derive(Clone, Debug, Builder, Deserialize)]
1036#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1037pub struct QuerySubAccountFuturesAssetTransferHistoryParams {
1038    ///
1039    /// The `email` parameter.
1040    ///
1041    /// This field is **required.
1042    #[builder(setter(into))]
1043    #[serde(rename = "email")]
1044    pub email: String,
1045    /// 1:USDT-margined Futures,2: Coin-margined Futures
1046    ///
1047    /// This field is **required.
1048    #[builder(setter(into))]
1049    #[serde(rename = "futuresType")]
1050    pub futures_type: i64,
1051    /// Cannot be earlier than 1 month ago
1052    ///
1053    /// This field is **optional.
1054    #[builder(setter(into), default)]
1055    #[serde(rename = "startTime", default)]
1056    pub start_time: Option<i64>,
1057    ///
1058    /// The `end_time` parameter.
1059    ///
1060    /// This field is **optional.
1061    #[builder(setter(into), default)]
1062    #[serde(rename = "endTime", default)]
1063    pub end_time: Option<i64>,
1064    ///
1065    /// The `page` parameter.
1066    ///
1067    /// This field is **optional.
1068    #[builder(setter(into), default)]
1069    #[serde(rename = "page", default)]
1070    pub page: Option<i64>,
1071    ///
1072    /// The `limit` parameter.
1073    ///
1074    /// This field is **optional.
1075    #[builder(setter(into), default)]
1076    #[serde(rename = "limit", default)]
1077    pub limit: Option<i64>,
1078    ///
1079    /// The `recv_window` parameter.
1080    ///
1081    /// This field is **optional.
1082    #[builder(setter(into), default)]
1083    #[serde(rename = "recvWindow", default)]
1084    pub recv_window: Option<i64>,
1085}
1086
1087impl QuerySubAccountFuturesAssetTransferHistoryParams {
1088    /// Create a builder for [`query_sub_account_futures_asset_transfer_history`].
1089    ///
1090    /// Required parameters:
1091    ///
1092    /// * `email` — String
1093    /// * `futures_type` — 1:USDT-margined Futures,2: Coin-margined Futures
1094    ///
1095    #[must_use]
1096    pub fn builder(
1097        email: String,
1098        futures_type: i64,
1099    ) -> QuerySubAccountFuturesAssetTransferHistoryParamsBuilder {
1100        QuerySubAccountFuturesAssetTransferHistoryParamsBuilder::default()
1101            .email(email)
1102            .futures_type(futures_type)
1103    }
1104}
1105/// Request parameters for the [`query_sub_account_spot_asset_transfer_history`] operation.
1106///
1107/// This struct holds all of the inputs you can pass when calling
1108/// [`query_sub_account_spot_asset_transfer_history`](#method.query_sub_account_spot_asset_transfer_history).
1109#[derive(Clone, Debug, Builder, Deserialize, Default)]
1110#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1111pub struct QuerySubAccountSpotAssetTransferHistoryParams {
1112    ///
1113    /// The `from_email` parameter.
1114    ///
1115    /// This field is **optional.
1116    #[builder(setter(into), default)]
1117    #[serde(rename = "fromEmail", default)]
1118    pub from_email: Option<String>,
1119    ///
1120    /// The `to_email` parameter.
1121    ///
1122    /// This field is **optional.
1123    #[builder(setter(into), default)]
1124    #[serde(rename = "toEmail", default)]
1125    pub to_email: Option<String>,
1126    ///
1127    /// The `start_time` parameter.
1128    ///
1129    /// This field is **optional.
1130    #[builder(setter(into), default)]
1131    #[serde(rename = "startTime", default)]
1132    pub start_time: Option<i64>,
1133    ///
1134    /// The `end_time` parameter.
1135    ///
1136    /// This field is **optional.
1137    #[builder(setter(into), default)]
1138    #[serde(rename = "endTime", default)]
1139    pub end_time: Option<i64>,
1140    ///
1141    /// The `page` parameter.
1142    ///
1143    /// This field is **optional.
1144    #[builder(setter(into), default)]
1145    #[serde(rename = "page", default)]
1146    pub page: Option<i64>,
1147    ///
1148    /// The `limit` parameter.
1149    ///
1150    /// This field is **optional.
1151    #[builder(setter(into), default)]
1152    #[serde(rename = "limit", default)]
1153    pub limit: Option<i64>,
1154    ///
1155    /// The `recv_window` parameter.
1156    ///
1157    /// This field is **optional.
1158    #[builder(setter(into), default)]
1159    #[serde(rename = "recvWindow", default)]
1160    pub recv_window: Option<i64>,
1161}
1162
1163impl QuerySubAccountSpotAssetTransferHistoryParams {
1164    /// Create a builder for [`query_sub_account_spot_asset_transfer_history`].
1165    ///
1166    #[must_use]
1167    pub fn builder() -> QuerySubAccountSpotAssetTransferHistoryParamsBuilder {
1168        QuerySubAccountSpotAssetTransferHistoryParamsBuilder::default()
1169    }
1170}
1171/// Request parameters for the [`query_sub_account_spot_assets_summary`] operation.
1172///
1173/// This struct holds all of the inputs you can pass when calling
1174/// [`query_sub_account_spot_assets_summary`](#method.query_sub_account_spot_assets_summary).
1175#[derive(Clone, Debug, Builder, Deserialize, Default)]
1176#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1177pub struct QuerySubAccountSpotAssetsSummaryParams {
1178    /// Managed sub-account email
1179    ///
1180    /// This field is **optional.
1181    #[builder(setter(into), default)]
1182    #[serde(rename = "email", default)]
1183    pub email: Option<String>,
1184    ///
1185    /// The `page` parameter.
1186    ///
1187    /// This field is **optional.
1188    #[builder(setter(into), default)]
1189    #[serde(rename = "page", default)]
1190    pub page: Option<i64>,
1191    ///
1192    /// The `size` parameter.
1193    ///
1194    /// This field is **optional.
1195    #[builder(setter(into), default)]
1196    #[serde(rename = "size", default)]
1197    pub size: Option<i64>,
1198    ///
1199    /// The `recv_window` parameter.
1200    ///
1201    /// This field is **optional.
1202    #[builder(setter(into), default)]
1203    #[serde(rename = "recvWindow", default)]
1204    pub recv_window: Option<i64>,
1205}
1206
1207impl QuerySubAccountSpotAssetsSummaryParams {
1208    /// Create a builder for [`query_sub_account_spot_assets_summary`].
1209    ///
1210    #[must_use]
1211    pub fn builder() -> QuerySubAccountSpotAssetsSummaryParamsBuilder {
1212        QuerySubAccountSpotAssetsSummaryParamsBuilder::default()
1213    }
1214}
1215/// Request parameters for the [`query_universal_transfer_history`] operation.
1216///
1217/// This struct holds all of the inputs you can pass when calling
1218/// [`query_universal_transfer_history`](#method.query_universal_transfer_history).
1219#[derive(Clone, Debug, Builder, Deserialize, Default)]
1220#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1221pub struct QueryUniversalTransferHistoryParams {
1222    ///
1223    /// The `from_email` parameter.
1224    ///
1225    /// This field is **optional.
1226    #[builder(setter(into), default)]
1227    #[serde(rename = "fromEmail", default)]
1228    pub from_email: Option<String>,
1229    ///
1230    /// The `to_email` parameter.
1231    ///
1232    /// This field is **optional.
1233    #[builder(setter(into), default)]
1234    #[serde(rename = "toEmail", default)]
1235    pub to_email: Option<String>,
1236    ///
1237    /// The `client_tran_id` parameter.
1238    ///
1239    /// This field is **optional.
1240    #[builder(setter(into), default)]
1241    #[serde(rename = "clientTranId", default)]
1242    pub client_tran_id: Option<String>,
1243    ///
1244    /// The `start_time` parameter.
1245    ///
1246    /// This field is **optional.
1247    #[builder(setter(into), default)]
1248    #[serde(rename = "startTime", default)]
1249    pub start_time: Option<i64>,
1250    ///
1251    /// The `end_time` parameter.
1252    ///
1253    /// This field is **optional.
1254    #[builder(setter(into), default)]
1255    #[serde(rename = "endTime", default)]
1256    pub end_time: Option<i64>,
1257    ///
1258    /// The `page` parameter.
1259    ///
1260    /// This field is **optional.
1261    #[builder(setter(into), default)]
1262    #[serde(rename = "page", default)]
1263    pub page: Option<i64>,
1264    ///
1265    /// The `limit` parameter.
1266    ///
1267    /// This field is **optional.
1268    #[builder(setter(into), default)]
1269    #[serde(rename = "limit", default)]
1270    pub limit: Option<i64>,
1271    ///
1272    /// The `recv_window` parameter.
1273    ///
1274    /// This field is **optional.
1275    #[builder(setter(into), default)]
1276    #[serde(rename = "recvWindow", default)]
1277    pub recv_window: Option<i64>,
1278}
1279
1280impl QueryUniversalTransferHistoryParams {
1281    /// Create a builder for [`query_universal_transfer_history`].
1282    ///
1283    #[must_use]
1284    pub fn builder() -> QueryUniversalTransferHistoryParamsBuilder {
1285        QueryUniversalTransferHistoryParamsBuilder::default()
1286    }
1287}
1288/// Request parameters for the [`sub_account_futures_asset_transfer`] operation.
1289///
1290/// This struct holds all of the inputs you can pass when calling
1291/// [`sub_account_futures_asset_transfer`](#method.sub_account_futures_asset_transfer).
1292#[derive(Clone, Debug, Builder, Deserialize)]
1293#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1294pub struct SubAccountFuturesAssetTransferParams {
1295    /// Sender email
1296    ///
1297    /// This field is **required.
1298    #[builder(setter(into))]
1299    #[serde(rename = "fromEmail")]
1300    pub from_email: String,
1301    /// Recipient email
1302    ///
1303    /// This field is **required.
1304    #[builder(setter(into))]
1305    #[serde(rename = "toEmail")]
1306    pub to_email: String,
1307    /// 1:USDT-margined Futures,2: Coin-margined Futures
1308    ///
1309    /// This field is **required.
1310    #[builder(setter(into))]
1311    #[serde(rename = "futuresType")]
1312    pub futures_type: i64,
1313    ///
1314    /// The `asset` parameter.
1315    ///
1316    /// This field is **required.
1317    #[builder(setter(into))]
1318    #[serde(rename = "asset")]
1319    pub asset: String,
1320    ///
1321    /// The `amount` parameter.
1322    ///
1323    /// This field is **required.
1324    #[builder(setter(into))]
1325    #[serde(rename = "amount")]
1326    pub amount: rust_decimal::Decimal,
1327    ///
1328    /// The `recv_window` parameter.
1329    ///
1330    /// This field is **optional.
1331    #[builder(setter(into), default)]
1332    #[serde(rename = "recvWindow", default)]
1333    pub recv_window: Option<i64>,
1334}
1335
1336impl SubAccountFuturesAssetTransferParams {
1337    /// Create a builder for [`sub_account_futures_asset_transfer`].
1338    ///
1339    /// Required parameters:
1340    ///
1341    /// * `from_email` — Sender email
1342    /// * `to_email` — Recipient email
1343    /// * `futures_type` — 1:USDT-margined Futures,2: Coin-margined Futures
1344    /// * `asset` — String
1345    /// * `amount` — `rust_decimal::Decimal`
1346    ///
1347    #[must_use]
1348    pub fn builder(
1349        from_email: String,
1350        to_email: String,
1351        futures_type: i64,
1352        asset: String,
1353        amount: rust_decimal::Decimal,
1354    ) -> SubAccountFuturesAssetTransferParamsBuilder {
1355        SubAccountFuturesAssetTransferParamsBuilder::default()
1356            .from_email(from_email)
1357            .to_email(to_email)
1358            .futures_type(futures_type)
1359            .asset(asset)
1360            .amount(amount)
1361    }
1362}
1363/// Request parameters for the [`sub_account_transfer_history`] operation.
1364///
1365/// This struct holds all of the inputs you can pass when calling
1366/// [`sub_account_transfer_history`](#method.sub_account_transfer_history).
1367#[derive(Clone, Debug, Builder, Deserialize, Default)]
1368#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1369pub struct SubAccountTransferHistoryParams {
1370    /// If not sent, result of all assets will be returned
1371    ///
1372    /// This field is **optional.
1373    #[builder(setter(into), default)]
1374    #[serde(rename = "asset", default)]
1375    pub asset: Option<String>,
1376    /// 1: transfer in, 2: transfer out
1377    ///
1378    /// This field is **optional.
1379    #[builder(setter(into), default)]
1380    #[serde(rename = "type", default)]
1381    pub r#type: Option<i64>,
1382    ///
1383    /// The `start_time` parameter.
1384    ///
1385    /// This field is **optional.
1386    #[builder(setter(into), default)]
1387    #[serde(rename = "startTime", default)]
1388    pub start_time: Option<i64>,
1389    ///
1390    /// The `end_time` parameter.
1391    ///
1392    /// This field is **optional.
1393    #[builder(setter(into), default)]
1394    #[serde(rename = "endTime", default)]
1395    pub end_time: Option<i64>,
1396    ///
1397    /// The `limit` parameter.
1398    ///
1399    /// This field is **optional.
1400    #[builder(setter(into), default)]
1401    #[serde(rename = "limit", default)]
1402    pub limit: Option<i64>,
1403    /// Default `False`, return PROCESS and SUCCESS status history; If `True`,return PROCESS and SUCCESS and FAILURE
1404    /// status history
1405    ///
1406    /// This field is **optional.
1407    #[builder(setter(into), default)]
1408    #[serde(rename = "returnFailHistory", default)]
1409    pub return_fail_history: Option<bool>,
1410    ///
1411    /// The `recv_window` parameter.
1412    ///
1413    /// This field is **optional.
1414    #[builder(setter(into), default)]
1415    #[serde(rename = "recvWindow", default)]
1416    pub recv_window: Option<i64>,
1417}
1418
1419impl SubAccountTransferHistoryParams {
1420    /// Create a builder for [`sub_account_transfer_history`].
1421    ///
1422    #[must_use]
1423    pub fn builder() -> SubAccountTransferHistoryParamsBuilder {
1424        SubAccountTransferHistoryParamsBuilder::default()
1425    }
1426}
1427/// Request parameters for the [`transfer_to_master`] operation.
1428///
1429/// This struct holds all of the inputs you can pass when calling
1430/// [`transfer_to_master`](#method.transfer_to_master).
1431#[derive(Clone, Debug, Builder, Deserialize)]
1432#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1433pub struct TransferToMasterParams {
1434    ///
1435    /// The `asset` parameter.
1436    ///
1437    /// This field is **required.
1438    #[builder(setter(into))]
1439    #[serde(rename = "asset")]
1440    pub asset: String,
1441    ///
1442    /// The `amount` parameter.
1443    ///
1444    /// This field is **required.
1445    #[builder(setter(into))]
1446    #[serde(rename = "amount")]
1447    pub amount: rust_decimal::Decimal,
1448    ///
1449    /// The `recv_window` parameter.
1450    ///
1451    /// This field is **optional.
1452    #[builder(setter(into), default)]
1453    #[serde(rename = "recvWindow", default)]
1454    pub recv_window: Option<i64>,
1455}
1456
1457impl TransferToMasterParams {
1458    /// Create a builder for [`transfer_to_master`].
1459    ///
1460    /// Required parameters:
1461    ///
1462    /// * `asset` — String
1463    /// * `amount` — `rust_decimal::Decimal`
1464    ///
1465    #[must_use]
1466    pub fn builder(asset: String, amount: rust_decimal::Decimal) -> TransferToMasterParamsBuilder {
1467        TransferToMasterParamsBuilder::default()
1468            .asset(asset)
1469            .amount(amount)
1470    }
1471}
1472/// Request parameters for the [`transfer_to_sub_account_of_same_master`] operation.
1473///
1474/// This struct holds all of the inputs you can pass when calling
1475/// [`transfer_to_sub_account_of_same_master`](#method.transfer_to_sub_account_of_same_master).
1476#[derive(Clone, Debug, Builder, Deserialize)]
1477#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1478pub struct TransferToSubAccountOfSameMasterParams {
1479    ///
1480    /// The `to_email` parameter.
1481    ///
1482    /// This field is **required.
1483    #[builder(setter(into))]
1484    #[serde(rename = "toEmail")]
1485    pub to_email: String,
1486    ///
1487    /// The `asset` parameter.
1488    ///
1489    /// This field is **required.
1490    #[builder(setter(into))]
1491    #[serde(rename = "asset")]
1492    pub asset: String,
1493    ///
1494    /// The `amount` parameter.
1495    ///
1496    /// This field is **required.
1497    #[builder(setter(into))]
1498    #[serde(rename = "amount")]
1499    pub amount: rust_decimal::Decimal,
1500    ///
1501    /// The `recv_window` parameter.
1502    ///
1503    /// This field is **optional.
1504    #[builder(setter(into), default)]
1505    #[serde(rename = "recvWindow", default)]
1506    pub recv_window: Option<i64>,
1507}
1508
1509impl TransferToSubAccountOfSameMasterParams {
1510    /// Create a builder for [`transfer_to_sub_account_of_same_master`].
1511    ///
1512    /// Required parameters:
1513    ///
1514    /// * `to_email` — String
1515    /// * `asset` — String
1516    /// * `amount` — `rust_decimal::Decimal`
1517    ///
1518    #[must_use]
1519    pub fn builder(
1520        to_email: String,
1521        asset: String,
1522        amount: rust_decimal::Decimal,
1523    ) -> TransferToSubAccountOfSameMasterParamsBuilder {
1524        TransferToSubAccountOfSameMasterParamsBuilder::default()
1525            .to_email(to_email)
1526            .asset(asset)
1527            .amount(amount)
1528    }
1529}
1530/// Request parameters for the [`universal_transfer`] operation.
1531///
1532/// This struct holds all of the inputs you can pass when calling
1533/// [`universal_transfer`](#method.universal_transfer).
1534#[derive(Clone, Debug, Builder, Deserialize)]
1535#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1536pub struct UniversalTransferParams {
1537    ///
1538    /// The `from_account_type` parameter.
1539    ///
1540    /// This field is **required.
1541    #[builder(setter(into))]
1542    #[serde(rename = "fromAccountType")]
1543    pub from_account_type: UniversalTransferFromAccountTypeEnum,
1544    ///
1545    /// The `to_account_type` parameter.
1546    ///
1547    /// This field is **required.
1548    #[builder(setter(into))]
1549    #[serde(rename = "toAccountType")]
1550    pub to_account_type: UniversalTransferToAccountTypeEnum,
1551    ///
1552    /// The `asset` parameter.
1553    ///
1554    /// This field is **required.
1555    #[builder(setter(into))]
1556    #[serde(rename = "asset")]
1557    pub asset: String,
1558    ///
1559    /// The `amount` parameter.
1560    ///
1561    /// This field is **required.
1562    #[builder(setter(into))]
1563    #[serde(rename = "amount")]
1564    pub amount: rust_decimal::Decimal,
1565    ///
1566    /// The `from_email` parameter.
1567    ///
1568    /// This field is **optional.
1569    #[builder(setter(into), default)]
1570    #[serde(rename = "fromEmail", default)]
1571    pub from_email: Option<String>,
1572    ///
1573    /// The `to_email` parameter.
1574    ///
1575    /// This field is **optional.
1576    #[builder(setter(into), default)]
1577    #[serde(rename = "toEmail", default)]
1578    pub to_email: Option<String>,
1579    /// Must be unique
1580    ///
1581    /// This field is **optional.
1582    #[builder(setter(into), default)]
1583    #[serde(rename = "clientTranId", default)]
1584    pub client_tran_id: Option<String>,
1585    /// Only supported under `ISOLATED_MARGIN` type
1586    ///
1587    /// This field is **optional.
1588    #[builder(setter(into), default)]
1589    #[serde(rename = "symbol", default)]
1590    pub symbol: Option<String>,
1591    ///
1592    /// The `recv_window` parameter.
1593    ///
1594    /// This field is **optional.
1595    #[builder(setter(into), default)]
1596    #[serde(rename = "recvWindow", default)]
1597    pub recv_window: Option<i64>,
1598}
1599
1600impl UniversalTransferParams {
1601    /// Create a builder for [`universal_transfer`].
1602    ///
1603    /// Required parameters:
1604    ///
1605    /// * `from_account_type` — String
1606    /// * `to_account_type` — String
1607    /// * `asset` — String
1608    /// * `amount` — `rust_decimal::Decimal`
1609    ///
1610    #[must_use]
1611    pub fn builder(
1612        from_account_type: UniversalTransferFromAccountTypeEnum,
1613        to_account_type: UniversalTransferToAccountTypeEnum,
1614        asset: String,
1615        amount: rust_decimal::Decimal,
1616    ) -> UniversalTransferParamsBuilder {
1617        UniversalTransferParamsBuilder::default()
1618            .from_account_type(from_account_type)
1619            .to_account_type(to_account_type)
1620            .asset(asset)
1621            .amount(amount)
1622    }
1623}
1624
1625#[async_trait]
1626impl AssetManagementApi for AssetManagementApiClient {
1627    async fn futures_transfer_for_sub_account(
1628        &self,
1629        params: FuturesTransferForSubAccountParams,
1630    ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>> {
1631        let FuturesTransferForSubAccountParams {
1632            email,
1633            asset,
1634            amount,
1635            r#type,
1636            recv_window,
1637        } = params;
1638
1639        let mut query_params = BTreeMap::new();
1640        let body_params = BTreeMap::new();
1641
1642        query_params.insert("email".to_string(), json!(email));
1643
1644        query_params.insert("asset".to_string(), json!(asset));
1645
1646        query_params.insert("amount".to_string(), json!(amount));
1647
1648        query_params.insert("type".to_string(), json!(r#type));
1649
1650        if let Some(rw) = recv_window {
1651            query_params.insert("recvWindow".to_string(), json!(rw));
1652        }
1653
1654        send_request::<models::FuturesTransferForSubAccountResponse>(
1655            &self.configuration,
1656            "/sapi/v1/sub-account/futures/transfer",
1657            reqwest::Method::POST,
1658            query_params,
1659            body_params,
1660            if HAS_TIME_UNIT {
1661                self.configuration.time_unit
1662            } else {
1663                None
1664            },
1665            true,
1666        )
1667        .await
1668    }
1669
1670    async fn get_detail_on_sub_accounts_futures_account(
1671        &self,
1672        params: GetDetailOnSubAccountsFuturesAccountParams,
1673    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>> {
1674        let GetDetailOnSubAccountsFuturesAccountParams { email, recv_window } = params;
1675
1676        let mut query_params = BTreeMap::new();
1677        let body_params = BTreeMap::new();
1678
1679        query_params.insert("email".to_string(), json!(email));
1680
1681        if let Some(rw) = recv_window {
1682            query_params.insert("recvWindow".to_string(), json!(rw));
1683        }
1684
1685        send_request::<models::GetDetailOnSubAccountsFuturesAccountResponse>(
1686            &self.configuration,
1687            "/sapi/v1/sub-account/futures/account",
1688            reqwest::Method::GET,
1689            query_params,
1690            body_params,
1691            if HAS_TIME_UNIT {
1692                self.configuration.time_unit
1693            } else {
1694                None
1695            },
1696            true,
1697        )
1698        .await
1699    }
1700
1701    async fn get_detail_on_sub_accounts_futures_account_v2(
1702        &self,
1703        params: GetDetailOnSubAccountsFuturesAccountV2Params,
1704    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>
1705    {
1706        let GetDetailOnSubAccountsFuturesAccountV2Params {
1707            email,
1708            futures_type,
1709            recv_window,
1710        } = params;
1711
1712        let mut query_params = BTreeMap::new();
1713        let body_params = BTreeMap::new();
1714
1715        query_params.insert("email".to_string(), json!(email));
1716
1717        query_params.insert("futuresType".to_string(), json!(futures_type));
1718
1719        if let Some(rw) = recv_window {
1720            query_params.insert("recvWindow".to_string(), json!(rw));
1721        }
1722
1723        send_request::<models::GetDetailOnSubAccountsFuturesAccountV2Response>(
1724            &self.configuration,
1725            "/sapi/v2/sub-account/futures/account",
1726            reqwest::Method::GET,
1727            query_params,
1728            body_params,
1729            if HAS_TIME_UNIT {
1730                self.configuration.time_unit
1731            } else {
1732                None
1733            },
1734            true,
1735        )
1736        .await
1737    }
1738
1739    async fn get_detail_on_sub_accounts_margin_account(
1740        &self,
1741        params: GetDetailOnSubAccountsMarginAccountParams,
1742    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>> {
1743        let GetDetailOnSubAccountsMarginAccountParams { email, recv_window } = params;
1744
1745        let mut query_params = BTreeMap::new();
1746        let body_params = BTreeMap::new();
1747
1748        query_params.insert("email".to_string(), json!(email));
1749
1750        if let Some(rw) = recv_window {
1751            query_params.insert("recvWindow".to_string(), json!(rw));
1752        }
1753
1754        send_request::<models::GetDetailOnSubAccountsMarginAccountResponse>(
1755            &self.configuration,
1756            "/sapi/v1/sub-account/margin/account",
1757            reqwest::Method::GET,
1758            query_params,
1759            body_params,
1760            if HAS_TIME_UNIT {
1761                self.configuration.time_unit
1762            } else {
1763                None
1764            },
1765            true,
1766        )
1767        .await
1768    }
1769
1770    async fn get_move_position_history_for_sub_account(
1771        &self,
1772        params: GetMovePositionHistoryForSubAccountParams,
1773    ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>> {
1774        let GetMovePositionHistoryForSubAccountParams {
1775            symbol,
1776            page,
1777            rows,
1778            product_type,
1779            start_time,
1780            end_time,
1781            recv_window,
1782        } = params;
1783
1784        let mut query_params = BTreeMap::new();
1785        let body_params = BTreeMap::new();
1786
1787        query_params.insert("symbol".to_string(), json!(symbol));
1788
1789        if let Some(rw) = product_type {
1790            query_params.insert("productType".to_string(), json!(rw));
1791        }
1792
1793        if let Some(rw) = start_time {
1794            query_params.insert("startTime".to_string(), json!(rw));
1795        }
1796
1797        if let Some(rw) = end_time {
1798            query_params.insert("endTime".to_string(), json!(rw));
1799        }
1800
1801        query_params.insert("page".to_string(), json!(page));
1802
1803        query_params.insert("rows".to_string(), json!(rows));
1804
1805        if let Some(rw) = recv_window {
1806            query_params.insert("recvWindow".to_string(), json!(rw));
1807        }
1808
1809        send_request::<models::GetMovePositionHistoryForSubAccountResponse>(
1810            &self.configuration,
1811            "/sapi/v1/sub-account/futures/move-position",
1812            reqwest::Method::GET,
1813            query_params,
1814            body_params,
1815            if HAS_TIME_UNIT {
1816                self.configuration.time_unit
1817            } else {
1818                None
1819            },
1820            true,
1821        )
1822        .await
1823    }
1824
1825    async fn get_sub_account_deposit_address(
1826        &self,
1827        params: GetSubAccountDepositAddressParams,
1828    ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>> {
1829        let GetSubAccountDepositAddressParams {
1830            email,
1831            coin,
1832            network,
1833            amount,
1834            recv_window,
1835        } = params;
1836
1837        let mut query_params = BTreeMap::new();
1838        let body_params = BTreeMap::new();
1839
1840        query_params.insert("email".to_string(), json!(email));
1841
1842        query_params.insert("coin".to_string(), json!(coin));
1843
1844        if let Some(rw) = network {
1845            query_params.insert("network".to_string(), json!(rw));
1846        }
1847
1848        if let Some(rw) = amount {
1849            query_params.insert("amount".to_string(), json!(rw));
1850        }
1851
1852        if let Some(rw) = recv_window {
1853            query_params.insert("recvWindow".to_string(), json!(rw));
1854        }
1855
1856        send_request::<models::GetSubAccountDepositAddressResponse>(
1857            &self.configuration,
1858            "/sapi/v1/capital/deposit/subAddress",
1859            reqwest::Method::GET,
1860            query_params,
1861            body_params,
1862            if HAS_TIME_UNIT {
1863                self.configuration.time_unit
1864            } else {
1865                None
1866            },
1867            true,
1868        )
1869        .await
1870    }
1871
1872    async fn get_sub_account_deposit_history(
1873        &self,
1874        params: GetSubAccountDepositHistoryParams,
1875    ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>
1876    {
1877        let GetSubAccountDepositHistoryParams {
1878            email,
1879            include_source,
1880            coin,
1881            status,
1882            start_time,
1883            end_time,
1884            limit,
1885            offset,
1886            recv_window,
1887            tx_id,
1888        } = params;
1889
1890        let mut query_params = BTreeMap::new();
1891        let body_params = BTreeMap::new();
1892
1893        query_params.insert("email".to_string(), json!(email));
1894
1895        if let Some(rw) = include_source {
1896            query_params.insert("includeSource".to_string(), json!(rw));
1897        }
1898
1899        if let Some(rw) = coin {
1900            query_params.insert("coin".to_string(), json!(rw));
1901        }
1902
1903        if let Some(rw) = status {
1904            query_params.insert("status".to_string(), json!(rw));
1905        }
1906
1907        if let Some(rw) = start_time {
1908            query_params.insert("startTime".to_string(), json!(rw));
1909        }
1910
1911        if let Some(rw) = end_time {
1912            query_params.insert("endTime".to_string(), json!(rw));
1913        }
1914
1915        if let Some(rw) = limit {
1916            query_params.insert("limit".to_string(), json!(rw));
1917        }
1918
1919        if let Some(rw) = offset {
1920            query_params.insert("offset".to_string(), json!(rw));
1921        }
1922
1923        if let Some(rw) = recv_window {
1924            query_params.insert("recvWindow".to_string(), json!(rw));
1925        }
1926
1927        if let Some(rw) = tx_id {
1928            query_params.insert("txId".to_string(), json!(rw));
1929        }
1930
1931        send_request::<Vec<models::GetSubAccountDepositHistoryResponseInner>>(
1932            &self.configuration,
1933            "/sapi/v1/capital/deposit/subHisrec",
1934            reqwest::Method::GET,
1935            query_params,
1936            body_params,
1937            if HAS_TIME_UNIT {
1938                self.configuration.time_unit
1939            } else {
1940                None
1941            },
1942            true,
1943        )
1944        .await
1945    }
1946
1947    async fn get_summary_of_sub_accounts_futures_account(
1948        &self,
1949        params: GetSummaryOfSubAccountsFuturesAccountParams,
1950    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>
1951    {
1952        let GetSummaryOfSubAccountsFuturesAccountParams {
1953            page,
1954            limit,
1955            recv_window,
1956        } = params;
1957
1958        let mut query_params = BTreeMap::new();
1959        let body_params = BTreeMap::new();
1960
1961        query_params.insert("page".to_string(), json!(page));
1962
1963        query_params.insert("limit".to_string(), json!(limit));
1964
1965        if let Some(rw) = recv_window {
1966            query_params.insert("recvWindow".to_string(), json!(rw));
1967        }
1968
1969        send_request::<models::GetSummaryOfSubAccountsFuturesAccountResponse>(
1970            &self.configuration,
1971            "/sapi/v1/sub-account/futures/accountSummary",
1972            reqwest::Method::GET,
1973            query_params,
1974            body_params,
1975            if HAS_TIME_UNIT {
1976                self.configuration.time_unit
1977            } else {
1978                None
1979            },
1980            true,
1981        )
1982        .await
1983    }
1984
1985    async fn get_summary_of_sub_accounts_futures_account_v2(
1986        &self,
1987        params: GetSummaryOfSubAccountsFuturesAccountV2Params,
1988    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>
1989    {
1990        let GetSummaryOfSubAccountsFuturesAccountV2Params {
1991            futures_type,
1992            page,
1993            limit,
1994            recv_window,
1995        } = params;
1996
1997        let mut query_params = BTreeMap::new();
1998        let body_params = BTreeMap::new();
1999
2000        query_params.insert("futuresType".to_string(), json!(futures_type));
2001
2002        if let Some(rw) = page {
2003            query_params.insert("page".to_string(), json!(rw));
2004        }
2005
2006        if let Some(rw) = limit {
2007            query_params.insert("limit".to_string(), json!(rw));
2008        }
2009
2010        if let Some(rw) = recv_window {
2011            query_params.insert("recvWindow".to_string(), json!(rw));
2012        }
2013
2014        send_request::<models::GetSummaryOfSubAccountsFuturesAccountV2Response>(
2015            &self.configuration,
2016            "/sapi/v2/sub-account/futures/accountSummary",
2017            reqwest::Method::GET,
2018            query_params,
2019            body_params,
2020            if HAS_TIME_UNIT {
2021                self.configuration.time_unit
2022            } else {
2023                None
2024            },
2025            true,
2026        )
2027        .await
2028    }
2029
2030    async fn get_summary_of_sub_accounts_margin_account(
2031        &self,
2032        params: GetSummaryOfSubAccountsMarginAccountParams,
2033    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>> {
2034        let GetSummaryOfSubAccountsMarginAccountParams { recv_window } = params;
2035
2036        let mut query_params = BTreeMap::new();
2037        let body_params = BTreeMap::new();
2038
2039        if let Some(rw) = recv_window {
2040            query_params.insert("recvWindow".to_string(), json!(rw));
2041        }
2042
2043        send_request::<models::GetSummaryOfSubAccountsMarginAccountResponse>(
2044            &self.configuration,
2045            "/sapi/v1/sub-account/margin/accountSummary",
2046            reqwest::Method::GET,
2047            query_params,
2048            body_params,
2049            if HAS_TIME_UNIT {
2050                self.configuration.time_unit
2051            } else {
2052                None
2053            },
2054            true,
2055        )
2056        .await
2057    }
2058
2059    async fn margin_transfer_for_sub_account(
2060        &self,
2061        params: MarginTransferForSubAccountParams,
2062    ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>> {
2063        let MarginTransferForSubAccountParams {
2064            email,
2065            asset,
2066            amount,
2067            r#type,
2068            recv_window,
2069        } = params;
2070
2071        let mut query_params = BTreeMap::new();
2072        let body_params = BTreeMap::new();
2073
2074        query_params.insert("email".to_string(), json!(email));
2075
2076        query_params.insert("asset".to_string(), json!(asset));
2077
2078        query_params.insert("amount".to_string(), json!(amount));
2079
2080        query_params.insert("type".to_string(), json!(r#type));
2081
2082        if let Some(rw) = recv_window {
2083            query_params.insert("recvWindow".to_string(), json!(rw));
2084        }
2085
2086        send_request::<models::MarginTransferForSubAccountResponse>(
2087            &self.configuration,
2088            "/sapi/v1/sub-account/margin/transfer",
2089            reqwest::Method::POST,
2090            query_params,
2091            body_params,
2092            if HAS_TIME_UNIT {
2093                self.configuration.time_unit
2094            } else {
2095                None
2096            },
2097            true,
2098        )
2099        .await
2100    }
2101
2102    async fn move_position_for_sub_account(
2103        &self,
2104        params: MovePositionForSubAccountParams,
2105    ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>> {
2106        let MovePositionForSubAccountParams {
2107            from_user_email,
2108            to_user_email,
2109            product_type,
2110            order_args,
2111            recv_window,
2112        } = params;
2113
2114        let mut query_params = BTreeMap::new();
2115        let body_params = BTreeMap::new();
2116
2117        query_params.insert("fromUserEmail".to_string(), json!(from_user_email));
2118
2119        query_params.insert("toUserEmail".to_string(), json!(to_user_email));
2120
2121        query_params.insert("productType".to_string(), json!(product_type));
2122
2123        query_params.insert("orderArgs".to_string(), json!(order_args));
2124
2125        if let Some(rw) = recv_window {
2126            query_params.insert("recvWindow".to_string(), json!(rw));
2127        }
2128
2129        send_request::<models::MovePositionForSubAccountResponse>(
2130            &self.configuration,
2131            "/sapi/v1/sub-account/futures/move-position",
2132            reqwest::Method::POST,
2133            query_params,
2134            body_params,
2135            if HAS_TIME_UNIT {
2136                self.configuration.time_unit
2137            } else {
2138                None
2139            },
2140            true,
2141        )
2142        .await
2143    }
2144
2145    async fn query_sub_account_assets(
2146        &self,
2147        params: QuerySubAccountAssetsParams,
2148    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>> {
2149        let QuerySubAccountAssetsParams { email, recv_window } = params;
2150
2151        let mut query_params = BTreeMap::new();
2152        let body_params = BTreeMap::new();
2153
2154        query_params.insert("email".to_string(), json!(email));
2155
2156        if let Some(rw) = recv_window {
2157            query_params.insert("recvWindow".to_string(), json!(rw));
2158        }
2159
2160        send_request::<models::QuerySubAccountAssetsResponse>(
2161            &self.configuration,
2162            "/sapi/v3/sub-account/assets",
2163            reqwest::Method::GET,
2164            query_params,
2165            body_params,
2166            if HAS_TIME_UNIT {
2167                self.configuration.time_unit
2168            } else {
2169                None
2170            },
2171            true,
2172        )
2173        .await
2174    }
2175
2176    async fn query_sub_account_assets_asset_management(
2177        &self,
2178        params: QuerySubAccountAssetsAssetManagementParams,
2179    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>> {
2180        let QuerySubAccountAssetsAssetManagementParams { email, recv_window } = params;
2181
2182        let mut query_params = BTreeMap::new();
2183        let body_params = BTreeMap::new();
2184
2185        query_params.insert("email".to_string(), json!(email));
2186
2187        if let Some(rw) = recv_window {
2188            query_params.insert("recvWindow".to_string(), json!(rw));
2189        }
2190
2191        send_request::<models::QuerySubAccountAssetsAssetManagementResponse>(
2192            &self.configuration,
2193            "/sapi/v4/sub-account/assets",
2194            reqwest::Method::GET,
2195            query_params,
2196            body_params,
2197            if HAS_TIME_UNIT {
2198                self.configuration.time_unit
2199            } else {
2200                None
2201            },
2202            true,
2203        )
2204        .await
2205    }
2206
2207    async fn query_sub_account_futures_asset_transfer_history(
2208        &self,
2209        params: QuerySubAccountFuturesAssetTransferHistoryParams,
2210    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>>
2211    {
2212        let QuerySubAccountFuturesAssetTransferHistoryParams {
2213            email,
2214            futures_type,
2215            start_time,
2216            end_time,
2217            page,
2218            limit,
2219            recv_window,
2220        } = params;
2221
2222        let mut query_params = BTreeMap::new();
2223        let body_params = BTreeMap::new();
2224
2225        query_params.insert("email".to_string(), json!(email));
2226
2227        query_params.insert("futuresType".to_string(), json!(futures_type));
2228
2229        if let Some(rw) = start_time {
2230            query_params.insert("startTime".to_string(), json!(rw));
2231        }
2232
2233        if let Some(rw) = end_time {
2234            query_params.insert("endTime".to_string(), json!(rw));
2235        }
2236
2237        if let Some(rw) = page {
2238            query_params.insert("page".to_string(), json!(rw));
2239        }
2240
2241        if let Some(rw) = limit {
2242            query_params.insert("limit".to_string(), json!(rw));
2243        }
2244
2245        if let Some(rw) = recv_window {
2246            query_params.insert("recvWindow".to_string(), json!(rw));
2247        }
2248
2249        send_request::<models::QuerySubAccountFuturesAssetTransferHistoryResponse>(
2250            &self.configuration,
2251            "/sapi/v1/sub-account/futures/internalTransfer",
2252            reqwest::Method::GET,
2253            query_params,
2254            body_params,
2255            if HAS_TIME_UNIT {
2256                self.configuration.time_unit
2257            } else {
2258                None
2259            },
2260            true,
2261        )
2262        .await
2263    }
2264
2265    async fn query_sub_account_spot_asset_transfer_history(
2266        &self,
2267        params: QuerySubAccountSpotAssetTransferHistoryParams,
2268    ) -> anyhow::Result<
2269        RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
2270    > {
2271        let QuerySubAccountSpotAssetTransferHistoryParams {
2272            from_email,
2273            to_email,
2274            start_time,
2275            end_time,
2276            page,
2277            limit,
2278            recv_window,
2279        } = params;
2280
2281        let mut query_params = BTreeMap::new();
2282        let body_params = BTreeMap::new();
2283
2284        if let Some(rw) = from_email {
2285            query_params.insert("fromEmail".to_string(), json!(rw));
2286        }
2287
2288        if let Some(rw) = to_email {
2289            query_params.insert("toEmail".to_string(), json!(rw));
2290        }
2291
2292        if let Some(rw) = start_time {
2293            query_params.insert("startTime".to_string(), json!(rw));
2294        }
2295
2296        if let Some(rw) = end_time {
2297            query_params.insert("endTime".to_string(), json!(rw));
2298        }
2299
2300        if let Some(rw) = page {
2301            query_params.insert("page".to_string(), json!(rw));
2302        }
2303
2304        if let Some(rw) = limit {
2305            query_params.insert("limit".to_string(), json!(rw));
2306        }
2307
2308        if let Some(rw) = recv_window {
2309            query_params.insert("recvWindow".to_string(), json!(rw));
2310        }
2311
2312        send_request::<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>(
2313            &self.configuration,
2314            "/sapi/v1/sub-account/sub/transfer/history",
2315            reqwest::Method::GET,
2316            query_params,
2317            body_params,
2318            if HAS_TIME_UNIT {
2319                self.configuration.time_unit
2320            } else {
2321                None
2322            },
2323            true,
2324        )
2325        .await
2326    }
2327
2328    async fn query_sub_account_spot_assets_summary(
2329        &self,
2330        params: QuerySubAccountSpotAssetsSummaryParams,
2331    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>> {
2332        let QuerySubAccountSpotAssetsSummaryParams {
2333            email,
2334            page,
2335            size,
2336            recv_window,
2337        } = params;
2338
2339        let mut query_params = BTreeMap::new();
2340        let body_params = BTreeMap::new();
2341
2342        if let Some(rw) = email {
2343            query_params.insert("email".to_string(), json!(rw));
2344        }
2345
2346        if let Some(rw) = page {
2347            query_params.insert("page".to_string(), json!(rw));
2348        }
2349
2350        if let Some(rw) = size {
2351            query_params.insert("size".to_string(), json!(rw));
2352        }
2353
2354        if let Some(rw) = recv_window {
2355            query_params.insert("recvWindow".to_string(), json!(rw));
2356        }
2357
2358        send_request::<models::QuerySubAccountSpotAssetsSummaryResponse>(
2359            &self.configuration,
2360            "/sapi/v1/sub-account/spotSummary",
2361            reqwest::Method::GET,
2362            query_params,
2363            body_params,
2364            if HAS_TIME_UNIT {
2365                self.configuration.time_unit
2366            } else {
2367                None
2368            },
2369            true,
2370        )
2371        .await
2372    }
2373
2374    async fn query_universal_transfer_history(
2375        &self,
2376        params: QueryUniversalTransferHistoryParams,
2377    ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>> {
2378        let QueryUniversalTransferHistoryParams {
2379            from_email,
2380            to_email,
2381            client_tran_id,
2382            start_time,
2383            end_time,
2384            page,
2385            limit,
2386            recv_window,
2387        } = params;
2388
2389        let mut query_params = BTreeMap::new();
2390        let body_params = BTreeMap::new();
2391
2392        if let Some(rw) = from_email {
2393            query_params.insert("fromEmail".to_string(), json!(rw));
2394        }
2395
2396        if let Some(rw) = to_email {
2397            query_params.insert("toEmail".to_string(), json!(rw));
2398        }
2399
2400        if let Some(rw) = client_tran_id {
2401            query_params.insert("clientTranId".to_string(), json!(rw));
2402        }
2403
2404        if let Some(rw) = start_time {
2405            query_params.insert("startTime".to_string(), json!(rw));
2406        }
2407
2408        if let Some(rw) = end_time {
2409            query_params.insert("endTime".to_string(), json!(rw));
2410        }
2411
2412        if let Some(rw) = page {
2413            query_params.insert("page".to_string(), json!(rw));
2414        }
2415
2416        if let Some(rw) = limit {
2417            query_params.insert("limit".to_string(), json!(rw));
2418        }
2419
2420        if let Some(rw) = recv_window {
2421            query_params.insert("recvWindow".to_string(), json!(rw));
2422        }
2423
2424        send_request::<models::QueryUniversalTransferHistoryResponse>(
2425            &self.configuration,
2426            "/sapi/v1/sub-account/universalTransfer",
2427            reqwest::Method::GET,
2428            query_params,
2429            body_params,
2430            if HAS_TIME_UNIT {
2431                self.configuration.time_unit
2432            } else {
2433                None
2434            },
2435            true,
2436        )
2437        .await
2438    }
2439
2440    async fn sub_account_futures_asset_transfer(
2441        &self,
2442        params: SubAccountFuturesAssetTransferParams,
2443    ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>> {
2444        let SubAccountFuturesAssetTransferParams {
2445            from_email,
2446            to_email,
2447            futures_type,
2448            asset,
2449            amount,
2450            recv_window,
2451        } = params;
2452
2453        let mut query_params = BTreeMap::new();
2454        let body_params = BTreeMap::new();
2455
2456        query_params.insert("fromEmail".to_string(), json!(from_email));
2457
2458        query_params.insert("toEmail".to_string(), json!(to_email));
2459
2460        query_params.insert("futuresType".to_string(), json!(futures_type));
2461
2462        query_params.insert("asset".to_string(), json!(asset));
2463
2464        query_params.insert("amount".to_string(), json!(amount));
2465
2466        if let Some(rw) = recv_window {
2467            query_params.insert("recvWindow".to_string(), json!(rw));
2468        }
2469
2470        send_request::<models::SubAccountFuturesAssetTransferResponse>(
2471            &self.configuration,
2472            "/sapi/v1/sub-account/futures/internalTransfer",
2473            reqwest::Method::POST,
2474            query_params,
2475            body_params,
2476            if HAS_TIME_UNIT {
2477                self.configuration.time_unit
2478            } else {
2479                None
2480            },
2481            true,
2482        )
2483        .await
2484    }
2485
2486    async fn sub_account_transfer_history(
2487        &self,
2488        params: SubAccountTransferHistoryParams,
2489    ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>> {
2490        let SubAccountTransferHistoryParams {
2491            asset,
2492            r#type,
2493            start_time,
2494            end_time,
2495            limit,
2496            return_fail_history,
2497            recv_window,
2498        } = params;
2499
2500        let mut query_params = BTreeMap::new();
2501        let body_params = BTreeMap::new();
2502
2503        if let Some(rw) = asset {
2504            query_params.insert("asset".to_string(), json!(rw));
2505        }
2506
2507        if let Some(rw) = r#type {
2508            query_params.insert("type".to_string(), json!(rw));
2509        }
2510
2511        if let Some(rw) = start_time {
2512            query_params.insert("startTime".to_string(), json!(rw));
2513        }
2514
2515        if let Some(rw) = end_time {
2516            query_params.insert("endTime".to_string(), json!(rw));
2517        }
2518
2519        if let Some(rw) = limit {
2520            query_params.insert("limit".to_string(), json!(rw));
2521        }
2522
2523        if let Some(rw) = return_fail_history {
2524            query_params.insert("returnFailHistory".to_string(), json!(rw));
2525        }
2526
2527        if let Some(rw) = recv_window {
2528            query_params.insert("recvWindow".to_string(), json!(rw));
2529        }
2530
2531        send_request::<Vec<models::SubAccountTransferHistoryResponseInner>>(
2532            &self.configuration,
2533            "/sapi/v1/sub-account/transfer/subUserHistory",
2534            reqwest::Method::GET,
2535            query_params,
2536            body_params,
2537            if HAS_TIME_UNIT {
2538                self.configuration.time_unit
2539            } else {
2540                None
2541            },
2542            true,
2543        )
2544        .await
2545    }
2546
2547    async fn transfer_to_master(
2548        &self,
2549        params: TransferToMasterParams,
2550    ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>> {
2551        let TransferToMasterParams {
2552            asset,
2553            amount,
2554            recv_window,
2555        } = params;
2556
2557        let mut query_params = BTreeMap::new();
2558        let body_params = BTreeMap::new();
2559
2560        query_params.insert("asset".to_string(), json!(asset));
2561
2562        query_params.insert("amount".to_string(), json!(amount));
2563
2564        if let Some(rw) = recv_window {
2565            query_params.insert("recvWindow".to_string(), json!(rw));
2566        }
2567
2568        send_request::<models::TransferToMasterResponse>(
2569            &self.configuration,
2570            "/sapi/v1/sub-account/transfer/subToMaster",
2571            reqwest::Method::POST,
2572            query_params,
2573            body_params,
2574            if HAS_TIME_UNIT {
2575                self.configuration.time_unit
2576            } else {
2577                None
2578            },
2579            true,
2580        )
2581        .await
2582    }
2583
2584    async fn transfer_to_sub_account_of_same_master(
2585        &self,
2586        params: TransferToSubAccountOfSameMasterParams,
2587    ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>> {
2588        let TransferToSubAccountOfSameMasterParams {
2589            to_email,
2590            asset,
2591            amount,
2592            recv_window,
2593        } = params;
2594
2595        let mut query_params = BTreeMap::new();
2596        let body_params = BTreeMap::new();
2597
2598        query_params.insert("toEmail".to_string(), json!(to_email));
2599
2600        query_params.insert("asset".to_string(), json!(asset));
2601
2602        query_params.insert("amount".to_string(), json!(amount));
2603
2604        if let Some(rw) = recv_window {
2605            query_params.insert("recvWindow".to_string(), json!(rw));
2606        }
2607
2608        send_request::<models::TransferToSubAccountOfSameMasterResponse>(
2609            &self.configuration,
2610            "/sapi/v1/sub-account/transfer/subToSub",
2611            reqwest::Method::POST,
2612            query_params,
2613            body_params,
2614            if HAS_TIME_UNIT {
2615                self.configuration.time_unit
2616            } else {
2617                None
2618            },
2619            true,
2620        )
2621        .await
2622    }
2623
2624    async fn universal_transfer(
2625        &self,
2626        params: UniversalTransferParams,
2627    ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>> {
2628        let UniversalTransferParams {
2629            from_account_type,
2630            to_account_type,
2631            asset,
2632            amount,
2633            from_email,
2634            to_email,
2635            client_tran_id,
2636            symbol,
2637            recv_window,
2638        } = params;
2639
2640        let mut query_params = BTreeMap::new();
2641        let body_params = BTreeMap::new();
2642
2643        if let Some(rw) = from_email {
2644            query_params.insert("fromEmail".to_string(), json!(rw));
2645        }
2646
2647        if let Some(rw) = to_email {
2648            query_params.insert("toEmail".to_string(), json!(rw));
2649        }
2650
2651        query_params.insert("fromAccountType".to_string(), json!(from_account_type));
2652
2653        query_params.insert("toAccountType".to_string(), json!(to_account_type));
2654
2655        if let Some(rw) = client_tran_id {
2656            query_params.insert("clientTranId".to_string(), json!(rw));
2657        }
2658
2659        if let Some(rw) = symbol {
2660            query_params.insert("symbol".to_string(), json!(rw));
2661        }
2662
2663        query_params.insert("asset".to_string(), json!(asset));
2664
2665        query_params.insert("amount".to_string(), json!(amount));
2666
2667        if let Some(rw) = recv_window {
2668            query_params.insert("recvWindow".to_string(), json!(rw));
2669        }
2670
2671        send_request::<models::UniversalTransferResponse>(
2672            &self.configuration,
2673            "/sapi/v1/sub-account/universalTransfer",
2674            reqwest::Method::POST,
2675            query_params,
2676            body_params,
2677            if HAS_TIME_UNIT {
2678                self.configuration.time_unit
2679            } else {
2680                None
2681            },
2682            true,
2683        )
2684        .await
2685    }
2686}
2687
2688#[cfg(all(test, feature = "sub_account"))]
2689mod tests {
2690    use super::*;
2691    use crate::TOKIO_SHARED_RT;
2692    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
2693    use async_trait::async_trait;
2694    use std::collections::HashMap;
2695
2696    struct DummyRestApiResponse<T> {
2697        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
2698        status: u16,
2699        headers: HashMap<String, String>,
2700        rate_limits: Option<Vec<RestApiRateLimit>>,
2701    }
2702
2703    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
2704        fn from(dummy: DummyRestApiResponse<T>) -> Self {
2705            Self {
2706                data_fn: dummy.inner,
2707                status: dummy.status,
2708                headers: dummy.headers,
2709                rate_limits: dummy.rate_limits,
2710            }
2711        }
2712    }
2713
2714    struct MockAssetManagementApiClient {
2715        force_error: bool,
2716    }
2717
2718    #[async_trait]
2719    impl AssetManagementApi for MockAssetManagementApiClient {
2720        async fn futures_transfer_for_sub_account(
2721            &self,
2722            _params: FuturesTransferForSubAccountParams,
2723        ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>> {
2724            if self.force_error {
2725                return Err(ConnectorError::ConnectorClientError {
2726                    msg: "ResponseError".to_string(),
2727                    code: None,
2728                }
2729                .into());
2730            }
2731
2732            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
2733                .unwrap_or_else(|_| serde_json::json!({}));
2734            let dummy_response: models::FuturesTransferForSubAccountResponse =
2735                serde_json::from_value(resp_json.clone())
2736                    .expect("should parse into models::FuturesTransferForSubAccountResponse");
2737
2738            let dummy = DummyRestApiResponse {
2739                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2740                status: 200,
2741                headers: HashMap::new(),
2742                rate_limits: None,
2743            };
2744
2745            Ok(dummy.into())
2746        }
2747
2748        async fn get_detail_on_sub_accounts_futures_account(
2749            &self,
2750            _params: GetDetailOnSubAccountsFuturesAccountParams,
2751        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>>
2752        {
2753            if self.force_error {
2754                return Err(ConnectorError::ConnectorClientError {
2755                    msg: "ResponseError".to_string(),
2756                    code: None,
2757                }
2758                .into());
2759            }
2760
2761            let resp_json: Value = serde_json::from_str(r#"{"email":"abc@test.com","asset":"USDT","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610}"#).unwrap_or_else(|_| serde_json::json!({}));
2762            let dummy_response: models::GetDetailOnSubAccountsFuturesAccountResponse =
2763                serde_json::from_value(resp_json.clone()).expect(
2764                    "should parse into models::GetDetailOnSubAccountsFuturesAccountResponse",
2765                );
2766
2767            let dummy = DummyRestApiResponse {
2768                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2769                status: 200,
2770                headers: HashMap::new(),
2771                rate_limits: None,
2772            };
2773
2774            Ok(dummy.into())
2775        }
2776
2777        async fn get_detail_on_sub_accounts_futures_account_v2(
2778            &self,
2779            _params: GetDetailOnSubAccountsFuturesAccountV2Params,
2780        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>
2781        {
2782            if self.force_error {
2783                return Err(ConnectorError::ConnectorClientError {
2784                    msg: "ResponseError".to_string(),
2785                    code: None,
2786                }
2787                .into());
2788            }
2789
2790            let resp_json: Value = serde_json::from_str(r#"{"futureAccountResp":{"email":"abc@test.com","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610},"deliveryAccountResp":{"email":"abc@test.com","assets":[{"asset":"BTC","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"updateTime":1598959682001}}"#).unwrap_or_else(|_| serde_json::json!({}));
2791            let dummy_response: models::GetDetailOnSubAccountsFuturesAccountV2Response =
2792                serde_json::from_value(resp_json.clone()).expect(
2793                    "should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response",
2794                );
2795
2796            let dummy = DummyRestApiResponse {
2797                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2798                status: 200,
2799                headers: HashMap::new(),
2800                rate_limits: None,
2801            };
2802
2803            Ok(dummy.into())
2804        }
2805
2806        async fn get_detail_on_sub_accounts_margin_account(
2807            &self,
2808            _params: GetDetailOnSubAccountsMarginAccountParams,
2809        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>>
2810        {
2811            if self.force_error {
2812                return Err(ConnectorError::ConnectorClientError {
2813                    msg: "ResponseError".to_string(),
2814                    code: None,
2815                }
2816                .into());
2817            }
2818
2819            let resp_json: Value = serde_json::from_str(r#"{"email":"123@test.com","marginLevel":"11.64405625","totalAssetOfBtc":"6.82728457","totalLiabilityOfBtc":"0.58633215","totalNetAssetOfBtc":"6.24095242","marginTradeCoeffVo":{"forceLiquidationBar":"1.10000000","marginCallBar":"1.50000000","normalBar":"2.00000000"},"marginUserAssetVoList":[{"asset":"BTC","borrowed":"0.00000000","free":"0.00499500","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00499500"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2820            let dummy_response: models::GetDetailOnSubAccountsMarginAccountResponse =
2821                serde_json::from_value(resp_json.clone()).expect(
2822                    "should parse into models::GetDetailOnSubAccountsMarginAccountResponse",
2823                );
2824
2825            let dummy = DummyRestApiResponse {
2826                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2827                status: 200,
2828                headers: HashMap::new(),
2829                rate_limits: None,
2830            };
2831
2832            Ok(dummy.into())
2833        }
2834
2835        async fn get_move_position_history_for_sub_account(
2836            &self,
2837            _params: GetMovePositionHistoryForSubAccountParams,
2838        ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>>
2839        {
2840            if self.force_error {
2841                return Err(ConnectorError::ConnectorClientError {
2842                    msg: "ResponseError".to_string(),
2843                    code: None,
2844                }
2845                .into());
2846            }
2847
2848            let resp_json: Value = serde_json::from_str(r#"{"total":3,"futureMovePositionOrderVoList":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","price":"105025.50981609","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1737544712000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2849            let dummy_response: models::GetMovePositionHistoryForSubAccountResponse =
2850                serde_json::from_value(resp_json.clone()).expect(
2851                    "should parse into models::GetMovePositionHistoryForSubAccountResponse",
2852                );
2853
2854            let dummy = DummyRestApiResponse {
2855                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2856                status: 200,
2857                headers: HashMap::new(),
2858                rate_limits: None,
2859            };
2860
2861            Ok(dummy.into())
2862        }
2863
2864        async fn get_sub_account_deposit_address(
2865            &self,
2866            _params: GetSubAccountDepositAddressParams,
2867        ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>> {
2868            if self.force_error {
2869                return Err(ConnectorError::ConnectorClientError {
2870                    msg: "ResponseError".to_string(),
2871                    code: None,
2872                }
2873                .into());
2874            }
2875
2876            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap_or_else(|_| serde_json::json!({}));
2877            let dummy_response: models::GetSubAccountDepositAddressResponse =
2878                serde_json::from_value(resp_json.clone())
2879                    .expect("should parse into models::GetSubAccountDepositAddressResponse");
2880
2881            let dummy = DummyRestApiResponse {
2882                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2883                status: 200,
2884                headers: HashMap::new(),
2885                rate_limits: None,
2886            };
2887
2888            Ok(dummy.into())
2889        }
2890
2891        async fn get_sub_account_deposit_history(
2892            &self,
2893            _params: GetSubAccountDepositHistoryParams,
2894        ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>
2895        {
2896            if self.force_error {
2897                return Err(ConnectorError::ConnectorClientError {
2898                    msg: "ResponseError".to_string(),
2899                    code: None,
2900                }
2901                .into());
2902            }
2903
2904            let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":0,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
2905            let dummy_response: Vec<models::GetSubAccountDepositHistoryResponseInner> =
2906                serde_json::from_value(resp_json.clone()).expect(
2907                    "should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>",
2908                );
2909
2910            let dummy = DummyRestApiResponse {
2911                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2912                status: 200,
2913                headers: HashMap::new(),
2914                rate_limits: None,
2915            };
2916
2917            Ok(dummy.into())
2918        }
2919
2920        async fn get_summary_of_sub_accounts_futures_account(
2921            &self,
2922            _params: GetSummaryOfSubAccountsFuturesAccountParams,
2923        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>
2924        {
2925            if self.force_error {
2926                return Err(ConnectorError::ConnectorClientError {
2927                    msg: "ResponseError".to_string(),
2928                    code: None,
2929                }
2930                .into());
2931            }
2932
2933            let resp_json: Value = serde_json::from_str(r#"{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2934            let dummy_response: models::GetSummaryOfSubAccountsFuturesAccountResponse =
2935                serde_json::from_value(resp_json.clone()).expect(
2936                    "should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse",
2937                );
2938
2939            let dummy = DummyRestApiResponse {
2940                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2941                status: 200,
2942                headers: HashMap::new(),
2943                rate_limits: None,
2944            };
2945
2946            Ok(dummy.into())
2947        }
2948
2949        async fn get_summary_of_sub_accounts_futures_account_v2(
2950            &self,
2951            _params: GetSummaryOfSubAccountsFuturesAccountV2Params,
2952        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>
2953        {
2954            if self.force_error {
2955                return Err(ConnectorError::ConnectorClientError {
2956                    msg: "ResponseError".to_string(),
2957                    code: None,
2958                }
2959                .into());
2960            }
2961
2962            let resp_json: Value = serde_json::from_str(r#"{"futureAccountSummaryResp":{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]},"deliveryAccountSummaryResp":{"totalMarginBalanceOfBTC":"25.03221121","totalUnrealizedProfitOfBTC":"0.12233410","totalWalletBalanceOfBTC":"22.15879444","asset":"BTC","subAccountList":[{"email":"123@test.com","totalMarginBalance":"22.12659734","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"BTC"}]}}"#).unwrap_or_else(|_| serde_json::json!({}));
2963            let dummy_response: models::GetSummaryOfSubAccountsFuturesAccountV2Response =
2964                serde_json::from_value(resp_json.clone()).expect(
2965                    "should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response",
2966                );
2967
2968            let dummy = DummyRestApiResponse {
2969                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2970                status: 200,
2971                headers: HashMap::new(),
2972                rate_limits: None,
2973            };
2974
2975            Ok(dummy.into())
2976        }
2977
2978        async fn get_summary_of_sub_accounts_margin_account(
2979            &self,
2980            _params: GetSummaryOfSubAccountsMarginAccountParams,
2981        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>>
2982        {
2983            if self.force_error {
2984                return Err(ConnectorError::ConnectorClientError {
2985                    msg: "ResponseError".to_string(),
2986                    code: None,
2987                }
2988                .into());
2989            }
2990
2991            let resp_json: Value = serde_json::from_str(r#"{"totalAssetOfBtc":"4.33333333","totalLiabilityOfBtc":"2.11111112","totalNetAssetOfBtc":"2.22222221","subAccountList":[{"email":"123@test.com","totalAssetOfBtc":"2.11111111","totalLiabilityOfBtc":"1.11111111","totalNetAssetOfBtc":"1.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2992            let dummy_response: models::GetSummaryOfSubAccountsMarginAccountResponse =
2993                serde_json::from_value(resp_json.clone()).expect(
2994                    "should parse into models::GetSummaryOfSubAccountsMarginAccountResponse",
2995                );
2996
2997            let dummy = DummyRestApiResponse {
2998                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2999                status: 200,
3000                headers: HashMap::new(),
3001                rate_limits: None,
3002            };
3003
3004            Ok(dummy.into())
3005        }
3006
3007        async fn margin_transfer_for_sub_account(
3008            &self,
3009            _params: MarginTransferForSubAccountParams,
3010        ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>> {
3011            if self.force_error {
3012                return Err(ConnectorError::ConnectorClientError {
3013                    msg: "ResponseError".to_string(),
3014                    code: None,
3015                }
3016                .into());
3017            }
3018
3019            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3020                .unwrap_or_else(|_| serde_json::json!({}));
3021            let dummy_response: models::MarginTransferForSubAccountResponse =
3022                serde_json::from_value(resp_json.clone())
3023                    .expect("should parse into models::MarginTransferForSubAccountResponse");
3024
3025            let dummy = DummyRestApiResponse {
3026                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3027                status: 200,
3028                headers: HashMap::new(),
3029                rate_limits: None,
3030            };
3031
3032            Ok(dummy.into())
3033        }
3034
3035        async fn move_position_for_sub_account(
3036            &self,
3037            _params: MovePositionForSubAccountParams,
3038        ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>> {
3039            if self.force_error {
3040                return Err(ConnectorError::ConnectorClientError {
3041                    msg: "ResponseError".to_string(),
3042                    code: None,
3043                }
3044                .into());
3045            }
3046
3047            let resp_json: Value = serde_json::from_str(r#"{"movePositionOrders":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.001","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3048            let dummy_response: models::MovePositionForSubAccountResponse =
3049                serde_json::from_value(resp_json.clone())
3050                    .expect("should parse into models::MovePositionForSubAccountResponse");
3051
3052            let dummy = DummyRestApiResponse {
3053                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3054                status: 200,
3055                headers: HashMap::new(),
3056                rate_limits: None,
3057            };
3058
3059            Ok(dummy.into())
3060        }
3061
3062        async fn query_sub_account_assets(
3063            &self,
3064            _params: QuerySubAccountAssetsParams,
3065        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>> {
3066            if self.force_error {
3067                return Err(ConnectorError::ConnectorClientError {
3068                    msg: "ResponseError".to_string(),
3069                    code: None,
3070                }
3071                .into());
3072            }
3073
3074            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":11467.6399,"locked":0}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3075            let dummy_response: models::QuerySubAccountAssetsResponse =
3076                serde_json::from_value(resp_json.clone())
3077                    .expect("should parse into models::QuerySubAccountAssetsResponse");
3078
3079            let dummy = DummyRestApiResponse {
3080                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3081                status: 200,
3082                headers: HashMap::new(),
3083                rate_limits: None,
3084            };
3085
3086            Ok(dummy.into())
3087        }
3088
3089        async fn query_sub_account_assets_asset_management(
3090            &self,
3091            _params: QuerySubAccountAssetsAssetManagementParams,
3092        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>>
3093        {
3094            if self.force_error {
3095                return Err(ConnectorError::ConnectorClientError {
3096                    msg: "ResponseError".to_string(),
3097                    code: None,
3098                }
3099                .into());
3100            }
3101
3102            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3103            let dummy_response: models::QuerySubAccountAssetsAssetManagementResponse =
3104                serde_json::from_value(resp_json.clone()).expect(
3105                    "should parse into models::QuerySubAccountAssetsAssetManagementResponse",
3106                );
3107
3108            let dummy = DummyRestApiResponse {
3109                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3110                status: 200,
3111                headers: HashMap::new(),
3112                rate_limits: None,
3113            };
3114
3115            Ok(dummy.into())
3116        }
3117
3118        async fn query_sub_account_futures_asset_transfer_history(
3119            &self,
3120            _params: QuerySubAccountFuturesAssetTransferHistoryParams,
3121        ) -> anyhow::Result<
3122            RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>,
3123        > {
3124            if self.force_error {
3125                return Err(ConnectorError::ConnectorClientError {
3126                    msg: "ResponseError".to_string(),
3127                    code: None,
3128                }
3129                .into());
3130            }
3131
3132            let resp_json: Value = serde_json::from_str(r#"{"success":true,"futuresType":2,"transfers":[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"1","tranId":11897001102,"time":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3133            let dummy_response: models::QuerySubAccountFuturesAssetTransferHistoryResponse =
3134                serde_json::from_value(resp_json.clone()).expect(
3135                    "should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse",
3136                );
3137
3138            let dummy = DummyRestApiResponse {
3139                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3140                status: 200,
3141                headers: HashMap::new(),
3142                rate_limits: None,
3143            };
3144
3145            Ok(dummy.into())
3146        }
3147
3148        async fn query_sub_account_spot_asset_transfer_history(
3149            &self,
3150            _params: QuerySubAccountSpotAssetTransferHistoryParams,
3151        ) -> anyhow::Result<
3152            RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
3153        > {
3154            if self.force_error {
3155                return Err(ConnectorError::ConnectorClientError {
3156                    msg: "ResponseError".to_string(),
3157                    code: None,
3158                }
3159                .into());
3160            }
3161
3162            let resp_json: Value = serde_json::from_str(r#"[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"10","status":"SUCCESS","tranId":6489943656,"time":1544433328000}]"#).unwrap_or_else(|_| serde_json::json!({}));
3163            let dummy_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");
3164
3165            let dummy = DummyRestApiResponse {
3166                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3167                status: 200,
3168                headers: HashMap::new(),
3169                rate_limits: None,
3170            };
3171
3172            Ok(dummy.into())
3173        }
3174
3175        async fn query_sub_account_spot_assets_summary(
3176            &self,
3177            _params: QuerySubAccountSpotAssetsSummaryParams,
3178        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>>
3179        {
3180            if self.force_error {
3181                return Err(ConnectorError::ConnectorClientError {
3182                    msg: "ResponseError".to_string(),
3183                    code: None,
3184                }
3185                .into());
3186            }
3187
3188            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3189            let dummy_response: models::QuerySubAccountSpotAssetsSummaryResponse =
3190                serde_json::from_value(resp_json.clone())
3191                    .expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");
3192
3193            let dummy = DummyRestApiResponse {
3194                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3195                status: 200,
3196                headers: HashMap::new(),
3197                rate_limits: None,
3198            };
3199
3200            Ok(dummy.into())
3201        }
3202
3203        async fn query_universal_transfer_history(
3204            &self,
3205            _params: QueryUniversalTransferHistoryParams,
3206        ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>>
3207        {
3208            if self.force_error {
3209                return Err(ConnectorError::ConnectorClientError {
3210                    msg: "ResponseError".to_string(),
3211                    code: None,
3212                }
3213                .into());
3214            }
3215
3216            let resp_json: Value = serde_json::from_str(r#"{"result":[{"tranId":92275823339,"fromEmail":"abctest@gmail.com","toEmail":"deftest@gmail.com","asset":"BNB","amount":"0.01","createTimeStamp":1640317374000,"fromAccountType":"USDT_FUTURE","toAccountType":"SPOT","status":"SUCCESS","clientTranId":"test"}],"totalCount":1}"#).unwrap_or_else(|_| serde_json::json!({}));
3217            let dummy_response: models::QueryUniversalTransferHistoryResponse =
3218                serde_json::from_value(resp_json.clone())
3219                    .expect("should parse into models::QueryUniversalTransferHistoryResponse");
3220
3221            let dummy = DummyRestApiResponse {
3222                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3223                status: 200,
3224                headers: HashMap::new(),
3225                rate_limits: None,
3226            };
3227
3228            Ok(dummy.into())
3229        }
3230
3231        async fn sub_account_futures_asset_transfer(
3232            &self,
3233            _params: SubAccountFuturesAssetTransferParams,
3234        ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>>
3235        {
3236            if self.force_error {
3237                return Err(ConnectorError::ConnectorClientError {
3238                    msg: "ResponseError".to_string(),
3239                    code: None,
3240                }
3241                .into());
3242            }
3243
3244            let resp_json: Value = serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#)
3245                .unwrap_or_else(|_| serde_json::json!({}));
3246            let dummy_response: models::SubAccountFuturesAssetTransferResponse =
3247                serde_json::from_value(resp_json.clone())
3248                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");
3249
3250            let dummy = DummyRestApiResponse {
3251                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3252                status: 200,
3253                headers: HashMap::new(),
3254                rate_limits: None,
3255            };
3256
3257            Ok(dummy.into())
3258        }
3259
3260        async fn sub_account_transfer_history(
3261            &self,
3262            _params: SubAccountTransferHistoryParams,
3263        ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>>
3264        {
3265            if self.force_error {
3266                return Err(ConnectorError::ConnectorClientError {
3267                    msg: "ResponseError".to_string(),
3268                    code: None,
3269                }
3270                .into());
3271            }
3272
3273            let resp_json: Value = serde_json::from_str(r#"[{"counterParty":"master","email":"master@test.com","type":1,"asset":"BTC","qty":"1","fromAccountType":"SPOT","toAccountType":"SPOT","status":"SUCCESS","tranId":11798835829,"time":1544433325000}]"#).unwrap_or_else(|_| serde_json::json!({}));
3274            let dummy_response: Vec<models::SubAccountTransferHistoryResponseInner> =
3275                serde_json::from_value(resp_json.clone()).expect(
3276                    "should parse into Vec<models::SubAccountTransferHistoryResponseInner>",
3277                );
3278
3279            let dummy = DummyRestApiResponse {
3280                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3281                status: 200,
3282                headers: HashMap::new(),
3283                rate_limits: None,
3284            };
3285
3286            Ok(dummy.into())
3287        }
3288
3289        async fn transfer_to_master(
3290            &self,
3291            _params: TransferToMasterParams,
3292        ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>> {
3293            if self.force_error {
3294                return Err(ConnectorError::ConnectorClientError {
3295                    msg: "ResponseError".to_string(),
3296                    code: None,
3297                }
3298                .into());
3299            }
3300
3301            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3302                .unwrap_or_else(|_| serde_json::json!({}));
3303            let dummy_response: models::TransferToMasterResponse =
3304                serde_json::from_value(resp_json.clone())
3305                    .expect("should parse into models::TransferToMasterResponse");
3306
3307            let dummy = DummyRestApiResponse {
3308                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3309                status: 200,
3310                headers: HashMap::new(),
3311                rate_limits: None,
3312            };
3313
3314            Ok(dummy.into())
3315        }
3316
3317        async fn transfer_to_sub_account_of_same_master(
3318            &self,
3319            _params: TransferToSubAccountOfSameMasterParams,
3320        ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>>
3321        {
3322            if self.force_error {
3323                return Err(ConnectorError::ConnectorClientError {
3324                    msg: "ResponseError".to_string(),
3325                    code: None,
3326                }
3327                .into());
3328            }
3329
3330            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3331                .unwrap_or_else(|_| serde_json::json!({}));
3332            let dummy_response: models::TransferToSubAccountOfSameMasterResponse =
3333                serde_json::from_value(resp_json.clone())
3334                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");
3335
3336            let dummy = DummyRestApiResponse {
3337                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3338                status: 200,
3339                headers: HashMap::new(),
3340                rate_limits: None,
3341            };
3342
3343            Ok(dummy.into())
3344        }
3345
3346        async fn universal_transfer(
3347            &self,
3348            _params: UniversalTransferParams,
3349        ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>> {
3350            if self.force_error {
3351                return Err(ConnectorError::ConnectorClientError {
3352                    msg: "ResponseError".to_string(),
3353                    code: None,
3354                }
3355                .into());
3356            }
3357
3358            let resp_json: Value =
3359                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#)
3360                    .unwrap_or_else(|_| serde_json::json!({}));
3361            let dummy_response: models::UniversalTransferResponse =
3362                serde_json::from_value(resp_json.clone())
3363                    .expect("should parse into models::UniversalTransferResponse");
3364
3365            let dummy = DummyRestApiResponse {
3366                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
3367                status: 200,
3368                headers: HashMap::new(),
3369                rate_limits: None,
3370            };
3371
3372            Ok(dummy.into())
3373        }
3374    }
3375
3376    #[test]
3377    fn futures_transfer_for_sub_account_required_params_success() {
3378        TOKIO_SHARED_RT.block_on(async {
3379            let client = MockAssetManagementApiClient { force_error: false };
3380
3381            let params = FuturesTransferForSubAccountParams::builder(
3382                "123@test.com".to_string(),
3383                "USDT".to_string(),
3384                dec!(1.0),
3385                1,
3386            )
3387            .build()
3388            .unwrap();
3389
3390            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3391                .unwrap_or_else(|_| serde_json::json!({}));
3392            let expected_response: models::FuturesTransferForSubAccountResponse =
3393                serde_json::from_value(resp_json.clone())
3394                    .expect("should parse into models::FuturesTransferForSubAccountResponse");
3395
3396            let resp = client
3397                .futures_transfer_for_sub_account(params)
3398                .await
3399                .expect("Expected a response");
3400            let data_future = resp.data();
3401            let actual_response = data_future.await.unwrap();
3402            assert_eq!(actual_response, expected_response);
3403        });
3404    }
3405
3406    #[test]
3407    fn futures_transfer_for_sub_account_optional_params_success() {
3408        TOKIO_SHARED_RT.block_on(async {
3409            let client = MockAssetManagementApiClient { force_error: false };
3410
3411            let params = FuturesTransferForSubAccountParams::builder(
3412                "123@test.com".to_string(),
3413                "USDT".to_string(),
3414                dec!(1.0),
3415                1,
3416            )
3417            .recv_window(5000)
3418            .build()
3419            .unwrap();
3420
3421            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3422                .unwrap_or_else(|_| serde_json::json!({}));
3423            let expected_response: models::FuturesTransferForSubAccountResponse =
3424                serde_json::from_value(resp_json.clone())
3425                    .expect("should parse into models::FuturesTransferForSubAccountResponse");
3426
3427            let resp = client
3428                .futures_transfer_for_sub_account(params)
3429                .await
3430                .expect("Expected a response");
3431            let data_future = resp.data();
3432            let actual_response = data_future.await.unwrap();
3433            assert_eq!(actual_response, expected_response);
3434        });
3435    }
3436
3437    #[test]
3438    fn futures_transfer_for_sub_account_response_error() {
3439        TOKIO_SHARED_RT.block_on(async {
3440            let client = MockAssetManagementApiClient { force_error: true };
3441
3442            let params = FuturesTransferForSubAccountParams::builder(
3443                "123@test.com".to_string(),
3444                "USDT".to_string(),
3445                dec!(1.0),
3446                1,
3447            )
3448            .build()
3449            .unwrap();
3450
3451            match client.futures_transfer_for_sub_account(params).await {
3452                Ok(_) => panic!("Expected an error"),
3453                Err(err) => {
3454                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3455                }
3456            }
3457        });
3458    }
3459
3460    #[test]
3461    fn get_detail_on_sub_accounts_futures_account_required_params_success() {
3462        TOKIO_SHARED_RT.block_on(async {
3463            let client = MockAssetManagementApiClient { force_error: false };
3464
3465            let params = GetDetailOnSubAccountsFuturesAccountParams::builder("123@test.com".to_string(),).build().unwrap();
3466
3467            let resp_json: Value = serde_json::from_str(r#"{"email":"abc@test.com","asset":"USDT","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610}"#).unwrap_or_else(|_| serde_json::json!({}));
3468            let expected_response : models::GetDetailOnSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountResponse");
3469
3470            let resp = client.get_detail_on_sub_accounts_futures_account(params).await.expect("Expected a response");
3471            let data_future = resp.data();
3472            let actual_response = data_future.await.unwrap();
3473            assert_eq!(actual_response, expected_response);
3474        });
3475    }
3476
3477    #[test]
3478    fn get_detail_on_sub_accounts_futures_account_optional_params_success() {
3479        TOKIO_SHARED_RT.block_on(async {
3480            let client = MockAssetManagementApiClient { force_error: false };
3481
3482            let params = GetDetailOnSubAccountsFuturesAccountParams::builder("123@test.com".to_string(),).recv_window(5000).build().unwrap();
3483
3484            let resp_json: Value = serde_json::from_str(r#"{"email":"abc@test.com","asset":"USDT","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610}"#).unwrap_or_else(|_| serde_json::json!({}));
3485            let expected_response : models::GetDetailOnSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountResponse");
3486
3487            let resp = client.get_detail_on_sub_accounts_futures_account(params).await.expect("Expected a response");
3488            let data_future = resp.data();
3489            let actual_response = data_future.await.unwrap();
3490            assert_eq!(actual_response, expected_response);
3491        });
3492    }
3493
3494    #[test]
3495    fn get_detail_on_sub_accounts_futures_account_response_error() {
3496        TOKIO_SHARED_RT.block_on(async {
3497            let client = MockAssetManagementApiClient { force_error: true };
3498
3499            let params =
3500                GetDetailOnSubAccountsFuturesAccountParams::builder("123@test.com".to_string())
3501                    .build()
3502                    .unwrap();
3503
3504            match client
3505                .get_detail_on_sub_accounts_futures_account(params)
3506                .await
3507            {
3508                Ok(_) => panic!("Expected an error"),
3509                Err(err) => {
3510                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3511                }
3512            }
3513        });
3514    }
3515
3516    #[test]
3517    fn get_detail_on_sub_accounts_futures_account_v2_required_params_success() {
3518        TOKIO_SHARED_RT.block_on(async {
3519            let client = MockAssetManagementApiClient { force_error: false };
3520
3521            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder("123@test.com".to_string(),1,).build().unwrap();
3522
3523            let resp_json: Value = serde_json::from_str(r#"{"futureAccountResp":{"email":"abc@test.com","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610},"deliveryAccountResp":{"email":"abc@test.com","assets":[{"asset":"BTC","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"updateTime":1598959682001}}"#).unwrap_or_else(|_| serde_json::json!({}));
3524            let expected_response : models::GetDetailOnSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response");
3525
3526            let resp = client.get_detail_on_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
3527            let data_future = resp.data();
3528            let actual_response = data_future.await.unwrap();
3529            assert_eq!(actual_response, expected_response);
3530        });
3531    }
3532
3533    #[test]
3534    fn get_detail_on_sub_accounts_futures_account_v2_optional_params_success() {
3535        TOKIO_SHARED_RT.block_on(async {
3536            let client = MockAssetManagementApiClient { force_error: false };
3537
3538            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder("123@test.com".to_string(),1,).recv_window(5000).build().unwrap();
3539
3540            let resp_json: Value = serde_json::from_str(r#"{"futureAccountResp":{"email":"abc@test.com","assets":[{"asset":"USDT","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"maxWithdrawAmount":"0.88308000","totalInitialMargin":"0.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"0.88308000","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"0.88308000","updateTime":1576756674610},"deliveryAccountResp":{"email":"abc@test.com","assets":[{"asset":"BTC","initialMargin":"0.00000000","maintenanceMargin":"0.00000000","marginBalance":"0.88308000","maxWithdrawAmount":"0.88308000","openOrderInitialMargin":"0.00000000","positionInitialMargin":"0.00000000","unrealizedProfit":"0.00000000","walletBalance":"0.88308000"}],"canDeposit":true,"canTrade":true,"canWithdraw":true,"feeTier":2,"updateTime":1598959682001}}"#).unwrap_or_else(|_| serde_json::json!({}));
3541            let expected_response : models::GetDetailOnSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response");
3542
3543            let resp = client.get_detail_on_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
3544            let data_future = resp.data();
3545            let actual_response = data_future.await.unwrap();
3546            assert_eq!(actual_response, expected_response);
3547        });
3548    }
3549
3550    #[test]
3551    fn get_detail_on_sub_accounts_futures_account_v2_response_error() {
3552        TOKIO_SHARED_RT.block_on(async {
3553            let client = MockAssetManagementApiClient { force_error: true };
3554
3555            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder(
3556                "123@test.com".to_string(),
3557                1,
3558            )
3559            .build()
3560            .unwrap();
3561
3562            match client
3563                .get_detail_on_sub_accounts_futures_account_v2(params)
3564                .await
3565            {
3566                Ok(_) => panic!("Expected an error"),
3567                Err(err) => {
3568                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3569                }
3570            }
3571        });
3572    }
3573
3574    #[test]
3575    fn get_detail_on_sub_accounts_margin_account_required_params_success() {
3576        TOKIO_SHARED_RT.block_on(async {
3577            let client = MockAssetManagementApiClient { force_error: false };
3578
3579            let params = GetDetailOnSubAccountsMarginAccountParams::builder("123@test.com".to_string(),).build().unwrap();
3580
3581            let resp_json: Value = serde_json::from_str(r#"{"email":"123@test.com","marginLevel":"11.64405625","totalAssetOfBtc":"6.82728457","totalLiabilityOfBtc":"0.58633215","totalNetAssetOfBtc":"6.24095242","marginTradeCoeffVo":{"forceLiquidationBar":"1.10000000","marginCallBar":"1.50000000","normalBar":"2.00000000"},"marginUserAssetVoList":[{"asset":"BTC","borrowed":"0.00000000","free":"0.00499500","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00499500"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3582            let expected_response : models::GetDetailOnSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsMarginAccountResponse");
3583
3584            let resp = client.get_detail_on_sub_accounts_margin_account(params).await.expect("Expected a response");
3585            let data_future = resp.data();
3586            let actual_response = data_future.await.unwrap();
3587            assert_eq!(actual_response, expected_response);
3588        });
3589    }
3590
3591    #[test]
3592    fn get_detail_on_sub_accounts_margin_account_optional_params_success() {
3593        TOKIO_SHARED_RT.block_on(async {
3594            let client = MockAssetManagementApiClient { force_error: false };
3595
3596            let params = GetDetailOnSubAccountsMarginAccountParams::builder("123@test.com".to_string(),).recv_window(5000).build().unwrap();
3597
3598            let resp_json: Value = serde_json::from_str(r#"{"email":"123@test.com","marginLevel":"11.64405625","totalAssetOfBtc":"6.82728457","totalLiabilityOfBtc":"0.58633215","totalNetAssetOfBtc":"6.24095242","marginTradeCoeffVo":{"forceLiquidationBar":"1.10000000","marginCallBar":"1.50000000","normalBar":"2.00000000"},"marginUserAssetVoList":[{"asset":"BTC","borrowed":"0.00000000","free":"0.00499500","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00499500"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3599            let expected_response : models::GetDetailOnSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsMarginAccountResponse");
3600
3601            let resp = client.get_detail_on_sub_accounts_margin_account(params).await.expect("Expected a response");
3602            let data_future = resp.data();
3603            let actual_response = data_future.await.unwrap();
3604            assert_eq!(actual_response, expected_response);
3605        });
3606    }
3607
3608    #[test]
3609    fn get_detail_on_sub_accounts_margin_account_response_error() {
3610        TOKIO_SHARED_RT.block_on(async {
3611            let client = MockAssetManagementApiClient { force_error: true };
3612
3613            let params =
3614                GetDetailOnSubAccountsMarginAccountParams::builder("123@test.com".to_string())
3615                    .build()
3616                    .unwrap();
3617
3618            match client
3619                .get_detail_on_sub_accounts_margin_account(params)
3620                .await
3621            {
3622                Ok(_) => panic!("Expected an error"),
3623                Err(err) => {
3624                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3625                }
3626            }
3627        });
3628    }
3629
3630    #[test]
3631    fn get_move_position_history_for_sub_account_required_params_success() {
3632        TOKIO_SHARED_RT.block_on(async {
3633            let client = MockAssetManagementApiClient { force_error: false };
3634
3635            let params = GetMovePositionHistoryForSubAccountParams::builder("BTCUSDT".to_string(),1,1,).build().unwrap();
3636
3637            let resp_json: Value = serde_json::from_str(r#"{"total":3,"futureMovePositionOrderVoList":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","price":"105025.50981609","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1737544712000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3638            let expected_response : models::GetMovePositionHistoryForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetMovePositionHistoryForSubAccountResponse");
3639
3640            let resp = client.get_move_position_history_for_sub_account(params).await.expect("Expected a response");
3641            let data_future = resp.data();
3642            let actual_response = data_future.await.unwrap();
3643            assert_eq!(actual_response, expected_response);
3644        });
3645    }
3646
3647    #[test]
3648    fn get_move_position_history_for_sub_account_optional_params_success() {
3649        TOKIO_SHARED_RT.block_on(async {
3650            let client = MockAssetManagementApiClient { force_error: false };
3651
3652            let params = GetMovePositionHistoryForSubAccountParams::builder("BTCUSDT".to_string(),1,1,).product_type(GetMovePositionHistoryForSubAccountProductTypeEnum::Um).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();
3653
3654            let resp_json: Value = serde_json::from_str(r#"{"total":3,"futureMovePositionOrderVoList":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","price":"105025.50981609","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1737544712000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3655            let expected_response : models::GetMovePositionHistoryForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetMovePositionHistoryForSubAccountResponse");
3656
3657            let resp = client.get_move_position_history_for_sub_account(params).await.expect("Expected a response");
3658            let data_future = resp.data();
3659            let actual_response = data_future.await.unwrap();
3660            assert_eq!(actual_response, expected_response);
3661        });
3662    }
3663
3664    #[test]
3665    fn get_move_position_history_for_sub_account_response_error() {
3666        TOKIO_SHARED_RT.block_on(async {
3667            let client = MockAssetManagementApiClient { force_error: true };
3668
3669            let params =
3670                GetMovePositionHistoryForSubAccountParams::builder("BTCUSDT".to_string(), 1, 1)
3671                    .build()
3672                    .unwrap();
3673
3674            match client
3675                .get_move_position_history_for_sub_account(params)
3676                .await
3677            {
3678                Ok(_) => panic!("Expected an error"),
3679                Err(err) => {
3680                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3681                }
3682            }
3683        });
3684    }
3685
3686    #[test]
3687    fn get_sub_account_deposit_address_required_params_success() {
3688        TOKIO_SHARED_RT.block_on(async {
3689            let client = MockAssetManagementApiClient { force_error: false };
3690
3691            let params = GetSubAccountDepositAddressParams::builder("123@test.com".to_string(),"BTC".to_string(),).build().unwrap();
3692
3693            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap_or_else(|_| serde_json::json!({}));
3694            let expected_response : models::GetSubAccountDepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSubAccountDepositAddressResponse");
3695
3696            let resp = client.get_sub_account_deposit_address(params).await.expect("Expected a response");
3697            let data_future = resp.data();
3698            let actual_response = data_future.await.unwrap();
3699            assert_eq!(actual_response, expected_response);
3700        });
3701    }
3702
3703    #[test]
3704    fn get_sub_account_deposit_address_optional_params_success() {
3705        TOKIO_SHARED_RT.block_on(async {
3706            let client = MockAssetManagementApiClient { force_error: false };
3707
3708            let params = GetSubAccountDepositAddressParams::builder("123@test.com".to_string(),"BTC".to_string(),).network("network_example".to_string()).amount(dec!(1.0)).recv_window(5000).build().unwrap();
3709
3710            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap_or_else(|_| serde_json::json!({}));
3711            let expected_response : models::GetSubAccountDepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSubAccountDepositAddressResponse");
3712
3713            let resp = client.get_sub_account_deposit_address(params).await.expect("Expected a response");
3714            let data_future = resp.data();
3715            let actual_response = data_future.await.unwrap();
3716            assert_eq!(actual_response, expected_response);
3717        });
3718    }
3719
3720    #[test]
3721    fn get_sub_account_deposit_address_response_error() {
3722        TOKIO_SHARED_RT.block_on(async {
3723            let client = MockAssetManagementApiClient { force_error: true };
3724
3725            let params = GetSubAccountDepositAddressParams::builder(
3726                "123@test.com".to_string(),
3727                "BTC".to_string(),
3728            )
3729            .build()
3730            .unwrap();
3731
3732            match client.get_sub_account_deposit_address(params).await {
3733                Ok(_) => panic!("Expected an error"),
3734                Err(err) => {
3735                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3736                }
3737            }
3738        });
3739    }
3740
3741    #[test]
3742    fn get_sub_account_deposit_history_required_params_success() {
3743        TOKIO_SHARED_RT.block_on(async {
3744            let client = MockAssetManagementApiClient { force_error: false };
3745
3746            let params = GetSubAccountDepositHistoryParams::builder("123@test.com".to_string(),).build().unwrap();
3747
3748            let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":0,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
3749            let expected_response : Vec<models::GetSubAccountDepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>");
3750
3751            let resp = client.get_sub_account_deposit_history(params).await.expect("Expected a response");
3752            let data_future = resp.data();
3753            let actual_response = data_future.await.unwrap();
3754            assert_eq!(actual_response, expected_response);
3755        });
3756    }
3757
3758    #[test]
3759    fn get_sub_account_deposit_history_optional_params_success() {
3760        TOKIO_SHARED_RT.block_on(async {
3761            let client = MockAssetManagementApiClient { force_error: false };
3762
3763            let params = GetSubAccountDepositHistoryParams::builder("123@test.com".to_string(),).include_source(false).coin("BTC".to_string()).status(0).start_time(1623319461670).end_time(1641782889000).limit(1).offset(0).recv_window(5000).tx_id("1".to_string()).build().unwrap();
3764
3765            let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":0,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
3766            let expected_response : Vec<models::GetSubAccountDepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>");
3767
3768            let resp = client.get_sub_account_deposit_history(params).await.expect("Expected a response");
3769            let data_future = resp.data();
3770            let actual_response = data_future.await.unwrap();
3771            assert_eq!(actual_response, expected_response);
3772        });
3773    }
3774
3775    #[test]
3776    fn get_sub_account_deposit_history_response_error() {
3777        TOKIO_SHARED_RT.block_on(async {
3778            let client = MockAssetManagementApiClient { force_error: true };
3779
3780            let params = GetSubAccountDepositHistoryParams::builder("123@test.com".to_string())
3781                .build()
3782                .unwrap();
3783
3784            match client.get_sub_account_deposit_history(params).await {
3785                Ok(_) => panic!("Expected an error"),
3786                Err(err) => {
3787                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3788                }
3789            }
3790        });
3791    }
3792
3793    #[test]
3794    fn get_summary_of_sub_accounts_futures_account_required_params_success() {
3795        TOKIO_SHARED_RT.block_on(async {
3796            let client = MockAssetManagementApiClient { force_error: false };
3797
3798            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(1,1,).build().unwrap();
3799
3800            let resp_json: Value = serde_json::from_str(r#"{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3801            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse");
3802
3803            let resp = client.get_summary_of_sub_accounts_futures_account(params).await.expect("Expected a response");
3804            let data_future = resp.data();
3805            let actual_response = data_future.await.unwrap();
3806            assert_eq!(actual_response, expected_response);
3807        });
3808    }
3809
3810    #[test]
3811    fn get_summary_of_sub_accounts_futures_account_optional_params_success() {
3812        TOKIO_SHARED_RT.block_on(async {
3813            let client = MockAssetManagementApiClient { force_error: false };
3814
3815            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(1,1,).recv_window(5000).build().unwrap();
3816
3817            let resp_json: Value = serde_json::from_str(r#"{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3818            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse");
3819
3820            let resp = client.get_summary_of_sub_accounts_futures_account(params).await.expect("Expected a response");
3821            let data_future = resp.data();
3822            let actual_response = data_future.await.unwrap();
3823            assert_eq!(actual_response, expected_response);
3824        });
3825    }
3826
3827    #[test]
3828    fn get_summary_of_sub_accounts_futures_account_response_error() {
3829        TOKIO_SHARED_RT.block_on(async {
3830            let client = MockAssetManagementApiClient { force_error: true };
3831
3832            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(1, 1)
3833                .build()
3834                .unwrap();
3835
3836            match client
3837                .get_summary_of_sub_accounts_futures_account(params)
3838                .await
3839            {
3840                Ok(_) => panic!("Expected an error"),
3841                Err(err) => {
3842                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3843                }
3844            }
3845        });
3846    }
3847
3848    #[test]
3849    fn get_summary_of_sub_accounts_futures_account_v2_required_params_success() {
3850        TOKIO_SHARED_RT.block_on(async {
3851            let client = MockAssetManagementApiClient { force_error: false };
3852
3853            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(1,).build().unwrap();
3854
3855            let resp_json: Value = serde_json::from_str(r#"{"futureAccountSummaryResp":{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]},"deliveryAccountSummaryResp":{"totalMarginBalanceOfBTC":"25.03221121","totalUnrealizedProfitOfBTC":"0.12233410","totalWalletBalanceOfBTC":"22.15879444","asset":"BTC","subAccountList":[{"email":"123@test.com","totalMarginBalance":"22.12659734","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"BTC"}]}}"#).unwrap_or_else(|_| serde_json::json!({}));
3856            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response");
3857
3858            let resp = client.get_summary_of_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
3859            let data_future = resp.data();
3860            let actual_response = data_future.await.unwrap();
3861            assert_eq!(actual_response, expected_response);
3862        });
3863    }
3864
3865    #[test]
3866    fn get_summary_of_sub_accounts_futures_account_v2_optional_params_success() {
3867        TOKIO_SHARED_RT.block_on(async {
3868            let client = MockAssetManagementApiClient { force_error: false };
3869
3870            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(1,).page(1).limit(10).recv_window(5000).build().unwrap();
3871
3872            let resp_json: Value = serde_json::from_str(r#"{"futureAccountSummaryResp":{"totalInitialMargin":"9.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"23.03235621","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"22.15879444","asset":"USD","subAccountList":[{"email":"123@test.com","totalInitialMargin":"9.00000000","totalMaintenanceMargin":"0.00000000","totalMarginBalance":"22.12659734","totalOpenOrderInitialMargin":"9.00000000","totalPositionInitialMargin":"0.00000000","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"USD"}]},"deliveryAccountSummaryResp":{"totalMarginBalanceOfBTC":"25.03221121","totalUnrealizedProfitOfBTC":"0.12233410","totalWalletBalanceOfBTC":"22.15879444","asset":"BTC","subAccountList":[{"email":"123@test.com","totalMarginBalance":"22.12659734","totalUnrealizedProfit":"0.00000000","totalWalletBalance":"22.12659734","asset":"BTC"}]}}"#).unwrap_or_else(|_| serde_json::json!({}));
3873            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response");
3874
3875            let resp = client.get_summary_of_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
3876            let data_future = resp.data();
3877            let actual_response = data_future.await.unwrap();
3878            assert_eq!(actual_response, expected_response);
3879        });
3880    }
3881
3882    #[test]
3883    fn get_summary_of_sub_accounts_futures_account_v2_response_error() {
3884        TOKIO_SHARED_RT.block_on(async {
3885            let client = MockAssetManagementApiClient { force_error: true };
3886
3887            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(1)
3888                .build()
3889                .unwrap();
3890
3891            match client
3892                .get_summary_of_sub_accounts_futures_account_v2(params)
3893                .await
3894            {
3895                Ok(_) => panic!("Expected an error"),
3896                Err(err) => {
3897                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3898                }
3899            }
3900        });
3901    }
3902
3903    #[test]
3904    fn get_summary_of_sub_accounts_margin_account_required_params_success() {
3905        TOKIO_SHARED_RT.block_on(async {
3906            let client = MockAssetManagementApiClient { force_error: false };
3907
3908            let params = GetSummaryOfSubAccountsMarginAccountParams::builder().build().unwrap();
3909
3910            let resp_json: Value = serde_json::from_str(r#"{"totalAssetOfBtc":"4.33333333","totalLiabilityOfBtc":"2.11111112","totalNetAssetOfBtc":"2.22222221","subAccountList":[{"email":"123@test.com","totalAssetOfBtc":"2.11111111","totalLiabilityOfBtc":"1.11111111","totalNetAssetOfBtc":"1.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3911            let expected_response : models::GetSummaryOfSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsMarginAccountResponse");
3912
3913            let resp = client.get_summary_of_sub_accounts_margin_account(params).await.expect("Expected a response");
3914            let data_future = resp.data();
3915            let actual_response = data_future.await.unwrap();
3916            assert_eq!(actual_response, expected_response);
3917        });
3918    }
3919
3920    #[test]
3921    fn get_summary_of_sub_accounts_margin_account_optional_params_success() {
3922        TOKIO_SHARED_RT.block_on(async {
3923            let client = MockAssetManagementApiClient { force_error: false };
3924
3925            let params = GetSummaryOfSubAccountsMarginAccountParams::builder().recv_window(5000).build().unwrap();
3926
3927            let resp_json: Value = serde_json::from_str(r#"{"totalAssetOfBtc":"4.33333333","totalLiabilityOfBtc":"2.11111112","totalNetAssetOfBtc":"2.22222221","subAccountList":[{"email":"123@test.com","totalAssetOfBtc":"2.11111111","totalLiabilityOfBtc":"1.11111111","totalNetAssetOfBtc":"1.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3928            let expected_response : models::GetSummaryOfSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsMarginAccountResponse");
3929
3930            let resp = client.get_summary_of_sub_accounts_margin_account(params).await.expect("Expected a response");
3931            let data_future = resp.data();
3932            let actual_response = data_future.await.unwrap();
3933            assert_eq!(actual_response, expected_response);
3934        });
3935    }
3936
3937    #[test]
3938    fn get_summary_of_sub_accounts_margin_account_response_error() {
3939        TOKIO_SHARED_RT.block_on(async {
3940            let client = MockAssetManagementApiClient { force_error: true };
3941
3942            let params = GetSummaryOfSubAccountsMarginAccountParams::builder()
3943                .build()
3944                .unwrap();
3945
3946            match client
3947                .get_summary_of_sub_accounts_margin_account(params)
3948                .await
3949            {
3950                Ok(_) => panic!("Expected an error"),
3951                Err(err) => {
3952                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3953                }
3954            }
3955        });
3956    }
3957
3958    #[test]
3959    fn margin_transfer_for_sub_account_required_params_success() {
3960        TOKIO_SHARED_RT.block_on(async {
3961            let client = MockAssetManagementApiClient { force_error: false };
3962
3963            let params = MarginTransferForSubAccountParams::builder(
3964                "123@test.com".to_string(),
3965                "BTC".to_string(),
3966                dec!(1.0),
3967                1,
3968            )
3969            .build()
3970            .unwrap();
3971
3972            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
3973                .unwrap_or_else(|_| serde_json::json!({}));
3974            let expected_response: models::MarginTransferForSubAccountResponse =
3975                serde_json::from_value(resp_json.clone())
3976                    .expect("should parse into models::MarginTransferForSubAccountResponse");
3977
3978            let resp = client
3979                .margin_transfer_for_sub_account(params)
3980                .await
3981                .expect("Expected a response");
3982            let data_future = resp.data();
3983            let actual_response = data_future.await.unwrap();
3984            assert_eq!(actual_response, expected_response);
3985        });
3986    }
3987
3988    #[test]
3989    fn margin_transfer_for_sub_account_optional_params_success() {
3990        TOKIO_SHARED_RT.block_on(async {
3991            let client = MockAssetManagementApiClient { force_error: false };
3992
3993            let params = MarginTransferForSubAccountParams::builder(
3994                "123@test.com".to_string(),
3995                "BTC".to_string(),
3996                dec!(1.0),
3997                1,
3998            )
3999            .recv_window(5000)
4000            .build()
4001            .unwrap();
4002
4003            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
4004                .unwrap_or_else(|_| serde_json::json!({}));
4005            let expected_response: models::MarginTransferForSubAccountResponse =
4006                serde_json::from_value(resp_json.clone())
4007                    .expect("should parse into models::MarginTransferForSubAccountResponse");
4008
4009            let resp = client
4010                .margin_transfer_for_sub_account(params)
4011                .await
4012                .expect("Expected a response");
4013            let data_future = resp.data();
4014            let actual_response = data_future.await.unwrap();
4015            assert_eq!(actual_response, expected_response);
4016        });
4017    }
4018
4019    #[test]
4020    fn margin_transfer_for_sub_account_response_error() {
4021        TOKIO_SHARED_RT.block_on(async {
4022            let client = MockAssetManagementApiClient { force_error: true };
4023
4024            let params = MarginTransferForSubAccountParams::builder(
4025                "123@test.com".to_string(),
4026                "BTC".to_string(),
4027                dec!(1.0),
4028                1,
4029            )
4030            .build()
4031            .unwrap();
4032
4033            match client.margin_transfer_for_sub_account(params).await {
4034                Ok(_) => panic!("Expected an error"),
4035                Err(err) => {
4036                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4037                }
4038            }
4039        });
4040    }
4041
4042    #[test]
4043    fn move_position_for_sub_account_required_params_success() {
4044        TOKIO_SHARED_RT.block_on(async {
4045            let client = MockAssetManagementApiClient { force_error: false };
4046
4047            let params = MovePositionForSubAccountParams::builder("testFrom@google.com".to_string(),"testTo@google.com".to_string(),MovePositionForSubAccountProductTypeEnum::Um,vec![],).build().unwrap();
4048
4049            let resp_json: Value = serde_json::from_str(r#"{"movePositionOrders":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.001","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4050            let expected_response : models::MovePositionForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MovePositionForSubAccountResponse");
4051
4052            let resp = client.move_position_for_sub_account(params).await.expect("Expected a response");
4053            let data_future = resp.data();
4054            let actual_response = data_future.await.unwrap();
4055            assert_eq!(actual_response, expected_response);
4056        });
4057    }
4058
4059    #[test]
4060    fn move_position_for_sub_account_optional_params_success() {
4061        TOKIO_SHARED_RT.block_on(async {
4062            let client = MockAssetManagementApiClient { force_error: false };
4063
4064            let params = MovePositionForSubAccountParams::builder("testFrom@google.com".to_string(),"testTo@google.com".to_string(),MovePositionForSubAccountProductTypeEnum::Um,vec![],).recv_window(5000).build().unwrap();
4065
4066            let resp_json: Value = serde_json::from_str(r#"{"movePositionOrders":[{"fromUserEmail":"testFrom@google.com","toUserEmail":"testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.001","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4067            let expected_response : models::MovePositionForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MovePositionForSubAccountResponse");
4068
4069            let resp = client.move_position_for_sub_account(params).await.expect("Expected a response");
4070            let data_future = resp.data();
4071            let actual_response = data_future.await.unwrap();
4072            assert_eq!(actual_response, expected_response);
4073        });
4074    }
4075
4076    #[test]
4077    fn move_position_for_sub_account_response_error() {
4078        TOKIO_SHARED_RT.block_on(async {
4079            let client = MockAssetManagementApiClient { force_error: true };
4080
4081            let params = MovePositionForSubAccountParams::builder(
4082                "testFrom@google.com".to_string(),
4083                "testTo@google.com".to_string(),
4084                MovePositionForSubAccountProductTypeEnum::Um,
4085                vec![],
4086            )
4087            .build()
4088            .unwrap();
4089
4090            match client.move_position_for_sub_account(params).await {
4091                Ok(_) => panic!("Expected an error"),
4092                Err(err) => {
4093                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4094                }
4095            }
4096        });
4097    }
4098
4099    #[test]
4100    fn query_sub_account_assets_required_params_success() {
4101        TOKIO_SHARED_RT.block_on(async {
4102            let client = MockAssetManagementApiClient { force_error: false };
4103
4104            let params = QuerySubAccountAssetsParams::builder("123@test.com".to_string(),).build().unwrap();
4105
4106            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":11467.6399,"locked":0}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4107            let expected_response : models::QuerySubAccountAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsResponse");
4108
4109            let resp = client.query_sub_account_assets(params).await.expect("Expected a response");
4110            let data_future = resp.data();
4111            let actual_response = data_future.await.unwrap();
4112            assert_eq!(actual_response, expected_response);
4113        });
4114    }
4115
4116    #[test]
4117    fn query_sub_account_assets_optional_params_success() {
4118        TOKIO_SHARED_RT.block_on(async {
4119            let client = MockAssetManagementApiClient { force_error: false };
4120
4121            let params = QuerySubAccountAssetsParams::builder("123@test.com".to_string(),).recv_window(5000).build().unwrap();
4122
4123            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":11467.6399,"locked":0}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4124            let expected_response : models::QuerySubAccountAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsResponse");
4125
4126            let resp = client.query_sub_account_assets(params).await.expect("Expected a response");
4127            let data_future = resp.data();
4128            let actual_response = data_future.await.unwrap();
4129            assert_eq!(actual_response, expected_response);
4130        });
4131    }
4132
4133    #[test]
4134    fn query_sub_account_assets_response_error() {
4135        TOKIO_SHARED_RT.block_on(async {
4136            let client = MockAssetManagementApiClient { force_error: true };
4137
4138            let params = QuerySubAccountAssetsParams::builder("123@test.com".to_string())
4139                .build()
4140                .unwrap();
4141
4142            match client.query_sub_account_assets(params).await {
4143                Ok(_) => panic!("Expected an error"),
4144                Err(err) => {
4145                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4146                }
4147            }
4148        });
4149    }
4150
4151    #[test]
4152    fn query_sub_account_assets_asset_management_required_params_success() {
4153        TOKIO_SHARED_RT.block_on(async {
4154            let client = MockAssetManagementApiClient { force_error: false };
4155
4156            let params = QuerySubAccountAssetsAssetManagementParams::builder("123@test.com".to_string(),).build().unwrap();
4157
4158            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4159            let expected_response : models::QuerySubAccountAssetsAssetManagementResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsAssetManagementResponse");
4160
4161            let resp = client.query_sub_account_assets_asset_management(params).await.expect("Expected a response");
4162            let data_future = resp.data();
4163            let actual_response = data_future.await.unwrap();
4164            assert_eq!(actual_response, expected_response);
4165        });
4166    }
4167
4168    #[test]
4169    fn query_sub_account_assets_asset_management_optional_params_success() {
4170        TOKIO_SHARED_RT.block_on(async {
4171            let client = MockAssetManagementApiClient { force_error: false };
4172
4173            let params = QuerySubAccountAssetsAssetManagementParams::builder("123@test.com".to_string(),).recv_window(5000).build().unwrap();
4174
4175            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4176            let expected_response : models::QuerySubAccountAssetsAssetManagementResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsAssetManagementResponse");
4177
4178            let resp = client.query_sub_account_assets_asset_management(params).await.expect("Expected a response");
4179            let data_future = resp.data();
4180            let actual_response = data_future.await.unwrap();
4181            assert_eq!(actual_response, expected_response);
4182        });
4183    }
4184
4185    #[test]
4186    fn query_sub_account_assets_asset_management_response_error() {
4187        TOKIO_SHARED_RT.block_on(async {
4188            let client = MockAssetManagementApiClient { force_error: true };
4189
4190            let params =
4191                QuerySubAccountAssetsAssetManagementParams::builder("123@test.com".to_string())
4192                    .build()
4193                    .unwrap();
4194
4195            match client
4196                .query_sub_account_assets_asset_management(params)
4197                .await
4198            {
4199                Ok(_) => panic!("Expected an error"),
4200                Err(err) => {
4201                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4202                }
4203            }
4204        });
4205    }
4206
4207    #[test]
4208    fn query_sub_account_futures_asset_transfer_history_required_params_success() {
4209        TOKIO_SHARED_RT.block_on(async {
4210            let client = MockAssetManagementApiClient { force_error: false };
4211
4212            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder("123@test.com".to_string(),1,).build().unwrap();
4213
4214            let resp_json: Value = serde_json::from_str(r#"{"success":true,"futuresType":2,"transfers":[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"1","tranId":11897001102,"time":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4215            let expected_response : models::QuerySubAccountFuturesAssetTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse");
4216
4217            let resp = client.query_sub_account_futures_asset_transfer_history(params).await.expect("Expected a response");
4218            let data_future = resp.data();
4219            let actual_response = data_future.await.unwrap();
4220            assert_eq!(actual_response, expected_response);
4221        });
4222    }
4223
4224    #[test]
4225    fn query_sub_account_futures_asset_transfer_history_optional_params_success() {
4226        TOKIO_SHARED_RT.block_on(async {
4227            let client = MockAssetManagementApiClient { force_error: false };
4228
4229            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder("123@test.com".to_string(),1,).start_time(1623319461670).end_time(1641782889000).page(1).limit(10).recv_window(5000).build().unwrap();
4230
4231            let resp_json: Value = serde_json::from_str(r#"{"success":true,"futuresType":2,"transfers":[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"1","tranId":11897001102,"time":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4232            let expected_response : models::QuerySubAccountFuturesAssetTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse");
4233
4234            let resp = client.query_sub_account_futures_asset_transfer_history(params).await.expect("Expected a response");
4235            let data_future = resp.data();
4236            let actual_response = data_future.await.unwrap();
4237            assert_eq!(actual_response, expected_response);
4238        });
4239    }
4240
4241    #[test]
4242    fn query_sub_account_futures_asset_transfer_history_response_error() {
4243        TOKIO_SHARED_RT.block_on(async {
4244            let client = MockAssetManagementApiClient { force_error: true };
4245
4246            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder(
4247                "123@test.com".to_string(),
4248                1,
4249            )
4250            .build()
4251            .unwrap();
4252
4253            match client
4254                .query_sub_account_futures_asset_transfer_history(params)
4255                .await
4256            {
4257                Ok(_) => panic!("Expected an error"),
4258                Err(err) => {
4259                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4260                }
4261            }
4262        });
4263    }
4264
4265    #[test]
4266    fn query_sub_account_spot_asset_transfer_history_required_params_success() {
4267        TOKIO_SHARED_RT.block_on(async {
4268            let client = MockAssetManagementApiClient { force_error: false };
4269
4270            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder().build().unwrap();
4271
4272            let resp_json: Value = serde_json::from_str(r#"[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"10","status":"SUCCESS","tranId":6489943656,"time":1544433328000}]"#).unwrap_or_else(|_| serde_json::json!({}));
4273            let expected_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");
4274
4275            let resp = client.query_sub_account_spot_asset_transfer_history(params).await.expect("Expected a response");
4276            let data_future = resp.data();
4277            let actual_response = data_future.await.unwrap();
4278            assert_eq!(actual_response, expected_response);
4279        });
4280    }
4281
4282    #[test]
4283    fn query_sub_account_spot_asset_transfer_history_optional_params_success() {
4284        TOKIO_SHARED_RT.block_on(async {
4285            let client = MockAssetManagementApiClient { force_error: false };
4286
4287            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder().from_email("aaa@test.com".to_string()).to_email("bbb@test.com".to_string()).start_time(1623319461670).end_time(1641782889000).page(1).limit(10).recv_window(5000).build().unwrap();
4288
4289            let resp_json: Value = serde_json::from_str(r#"[{"from":"aaa@test.com","to":"bbb@test.com","asset":"BTC","qty":"10","status":"SUCCESS","tranId":6489943656,"time":1544433328000}]"#).unwrap_or_else(|_| serde_json::json!({}));
4290            let expected_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");
4291
4292            let resp = client.query_sub_account_spot_asset_transfer_history(params).await.expect("Expected a response");
4293            let data_future = resp.data();
4294            let actual_response = data_future.await.unwrap();
4295            assert_eq!(actual_response, expected_response);
4296        });
4297    }
4298
4299    #[test]
4300    fn query_sub_account_spot_asset_transfer_history_response_error() {
4301        TOKIO_SHARED_RT.block_on(async {
4302            let client = MockAssetManagementApiClient { force_error: true };
4303
4304            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder()
4305                .build()
4306                .unwrap();
4307
4308            match client
4309                .query_sub_account_spot_asset_transfer_history(params)
4310                .await
4311            {
4312                Ok(_) => panic!("Expected an error"),
4313                Err(err) => {
4314                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4315                }
4316            }
4317        });
4318    }
4319
4320    #[test]
4321    fn query_sub_account_spot_assets_summary_required_params_success() {
4322        TOKIO_SHARED_RT.block_on(async {
4323            let client = MockAssetManagementApiClient { force_error: false };
4324
4325            let params = QuerySubAccountSpotAssetsSummaryParams::builder().build().unwrap();
4326
4327            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4328            let expected_response : models::QuerySubAccountSpotAssetsSummaryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");
4329
4330            let resp = client.query_sub_account_spot_assets_summary(params).await.expect("Expected a response");
4331            let data_future = resp.data();
4332            let actual_response = data_future.await.unwrap();
4333            assert_eq!(actual_response, expected_response);
4334        });
4335    }
4336
4337    #[test]
4338    fn query_sub_account_spot_assets_summary_optional_params_success() {
4339        TOKIO_SHARED_RT.block_on(async {
4340            let client = MockAssetManagementApiClient { force_error: false };
4341
4342            let params = QuerySubAccountSpotAssetsSummaryParams::builder().email("123@test.com".to_string()).page(1).size(10).recv_window(5000).build().unwrap();
4343
4344            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
4345            let expected_response : models::QuerySubAccountSpotAssetsSummaryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");
4346
4347            let resp = client.query_sub_account_spot_assets_summary(params).await.expect("Expected a response");
4348            let data_future = resp.data();
4349            let actual_response = data_future.await.unwrap();
4350            assert_eq!(actual_response, expected_response);
4351        });
4352    }
4353
4354    #[test]
4355    fn query_sub_account_spot_assets_summary_response_error() {
4356        TOKIO_SHARED_RT.block_on(async {
4357            let client = MockAssetManagementApiClient { force_error: true };
4358
4359            let params = QuerySubAccountSpotAssetsSummaryParams::builder()
4360                .build()
4361                .unwrap();
4362
4363            match client.query_sub_account_spot_assets_summary(params).await {
4364                Ok(_) => panic!("Expected an error"),
4365                Err(err) => {
4366                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4367                }
4368            }
4369        });
4370    }
4371
4372    #[test]
4373    fn query_universal_transfer_history_required_params_success() {
4374        TOKIO_SHARED_RT.block_on(async {
4375            let client = MockAssetManagementApiClient { force_error: false };
4376
4377            let params = QueryUniversalTransferHistoryParams::builder().build().unwrap();
4378
4379            let resp_json: Value = serde_json::from_str(r#"{"result":[{"tranId":92275823339,"fromEmail":"abctest@gmail.com","toEmail":"deftest@gmail.com","asset":"BNB","amount":"0.01","createTimeStamp":1640317374000,"fromAccountType":"USDT_FUTURE","toAccountType":"SPOT","status":"SUCCESS","clientTranId":"test"}],"totalCount":1}"#).unwrap_or_else(|_| serde_json::json!({}));
4380            let expected_response : models::QueryUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUniversalTransferHistoryResponse");
4381
4382            let resp = client.query_universal_transfer_history(params).await.expect("Expected a response");
4383            let data_future = resp.data();
4384            let actual_response = data_future.await.unwrap();
4385            assert_eq!(actual_response, expected_response);
4386        });
4387    }
4388
4389    #[test]
4390    fn query_universal_transfer_history_optional_params_success() {
4391        TOKIO_SHARED_RT.block_on(async {
4392            let client = MockAssetManagementApiClient { force_error: false };
4393
4394            let params = QueryUniversalTransferHistoryParams::builder().from_email("abctest@gmail.com".to_string()).to_email("deftest@gmail.com".to_string()).client_tran_id("1".to_string()).start_time(1623319461670).end_time(1641782889000).page(1).limit(10).recv_window(5000).build().unwrap();
4395
4396            let resp_json: Value = serde_json::from_str(r#"{"result":[{"tranId":92275823339,"fromEmail":"abctest@gmail.com","toEmail":"deftest@gmail.com","asset":"BNB","amount":"0.01","createTimeStamp":1640317374000,"fromAccountType":"USDT_FUTURE","toAccountType":"SPOT","status":"SUCCESS","clientTranId":"test"}],"totalCount":1}"#).unwrap_or_else(|_| serde_json::json!({}));
4397            let expected_response : models::QueryUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUniversalTransferHistoryResponse");
4398
4399            let resp = client.query_universal_transfer_history(params).await.expect("Expected a response");
4400            let data_future = resp.data();
4401            let actual_response = data_future.await.unwrap();
4402            assert_eq!(actual_response, expected_response);
4403        });
4404    }
4405
4406    #[test]
4407    fn query_universal_transfer_history_response_error() {
4408        TOKIO_SHARED_RT.block_on(async {
4409            let client = MockAssetManagementApiClient { force_error: true };
4410
4411            let params = QueryUniversalTransferHistoryParams::builder()
4412                .build()
4413                .unwrap();
4414
4415            match client.query_universal_transfer_history(params).await {
4416                Ok(_) => panic!("Expected an error"),
4417                Err(err) => {
4418                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4419                }
4420            }
4421        });
4422    }
4423
4424    #[test]
4425    fn sub_account_futures_asset_transfer_required_params_success() {
4426        TOKIO_SHARED_RT.block_on(async {
4427            let client = MockAssetManagementApiClient { force_error: false };
4428
4429            let params = SubAccountFuturesAssetTransferParams::builder(
4430                "abc@test.com".to_string(),
4431                "def@test.com".to_string(),
4432                1,
4433                "BTC".to_string(),
4434                dec!(1.0),
4435            )
4436            .build()
4437            .unwrap();
4438
4439            let resp_json: Value = serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#)
4440                .unwrap_or_else(|_| serde_json::json!({}));
4441            let expected_response: models::SubAccountFuturesAssetTransferResponse =
4442                serde_json::from_value(resp_json.clone())
4443                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");
4444
4445            let resp = client
4446                .sub_account_futures_asset_transfer(params)
4447                .await
4448                .expect("Expected a response");
4449            let data_future = resp.data();
4450            let actual_response = data_future.await.unwrap();
4451            assert_eq!(actual_response, expected_response);
4452        });
4453    }
4454
4455    #[test]
4456    fn sub_account_futures_asset_transfer_optional_params_success() {
4457        TOKIO_SHARED_RT.block_on(async {
4458            let client = MockAssetManagementApiClient { force_error: false };
4459
4460            let params = SubAccountFuturesAssetTransferParams::builder(
4461                "abc@test.com".to_string(),
4462                "def@test.com".to_string(),
4463                1,
4464                "BTC".to_string(),
4465                dec!(1.0),
4466            )
4467            .recv_window(5000)
4468            .build()
4469            .unwrap();
4470
4471            let resp_json: Value = serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#)
4472                .unwrap_or_else(|_| serde_json::json!({}));
4473            let expected_response: models::SubAccountFuturesAssetTransferResponse =
4474                serde_json::from_value(resp_json.clone())
4475                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");
4476
4477            let resp = client
4478                .sub_account_futures_asset_transfer(params)
4479                .await
4480                .expect("Expected a response");
4481            let data_future = resp.data();
4482            let actual_response = data_future.await.unwrap();
4483            assert_eq!(actual_response, expected_response);
4484        });
4485    }
4486
4487    #[test]
4488    fn sub_account_futures_asset_transfer_response_error() {
4489        TOKIO_SHARED_RT.block_on(async {
4490            let client = MockAssetManagementApiClient { force_error: true };
4491
4492            let params = SubAccountFuturesAssetTransferParams::builder(
4493                "abc@test.com".to_string(),
4494                "def@test.com".to_string(),
4495                1,
4496                "BTC".to_string(),
4497                dec!(1.0),
4498            )
4499            .build()
4500            .unwrap();
4501
4502            match client.sub_account_futures_asset_transfer(params).await {
4503                Ok(_) => panic!("Expected an error"),
4504                Err(err) => {
4505                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4506                }
4507            }
4508        });
4509    }
4510
4511    #[test]
4512    fn sub_account_transfer_history_required_params_success() {
4513        TOKIO_SHARED_RT.block_on(async {
4514            let client = MockAssetManagementApiClient { force_error: false };
4515
4516            let params = SubAccountTransferHistoryParams::builder().build().unwrap();
4517
4518            let resp_json: Value = serde_json::from_str(r#"[{"counterParty":"master","email":"master@test.com","type":1,"asset":"BTC","qty":"1","fromAccountType":"SPOT","toAccountType":"SPOT","status":"SUCCESS","tranId":11798835829,"time":1544433325000}]"#).unwrap_or_else(|_| serde_json::json!({}));
4519            let expected_response : Vec<models::SubAccountTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SubAccountTransferHistoryResponseInner>");
4520
4521            let resp = client.sub_account_transfer_history(params).await.expect("Expected a response");
4522            let data_future = resp.data();
4523            let actual_response = data_future.await.unwrap();
4524            assert_eq!(actual_response, expected_response);
4525        });
4526    }
4527
4528    #[test]
4529    fn sub_account_transfer_history_optional_params_success() {
4530        TOKIO_SHARED_RT.block_on(async {
4531            let client = MockAssetManagementApiClient { force_error: false };
4532
4533            let params = SubAccountTransferHistoryParams::builder().asset("BTC".to_string()).r#type(1).start_time(1623319461670).end_time(1641782889000).limit(10).return_fail_history(false).recv_window(5000).build().unwrap();
4534
4535            let resp_json: Value = serde_json::from_str(r#"[{"counterParty":"master","email":"master@test.com","type":1,"asset":"BTC","qty":"1","fromAccountType":"SPOT","toAccountType":"SPOT","status":"SUCCESS","tranId":11798835829,"time":1544433325000}]"#).unwrap_or_else(|_| serde_json::json!({}));
4536            let expected_response : Vec<models::SubAccountTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SubAccountTransferHistoryResponseInner>");
4537
4538            let resp = client.sub_account_transfer_history(params).await.expect("Expected a response");
4539            let data_future = resp.data();
4540            let actual_response = data_future.await.unwrap();
4541            assert_eq!(actual_response, expected_response);
4542        });
4543    }
4544
4545    #[test]
4546    fn sub_account_transfer_history_response_error() {
4547        TOKIO_SHARED_RT.block_on(async {
4548            let client = MockAssetManagementApiClient { force_error: true };
4549
4550            let params = SubAccountTransferHistoryParams::builder().build().unwrap();
4551
4552            match client.sub_account_transfer_history(params).await {
4553                Ok(_) => panic!("Expected an error"),
4554                Err(err) => {
4555                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4556                }
4557            }
4558        });
4559    }
4560
4561    #[test]
4562    fn transfer_to_master_required_params_success() {
4563        TOKIO_SHARED_RT.block_on(async {
4564            let client = MockAssetManagementApiClient { force_error: false };
4565
4566            let params = TransferToMasterParams::builder("BTC".to_string(), dec!(1.0))
4567                .build()
4568                .unwrap();
4569
4570            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
4571                .unwrap_or_else(|_| serde_json::json!({}));
4572            let expected_response: models::TransferToMasterResponse =
4573                serde_json::from_value(resp_json.clone())
4574                    .expect("should parse into models::TransferToMasterResponse");
4575
4576            let resp = client
4577                .transfer_to_master(params)
4578                .await
4579                .expect("Expected a response");
4580            let data_future = resp.data();
4581            let actual_response = data_future.await.unwrap();
4582            assert_eq!(actual_response, expected_response);
4583        });
4584    }
4585
4586    #[test]
4587    fn transfer_to_master_optional_params_success() {
4588        TOKIO_SHARED_RT.block_on(async {
4589            let client = MockAssetManagementApiClient { force_error: false };
4590
4591            let params = TransferToMasterParams::builder("BTC".to_string(), dec!(1.0))
4592                .recv_window(5000)
4593                .build()
4594                .unwrap();
4595
4596            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
4597                .unwrap_or_else(|_| serde_json::json!({}));
4598            let expected_response: models::TransferToMasterResponse =
4599                serde_json::from_value(resp_json.clone())
4600                    .expect("should parse into models::TransferToMasterResponse");
4601
4602            let resp = client
4603                .transfer_to_master(params)
4604                .await
4605                .expect("Expected a response");
4606            let data_future = resp.data();
4607            let actual_response = data_future.await.unwrap();
4608            assert_eq!(actual_response, expected_response);
4609        });
4610    }
4611
4612    #[test]
4613    fn transfer_to_master_response_error() {
4614        TOKIO_SHARED_RT.block_on(async {
4615            let client = MockAssetManagementApiClient { force_error: true };
4616
4617            let params = TransferToMasterParams::builder("BTC".to_string(), dec!(1.0))
4618                .build()
4619                .unwrap();
4620
4621            match client.transfer_to_master(params).await {
4622                Ok(_) => panic!("Expected an error"),
4623                Err(err) => {
4624                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4625                }
4626            }
4627        });
4628    }
4629
4630    #[test]
4631    fn transfer_to_sub_account_of_same_master_required_params_success() {
4632        TOKIO_SHARED_RT.block_on(async {
4633            let client = MockAssetManagementApiClient { force_error: false };
4634
4635            let params = TransferToSubAccountOfSameMasterParams::builder(
4636                "abc@test.com".to_string(),
4637                "BTC".to_string(),
4638                dec!(1.0),
4639            )
4640            .build()
4641            .unwrap();
4642
4643            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
4644                .unwrap_or_else(|_| serde_json::json!({}));
4645            let expected_response: models::TransferToSubAccountOfSameMasterResponse =
4646                serde_json::from_value(resp_json.clone())
4647                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");
4648
4649            let resp = client
4650                .transfer_to_sub_account_of_same_master(params)
4651                .await
4652                .expect("Expected a response");
4653            let data_future = resp.data();
4654            let actual_response = data_future.await.unwrap();
4655            assert_eq!(actual_response, expected_response);
4656        });
4657    }
4658
4659    #[test]
4660    fn transfer_to_sub_account_of_same_master_optional_params_success() {
4661        TOKIO_SHARED_RT.block_on(async {
4662            let client = MockAssetManagementApiClient { force_error: false };
4663
4664            let params = TransferToSubAccountOfSameMasterParams::builder(
4665                "abc@test.com".to_string(),
4666                "BTC".to_string(),
4667                dec!(1.0),
4668            )
4669            .recv_window(5000)
4670            .build()
4671            .unwrap();
4672
4673            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#)
4674                .unwrap_or_else(|_| serde_json::json!({}));
4675            let expected_response: models::TransferToSubAccountOfSameMasterResponse =
4676                serde_json::from_value(resp_json.clone())
4677                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");
4678
4679            let resp = client
4680                .transfer_to_sub_account_of_same_master(params)
4681                .await
4682                .expect("Expected a response");
4683            let data_future = resp.data();
4684            let actual_response = data_future.await.unwrap();
4685            assert_eq!(actual_response, expected_response);
4686        });
4687    }
4688
4689    #[test]
4690    fn transfer_to_sub_account_of_same_master_response_error() {
4691        TOKIO_SHARED_RT.block_on(async {
4692            let client = MockAssetManagementApiClient { force_error: true };
4693
4694            let params = TransferToSubAccountOfSameMasterParams::builder(
4695                "abc@test.com".to_string(),
4696                "BTC".to_string(),
4697                dec!(1.0),
4698            )
4699            .build()
4700            .unwrap();
4701
4702            match client.transfer_to_sub_account_of_same_master(params).await {
4703                Ok(_) => panic!("Expected an error"),
4704                Err(err) => {
4705                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4706                }
4707            }
4708        });
4709    }
4710
4711    #[test]
4712    fn universal_transfer_required_params_success() {
4713        TOKIO_SHARED_RT.block_on(async {
4714            let client = MockAssetManagementApiClient { force_error: false };
4715
4716            let params = UniversalTransferParams::builder(
4717                UniversalTransferFromAccountTypeEnum::Spot,
4718                UniversalTransferToAccountTypeEnum::Spot,
4719                "BTC".to_string(),
4720                dec!(1.0),
4721            )
4722            .build()
4723            .unwrap();
4724
4725            let resp_json: Value =
4726                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#)
4727                    .unwrap_or_else(|_| serde_json::json!({}));
4728            let expected_response: models::UniversalTransferResponse =
4729                serde_json::from_value(resp_json.clone())
4730                    .expect("should parse into models::UniversalTransferResponse");
4731
4732            let resp = client
4733                .universal_transfer(params)
4734                .await
4735                .expect("Expected a response");
4736            let data_future = resp.data();
4737            let actual_response = data_future.await.unwrap();
4738            assert_eq!(actual_response, expected_response);
4739        });
4740    }
4741
4742    #[test]
4743    fn universal_transfer_optional_params_success() {
4744        TOKIO_SHARED_RT.block_on(async {
4745            let client = MockAssetManagementApiClient { force_error: false };
4746
4747            let params = UniversalTransferParams::builder(
4748                UniversalTransferFromAccountTypeEnum::Spot,
4749                UniversalTransferToAccountTypeEnum::Spot,
4750                "BTC".to_string(),
4751                dec!(1.0),
4752            )
4753            .from_email("abc@test.com".to_string())
4754            .to_email("def@test.com".to_string())
4755            .client_tran_id("1".to_string())
4756            .symbol("BTCUSDT".to_string())
4757            .recv_window(5000)
4758            .build()
4759            .unwrap();
4760
4761            let resp_json: Value =
4762                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#)
4763                    .unwrap_or_else(|_| serde_json::json!({}));
4764            let expected_response: models::UniversalTransferResponse =
4765                serde_json::from_value(resp_json.clone())
4766                    .expect("should parse into models::UniversalTransferResponse");
4767
4768            let resp = client
4769                .universal_transfer(params)
4770                .await
4771                .expect("Expected a response");
4772            let data_future = resp.data();
4773            let actual_response = data_future.await.unwrap();
4774            assert_eq!(actual_response, expected_response);
4775        });
4776    }
4777
4778    #[test]
4779    fn universal_transfer_response_error() {
4780        TOKIO_SHARED_RT.block_on(async {
4781            let client = MockAssetManagementApiClient { force_error: true };
4782
4783            let params = UniversalTransferParams::builder(
4784                UniversalTransferFromAccountTypeEnum::Spot,
4785                UniversalTransferToAccountTypeEnum::Spot,
4786                "BTC".to_string(),
4787                dec!(1.0),
4788            )
4789            .build()
4790            .unwrap();
4791
4792            match client.universal_transfer(params).await {
4793                Ok(_) => panic!("Expected an error"),
4794                Err(err) => {
4795                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
4796                }
4797            }
4798        });
4799    }
4800}