Skip to main content

binance_sdk/wallet/rest_api/apis/
asset_api.rs

1/*
2 * Wallet REST API
3 *
4 * Query balances, manage assets, and perform wallet operations via the Binance Wallet API.
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24    config::ConfigurationRestApi,
25    models::{ParamBuildError, RestApiResponse},
26    utils::send_request,
27};
28use crate::wallet::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait AssetApi: Send + Sync {
34    async fn asset_detail(
35        &self,
36        params: AssetDetailParams,
37    ) -> anyhow::Result<RestApiResponse<models::AssetDetailResponse>>;
38    async fn asset_dividend_record(
39        &self,
40        params: AssetDividendRecordParams,
41    ) -> anyhow::Result<RestApiResponse<models::AssetDividendRecordResponse>>;
42    async fn dust_convert(
43        &self,
44        params: DustConvertParams,
45    ) -> anyhow::Result<RestApiResponse<models::DustConvertResponse>>;
46    async fn dust_convertible_assets(
47        &self,
48        params: DustConvertibleAssetsParams,
49    ) -> anyhow::Result<RestApiResponse<models::DustConvertibleAssetsResponse>>;
50    async fn dust_transfer(
51        &self,
52        params: DustTransferParams,
53    ) -> anyhow::Result<RestApiResponse<models::DustTransferResponse>>;
54    async fn dustlog(
55        &self,
56        params: DustlogParams,
57    ) -> anyhow::Result<RestApiResponse<models::DustlogResponse>>;
58    async fn funding_wallet(
59        &self,
60        params: FundingWalletParams,
61    ) -> anyhow::Result<RestApiResponse<Vec<models::FundingWalletResponseInner>>>;
62    async fn get_assets_that_can_be_converted_into_bnb(
63        &self,
64        params: GetAssetsThatCanBeConvertedIntoBnbParams,
65    ) -> anyhow::Result<RestApiResponse<models::GetAssetsThatCanBeConvertedIntoBnbResponse>>;
66    async fn get_cloud_mining_payment_and_refund_history(
67        &self,
68        params: GetCloudMiningPaymentAndRefundHistoryParams,
69    ) -> anyhow::Result<RestApiResponse<models::GetCloudMiningPaymentAndRefundHistoryResponse>>;
70    async fn get_open_symbol_list(
71        &self,
72    ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenSymbolListResponseInner>>>;
73    async fn query_user_delegation_history(
74        &self,
75        params: QueryUserDelegationHistoryParams,
76    ) -> anyhow::Result<RestApiResponse<models::QueryUserDelegationHistoryResponse>>;
77    async fn query_user_universal_transfer_history(
78        &self,
79        params: QueryUserUniversalTransferHistoryParams,
80    ) -> anyhow::Result<RestApiResponse<models::QueryUserUniversalTransferHistoryResponse>>;
81    async fn query_user_wallet_balance(
82        &self,
83        params: QueryUserWalletBalanceParams,
84    ) -> anyhow::Result<RestApiResponse<Vec<models::QueryUserWalletBalanceResponseInner>>>;
85    async fn toggle_bnb_burn_on_spot_trade_and_margin_interest(
86        &self,
87        params: ToggleBnbBurnOnSpotTradeAndMarginInterestParams,
88    ) -> anyhow::Result<RestApiResponse<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>>;
89    async fn trade_fee(
90        &self,
91        params: TradeFeeParams,
92    ) -> anyhow::Result<RestApiResponse<Vec<models::TradeFeeResponseInner>>>;
93    async fn user_asset(
94        &self,
95        params: UserAssetParams,
96    ) -> anyhow::Result<RestApiResponse<Vec<models::UserAssetResponseInner>>>;
97    async fn user_universal_transfer(
98        &self,
99        params: UserUniversalTransferParams,
100    ) -> anyhow::Result<RestApiResponse<models::UserUniversalTransferResponse>>;
101}
102
103#[derive(Debug, Clone)]
104pub struct AssetApiClient {
105    configuration: ConfigurationRestApi,
106}
107
108impl AssetApiClient {
109    pub fn new(configuration: ConfigurationRestApi) -> Self {
110        Self { configuration }
111    }
112}
113
114#[allow(non_camel_case_types)]
115#[derive(Debug, Clone, Serialize, Deserialize)]
116pub enum DustTransferAccountTypeEnum {
117    #[serde(rename = "SPOT")]
118    Spot,
119    #[serde(rename = "MARGIN")]
120    Margin,
121}
122
123impl DustTransferAccountTypeEnum {
124    #[must_use]
125    pub fn as_str(&self) -> &'static str {
126        match self {
127            Self::Spot => "SPOT",
128            Self::Margin => "MARGIN",
129        }
130    }
131}
132
133impl std::str::FromStr for DustTransferAccountTypeEnum {
134    type Err = Box<dyn std::error::Error + Send + Sync>;
135
136    fn from_str(s: &str) -> Result<Self, Self::Err> {
137        match s {
138            "SPOT" => Ok(Self::Spot),
139            "MARGIN" => Ok(Self::Margin),
140            other => Err(format!("invalid DustTransferAccountTypeEnum: {}", other).into()),
141        }
142    }
143}
144
145#[allow(non_camel_case_types)]
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub enum DustlogAccountTypeEnum {
148    #[serde(rename = "SPOT")]
149    Spot,
150    #[serde(rename = "MARGIN")]
151    Margin,
152}
153
154impl DustlogAccountTypeEnum {
155    #[must_use]
156    pub fn as_str(&self) -> &'static str {
157        match self {
158            Self::Spot => "SPOT",
159            Self::Margin => "MARGIN",
160        }
161    }
162}
163
164impl std::str::FromStr for DustlogAccountTypeEnum {
165    type Err = Box<dyn std::error::Error + Send + Sync>;
166
167    fn from_str(s: &str) -> Result<Self, Self::Err> {
168        match s {
169            "SPOT" => Ok(Self::Spot),
170            "MARGIN" => Ok(Self::Margin),
171            other => Err(format!("invalid DustlogAccountTypeEnum: {}", other).into()),
172        }
173    }
174}
175
176#[allow(non_camel_case_types)]
177#[derive(Debug, Clone, Serialize, Deserialize)]
178pub enum GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum {
179    #[serde(rename = "SPOT")]
180    Spot,
181    #[serde(rename = "MARGIN")]
182    Margin,
183}
184
185impl GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum {
186    #[must_use]
187    pub fn as_str(&self) -> &'static str {
188        match self {
189            Self::Spot => "SPOT",
190            Self::Margin => "MARGIN",
191        }
192    }
193}
194
195impl std::str::FromStr for GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum {
196    type Err = Box<dyn std::error::Error + Send + Sync>;
197
198    fn from_str(s: &str) -> Result<Self, Self::Err> {
199        match s {
200            "SPOT" => Ok(Self::Spot),
201            "MARGIN" => Ok(Self::Margin),
202            other => Err(format!(
203                "invalid GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum: {}",
204                other
205            )
206            .into()),
207        }
208    }
209}
210
211#[allow(non_camel_case_types)]
212#[derive(Debug, Clone, Serialize, Deserialize)]
213pub enum QueryUserDelegationHistoryTypeEnum {
214    #[serde(rename = "DELEGATE")]
215    Delegate,
216    #[serde(rename = "UNDELEGATE")]
217    Undelegate,
218}
219
220impl QueryUserDelegationHistoryTypeEnum {
221    #[must_use]
222    pub fn as_str(&self) -> &'static str {
223        match self {
224            Self::Delegate => "DELEGATE",
225            Self::Undelegate => "UNDELEGATE",
226        }
227    }
228}
229
230impl std::str::FromStr for QueryUserDelegationHistoryTypeEnum {
231    type Err = Box<dyn std::error::Error + Send + Sync>;
232
233    fn from_str(s: &str) -> Result<Self, Self::Err> {
234        match s {
235            "DELEGATE" => Ok(Self::Delegate),
236            "UNDELEGATE" => Ok(Self::Undelegate),
237            other => Err(format!("invalid QueryUserDelegationHistoryTypeEnum: {}", other).into()),
238        }
239    }
240}
241
242#[allow(non_camel_case_types)]
243#[derive(Debug, Clone, Serialize, Deserialize)]
244pub enum QueryUserUniversalTransferHistoryFromSymbolEnum {
245    #[serde(rename = "ISOLATEDMARGIN_MARGIN")]
246    IsolatedmarginMargin,
247    #[serde(rename = "ISOLATEDMARGIN_ISOLATEDMARGIN")]
248    IsolatedmarginIsolatedmargin,
249}
250
251impl QueryUserUniversalTransferHistoryFromSymbolEnum {
252    #[must_use]
253    pub fn as_str(&self) -> &'static str {
254        match self {
255            Self::IsolatedmarginMargin => "ISOLATEDMARGIN_MARGIN",
256            Self::IsolatedmarginIsolatedmargin => "ISOLATEDMARGIN_ISOLATEDMARGIN",
257        }
258    }
259}
260
261impl std::str::FromStr for QueryUserUniversalTransferHistoryFromSymbolEnum {
262    type Err = Box<dyn std::error::Error + Send + Sync>;
263
264    fn from_str(s: &str) -> Result<Self, Self::Err> {
265        match s {
266            "ISOLATEDMARGIN_MARGIN" => Ok(Self::IsolatedmarginMargin),
267            "ISOLATEDMARGIN_ISOLATEDMARGIN" => Ok(Self::IsolatedmarginIsolatedmargin),
268            other => Err(format!(
269                "invalid QueryUserUniversalTransferHistoryFromSymbolEnum: {}",
270                other
271            )
272            .into()),
273        }
274    }
275}
276
277#[allow(non_camel_case_types)]
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub enum QueryUserUniversalTransferHistoryToSymbolEnum {
280    #[serde(rename = "MARGIN_ISOLATEDMARGIN")]
281    MarginIsolatedmargin,
282    #[serde(rename = "ISOLATEDMARGIN_ISOLATEDMARGIN")]
283    IsolatedmarginIsolatedmargin,
284}
285
286impl QueryUserUniversalTransferHistoryToSymbolEnum {
287    #[must_use]
288    pub fn as_str(&self) -> &'static str {
289        match self {
290            Self::MarginIsolatedmargin => "MARGIN_ISOLATEDMARGIN",
291            Self::IsolatedmarginIsolatedmargin => "ISOLATEDMARGIN_ISOLATEDMARGIN",
292        }
293    }
294}
295
296impl std::str::FromStr for QueryUserUniversalTransferHistoryToSymbolEnum {
297    type Err = Box<dyn std::error::Error + Send + Sync>;
298
299    fn from_str(s: &str) -> Result<Self, Self::Err> {
300        match s {
301            "MARGIN_ISOLATEDMARGIN" => Ok(Self::MarginIsolatedmargin),
302            "ISOLATEDMARGIN_ISOLATEDMARGIN" => Ok(Self::IsolatedmarginIsolatedmargin),
303            other => Err(format!(
304                "invalid QueryUserUniversalTransferHistoryToSymbolEnum: {}",
305                other
306            )
307            .into()),
308        }
309    }
310}
311
312#[allow(non_camel_case_types)]
313#[derive(Debug, Clone, Serialize, Deserialize)]
314pub enum UserUniversalTransferTypeEnum {
315    #[serde(rename = "MAIN_UMFUTURE")]
316    MainUmfuture,
317    #[serde(rename = "MAIN_CMFUTURE")]
318    MainCmfuture,
319    #[serde(rename = "MAIN_MARGIN")]
320    MainMargin,
321    #[serde(rename = "UMFUTURE_MAIN")]
322    UmfutureMain,
323    #[serde(rename = "UMFUTURE_MARGIN")]
324    UmfutureMargin,
325    #[serde(rename = "CMFUTURE_MAIN")]
326    CmfutureMain,
327    #[serde(rename = "CMFUTURE_MARGIN")]
328    CmfutureMargin,
329    #[serde(rename = "MARGIN_MAIN")]
330    MarginMain,
331    #[serde(rename = "MARGIN_UMFUTURE")]
332    MarginUmfuture,
333    #[serde(rename = "MARGIN_CMFUTURE")]
334    MarginCmfuture,
335    #[serde(rename = "ISOLATEDMARGIN_MARGIN")]
336    IsolatedmarginMargin,
337    #[serde(rename = "MARGIN_ISOLATEDMARGIN")]
338    MarginIsolatedmargin,
339    #[serde(rename = "ISOLATEDMARGIN_ISOLATEDMARGIN")]
340    IsolatedmarginIsolatedmargin,
341    #[serde(rename = "MAIN_FUNDING")]
342    MainFunding,
343    #[serde(rename = "FUNDING_MAIN")]
344    FundingMain,
345    #[serde(rename = "FUNDING_UMFUTURE")]
346    FundingUmfuture,
347    #[serde(rename = "UMFUTURE_FUNDING")]
348    UmfutureFunding,
349    #[serde(rename = "MARGIN_FUNDING")]
350    MarginFunding,
351    #[serde(rename = "FUNDING_MARGIN")]
352    FundingMargin,
353    #[serde(rename = "FUNDING_CMFUTURE")]
354    FundingCmfuture,
355    #[serde(rename = "CMFUTURE_FUNDING")]
356    CmfutureFunding,
357    #[serde(rename = "MAIN_OPTION")]
358    MainOption,
359    #[serde(rename = "OPTION_MAIN")]
360    OptionMain,
361    #[serde(rename = "UMFUTURE_OPTION")]
362    UmfutureOption,
363    #[serde(rename = "OPTION_UMFUTURE")]
364    OptionUmfuture,
365    #[serde(rename = "MARGIN_OPTION")]
366    MarginOption,
367    #[serde(rename = "OPTION_MARGIN")]
368    OptionMargin,
369    #[serde(rename = "FUNDING_OPTION")]
370    FundingOption,
371    #[serde(rename = "OPTION_FUNDING")]
372    OptionFunding,
373    #[serde(rename = "MAIN_PORTFOLIO_MARGIN")]
374    MainPortfolioMargin,
375    #[serde(rename = "PORTFOLIO_MARGIN_MAIN")]
376    PortfolioMarginMain,
377}
378
379impl UserUniversalTransferTypeEnum {
380    #[must_use]
381    pub fn as_str(&self) -> &'static str {
382        match self {
383            Self::MainUmfuture => "MAIN_UMFUTURE",
384            Self::MainCmfuture => "MAIN_CMFUTURE",
385            Self::MainMargin => "MAIN_MARGIN",
386            Self::UmfutureMain => "UMFUTURE_MAIN",
387            Self::UmfutureMargin => "UMFUTURE_MARGIN",
388            Self::CmfutureMain => "CMFUTURE_MAIN",
389            Self::CmfutureMargin => "CMFUTURE_MARGIN",
390            Self::MarginMain => "MARGIN_MAIN",
391            Self::MarginUmfuture => "MARGIN_UMFUTURE",
392            Self::MarginCmfuture => "MARGIN_CMFUTURE",
393            Self::IsolatedmarginMargin => "ISOLATEDMARGIN_MARGIN",
394            Self::MarginIsolatedmargin => "MARGIN_ISOLATEDMARGIN",
395            Self::IsolatedmarginIsolatedmargin => "ISOLATEDMARGIN_ISOLATEDMARGIN",
396            Self::MainFunding => "MAIN_FUNDING",
397            Self::FundingMain => "FUNDING_MAIN",
398            Self::FundingUmfuture => "FUNDING_UMFUTURE",
399            Self::UmfutureFunding => "UMFUTURE_FUNDING",
400            Self::MarginFunding => "MARGIN_FUNDING",
401            Self::FundingMargin => "FUNDING_MARGIN",
402            Self::FundingCmfuture => "FUNDING_CMFUTURE",
403            Self::CmfutureFunding => "CMFUTURE_FUNDING",
404            Self::MainOption => "MAIN_OPTION",
405            Self::OptionMain => "OPTION_MAIN",
406            Self::UmfutureOption => "UMFUTURE_OPTION",
407            Self::OptionUmfuture => "OPTION_UMFUTURE",
408            Self::MarginOption => "MARGIN_OPTION",
409            Self::OptionMargin => "OPTION_MARGIN",
410            Self::FundingOption => "FUNDING_OPTION",
411            Self::OptionFunding => "OPTION_FUNDING",
412            Self::MainPortfolioMargin => "MAIN_PORTFOLIO_MARGIN",
413            Self::PortfolioMarginMain => "PORTFOLIO_MARGIN_MAIN",
414        }
415    }
416}
417
418impl std::str::FromStr for UserUniversalTransferTypeEnum {
419    type Err = Box<dyn std::error::Error + Send + Sync>;
420
421    fn from_str(s: &str) -> Result<Self, Self::Err> {
422        match s {
423            "MAIN_UMFUTURE" => Ok(Self::MainUmfuture),
424            "MAIN_CMFUTURE" => Ok(Self::MainCmfuture),
425            "MAIN_MARGIN" => Ok(Self::MainMargin),
426            "UMFUTURE_MAIN" => Ok(Self::UmfutureMain),
427            "UMFUTURE_MARGIN" => Ok(Self::UmfutureMargin),
428            "CMFUTURE_MAIN" => Ok(Self::CmfutureMain),
429            "CMFUTURE_MARGIN" => Ok(Self::CmfutureMargin),
430            "MARGIN_MAIN" => Ok(Self::MarginMain),
431            "MARGIN_UMFUTURE" => Ok(Self::MarginUmfuture),
432            "MARGIN_CMFUTURE" => Ok(Self::MarginCmfuture),
433            "ISOLATEDMARGIN_MARGIN" => Ok(Self::IsolatedmarginMargin),
434            "MARGIN_ISOLATEDMARGIN" => Ok(Self::MarginIsolatedmargin),
435            "ISOLATEDMARGIN_ISOLATEDMARGIN" => Ok(Self::IsolatedmarginIsolatedmargin),
436            "MAIN_FUNDING" => Ok(Self::MainFunding),
437            "FUNDING_MAIN" => Ok(Self::FundingMain),
438            "FUNDING_UMFUTURE" => Ok(Self::FundingUmfuture),
439            "UMFUTURE_FUNDING" => Ok(Self::UmfutureFunding),
440            "MARGIN_FUNDING" => Ok(Self::MarginFunding),
441            "FUNDING_MARGIN" => Ok(Self::FundingMargin),
442            "FUNDING_CMFUTURE" => Ok(Self::FundingCmfuture),
443            "CMFUTURE_FUNDING" => Ok(Self::CmfutureFunding),
444            "MAIN_OPTION" => Ok(Self::MainOption),
445            "OPTION_MAIN" => Ok(Self::OptionMain),
446            "UMFUTURE_OPTION" => Ok(Self::UmfutureOption),
447            "OPTION_UMFUTURE" => Ok(Self::OptionUmfuture),
448            "MARGIN_OPTION" => Ok(Self::MarginOption),
449            "OPTION_MARGIN" => Ok(Self::OptionMargin),
450            "FUNDING_OPTION" => Ok(Self::FundingOption),
451            "OPTION_FUNDING" => Ok(Self::OptionFunding),
452            "MAIN_PORTFOLIO_MARGIN" => Ok(Self::MainPortfolioMargin),
453            "PORTFOLIO_MARGIN_MAIN" => Ok(Self::PortfolioMarginMain),
454            other => Err(format!("invalid UserUniversalTransferTypeEnum: {}", other).into()),
455        }
456    }
457}
458
459#[allow(non_camel_case_types)]
460#[derive(Debug, Clone, Serialize, Deserialize)]
461pub enum UserUniversalTransferFromSymbolEnum {
462    #[serde(rename = "ISOLATEDMARGIN_MARGIN")]
463    IsolatedmarginMargin,
464    #[serde(rename = "ISOLATEDMARGIN_ISOLATEDMARGIN")]
465    IsolatedmarginIsolatedmargin,
466}
467
468impl UserUniversalTransferFromSymbolEnum {
469    #[must_use]
470    pub fn as_str(&self) -> &'static str {
471        match self {
472            Self::IsolatedmarginMargin => "ISOLATEDMARGIN_MARGIN",
473            Self::IsolatedmarginIsolatedmargin => "ISOLATEDMARGIN_ISOLATEDMARGIN",
474        }
475    }
476}
477
478impl std::str::FromStr for UserUniversalTransferFromSymbolEnum {
479    type Err = Box<dyn std::error::Error + Send + Sync>;
480
481    fn from_str(s: &str) -> Result<Self, Self::Err> {
482        match s {
483            "ISOLATEDMARGIN_MARGIN" => Ok(Self::IsolatedmarginMargin),
484            "ISOLATEDMARGIN_ISOLATEDMARGIN" => Ok(Self::IsolatedmarginIsolatedmargin),
485            other => Err(format!("invalid UserUniversalTransferFromSymbolEnum: {}", other).into()),
486        }
487    }
488}
489
490#[allow(non_camel_case_types)]
491#[derive(Debug, Clone, Serialize, Deserialize)]
492pub enum UserUniversalTransferToSymbolEnum {
493    #[serde(rename = "MARGIN_ISOLATEDMARGIN")]
494    MarginIsolatedmargin,
495    #[serde(rename = "ISOLATEDMARGIN_ISOLATEDMARGIN")]
496    IsolatedmarginIsolatedmargin,
497}
498
499impl UserUniversalTransferToSymbolEnum {
500    #[must_use]
501    pub fn as_str(&self) -> &'static str {
502        match self {
503            Self::MarginIsolatedmargin => "MARGIN_ISOLATEDMARGIN",
504            Self::IsolatedmarginIsolatedmargin => "ISOLATEDMARGIN_ISOLATEDMARGIN",
505        }
506    }
507}
508
509impl std::str::FromStr for UserUniversalTransferToSymbolEnum {
510    type Err = Box<dyn std::error::Error + Send + Sync>;
511
512    fn from_str(s: &str) -> Result<Self, Self::Err> {
513        match s {
514            "MARGIN_ISOLATEDMARGIN" => Ok(Self::MarginIsolatedmargin),
515            "ISOLATEDMARGIN_ISOLATEDMARGIN" => Ok(Self::IsolatedmarginIsolatedmargin),
516            other => Err(format!("invalid UserUniversalTransferToSymbolEnum: {}", other).into()),
517        }
518    }
519}
520
521/// Request parameters for the [`asset_detail`] operation.
522///
523/// This struct holds all of the inputs you can pass when calling
524/// [`asset_detail`](#method.asset_detail).
525#[derive(Clone, Debug, Builder, Deserialize, Default)]
526#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
527pub struct AssetDetailParams {
528    ///
529    /// The `asset` parameter.
530    ///
531    /// This field is **optional.
532    #[builder(setter(into), default)]
533    #[serde(rename = "asset", default)]
534    pub asset: Option<String>,
535    ///
536    /// The `recv_window` parameter.
537    ///
538    /// This field is **optional.
539    #[builder(setter(into), default)]
540    #[serde(rename = "recvWindow", default)]
541    pub recv_window: Option<i64>,
542}
543
544impl AssetDetailParams {
545    /// Create a builder for [`asset_detail`].
546    ///
547    #[must_use]
548    pub fn builder() -> AssetDetailParamsBuilder {
549        AssetDetailParamsBuilder::default()
550    }
551}
552/// Request parameters for the [`asset_dividend_record`] operation.
553///
554/// This struct holds all of the inputs you can pass when calling
555/// [`asset_dividend_record`](#method.asset_dividend_record).
556#[derive(Clone, Debug, Builder, Deserialize, Default)]
557#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
558pub struct AssetDividendRecordParams {
559    ///
560    /// The `asset` parameter.
561    ///
562    /// This field is **optional.
563    #[builder(setter(into), default)]
564    #[serde(rename = "asset", default)]
565    pub asset: Option<String>,
566    ///
567    /// The `start_time` parameter.
568    ///
569    /// This field is **optional.
570    #[builder(setter(into), default)]
571    #[serde(rename = "startTime", default)]
572    pub start_time: Option<i64>,
573    ///
574    /// The `end_time` parameter.
575    ///
576    /// This field is **optional.
577    #[builder(setter(into), default)]
578    #[serde(rename = "endTime", default)]
579    pub end_time: Option<i64>,
580    ///
581    /// The `limit` parameter.
582    ///
583    /// This field is **optional.
584    #[builder(setter(into), default)]
585    #[serde(rename = "limit", default)]
586    pub limit: Option<i64>,
587    ///
588    /// The `recv_window` parameter.
589    ///
590    /// This field is **optional.
591    #[builder(setter(into), default)]
592    #[serde(rename = "recvWindow", default)]
593    pub recv_window: Option<i64>,
594}
595
596impl AssetDividendRecordParams {
597    /// Create a builder for [`asset_dividend_record`].
598    ///
599    #[must_use]
600    pub fn builder() -> AssetDividendRecordParamsBuilder {
601        AssetDividendRecordParamsBuilder::default()
602    }
603}
604/// Request parameters for the [`dust_convert`] operation.
605///
606/// This struct holds all of the inputs you can pass when calling
607/// [`dust_convert`](#method.dust_convert).
608#[derive(Clone, Debug, Builder, Deserialize)]
609#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
610pub struct DustConvertParams {
611    ///
612    /// The `asset` parameter.
613    ///
614    /// This field is **required.
615    #[builder(setter(into))]
616    #[serde(rename = "asset")]
617    pub asset: String,
618    /// `SPOT` or `MARGIN`, default `SPOT`
619    ///
620    /// This field is **optional.
621    #[builder(setter(into), default)]
622    #[serde(rename = "accountType", default)]
623    pub account_type: Option<String>,
624    /// A unique id for the request
625    ///
626    /// This field is **optional.
627    #[builder(setter(into), default)]
628    #[serde(rename = "clientId", default)]
629    pub client_id: Option<String>,
630    ///
631    /// The `target_asset` parameter.
632    ///
633    /// This field is **optional.
634    #[builder(setter(into), default)]
635    #[serde(rename = "targetAsset", default)]
636    pub target_asset: Option<String>,
637    ///
638    /// The `third_party_client_id` parameter.
639    ///
640    /// This field is **optional.
641    #[builder(setter(into), default)]
642    #[serde(rename = "thirdPartyClientId", default)]
643    pub third_party_client_id: Option<String>,
644    ///
645    /// The `dust_quota_asset_to_target_asset_price` parameter.
646    ///
647    /// This field is **optional.
648    #[builder(setter(into), default)]
649    #[serde(rename = "dustQuotaAssetToTargetAssetPrice", default)]
650    pub dust_quota_asset_to_target_asset_price: Option<rust_decimal::Decimal>,
651}
652
653impl DustConvertParams {
654    /// Create a builder for [`dust_convert`].
655    ///
656    /// Required parameters:
657    ///
658    /// * `asset` — String
659    ///
660    #[must_use]
661    pub fn builder(asset: String) -> DustConvertParamsBuilder {
662        DustConvertParamsBuilder::default().asset(asset)
663    }
664}
665/// Request parameters for the [`dust_convertible_assets`] operation.
666///
667/// This struct holds all of the inputs you can pass when calling
668/// [`dust_convertible_assets`](#method.dust_convertible_assets).
669#[derive(Clone, Debug, Builder, Deserialize)]
670#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
671pub struct DustConvertibleAssetsParams {
672    ///
673    /// The `target_asset` parameter.
674    ///
675    /// This field is **required.
676    #[builder(setter(into))]
677    #[serde(rename = "targetAsset")]
678    pub target_asset: String,
679    /// `SPOT` or `MARGIN`, default `SPOT`
680    ///
681    /// This field is **optional.
682    #[builder(setter(into), default)]
683    #[serde(rename = "accountType", default)]
684    pub account_type: Option<String>,
685    ///
686    /// The `dust_quota_asset_to_target_asset_price` parameter.
687    ///
688    /// This field is **optional.
689    #[builder(setter(into), default)]
690    #[serde(rename = "dustQuotaAssetToTargetAssetPrice", default)]
691    pub dust_quota_asset_to_target_asset_price: Option<rust_decimal::Decimal>,
692}
693
694impl DustConvertibleAssetsParams {
695    /// Create a builder for [`dust_convertible_assets`].
696    ///
697    /// Required parameters:
698    ///
699    /// * `target_asset` — String
700    ///
701    #[must_use]
702    pub fn builder(target_asset: String) -> DustConvertibleAssetsParamsBuilder {
703        DustConvertibleAssetsParamsBuilder::default().target_asset(target_asset)
704    }
705}
706/// Request parameters for the [`dust_transfer`] operation.
707///
708/// This struct holds all of the inputs you can pass when calling
709/// [`dust_transfer`](#method.dust_transfer).
710#[derive(Clone, Debug, Builder, Deserialize)]
711#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
712pub struct DustTransferParams {
713    /// The asset being converted. For example: asset=BTC,USDT
714    ///
715    /// This field is **required.
716    #[builder(setter(into))]
717    #[serde(rename = "asset")]
718    pub asset: String,
719    ///
720    /// The `account_type` parameter.
721    ///
722    /// This field is **optional.
723    #[builder(setter(into), default)]
724    #[serde(rename = "accountType", default)]
725    pub account_type: Option<DustTransferAccountTypeEnum>,
726    ///
727    /// The `recv_window` parameter.
728    ///
729    /// This field is **optional.
730    #[builder(setter(into), default)]
731    #[serde(rename = "recvWindow", default)]
732    pub recv_window: Option<i64>,
733}
734
735impl DustTransferParams {
736    /// Create a builder for [`dust_transfer`].
737    ///
738    /// Required parameters:
739    ///
740    /// * `asset` — The asset being converted. For example: asset=BTC,USDT
741    ///
742    #[must_use]
743    pub fn builder(asset: String) -> DustTransferParamsBuilder {
744        DustTransferParamsBuilder::default().asset(asset)
745    }
746}
747/// Request parameters for the [`dustlog`] operation.
748///
749/// This struct holds all of the inputs you can pass when calling
750/// [`dustlog`](#method.dustlog).
751#[derive(Clone, Debug, Builder, Deserialize, Default)]
752#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
753pub struct DustlogParams {
754    ///
755    /// The `account_type` parameter.
756    ///
757    /// This field is **optional.
758    #[builder(setter(into), default)]
759    #[serde(rename = "accountType", default)]
760    pub account_type: Option<DustlogAccountTypeEnum>,
761    ///
762    /// The `start_time` parameter.
763    ///
764    /// This field is **optional.
765    #[builder(setter(into), default)]
766    #[serde(rename = "startTime", default)]
767    pub start_time: Option<i64>,
768    ///
769    /// The `end_time` parameter.
770    ///
771    /// This field is **optional.
772    #[builder(setter(into), default)]
773    #[serde(rename = "endTime", default)]
774    pub end_time: Option<i64>,
775    ///
776    /// The `recv_window` parameter.
777    ///
778    /// This field is **optional.
779    #[builder(setter(into), default)]
780    #[serde(rename = "recvWindow", default)]
781    pub recv_window: Option<i64>,
782}
783
784impl DustlogParams {
785    /// Create a builder for [`dustlog`].
786    ///
787    #[must_use]
788    pub fn builder() -> DustlogParamsBuilder {
789        DustlogParamsBuilder::default()
790    }
791}
792/// Request parameters for the [`funding_wallet`] operation.
793///
794/// This struct holds all of the inputs you can pass when calling
795/// [`funding_wallet`](#method.funding_wallet).
796#[derive(Clone, Debug, Builder, Deserialize, Default)]
797#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
798pub struct FundingWalletParams {
799    ///
800    /// The `asset` parameter.
801    ///
802    /// This field is **optional.
803    #[builder(setter(into), default)]
804    #[serde(rename = "asset", default)]
805    pub asset: Option<String>,
806    ///
807    /// The `need_btc_valuation` parameter.
808    ///
809    /// This field is **optional.
810    #[builder(setter(into), default)]
811    #[serde(rename = "needBtcValuation", default)]
812    pub need_btc_valuation: Option<bool>,
813    ///
814    /// The `recv_window` parameter.
815    ///
816    /// This field is **optional.
817    #[builder(setter(into), default)]
818    #[serde(rename = "recvWindow", default)]
819    pub recv_window: Option<i64>,
820}
821
822impl FundingWalletParams {
823    /// Create a builder for [`funding_wallet`].
824    ///
825    #[must_use]
826    pub fn builder() -> FundingWalletParamsBuilder {
827        FundingWalletParamsBuilder::default()
828    }
829}
830/// Request parameters for the [`get_assets_that_can_be_converted_into_bnb`] operation.
831///
832/// This struct holds all of the inputs you can pass when calling
833/// [`get_assets_that_can_be_converted_into_bnb`](#method.get_assets_that_can_be_converted_into_bnb).
834#[derive(Clone, Debug, Builder, Deserialize, Default)]
835#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
836pub struct GetAssetsThatCanBeConvertedIntoBnbParams {
837    ///
838    /// The `account_type` parameter.
839    ///
840    /// This field is **optional.
841    #[builder(setter(into), default)]
842    #[serde(rename = "accountType", default)]
843    pub account_type: Option<GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum>,
844    ///
845    /// The `recv_window` parameter.
846    ///
847    /// This field is **optional.
848    #[builder(setter(into), default)]
849    #[serde(rename = "recvWindow", default)]
850    pub recv_window: Option<i64>,
851}
852
853impl GetAssetsThatCanBeConvertedIntoBnbParams {
854    /// Create a builder for [`get_assets_that_can_be_converted_into_bnb`].
855    ///
856    #[must_use]
857    pub fn builder() -> GetAssetsThatCanBeConvertedIntoBnbParamsBuilder {
858        GetAssetsThatCanBeConvertedIntoBnbParamsBuilder::default()
859    }
860}
861/// Request parameters for the [`get_cloud_mining_payment_and_refund_history`] operation.
862///
863/// This struct holds all of the inputs you can pass when calling
864/// [`get_cloud_mining_payment_and_refund_history`](#method.get_cloud_mining_payment_and_refund_history).
865#[derive(Clone, Debug, Builder, Deserialize)]
866#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
867pub struct GetCloudMiningPaymentAndRefundHistoryParams {
868    /// inclusive, unit: ms
869    ///
870    /// This field is **required.
871    #[builder(setter(into))]
872    #[serde(rename = "startTime")]
873    pub start_time: i64,
874    /// exclusive, unit: ms
875    ///
876    /// This field is **required.
877    #[builder(setter(into))]
878    #[serde(rename = "endTime")]
879    pub end_time: i64,
880    /// The transaction id
881    ///
882    /// This field is **optional.
883    #[builder(setter(into), default)]
884    #[serde(rename = "tranId", default)]
885    pub tran_id: Option<i64>,
886    /// The unique flag
887    ///
888    /// This field is **optional.
889    #[builder(setter(into), default)]
890    #[serde(rename = "clientTranId", default)]
891    pub client_tran_id: Option<String>,
892    /// If it is blank, we will query all assets
893    ///
894    /// This field is **optional.
895    #[builder(setter(into), default)]
896    #[serde(rename = "asset", default)]
897    pub asset: Option<String>,
898    ///
899    /// The `current` parameter.
900    ///
901    /// This field is **optional.
902    #[builder(setter(into), default)]
903    #[serde(rename = "current", default)]
904    pub current: Option<i64>,
905    ///
906    /// The `size` parameter.
907    ///
908    /// This field is **optional.
909    #[builder(setter(into), default)]
910    #[serde(rename = "size", default)]
911    pub size: Option<i64>,
912}
913
914impl GetCloudMiningPaymentAndRefundHistoryParams {
915    /// Create a builder for [`get_cloud_mining_payment_and_refund_history`].
916    ///
917    /// Required parameters:
918    ///
919    /// * `start_time` — inclusive, unit: ms
920    /// * `end_time` — exclusive, unit: ms
921    ///
922    #[must_use]
923    pub fn builder(
924        start_time: i64,
925        end_time: i64,
926    ) -> GetCloudMiningPaymentAndRefundHistoryParamsBuilder {
927        GetCloudMiningPaymentAndRefundHistoryParamsBuilder::default()
928            .start_time(start_time)
929            .end_time(end_time)
930    }
931}
932/// Request parameters for the [`query_user_delegation_history`] operation.
933///
934/// This struct holds all of the inputs you can pass when calling
935/// [`query_user_delegation_history`](#method.query_user_delegation_history).
936#[derive(Clone, Debug, Builder, Deserialize)]
937#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
938pub struct QueryUserDelegationHistoryParams {
939    ///
940    /// The `email` parameter.
941    ///
942    /// This field is **required.
943    #[builder(setter(into))]
944    #[serde(rename = "email")]
945    pub email: String,
946    ///
947    /// The `start_time` parameter.
948    ///
949    /// This field is **required.
950    #[builder(setter(into))]
951    #[serde(rename = "startTime")]
952    pub start_time: i64,
953    ///
954    /// The `end_time` parameter.
955    ///
956    /// This field is **required.
957    #[builder(setter(into))]
958    #[serde(rename = "endTime")]
959    pub end_time: i64,
960    ///
961    /// The `r#type` parameter.
962    ///
963    /// This field is **optional.
964    #[builder(setter(into), default)]
965    #[serde(rename = "type", default)]
966    pub r#type: Option<QueryUserDelegationHistoryTypeEnum>,
967    ///
968    /// The `asset` parameter.
969    ///
970    /// This field is **optional.
971    #[builder(setter(into), default)]
972    #[serde(rename = "asset", default)]
973    pub asset: Option<String>,
974    ///
975    /// The `current` parameter.
976    ///
977    /// This field is **optional.
978    #[builder(setter(into), default)]
979    #[serde(rename = "current", default)]
980    pub current: Option<i64>,
981    ///
982    /// The `size` parameter.
983    ///
984    /// This field is **optional.
985    #[builder(setter(into), default)]
986    #[serde(rename = "size", default)]
987    pub size: Option<i64>,
988    ///
989    /// The `recv_window` parameter.
990    ///
991    /// This field is **optional.
992    #[builder(setter(into), default)]
993    #[serde(rename = "recvWindow", default)]
994    pub recv_window: Option<i64>,
995}
996
997impl QueryUserDelegationHistoryParams {
998    /// Create a builder for [`query_user_delegation_history`].
999    ///
1000    /// Required parameters:
1001    ///
1002    /// * `email` — String
1003    /// * `start_time` — i64
1004    /// * `end_time` — i64
1005    ///
1006    #[must_use]
1007    pub fn builder(
1008        email: String,
1009        start_time: i64,
1010        end_time: i64,
1011    ) -> QueryUserDelegationHistoryParamsBuilder {
1012        QueryUserDelegationHistoryParamsBuilder::default()
1013            .email(email)
1014            .start_time(start_time)
1015            .end_time(end_time)
1016    }
1017}
1018/// Request parameters for the [`query_user_universal_transfer_history`] operation.
1019///
1020/// This struct holds all of the inputs you can pass when calling
1021/// [`query_user_universal_transfer_history`](#method.query_user_universal_transfer_history).
1022#[derive(Clone, Debug, Builder, Deserialize)]
1023#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1024pub struct QueryUserUniversalTransferHistoryParams {
1025    ///
1026    /// The `r#type` parameter.
1027    ///
1028    /// This field is **required.
1029    #[builder(setter(into))]
1030    #[serde(rename = "type")]
1031    pub r#type: String,
1032    ///
1033    /// The `start_time` parameter.
1034    ///
1035    /// This field is **optional.
1036    #[builder(setter(into), default)]
1037    #[serde(rename = "startTime", default)]
1038    pub start_time: Option<i64>,
1039    ///
1040    /// The `end_time` parameter.
1041    ///
1042    /// This field is **optional.
1043    #[builder(setter(into), default)]
1044    #[serde(rename = "endTime", default)]
1045    pub end_time: Option<i64>,
1046    ///
1047    /// The `current` parameter.
1048    ///
1049    /// This field is **optional.
1050    #[builder(setter(into), default)]
1051    #[serde(rename = "current", default)]
1052    pub current: Option<i64>,
1053    ///
1054    /// The `size` parameter.
1055    ///
1056    /// This field is **optional.
1057    #[builder(setter(into), default)]
1058    #[serde(rename = "size", default)]
1059    pub size: Option<i64>,
1060    ///
1061    /// The `from_symbol` parameter.
1062    ///
1063    /// This field is **optional.
1064    #[builder(setter(into), default)]
1065    #[serde(rename = "fromSymbol", default)]
1066    pub from_symbol: Option<QueryUserUniversalTransferHistoryFromSymbolEnum>,
1067    ///
1068    /// The `to_symbol` parameter.
1069    ///
1070    /// This field is **optional.
1071    #[builder(setter(into), default)]
1072    #[serde(rename = "toSymbol", default)]
1073    pub to_symbol: Option<QueryUserUniversalTransferHistoryToSymbolEnum>,
1074    ///
1075    /// The `recv_window` parameter.
1076    ///
1077    /// This field is **optional.
1078    #[builder(setter(into), default)]
1079    #[serde(rename = "recvWindow", default)]
1080    pub recv_window: Option<i64>,
1081}
1082
1083impl QueryUserUniversalTransferHistoryParams {
1084    /// Create a builder for [`query_user_universal_transfer_history`].
1085    ///
1086    /// Required parameters:
1087    ///
1088    /// * `r#type` — String
1089    ///
1090    #[must_use]
1091    pub fn builder(r#type: String) -> QueryUserUniversalTransferHistoryParamsBuilder {
1092        QueryUserUniversalTransferHistoryParamsBuilder::default().r#type(r#type)
1093    }
1094}
1095/// Request parameters for the [`query_user_wallet_balance`] operation.
1096///
1097/// This struct holds all of the inputs you can pass when calling
1098/// [`query_user_wallet_balance`](#method.query_user_wallet_balance).
1099#[derive(Clone, Debug, Builder, Deserialize, Default)]
1100#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1101pub struct QueryUserWalletBalanceParams {
1102    ///
1103    /// The `quote_asset` parameter.
1104    ///
1105    /// This field is **optional.
1106    #[builder(setter(into), default)]
1107    #[serde(rename = "quoteAsset", default)]
1108    pub quote_asset: Option<String>,
1109    ///
1110    /// The `recv_window` parameter.
1111    ///
1112    /// This field is **optional.
1113    #[builder(setter(into), default)]
1114    #[serde(rename = "recvWindow", default)]
1115    pub recv_window: Option<i64>,
1116}
1117
1118impl QueryUserWalletBalanceParams {
1119    /// Create a builder for [`query_user_wallet_balance`].
1120    ///
1121    #[must_use]
1122    pub fn builder() -> QueryUserWalletBalanceParamsBuilder {
1123        QueryUserWalletBalanceParamsBuilder::default()
1124    }
1125}
1126/// Request parameters for the [`toggle_bnb_burn_on_spot_trade_and_margin_interest`] operation.
1127///
1128/// This struct holds all of the inputs you can pass when calling
1129/// [`toggle_bnb_burn_on_spot_trade_and_margin_interest`](#method.toggle_bnb_burn_on_spot_trade_and_margin_interest).
1130#[derive(Clone, Debug, Builder, Deserialize, Default)]
1131#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1132pub struct ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
1133    /// Determines whether to use BNB to pay for trading fees on SPOT
1134    ///
1135    /// This field is **optional.
1136    #[builder(setter(into), default)]
1137    #[serde(rename = "spotBNBBurn", default)]
1138    pub spot_bnb_burn: Option<String>,
1139    /// Determines whether to use BNB to pay for margin loan's interest
1140    ///
1141    /// This field is **optional.
1142    #[builder(setter(into), default)]
1143    #[serde(rename = "interestBNBBurn", default)]
1144    pub interest_bnb_burn: Option<String>,
1145    ///
1146    /// The `recv_window` parameter.
1147    ///
1148    /// This field is **optional.
1149    #[builder(setter(into), default)]
1150    #[serde(rename = "recvWindow", default)]
1151    pub recv_window: Option<i64>,
1152}
1153
1154impl ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
1155    /// Create a builder for [`toggle_bnb_burn_on_spot_trade_and_margin_interest`].
1156    ///
1157    #[must_use]
1158    pub fn builder() -> ToggleBnbBurnOnSpotTradeAndMarginInterestParamsBuilder {
1159        ToggleBnbBurnOnSpotTradeAndMarginInterestParamsBuilder::default()
1160    }
1161}
1162/// Request parameters for the [`trade_fee`] operation.
1163///
1164/// This struct holds all of the inputs you can pass when calling
1165/// [`trade_fee`](#method.trade_fee).
1166#[derive(Clone, Debug, Builder, Deserialize, Default)]
1167#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1168pub struct TradeFeeParams {
1169    ///
1170    /// The `symbol` parameter.
1171    ///
1172    /// This field is **optional.
1173    #[builder(setter(into), default)]
1174    #[serde(rename = "symbol", default)]
1175    pub symbol: Option<String>,
1176    ///
1177    /// The `recv_window` parameter.
1178    ///
1179    /// This field is **optional.
1180    #[builder(setter(into), default)]
1181    #[serde(rename = "recvWindow", default)]
1182    pub recv_window: Option<i64>,
1183}
1184
1185impl TradeFeeParams {
1186    /// Create a builder for [`trade_fee`].
1187    ///
1188    #[must_use]
1189    pub fn builder() -> TradeFeeParamsBuilder {
1190        TradeFeeParamsBuilder::default()
1191    }
1192}
1193/// Request parameters for the [`user_asset`] operation.
1194///
1195/// This struct holds all of the inputs you can pass when calling
1196/// [`user_asset`](#method.user_asset).
1197#[derive(Clone, Debug, Builder, Deserialize, Default)]
1198#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1199pub struct UserAssetParams {
1200    /// If asset is blank, then query all positive assets user have.
1201    ///
1202    /// This field is **optional.
1203    #[builder(setter(into), default)]
1204    #[serde(rename = "asset", default)]
1205    pub asset: Option<String>,
1206    /// Whether need btc valuation or not.
1207    ///
1208    /// This field is **optional.
1209    #[builder(setter(into), default)]
1210    #[serde(rename = "needBtcValuation", default)]
1211    pub need_btc_valuation: Option<bool>,
1212    ///
1213    /// The `recv_window` parameter.
1214    ///
1215    /// This field is **optional.
1216    #[builder(setter(into), default)]
1217    #[serde(rename = "recvWindow", default)]
1218    pub recv_window: Option<i64>,
1219}
1220
1221impl UserAssetParams {
1222    /// Create a builder for [`user_asset`].
1223    ///
1224    #[must_use]
1225    pub fn builder() -> UserAssetParamsBuilder {
1226        UserAssetParamsBuilder::default()
1227    }
1228}
1229/// Request parameters for the [`user_universal_transfer`] operation.
1230///
1231/// This struct holds all of the inputs you can pass when calling
1232/// [`user_universal_transfer`](#method.user_universal_transfer).
1233#[derive(Clone, Debug, Builder, Deserialize)]
1234#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
1235pub struct UserUniversalTransferParams {
1236    ///
1237    /// The `r#type` parameter.
1238    ///
1239    /// This field is **required.
1240    #[builder(setter(into))]
1241    #[serde(rename = "type")]
1242    pub r#type: UserUniversalTransferTypeEnum,
1243    ///
1244    /// The `asset` parameter.
1245    ///
1246    /// This field is **required.
1247    #[builder(setter(into))]
1248    #[serde(rename = "asset")]
1249    pub asset: String,
1250    ///
1251    /// The `amount` parameter.
1252    ///
1253    /// This field is **required.
1254    #[builder(setter(into))]
1255    #[serde(rename = "amount")]
1256    pub amount: rust_decimal::Decimal,
1257    ///
1258    /// The `from_symbol` parameter.
1259    ///
1260    /// This field is **optional.
1261    #[builder(setter(into), default)]
1262    #[serde(rename = "fromSymbol", default)]
1263    pub from_symbol: Option<UserUniversalTransferFromSymbolEnum>,
1264    ///
1265    /// The `to_symbol` parameter.
1266    ///
1267    /// This field is **optional.
1268    #[builder(setter(into), default)]
1269    #[serde(rename = "toSymbol", default)]
1270    pub to_symbol: Option<UserUniversalTransferToSymbolEnum>,
1271    ///
1272    /// The `recv_window` parameter.
1273    ///
1274    /// This field is **optional.
1275    #[builder(setter(into), default)]
1276    #[serde(rename = "recvWindow", default)]
1277    pub recv_window: Option<i64>,
1278}
1279
1280impl UserUniversalTransferParams {
1281    /// Create a builder for [`user_universal_transfer`].
1282    ///
1283    /// Required parameters:
1284    ///
1285    /// * `r#type` — String
1286    /// * `asset` — String
1287    /// * `amount` — `rust_decimal::Decimal`
1288    ///
1289    #[must_use]
1290    pub fn builder(
1291        r#type: UserUniversalTransferTypeEnum,
1292        asset: String,
1293        amount: rust_decimal::Decimal,
1294    ) -> UserUniversalTransferParamsBuilder {
1295        UserUniversalTransferParamsBuilder::default()
1296            .r#type(r#type)
1297            .asset(asset)
1298            .amount(amount)
1299    }
1300}
1301
1302#[async_trait]
1303impl AssetApi for AssetApiClient {
1304    async fn asset_detail(
1305        &self,
1306        params: AssetDetailParams,
1307    ) -> anyhow::Result<RestApiResponse<models::AssetDetailResponse>> {
1308        let AssetDetailParams { asset, recv_window } = params;
1309
1310        let mut query_params = BTreeMap::new();
1311        let body_params = BTreeMap::new();
1312
1313        if let Some(rw) = asset {
1314            query_params.insert("asset".to_string(), json!(rw));
1315        }
1316
1317        if let Some(rw) = recv_window {
1318            query_params.insert("recvWindow".to_string(), json!(rw));
1319        }
1320
1321        send_request::<models::AssetDetailResponse>(
1322            &self.configuration,
1323            "/sapi/v1/asset/assetDetail",
1324            reqwest::Method::GET,
1325            query_params,
1326            body_params,
1327            if HAS_TIME_UNIT {
1328                self.configuration.time_unit
1329            } else {
1330                None
1331            },
1332            true,
1333        )
1334        .await
1335    }
1336
1337    async fn asset_dividend_record(
1338        &self,
1339        params: AssetDividendRecordParams,
1340    ) -> anyhow::Result<RestApiResponse<models::AssetDividendRecordResponse>> {
1341        let AssetDividendRecordParams {
1342            asset,
1343            start_time,
1344            end_time,
1345            limit,
1346            recv_window,
1347        } = params;
1348
1349        let mut query_params = BTreeMap::new();
1350        let body_params = BTreeMap::new();
1351
1352        if let Some(rw) = asset {
1353            query_params.insert("asset".to_string(), json!(rw));
1354        }
1355
1356        if let Some(rw) = start_time {
1357            query_params.insert("startTime".to_string(), json!(rw));
1358        }
1359
1360        if let Some(rw) = end_time {
1361            query_params.insert("endTime".to_string(), json!(rw));
1362        }
1363
1364        if let Some(rw) = limit {
1365            query_params.insert("limit".to_string(), json!(rw));
1366        }
1367
1368        if let Some(rw) = recv_window {
1369            query_params.insert("recvWindow".to_string(), json!(rw));
1370        }
1371
1372        send_request::<models::AssetDividendRecordResponse>(
1373            &self.configuration,
1374            "/sapi/v1/asset/assetDividend",
1375            reqwest::Method::GET,
1376            query_params,
1377            body_params,
1378            if HAS_TIME_UNIT {
1379                self.configuration.time_unit
1380            } else {
1381                None
1382            },
1383            true,
1384        )
1385        .await
1386    }
1387
1388    async fn dust_convert(
1389        &self,
1390        params: DustConvertParams,
1391    ) -> anyhow::Result<RestApiResponse<models::DustConvertResponse>> {
1392        let DustConvertParams {
1393            asset,
1394            account_type,
1395            client_id,
1396            target_asset,
1397            third_party_client_id,
1398            dust_quota_asset_to_target_asset_price,
1399        } = params;
1400
1401        let mut query_params = BTreeMap::new();
1402        let body_params = BTreeMap::new();
1403
1404        query_params.insert("asset".to_string(), json!(asset));
1405
1406        if let Some(rw) = account_type {
1407            query_params.insert("accountType".to_string(), json!(rw));
1408        }
1409
1410        if let Some(rw) = client_id {
1411            query_params.insert("clientId".to_string(), json!(rw));
1412        }
1413
1414        if let Some(rw) = target_asset {
1415            query_params.insert("targetAsset".to_string(), json!(rw));
1416        }
1417
1418        if let Some(rw) = third_party_client_id {
1419            query_params.insert("thirdPartyClientId".to_string(), json!(rw));
1420        }
1421
1422        if let Some(rw) = dust_quota_asset_to_target_asset_price {
1423            query_params.insert("dustQuotaAssetToTargetAssetPrice".to_string(), json!(rw));
1424        }
1425
1426        send_request::<models::DustConvertResponse>(
1427            &self.configuration,
1428            "/sapi/v1/asset/dust-convert/convert",
1429            reqwest::Method::POST,
1430            query_params,
1431            body_params,
1432            if HAS_TIME_UNIT {
1433                self.configuration.time_unit
1434            } else {
1435                None
1436            },
1437            true,
1438        )
1439        .await
1440    }
1441
1442    async fn dust_convertible_assets(
1443        &self,
1444        params: DustConvertibleAssetsParams,
1445    ) -> anyhow::Result<RestApiResponse<models::DustConvertibleAssetsResponse>> {
1446        let DustConvertibleAssetsParams {
1447            target_asset,
1448            account_type,
1449            dust_quota_asset_to_target_asset_price,
1450        } = params;
1451
1452        let mut query_params = BTreeMap::new();
1453        let body_params = BTreeMap::new();
1454
1455        if let Some(rw) = account_type {
1456            query_params.insert("accountType".to_string(), json!(rw));
1457        }
1458
1459        query_params.insert("targetAsset".to_string(), json!(target_asset));
1460
1461        if let Some(rw) = dust_quota_asset_to_target_asset_price {
1462            query_params.insert("dustQuotaAssetToTargetAssetPrice".to_string(), json!(rw));
1463        }
1464
1465        send_request::<models::DustConvertibleAssetsResponse>(
1466            &self.configuration,
1467            "/sapi/v1/asset/dust-convert/query-convertible-assets",
1468            reqwest::Method::POST,
1469            query_params,
1470            body_params,
1471            if HAS_TIME_UNIT {
1472                self.configuration.time_unit
1473            } else {
1474                None
1475            },
1476            true,
1477        )
1478        .await
1479    }
1480
1481    async fn dust_transfer(
1482        &self,
1483        params: DustTransferParams,
1484    ) -> anyhow::Result<RestApiResponse<models::DustTransferResponse>> {
1485        let DustTransferParams {
1486            asset,
1487            account_type,
1488            recv_window,
1489        } = params;
1490
1491        let mut query_params = BTreeMap::new();
1492        let body_params = BTreeMap::new();
1493
1494        query_params.insert("asset".to_string(), json!(asset));
1495
1496        if let Some(rw) = account_type {
1497            query_params.insert("accountType".to_string(), json!(rw));
1498        }
1499
1500        if let Some(rw) = recv_window {
1501            query_params.insert("recvWindow".to_string(), json!(rw));
1502        }
1503
1504        send_request::<models::DustTransferResponse>(
1505            &self.configuration,
1506            "/sapi/v1/asset/dust",
1507            reqwest::Method::POST,
1508            query_params,
1509            body_params,
1510            if HAS_TIME_UNIT {
1511                self.configuration.time_unit
1512            } else {
1513                None
1514            },
1515            true,
1516        )
1517        .await
1518    }
1519
1520    async fn dustlog(
1521        &self,
1522        params: DustlogParams,
1523    ) -> anyhow::Result<RestApiResponse<models::DustlogResponse>> {
1524        let DustlogParams {
1525            account_type,
1526            start_time,
1527            end_time,
1528            recv_window,
1529        } = params;
1530
1531        let mut query_params = BTreeMap::new();
1532        let body_params = BTreeMap::new();
1533
1534        if let Some(rw) = account_type {
1535            query_params.insert("accountType".to_string(), json!(rw));
1536        }
1537
1538        if let Some(rw) = start_time {
1539            query_params.insert("startTime".to_string(), json!(rw));
1540        }
1541
1542        if let Some(rw) = end_time {
1543            query_params.insert("endTime".to_string(), json!(rw));
1544        }
1545
1546        if let Some(rw) = recv_window {
1547            query_params.insert("recvWindow".to_string(), json!(rw));
1548        }
1549
1550        send_request::<models::DustlogResponse>(
1551            &self.configuration,
1552            "/sapi/v1/asset/dribblet",
1553            reqwest::Method::GET,
1554            query_params,
1555            body_params,
1556            if HAS_TIME_UNIT {
1557                self.configuration.time_unit
1558            } else {
1559                None
1560            },
1561            true,
1562        )
1563        .await
1564    }
1565
1566    async fn funding_wallet(
1567        &self,
1568        params: FundingWalletParams,
1569    ) -> anyhow::Result<RestApiResponse<Vec<models::FundingWalletResponseInner>>> {
1570        let FundingWalletParams {
1571            asset,
1572            need_btc_valuation,
1573            recv_window,
1574        } = params;
1575
1576        let mut query_params = BTreeMap::new();
1577        let body_params = BTreeMap::new();
1578
1579        if let Some(rw) = asset {
1580            query_params.insert("asset".to_string(), json!(rw));
1581        }
1582
1583        if let Some(rw) = need_btc_valuation {
1584            query_params.insert("needBtcValuation".to_string(), json!(rw));
1585        }
1586
1587        if let Some(rw) = recv_window {
1588            query_params.insert("recvWindow".to_string(), json!(rw));
1589        }
1590
1591        send_request::<Vec<models::FundingWalletResponseInner>>(
1592            &self.configuration,
1593            "/sapi/v1/asset/get-funding-asset",
1594            reqwest::Method::POST,
1595            query_params,
1596            body_params,
1597            if HAS_TIME_UNIT {
1598                self.configuration.time_unit
1599            } else {
1600                None
1601            },
1602            true,
1603        )
1604        .await
1605    }
1606
1607    async fn get_assets_that_can_be_converted_into_bnb(
1608        &self,
1609        params: GetAssetsThatCanBeConvertedIntoBnbParams,
1610    ) -> anyhow::Result<RestApiResponse<models::GetAssetsThatCanBeConvertedIntoBnbResponse>> {
1611        let GetAssetsThatCanBeConvertedIntoBnbParams {
1612            account_type,
1613            recv_window,
1614        } = params;
1615
1616        let mut query_params = BTreeMap::new();
1617        let body_params = BTreeMap::new();
1618
1619        if let Some(rw) = account_type {
1620            query_params.insert("accountType".to_string(), json!(rw));
1621        }
1622
1623        if let Some(rw) = recv_window {
1624            query_params.insert("recvWindow".to_string(), json!(rw));
1625        }
1626
1627        send_request::<models::GetAssetsThatCanBeConvertedIntoBnbResponse>(
1628            &self.configuration,
1629            "/sapi/v1/asset/dust-btc",
1630            reqwest::Method::POST,
1631            query_params,
1632            body_params,
1633            if HAS_TIME_UNIT {
1634                self.configuration.time_unit
1635            } else {
1636                None
1637            },
1638            true,
1639        )
1640        .await
1641    }
1642
1643    async fn get_cloud_mining_payment_and_refund_history(
1644        &self,
1645        params: GetCloudMiningPaymentAndRefundHistoryParams,
1646    ) -> anyhow::Result<RestApiResponse<models::GetCloudMiningPaymentAndRefundHistoryResponse>>
1647    {
1648        let GetCloudMiningPaymentAndRefundHistoryParams {
1649            start_time,
1650            end_time,
1651            tran_id,
1652            client_tran_id,
1653            asset,
1654            current,
1655            size,
1656        } = params;
1657
1658        let mut query_params = BTreeMap::new();
1659        let body_params = BTreeMap::new();
1660
1661        if let Some(rw) = tran_id {
1662            query_params.insert("tranId".to_string(), json!(rw));
1663        }
1664
1665        if let Some(rw) = client_tran_id {
1666            query_params.insert("clientTranId".to_string(), json!(rw));
1667        }
1668
1669        if let Some(rw) = asset {
1670            query_params.insert("asset".to_string(), json!(rw));
1671        }
1672
1673        query_params.insert("startTime".to_string(), json!(start_time));
1674
1675        query_params.insert("endTime".to_string(), json!(end_time));
1676
1677        if let Some(rw) = current {
1678            query_params.insert("current".to_string(), json!(rw));
1679        }
1680
1681        if let Some(rw) = size {
1682            query_params.insert("size".to_string(), json!(rw));
1683        }
1684
1685        send_request::<models::GetCloudMiningPaymentAndRefundHistoryResponse>(
1686            &self.configuration,
1687            "/sapi/v1/asset/ledger-transfer/cloud-mining/queryByPage",
1688            reqwest::Method::GET,
1689            query_params,
1690            body_params,
1691            if HAS_TIME_UNIT {
1692                self.configuration.time_unit
1693            } else {
1694                None
1695            },
1696            true,
1697        )
1698        .await
1699    }
1700
1701    async fn get_open_symbol_list(
1702        &self,
1703    ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenSymbolListResponseInner>>> {
1704        let query_params = BTreeMap::new();
1705        let body_params = BTreeMap::new();
1706
1707        send_request::<Vec<models::GetOpenSymbolListResponseInner>>(
1708            &self.configuration,
1709            "/sapi/v1/spot/open-symbol-list",
1710            reqwest::Method::GET,
1711            query_params,
1712            body_params,
1713            if HAS_TIME_UNIT {
1714                self.configuration.time_unit
1715            } else {
1716                None
1717            },
1718            false,
1719        )
1720        .await
1721    }
1722
1723    async fn query_user_delegation_history(
1724        &self,
1725        params: QueryUserDelegationHistoryParams,
1726    ) -> anyhow::Result<RestApiResponse<models::QueryUserDelegationHistoryResponse>> {
1727        let QueryUserDelegationHistoryParams {
1728            email,
1729            start_time,
1730            end_time,
1731            r#type,
1732            asset,
1733            current,
1734            size,
1735            recv_window,
1736        } = params;
1737
1738        let mut query_params = BTreeMap::new();
1739        let body_params = BTreeMap::new();
1740
1741        query_params.insert("email".to_string(), json!(email));
1742
1743        query_params.insert("startTime".to_string(), json!(start_time));
1744
1745        query_params.insert("endTime".to_string(), json!(end_time));
1746
1747        if let Some(rw) = r#type {
1748            query_params.insert("type".to_string(), json!(rw));
1749        }
1750
1751        if let Some(rw) = asset {
1752            query_params.insert("asset".to_string(), json!(rw));
1753        }
1754
1755        if let Some(rw) = current {
1756            query_params.insert("current".to_string(), json!(rw));
1757        }
1758
1759        if let Some(rw) = size {
1760            query_params.insert("size".to_string(), json!(rw));
1761        }
1762
1763        if let Some(rw) = recv_window {
1764            query_params.insert("recvWindow".to_string(), json!(rw));
1765        }
1766
1767        send_request::<models::QueryUserDelegationHistoryResponse>(
1768            &self.configuration,
1769            "/sapi/v1/asset/custody/transfer-history",
1770            reqwest::Method::GET,
1771            query_params,
1772            body_params,
1773            if HAS_TIME_UNIT {
1774                self.configuration.time_unit
1775            } else {
1776                None
1777            },
1778            true,
1779        )
1780        .await
1781    }
1782
1783    async fn query_user_universal_transfer_history(
1784        &self,
1785        params: QueryUserUniversalTransferHistoryParams,
1786    ) -> anyhow::Result<RestApiResponse<models::QueryUserUniversalTransferHistoryResponse>> {
1787        let QueryUserUniversalTransferHistoryParams {
1788            r#type,
1789            start_time,
1790            end_time,
1791            current,
1792            size,
1793            from_symbol,
1794            to_symbol,
1795            recv_window,
1796        } = params;
1797
1798        let mut query_params = BTreeMap::new();
1799        let body_params = BTreeMap::new();
1800
1801        query_params.insert("type".to_string(), json!(r#type));
1802
1803        if let Some(rw) = start_time {
1804            query_params.insert("startTime".to_string(), json!(rw));
1805        }
1806
1807        if let Some(rw) = end_time {
1808            query_params.insert("endTime".to_string(), json!(rw));
1809        }
1810
1811        if let Some(rw) = current {
1812            query_params.insert("current".to_string(), json!(rw));
1813        }
1814
1815        if let Some(rw) = size {
1816            query_params.insert("size".to_string(), json!(rw));
1817        }
1818
1819        if let Some(rw) = from_symbol {
1820            query_params.insert("fromSymbol".to_string(), json!(rw));
1821        }
1822
1823        if let Some(rw) = to_symbol {
1824            query_params.insert("toSymbol".to_string(), json!(rw));
1825        }
1826
1827        if let Some(rw) = recv_window {
1828            query_params.insert("recvWindow".to_string(), json!(rw));
1829        }
1830
1831        send_request::<models::QueryUserUniversalTransferHistoryResponse>(
1832            &self.configuration,
1833            "/sapi/v1/asset/transfer",
1834            reqwest::Method::GET,
1835            query_params,
1836            body_params,
1837            if HAS_TIME_UNIT {
1838                self.configuration.time_unit
1839            } else {
1840                None
1841            },
1842            true,
1843        )
1844        .await
1845    }
1846
1847    async fn query_user_wallet_balance(
1848        &self,
1849        params: QueryUserWalletBalanceParams,
1850    ) -> anyhow::Result<RestApiResponse<Vec<models::QueryUserWalletBalanceResponseInner>>> {
1851        let QueryUserWalletBalanceParams {
1852            quote_asset,
1853            recv_window,
1854        } = params;
1855
1856        let mut query_params = BTreeMap::new();
1857        let body_params = BTreeMap::new();
1858
1859        if let Some(rw) = quote_asset {
1860            query_params.insert("quoteAsset".to_string(), json!(rw));
1861        }
1862
1863        if let Some(rw) = recv_window {
1864            query_params.insert("recvWindow".to_string(), json!(rw));
1865        }
1866
1867        send_request::<Vec<models::QueryUserWalletBalanceResponseInner>>(
1868            &self.configuration,
1869            "/sapi/v1/asset/wallet/balance",
1870            reqwest::Method::GET,
1871            query_params,
1872            body_params,
1873            if HAS_TIME_UNIT {
1874                self.configuration.time_unit
1875            } else {
1876                None
1877            },
1878            true,
1879        )
1880        .await
1881    }
1882
1883    async fn toggle_bnb_burn_on_spot_trade_and_margin_interest(
1884        &self,
1885        params: ToggleBnbBurnOnSpotTradeAndMarginInterestParams,
1886    ) -> anyhow::Result<RestApiResponse<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>>
1887    {
1888        let ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
1889            spot_bnb_burn,
1890            interest_bnb_burn,
1891            recv_window,
1892        } = params;
1893
1894        let mut query_params = BTreeMap::new();
1895        let body_params = BTreeMap::new();
1896
1897        if let Some(rw) = spot_bnb_burn {
1898            query_params.insert("spotBNBBurn".to_string(), json!(rw));
1899        }
1900
1901        if let Some(rw) = interest_bnb_burn {
1902            query_params.insert("interestBNBBurn".to_string(), json!(rw));
1903        }
1904
1905        if let Some(rw) = recv_window {
1906            query_params.insert("recvWindow".to_string(), json!(rw));
1907        }
1908
1909        send_request::<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>(
1910            &self.configuration,
1911            "/sapi/v1/bnbBurn",
1912            reqwest::Method::POST,
1913            query_params,
1914            body_params,
1915            if HAS_TIME_UNIT {
1916                self.configuration.time_unit
1917            } else {
1918                None
1919            },
1920            true,
1921        )
1922        .await
1923    }
1924
1925    async fn trade_fee(
1926        &self,
1927        params: TradeFeeParams,
1928    ) -> anyhow::Result<RestApiResponse<Vec<models::TradeFeeResponseInner>>> {
1929        let TradeFeeParams {
1930            symbol,
1931            recv_window,
1932        } = params;
1933
1934        let mut query_params = BTreeMap::new();
1935        let body_params = BTreeMap::new();
1936
1937        if let Some(rw) = symbol {
1938            query_params.insert("symbol".to_string(), json!(rw));
1939        }
1940
1941        if let Some(rw) = recv_window {
1942            query_params.insert("recvWindow".to_string(), json!(rw));
1943        }
1944
1945        send_request::<Vec<models::TradeFeeResponseInner>>(
1946            &self.configuration,
1947            "/sapi/v1/asset/tradeFee",
1948            reqwest::Method::GET,
1949            query_params,
1950            body_params,
1951            if HAS_TIME_UNIT {
1952                self.configuration.time_unit
1953            } else {
1954                None
1955            },
1956            true,
1957        )
1958        .await
1959    }
1960
1961    async fn user_asset(
1962        &self,
1963        params: UserAssetParams,
1964    ) -> anyhow::Result<RestApiResponse<Vec<models::UserAssetResponseInner>>> {
1965        let UserAssetParams {
1966            asset,
1967            need_btc_valuation,
1968            recv_window,
1969        } = params;
1970
1971        let mut query_params = BTreeMap::new();
1972        let body_params = BTreeMap::new();
1973
1974        if let Some(rw) = asset {
1975            query_params.insert("asset".to_string(), json!(rw));
1976        }
1977
1978        if let Some(rw) = need_btc_valuation {
1979            query_params.insert("needBtcValuation".to_string(), json!(rw));
1980        }
1981
1982        if let Some(rw) = recv_window {
1983            query_params.insert("recvWindow".to_string(), json!(rw));
1984        }
1985
1986        send_request::<Vec<models::UserAssetResponseInner>>(
1987            &self.configuration,
1988            "/sapi/v3/asset/getUserAsset",
1989            reqwest::Method::POST,
1990            query_params,
1991            body_params,
1992            if HAS_TIME_UNIT {
1993                self.configuration.time_unit
1994            } else {
1995                None
1996            },
1997            true,
1998        )
1999        .await
2000    }
2001
2002    async fn user_universal_transfer(
2003        &self,
2004        params: UserUniversalTransferParams,
2005    ) -> anyhow::Result<RestApiResponse<models::UserUniversalTransferResponse>> {
2006        let UserUniversalTransferParams {
2007            r#type,
2008            asset,
2009            amount,
2010            from_symbol,
2011            to_symbol,
2012            recv_window,
2013        } = params;
2014
2015        let mut query_params = BTreeMap::new();
2016        let body_params = BTreeMap::new();
2017
2018        query_params.insert("type".to_string(), json!(r#type));
2019
2020        query_params.insert("asset".to_string(), json!(asset));
2021
2022        query_params.insert("amount".to_string(), json!(amount));
2023
2024        if let Some(rw) = from_symbol {
2025            query_params.insert("fromSymbol".to_string(), json!(rw));
2026        }
2027
2028        if let Some(rw) = to_symbol {
2029            query_params.insert("toSymbol".to_string(), json!(rw));
2030        }
2031
2032        if let Some(rw) = recv_window {
2033            query_params.insert("recvWindow".to_string(), json!(rw));
2034        }
2035
2036        send_request::<models::UserUniversalTransferResponse>(
2037            &self.configuration,
2038            "/sapi/v1/asset/transfer",
2039            reqwest::Method::POST,
2040            query_params,
2041            body_params,
2042            if HAS_TIME_UNIT {
2043                self.configuration.time_unit
2044            } else {
2045                None
2046            },
2047            true,
2048        )
2049        .await
2050    }
2051}
2052
2053#[cfg(all(test, feature = "wallet"))]
2054mod tests {
2055    use super::*;
2056    use crate::TOKIO_SHARED_RT;
2057    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
2058    use async_trait::async_trait;
2059    use std::collections::HashMap;
2060
2061    struct DummyRestApiResponse<T> {
2062        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
2063        status: u16,
2064        headers: HashMap<String, String>,
2065        rate_limits: Option<Vec<RestApiRateLimit>>,
2066    }
2067
2068    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
2069        fn from(dummy: DummyRestApiResponse<T>) -> Self {
2070            Self {
2071                data_fn: dummy.inner,
2072                status: dummy.status,
2073                headers: dummy.headers,
2074                rate_limits: dummy.rate_limits,
2075            }
2076        }
2077    }
2078
2079    struct MockAssetApiClient {
2080        force_error: bool,
2081    }
2082
2083    #[async_trait]
2084    impl AssetApi for MockAssetApiClient {
2085        async fn asset_detail(
2086            &self,
2087            _params: AssetDetailParams,
2088        ) -> anyhow::Result<RestApiResponse<models::AssetDetailResponse>> {
2089            if self.force_error {
2090                return Err(ConnectorError::ConnectorClientError {
2091                    msg: "ResponseError".to_string(),
2092                    code: None,
2093                }
2094                .into());
2095            }
2096
2097            let resp_json: Value = serde_json::from_str(r#"{"CTR":{"minWithdrawAmount":"70.00000000","depositStatus":false,"withdrawFee":35,"withdrawStatus":true,"depositTip":"Delisted, Deposit Suspended"},"SKY":{"minWithdrawAmount":"0.02000000","depositStatus":true,"withdrawFee":0.01,"withdrawStatus":true}}"#).unwrap_or_else(|_| serde_json::json!({}));
2098            let dummy_response: models::AssetDetailResponse =
2099                serde_json::from_value(resp_json.clone())
2100                    .expect("should parse into models::AssetDetailResponse");
2101
2102            let dummy = DummyRestApiResponse {
2103                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2104                status: 200,
2105                headers: HashMap::new(),
2106                rate_limits: None,
2107            };
2108
2109            Ok(dummy.into())
2110        }
2111
2112        async fn asset_dividend_record(
2113            &self,
2114            _params: AssetDividendRecordParams,
2115        ) -> anyhow::Result<RestApiResponse<models::AssetDividendRecordResponse>> {
2116            if self.force_error {
2117                return Err(ConnectorError::ConnectorClientError {
2118                    msg: "ResponseError".to_string(),
2119                    code: None,
2120                }
2121                .into());
2122            }
2123
2124            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"id":1637366104,"amount":"10.00000000","asset":"BHFT","divTime":1563189166000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap_or_else(|_| serde_json::json!({}));
2125            let dummy_response: models::AssetDividendRecordResponse =
2126                serde_json::from_value(resp_json.clone())
2127                    .expect("should parse into models::AssetDividendRecordResponse");
2128
2129            let dummy = DummyRestApiResponse {
2130                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2131                status: 200,
2132                headers: HashMap::new(),
2133                rate_limits: None,
2134            };
2135
2136            Ok(dummy.into())
2137        }
2138
2139        async fn dust_convert(
2140            &self,
2141            _params: DustConvertParams,
2142        ) -> anyhow::Result<RestApiResponse<models::DustConvertResponse>> {
2143            if self.force_error {
2144                return Err(ConnectorError::ConnectorClientError {
2145                    msg: "ResponseError".to_string(),
2146                    code: None,
2147                }
2148                .into());
2149            }
2150
2151            let resp_json: Value = serde_json::from_str(r#"{"totalTransfered":"3.5971223","totalServiceCharge":"0.0794964","transferResult":[{"tranId":2987331510,"fromAsset":"USDT","amount":"1","transferedAmount":"3.5971223","serviceChargeAmount":"0.0794964","operateTime":1765212029749}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2152            let dummy_response: models::DustConvertResponse =
2153                serde_json::from_value(resp_json.clone())
2154                    .expect("should parse into models::DustConvertResponse");
2155
2156            let dummy = DummyRestApiResponse {
2157                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2158                status: 200,
2159                headers: HashMap::new(),
2160                rate_limits: None,
2161            };
2162
2163            Ok(dummy.into())
2164        }
2165
2166        async fn dust_convertible_assets(
2167            &self,
2168            _params: DustConvertibleAssetsParams,
2169        ) -> anyhow::Result<RestApiResponse<models::DustConvertibleAssetsResponse>> {
2170            if self.force_error {
2171                return Err(ConnectorError::ConnectorClientError {
2172                    msg: "ResponseError".to_string(),
2173                    code: None,
2174                }
2175                .into());
2176            }
2177
2178            let resp_json: Value = serde_json::from_str(r#"{"dribbletPercentage":"0.02","totalTransferQuotaAssetAmount":"0.7899968","totalTransferTargetAssetAmount":"0.7899968","dribbletBase":"10","details":[{"asset":"AR","assetFullName":"AR","amountFree":"0.00856","exchange":"0.00073616","toQuotaAssetAmount":"0.036808","toTargetAssetAmount":"0.036808","toTargetAssetOffExchange":"0.03607184"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2179            let dummy_response: models::DustConvertibleAssetsResponse =
2180                serde_json::from_value(resp_json.clone())
2181                    .expect("should parse into models::DustConvertibleAssetsResponse");
2182
2183            let dummy = DummyRestApiResponse {
2184                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2185                status: 200,
2186                headers: HashMap::new(),
2187                rate_limits: None,
2188            };
2189
2190            Ok(dummy.into())
2191        }
2192
2193        async fn dust_transfer(
2194            &self,
2195            _params: DustTransferParams,
2196        ) -> anyhow::Result<RestApiResponse<models::DustTransferResponse>> {
2197            if self.force_error {
2198                return Err(ConnectorError::ConnectorClientError {
2199                    msg: "ResponseError".to_string(),
2200                    code: None,
2201                }
2202                .into());
2203            }
2204
2205            let resp_json: Value = serde_json::from_str(r#"{"totalServiceCharge":"0.02102542","totalTransfered":"1.05127099","transferResult":[{"amount":"0.03000000","fromAsset":"ETH","operateTime":1563368549307,"serviceChargeAmount":"0.00500000","tranId":2970932918,"transferedAmount":"0.25000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2206            let dummy_response: models::DustTransferResponse =
2207                serde_json::from_value(resp_json.clone())
2208                    .expect("should parse into models::DustTransferResponse");
2209
2210            let dummy = DummyRestApiResponse {
2211                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2212                status: 200,
2213                headers: HashMap::new(),
2214                rate_limits: None,
2215            };
2216
2217            Ok(dummy.into())
2218        }
2219
2220        async fn dustlog(
2221            &self,
2222            _params: DustlogParams,
2223        ) -> anyhow::Result<RestApiResponse<models::DustlogResponse>> {
2224            if self.force_error {
2225                return Err(ConnectorError::ConnectorClientError {
2226                    msg: "ResponseError".to_string(),
2227                    code: None,
2228                }
2229                .into());
2230            }
2231
2232            let resp_json: Value = serde_json::from_str(r#"{"total":8,"userAssetDribblets":[{"operateTime":1615985535000,"totalTransferedAmount":"0.00132256","totalServiceChargeAmount":"0.00002699","transId":45178372831,"userAssetDribbletDetails":[{"transId":4359321,"serviceChargeAmount":"0.000009","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.000441","fromAsset":"USDT","targetAsset":"BNB"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2233            let dummy_response: models::DustlogResponse = serde_json::from_value(resp_json.clone())
2234                .expect("should parse into models::DustlogResponse");
2235
2236            let dummy = DummyRestApiResponse {
2237                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2238                status: 200,
2239                headers: HashMap::new(),
2240                rate_limits: None,
2241            };
2242
2243            Ok(dummy.into())
2244        }
2245
2246        async fn funding_wallet(
2247            &self,
2248            _params: FundingWalletParams,
2249        ) -> anyhow::Result<RestApiResponse<Vec<models::FundingWalletResponseInner>>> {
2250            if self.force_error {
2251                return Err(ConnectorError::ConnectorClientError {
2252                    msg: "ResponseError".to_string(),
2253                    code: None,
2254                }
2255                .into());
2256            }
2257
2258            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap_or_else(|_| serde_json::json!({}));
2259            let dummy_response: Vec<models::FundingWalletResponseInner> =
2260                serde_json::from_value(resp_json.clone())
2261                    .expect("should parse into Vec<models::FundingWalletResponseInner>");
2262
2263            let dummy = DummyRestApiResponse {
2264                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2265                status: 200,
2266                headers: HashMap::new(),
2267                rate_limits: None,
2268            };
2269
2270            Ok(dummy.into())
2271        }
2272
2273        async fn get_assets_that_can_be_converted_into_bnb(
2274            &self,
2275            _params: GetAssetsThatCanBeConvertedIntoBnbParams,
2276        ) -> anyhow::Result<RestApiResponse<models::GetAssetsThatCanBeConvertedIntoBnbResponse>>
2277        {
2278            if self.force_error {
2279                return Err(ConnectorError::ConnectorClientError {
2280                    msg: "ResponseError".to_string(),
2281                    code: None,
2282                }
2283                .into());
2284            }
2285
2286            let resp_json: Value = serde_json::from_str(r#"{"details":[{"asset":"ADA","assetFullName":"ADA","amountFree":"6.21","toBTC":"0.00016848","toBNB":"0.01777302","toBNBOffExchange":"0.01741756","exchange":"0.00035546"}],"totalTransferBtc":"0.00016848","totalTransferBNB":"0.01777302","dribbletPercentage":"0.02"}"#).unwrap_or_else(|_| serde_json::json!({}));
2287            let dummy_response: models::GetAssetsThatCanBeConvertedIntoBnbResponse =
2288                serde_json::from_value(resp_json.clone())
2289                    .expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
2290
2291            let dummy = DummyRestApiResponse {
2292                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2293                status: 200,
2294                headers: HashMap::new(),
2295                rate_limits: None,
2296            };
2297
2298            Ok(dummy.into())
2299        }
2300
2301        async fn get_cloud_mining_payment_and_refund_history(
2302            &self,
2303            _params: GetCloudMiningPaymentAndRefundHistoryParams,
2304        ) -> anyhow::Result<RestApiResponse<models::GetCloudMiningPaymentAndRefundHistoryResponse>>
2305        {
2306            if self.force_error {
2307                return Err(ConnectorError::ConnectorClientError {
2308                    msg: "ResponseError".to_string(),
2309                    code: None,
2310                }
2311                .into());
2312            }
2313
2314            let resp_json: Value = serde_json::from_str(r#"{"total":5,"rows":[{"createTime":1667880112000,"tranId":121230610120,"type":248,"asset":"USDT","amount":"25.0068","status":"S"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2315            let dummy_response: models::GetCloudMiningPaymentAndRefundHistoryResponse =
2316                serde_json::from_value(resp_json.clone()).expect(
2317                    "should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse",
2318                );
2319
2320            let dummy = DummyRestApiResponse {
2321                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2322                status: 200,
2323                headers: HashMap::new(),
2324                rate_limits: None,
2325            };
2326
2327            Ok(dummy.into())
2328        }
2329
2330        async fn get_open_symbol_list(
2331            &self,
2332        ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenSymbolListResponseInner>>> {
2333            if self.force_error {
2334                return Err(ConnectorError::ConnectorClientError {
2335                    msg: "ResponseError".to_string(),
2336                    code: None,
2337                }
2338                .into());
2339            }
2340
2341            let resp_json: Value =
2342                serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC"]}]"#)
2343                    .unwrap_or_else(|_| serde_json::json!({}));
2344            let dummy_response: Vec<models::GetOpenSymbolListResponseInner> =
2345                serde_json::from_value(resp_json.clone())
2346                    .expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
2347
2348            let dummy = DummyRestApiResponse {
2349                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2350                status: 200,
2351                headers: HashMap::new(),
2352                rate_limits: None,
2353            };
2354
2355            Ok(dummy.into())
2356        }
2357
2358        async fn query_user_delegation_history(
2359            &self,
2360            _params: QueryUserDelegationHistoryParams,
2361        ) -> anyhow::Result<RestApiResponse<models::QueryUserDelegationHistoryResponse>> {
2362            if self.force_error {
2363                return Err(ConnectorError::ConnectorClientError {
2364                    msg: "ResponseError".to_string(),
2365                    code: None,
2366                }
2367                .into());
2368            }
2369
2370            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2371            let dummy_response: models::QueryUserDelegationHistoryResponse =
2372                serde_json::from_value(resp_json.clone())
2373                    .expect("should parse into models::QueryUserDelegationHistoryResponse");
2374
2375            let dummy = DummyRestApiResponse {
2376                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2377                status: 200,
2378                headers: HashMap::new(),
2379                rate_limits: None,
2380            };
2381
2382            Ok(dummy.into())
2383        }
2384
2385        async fn query_user_universal_transfer_history(
2386            &self,
2387            _params: QueryUserUniversalTransferHistoryParams,
2388        ) -> anyhow::Result<RestApiResponse<models::QueryUserUniversalTransferHistoryResponse>>
2389        {
2390            if self.force_error {
2391                return Err(ConnectorError::ConnectorClientError {
2392                    msg: "ResponseError".to_string(),
2393                    code: None,
2394                }
2395                .into());
2396            }
2397
2398            let resp_json: Value = serde_json::from_str(r#"{"total":2,"rows":[{"asset":"USDT","amount":"1","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11415955596,"timestamp":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2399            let dummy_response: models::QueryUserUniversalTransferHistoryResponse =
2400                serde_json::from_value(resp_json.clone())
2401                    .expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
2402
2403            let dummy = DummyRestApiResponse {
2404                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2405                status: 200,
2406                headers: HashMap::new(),
2407                rate_limits: None,
2408            };
2409
2410            Ok(dummy.into())
2411        }
2412
2413        async fn query_user_wallet_balance(
2414            &self,
2415            _params: QueryUserWalletBalanceParams,
2416        ) -> anyhow::Result<RestApiResponse<Vec<models::QueryUserWalletBalanceResponseInner>>>
2417        {
2418            if self.force_error {
2419                return Err(ConnectorError::ConnectorClientError {
2420                    msg: "ResponseError".to_string(),
2421                    code: None,
2422                }
2423                .into());
2424            }
2425
2426            let resp_json: Value =
2427                serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"}]"#)
2428                    .unwrap_or_else(|_| serde_json::json!({}));
2429            let dummy_response: Vec<models::QueryUserWalletBalanceResponseInner> =
2430                serde_json::from_value(resp_json.clone())
2431                    .expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
2432
2433            let dummy = DummyRestApiResponse {
2434                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2435                status: 200,
2436                headers: HashMap::new(),
2437                rate_limits: None,
2438            };
2439
2440            Ok(dummy.into())
2441        }
2442
2443        async fn toggle_bnb_burn_on_spot_trade_and_margin_interest(
2444            &self,
2445            _params: ToggleBnbBurnOnSpotTradeAndMarginInterestParams,
2446        ) -> anyhow::Result<
2447            RestApiResponse<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>,
2448        > {
2449            if self.force_error {
2450                return Err(ConnectorError::ConnectorClientError {
2451                    msg: "ResponseError".to_string(),
2452                    code: None,
2453                }
2454                .into());
2455            }
2456
2457            let resp_json: Value =
2458                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#)
2459                    .unwrap_or_else(|_| serde_json::json!({}));
2460            let dummy_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
2461                serde_json::from_value(resp_json.clone()).expect(
2462                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
2463                );
2464
2465            let dummy = DummyRestApiResponse {
2466                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2467                status: 200,
2468                headers: HashMap::new(),
2469                rate_limits: None,
2470            };
2471
2472            Ok(dummy.into())
2473        }
2474
2475        async fn trade_fee(
2476            &self,
2477            _params: TradeFeeParams,
2478        ) -> anyhow::Result<RestApiResponse<Vec<models::TradeFeeResponseInner>>> {
2479            if self.force_error {
2480                return Err(ConnectorError::ConnectorClientError {
2481                    msg: "ResponseError".to_string(),
2482                    code: None,
2483                }
2484                .into());
2485            }
2486
2487            let resp_json: Value = serde_json::from_str(
2488                r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"}]"#,
2489            )
2490            .unwrap_or_else(|_| serde_json::json!({}));
2491            let dummy_response: Vec<models::TradeFeeResponseInner> =
2492                serde_json::from_value(resp_json.clone())
2493                    .expect("should parse into Vec<models::TradeFeeResponseInner>");
2494
2495            let dummy = DummyRestApiResponse {
2496                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2497                status: 200,
2498                headers: HashMap::new(),
2499                rate_limits: None,
2500            };
2501
2502            Ok(dummy.into())
2503        }
2504
2505        async fn user_asset(
2506            &self,
2507            _params: UserAssetParams,
2508        ) -> anyhow::Result<RestApiResponse<Vec<models::UserAssetResponseInner>>> {
2509            if self.force_error {
2510                return Err(ConnectorError::ConnectorClientError {
2511                    msg: "ResponseError".to_string(),
2512                    code: None,
2513                }
2514                .into());
2515            }
2516
2517            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap_or_else(|_| serde_json::json!({}));
2518            let dummy_response: Vec<models::UserAssetResponseInner> =
2519                serde_json::from_value(resp_json.clone())
2520                    .expect("should parse into Vec<models::UserAssetResponseInner>");
2521
2522            let dummy = DummyRestApiResponse {
2523                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2524                status: 200,
2525                headers: HashMap::new(),
2526                rate_limits: None,
2527            };
2528
2529            Ok(dummy.into())
2530        }
2531
2532        async fn user_universal_transfer(
2533            &self,
2534            _params: UserUniversalTransferParams,
2535        ) -> anyhow::Result<RestApiResponse<models::UserUniversalTransferResponse>> {
2536            if self.force_error {
2537                return Err(ConnectorError::ConnectorClientError {
2538                    msg: "ResponseError".to_string(),
2539                    code: None,
2540                }
2541                .into());
2542            }
2543
2544            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#)
2545                .unwrap_or_else(|_| serde_json::json!({}));
2546            let dummy_response: models::UserUniversalTransferResponse =
2547                serde_json::from_value(resp_json.clone())
2548                    .expect("should parse into models::UserUniversalTransferResponse");
2549
2550            let dummy = DummyRestApiResponse {
2551                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2552                status: 200,
2553                headers: HashMap::new(),
2554                rate_limits: None,
2555            };
2556
2557            Ok(dummy.into())
2558        }
2559    }
2560
2561    #[test]
2562    fn asset_detail_required_params_success() {
2563        TOKIO_SHARED_RT.block_on(async {
2564            let client = MockAssetApiClient { force_error: false };
2565
2566            let params = AssetDetailParams::builder().build().unwrap();
2567
2568            let resp_json: Value = serde_json::from_str(r#"{"CTR":{"minWithdrawAmount":"70.00000000","depositStatus":false,"withdrawFee":35,"withdrawStatus":true,"depositTip":"Delisted, Deposit Suspended"},"SKY":{"minWithdrawAmount":"0.02000000","depositStatus":true,"withdrawFee":0.01,"withdrawStatus":true}}"#).unwrap_or_else(|_| serde_json::json!({}));
2569            let expected_response : models::AssetDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDetailResponse");
2570
2571            let resp = client.asset_detail(params).await.expect("Expected a response");
2572            let data_future = resp.data();
2573            let actual_response = data_future.await.unwrap();
2574            assert_eq!(actual_response, expected_response);
2575        });
2576    }
2577
2578    #[test]
2579    fn asset_detail_optional_params_success() {
2580        TOKIO_SHARED_RT.block_on(async {
2581            let client = MockAssetApiClient { force_error: false };
2582
2583            let params = AssetDetailParams::builder().asset("BTC".to_string()).recv_window(5000).build().unwrap();
2584
2585            let resp_json: Value = serde_json::from_str(r#"{"CTR":{"minWithdrawAmount":"70.00000000","depositStatus":false,"withdrawFee":35,"withdrawStatus":true,"depositTip":"Delisted, Deposit Suspended"},"SKY":{"minWithdrawAmount":"0.02000000","depositStatus":true,"withdrawFee":0.01,"withdrawStatus":true}}"#).unwrap_or_else(|_| serde_json::json!({}));
2586            let expected_response : models::AssetDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDetailResponse");
2587
2588            let resp = client.asset_detail(params).await.expect("Expected a response");
2589            let data_future = resp.data();
2590            let actual_response = data_future.await.unwrap();
2591            assert_eq!(actual_response, expected_response);
2592        });
2593    }
2594
2595    #[test]
2596    fn asset_detail_response_error() {
2597        TOKIO_SHARED_RT.block_on(async {
2598            let client = MockAssetApiClient { force_error: true };
2599
2600            let params = AssetDetailParams::builder().build().unwrap();
2601
2602            match client.asset_detail(params).await {
2603                Ok(_) => panic!("Expected an error"),
2604                Err(err) => {
2605                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2606                }
2607            }
2608        });
2609    }
2610
2611    #[test]
2612    fn asset_dividend_record_required_params_success() {
2613        TOKIO_SHARED_RT.block_on(async {
2614            let client = MockAssetApiClient { force_error: false };
2615
2616            let params = AssetDividendRecordParams::builder().build().unwrap();
2617
2618            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"id":1637366104,"amount":"10.00000000","asset":"BHFT","divTime":1563189166000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap_or_else(|_| serde_json::json!({}));
2619            let expected_response : models::AssetDividendRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDividendRecordResponse");
2620
2621            let resp = client.asset_dividend_record(params).await.expect("Expected a response");
2622            let data_future = resp.data();
2623            let actual_response = data_future.await.unwrap();
2624            assert_eq!(actual_response, expected_response);
2625        });
2626    }
2627
2628    #[test]
2629    fn asset_dividend_record_optional_params_success() {
2630        TOKIO_SHARED_RT.block_on(async {
2631            let client = MockAssetApiClient { force_error: false };
2632
2633            let params = AssetDividendRecordParams::builder().asset("BTC".to_string()).start_time(1623319461670).end_time(1641782889000).limit(20).recv_window(5000).build().unwrap();
2634
2635            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"id":1637366104,"amount":"10.00000000","asset":"BHFT","divTime":1563189166000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap_or_else(|_| serde_json::json!({}));
2636            let expected_response : models::AssetDividendRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDividendRecordResponse");
2637
2638            let resp = client.asset_dividend_record(params).await.expect("Expected a response");
2639            let data_future = resp.data();
2640            let actual_response = data_future.await.unwrap();
2641            assert_eq!(actual_response, expected_response);
2642        });
2643    }
2644
2645    #[test]
2646    fn asset_dividend_record_response_error() {
2647        TOKIO_SHARED_RT.block_on(async {
2648            let client = MockAssetApiClient { force_error: true };
2649
2650            let params = AssetDividendRecordParams::builder().build().unwrap();
2651
2652            match client.asset_dividend_record(params).await {
2653                Ok(_) => panic!("Expected an error"),
2654                Err(err) => {
2655                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2656                }
2657            }
2658        });
2659    }
2660
2661    #[test]
2662    fn dust_convert_required_params_success() {
2663        TOKIO_SHARED_RT.block_on(async {
2664            let client = MockAssetApiClient { force_error: false };
2665
2666            let params = DustConvertParams::builder("USDT".to_string(),).build().unwrap();
2667
2668            let resp_json: Value = serde_json::from_str(r#"{"totalTransfered":"3.5971223","totalServiceCharge":"0.0794964","transferResult":[{"tranId":2987331510,"fromAsset":"USDT","amount":"1","transferedAmount":"3.5971223","serviceChargeAmount":"0.0794964","operateTime":1765212029749}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2669            let expected_response : models::DustConvertResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertResponse");
2670
2671            let resp = client.dust_convert(params).await.expect("Expected a response");
2672            let data_future = resp.data();
2673            let actual_response = data_future.await.unwrap();
2674            assert_eq!(actual_response, expected_response);
2675        });
2676    }
2677
2678    #[test]
2679    fn dust_convert_optional_params_success() {
2680        TOKIO_SHARED_RT.block_on(async {
2681            let client = MockAssetApiClient { force_error: false };
2682
2683            let params = DustConvertParams::builder("USDT".to_string(),).account_type("SPOT".to_string()).client_id("1".to_string()).target_asset("BTC".to_string()).third_party_client_id("1".to_string()).dust_quota_asset_to_target_asset_price(dec!(1.0)).build().unwrap();
2684
2685            let resp_json: Value = serde_json::from_str(r#"{"totalTransfered":"3.5971223","totalServiceCharge":"0.0794964","transferResult":[{"tranId":2987331510,"fromAsset":"USDT","amount":"1","transferedAmount":"3.5971223","serviceChargeAmount":"0.0794964","operateTime":1765212029749}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2686            let expected_response : models::DustConvertResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertResponse");
2687
2688            let resp = client.dust_convert(params).await.expect("Expected a response");
2689            let data_future = resp.data();
2690            let actual_response = data_future.await.unwrap();
2691            assert_eq!(actual_response, expected_response);
2692        });
2693    }
2694
2695    #[test]
2696    fn dust_convert_response_error() {
2697        TOKIO_SHARED_RT.block_on(async {
2698            let client = MockAssetApiClient { force_error: true };
2699
2700            let params = DustConvertParams::builder("USDT".to_string())
2701                .build()
2702                .unwrap();
2703
2704            match client.dust_convert(params).await {
2705                Ok(_) => panic!("Expected an error"),
2706                Err(err) => {
2707                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2708                }
2709            }
2710        });
2711    }
2712
2713    #[test]
2714    fn dust_convertible_assets_required_params_success() {
2715        TOKIO_SHARED_RT.block_on(async {
2716            let client = MockAssetApiClient { force_error: false };
2717
2718            let params = DustConvertibleAssetsParams::builder("BTC".to_string(),).build().unwrap();
2719
2720            let resp_json: Value = serde_json::from_str(r#"{"dribbletPercentage":"0.02","totalTransferQuotaAssetAmount":"0.7899968","totalTransferTargetAssetAmount":"0.7899968","dribbletBase":"10","details":[{"asset":"AR","assetFullName":"AR","amountFree":"0.00856","exchange":"0.00073616","toQuotaAssetAmount":"0.036808","toTargetAssetAmount":"0.036808","toTargetAssetOffExchange":"0.03607184"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2721            let expected_response : models::DustConvertibleAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertibleAssetsResponse");
2722
2723            let resp = client.dust_convertible_assets(params).await.expect("Expected a response");
2724            let data_future = resp.data();
2725            let actual_response = data_future.await.unwrap();
2726            assert_eq!(actual_response, expected_response);
2727        });
2728    }
2729
2730    #[test]
2731    fn dust_convertible_assets_optional_params_success() {
2732        TOKIO_SHARED_RT.block_on(async {
2733            let client = MockAssetApiClient { force_error: false };
2734
2735            let params = DustConvertibleAssetsParams::builder("BTC".to_string(),).account_type("SPOT".to_string()).dust_quota_asset_to_target_asset_price(dec!(1.0)).build().unwrap();
2736
2737            let resp_json: Value = serde_json::from_str(r#"{"dribbletPercentage":"0.02","totalTransferQuotaAssetAmount":"0.7899968","totalTransferTargetAssetAmount":"0.7899968","dribbletBase":"10","details":[{"asset":"AR","assetFullName":"AR","amountFree":"0.00856","exchange":"0.00073616","toQuotaAssetAmount":"0.036808","toTargetAssetAmount":"0.036808","toTargetAssetOffExchange":"0.03607184"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2738            let expected_response : models::DustConvertibleAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertibleAssetsResponse");
2739
2740            let resp = client.dust_convertible_assets(params).await.expect("Expected a response");
2741            let data_future = resp.data();
2742            let actual_response = data_future.await.unwrap();
2743            assert_eq!(actual_response, expected_response);
2744        });
2745    }
2746
2747    #[test]
2748    fn dust_convertible_assets_response_error() {
2749        TOKIO_SHARED_RT.block_on(async {
2750            let client = MockAssetApiClient { force_error: true };
2751
2752            let params = DustConvertibleAssetsParams::builder("BTC".to_string())
2753                .build()
2754                .unwrap();
2755
2756            match client.dust_convertible_assets(params).await {
2757                Ok(_) => panic!("Expected an error"),
2758                Err(err) => {
2759                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2760                }
2761            }
2762        });
2763    }
2764
2765    #[test]
2766    fn dust_transfer_required_params_success() {
2767        TOKIO_SHARED_RT.block_on(async {
2768            let client = MockAssetApiClient { force_error: false };
2769
2770            let params = DustTransferParams::builder("BTC".to_string(),).build().unwrap();
2771
2772            let resp_json: Value = serde_json::from_str(r#"{"totalServiceCharge":"0.02102542","totalTransfered":"1.05127099","transferResult":[{"amount":"0.03000000","fromAsset":"ETH","operateTime":1563368549307,"serviceChargeAmount":"0.00500000","tranId":2970932918,"transferedAmount":"0.25000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2773            let expected_response : models::DustTransferResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustTransferResponse");
2774
2775            let resp = client.dust_transfer(params).await.expect("Expected a response");
2776            let data_future = resp.data();
2777            let actual_response = data_future.await.unwrap();
2778            assert_eq!(actual_response, expected_response);
2779        });
2780    }
2781
2782    #[test]
2783    fn dust_transfer_optional_params_success() {
2784        TOKIO_SHARED_RT.block_on(async {
2785            let client = MockAssetApiClient { force_error: false };
2786
2787            let params = DustTransferParams::builder("BTC".to_string(),).account_type(DustTransferAccountTypeEnum::Spot).recv_window(5000).build().unwrap();
2788
2789            let resp_json: Value = serde_json::from_str(r#"{"totalServiceCharge":"0.02102542","totalTransfered":"1.05127099","transferResult":[{"amount":"0.03000000","fromAsset":"ETH","operateTime":1563368549307,"serviceChargeAmount":"0.00500000","tranId":2970932918,"transferedAmount":"0.25000000"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2790            let expected_response : models::DustTransferResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustTransferResponse");
2791
2792            let resp = client.dust_transfer(params).await.expect("Expected a response");
2793            let data_future = resp.data();
2794            let actual_response = data_future.await.unwrap();
2795            assert_eq!(actual_response, expected_response);
2796        });
2797    }
2798
2799    #[test]
2800    fn dust_transfer_response_error() {
2801        TOKIO_SHARED_RT.block_on(async {
2802            let client = MockAssetApiClient { force_error: true };
2803
2804            let params = DustTransferParams::builder("BTC".to_string())
2805                .build()
2806                .unwrap();
2807
2808            match client.dust_transfer(params).await {
2809                Ok(_) => panic!("Expected an error"),
2810                Err(err) => {
2811                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2812                }
2813            }
2814        });
2815    }
2816
2817    #[test]
2818    fn dustlog_required_params_success() {
2819        TOKIO_SHARED_RT.block_on(async {
2820            let client = MockAssetApiClient { force_error: false };
2821
2822            let params = DustlogParams::builder().build().unwrap();
2823
2824            let resp_json: Value = serde_json::from_str(r#"{"total":8,"userAssetDribblets":[{"operateTime":1615985535000,"totalTransferedAmount":"0.00132256","totalServiceChargeAmount":"0.00002699","transId":45178372831,"userAssetDribbletDetails":[{"transId":4359321,"serviceChargeAmount":"0.000009","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.000441","fromAsset":"USDT","targetAsset":"BNB"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2825            let expected_response : models::DustlogResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustlogResponse");
2826
2827            let resp = client.dustlog(params).await.expect("Expected a response");
2828            let data_future = resp.data();
2829            let actual_response = data_future.await.unwrap();
2830            assert_eq!(actual_response, expected_response);
2831        });
2832    }
2833
2834    #[test]
2835    fn dustlog_optional_params_success() {
2836        TOKIO_SHARED_RT.block_on(async {
2837            let client = MockAssetApiClient { force_error: false };
2838
2839            let params = DustlogParams::builder().account_type(DustlogAccountTypeEnum::Spot).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();
2840
2841            let resp_json: Value = serde_json::from_str(r#"{"total":8,"userAssetDribblets":[{"operateTime":1615985535000,"totalTransferedAmount":"0.00132256","totalServiceChargeAmount":"0.00002699","transId":45178372831,"userAssetDribbletDetails":[{"transId":4359321,"serviceChargeAmount":"0.000009","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.000441","fromAsset":"USDT","targetAsset":"BNB"}]}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2842            let expected_response : models::DustlogResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustlogResponse");
2843
2844            let resp = client.dustlog(params).await.expect("Expected a response");
2845            let data_future = resp.data();
2846            let actual_response = data_future.await.unwrap();
2847            assert_eq!(actual_response, expected_response);
2848        });
2849    }
2850
2851    #[test]
2852    fn dustlog_response_error() {
2853        TOKIO_SHARED_RT.block_on(async {
2854            let client = MockAssetApiClient { force_error: true };
2855
2856            let params = DustlogParams::builder().build().unwrap();
2857
2858            match client.dustlog(params).await {
2859                Ok(_) => panic!("Expected an error"),
2860                Err(err) => {
2861                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2862                }
2863            }
2864        });
2865    }
2866
2867    #[test]
2868    fn funding_wallet_required_params_success() {
2869        TOKIO_SHARED_RT.block_on(async {
2870            let client = MockAssetApiClient { force_error: false };
2871
2872            let params = FundingWalletParams::builder().build().unwrap();
2873
2874            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap_or_else(|_| serde_json::json!({}));
2875            let expected_response : Vec<models::FundingWalletResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FundingWalletResponseInner>");
2876
2877            let resp = client.funding_wallet(params).await.expect("Expected a response");
2878            let data_future = resp.data();
2879            let actual_response = data_future.await.unwrap();
2880            assert_eq!(actual_response, expected_response);
2881        });
2882    }
2883
2884    #[test]
2885    fn funding_wallet_optional_params_success() {
2886        TOKIO_SHARED_RT.block_on(async {
2887            let client = MockAssetApiClient { force_error: false };
2888
2889            let params = FundingWalletParams::builder().asset("BTC".to_string()).need_btc_valuation(true).recv_window(5000).build().unwrap();
2890
2891            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap_or_else(|_| serde_json::json!({}));
2892            let expected_response : Vec<models::FundingWalletResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FundingWalletResponseInner>");
2893
2894            let resp = client.funding_wallet(params).await.expect("Expected a response");
2895            let data_future = resp.data();
2896            let actual_response = data_future.await.unwrap();
2897            assert_eq!(actual_response, expected_response);
2898        });
2899    }
2900
2901    #[test]
2902    fn funding_wallet_response_error() {
2903        TOKIO_SHARED_RT.block_on(async {
2904            let client = MockAssetApiClient { force_error: true };
2905
2906            let params = FundingWalletParams::builder().build().unwrap();
2907
2908            match client.funding_wallet(params).await {
2909                Ok(_) => panic!("Expected an error"),
2910                Err(err) => {
2911                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2912                }
2913            }
2914        });
2915    }
2916
2917    #[test]
2918    fn get_assets_that_can_be_converted_into_bnb_required_params_success() {
2919        TOKIO_SHARED_RT.block_on(async {
2920            let client = MockAssetApiClient { force_error: false };
2921
2922            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder().build().unwrap();
2923
2924            let resp_json: Value = serde_json::from_str(r#"{"details":[{"asset":"ADA","assetFullName":"ADA","amountFree":"6.21","toBTC":"0.00016848","toBNB":"0.01777302","toBNBOffExchange":"0.01741756","exchange":"0.00035546"}],"totalTransferBtc":"0.00016848","totalTransferBNB":"0.01777302","dribbletPercentage":"0.02"}"#).unwrap_or_else(|_| serde_json::json!({}));
2925            let expected_response : models::GetAssetsThatCanBeConvertedIntoBnbResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
2926
2927            let resp = client.get_assets_that_can_be_converted_into_bnb(params).await.expect("Expected a response");
2928            let data_future = resp.data();
2929            let actual_response = data_future.await.unwrap();
2930            assert_eq!(actual_response, expected_response);
2931        });
2932    }
2933
2934    #[test]
2935    fn get_assets_that_can_be_converted_into_bnb_optional_params_success() {
2936        TOKIO_SHARED_RT.block_on(async {
2937            let client = MockAssetApiClient { force_error: false };
2938
2939            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder().account_type(GetAssetsThatCanBeConvertedIntoBnbAccountTypeEnum::Spot).recv_window(5000).build().unwrap();
2940
2941            let resp_json: Value = serde_json::from_str(r#"{"details":[{"asset":"ADA","assetFullName":"ADA","amountFree":"6.21","toBTC":"0.00016848","toBNB":"0.01777302","toBNBOffExchange":"0.01741756","exchange":"0.00035546"}],"totalTransferBtc":"0.00016848","totalTransferBNB":"0.01777302","dribbletPercentage":"0.02"}"#).unwrap_or_else(|_| serde_json::json!({}));
2942            let expected_response : models::GetAssetsThatCanBeConvertedIntoBnbResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
2943
2944            let resp = client.get_assets_that_can_be_converted_into_bnb(params).await.expect("Expected a response");
2945            let data_future = resp.data();
2946            let actual_response = data_future.await.unwrap();
2947            assert_eq!(actual_response, expected_response);
2948        });
2949    }
2950
2951    #[test]
2952    fn get_assets_that_can_be_converted_into_bnb_response_error() {
2953        TOKIO_SHARED_RT.block_on(async {
2954            let client = MockAssetApiClient { force_error: true };
2955
2956            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder()
2957                .build()
2958                .unwrap();
2959
2960            match client
2961                .get_assets_that_can_be_converted_into_bnb(params)
2962                .await
2963            {
2964                Ok(_) => panic!("Expected an error"),
2965                Err(err) => {
2966                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2967                }
2968            }
2969        });
2970    }
2971
2972    #[test]
2973    fn get_cloud_mining_payment_and_refund_history_required_params_success() {
2974        TOKIO_SHARED_RT.block_on(async {
2975            let client = MockAssetApiClient { force_error: false };
2976
2977            let params = GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670,1641782889000,).build().unwrap();
2978
2979            let resp_json: Value = serde_json::from_str(r#"{"total":5,"rows":[{"createTime":1667880112000,"tranId":121230610120,"type":248,"asset":"USDT","amount":"25.0068","status":"S"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2980            let expected_response : models::GetCloudMiningPaymentAndRefundHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse");
2981
2982            let resp = client.get_cloud_mining_payment_and_refund_history(params).await.expect("Expected a response");
2983            let data_future = resp.data();
2984            let actual_response = data_future.await.unwrap();
2985            assert_eq!(actual_response, expected_response);
2986        });
2987    }
2988
2989    #[test]
2990    fn get_cloud_mining_payment_and_refund_history_optional_params_success() {
2991        TOKIO_SHARED_RT.block_on(async {
2992            let client = MockAssetApiClient { force_error: false };
2993
2994            let params = GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670,1641782889000,).tran_id(1).client_tran_id("1".to_string()).asset("BTC".to_string()).current(1).size(10).build().unwrap();
2995
2996            let resp_json: Value = serde_json::from_str(r#"{"total":5,"rows":[{"createTime":1667880112000,"tranId":121230610120,"type":248,"asset":"USDT","amount":"25.0068","status":"S"}]}"#).unwrap_or_else(|_| serde_json::json!({}));
2997            let expected_response : models::GetCloudMiningPaymentAndRefundHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse");
2998
2999            let resp = client.get_cloud_mining_payment_and_refund_history(params).await.expect("Expected a response");
3000            let data_future = resp.data();
3001            let actual_response = data_future.await.unwrap();
3002            assert_eq!(actual_response, expected_response);
3003        });
3004    }
3005
3006    #[test]
3007    fn get_cloud_mining_payment_and_refund_history_response_error() {
3008        TOKIO_SHARED_RT.block_on(async {
3009            let client = MockAssetApiClient { force_error: true };
3010
3011            let params =
3012                GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670, 1641782889000)
3013                    .build()
3014                    .unwrap();
3015
3016            match client
3017                .get_cloud_mining_payment_and_refund_history(params)
3018                .await
3019            {
3020                Ok(_) => panic!("Expected an error"),
3021                Err(err) => {
3022                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3023                }
3024            }
3025        });
3026    }
3027
3028    #[test]
3029    fn get_open_symbol_list_required_params_success() {
3030        TOKIO_SHARED_RT.block_on(async {
3031            let client = MockAssetApiClient { force_error: false };
3032
3033            let resp_json: Value =
3034                serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC"]}]"#)
3035                    .unwrap_or_else(|_| serde_json::json!({}));
3036            let expected_response: Vec<models::GetOpenSymbolListResponseInner> =
3037                serde_json::from_value(resp_json.clone())
3038                    .expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
3039
3040            let resp = client
3041                .get_open_symbol_list()
3042                .await
3043                .expect("Expected a response");
3044            let data_future = resp.data();
3045            let actual_response = data_future.await.unwrap();
3046            assert_eq!(actual_response, expected_response);
3047        });
3048    }
3049
3050    #[test]
3051    fn get_open_symbol_list_optional_params_success() {
3052        TOKIO_SHARED_RT.block_on(async {
3053            let client = MockAssetApiClient { force_error: false };
3054
3055            let resp_json: Value =
3056                serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC"]}]"#)
3057                    .unwrap_or_else(|_| serde_json::json!({}));
3058            let expected_response: Vec<models::GetOpenSymbolListResponseInner> =
3059                serde_json::from_value(resp_json.clone())
3060                    .expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
3061
3062            let resp = client
3063                .get_open_symbol_list()
3064                .await
3065                .expect("Expected a response");
3066            let data_future = resp.data();
3067            let actual_response = data_future.await.unwrap();
3068            assert_eq!(actual_response, expected_response);
3069        });
3070    }
3071
3072    #[test]
3073    fn get_open_symbol_list_response_error() {
3074        TOKIO_SHARED_RT.block_on(async {
3075            let client = MockAssetApiClient { force_error: true };
3076
3077            match client.get_open_symbol_list().await {
3078                Ok(_) => panic!("Expected an error"),
3079                Err(err) => {
3080                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3081                }
3082            }
3083        });
3084    }
3085
3086    #[test]
3087    fn query_user_delegation_history_required_params_success() {
3088        TOKIO_SHARED_RT.block_on(async {
3089            let client = MockAssetApiClient { force_error: false };
3090
3091            let params = QueryUserDelegationHistoryParams::builder("abc@test.com".to_string(),1623319461670,1641782889000,).build().unwrap();
3092
3093            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3094            let expected_response : models::QueryUserDelegationHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserDelegationHistoryResponse");
3095
3096            let resp = client.query_user_delegation_history(params).await.expect("Expected a response");
3097            let data_future = resp.data();
3098            let actual_response = data_future.await.unwrap();
3099            assert_eq!(actual_response, expected_response);
3100        });
3101    }
3102
3103    #[test]
3104    fn query_user_delegation_history_optional_params_success() {
3105        TOKIO_SHARED_RT.block_on(async {
3106            let client = MockAssetApiClient { force_error: false };
3107
3108            let params = QueryUserDelegationHistoryParams::builder("abc@test.com".to_string(),1623319461670,1641782889000,).r#type(QueryUserDelegationHistoryTypeEnum::Delegate).asset("BTC".to_string()).current(1).size(10).recv_window(5000).build().unwrap();
3109
3110            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3111            let expected_response : models::QueryUserDelegationHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserDelegationHistoryResponse");
3112
3113            let resp = client.query_user_delegation_history(params).await.expect("Expected a response");
3114            let data_future = resp.data();
3115            let actual_response = data_future.await.unwrap();
3116            assert_eq!(actual_response, expected_response);
3117        });
3118    }
3119
3120    #[test]
3121    fn query_user_delegation_history_response_error() {
3122        TOKIO_SHARED_RT.block_on(async {
3123            let client = MockAssetApiClient { force_error: true };
3124
3125            let params = QueryUserDelegationHistoryParams::builder(
3126                "abc@test.com".to_string(),
3127                1623319461670,
3128                1641782889000,
3129            )
3130            .build()
3131            .unwrap();
3132
3133            match client.query_user_delegation_history(params).await {
3134                Ok(_) => panic!("Expected an error"),
3135                Err(err) => {
3136                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3137                }
3138            }
3139        });
3140    }
3141
3142    #[test]
3143    fn query_user_universal_transfer_history_required_params_success() {
3144        TOKIO_SHARED_RT.block_on(async {
3145            let client = MockAssetApiClient { force_error: false };
3146
3147            let params = QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string(),).build().unwrap();
3148
3149            let resp_json: Value = serde_json::from_str(r#"{"total":2,"rows":[{"asset":"USDT","amount":"1","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11415955596,"timestamp":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3150            let expected_response : models::QueryUserUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
3151
3152            let resp = client.query_user_universal_transfer_history(params).await.expect("Expected a response");
3153            let data_future = resp.data();
3154            let actual_response = data_future.await.unwrap();
3155            assert_eq!(actual_response, expected_response);
3156        });
3157    }
3158
3159    #[test]
3160    fn query_user_universal_transfer_history_optional_params_success() {
3161        TOKIO_SHARED_RT.block_on(async {
3162            let client = MockAssetApiClient { force_error: false };
3163
3164            let params = QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string(),).start_time(1623319461670).end_time(1641782889000).current(1).size(10).from_symbol(QueryUserUniversalTransferHistoryFromSymbolEnum::IsolatedmarginMargin).to_symbol(QueryUserUniversalTransferHistoryToSymbolEnum::MarginIsolatedmargin).recv_window(5000).build().unwrap();
3165
3166            let resp_json: Value = serde_json::from_str(r#"{"total":2,"rows":[{"asset":"USDT","amount":"1","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11415955596,"timestamp":1544433328000}]}"#).unwrap_or_else(|_| serde_json::json!({}));
3167            let expected_response : models::QueryUserUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
3168
3169            let resp = client.query_user_universal_transfer_history(params).await.expect("Expected a response");
3170            let data_future = resp.data();
3171            let actual_response = data_future.await.unwrap();
3172            assert_eq!(actual_response, expected_response);
3173        });
3174    }
3175
3176    #[test]
3177    fn query_user_universal_transfer_history_response_error() {
3178        TOKIO_SHARED_RT.block_on(async {
3179            let client = MockAssetApiClient { force_error: true };
3180
3181            let params =
3182                QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string())
3183                    .build()
3184                    .unwrap();
3185
3186            match client.query_user_universal_transfer_history(params).await {
3187                Ok(_) => panic!("Expected an error"),
3188                Err(err) => {
3189                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3190                }
3191            }
3192        });
3193    }
3194
3195    #[test]
3196    fn query_user_wallet_balance_required_params_success() {
3197        TOKIO_SHARED_RT.block_on(async {
3198            let client = MockAssetApiClient { force_error: false };
3199
3200            let params = QueryUserWalletBalanceParams::builder().build().unwrap();
3201
3202            let resp_json: Value =
3203                serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"}]"#)
3204                    .unwrap_or_else(|_| serde_json::json!({}));
3205            let expected_response: Vec<models::QueryUserWalletBalanceResponseInner> =
3206                serde_json::from_value(resp_json.clone())
3207                    .expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
3208
3209            let resp = client
3210                .query_user_wallet_balance(params)
3211                .await
3212                .expect("Expected a response");
3213            let data_future = resp.data();
3214            let actual_response = data_future.await.unwrap();
3215            assert_eq!(actual_response, expected_response);
3216        });
3217    }
3218
3219    #[test]
3220    fn query_user_wallet_balance_optional_params_success() {
3221        TOKIO_SHARED_RT.block_on(async {
3222            let client = MockAssetApiClient { force_error: false };
3223
3224            let params = QueryUserWalletBalanceParams::builder()
3225                .quote_asset("BTC".to_string())
3226                .recv_window(5000)
3227                .build()
3228                .unwrap();
3229
3230            let resp_json: Value =
3231                serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"}]"#)
3232                    .unwrap_or_else(|_| serde_json::json!({}));
3233            let expected_response: Vec<models::QueryUserWalletBalanceResponseInner> =
3234                serde_json::from_value(resp_json.clone())
3235                    .expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
3236
3237            let resp = client
3238                .query_user_wallet_balance(params)
3239                .await
3240                .expect("Expected a response");
3241            let data_future = resp.data();
3242            let actual_response = data_future.await.unwrap();
3243            assert_eq!(actual_response, expected_response);
3244        });
3245    }
3246
3247    #[test]
3248    fn query_user_wallet_balance_response_error() {
3249        TOKIO_SHARED_RT.block_on(async {
3250            let client = MockAssetApiClient { force_error: true };
3251
3252            let params = QueryUserWalletBalanceParams::builder().build().unwrap();
3253
3254            match client.query_user_wallet_balance(params).await {
3255                Ok(_) => panic!("Expected an error"),
3256                Err(err) => {
3257                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3258                }
3259            }
3260        });
3261    }
3262
3263    #[test]
3264    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_required_params_success() {
3265        TOKIO_SHARED_RT.block_on(async {
3266            let client = MockAssetApiClient { force_error: false };
3267
3268            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
3269                .build()
3270                .unwrap();
3271
3272            let resp_json: Value =
3273                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#)
3274                    .unwrap_or_else(|_| serde_json::json!({}));
3275            let expected_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
3276                serde_json::from_value(resp_json.clone()).expect(
3277                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
3278                );
3279
3280            let resp = client
3281                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
3282                .await
3283                .expect("Expected a response");
3284            let data_future = resp.data();
3285            let actual_response = data_future.await.unwrap();
3286            assert_eq!(actual_response, expected_response);
3287        });
3288    }
3289
3290    #[test]
3291    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_optional_params_success() {
3292        TOKIO_SHARED_RT.block_on(async {
3293            let client = MockAssetApiClient { force_error: false };
3294
3295            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
3296                .spot_bnb_burn("true".to_string())
3297                .interest_bnb_burn("true".to_string())
3298                .recv_window(5000)
3299                .build()
3300                .unwrap();
3301
3302            let resp_json: Value =
3303                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#)
3304                    .unwrap_or_else(|_| serde_json::json!({}));
3305            let expected_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
3306                serde_json::from_value(resp_json.clone()).expect(
3307                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
3308                );
3309
3310            let resp = client
3311                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
3312                .await
3313                .expect("Expected a response");
3314            let data_future = resp.data();
3315            let actual_response = data_future.await.unwrap();
3316            assert_eq!(actual_response, expected_response);
3317        });
3318    }
3319
3320    #[test]
3321    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_response_error() {
3322        TOKIO_SHARED_RT.block_on(async {
3323            let client = MockAssetApiClient { force_error: true };
3324
3325            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
3326                .build()
3327                .unwrap();
3328
3329            match client
3330                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
3331                .await
3332            {
3333                Ok(_) => panic!("Expected an error"),
3334                Err(err) => {
3335                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3336                }
3337            }
3338        });
3339    }
3340
3341    #[test]
3342    fn trade_fee_required_params_success() {
3343        TOKIO_SHARED_RT.block_on(async {
3344            let client = MockAssetApiClient { force_error: false };
3345
3346            let params = TradeFeeParams::builder().build().unwrap();
3347
3348            let resp_json: Value = serde_json::from_str(
3349                r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"}]"#,
3350            )
3351            .unwrap_or_else(|_| serde_json::json!({}));
3352            let expected_response: Vec<models::TradeFeeResponseInner> =
3353                serde_json::from_value(resp_json.clone())
3354                    .expect("should parse into Vec<models::TradeFeeResponseInner>");
3355
3356            let resp = client.trade_fee(params).await.expect("Expected a response");
3357            let data_future = resp.data();
3358            let actual_response = data_future.await.unwrap();
3359            assert_eq!(actual_response, expected_response);
3360        });
3361    }
3362
3363    #[test]
3364    fn trade_fee_optional_params_success() {
3365        TOKIO_SHARED_RT.block_on(async {
3366            let client = MockAssetApiClient { force_error: false };
3367
3368            let params = TradeFeeParams::builder()
3369                .symbol("ADABNB".to_string())
3370                .recv_window(5000)
3371                .build()
3372                .unwrap();
3373
3374            let resp_json: Value = serde_json::from_str(
3375                r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"}]"#,
3376            )
3377            .unwrap_or_else(|_| serde_json::json!({}));
3378            let expected_response: Vec<models::TradeFeeResponseInner> =
3379                serde_json::from_value(resp_json.clone())
3380                    .expect("should parse into Vec<models::TradeFeeResponseInner>");
3381
3382            let resp = client.trade_fee(params).await.expect("Expected a response");
3383            let data_future = resp.data();
3384            let actual_response = data_future.await.unwrap();
3385            assert_eq!(actual_response, expected_response);
3386        });
3387    }
3388
3389    #[test]
3390    fn trade_fee_response_error() {
3391        TOKIO_SHARED_RT.block_on(async {
3392            let client = MockAssetApiClient { force_error: true };
3393
3394            let params = TradeFeeParams::builder().build().unwrap();
3395
3396            match client.trade_fee(params).await {
3397                Ok(_) => panic!("Expected an error"),
3398                Err(err) => {
3399                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3400                }
3401            }
3402        });
3403    }
3404
3405    #[test]
3406    fn user_asset_required_params_success() {
3407        TOKIO_SHARED_RT.block_on(async {
3408            let client = MockAssetApiClient { force_error: false };
3409
3410            let params = UserAssetParams::builder().build().unwrap();
3411
3412            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap_or_else(|_| serde_json::json!({}));
3413            let expected_response : Vec<models::UserAssetResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::UserAssetResponseInner>");
3414
3415            let resp = client.user_asset(params).await.expect("Expected a response");
3416            let data_future = resp.data();
3417            let actual_response = data_future.await.unwrap();
3418            assert_eq!(actual_response, expected_response);
3419        });
3420    }
3421
3422    #[test]
3423    fn user_asset_optional_params_success() {
3424        TOKIO_SHARED_RT.block_on(async {
3425            let client = MockAssetApiClient { force_error: false };
3426
3427            let params = UserAssetParams::builder().asset("BTC".to_string()).need_btc_valuation(true).recv_window(5000).build().unwrap();
3428
3429            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap_or_else(|_| serde_json::json!({}));
3430            let expected_response : Vec<models::UserAssetResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::UserAssetResponseInner>");
3431
3432            let resp = client.user_asset(params).await.expect("Expected a response");
3433            let data_future = resp.data();
3434            let actual_response = data_future.await.unwrap();
3435            assert_eq!(actual_response, expected_response);
3436        });
3437    }
3438
3439    #[test]
3440    fn user_asset_response_error() {
3441        TOKIO_SHARED_RT.block_on(async {
3442            let client = MockAssetApiClient { force_error: true };
3443
3444            let params = UserAssetParams::builder().build().unwrap();
3445
3446            match client.user_asset(params).await {
3447                Ok(_) => panic!("Expected an error"),
3448                Err(err) => {
3449                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3450                }
3451            }
3452        });
3453    }
3454
3455    #[test]
3456    fn user_universal_transfer_required_params_success() {
3457        TOKIO_SHARED_RT.block_on(async {
3458            let client = MockAssetApiClient { force_error: false };
3459
3460            let params = UserUniversalTransferParams::builder(
3461                UserUniversalTransferTypeEnum::MainUmfuture,
3462                "BTC".to_string(),
3463                dec!(1.0),
3464            )
3465            .build()
3466            .unwrap();
3467
3468            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#)
3469                .unwrap_or_else(|_| serde_json::json!({}));
3470            let expected_response: models::UserUniversalTransferResponse =
3471                serde_json::from_value(resp_json.clone())
3472                    .expect("should parse into models::UserUniversalTransferResponse");
3473
3474            let resp = client
3475                .user_universal_transfer(params)
3476                .await
3477                .expect("Expected a response");
3478            let data_future = resp.data();
3479            let actual_response = data_future.await.unwrap();
3480            assert_eq!(actual_response, expected_response);
3481        });
3482    }
3483
3484    #[test]
3485    fn user_universal_transfer_optional_params_success() {
3486        TOKIO_SHARED_RT.block_on(async {
3487            let client = MockAssetApiClient { force_error: false };
3488
3489            let params = UserUniversalTransferParams::builder(
3490                UserUniversalTransferTypeEnum::MainUmfuture,
3491                "BTC".to_string(),
3492                dec!(1.0),
3493            )
3494            .from_symbol(UserUniversalTransferFromSymbolEnum::IsolatedmarginMargin)
3495            .to_symbol(UserUniversalTransferToSymbolEnum::MarginIsolatedmargin)
3496            .recv_window(5000)
3497            .build()
3498            .unwrap();
3499
3500            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#)
3501                .unwrap_or_else(|_| serde_json::json!({}));
3502            let expected_response: models::UserUniversalTransferResponse =
3503                serde_json::from_value(resp_json.clone())
3504                    .expect("should parse into models::UserUniversalTransferResponse");
3505
3506            let resp = client
3507                .user_universal_transfer(params)
3508                .await
3509                .expect("Expected a response");
3510            let data_future = resp.data();
3511            let actual_response = data_future.await.unwrap();
3512            assert_eq!(actual_response, expected_response);
3513        });
3514    }
3515
3516    #[test]
3517    fn user_universal_transfer_response_error() {
3518        TOKIO_SHARED_RT.block_on(async {
3519            let client = MockAssetApiClient { force_error: true };
3520
3521            let params = UserUniversalTransferParams::builder(
3522                UserUniversalTransferTypeEnum::MainUmfuture,
3523                "BTC".to_string(),
3524                dec!(1.0),
3525            )
3526            .build()
3527            .unwrap();
3528
3529            match client.user_universal_transfer(params).await {
3530                Ok(_) => panic!("Expected an error"),
3531                Err(err) => {
3532                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
3533                }
3534            }
3535        });
3536    }
3537}