/*
 * Binance Sub Account REST API
 *
 * OpenAPI Specification for the Binance Sub Account REST API
 *
 * The version of the OpenAPI document: 1.0.0
 *
 *
 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
 * https://openapi-generator.tech
 * Do not edit the class manually.
 */

#![allow(unused_imports)]
use async_trait::async_trait;
use derive_builder::Builder;
use reqwest;
use rust_decimal::prelude::*;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::collections::BTreeMap;

use crate::common::{
    config::ConfigurationRestApi,
    models::{ParamBuildError, RestApiResponse},
    utils::send_request,
};
use crate::sub_account::rest_api::models;

const HAS_TIME_UNIT: bool = false;

#[async_trait]
pub trait AssetManagementApi: Send + Sync {
    async fn futures_transfer_for_sub_account(
        &self,
        params: FuturesTransferForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>>;
    async fn get_detail_on_sub_accounts_futures_account(
        &self,
        params: GetDetailOnSubAccountsFuturesAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>>;
    async fn get_detail_on_sub_accounts_futures_account_v2(
        &self,
        params: GetDetailOnSubAccountsFuturesAccountV2Params,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>;
    async fn get_detail_on_sub_accounts_margin_account(
        &self,
        params: GetDetailOnSubAccountsMarginAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>>;
    async fn get_move_position_history_for_sub_account(
        &self,
        params: GetMovePositionHistoryForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>>;
    async fn get_sub_account_deposit_address(
        &self,
        params: GetSubAccountDepositAddressParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>>;
    async fn get_sub_account_deposit_history(
        &self,
        params: GetSubAccountDepositHistoryParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>;
    async fn get_summary_of_sub_accounts_futures_account(
        &self,
        params: GetSummaryOfSubAccountsFuturesAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>;
    async fn get_summary_of_sub_accounts_futures_account_v2(
        &self,
        params: GetSummaryOfSubAccountsFuturesAccountV2Params,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>;
    async fn get_summary_of_sub_accounts_margin_account(
        &self,
        params: GetSummaryOfSubAccountsMarginAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>>;
    async fn margin_transfer_for_sub_account(
        &self,
        params: MarginTransferForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>>;
    async fn move_position_for_sub_account(
        &self,
        params: MovePositionForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>>;
    async fn query_sub_account_assets(
        &self,
        params: QuerySubAccountAssetsParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>>;
    async fn query_sub_account_assets_asset_management(
        &self,
        params: QuerySubAccountAssetsAssetManagementParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>>;
    async fn query_sub_account_futures_asset_transfer_history(
        &self,
        params: QuerySubAccountFuturesAssetTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>>;
    async fn query_sub_account_spot_asset_transfer_history(
        &self,
        params: QuerySubAccountSpotAssetTransferHistoryParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
    >;
    async fn query_sub_account_spot_assets_summary(
        &self,
        params: QuerySubAccountSpotAssetsSummaryParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>>;
    async fn query_universal_transfer_history(
        &self,
        params: QueryUniversalTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>>;
    async fn sub_account_futures_asset_transfer(
        &self,
        params: SubAccountFuturesAssetTransferParams,
    ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>>;
    async fn sub_account_transfer_history(
        &self,
        params: SubAccountTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>>;
    async fn transfer_to_master(
        &self,
        params: TransferToMasterParams,
    ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>>;
    async fn transfer_to_sub_account_of_same_master(
        &self,
        params: TransferToSubAccountOfSameMasterParams,
    ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>>;
    async fn universal_transfer(
        &self,
        params: UniversalTransferParams,
    ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>>;
}

#[derive(Debug, Clone)]
pub struct AssetManagementApiClient {
    configuration: ConfigurationRestApi,
}

impl AssetManagementApiClient {
    pub fn new(configuration: ConfigurationRestApi) -> Self {
        Self { configuration }
    }
}

/// Request parameters for the [`futures_transfer_for_sub_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`futures_transfer_for_sub_account`](#method.futures_transfer_for_sub_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct FuturesTransferForSubAccountParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    /// 1: transfer from subaccount's  spot account to margin account 2: transfer from subaccount's margin account to its spot account
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub r#type: i64,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl FuturesTransferForSubAccountParams {
    /// Create a builder for [`futures_transfer_for_sub_account`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    /// * `r#type` — 1: transfer from subaccount's  spot account to margin account 2: transfer from subaccount's margin account to its spot account
    ///
    #[must_use]
    pub fn builder(
        email: String,
        asset: String,
        amount: rust_decimal::Decimal,
        r#type: i64,
    ) -> FuturesTransferForSubAccountParamsBuilder {
        FuturesTransferForSubAccountParamsBuilder::default()
            .email(email)
            .asset(asset)
            .amount(amount)
            .r#type(r#type)
    }
}
/// Request parameters for the [`get_detail_on_sub_accounts_futures_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_detail_on_sub_accounts_futures_account`](#method.get_detail_on_sub_accounts_futures_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetDetailOnSubAccountsFuturesAccountParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetDetailOnSubAccountsFuturesAccountParams {
    /// Create a builder for [`get_detail_on_sub_accounts_futures_account`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    ///
    #[must_use]
    pub fn builder(email: String) -> GetDetailOnSubAccountsFuturesAccountParamsBuilder {
        GetDetailOnSubAccountsFuturesAccountParamsBuilder::default().email(email)
    }
}
/// Request parameters for the [`get_detail_on_sub_accounts_futures_account_v2`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_detail_on_sub_accounts_futures_account_v2`](#method.get_detail_on_sub_accounts_futures_account_v2).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetDetailOnSubAccountsFuturesAccountV2Params {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    /// 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub futures_type: i64,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetDetailOnSubAccountsFuturesAccountV2Params {
    /// Create a builder for [`get_detail_on_sub_accounts_futures_account_v2`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    /// * `futures_type` — 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    #[must_use]
    pub fn builder(
        email: String,
        futures_type: i64,
    ) -> GetDetailOnSubAccountsFuturesAccountV2ParamsBuilder {
        GetDetailOnSubAccountsFuturesAccountV2ParamsBuilder::default()
            .email(email)
            .futures_type(futures_type)
    }
}
/// Request parameters for the [`get_detail_on_sub_accounts_margin_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_detail_on_sub_accounts_margin_account`](#method.get_detail_on_sub_accounts_margin_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetDetailOnSubAccountsMarginAccountParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetDetailOnSubAccountsMarginAccountParams {
    /// Create a builder for [`get_detail_on_sub_accounts_margin_account`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    ///
    #[must_use]
    pub fn builder(email: String) -> GetDetailOnSubAccountsMarginAccountParamsBuilder {
        GetDetailOnSubAccountsMarginAccountParamsBuilder::default().email(email)
    }
}
/// Request parameters for the [`get_move_position_history_for_sub_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_move_position_history_for_sub_account`](#method.get_move_position_history_for_sub_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetMovePositionHistoryForSubAccountParams {
    ///
    /// The `symbol` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub symbol: String,
    /// Page
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub page: i64,
    ///
    /// The `row` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub row: i64,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetMovePositionHistoryForSubAccountParams {
    /// Create a builder for [`get_move_position_history_for_sub_account`].
    ///
    /// Required parameters:
    ///
    /// * `symbol` — String
    /// * `page` — Page
    /// * `row` — i64
    ///
    #[must_use]
    pub fn builder(
        symbol: String,
        page: i64,
        row: i64,
    ) -> GetMovePositionHistoryForSubAccountParamsBuilder {
        GetMovePositionHistoryForSubAccountParamsBuilder::default()
            .symbol(symbol)
            .page(page)
            .row(row)
    }
}
/// Request parameters for the [`get_sub_account_deposit_address`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_sub_account_deposit_address`](#method.get_sub_account_deposit_address).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetSubAccountDepositAddressParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `coin` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub coin: String,
    /// networks can be found in `GET /sapi/v1/capital/deposit/address`
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub network: Option<String>,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub amount: Option<rust_decimal::Decimal>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetSubAccountDepositAddressParams {
    /// Create a builder for [`get_sub_account_deposit_address`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    /// * `coin` — String
    ///
    #[must_use]
    pub fn builder(email: String, coin: String) -> GetSubAccountDepositAddressParamsBuilder {
        GetSubAccountDepositAddressParamsBuilder::default()
            .email(email)
            .coin(coin)
    }
}
/// Request parameters for the [`get_sub_account_deposit_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_sub_account_deposit_history`](#method.get_sub_account_deposit_history).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetSubAccountDepositHistoryParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `coin` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub coin: Option<String>,
    /// 0(0:pending,6: credited but cannot withdraw,7:Wrong Deposit,8:Waiting User confirm,1:success)
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub status: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    /// default:0
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub offset: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
    ///
    /// The `tx_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub tx_id: Option<String>,
}

impl GetSubAccountDepositHistoryParams {
    /// Create a builder for [`get_sub_account_deposit_history`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    ///
    #[must_use]
    pub fn builder(email: String) -> GetSubAccountDepositHistoryParamsBuilder {
        GetSubAccountDepositHistoryParamsBuilder::default().email(email)
    }
}
/// Request parameters for the [`get_summary_of_sub_accounts_futures_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_summary_of_sub_accounts_futures_account`](#method.get_summary_of_sub_accounts_futures_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetSummaryOfSubAccountsFuturesAccountParams {
    /// Page
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub page: i64,
    /// Limit (Max: 500)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub limit: i64,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetSummaryOfSubAccountsFuturesAccountParams {
    /// Create a builder for [`get_summary_of_sub_accounts_futures_account`].
    ///
    /// Required parameters:
    ///
    /// * `page` — Page
    /// * `limit` — Limit (Max: 500)
    ///
    #[must_use]
    pub fn builder(page: i64, limit: i64) -> GetSummaryOfSubAccountsFuturesAccountParamsBuilder {
        GetSummaryOfSubAccountsFuturesAccountParamsBuilder::default()
            .page(page)
            .limit(limit)
    }
}
/// Request parameters for the [`get_summary_of_sub_accounts_futures_account_v2`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_summary_of_sub_accounts_futures_account_v2`](#method.get_summary_of_sub_accounts_futures_account_v2).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetSummaryOfSubAccountsFuturesAccountV2Params {
    /// 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub futures_type: i64,
    /// Default value: 1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub page: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetSummaryOfSubAccountsFuturesAccountV2Params {
    /// Create a builder for [`get_summary_of_sub_accounts_futures_account_v2`].
    ///
    /// Required parameters:
    ///
    /// * `futures_type` — 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    #[must_use]
    pub fn builder(futures_type: i64) -> GetSummaryOfSubAccountsFuturesAccountV2ParamsBuilder {
        GetSummaryOfSubAccountsFuturesAccountV2ParamsBuilder::default().futures_type(futures_type)
    }
}
/// Request parameters for the [`get_summary_of_sub_accounts_margin_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`get_summary_of_sub_accounts_margin_account`](#method.get_summary_of_sub_accounts_margin_account).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct GetSummaryOfSubAccountsMarginAccountParams {
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl GetSummaryOfSubAccountsMarginAccountParams {
    /// Create a builder for [`get_summary_of_sub_accounts_margin_account`].
    ///
    #[must_use]
    pub fn builder() -> GetSummaryOfSubAccountsMarginAccountParamsBuilder {
        GetSummaryOfSubAccountsMarginAccountParamsBuilder::default()
    }
}
/// Request parameters for the [`margin_transfer_for_sub_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`margin_transfer_for_sub_account`](#method.margin_transfer_for_sub_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct MarginTransferForSubAccountParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    /// 1: transfer from subaccount's  spot account to margin account 2: transfer from subaccount's margin account to its spot account
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub r#type: i64,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl MarginTransferForSubAccountParams {
    /// Create a builder for [`margin_transfer_for_sub_account`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    /// * `r#type` — 1: transfer from subaccount's  spot account to margin account 2: transfer from subaccount's margin account to its spot account
    ///
    #[must_use]
    pub fn builder(
        email: String,
        asset: String,
        amount: rust_decimal::Decimal,
        r#type: i64,
    ) -> MarginTransferForSubAccountParamsBuilder {
        MarginTransferForSubAccountParamsBuilder::default()
            .email(email)
            .asset(asset)
            .amount(amount)
            .r#type(r#type)
    }
}
/// Request parameters for the [`move_position_for_sub_account`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`move_position_for_sub_account`](#method.move_position_for_sub_account).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct MovePositionForSubAccountParams {
    ///
    /// The `from_user_email` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub from_user_email: String,
    ///
    /// The `to_user_email` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub to_user_email: String,
    /// Only support UM
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub product_type: String,
    /// 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
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub order_args: Vec<models::MovePositionForSubAccountOrderArgsParameterInner>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl MovePositionForSubAccountParams {
    /// Create a builder for [`move_position_for_sub_account`].
    ///
    /// Required parameters:
    ///
    /// * `from_user_email` — String
    /// * `to_user_email` — String
    /// * `product_type` — Only support UM
    /// * `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
    ///
    #[must_use]
    pub fn builder(
        from_user_email: String,
        to_user_email: String,
        product_type: String,
        order_args: Vec<models::MovePositionForSubAccountOrderArgsParameterInner>,
    ) -> MovePositionForSubAccountParamsBuilder {
        MovePositionForSubAccountParamsBuilder::default()
            .from_user_email(from_user_email)
            .to_user_email(to_user_email)
            .product_type(product_type)
            .order_args(order_args)
    }
}
/// Request parameters for the [`query_sub_account_assets`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_sub_account_assets`](#method.query_sub_account_assets).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QuerySubAccountAssetsParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QuerySubAccountAssetsParams {
    /// Create a builder for [`query_sub_account_assets`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    ///
    #[must_use]
    pub fn builder(email: String) -> QuerySubAccountAssetsParamsBuilder {
        QuerySubAccountAssetsParamsBuilder::default().email(email)
    }
}
/// Request parameters for the [`query_sub_account_assets_asset_management`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_sub_account_assets_asset_management`](#method.query_sub_account_assets_asset_management).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QuerySubAccountAssetsAssetManagementParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QuerySubAccountAssetsAssetManagementParams {
    /// Create a builder for [`query_sub_account_assets_asset_management`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    ///
    #[must_use]
    pub fn builder(email: String) -> QuerySubAccountAssetsAssetManagementParamsBuilder {
        QuerySubAccountAssetsAssetManagementParamsBuilder::default().email(email)
    }
}
/// Request parameters for the [`query_sub_account_futures_asset_transfer_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_sub_account_futures_asset_transfer_history`](#method.query_sub_account_futures_asset_transfer_history).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QuerySubAccountFuturesAssetTransferHistoryParams {
    /// [Sub-account email](#email-address)
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub email: String,
    /// 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub futures_type: i64,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default value: 1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub page: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QuerySubAccountFuturesAssetTransferHistoryParams {
    /// Create a builder for [`query_sub_account_futures_asset_transfer_history`].
    ///
    /// Required parameters:
    ///
    /// * `email` — [Sub-account email](#email-address)
    /// * `futures_type` — 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    #[must_use]
    pub fn builder(
        email: String,
        futures_type: i64,
    ) -> QuerySubAccountFuturesAssetTransferHistoryParamsBuilder {
        QuerySubAccountFuturesAssetTransferHistoryParamsBuilder::default()
            .email(email)
            .futures_type(futures_type)
    }
}
/// Request parameters for the [`query_sub_account_spot_asset_transfer_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_sub_account_spot_asset_transfer_history`](#method.query_sub_account_spot_asset_transfer_history).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QuerySubAccountSpotAssetTransferHistoryParams {
    ///
    /// The `from_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub from_email: Option<String>,
    ///
    /// The `to_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub to_email: Option<String>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default value: 1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub page: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QuerySubAccountSpotAssetTransferHistoryParams {
    /// Create a builder for [`query_sub_account_spot_asset_transfer_history`].
    ///
    #[must_use]
    pub fn builder() -> QuerySubAccountSpotAssetTransferHistoryParamsBuilder {
        QuerySubAccountSpotAssetTransferHistoryParamsBuilder::default()
    }
}
/// Request parameters for the [`query_sub_account_spot_assets_summary`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_sub_account_spot_assets_summary`](#method.query_sub_account_spot_assets_summary).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QuerySubAccountSpotAssetsSummaryParams {
    /// Managed sub-account email
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub email: Option<String>,
    /// Default value: 1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub page: Option<i64>,
    /// default 10, max 20
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub size: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QuerySubAccountSpotAssetsSummaryParams {
    /// Create a builder for [`query_sub_account_spot_assets_summary`].
    ///
    #[must_use]
    pub fn builder() -> QuerySubAccountSpotAssetsSummaryParamsBuilder {
        QuerySubAccountSpotAssetsSummaryParamsBuilder::default()
    }
}
/// Request parameters for the [`query_universal_transfer_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`query_universal_transfer_history`](#method.query_universal_transfer_history).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct QueryUniversalTransferHistoryParams {
    ///
    /// The `from_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub from_email: Option<String>,
    ///
    /// The `to_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub to_email: Option<String>,
    ///
    /// The `client_tran_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub client_tran_id: Option<String>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default value: 1
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub page: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl QueryUniversalTransferHistoryParams {
    /// Create a builder for [`query_universal_transfer_history`].
    ///
    #[must_use]
    pub fn builder() -> QueryUniversalTransferHistoryParamsBuilder {
        QueryUniversalTransferHistoryParamsBuilder::default()
    }
}
/// Request parameters for the [`sub_account_futures_asset_transfer`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`sub_account_futures_asset_transfer`](#method.sub_account_futures_asset_transfer).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SubAccountFuturesAssetTransferParams {
    ///
    /// The `from_email` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub from_email: String,
    ///
    /// The `to_email` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub to_email: String,
    /// 1:USDT-margined Futures，2: Coin-margined Futures
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub futures_type: i64,
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl SubAccountFuturesAssetTransferParams {
    /// Create a builder for [`sub_account_futures_asset_transfer`].
    ///
    /// Required parameters:
    ///
    /// * `from_email` — String
    /// * `to_email` — String
    /// * `futures_type` — 1:USDT-margined Futures，2: Coin-margined Futures
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    ///
    #[must_use]
    pub fn builder(
        from_email: String,
        to_email: String,
        futures_type: i64,
        asset: String,
        amount: rust_decimal::Decimal,
    ) -> SubAccountFuturesAssetTransferParamsBuilder {
        SubAccountFuturesAssetTransferParamsBuilder::default()
            .from_email(from_email)
            .to_email(to_email)
            .futures_type(futures_type)
            .asset(asset)
            .amount(amount)
    }
}
/// Request parameters for the [`sub_account_transfer_history`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`sub_account_transfer_history`](#method.sub_account_transfer_history).
#[derive(Clone, Debug, Builder, Default)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct SubAccountTransferHistoryParams {
    /// If not sent, result of all assets will be returned
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub asset: Option<String>,
    /// 1: transfer in, 2: transfer out
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub r#type: Option<i64>,
    ///
    /// The `start_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub start_time: Option<i64>,
    ///
    /// The `end_time` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub end_time: Option<i64>,
    /// Default value: 1, Max value: 200
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub limit: Option<i64>,
    /// Default `False`, return PROCESS and SUCCESS status history; If `True`,return PROCESS and SUCCESS and FAILURE status history
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub return_fail_history: Option<bool>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl SubAccountTransferHistoryParams {
    /// Create a builder for [`sub_account_transfer_history`].
    ///
    #[must_use]
    pub fn builder() -> SubAccountTransferHistoryParamsBuilder {
        SubAccountTransferHistoryParamsBuilder::default()
    }
}
/// Request parameters for the [`transfer_to_master`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`transfer_to_master`](#method.transfer_to_master).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct TransferToMasterParams {
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl TransferToMasterParams {
    /// Create a builder for [`transfer_to_master`].
    ///
    /// Required parameters:
    ///
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    ///
    #[must_use]
    pub fn builder(asset: String, amount: rust_decimal::Decimal) -> TransferToMasterParamsBuilder {
        TransferToMasterParamsBuilder::default()
            .asset(asset)
            .amount(amount)
    }
}
/// Request parameters for the [`transfer_to_sub_account_of_same_master`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`transfer_to_sub_account_of_same_master`](#method.transfer_to_sub_account_of_same_master).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct TransferToSubAccountOfSameMasterParams {
    ///
    /// The `to_email` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub to_email: String,
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl TransferToSubAccountOfSameMasterParams {
    /// Create a builder for [`transfer_to_sub_account_of_same_master`].
    ///
    /// Required parameters:
    ///
    /// * `to_email` — String
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    ///
    #[must_use]
    pub fn builder(
        to_email: String,
        asset: String,
        amount: rust_decimal::Decimal,
    ) -> TransferToSubAccountOfSameMasterParamsBuilder {
        TransferToSubAccountOfSameMasterParamsBuilder::default()
            .to_email(to_email)
            .asset(asset)
            .amount(amount)
    }
}
/// Request parameters for the [`universal_transfer`] operation.
///
/// This struct holds all of the inputs you can pass when calling
/// [`universal_transfer`](#method.universal_transfer).
#[derive(Clone, Debug, Builder)]
#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
pub struct UniversalTransferParams {
    /// "`SPOT","USDT_FUTURE","COIN_FUTURE","MARGIN"(Cross),"ISOLATED_MARGIN`"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub from_account_type: String,
    /// "`SPOT","USDT_FUTURE","COIN_FUTURE","MARGIN"(Cross),"ISOLATED_MARGIN`"
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub to_account_type: String,
    ///
    /// The `asset` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub asset: String,
    ///
    /// The `amount` parameter.
    ///
    /// This field is **required.
    #[builder(setter(into))]
    pub amount: rust_decimal::Decimal,
    ///
    /// The `from_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub from_email: Option<String>,
    ///
    /// The `to_email` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub to_email: Option<String>,
    ///
    /// The `client_tran_id` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub client_tran_id: Option<String>,
    /// Only supported under `ISOLATED_MARGIN` type
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub symbol: Option<String>,
    ///
    /// The `recv_window` parameter.
    ///
    /// This field is **optional.
    #[builder(setter(into), default)]
    pub recv_window: Option<i64>,
}

impl UniversalTransferParams {
    /// Create a builder for [`universal_transfer`].
    ///
    /// Required parameters:
    ///
    /// * `from_account_type` — \"SPOT\",\"`USDT_FUTURE`\",\"`COIN_FUTURE`\",\"MARGIN\"(Cross),\"`ISOLATED_MARGIN`\"
    /// * `to_account_type` — \"SPOT\",\"`USDT_FUTURE`\",\"`COIN_FUTURE`\",\"MARGIN\"(Cross),\"`ISOLATED_MARGIN`\"
    /// * `asset` — String
    /// * `amount` — `rust_decimal::Decimal`
    ///
    #[must_use]
    pub fn builder(
        from_account_type: String,
        to_account_type: String,
        asset: String,
        amount: rust_decimal::Decimal,
    ) -> UniversalTransferParamsBuilder {
        UniversalTransferParamsBuilder::default()
            .from_account_type(from_account_type)
            .to_account_type(to_account_type)
            .asset(asset)
            .amount(amount)
    }
}

#[async_trait]
impl AssetManagementApi for AssetManagementApiClient {
    async fn futures_transfer_for_sub_account(
        &self,
        params: FuturesTransferForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>> {
        let FuturesTransferForSubAccountParams {
            email,
            asset,
            amount,
            r#type,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        query_params.insert("type".to_string(), json!(r#type));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::FuturesTransferForSubAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/transfer",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_detail_on_sub_accounts_futures_account(
        &self,
        params: GetDetailOnSubAccountsFuturesAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>> {
        let GetDetailOnSubAccountsFuturesAccountParams { email, recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetDetailOnSubAccountsFuturesAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/account",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_detail_on_sub_accounts_futures_account_v2(
        &self,
        params: GetDetailOnSubAccountsFuturesAccountV2Params,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>
    {
        let GetDetailOnSubAccountsFuturesAccountV2Params {
            email,
            futures_type,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        query_params.insert("futuresType".to_string(), json!(futures_type));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetDetailOnSubAccountsFuturesAccountV2Response>(
            &self.configuration,
            "/sapi/v2/sub-account/futures/account",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_detail_on_sub_accounts_margin_account(
        &self,
        params: GetDetailOnSubAccountsMarginAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>> {
        let GetDetailOnSubAccountsMarginAccountParams { email, recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetDetailOnSubAccountsMarginAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/margin/account",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_move_position_history_for_sub_account(
        &self,
        params: GetMovePositionHistoryForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>> {
        let GetMovePositionHistoryForSubAccountParams {
            symbol,
            page,
            row,
            start_time,
            end_time,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("symbol".to_string(), json!(symbol));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        query_params.insert("page".to_string(), json!(page));

        query_params.insert("row".to_string(), json!(row));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetMovePositionHistoryForSubAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/move-position",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_sub_account_deposit_address(
        &self,
        params: GetSubAccountDepositAddressParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>> {
        let GetSubAccountDepositAddressParams {
            email,
            coin,
            network,
            amount,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        query_params.insert("coin".to_string(), json!(coin));

        if let Some(rw) = network {
            query_params.insert("network".to_string(), json!(rw));
        }

        if let Some(rw) = amount {
            query_params.insert("amount".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetSubAccountDepositAddressResponse>(
            &self.configuration,
            "/sapi/v1/capital/deposit/subAddress",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_sub_account_deposit_history(
        &self,
        params: GetSubAccountDepositHistoryParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>
    {
        let GetSubAccountDepositHistoryParams {
            email,
            coin,
            status,
            start_time,
            end_time,
            limit,
            offset,
            recv_window,
            tx_id,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        if let Some(rw) = coin {
            query_params.insert("coin".to_string(), json!(rw));
        }

        if let Some(rw) = status {
            query_params.insert("status".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = offset {
            query_params.insert("offset".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        if let Some(rw) = tx_id {
            query_params.insert("txId".to_string(), json!(rw));
        }

        send_request::<Vec<models::GetSubAccountDepositHistoryResponseInner>>(
            &self.configuration,
            "/sapi/v1/capital/deposit/subHisrec",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_summary_of_sub_accounts_futures_account(
        &self,
        params: GetSummaryOfSubAccountsFuturesAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>
    {
        let GetSummaryOfSubAccountsFuturesAccountParams {
            page,
            limit,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("page".to_string(), json!(page));

        query_params.insert("limit".to_string(), json!(limit));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetSummaryOfSubAccountsFuturesAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/accountSummary",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_summary_of_sub_accounts_futures_account_v2(
        &self,
        params: GetSummaryOfSubAccountsFuturesAccountV2Params,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>
    {
        let GetSummaryOfSubAccountsFuturesAccountV2Params {
            futures_type,
            page,
            limit,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("futuresType".to_string(), json!(futures_type));

        if let Some(rw) = page {
            query_params.insert("page".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetSummaryOfSubAccountsFuturesAccountV2Response>(
            &self.configuration,
            "/sapi/v2/sub-account/futures/accountSummary",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn get_summary_of_sub_accounts_margin_account(
        &self,
        params: GetSummaryOfSubAccountsMarginAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>> {
        let GetSummaryOfSubAccountsMarginAccountParams { recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::GetSummaryOfSubAccountsMarginAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/margin/accountSummary",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn margin_transfer_for_sub_account(
        &self,
        params: MarginTransferForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>> {
        let MarginTransferForSubAccountParams {
            email,
            asset,
            amount,
            r#type,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        query_params.insert("type".to_string(), json!(r#type));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::MarginTransferForSubAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/margin/transfer",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn move_position_for_sub_account(
        &self,
        params: MovePositionForSubAccountParams,
    ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>> {
        let MovePositionForSubAccountParams {
            from_user_email,
            to_user_email,
            product_type,
            order_args,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("fromUserEmail".to_string(), json!(from_user_email));

        query_params.insert("toUserEmail".to_string(), json!(to_user_email));

        query_params.insert("productType".to_string(), json!(product_type));

        query_params.insert("orderArgs".to_string(), json!(order_args));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::MovePositionForSubAccountResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/move-position",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_sub_account_assets(
        &self,
        params: QuerySubAccountAssetsParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>> {
        let QuerySubAccountAssetsParams { email, recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::QuerySubAccountAssetsResponse>(
            &self.configuration,
            "/sapi/v3/sub-account/assets",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_sub_account_assets_asset_management(
        &self,
        params: QuerySubAccountAssetsAssetManagementParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>> {
        let QuerySubAccountAssetsAssetManagementParams { email, recv_window } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::QuerySubAccountAssetsAssetManagementResponse>(
            &self.configuration,
            "/sapi/v4/sub-account/assets",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_sub_account_futures_asset_transfer_history(
        &self,
        params: QuerySubAccountFuturesAssetTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>>
    {
        let QuerySubAccountFuturesAssetTransferHistoryParams {
            email,
            futures_type,
            start_time,
            end_time,
            page,
            limit,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("email".to_string(), json!(email));

        query_params.insert("futuresType".to_string(), json!(futures_type));

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = page {
            query_params.insert("page".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::QuerySubAccountFuturesAssetTransferHistoryResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/internalTransfer",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_sub_account_spot_asset_transfer_history(
        &self,
        params: QuerySubAccountSpotAssetTransferHistoryParams,
    ) -> anyhow::Result<
        RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
    > {
        let QuerySubAccountSpotAssetTransferHistoryParams {
            from_email,
            to_email,
            start_time,
            end_time,
            page,
            limit,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = from_email {
            query_params.insert("fromEmail".to_string(), json!(rw));
        }

        if let Some(rw) = to_email {
            query_params.insert("toEmail".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = page {
            query_params.insert("page".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>(
            &self.configuration,
            "/sapi/v1/sub-account/sub/transfer/history",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_sub_account_spot_assets_summary(
        &self,
        params: QuerySubAccountSpotAssetsSummaryParams,
    ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>> {
        let QuerySubAccountSpotAssetsSummaryParams {
            email,
            page,
            size,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = email {
            query_params.insert("email".to_string(), json!(rw));
        }

        if let Some(rw) = page {
            query_params.insert("page".to_string(), json!(rw));
        }

        if let Some(rw) = size {
            query_params.insert("size".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::QuerySubAccountSpotAssetsSummaryResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/spotSummary",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn query_universal_transfer_history(
        &self,
        params: QueryUniversalTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>> {
        let QueryUniversalTransferHistoryParams {
            from_email,
            to_email,
            client_tran_id,
            start_time,
            end_time,
            page,
            limit,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = from_email {
            query_params.insert("fromEmail".to_string(), json!(rw));
        }

        if let Some(rw) = to_email {
            query_params.insert("toEmail".to_string(), json!(rw));
        }

        if let Some(rw) = client_tran_id {
            query_params.insert("clientTranId".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = page {
            query_params.insert("page".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::QueryUniversalTransferHistoryResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/universalTransfer",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn sub_account_futures_asset_transfer(
        &self,
        params: SubAccountFuturesAssetTransferParams,
    ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>> {
        let SubAccountFuturesAssetTransferParams {
            from_email,
            to_email,
            futures_type,
            asset,
            amount,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("fromEmail".to_string(), json!(from_email));

        query_params.insert("toEmail".to_string(), json!(to_email));

        query_params.insert("futuresType".to_string(), json!(futures_type));

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::SubAccountFuturesAssetTransferResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/futures/internalTransfer",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn sub_account_transfer_history(
        &self,
        params: SubAccountTransferHistoryParams,
    ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>> {
        let SubAccountTransferHistoryParams {
            asset,
            r#type,
            start_time,
            end_time,
            limit,
            return_fail_history,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = asset {
            query_params.insert("asset".to_string(), json!(rw));
        }

        if let Some(rw) = r#type {
            query_params.insert("type".to_string(), json!(rw));
        }

        if let Some(rw) = start_time {
            query_params.insert("startTime".to_string(), json!(rw));
        }

        if let Some(rw) = end_time {
            query_params.insert("endTime".to_string(), json!(rw));
        }

        if let Some(rw) = limit {
            query_params.insert("limit".to_string(), json!(rw));
        }

        if let Some(rw) = return_fail_history {
            query_params.insert("returnFailHistory".to_string(), json!(rw));
        }

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<Vec<models::SubAccountTransferHistoryResponseInner>>(
            &self.configuration,
            "/sapi/v1/sub-account/transfer/subUserHistory",
            reqwest::Method::GET,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn transfer_to_master(
        &self,
        params: TransferToMasterParams,
    ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>> {
        let TransferToMasterParams {
            asset,
            amount,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::TransferToMasterResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/transfer/subToMaster",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn transfer_to_sub_account_of_same_master(
        &self,
        params: TransferToSubAccountOfSameMasterParams,
    ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>> {
        let TransferToSubAccountOfSameMasterParams {
            to_email,
            asset,
            amount,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        query_params.insert("toEmail".to_string(), json!(to_email));

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::TransferToSubAccountOfSameMasterResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/transfer/subToSub",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }

    async fn universal_transfer(
        &self,
        params: UniversalTransferParams,
    ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>> {
        let UniversalTransferParams {
            from_account_type,
            to_account_type,
            asset,
            amount,
            from_email,
            to_email,
            client_tran_id,
            symbol,
            recv_window,
        } = params;

        let mut query_params = BTreeMap::new();
        let body_params = BTreeMap::new();

        if let Some(rw) = from_email {
            query_params.insert("fromEmail".to_string(), json!(rw));
        }

        if let Some(rw) = to_email {
            query_params.insert("toEmail".to_string(), json!(rw));
        }

        query_params.insert("fromAccountType".to_string(), json!(from_account_type));

        query_params.insert("toAccountType".to_string(), json!(to_account_type));

        if let Some(rw) = client_tran_id {
            query_params.insert("clientTranId".to_string(), json!(rw));
        }

        if let Some(rw) = symbol {
            query_params.insert("symbol".to_string(), json!(rw));
        }

        query_params.insert("asset".to_string(), json!(asset));

        query_params.insert("amount".to_string(), json!(amount));

        if let Some(rw) = recv_window {
            query_params.insert("recvWindow".to_string(), json!(rw));
        }

        send_request::<models::UniversalTransferResponse>(
            &self.configuration,
            "/sapi/v1/sub-account/universalTransfer",
            reqwest::Method::POST,
            query_params,
            body_params,
            if HAS_TIME_UNIT {
                self.configuration.time_unit
            } else {
                None
            },
            true,
        )
        .await
    }
}

#[cfg(all(test, feature = "sub_account"))]
mod tests {
    use super::*;
    use crate::TOKIO_SHARED_RT;
    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
    use async_trait::async_trait;
    use std::collections::HashMap;

    struct DummyRestApiResponse<T> {
        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
        status: u16,
        headers: HashMap<String, String>,
        rate_limits: Option<Vec<RestApiRateLimit>>,
    }

    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
        fn from(dummy: DummyRestApiResponse<T>) -> Self {
            Self {
                data_fn: dummy.inner,
                status: dummy.status,
                headers: dummy.headers,
                rate_limits: dummy.rate_limits,
            }
        }
    }

    struct MockAssetManagementApiClient {
        force_error: bool,
    }

    #[async_trait]
    impl AssetManagementApi for MockAssetManagementApiClient {
        async fn futures_transfer_for_sub_account(
            &self,
            _params: FuturesTransferForSubAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::FuturesTransferForSubAccountResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let dummy_response: models::FuturesTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::FuturesTransferForSubAccountResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_detail_on_sub_accounts_futures_account(
            &self,
            _params: GetDetailOnSubAccountsFuturesAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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();
            let dummy_response: models::GetDetailOnSubAccountsFuturesAccountResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetDetailOnSubAccountsFuturesAccountResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_detail_on_sub_accounts_futures_account_v2(
            &self,
            _params: GetDetailOnSubAccountsFuturesAccountV2Params,
        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsFuturesAccountV2Response>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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();
            let dummy_response: models::GetDetailOnSubAccountsFuturesAccountV2Response =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_detail_on_sub_accounts_margin_account(
            &self,
            _params: GetDetailOnSubAccountsMarginAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::GetDetailOnSubAccountsMarginAccountResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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"},{"asset":"BNB","borrowed":"201.66666672","free":"2346.50000000","interest":"0.00000000","locked":"0.00000000","netAsset":"2144.83333328"},{"asset":"ETH","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"},{"asset":"USDT","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"}]}"#).unwrap();
            let dummy_response: models::GetDetailOnSubAccountsMarginAccountResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetDetailOnSubAccountsMarginAccountResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_move_position_history_for_sub_account(
            &self,
            _params: GetMovePositionHistoryForSubAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::GetMovePositionHistoryForSubAccountResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"testTo1@google.com","productType":"UM","symbol":"BTCUSDT","price":"97100.00000000","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041627000},{"fromUserEmail":"testFrom2@google.com","toUserEmail":"testTo2@google.com","productType":"UM","symbol":"BTCUSDT","price":"97108.62068889","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041959000}]}"#).unwrap();
            let dummy_response: models::GetMovePositionHistoryForSubAccountResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetMovePositionHistoryForSubAccountResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_sub_account_deposit_address(
            &self,
            _params: GetSubAccountDepositAddressParams,
        ) -> anyhow::Result<RestApiResponse<models::GetSubAccountDepositAddressResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap();
            let dummy_response: models::GetSubAccountDepositAddressResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::GetSubAccountDepositAddressResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_sub_account_deposit_history(
            &self,
            _params: GetSubAccountDepositHistoryParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::GetSubAccountDepositHistoryResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap();
            let dummy_response: Vec<models::GetSubAccountDepositHistoryResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_summary_of_sub_accounts_futures_account(
            &self,
            _params: GetSummaryOfSubAccountsFuturesAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"USD"}]}"#).unwrap();
            let dummy_response: models::GetSummaryOfSubAccountsFuturesAccountResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_summary_of_sub_accounts_futures_account_v2(
            &self,
            _params: GetSummaryOfSubAccountsFuturesAccountV2Params,
        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsFuturesAccountV2Response>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","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"},{"email":"345@test.com","totalMarginBalance":"0.90575887","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"BTC"}]}}"#).unwrap();
            let dummy_response: models::GetSummaryOfSubAccountsFuturesAccountV2Response =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn get_summary_of_sub_accounts_margin_account(
            &self,
            _params: GetSummaryOfSubAccountsMarginAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::GetSummaryOfSubAccountsMarginAccountResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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"},{"email":"345@test.com","totalAssetOfBtc":"2.22222222","totalLiabilityOfBtc":"1.00000001","totalNetAssetOfBtc":"1.22222221"}]}"#).unwrap();
            let dummy_response: models::GetSummaryOfSubAccountsMarginAccountResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::GetSummaryOfSubAccountsMarginAccountResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn margin_transfer_for_sub_account(
            &self,
            _params: MarginTransferForSubAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::MarginTransferForSubAccountResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let dummy_response: models::MarginTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::MarginTransferForSubAccountResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn move_position_for_sub_account(
            &self,
            _params: MovePositionForSubAccountParams,
        ) -> anyhow::Result<RestApiResponse<models::MovePositionForSubAccountResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"1testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.0011","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap();
            let dummy_response: models::MovePositionForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::MovePositionForSubAccountResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_sub_account_assets(
            &self,
            _params: QuerySubAccountAssetsParams,
        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":10000,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BNB","free":10003,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BTC","free":11467.6399,"locked":0},{"freeze":0,"withdrawing":0,"asset":"ETH","free":10004.995,"locked":0},{"freeze":0,"withdrawing":0,"asset":"USDT","free":11652.14213,"locked":0}]}"#).unwrap();
            let dummy_response: models::QuerySubAccountAssetsResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::QuerySubAccountAssetsResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_sub_account_assets_asset_management(
            &self,
            _params: QuerySubAccountAssetsAssetManagementParams,
        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountAssetsAssetManagementResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BNB","free":"10003","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BTC","free":"11467.6399","locked":"0"}]}"#).unwrap();
            let dummy_response: models::QuerySubAccountAssetsAssetManagementResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::QuerySubAccountAssetsAssetManagementResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_sub_account_futures_asset_transfer_history(
            &self,
            _params: QuerySubAccountFuturesAssetTransferHistoryParams,
        ) -> anyhow::Result<
            RestApiResponse<models::QuerySubAccountFuturesAssetTransferHistoryResponse>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","tranId":11631474902,"time":1544433328000}]}"#).unwrap();
            let dummy_response: models::QuerySubAccountFuturesAssetTransferHistoryResponse =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_sub_account_spot_asset_transfer_history(
            &self,
            _params: QuerySubAccountSpotAssetTransferHistoryParams,
        ) -> anyhow::Result<
            RestApiResponse<Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>>,
        > {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","status":"SUCCESS","tranId":6489938713,"time":1544433328000}]"#).unwrap();
            let dummy_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_sub_account_spot_assets_summary(
            &self,
            _params: QuerySubAccountSpotAssetsSummaryParams,
        ) -> anyhow::Result<RestApiResponse<models::QuerySubAccountSpotAssetsSummaryResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"},{"email":"test456@test.com","totalAsset":"0.00000000"}]}"#).unwrap();
            let dummy_response: models::QuerySubAccountSpotAssetsSummaryResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn query_universal_transfer_history(
            &self,
            _params: QueryUniversalTransferHistoryParams,
        ) -> anyhow::Result<RestApiResponse<models::QueryUniversalTransferHistoryResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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();
            let dummy_response: models::QueryUniversalTransferHistoryResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::QueryUniversalTransferHistoryResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn sub_account_futures_asset_transfer(
            &self,
            _params: SubAccountFuturesAssetTransferParams,
        ) -> anyhow::Result<RestApiResponse<models::SubAccountFuturesAssetTransferResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value =
                serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#).unwrap();
            let dummy_response: models::SubAccountFuturesAssetTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn sub_account_transfer_history(
            &self,
            _params: SubAccountTransferHistoryParams,
        ) -> anyhow::Result<RestApiResponse<Vec<models::SubAccountTransferHistoryResponseInner>>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            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},{"counterParty":"subAccount","email":"sub2@test.com","type":1,"asset":"ETH","qty":"2","fromAccountType":"SPOT","toAccountType":"COIN_FUTURE","status":"SUCCESS","tranId":11798829519,"time":1544433326000}]"#).unwrap();
            let dummy_response: Vec<models::SubAccountTransferHistoryResponseInner> =
                serde_json::from_value(resp_json.clone()).expect(
                    "should parse into Vec<models::SubAccountTransferHistoryResponseInner>",
                );

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn transfer_to_master(
            &self,
            _params: TransferToMasterParams,
        ) -> anyhow::Result<RestApiResponse<models::TransferToMasterResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let dummy_response: models::TransferToMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToMasterResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn transfer_to_sub_account_of_same_master(
            &self,
            _params: TransferToSubAccountOfSameMasterParams,
        ) -> anyhow::Result<RestApiResponse<models::TransferToSubAccountOfSameMasterResponse>>
        {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let dummy_response: models::TransferToSubAccountOfSameMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }

        async fn universal_transfer(
            &self,
            _params: UniversalTransferParams,
        ) -> anyhow::Result<RestApiResponse<models::UniversalTransferResponse>> {
            if self.force_error {
                return Err(ConnectorError::ConnectorClientError {
                    msg: "ResponseError".to_string(),
                    code: None,
                }
                .into());
            }

            let resp_json: Value =
                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#).unwrap();
            let dummy_response: models::UniversalTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::UniversalTransferResponse");

            let dummy = DummyRestApiResponse {
                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
                status: 200,
                headers: HashMap::new(),
                rate_limits: None,
            };

            Ok(dummy.into())
        }
    }

    #[test]
    fn futures_transfer_for_sub_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = FuturesTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::FuturesTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::FuturesTransferForSubAccountResponse");

            let resp = client
                .futures_transfer_for_sub_account(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn futures_transfer_for_sub_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = FuturesTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::FuturesTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::FuturesTransferForSubAccountResponse");

            let resp = client
                .futures_transfer_for_sub_account(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn futures_transfer_for_sub_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = FuturesTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .build()
            .unwrap();

            match client.futures_transfer_for_sub_account(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsFuturesAccountParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();

            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();
            let expected_response : models::GetDetailOnSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountResponse");

            let resp = client.get_detail_on_sub_accounts_futures_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsFuturesAccountParams::builder("sub-account-email@email.com".to_string(),).recv_window(5000).build().unwrap();

            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();
            let expected_response : models::GetDetailOnSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountResponse");

            let resp = client.get_detail_on_sub_accounts_futures_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetDetailOnSubAccountsFuturesAccountParams::builder(
                "sub-account-email@email.com".to_string(),
            )
            .build()
            .unwrap();

            match client
                .get_detail_on_sub_accounts_futures_account(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_v2_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder("sub-account-email@email.com".to_string(),789,).build().unwrap();

            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();
            let expected_response : models::GetDetailOnSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response");

            let resp = client.get_detail_on_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_v2_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder("sub-account-email@email.com".to_string(),789,).recv_window(5000).build().unwrap();

            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();
            let expected_response : models::GetDetailOnSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsFuturesAccountV2Response");

            let resp = client.get_detail_on_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_futures_account_v2_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetDetailOnSubAccountsFuturesAccountV2Params::builder(
                "sub-account-email@email.com".to_string(),
                789,
            )
            .build()
            .unwrap();

            match client
                .get_detail_on_sub_accounts_futures_account_v2(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_margin_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsMarginAccountParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();

            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"},{"asset":"BNB","borrowed":"201.66666672","free":"2346.50000000","interest":"0.00000000","locked":"0.00000000","netAsset":"2144.83333328"},{"asset":"ETH","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"},{"asset":"USDT","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"}]}"#).unwrap();
            let expected_response : models::GetDetailOnSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsMarginAccountResponse");

            let resp = client.get_detail_on_sub_accounts_margin_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_margin_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetDetailOnSubAccountsMarginAccountParams::builder("sub-account-email@email.com".to_string(),).recv_window(5000).build().unwrap();

            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"},{"asset":"BNB","borrowed":"201.66666672","free":"2346.50000000","interest":"0.00000000","locked":"0.00000000","netAsset":"2144.83333328"},{"asset":"ETH","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"},{"asset":"USDT","borrowed":"0.00000000","free":"0.00000000","interest":"0.00000000","locked":"0.00000000","netAsset":"0.00000000"}]}"#).unwrap();
            let expected_response : models::GetDetailOnSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetDetailOnSubAccountsMarginAccountResponse");

            let resp = client.get_detail_on_sub_accounts_margin_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_detail_on_sub_accounts_margin_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetDetailOnSubAccountsMarginAccountParams::builder(
                "sub-account-email@email.com".to_string(),
            )
            .build()
            .unwrap();

            match client
                .get_detail_on_sub_accounts_margin_account(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_move_position_history_for_sub_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetMovePositionHistoryForSubAccountParams::builder("symbol_example".to_string(),789,789,).build().unwrap();

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"testTo1@google.com","productType":"UM","symbol":"BTCUSDT","price":"97100.00000000","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041627000},{"fromUserEmail":"testFrom2@google.com","toUserEmail":"testTo2@google.com","productType":"UM","symbol":"BTCUSDT","price":"97108.62068889","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041959000}]}"#).unwrap();
            let expected_response : models::GetMovePositionHistoryForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetMovePositionHistoryForSubAccountResponse");

            let resp = client.get_move_position_history_for_sub_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_move_position_history_for_sub_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetMovePositionHistoryForSubAccountParams::builder("symbol_example".to_string(),789,789,).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"testTo1@google.com","productType":"UM","symbol":"BTCUSDT","price":"97100.00000000","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041627000},{"fromUserEmail":"testFrom2@google.com","toUserEmail":"testTo2@google.com","productType":"UM","symbol":"BTCUSDT","price":"97108.62068889","quantity":"0.00100000","positionSide":"BOTH","side":"SELL","timeStamp":1740041959000}]}"#).unwrap();
            let expected_response : models::GetMovePositionHistoryForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetMovePositionHistoryForSubAccountResponse");

            let resp = client.get_move_position_history_for_sub_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_move_position_history_for_sub_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetMovePositionHistoryForSubAccountParams::builder(
                "symbol_example".to_string(),
                789,
                789,
            )
            .build()
            .unwrap();

            match client
                .get_move_position_history_for_sub_account(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_sub_account_deposit_address_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSubAccountDepositAddressParams::builder("sub-account-email@email.com".to_string(),"coin_example".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap();
            let expected_response : models::GetSubAccountDepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSubAccountDepositAddressResponse");

            let resp = client.get_sub_account_deposit_address(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_sub_account_deposit_address_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSubAccountDepositAddressParams::builder("sub-account-email@email.com".to_string(),"coin_example".to_string(),).network("network_example".to_string()).amount(dec!(1.0)).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"address":"TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV","coin":"USDT","tag":"","url":"https://tronscan.org/#/address/TDunhSa7jkTNuKrusUTU1MUHtqXoBPKETV"}"#).unwrap();
            let expected_response : models::GetSubAccountDepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSubAccountDepositAddressResponse");

            let resp = client.get_sub_account_deposit_address(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_sub_account_deposit_address_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetSubAccountDepositAddressParams::builder(
                "sub-account-email@email.com".to_string(),
                "coin_example".to_string(),
            )
            .build()
            .unwrap();

            match client.get_sub_account_deposit_address(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_sub_account_deposit_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSubAccountDepositHistoryParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();

            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},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap();
            let expected_response : Vec<models::GetSubAccountDepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>");

            let resp = client.get_sub_account_deposit_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_sub_account_deposit_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSubAccountDepositHistoryParams::builder("sub-account-email@email.com".to_string(),).coin("coin_example".to_string()).status(789).start_time(1623319461670).end_time(1641782889000).limit(1).offset(0).recv_window(5000).tx_id("1".to_string()).build().unwrap();

            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},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0}]"#).unwrap();
            let expected_response : Vec<models::GetSubAccountDepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetSubAccountDepositHistoryResponseInner>");

            let resp = client.get_sub_account_deposit_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_sub_account_deposit_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetSubAccountDepositHistoryParams::builder(
                "sub-account-email@email.com".to_string(),
            )
            .build()
            .unwrap();

            match client.get_sub_account_deposit_history(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(789,789,).build().unwrap();

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"USD"}]}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse");

            let resp = client.get_summary_of_sub_accounts_futures_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(789,789,).recv_window(5000).build().unwrap();

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"USD"}]}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountResponse");

            let resp = client.get_summary_of_sub_accounts_futures_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetSummaryOfSubAccountsFuturesAccountParams::builder(789, 789)
                .build()
                .unwrap();

            match client
                .get_summary_of_sub_accounts_futures_account(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_v2_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(789,).build().unwrap();

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","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"},{"email":"345@test.com","totalMarginBalance":"0.90575887","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"BTC"}]}}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response");

            let resp = client.get_summary_of_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_v2_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(789,).page(1).limit(1).recv_window(5000).build().unwrap();

            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"},{"email":"345@test.com","totalInitialMargin":"0.83137400","totalMaintenanceMargin":"0.41568700","totalMarginBalance":"0.90575887","totalOpenOrderInitialMargin":"0.00000000","totalPositionInitialMargin":"0.83137400","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","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"},{"email":"345@test.com","totalMarginBalance":"0.90575887","totalUnrealizedProfit":"0.03219710","totalWalletBalance":"0.87356177","asset":"BTC"}]}}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsFuturesAccountV2Response = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsFuturesAccountV2Response");

            let resp = client.get_summary_of_sub_accounts_futures_account_v2(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_futures_account_v2_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetSummaryOfSubAccountsFuturesAccountV2Params::builder(789)
                .build()
                .unwrap();

            match client
                .get_summary_of_sub_accounts_futures_account_v2(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_margin_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsMarginAccountParams::builder().build().unwrap();

            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"},{"email":"345@test.com","totalAssetOfBtc":"2.22222222","totalLiabilityOfBtc":"1.00000001","totalNetAssetOfBtc":"1.22222221"}]}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsMarginAccountResponse");

            let resp = client.get_summary_of_sub_accounts_margin_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_margin_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = GetSummaryOfSubAccountsMarginAccountParams::builder().recv_window(5000).build().unwrap();

            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"},{"email":"345@test.com","totalAssetOfBtc":"2.22222222","totalLiabilityOfBtc":"1.00000001","totalNetAssetOfBtc":"1.22222221"}]}"#).unwrap();
            let expected_response : models::GetSummaryOfSubAccountsMarginAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetSummaryOfSubAccountsMarginAccountResponse");

            let resp = client.get_summary_of_sub_accounts_margin_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn get_summary_of_sub_accounts_margin_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = GetSummaryOfSubAccountsMarginAccountParams::builder()
                .build()
                .unwrap();

            match client
                .get_summary_of_sub_accounts_margin_account(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn margin_transfer_for_sub_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = MarginTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::MarginTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::MarginTransferForSubAccountResponse");

            let resp = client
                .margin_transfer_for_sub_account(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn margin_transfer_for_sub_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = MarginTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::MarginTransferForSubAccountResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::MarginTransferForSubAccountResponse");

            let resp = client
                .margin_transfer_for_sub_account(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn margin_transfer_for_sub_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = MarginTransferForSubAccountParams::builder(
                "sub-account-email@email.com".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
                789,
            )
            .build()
            .unwrap();

            match client.margin_transfer_for_sub_account(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn move_position_for_sub_account_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = MovePositionForSubAccountParams::builder("from_user_email_example".to_string(),"to_user_email_example".to_string(),"product_type_example".to_string(),vec![],).build().unwrap();

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"1testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.0011","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap();
            let expected_response : models::MovePositionForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MovePositionForSubAccountResponse");

            let resp = client.move_position_for_sub_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn move_position_for_sub_account_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = MovePositionForSubAccountParams::builder("from_user_email_example".to_string(),"to_user_email_example".to_string(),"product_type_example".to_string(),vec![],).recv_window(5000).build().unwrap();

            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},{"fromUserEmail":"testFrom1@google.com","toUserEmail":"1testTo@google.com","productType":"UM","symbol":"BTCUSDT","priceType":"MARK_PRICE","price":"97139.00000000","quantity":"0.0011","positionSide":"BOTH","side":"BUY","success":true}]}"#).unwrap();
            let expected_response : models::MovePositionForSubAccountResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::MovePositionForSubAccountResponse");

            let resp = client.move_position_for_sub_account(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn move_position_for_sub_account_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = MovePositionForSubAccountParams::builder(
                "from_user_email_example".to_string(),
                "to_user_email_example".to_string(),
                "product_type_example".to_string(),
                vec![],
            )
            .build()
            .unwrap();

            match client.move_position_for_sub_account(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_sub_account_assets_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountAssetsParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":10000,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BNB","free":10003,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BTC","free":11467.6399,"locked":0},{"freeze":0,"withdrawing":0,"asset":"ETH","free":10004.995,"locked":0},{"freeze":0,"withdrawing":0,"asset":"USDT","free":11652.14213,"locked":0}]}"#).unwrap();
            let expected_response : models::QuerySubAccountAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsResponse");

            let resp = client.query_sub_account_assets(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_assets_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountAssetsParams::builder("sub-account-email@email.com".to_string(),).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":0,"withdrawing":0,"asset":"ADA","free":10000,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BNB","free":10003,"locked":0},{"freeze":0,"withdrawing":0,"asset":"BTC","free":11467.6399,"locked":0},{"freeze":0,"withdrawing":0,"asset":"ETH","free":10004.995,"locked":0},{"freeze":0,"withdrawing":0,"asset":"USDT","free":11652.14213,"locked":0}]}"#).unwrap();
            let expected_response : models::QuerySubAccountAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsResponse");

            let resp = client.query_sub_account_assets(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_assets_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params =
                QuerySubAccountAssetsParams::builder("sub-account-email@email.com".to_string())
                    .build()
                    .unwrap();

            match client.query_sub_account_assets(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_sub_account_assets_asset_management_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountAssetsAssetManagementParams::builder("sub-account-email@email.com".to_string(),).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BNB","free":"10003","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BTC","free":"11467.6399","locked":"0"}]}"#).unwrap();
            let expected_response : models::QuerySubAccountAssetsAssetManagementResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsAssetManagementResponse");

            let resp = client.query_sub_account_assets_asset_management(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_assets_asset_management_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountAssetsAssetManagementParams::builder("sub-account-email@email.com".to_string(),).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"balances":[{"freeze":"0","withdrawing":"0","asset":"ADA","free":"10000","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BNB","free":"10003","locked":"0"},{"freeze":"0","withdrawing":"0","asset":"BTC","free":"11467.6399","locked":"0"}]}"#).unwrap();
            let expected_response : models::QuerySubAccountAssetsAssetManagementResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountAssetsAssetManagementResponse");

            let resp = client.query_sub_account_assets_asset_management(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_assets_asset_management_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = QuerySubAccountAssetsAssetManagementParams::builder(
                "sub-account-email@email.com".to_string(),
            )
            .build()
            .unwrap();

            match client
                .query_sub_account_assets_asset_management(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_sub_account_futures_asset_transfer_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder("sub-account-email@email.com".to_string(),789,).build().unwrap();

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","tranId":11631474902,"time":1544433328000}]}"#).unwrap();
            let expected_response : models::QuerySubAccountFuturesAssetTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse");

            let resp = client.query_sub_account_futures_asset_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_futures_asset_transfer_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder("sub-account-email@email.com".to_string(),789,).start_time(1623319461670).end_time(1641782889000).page(1).limit(1).recv_window(5000).build().unwrap();

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","tranId":11631474902,"time":1544433328000}]}"#).unwrap();
            let expected_response : models::QuerySubAccountFuturesAssetTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountFuturesAssetTransferHistoryResponse");

            let resp = client.query_sub_account_futures_asset_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_futures_asset_transfer_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = QuerySubAccountFuturesAssetTransferHistoryParams::builder(
                "sub-account-email@email.com".to_string(),
                789,
            )
            .build()
            .unwrap();

            match client
                .query_sub_account_futures_asset_transfer_history(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_sub_account_spot_asset_transfer_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder().build().unwrap();

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","status":"SUCCESS","tranId":6489938713,"time":1544433328000}]"#).unwrap();
            let expected_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");

            let resp = client.query_sub_account_spot_asset_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_spot_asset_transfer_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder().from_email("from_email_example".to_string()).to_email("to_email_example".to_string()).start_time(1623319461670).end_time(1641782889000).page(1).limit(1).recv_window(5000).build().unwrap();

            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},{"from":"bbb@test.com","to":"ccc@test.com","asset":"ETH","qty":"2","status":"SUCCESS","tranId":6489938713,"time":1544433328000}]"#).unwrap();
            let expected_response : Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QuerySubAccountSpotAssetTransferHistoryResponseInner>");

            let resp = client.query_sub_account_spot_asset_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_spot_asset_transfer_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = QuerySubAccountSpotAssetTransferHistoryParams::builder()
                .build()
                .unwrap();

            match client
                .query_sub_account_spot_asset_transfer_history(params)
                .await
            {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_sub_account_spot_assets_summary_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountSpotAssetsSummaryParams::builder().build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"},{"email":"test456@test.com","totalAsset":"0.00000000"}]}"#).unwrap();
            let expected_response : models::QuerySubAccountSpotAssetsSummaryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");

            let resp = client.query_sub_account_spot_assets_summary(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_spot_assets_summary_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QuerySubAccountSpotAssetsSummaryParams::builder().email("email_example".to_string()).page(1).size(10).recv_window(5000).build().unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"totalCount":2,"masterAccountTotalAsset":"0.23231201","spotSubUserAssetBtcVoList":[{"email":"sub123@test.com","totalAsset":"9999.00000000"},{"email":"test456@test.com","totalAsset":"0.00000000"}]}"#).unwrap();
            let expected_response : models::QuerySubAccountSpotAssetsSummaryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QuerySubAccountSpotAssetsSummaryResponse");

            let resp = client.query_sub_account_spot_assets_summary(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_sub_account_spot_assets_summary_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = QuerySubAccountSpotAssetsSummaryParams::builder()
                .build()
                .unwrap();

            match client.query_sub_account_spot_assets_summary(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn query_universal_transfer_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QueryUniversalTransferHistoryParams::builder().build().unwrap();

            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();
            let expected_response : models::QueryUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUniversalTransferHistoryResponse");

            let resp = client.query_universal_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_universal_transfer_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = QueryUniversalTransferHistoryParams::builder().from_email("from_email_example".to_string()).to_email("to_email_example".to_string()).client_tran_id("1".to_string()).start_time(1623319461670).end_time(1641782889000).page(1).limit(1).recv_window(5000).build().unwrap();

            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();
            let expected_response : models::QueryUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUniversalTransferHistoryResponse");

            let resp = client.query_universal_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn query_universal_transfer_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = QueryUniversalTransferHistoryParams::builder()
                .build()
                .unwrap();

            match client.query_universal_transfer_history(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn sub_account_futures_asset_transfer_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = SubAccountFuturesAssetTransferParams::builder(
                "from_email_example".to_string(),
                "to_email_example".to_string(),
                789,
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#).unwrap();
            let expected_response: models::SubAccountFuturesAssetTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");

            let resp = client
                .sub_account_futures_asset_transfer(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn sub_account_futures_asset_transfer_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = SubAccountFuturesAssetTransferParams::builder(
                "from_email_example".to_string(),
                "to_email_example".to_string(),
                789,
                "asset_example".to_string(),
                dec!(1.0),
            )
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"success":true,"txnId":"2934662589"}"#).unwrap();
            let expected_response: models::SubAccountFuturesAssetTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::SubAccountFuturesAssetTransferResponse");

            let resp = client
                .sub_account_futures_asset_transfer(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn sub_account_futures_asset_transfer_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = SubAccountFuturesAssetTransferParams::builder(
                "from_email_example".to_string(),
                "to_email_example".to_string(),
                789,
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            match client.sub_account_futures_asset_transfer(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn sub_account_transfer_history_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = SubAccountTransferHistoryParams::builder().build().unwrap();

            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},{"counterParty":"subAccount","email":"sub2@test.com","type":1,"asset":"ETH","qty":"2","fromAccountType":"SPOT","toAccountType":"COIN_FUTURE","status":"SUCCESS","tranId":11798829519,"time":1544433326000}]"#).unwrap();
            let expected_response : Vec<models::SubAccountTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SubAccountTransferHistoryResponseInner>");

            let resp = client.sub_account_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn sub_account_transfer_history_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = SubAccountTransferHistoryParams::builder().asset("asset_example".to_string()).r#type(789).start_time(1623319461670).end_time(1641782889000).limit(1).return_fail_history(false).recv_window(5000).build().unwrap();

            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},{"counterParty":"subAccount","email":"sub2@test.com","type":1,"asset":"ETH","qty":"2","fromAccountType":"SPOT","toAccountType":"COIN_FUTURE","status":"SUCCESS","tranId":11798829519,"time":1544433326000}]"#).unwrap();
            let expected_response : Vec<models::SubAccountTransferHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::SubAccountTransferHistoryResponseInner>");

            let resp = client.sub_account_transfer_history(params).await.expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn sub_account_transfer_history_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = SubAccountTransferHistoryParams::builder().build().unwrap();

            match client.sub_account_transfer_history(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn transfer_to_master_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = TransferToMasterParams::builder("asset_example".to_string(), dec!(1.0))
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::TransferToMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToMasterResponse");

            let resp = client
                .transfer_to_master(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn transfer_to_master_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = TransferToMasterParams::builder("asset_example".to_string(), dec!(1.0))
                .recv_window(5000)
                .build()
                .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::TransferToMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToMasterResponse");

            let resp = client
                .transfer_to_master(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn transfer_to_master_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = TransferToMasterParams::builder("asset_example".to_string(), dec!(1.0))
                .build()
                .unwrap();

            match client.transfer_to_master(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn transfer_to_sub_account_of_same_master_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = TransferToSubAccountOfSameMasterParams::builder(
                "to_email_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::TransferToSubAccountOfSameMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");

            let resp = client
                .transfer_to_sub_account_of_same_master(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn transfer_to_sub_account_of_same_master_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = TransferToSubAccountOfSameMasterParams::builder(
                "to_email_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value = serde_json::from_str(r#"{"txnId":"2966662589"}"#).unwrap();
            let expected_response: models::TransferToSubAccountOfSameMasterResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::TransferToSubAccountOfSameMasterResponse");

            let resp = client
                .transfer_to_sub_account_of_same_master(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn transfer_to_sub_account_of_same_master_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = TransferToSubAccountOfSameMasterParams::builder(
                "to_email_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            match client.transfer_to_sub_account_of_same_master(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }

    #[test]
    fn universal_transfer_required_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = UniversalTransferParams::builder(
                "from_account_type_example".to_string(),
                "to_account_type_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#).unwrap();
            let expected_response: models::UniversalTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::UniversalTransferResponse");

            let resp = client
                .universal_transfer(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn universal_transfer_optional_params_success() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: false };

            let params = UniversalTransferParams::builder(
                "from_account_type_example".to_string(),
                "to_account_type_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .from_email("from_email_example".to_string())
            .to_email("to_email_example".to_string())
            .client_tran_id("1".to_string())
            .symbol("symbol_example".to_string())
            .recv_window(5000)
            .build()
            .unwrap();

            let resp_json: Value =
                serde_json::from_str(r#"{"tranId":11945860693,"clientTranId":"test"}"#).unwrap();
            let expected_response: models::UniversalTransferResponse =
                serde_json::from_value(resp_json.clone())
                    .expect("should parse into models::UniversalTransferResponse");

            let resp = client
                .universal_transfer(params)
                .await
                .expect("Expected a response");
            let data_future = resp.data();
            let actual_response = data_future.await.unwrap();
            assert_eq!(actual_response, expected_response);
        });
    }

    #[test]
    fn universal_transfer_response_error() {
        TOKIO_SHARED_RT.block_on(async {
            let client = MockAssetManagementApiClient { force_error: true };

            let params = UniversalTransferParams::builder(
                "from_account_type_example".to_string(),
                "to_account_type_example".to_string(),
                "asset_example".to_string(),
                dec!(1.0),
            )
            .build()
            .unwrap();

            match client.universal_transfer(params).await {
                Ok(_) => panic!("Expected an error"),
                Err(err) => {
                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
                }
            }
        });
    }
}
