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