Skip to main content

binance_sdk/wallet/rest_api/apis/
asset_api.rs

1/*
2 * Binance Wallet REST API
3 *
4 * OpenAPI Specification for the Binance Wallet REST API
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24    config::ConfigurationRestApi,
25    models::{ParamBuildError, RestApiResponse},
26    utils::send_request,
27};
28use crate::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/// Request parameters for the [`asset_detail`] operation.
115///
116/// This struct holds all of the inputs you can pass when calling
117/// [`asset_detail`](#method.asset_detail).
118#[derive(Clone, Debug, Builder, Default)]
119#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
120pub struct AssetDetailParams {
121    /// If asset is blank, then query all positive assets user have.
122    ///
123    /// This field is **optional.
124    #[builder(setter(into), default)]
125    pub asset: Option<String>,
126    ///
127    /// The `recv_window` parameter.
128    ///
129    /// This field is **optional.
130    #[builder(setter(into), default)]
131    pub recv_window: Option<i64>,
132}
133
134impl AssetDetailParams {
135    /// Create a builder for [`asset_detail`].
136    ///
137    #[must_use]
138    pub fn builder() -> AssetDetailParamsBuilder {
139        AssetDetailParamsBuilder::default()
140    }
141}
142/// Request parameters for the [`asset_dividend_record`] operation.
143///
144/// This struct holds all of the inputs you can pass when calling
145/// [`asset_dividend_record`](#method.asset_dividend_record).
146#[derive(Clone, Debug, Builder, Default)]
147#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
148pub struct AssetDividendRecordParams {
149    /// If asset is blank, then query all positive assets user have.
150    ///
151    /// This field is **optional.
152    #[builder(setter(into), default)]
153    pub asset: Option<String>,
154    ///
155    /// The `start_time` parameter.
156    ///
157    /// This field is **optional.
158    #[builder(setter(into), default)]
159    pub start_time: Option<i64>,
160    ///
161    /// The `end_time` parameter.
162    ///
163    /// This field is **optional.
164    #[builder(setter(into), default)]
165    pub end_time: Option<i64>,
166    /// min 7, max 30, default 7
167    ///
168    /// This field is **optional.
169    #[builder(setter(into), default)]
170    pub limit: Option<i64>,
171    ///
172    /// The `recv_window` parameter.
173    ///
174    /// This field is **optional.
175    #[builder(setter(into), default)]
176    pub recv_window: Option<i64>,
177}
178
179impl AssetDividendRecordParams {
180    /// Create a builder for [`asset_dividend_record`].
181    ///
182    #[must_use]
183    pub fn builder() -> AssetDividendRecordParamsBuilder {
184        AssetDividendRecordParamsBuilder::default()
185    }
186}
187/// Request parameters for the [`dust_convert`] operation.
188///
189/// This struct holds all of the inputs you can pass when calling
190/// [`dust_convert`](#method.dust_convert).
191#[derive(Clone, Debug, Builder)]
192#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
193pub struct DustConvertParams {
194    ///
195    /// The `asset` parameter.
196    ///
197    /// This field is **required.
198    #[builder(setter(into))]
199    pub asset: String,
200    /// `SPOT` or `MARGIN`,default `SPOT`
201    ///
202    /// This field is **optional.
203    #[builder(setter(into), default)]
204    pub account_type: Option<String>,
205    /// A unique id for the request
206    ///
207    /// This field is **optional.
208    #[builder(setter(into), default)]
209    pub client_id: Option<String>,
210    ///
211    /// The `target_asset` parameter.
212    ///
213    /// This field is **optional.
214    #[builder(setter(into), default)]
215    pub target_asset: Option<String>,
216    ///
217    /// The `third_party_client_id` parameter.
218    ///
219    /// This field is **optional.
220    #[builder(setter(into), default)]
221    pub third_party_client_id: Option<String>,
222    ///
223    /// The `dust_quota_asset_to_target_asset_price` parameter.
224    ///
225    /// This field is **optional.
226    #[builder(setter(into), default)]
227    pub dust_quota_asset_to_target_asset_price: Option<rust_decimal::Decimal>,
228}
229
230impl DustConvertParams {
231    /// Create a builder for [`dust_convert`].
232    ///
233    /// Required parameters:
234    ///
235    /// * `asset` — String
236    ///
237    #[must_use]
238    pub fn builder(asset: String) -> DustConvertParamsBuilder {
239        DustConvertParamsBuilder::default().asset(asset)
240    }
241}
242/// Request parameters for the [`dust_convertible_assets`] operation.
243///
244/// This struct holds all of the inputs you can pass when calling
245/// [`dust_convertible_assets`](#method.dust_convertible_assets).
246#[derive(Clone, Debug, Builder)]
247#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
248pub struct DustConvertibleAssetsParams {
249    ///
250    /// The `target_asset` parameter.
251    ///
252    /// This field is **required.
253    #[builder(setter(into))]
254    pub target_asset: String,
255    /// `SPOT` or `MARGIN`,default `SPOT`
256    ///
257    /// This field is **optional.
258    #[builder(setter(into), default)]
259    pub account_type: Option<String>,
260    ///
261    /// The `dust_quota_asset_to_target_asset_price` parameter.
262    ///
263    /// This field is **optional.
264    #[builder(setter(into), default)]
265    pub dust_quota_asset_to_target_asset_price: Option<rust_decimal::Decimal>,
266}
267
268impl DustConvertibleAssetsParams {
269    /// Create a builder for [`dust_convertible_assets`].
270    ///
271    /// Required parameters:
272    ///
273    /// * `target_asset` — String
274    ///
275    #[must_use]
276    pub fn builder(target_asset: String) -> DustConvertibleAssetsParamsBuilder {
277        DustConvertibleAssetsParamsBuilder::default().target_asset(target_asset)
278    }
279}
280/// Request parameters for the [`dust_transfer`] operation.
281///
282/// This struct holds all of the inputs you can pass when calling
283/// [`dust_transfer`](#method.dust_transfer).
284#[derive(Clone, Debug, Builder)]
285#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
286pub struct DustTransferParams {
287    ///
288    /// The `asset` parameter.
289    ///
290    /// This field is **required.
291    #[builder(setter(into))]
292    pub asset: String,
293    /// `SPOT` or `MARGIN`,default `SPOT`
294    ///
295    /// This field is **optional.
296    #[builder(setter(into), default)]
297    pub account_type: Option<String>,
298    ///
299    /// The `recv_window` parameter.
300    ///
301    /// This field is **optional.
302    #[builder(setter(into), default)]
303    pub recv_window: Option<i64>,
304}
305
306impl DustTransferParams {
307    /// Create a builder for [`dust_transfer`].
308    ///
309    /// Required parameters:
310    ///
311    /// * `asset` — String
312    ///
313    #[must_use]
314    pub fn builder(asset: String) -> DustTransferParamsBuilder {
315        DustTransferParamsBuilder::default().asset(asset)
316    }
317}
318/// Request parameters for the [`dustlog`] operation.
319///
320/// This struct holds all of the inputs you can pass when calling
321/// [`dustlog`](#method.dustlog).
322#[derive(Clone, Debug, Builder, Default)]
323#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
324pub struct DustlogParams {
325    /// `SPOT` or `MARGIN`,default `SPOT`
326    ///
327    /// This field is **optional.
328    #[builder(setter(into), default)]
329    pub account_type: Option<String>,
330    ///
331    /// The `start_time` parameter.
332    ///
333    /// This field is **optional.
334    #[builder(setter(into), default)]
335    pub start_time: Option<i64>,
336    ///
337    /// The `end_time` parameter.
338    ///
339    /// This field is **optional.
340    #[builder(setter(into), default)]
341    pub end_time: Option<i64>,
342    ///
343    /// The `recv_window` parameter.
344    ///
345    /// This field is **optional.
346    #[builder(setter(into), default)]
347    pub recv_window: Option<i64>,
348}
349
350impl DustlogParams {
351    /// Create a builder for [`dustlog`].
352    ///
353    #[must_use]
354    pub fn builder() -> DustlogParamsBuilder {
355        DustlogParamsBuilder::default()
356    }
357}
358/// Request parameters for the [`funding_wallet`] operation.
359///
360/// This struct holds all of the inputs you can pass when calling
361/// [`funding_wallet`](#method.funding_wallet).
362#[derive(Clone, Debug, Builder, Default)]
363#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
364pub struct FundingWalletParams {
365    /// If asset is blank, then query all positive assets user have.
366    ///
367    /// This field is **optional.
368    #[builder(setter(into), default)]
369    pub asset: Option<String>,
370    /// true or false
371    ///
372    /// This field is **optional.
373    #[builder(setter(into), default)]
374    pub need_btc_valuation: Option<String>,
375    ///
376    /// The `recv_window` parameter.
377    ///
378    /// This field is **optional.
379    #[builder(setter(into), default)]
380    pub recv_window: Option<i64>,
381}
382
383impl FundingWalletParams {
384    /// Create a builder for [`funding_wallet`].
385    ///
386    #[must_use]
387    pub fn builder() -> FundingWalletParamsBuilder {
388        FundingWalletParamsBuilder::default()
389    }
390}
391/// Request parameters for the [`get_assets_that_can_be_converted_into_bnb`] operation.
392///
393/// This struct holds all of the inputs you can pass when calling
394/// [`get_assets_that_can_be_converted_into_bnb`](#method.get_assets_that_can_be_converted_into_bnb).
395#[derive(Clone, Debug, Builder, Default)]
396#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
397pub struct GetAssetsThatCanBeConvertedIntoBnbParams {
398    /// `SPOT` or `MARGIN`,default `SPOT`
399    ///
400    /// This field is **optional.
401    #[builder(setter(into), default)]
402    pub account_type: Option<String>,
403    ///
404    /// The `recv_window` parameter.
405    ///
406    /// This field is **optional.
407    #[builder(setter(into), default)]
408    pub recv_window: Option<i64>,
409}
410
411impl GetAssetsThatCanBeConvertedIntoBnbParams {
412    /// Create a builder for [`get_assets_that_can_be_converted_into_bnb`].
413    ///
414    #[must_use]
415    pub fn builder() -> GetAssetsThatCanBeConvertedIntoBnbParamsBuilder {
416        GetAssetsThatCanBeConvertedIntoBnbParamsBuilder::default()
417    }
418}
419/// Request parameters for the [`get_cloud_mining_payment_and_refund_history`] operation.
420///
421/// This struct holds all of the inputs you can pass when calling
422/// [`get_cloud_mining_payment_and_refund_history`](#method.get_cloud_mining_payment_and_refund_history).
423#[derive(Clone, Debug, Builder)]
424#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
425pub struct GetCloudMiningPaymentAndRefundHistoryParams {
426    ///
427    /// The `start_time` parameter.
428    ///
429    /// This field is **required.
430    #[builder(setter(into))]
431    pub start_time: i64,
432    ///
433    /// The `end_time` parameter.
434    ///
435    /// This field is **required.
436    #[builder(setter(into))]
437    pub end_time: i64,
438    /// The transaction id
439    ///
440    /// This field is **optional.
441    #[builder(setter(into), default)]
442    pub tran_id: Option<i64>,
443    /// The unique flag
444    ///
445    /// This field is **optional.
446    #[builder(setter(into), default)]
447    pub client_tran_id: Option<String>,
448    /// If asset is blank, then query all positive assets user have.
449    ///
450    /// This field is **optional.
451    #[builder(setter(into), default)]
452    pub asset: Option<String>,
453    /// current page, default 1, the min value is 1
454    ///
455    /// This field is **optional.
456    #[builder(setter(into), default)]
457    pub current: Option<i64>,
458    /// page size, default 10, the max value is 100
459    ///
460    /// This field is **optional.
461    #[builder(setter(into), default)]
462    pub size: Option<i64>,
463}
464
465impl GetCloudMiningPaymentAndRefundHistoryParams {
466    /// Create a builder for [`get_cloud_mining_payment_and_refund_history`].
467    ///
468    /// Required parameters:
469    ///
470    /// * `start_time` — i64
471    /// * `end_time` — i64
472    ///
473    #[must_use]
474    pub fn builder(
475        start_time: i64,
476        end_time: i64,
477    ) -> GetCloudMiningPaymentAndRefundHistoryParamsBuilder {
478        GetCloudMiningPaymentAndRefundHistoryParamsBuilder::default()
479            .start_time(start_time)
480            .end_time(end_time)
481    }
482}
483/// Request parameters for the [`query_user_delegation_history`] operation.
484///
485/// This struct holds all of the inputs you can pass when calling
486/// [`query_user_delegation_history`](#method.query_user_delegation_history).
487#[derive(Clone, Debug, Builder)]
488#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
489pub struct QueryUserDelegationHistoryParams {
490    ///
491    /// The `email` parameter.
492    ///
493    /// This field is **required.
494    #[builder(setter(into))]
495    pub email: String,
496    ///
497    /// The `start_time` parameter.
498    ///
499    /// This field is **required.
500    #[builder(setter(into))]
501    pub start_time: i64,
502    ///
503    /// The `end_time` parameter.
504    ///
505    /// This field is **required.
506    #[builder(setter(into))]
507    pub end_time: i64,
508    /// Delegate/Undelegate
509    ///
510    /// This field is **optional.
511    #[builder(setter(into), default)]
512    pub r#type: Option<String>,
513    /// If asset is blank, then query all positive assets user have.
514    ///
515    /// This field is **optional.
516    #[builder(setter(into), default)]
517    pub asset: Option<String>,
518    /// current page, default 1, the min value is 1
519    ///
520    /// This field is **optional.
521    #[builder(setter(into), default)]
522    pub current: Option<i64>,
523    /// page size, default 10, the max value is 100
524    ///
525    /// This field is **optional.
526    #[builder(setter(into), default)]
527    pub size: Option<i64>,
528    ///
529    /// The `recv_window` parameter.
530    ///
531    /// This field is **optional.
532    #[builder(setter(into), default)]
533    pub recv_window: Option<i64>,
534}
535
536impl QueryUserDelegationHistoryParams {
537    /// Create a builder for [`query_user_delegation_history`].
538    ///
539    /// Required parameters:
540    ///
541    /// * `email` — String
542    /// * `start_time` — i64
543    /// * `end_time` — i64
544    ///
545    #[must_use]
546    pub fn builder(
547        email: String,
548        start_time: i64,
549        end_time: i64,
550    ) -> QueryUserDelegationHistoryParamsBuilder {
551        QueryUserDelegationHistoryParamsBuilder::default()
552            .email(email)
553            .start_time(start_time)
554            .end_time(end_time)
555    }
556}
557/// Request parameters for the [`query_user_universal_transfer_history`] operation.
558///
559/// This struct holds all of the inputs you can pass when calling
560/// [`query_user_universal_transfer_history`](#method.query_user_universal_transfer_history).
561#[derive(Clone, Debug, Builder)]
562#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
563pub struct QueryUserUniversalTransferHistoryParams {
564    ///
565    /// The `r#type` parameter.
566    ///
567    /// This field is **required.
568    #[builder(setter(into))]
569    pub r#type: String,
570    ///
571    /// The `start_time` parameter.
572    ///
573    /// This field is **optional.
574    #[builder(setter(into), default)]
575    pub start_time: Option<i64>,
576    ///
577    /// The `end_time` parameter.
578    ///
579    /// This field is **optional.
580    #[builder(setter(into), default)]
581    pub end_time: Option<i64>,
582    /// current page, default 1, the min value is 1
583    ///
584    /// This field is **optional.
585    #[builder(setter(into), default)]
586    pub current: Option<i64>,
587    /// page size, default 10, the max value is 100
588    ///
589    /// This field is **optional.
590    #[builder(setter(into), default)]
591    pub size: Option<i64>,
592    ///
593    /// The `from_symbol` parameter.
594    ///
595    /// This field is **optional.
596    #[builder(setter(into), default)]
597    pub from_symbol: Option<String>,
598    ///
599    /// The `to_symbol` parameter.
600    ///
601    /// This field is **optional.
602    #[builder(setter(into), default)]
603    pub to_symbol: Option<String>,
604    ///
605    /// The `recv_window` parameter.
606    ///
607    /// This field is **optional.
608    #[builder(setter(into), default)]
609    pub recv_window: Option<i64>,
610}
611
612impl QueryUserUniversalTransferHistoryParams {
613    /// Create a builder for [`query_user_universal_transfer_history`].
614    ///
615    /// Required parameters:
616    ///
617    /// * `r#type` — String
618    ///
619    #[must_use]
620    pub fn builder(r#type: String) -> QueryUserUniversalTransferHistoryParamsBuilder {
621        QueryUserUniversalTransferHistoryParamsBuilder::default().r#type(r#type)
622    }
623}
624/// Request parameters for the [`query_user_wallet_balance`] operation.
625///
626/// This struct holds all of the inputs you can pass when calling
627/// [`query_user_wallet_balance`](#method.query_user_wallet_balance).
628#[derive(Clone, Debug, Builder, Default)]
629#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
630pub struct QueryUserWalletBalanceParams {
631    /// `USDT`, `ETH`, `USDC`, `BNB`, etc. default `BTC`
632    ///
633    /// This field is **optional.
634    #[builder(setter(into), default)]
635    pub quote_asset: Option<String>,
636    ///
637    /// The `recv_window` parameter.
638    ///
639    /// This field is **optional.
640    #[builder(setter(into), default)]
641    pub recv_window: Option<i64>,
642}
643
644impl QueryUserWalletBalanceParams {
645    /// Create a builder for [`query_user_wallet_balance`].
646    ///
647    #[must_use]
648    pub fn builder() -> QueryUserWalletBalanceParamsBuilder {
649        QueryUserWalletBalanceParamsBuilder::default()
650    }
651}
652/// Request parameters for the [`toggle_bnb_burn_on_spot_trade_and_margin_interest`] operation.
653///
654/// This struct holds all of the inputs you can pass when calling
655/// [`toggle_bnb_burn_on_spot_trade_and_margin_interest`](#method.toggle_bnb_burn_on_spot_trade_and_margin_interest).
656#[derive(Clone, Debug, Builder, Default)]
657#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
658pub struct ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
659    /// "true" or "false"; Determines whether to use BNB to pay for trading fees on SPOT
660    ///
661    /// This field is **optional.
662    #[builder(setter(into), default)]
663    pub spot_bnb_burn: Option<String>,
664    /// "true" or "false"; Determines whether to use BNB to pay for margin loan's interest
665    ///
666    /// This field is **optional.
667    #[builder(setter(into), default)]
668    pub interest_bnb_burn: Option<String>,
669    ///
670    /// The `recv_window` parameter.
671    ///
672    /// This field is **optional.
673    #[builder(setter(into), default)]
674    pub recv_window: Option<i64>,
675}
676
677impl ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
678    /// Create a builder for [`toggle_bnb_burn_on_spot_trade_and_margin_interest`].
679    ///
680    #[must_use]
681    pub fn builder() -> ToggleBnbBurnOnSpotTradeAndMarginInterestParamsBuilder {
682        ToggleBnbBurnOnSpotTradeAndMarginInterestParamsBuilder::default()
683    }
684}
685/// Request parameters for the [`trade_fee`] operation.
686///
687/// This struct holds all of the inputs you can pass when calling
688/// [`trade_fee`](#method.trade_fee).
689#[derive(Clone, Debug, Builder, Default)]
690#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
691pub struct TradeFeeParams {
692    ///
693    /// The `symbol` parameter.
694    ///
695    /// This field is **optional.
696    #[builder(setter(into), default)]
697    pub symbol: Option<String>,
698    ///
699    /// The `recv_window` parameter.
700    ///
701    /// This field is **optional.
702    #[builder(setter(into), default)]
703    pub recv_window: Option<i64>,
704}
705
706impl TradeFeeParams {
707    /// Create a builder for [`trade_fee`].
708    ///
709    #[must_use]
710    pub fn builder() -> TradeFeeParamsBuilder {
711        TradeFeeParamsBuilder::default()
712    }
713}
714/// Request parameters for the [`user_asset`] operation.
715///
716/// This struct holds all of the inputs you can pass when calling
717/// [`user_asset`](#method.user_asset).
718#[derive(Clone, Debug, Builder, Default)]
719#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
720pub struct UserAssetParams {
721    /// If asset is blank, then query all positive assets user have.
722    ///
723    /// This field is **optional.
724    #[builder(setter(into), default)]
725    pub asset: Option<String>,
726    /// Whether need btc valuation or not.
727    ///
728    /// This field is **optional.
729    #[builder(setter(into), default)]
730    pub need_btc_valuation: Option<bool>,
731    ///
732    /// The `recv_window` parameter.
733    ///
734    /// This field is **optional.
735    #[builder(setter(into), default)]
736    pub recv_window: Option<i64>,
737}
738
739impl UserAssetParams {
740    /// Create a builder for [`user_asset`].
741    ///
742    #[must_use]
743    pub fn builder() -> UserAssetParamsBuilder {
744        UserAssetParamsBuilder::default()
745    }
746}
747/// Request parameters for the [`user_universal_transfer`] operation.
748///
749/// This struct holds all of the inputs you can pass when calling
750/// [`user_universal_transfer`](#method.user_universal_transfer).
751#[derive(Clone, Debug, Builder)]
752#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
753pub struct UserUniversalTransferParams {
754    ///
755    /// The `r#type` parameter.
756    ///
757    /// This field is **required.
758    #[builder(setter(into))]
759    pub r#type: String,
760    ///
761    /// The `asset` parameter.
762    ///
763    /// This field is **required.
764    #[builder(setter(into))]
765    pub asset: String,
766    ///
767    /// The `amount` parameter.
768    ///
769    /// This field is **required.
770    #[builder(setter(into))]
771    pub amount: rust_decimal::Decimal,
772    ///
773    /// The `from_symbol` parameter.
774    ///
775    /// This field is **optional.
776    #[builder(setter(into), default)]
777    pub from_symbol: Option<String>,
778    ///
779    /// The `to_symbol` parameter.
780    ///
781    /// This field is **optional.
782    #[builder(setter(into), default)]
783    pub to_symbol: Option<String>,
784    ///
785    /// The `recv_window` parameter.
786    ///
787    /// This field is **optional.
788    #[builder(setter(into), default)]
789    pub recv_window: Option<i64>,
790}
791
792impl UserUniversalTransferParams {
793    /// Create a builder for [`user_universal_transfer`].
794    ///
795    /// Required parameters:
796    ///
797    /// * `r#type` — String
798    /// * `asset` — String
799    /// * `amount` — `rust_decimal::Decimal`
800    ///
801    #[must_use]
802    pub fn builder(
803        r#type: String,
804        asset: String,
805        amount: rust_decimal::Decimal,
806    ) -> UserUniversalTransferParamsBuilder {
807        UserUniversalTransferParamsBuilder::default()
808            .r#type(r#type)
809            .asset(asset)
810            .amount(amount)
811    }
812}
813
814#[async_trait]
815impl AssetApi for AssetApiClient {
816    async fn asset_detail(
817        &self,
818        params: AssetDetailParams,
819    ) -> anyhow::Result<RestApiResponse<models::AssetDetailResponse>> {
820        let AssetDetailParams { asset, recv_window } = params;
821
822        let mut query_params = BTreeMap::new();
823        let body_params = BTreeMap::new();
824
825        if let Some(rw) = asset {
826            query_params.insert("asset".to_string(), json!(rw));
827        }
828
829        if let Some(rw) = recv_window {
830            query_params.insert("recvWindow".to_string(), json!(rw));
831        }
832
833        send_request::<models::AssetDetailResponse>(
834            &self.configuration,
835            "/sapi/v1/asset/assetDetail",
836            reqwest::Method::GET,
837            query_params,
838            body_params,
839            if HAS_TIME_UNIT {
840                self.configuration.time_unit
841            } else {
842                None
843            },
844            true,
845        )
846        .await
847    }
848
849    async fn asset_dividend_record(
850        &self,
851        params: AssetDividendRecordParams,
852    ) -> anyhow::Result<RestApiResponse<models::AssetDividendRecordResponse>> {
853        let AssetDividendRecordParams {
854            asset,
855            start_time,
856            end_time,
857            limit,
858            recv_window,
859        } = params;
860
861        let mut query_params = BTreeMap::new();
862        let body_params = BTreeMap::new();
863
864        if let Some(rw) = asset {
865            query_params.insert("asset".to_string(), json!(rw));
866        }
867
868        if let Some(rw) = start_time {
869            query_params.insert("startTime".to_string(), json!(rw));
870        }
871
872        if let Some(rw) = end_time {
873            query_params.insert("endTime".to_string(), json!(rw));
874        }
875
876        if let Some(rw) = limit {
877            query_params.insert("limit".to_string(), json!(rw));
878        }
879
880        if let Some(rw) = recv_window {
881            query_params.insert("recvWindow".to_string(), json!(rw));
882        }
883
884        send_request::<models::AssetDividendRecordResponse>(
885            &self.configuration,
886            "/sapi/v1/asset/assetDividend",
887            reqwest::Method::GET,
888            query_params,
889            body_params,
890            if HAS_TIME_UNIT {
891                self.configuration.time_unit
892            } else {
893                None
894            },
895            true,
896        )
897        .await
898    }
899
900    async fn dust_convert(
901        &self,
902        params: DustConvertParams,
903    ) -> anyhow::Result<RestApiResponse<models::DustConvertResponse>> {
904        let DustConvertParams {
905            asset,
906            account_type,
907            client_id,
908            target_asset,
909            third_party_client_id,
910            dust_quota_asset_to_target_asset_price,
911        } = params;
912
913        let mut query_params = BTreeMap::new();
914        let body_params = BTreeMap::new();
915
916        query_params.insert("asset".to_string(), json!(asset));
917
918        if let Some(rw) = account_type {
919            query_params.insert("accountType".to_string(), json!(rw));
920        }
921
922        if let Some(rw) = client_id {
923            query_params.insert("clientId".to_string(), json!(rw));
924        }
925
926        if let Some(rw) = target_asset {
927            query_params.insert("targetAsset".to_string(), json!(rw));
928        }
929
930        if let Some(rw) = third_party_client_id {
931            query_params.insert("thirdPartyClientId".to_string(), json!(rw));
932        }
933
934        if let Some(rw) = dust_quota_asset_to_target_asset_price {
935            query_params.insert("dustQuotaAssetToTargetAssetPrice".to_string(), json!(rw));
936        }
937
938        send_request::<models::DustConvertResponse>(
939            &self.configuration,
940            "/sapi/v1/asset/dust-convert/convert",
941            reqwest::Method::POST,
942            query_params,
943            body_params,
944            if HAS_TIME_UNIT {
945                self.configuration.time_unit
946            } else {
947                None
948            },
949            true,
950        )
951        .await
952    }
953
954    async fn dust_convertible_assets(
955        &self,
956        params: DustConvertibleAssetsParams,
957    ) -> anyhow::Result<RestApiResponse<models::DustConvertibleAssetsResponse>> {
958        let DustConvertibleAssetsParams {
959            target_asset,
960            account_type,
961            dust_quota_asset_to_target_asset_price,
962        } = params;
963
964        let mut query_params = BTreeMap::new();
965        let body_params = BTreeMap::new();
966
967        if let Some(rw) = account_type {
968            query_params.insert("accountType".to_string(), json!(rw));
969        }
970
971        query_params.insert("targetAsset".to_string(), json!(target_asset));
972
973        if let Some(rw) = dust_quota_asset_to_target_asset_price {
974            query_params.insert("dustQuotaAssetToTargetAssetPrice".to_string(), json!(rw));
975        }
976
977        send_request::<models::DustConvertibleAssetsResponse>(
978            &self.configuration,
979            "/sapi/v1/asset/dust-convert/query-convertible-assets",
980            reqwest::Method::POST,
981            query_params,
982            body_params,
983            if HAS_TIME_UNIT {
984                self.configuration.time_unit
985            } else {
986                None
987            },
988            true,
989        )
990        .await
991    }
992
993    async fn dust_transfer(
994        &self,
995        params: DustTransferParams,
996    ) -> anyhow::Result<RestApiResponse<models::DustTransferResponse>> {
997        let DustTransferParams {
998            asset,
999            account_type,
1000            recv_window,
1001        } = params;
1002
1003        let mut query_params = BTreeMap::new();
1004        let body_params = BTreeMap::new();
1005
1006        query_params.insert("asset".to_string(), json!(asset));
1007
1008        if let Some(rw) = account_type {
1009            query_params.insert("accountType".to_string(), json!(rw));
1010        }
1011
1012        if let Some(rw) = recv_window {
1013            query_params.insert("recvWindow".to_string(), json!(rw));
1014        }
1015
1016        send_request::<models::DustTransferResponse>(
1017            &self.configuration,
1018            "/sapi/v1/asset/dust",
1019            reqwest::Method::POST,
1020            query_params,
1021            body_params,
1022            if HAS_TIME_UNIT {
1023                self.configuration.time_unit
1024            } else {
1025                None
1026            },
1027            true,
1028        )
1029        .await
1030    }
1031
1032    async fn dustlog(
1033        &self,
1034        params: DustlogParams,
1035    ) -> anyhow::Result<RestApiResponse<models::DustlogResponse>> {
1036        let DustlogParams {
1037            account_type,
1038            start_time,
1039            end_time,
1040            recv_window,
1041        } = params;
1042
1043        let mut query_params = BTreeMap::new();
1044        let body_params = BTreeMap::new();
1045
1046        if let Some(rw) = account_type {
1047            query_params.insert("accountType".to_string(), json!(rw));
1048        }
1049
1050        if let Some(rw) = start_time {
1051            query_params.insert("startTime".to_string(), json!(rw));
1052        }
1053
1054        if let Some(rw) = end_time {
1055            query_params.insert("endTime".to_string(), json!(rw));
1056        }
1057
1058        if let Some(rw) = recv_window {
1059            query_params.insert("recvWindow".to_string(), json!(rw));
1060        }
1061
1062        send_request::<models::DustlogResponse>(
1063            &self.configuration,
1064            "/sapi/v1/asset/dribblet",
1065            reqwest::Method::GET,
1066            query_params,
1067            body_params,
1068            if HAS_TIME_UNIT {
1069                self.configuration.time_unit
1070            } else {
1071                None
1072            },
1073            true,
1074        )
1075        .await
1076    }
1077
1078    async fn funding_wallet(
1079        &self,
1080        params: FundingWalletParams,
1081    ) -> anyhow::Result<RestApiResponse<Vec<models::FundingWalletResponseInner>>> {
1082        let FundingWalletParams {
1083            asset,
1084            need_btc_valuation,
1085            recv_window,
1086        } = params;
1087
1088        let mut query_params = BTreeMap::new();
1089        let body_params = BTreeMap::new();
1090
1091        if let Some(rw) = asset {
1092            query_params.insert("asset".to_string(), json!(rw));
1093        }
1094
1095        if let Some(rw) = need_btc_valuation {
1096            query_params.insert("needBtcValuation".to_string(), json!(rw));
1097        }
1098
1099        if let Some(rw) = recv_window {
1100            query_params.insert("recvWindow".to_string(), json!(rw));
1101        }
1102
1103        send_request::<Vec<models::FundingWalletResponseInner>>(
1104            &self.configuration,
1105            "/sapi/v1/asset/get-funding-asset",
1106            reqwest::Method::POST,
1107            query_params,
1108            body_params,
1109            if HAS_TIME_UNIT {
1110                self.configuration.time_unit
1111            } else {
1112                None
1113            },
1114            true,
1115        )
1116        .await
1117    }
1118
1119    async fn get_assets_that_can_be_converted_into_bnb(
1120        &self,
1121        params: GetAssetsThatCanBeConvertedIntoBnbParams,
1122    ) -> anyhow::Result<RestApiResponse<models::GetAssetsThatCanBeConvertedIntoBnbResponse>> {
1123        let GetAssetsThatCanBeConvertedIntoBnbParams {
1124            account_type,
1125            recv_window,
1126        } = params;
1127
1128        let mut query_params = BTreeMap::new();
1129        let body_params = BTreeMap::new();
1130
1131        if let Some(rw) = account_type {
1132            query_params.insert("accountType".to_string(), json!(rw));
1133        }
1134
1135        if let Some(rw) = recv_window {
1136            query_params.insert("recvWindow".to_string(), json!(rw));
1137        }
1138
1139        send_request::<models::GetAssetsThatCanBeConvertedIntoBnbResponse>(
1140            &self.configuration,
1141            "/sapi/v1/asset/dust-btc",
1142            reqwest::Method::POST,
1143            query_params,
1144            body_params,
1145            if HAS_TIME_UNIT {
1146                self.configuration.time_unit
1147            } else {
1148                None
1149            },
1150            true,
1151        )
1152        .await
1153    }
1154
1155    async fn get_cloud_mining_payment_and_refund_history(
1156        &self,
1157        params: GetCloudMiningPaymentAndRefundHistoryParams,
1158    ) -> anyhow::Result<RestApiResponse<models::GetCloudMiningPaymentAndRefundHistoryResponse>>
1159    {
1160        let GetCloudMiningPaymentAndRefundHistoryParams {
1161            start_time,
1162            end_time,
1163            tran_id,
1164            client_tran_id,
1165            asset,
1166            current,
1167            size,
1168        } = params;
1169
1170        let mut query_params = BTreeMap::new();
1171        let body_params = BTreeMap::new();
1172
1173        if let Some(rw) = tran_id {
1174            query_params.insert("tranId".to_string(), json!(rw));
1175        }
1176
1177        if let Some(rw) = client_tran_id {
1178            query_params.insert("clientTranId".to_string(), json!(rw));
1179        }
1180
1181        if let Some(rw) = asset {
1182            query_params.insert("asset".to_string(), json!(rw));
1183        }
1184
1185        query_params.insert("startTime".to_string(), json!(start_time));
1186
1187        query_params.insert("endTime".to_string(), json!(end_time));
1188
1189        if let Some(rw) = current {
1190            query_params.insert("current".to_string(), json!(rw));
1191        }
1192
1193        if let Some(rw) = size {
1194            query_params.insert("size".to_string(), json!(rw));
1195        }
1196
1197        send_request::<models::GetCloudMiningPaymentAndRefundHistoryResponse>(
1198            &self.configuration,
1199            "/sapi/v1/asset/ledger-transfer/cloud-mining/queryByPage",
1200            reqwest::Method::GET,
1201            query_params,
1202            body_params,
1203            if HAS_TIME_UNIT {
1204                self.configuration.time_unit
1205            } else {
1206                None
1207            },
1208            true,
1209        )
1210        .await
1211    }
1212
1213    async fn get_open_symbol_list(
1214        &self,
1215    ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenSymbolListResponseInner>>> {
1216        let query_params = BTreeMap::new();
1217        let body_params = BTreeMap::new();
1218
1219        send_request::<Vec<models::GetOpenSymbolListResponseInner>>(
1220            &self.configuration,
1221            "/sapi/v1/spot/open-symbol-list",
1222            reqwest::Method::GET,
1223            query_params,
1224            body_params,
1225            if HAS_TIME_UNIT {
1226                self.configuration.time_unit
1227            } else {
1228                None
1229            },
1230            false,
1231        )
1232        .await
1233    }
1234
1235    async fn query_user_delegation_history(
1236        &self,
1237        params: QueryUserDelegationHistoryParams,
1238    ) -> anyhow::Result<RestApiResponse<models::QueryUserDelegationHistoryResponse>> {
1239        let QueryUserDelegationHistoryParams {
1240            email,
1241            start_time,
1242            end_time,
1243            r#type,
1244            asset,
1245            current,
1246            size,
1247            recv_window,
1248        } = params;
1249
1250        let mut query_params = BTreeMap::new();
1251        let body_params = BTreeMap::new();
1252
1253        query_params.insert("email".to_string(), json!(email));
1254
1255        query_params.insert("startTime".to_string(), json!(start_time));
1256
1257        query_params.insert("endTime".to_string(), json!(end_time));
1258
1259        if let Some(rw) = r#type {
1260            query_params.insert("type".to_string(), json!(rw));
1261        }
1262
1263        if let Some(rw) = asset {
1264            query_params.insert("asset".to_string(), json!(rw));
1265        }
1266
1267        if let Some(rw) = current {
1268            query_params.insert("current".to_string(), json!(rw));
1269        }
1270
1271        if let Some(rw) = size {
1272            query_params.insert("size".to_string(), json!(rw));
1273        }
1274
1275        if let Some(rw) = recv_window {
1276            query_params.insert("recvWindow".to_string(), json!(rw));
1277        }
1278
1279        send_request::<models::QueryUserDelegationHistoryResponse>(
1280            &self.configuration,
1281            "/sapi/v1/asset/custody/transfer-history",
1282            reqwest::Method::GET,
1283            query_params,
1284            body_params,
1285            if HAS_TIME_UNIT {
1286                self.configuration.time_unit
1287            } else {
1288                None
1289            },
1290            true,
1291        )
1292        .await
1293    }
1294
1295    async fn query_user_universal_transfer_history(
1296        &self,
1297        params: QueryUserUniversalTransferHistoryParams,
1298    ) -> anyhow::Result<RestApiResponse<models::QueryUserUniversalTransferHistoryResponse>> {
1299        let QueryUserUniversalTransferHistoryParams {
1300            r#type,
1301            start_time,
1302            end_time,
1303            current,
1304            size,
1305            from_symbol,
1306            to_symbol,
1307            recv_window,
1308        } = params;
1309
1310        let mut query_params = BTreeMap::new();
1311        let body_params = BTreeMap::new();
1312
1313        query_params.insert("type".to_string(), json!(r#type));
1314
1315        if let Some(rw) = start_time {
1316            query_params.insert("startTime".to_string(), json!(rw));
1317        }
1318
1319        if let Some(rw) = end_time {
1320            query_params.insert("endTime".to_string(), json!(rw));
1321        }
1322
1323        if let Some(rw) = current {
1324            query_params.insert("current".to_string(), json!(rw));
1325        }
1326
1327        if let Some(rw) = size {
1328            query_params.insert("size".to_string(), json!(rw));
1329        }
1330
1331        if let Some(rw) = from_symbol {
1332            query_params.insert("fromSymbol".to_string(), json!(rw));
1333        }
1334
1335        if let Some(rw) = to_symbol {
1336            query_params.insert("toSymbol".to_string(), json!(rw));
1337        }
1338
1339        if let Some(rw) = recv_window {
1340            query_params.insert("recvWindow".to_string(), json!(rw));
1341        }
1342
1343        send_request::<models::QueryUserUniversalTransferHistoryResponse>(
1344            &self.configuration,
1345            "/sapi/v1/asset/transfer",
1346            reqwest::Method::GET,
1347            query_params,
1348            body_params,
1349            if HAS_TIME_UNIT {
1350                self.configuration.time_unit
1351            } else {
1352                None
1353            },
1354            true,
1355        )
1356        .await
1357    }
1358
1359    async fn query_user_wallet_balance(
1360        &self,
1361        params: QueryUserWalletBalanceParams,
1362    ) -> anyhow::Result<RestApiResponse<Vec<models::QueryUserWalletBalanceResponseInner>>> {
1363        let QueryUserWalletBalanceParams {
1364            quote_asset,
1365            recv_window,
1366        } = params;
1367
1368        let mut query_params = BTreeMap::new();
1369        let body_params = BTreeMap::new();
1370
1371        if let Some(rw) = quote_asset {
1372            query_params.insert("quoteAsset".to_string(), json!(rw));
1373        }
1374
1375        if let Some(rw) = recv_window {
1376            query_params.insert("recvWindow".to_string(), json!(rw));
1377        }
1378
1379        send_request::<Vec<models::QueryUserWalletBalanceResponseInner>>(
1380            &self.configuration,
1381            "/sapi/v1/asset/wallet/balance",
1382            reqwest::Method::GET,
1383            query_params,
1384            body_params,
1385            if HAS_TIME_UNIT {
1386                self.configuration.time_unit
1387            } else {
1388                None
1389            },
1390            true,
1391        )
1392        .await
1393    }
1394
1395    async fn toggle_bnb_burn_on_spot_trade_and_margin_interest(
1396        &self,
1397        params: ToggleBnbBurnOnSpotTradeAndMarginInterestParams,
1398    ) -> anyhow::Result<RestApiResponse<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>>
1399    {
1400        let ToggleBnbBurnOnSpotTradeAndMarginInterestParams {
1401            spot_bnb_burn,
1402            interest_bnb_burn,
1403            recv_window,
1404        } = params;
1405
1406        let mut query_params = BTreeMap::new();
1407        let body_params = BTreeMap::new();
1408
1409        if let Some(rw) = spot_bnb_burn {
1410            query_params.insert("spotBNBBurn".to_string(), json!(rw));
1411        }
1412
1413        if let Some(rw) = interest_bnb_burn {
1414            query_params.insert("interestBNBBurn".to_string(), json!(rw));
1415        }
1416
1417        if let Some(rw) = recv_window {
1418            query_params.insert("recvWindow".to_string(), json!(rw));
1419        }
1420
1421        send_request::<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>(
1422            &self.configuration,
1423            "/sapi/v1/bnbBurn",
1424            reqwest::Method::POST,
1425            query_params,
1426            body_params,
1427            if HAS_TIME_UNIT {
1428                self.configuration.time_unit
1429            } else {
1430                None
1431            },
1432            true,
1433        )
1434        .await
1435    }
1436
1437    async fn trade_fee(
1438        &self,
1439        params: TradeFeeParams,
1440    ) -> anyhow::Result<RestApiResponse<Vec<models::TradeFeeResponseInner>>> {
1441        let TradeFeeParams {
1442            symbol,
1443            recv_window,
1444        } = params;
1445
1446        let mut query_params = BTreeMap::new();
1447        let body_params = BTreeMap::new();
1448
1449        if let Some(rw) = symbol {
1450            query_params.insert("symbol".to_string(), json!(rw));
1451        }
1452
1453        if let Some(rw) = recv_window {
1454            query_params.insert("recvWindow".to_string(), json!(rw));
1455        }
1456
1457        send_request::<Vec<models::TradeFeeResponseInner>>(
1458            &self.configuration,
1459            "/sapi/v1/asset/tradeFee",
1460            reqwest::Method::GET,
1461            query_params,
1462            body_params,
1463            if HAS_TIME_UNIT {
1464                self.configuration.time_unit
1465            } else {
1466                None
1467            },
1468            true,
1469        )
1470        .await
1471    }
1472
1473    async fn user_asset(
1474        &self,
1475        params: UserAssetParams,
1476    ) -> anyhow::Result<RestApiResponse<Vec<models::UserAssetResponseInner>>> {
1477        let UserAssetParams {
1478            asset,
1479            need_btc_valuation,
1480            recv_window,
1481        } = params;
1482
1483        let mut query_params = BTreeMap::new();
1484        let body_params = BTreeMap::new();
1485
1486        if let Some(rw) = asset {
1487            query_params.insert("asset".to_string(), json!(rw));
1488        }
1489
1490        if let Some(rw) = need_btc_valuation {
1491            query_params.insert("needBtcValuation".to_string(), json!(rw));
1492        }
1493
1494        if let Some(rw) = recv_window {
1495            query_params.insert("recvWindow".to_string(), json!(rw));
1496        }
1497
1498        send_request::<Vec<models::UserAssetResponseInner>>(
1499            &self.configuration,
1500            "/sapi/v3/asset/getUserAsset",
1501            reqwest::Method::POST,
1502            query_params,
1503            body_params,
1504            if HAS_TIME_UNIT {
1505                self.configuration.time_unit
1506            } else {
1507                None
1508            },
1509            true,
1510        )
1511        .await
1512    }
1513
1514    async fn user_universal_transfer(
1515        &self,
1516        params: UserUniversalTransferParams,
1517    ) -> anyhow::Result<RestApiResponse<models::UserUniversalTransferResponse>> {
1518        let UserUniversalTransferParams {
1519            r#type,
1520            asset,
1521            amount,
1522            from_symbol,
1523            to_symbol,
1524            recv_window,
1525        } = params;
1526
1527        let mut query_params = BTreeMap::new();
1528        let body_params = BTreeMap::new();
1529
1530        query_params.insert("type".to_string(), json!(r#type));
1531
1532        query_params.insert("asset".to_string(), json!(asset));
1533
1534        query_params.insert("amount".to_string(), json!(amount));
1535
1536        if let Some(rw) = from_symbol {
1537            query_params.insert("fromSymbol".to_string(), json!(rw));
1538        }
1539
1540        if let Some(rw) = to_symbol {
1541            query_params.insert("toSymbol".to_string(), json!(rw));
1542        }
1543
1544        if let Some(rw) = recv_window {
1545            query_params.insert("recvWindow".to_string(), json!(rw));
1546        }
1547
1548        send_request::<models::UserUniversalTransferResponse>(
1549            &self.configuration,
1550            "/sapi/v1/asset/transfer",
1551            reqwest::Method::POST,
1552            query_params,
1553            body_params,
1554            if HAS_TIME_UNIT {
1555                self.configuration.time_unit
1556            } else {
1557                None
1558            },
1559            true,
1560        )
1561        .await
1562    }
1563}
1564
1565#[cfg(all(test, feature = "wallet"))]
1566mod tests {
1567    use super::*;
1568    use crate::TOKIO_SHARED_RT;
1569    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
1570    use async_trait::async_trait;
1571    use std::collections::HashMap;
1572
1573    struct DummyRestApiResponse<T> {
1574        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
1575        status: u16,
1576        headers: HashMap<String, String>,
1577        rate_limits: Option<Vec<RestApiRateLimit>>,
1578    }
1579
1580    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
1581        fn from(dummy: DummyRestApiResponse<T>) -> Self {
1582            Self {
1583                data_fn: dummy.inner,
1584                status: dummy.status,
1585                headers: dummy.headers,
1586                rate_limits: dummy.rate_limits,
1587            }
1588        }
1589    }
1590
1591    struct MockAssetApiClient {
1592        force_error: bool,
1593    }
1594
1595    #[async_trait]
1596    impl AssetApi for MockAssetApiClient {
1597        async fn asset_detail(
1598            &self,
1599            _params: AssetDetailParams,
1600        ) -> anyhow::Result<RestApiResponse<models::AssetDetailResponse>> {
1601            if self.force_error {
1602                return Err(ConnectorError::ConnectorClientError {
1603                    msg: "ResponseError".to_string(),
1604                    code: None,
1605                }
1606                .into());
1607            }
1608
1609            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();
1610            let dummy_response: models::AssetDetailResponse =
1611                serde_json::from_value(resp_json.clone())
1612                    .expect("should parse into models::AssetDetailResponse");
1613
1614            let dummy = DummyRestApiResponse {
1615                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1616                status: 200,
1617                headers: HashMap::new(),
1618                rate_limits: None,
1619            };
1620
1621            Ok(dummy.into())
1622        }
1623
1624        async fn asset_dividend_record(
1625            &self,
1626            _params: AssetDividendRecordParams,
1627        ) -> anyhow::Result<RestApiResponse<models::AssetDividendRecordResponse>> {
1628            if self.force_error {
1629                return Err(ConnectorError::ConnectorClientError {
1630                    msg: "ResponseError".to_string(),
1631                    code: None,
1632                }
1633                .into());
1634            }
1635
1636            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},{"id":1631750237,"amount":"10.00000000","asset":"BHFT","divTime":1563189165000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap();
1637            let dummy_response: models::AssetDividendRecordResponse =
1638                serde_json::from_value(resp_json.clone())
1639                    .expect("should parse into models::AssetDividendRecordResponse");
1640
1641            let dummy = DummyRestApiResponse {
1642                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1643                status: 200,
1644                headers: HashMap::new(),
1645                rate_limits: None,
1646            };
1647
1648            Ok(dummy.into())
1649        }
1650
1651        async fn dust_convert(
1652            &self,
1653            _params: DustConvertParams,
1654        ) -> anyhow::Result<RestApiResponse<models::DustConvertResponse>> {
1655            if self.force_error {
1656                return Err(ConnectorError::ConnectorClientError {
1657                    msg: "ResponseError".to_string(),
1658                    code: None,
1659                }
1660                .into());
1661            }
1662
1663            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();
1664            let dummy_response: models::DustConvertResponse =
1665                serde_json::from_value(resp_json.clone())
1666                    .expect("should parse into models::DustConvertResponse");
1667
1668            let dummy = DummyRestApiResponse {
1669                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1670                status: 200,
1671                headers: HashMap::new(),
1672                rate_limits: None,
1673            };
1674
1675            Ok(dummy.into())
1676        }
1677
1678        async fn dust_convertible_assets(
1679            &self,
1680            _params: DustConvertibleAssetsParams,
1681        ) -> anyhow::Result<RestApiResponse<models::DustConvertibleAssetsResponse>> {
1682            if self.force_error {
1683                return Err(ConnectorError::ConnectorClientError {
1684                    msg: "ResponseError".to_string(),
1685                    code: None,
1686                }
1687                .into());
1688            }
1689
1690            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"},{"asset":"BNB","assetFullName":"BNB","amountFree":"0.00082768","exchange":"0.01506378","toQuotaAssetAmount":"0.7531888","toTargetAssetAmount":"0.7531888","toTargetAssetOffExchange":"0.73812502"}]}"#).unwrap();
1691            let dummy_response: models::DustConvertibleAssetsResponse =
1692                serde_json::from_value(resp_json.clone())
1693                    .expect("should parse into models::DustConvertibleAssetsResponse");
1694
1695            let dummy = DummyRestApiResponse {
1696                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1697                status: 200,
1698                headers: HashMap::new(),
1699                rate_limits: None,
1700            };
1701
1702            Ok(dummy.into())
1703        }
1704
1705        async fn dust_transfer(
1706            &self,
1707            _params: DustTransferParams,
1708        ) -> anyhow::Result<RestApiResponse<models::DustTransferResponse>> {
1709            if self.force_error {
1710                return Err(ConnectorError::ConnectorClientError {
1711                    msg: "ResponseError".to_string(),
1712                    code: None,
1713                }
1714                .into());
1715            }
1716
1717            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"},{"amount":"0.09000000","fromAsset":"LTC","operateTime":1563368549404,"serviceChargeAmount":"0.01548000","tranId":2970932918,"transferedAmount":"0.77400000"},{"amount":"248.61878453","fromAsset":"TRX","operateTime":1563368549489,"serviceChargeAmount":"0.00054542","tranId":2970932918,"transferedAmount":"0.02727099"}]}"#).unwrap();
1718            let dummy_response: models::DustTransferResponse =
1719                serde_json::from_value(resp_json.clone())
1720                    .expect("should parse into models::DustTransferResponse");
1721
1722            let dummy = DummyRestApiResponse {
1723                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1724                status: 200,
1725                headers: HashMap::new(),
1726                rate_limits: None,
1727            };
1728
1729            Ok(dummy.into())
1730        }
1731
1732        async fn dustlog(
1733            &self,
1734            _params: DustlogParams,
1735        ) -> anyhow::Result<RestApiResponse<models::DustlogResponse>> {
1736            if self.force_error {
1737                return Err(ConnectorError::ConnectorClientError {
1738                    msg: "ResponseError".to_string(),
1739                    code: None,
1740                }
1741                .into());
1742            }
1743
1744            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"},{"transId":4359321,"serviceChargeAmount":"0.00001799","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.00088156","fromAsset":"ETH"}]},{"operateTime":1616203180000,"totalTransferedAmount":"0.00058795","totalServiceChargeAmount":"0.000012","transId":4357015,"userAssetDribbletDetails":[{"transId":4357015,"serviceChargeAmount":"0.00001","amount":"0.001","operateTime":1616203180000,"transferedAmount":"0.00049","fromAsset":"USDT"},{"transId":4357015,"serviceChargeAmount":"0.000002","amount":"0.0001","operateTime":1616203180000,"transferedAmount":"0.00009795","fromAsset":"ETH"}]}]}"#).unwrap();
1745            let dummy_response: models::DustlogResponse = serde_json::from_value(resp_json.clone())
1746                .expect("should parse into models::DustlogResponse");
1747
1748            let dummy = DummyRestApiResponse {
1749                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1750                status: 200,
1751                headers: HashMap::new(),
1752                rate_limits: None,
1753            };
1754
1755            Ok(dummy.into())
1756        }
1757
1758        async fn funding_wallet(
1759            &self,
1760            _params: FundingWalletParams,
1761        ) -> anyhow::Result<RestApiResponse<Vec<models::FundingWalletResponseInner>>> {
1762            if self.force_error {
1763                return Err(ConnectorError::ConnectorClientError {
1764                    msg: "ResponseError".to_string(),
1765                    code: None,
1766                }
1767                .into());
1768            }
1769
1770            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap();
1771            let dummy_response: Vec<models::FundingWalletResponseInner> =
1772                serde_json::from_value(resp_json.clone())
1773                    .expect("should parse into Vec<models::FundingWalletResponseInner>");
1774
1775            let dummy = DummyRestApiResponse {
1776                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1777                status: 200,
1778                headers: HashMap::new(),
1779                rate_limits: None,
1780            };
1781
1782            Ok(dummy.into())
1783        }
1784
1785        async fn get_assets_that_can_be_converted_into_bnb(
1786            &self,
1787            _params: GetAssetsThatCanBeConvertedIntoBnbParams,
1788        ) -> anyhow::Result<RestApiResponse<models::GetAssetsThatCanBeConvertedIntoBnbResponse>>
1789        {
1790            if self.force_error {
1791                return Err(ConnectorError::ConnectorClientError {
1792                    msg: "ResponseError".to_string(),
1793                    code: None,
1794                }
1795                .into());
1796            }
1797
1798            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();
1799            let dummy_response: models::GetAssetsThatCanBeConvertedIntoBnbResponse =
1800                serde_json::from_value(resp_json.clone())
1801                    .expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
1802
1803            let dummy = DummyRestApiResponse {
1804                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1805                status: 200,
1806                headers: HashMap::new(),
1807                rate_limits: None,
1808            };
1809
1810            Ok(dummy.into())
1811        }
1812
1813        async fn get_cloud_mining_payment_and_refund_history(
1814            &self,
1815            _params: GetCloudMiningPaymentAndRefundHistoryParams,
1816        ) -> anyhow::Result<RestApiResponse<models::GetCloudMiningPaymentAndRefundHistoryResponse>>
1817        {
1818            if self.force_error {
1819                return Err(ConnectorError::ConnectorClientError {
1820                    msg: "ResponseError".to_string(),
1821                    code: None,
1822                }
1823                .into());
1824            }
1825
1826            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"},{"createTime":1666776366000,"tranId":119991507468,"type":249,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666764505000,"tranId":119977966327,"type":248,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666758189000,"tranId":119973601721,"type":248,"asset":"USDT","amount":"0.018","status":"S"},{"createTime":1666757278000,"tranId":119973028551,"type":248,"asset":"USDT","amount":"0.018","status":"S"}]}"#).unwrap();
1827            let dummy_response: models::GetCloudMiningPaymentAndRefundHistoryResponse =
1828                serde_json::from_value(resp_json.clone()).expect(
1829                    "should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse",
1830                );
1831
1832            let dummy = DummyRestApiResponse {
1833                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1834                status: 200,
1835                headers: HashMap::new(),
1836                rate_limits: None,
1837            };
1838
1839            Ok(dummy.into())
1840        }
1841
1842        async fn get_open_symbol_list(
1843            &self,
1844        ) -> anyhow::Result<RestApiResponse<Vec<models::GetOpenSymbolListResponseInner>>> {
1845            if self.force_error {
1846                return Err(ConnectorError::ConnectorClientError {
1847                    msg: "ResponseError".to_string(),
1848                    code: None,
1849                }
1850                .into());
1851            }
1852
1853            let resp_json: Value = serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC","BNBETH"]},{"openTime":1686222232000,"symbols":["BTCUSDT"]}]"#).unwrap();
1854            let dummy_response: Vec<models::GetOpenSymbolListResponseInner> =
1855                serde_json::from_value(resp_json.clone())
1856                    .expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
1857
1858            let dummy = DummyRestApiResponse {
1859                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1860                status: 200,
1861                headers: HashMap::new(),
1862                rate_limits: None,
1863            };
1864
1865            Ok(dummy.into())
1866        }
1867
1868        async fn query_user_delegation_history(
1869            &self,
1870            _params: QueryUserDelegationHistoryParams,
1871        ) -> anyhow::Result<RestApiResponse<models::QueryUserDelegationHistoryResponse>> {
1872            if self.force_error {
1873                return Err(ConnectorError::ConnectorClientError {
1874                    msg: "ResponseError".to_string(),
1875                    code: None,
1876                }
1877                .into());
1878            }
1879
1880            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000},{"clientTranId":"293915892281413632","transferType":"Delegate","asset":"ETH","amount":"1","time":1695205396000}]}"#).unwrap();
1881            let dummy_response: models::QueryUserDelegationHistoryResponse =
1882                serde_json::from_value(resp_json.clone())
1883                    .expect("should parse into models::QueryUserDelegationHistoryResponse");
1884
1885            let dummy = DummyRestApiResponse {
1886                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1887                status: 200,
1888                headers: HashMap::new(),
1889                rate_limits: None,
1890            };
1891
1892            Ok(dummy.into())
1893        }
1894
1895        async fn query_user_universal_transfer_history(
1896            &self,
1897            _params: QueryUserUniversalTransferHistoryParams,
1898        ) -> anyhow::Result<RestApiResponse<models::QueryUserUniversalTransferHistoryResponse>>
1899        {
1900            if self.force_error {
1901                return Err(ConnectorError::ConnectorClientError {
1902                    msg: "ResponseError".to_string(),
1903                    code: None,
1904                }
1905                .into());
1906            }
1907
1908            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},{"asset":"USDT","amount":"2","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11366865406,"timestamp":1544433328000}]}"#).unwrap();
1909            let dummy_response: models::QueryUserUniversalTransferHistoryResponse =
1910                serde_json::from_value(resp_json.clone())
1911                    .expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
1912
1913            let dummy = DummyRestApiResponse {
1914                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1915                status: 200,
1916                headers: HashMap::new(),
1917                rate_limits: None,
1918            };
1919
1920            Ok(dummy.into())
1921        }
1922
1923        async fn query_user_wallet_balance(
1924            &self,
1925            _params: QueryUserWalletBalanceParams,
1926        ) -> anyhow::Result<RestApiResponse<Vec<models::QueryUserWalletBalanceResponseInner>>>
1927        {
1928            if self.force_error {
1929                return Err(ConnectorError::ConnectorClientError {
1930                    msg: "ResponseError".to_string(),
1931                    code: None,
1932                }
1933                .into());
1934            }
1935
1936            let resp_json: Value = serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"},{"activate":true,"balance":"0","walletName":"Funding"},{"activate":true,"balance":"0","walletName":"Cross Margin"},{"activate":true,"balance":"0","walletName":"Isolated Margin"},{"activate":true,"balance":"0.71842752","walletName":"USDⓈ-M Futures"},{"activate":true,"balance":"0","walletName":"COIN-M Futures"},{"activate":true,"balance":"0","walletName":"Earn"},{"activate":false,"balance":"0","walletName":"Options"},{"activate":true,"balance":"0","walletName":"Trading Bots"},{"activate":true,"balance":"0","walletName":"Copy Trading"}]"#).unwrap();
1937            let dummy_response: Vec<models::QueryUserWalletBalanceResponseInner> =
1938                serde_json::from_value(resp_json.clone())
1939                    .expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
1940
1941            let dummy = DummyRestApiResponse {
1942                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1943                status: 200,
1944                headers: HashMap::new(),
1945                rate_limits: None,
1946            };
1947
1948            Ok(dummy.into())
1949        }
1950
1951        async fn toggle_bnb_burn_on_spot_trade_and_margin_interest(
1952            &self,
1953            _params: ToggleBnbBurnOnSpotTradeAndMarginInterestParams,
1954        ) -> anyhow::Result<
1955            RestApiResponse<models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse>,
1956        > {
1957            if self.force_error {
1958                return Err(ConnectorError::ConnectorClientError {
1959                    msg: "ResponseError".to_string(),
1960                    code: None,
1961                }
1962                .into());
1963            }
1964
1965            let resp_json: Value =
1966                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#).unwrap();
1967            let dummy_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
1968                serde_json::from_value(resp_json.clone()).expect(
1969                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
1970                );
1971
1972            let dummy = DummyRestApiResponse {
1973                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1974                status: 200,
1975                headers: HashMap::new(),
1976                rate_limits: None,
1977            };
1978
1979            Ok(dummy.into())
1980        }
1981
1982        async fn trade_fee(
1983            &self,
1984            _params: TradeFeeParams,
1985        ) -> anyhow::Result<RestApiResponse<Vec<models::TradeFeeResponseInner>>> {
1986            if self.force_error {
1987                return Err(ConnectorError::ConnectorClientError {
1988                    msg: "ResponseError".to_string(),
1989                    code: None,
1990                }
1991                .into());
1992            }
1993
1994            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"},{"symbol":"BNBBTC","makerCommission":"0.001","takerCommission":"0.001"}]"#).unwrap();
1995            let dummy_response: Vec<models::TradeFeeResponseInner> =
1996                serde_json::from_value(resp_json.clone())
1997                    .expect("should parse into Vec<models::TradeFeeResponseInner>");
1998
1999            let dummy = DummyRestApiResponse {
2000                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2001                status: 200,
2002                headers: HashMap::new(),
2003                rate_limits: None,
2004            };
2005
2006            Ok(dummy.into())
2007        }
2008
2009        async fn user_asset(
2010            &self,
2011            _params: UserAssetParams,
2012        ) -> anyhow::Result<RestApiResponse<Vec<models::UserAssetResponseInner>>> {
2013            if self.force_error {
2014                return Err(ConnectorError::ConnectorClientError {
2015                    msg: "ResponseError".to_string(),
2016                    code: None,
2017                }
2018                .into());
2019            }
2020
2021            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BCH","free":"0.9","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BNB","free":"887.47061626","locked":"0","freeze":"10.52","withdrawing":"0.1","ipoable":"0","btcValuation":"0"},{"asset":"BUSD","free":"9999.7","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"SHIB","free":"532.32","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"USDT","free":"50300000001.44911105","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"WRZ","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap();
2022            let dummy_response: Vec<models::UserAssetResponseInner> =
2023                serde_json::from_value(resp_json.clone())
2024                    .expect("should parse into Vec<models::UserAssetResponseInner>");
2025
2026            let dummy = DummyRestApiResponse {
2027                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2028                status: 200,
2029                headers: HashMap::new(),
2030                rate_limits: None,
2031            };
2032
2033            Ok(dummy.into())
2034        }
2035
2036        async fn user_universal_transfer(
2037            &self,
2038            _params: UserUniversalTransferParams,
2039        ) -> anyhow::Result<RestApiResponse<models::UserUniversalTransferResponse>> {
2040            if self.force_error {
2041                return Err(ConnectorError::ConnectorClientError {
2042                    msg: "ResponseError".to_string(),
2043                    code: None,
2044                }
2045                .into());
2046            }
2047
2048            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#).unwrap();
2049            let dummy_response: models::UserUniversalTransferResponse =
2050                serde_json::from_value(resp_json.clone())
2051                    .expect("should parse into models::UserUniversalTransferResponse");
2052
2053            let dummy = DummyRestApiResponse {
2054                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
2055                status: 200,
2056                headers: HashMap::new(),
2057                rate_limits: None,
2058            };
2059
2060            Ok(dummy.into())
2061        }
2062    }
2063
2064    #[test]
2065    fn asset_detail_required_params_success() {
2066        TOKIO_SHARED_RT.block_on(async {
2067            let client = MockAssetApiClient { force_error: false };
2068
2069            let params = AssetDetailParams::builder().build().unwrap();
2070
2071            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();
2072            let expected_response : models::AssetDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDetailResponse");
2073
2074            let resp = client.asset_detail(params).await.expect("Expected a response");
2075            let data_future = resp.data();
2076            let actual_response = data_future.await.unwrap();
2077            assert_eq!(actual_response, expected_response);
2078        });
2079    }
2080
2081    #[test]
2082    fn asset_detail_optional_params_success() {
2083        TOKIO_SHARED_RT.block_on(async {
2084            let client = MockAssetApiClient { force_error: false };
2085
2086            let params = AssetDetailParams::builder().asset("asset_example".to_string()).recv_window(5000).build().unwrap();
2087
2088            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();
2089            let expected_response : models::AssetDetailResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDetailResponse");
2090
2091            let resp = client.asset_detail(params).await.expect("Expected a response");
2092            let data_future = resp.data();
2093            let actual_response = data_future.await.unwrap();
2094            assert_eq!(actual_response, expected_response);
2095        });
2096    }
2097
2098    #[test]
2099    fn asset_detail_response_error() {
2100        TOKIO_SHARED_RT.block_on(async {
2101            let client = MockAssetApiClient { force_error: true };
2102
2103            let params = AssetDetailParams::builder().build().unwrap();
2104
2105            match client.asset_detail(params).await {
2106                Ok(_) => panic!("Expected an error"),
2107                Err(err) => {
2108                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2109                }
2110            }
2111        });
2112    }
2113
2114    #[test]
2115    fn asset_dividend_record_required_params_success() {
2116        TOKIO_SHARED_RT.block_on(async {
2117            let client = MockAssetApiClient { force_error: false };
2118
2119            let params = AssetDividendRecordParams::builder().build().unwrap();
2120
2121            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},{"id":1631750237,"amount":"10.00000000","asset":"BHFT","divTime":1563189165000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap();
2122            let expected_response : models::AssetDividendRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDividendRecordResponse");
2123
2124            let resp = client.asset_dividend_record(params).await.expect("Expected a response");
2125            let data_future = resp.data();
2126            let actual_response = data_future.await.unwrap();
2127            assert_eq!(actual_response, expected_response);
2128        });
2129    }
2130
2131    #[test]
2132    fn asset_dividend_record_optional_params_success() {
2133        TOKIO_SHARED_RT.block_on(async {
2134            let client = MockAssetApiClient { force_error: false };
2135
2136            let params = AssetDividendRecordParams::builder().asset("asset_example".to_string()).start_time(1623319461670).end_time(1641782889000).limit(7).recv_window(5000).build().unwrap();
2137
2138            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},{"id":1631750237,"amount":"10.00000000","asset":"BHFT","divTime":1563189165000,"enInfo":"BHFT distribution","tranId":2968885920,"direction":1}],"total":2}"#).unwrap();
2139            let expected_response : models::AssetDividendRecordResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::AssetDividendRecordResponse");
2140
2141            let resp = client.asset_dividend_record(params).await.expect("Expected a response");
2142            let data_future = resp.data();
2143            let actual_response = data_future.await.unwrap();
2144            assert_eq!(actual_response, expected_response);
2145        });
2146    }
2147
2148    #[test]
2149    fn asset_dividend_record_response_error() {
2150        TOKIO_SHARED_RT.block_on(async {
2151            let client = MockAssetApiClient { force_error: true };
2152
2153            let params = AssetDividendRecordParams::builder().build().unwrap();
2154
2155            match client.asset_dividend_record(params).await {
2156                Ok(_) => panic!("Expected an error"),
2157                Err(err) => {
2158                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2159                }
2160            }
2161        });
2162    }
2163
2164    #[test]
2165    fn dust_convert_required_params_success() {
2166        TOKIO_SHARED_RT.block_on(async {
2167            let client = MockAssetApiClient { force_error: false };
2168
2169            let params = DustConvertParams::builder("asset_example".to_string(),).build().unwrap();
2170
2171            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();
2172            let expected_response : models::DustConvertResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertResponse");
2173
2174            let resp = client.dust_convert(params).await.expect("Expected a response");
2175            let data_future = resp.data();
2176            let actual_response = data_future.await.unwrap();
2177            assert_eq!(actual_response, expected_response);
2178        });
2179    }
2180
2181    #[test]
2182    fn dust_convert_optional_params_success() {
2183        TOKIO_SHARED_RT.block_on(async {
2184            let client = MockAssetApiClient { force_error: false };
2185
2186            let params = DustConvertParams::builder("asset_example".to_string(),).account_type("SPOT".to_string()).client_id("1".to_string()).target_asset("target_asset_example".to_string()).third_party_client_id("1".to_string()).dust_quota_asset_to_target_asset_price(dec!(1.0)).build().unwrap();
2187
2188            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();
2189            let expected_response : models::DustConvertResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertResponse");
2190
2191            let resp = client.dust_convert(params).await.expect("Expected a response");
2192            let data_future = resp.data();
2193            let actual_response = data_future.await.unwrap();
2194            assert_eq!(actual_response, expected_response);
2195        });
2196    }
2197
2198    #[test]
2199    fn dust_convert_response_error() {
2200        TOKIO_SHARED_RT.block_on(async {
2201            let client = MockAssetApiClient { force_error: true };
2202
2203            let params = DustConvertParams::builder("asset_example".to_string())
2204                .build()
2205                .unwrap();
2206
2207            match client.dust_convert(params).await {
2208                Ok(_) => panic!("Expected an error"),
2209                Err(err) => {
2210                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2211                }
2212            }
2213        });
2214    }
2215
2216    #[test]
2217    fn dust_convertible_assets_required_params_success() {
2218        TOKIO_SHARED_RT.block_on(async {
2219            let client = MockAssetApiClient { force_error: false };
2220
2221            let params = DustConvertibleAssetsParams::builder("target_asset_example".to_string(),).build().unwrap();
2222
2223            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"},{"asset":"BNB","assetFullName":"BNB","amountFree":"0.00082768","exchange":"0.01506378","toQuotaAssetAmount":"0.7531888","toTargetAssetAmount":"0.7531888","toTargetAssetOffExchange":"0.73812502"}]}"#).unwrap();
2224            let expected_response : models::DustConvertibleAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertibleAssetsResponse");
2225
2226            let resp = client.dust_convertible_assets(params).await.expect("Expected a response");
2227            let data_future = resp.data();
2228            let actual_response = data_future.await.unwrap();
2229            assert_eq!(actual_response, expected_response);
2230        });
2231    }
2232
2233    #[test]
2234    fn dust_convertible_assets_optional_params_success() {
2235        TOKIO_SHARED_RT.block_on(async {
2236            let client = MockAssetApiClient { force_error: false };
2237
2238            let params = DustConvertibleAssetsParams::builder("target_asset_example".to_string(),).account_type("SPOT".to_string()).dust_quota_asset_to_target_asset_price(dec!(1.0)).build().unwrap();
2239
2240            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"},{"asset":"BNB","assetFullName":"BNB","amountFree":"0.00082768","exchange":"0.01506378","toQuotaAssetAmount":"0.7531888","toTargetAssetAmount":"0.7531888","toTargetAssetOffExchange":"0.73812502"}]}"#).unwrap();
2241            let expected_response : models::DustConvertibleAssetsResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustConvertibleAssetsResponse");
2242
2243            let resp = client.dust_convertible_assets(params).await.expect("Expected a response");
2244            let data_future = resp.data();
2245            let actual_response = data_future.await.unwrap();
2246            assert_eq!(actual_response, expected_response);
2247        });
2248    }
2249
2250    #[test]
2251    fn dust_convertible_assets_response_error() {
2252        TOKIO_SHARED_RT.block_on(async {
2253            let client = MockAssetApiClient { force_error: true };
2254
2255            let params = DustConvertibleAssetsParams::builder("target_asset_example".to_string())
2256                .build()
2257                .unwrap();
2258
2259            match client.dust_convertible_assets(params).await {
2260                Ok(_) => panic!("Expected an error"),
2261                Err(err) => {
2262                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2263                }
2264            }
2265        });
2266    }
2267
2268    #[test]
2269    fn dust_transfer_required_params_success() {
2270        TOKIO_SHARED_RT.block_on(async {
2271            let client = MockAssetApiClient { force_error: false };
2272
2273            let params = DustTransferParams::builder("asset_example".to_string(),).build().unwrap();
2274
2275            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"},{"amount":"0.09000000","fromAsset":"LTC","operateTime":1563368549404,"serviceChargeAmount":"0.01548000","tranId":2970932918,"transferedAmount":"0.77400000"},{"amount":"248.61878453","fromAsset":"TRX","operateTime":1563368549489,"serviceChargeAmount":"0.00054542","tranId":2970932918,"transferedAmount":"0.02727099"}]}"#).unwrap();
2276            let expected_response : models::DustTransferResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustTransferResponse");
2277
2278            let resp = client.dust_transfer(params).await.expect("Expected a response");
2279            let data_future = resp.data();
2280            let actual_response = data_future.await.unwrap();
2281            assert_eq!(actual_response, expected_response);
2282        });
2283    }
2284
2285    #[test]
2286    fn dust_transfer_optional_params_success() {
2287        TOKIO_SHARED_RT.block_on(async {
2288            let client = MockAssetApiClient { force_error: false };
2289
2290            let params = DustTransferParams::builder("asset_example".to_string(),).account_type("SPOT".to_string()).recv_window(5000).build().unwrap();
2291
2292            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"},{"amount":"0.09000000","fromAsset":"LTC","operateTime":1563368549404,"serviceChargeAmount":"0.01548000","tranId":2970932918,"transferedAmount":"0.77400000"},{"amount":"248.61878453","fromAsset":"TRX","operateTime":1563368549489,"serviceChargeAmount":"0.00054542","tranId":2970932918,"transferedAmount":"0.02727099"}]}"#).unwrap();
2293            let expected_response : models::DustTransferResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustTransferResponse");
2294
2295            let resp = client.dust_transfer(params).await.expect("Expected a response");
2296            let data_future = resp.data();
2297            let actual_response = data_future.await.unwrap();
2298            assert_eq!(actual_response, expected_response);
2299        });
2300    }
2301
2302    #[test]
2303    fn dust_transfer_response_error() {
2304        TOKIO_SHARED_RT.block_on(async {
2305            let client = MockAssetApiClient { force_error: true };
2306
2307            let params = DustTransferParams::builder("asset_example".to_string())
2308                .build()
2309                .unwrap();
2310
2311            match client.dust_transfer(params).await {
2312                Ok(_) => panic!("Expected an error"),
2313                Err(err) => {
2314                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2315                }
2316            }
2317        });
2318    }
2319
2320    #[test]
2321    fn dustlog_required_params_success() {
2322        TOKIO_SHARED_RT.block_on(async {
2323            let client = MockAssetApiClient { force_error: false };
2324
2325            let params = DustlogParams::builder().build().unwrap();
2326
2327            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"},{"transId":4359321,"serviceChargeAmount":"0.00001799","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.00088156","fromAsset":"ETH"}]},{"operateTime":1616203180000,"totalTransferedAmount":"0.00058795","totalServiceChargeAmount":"0.000012","transId":4357015,"userAssetDribbletDetails":[{"transId":4357015,"serviceChargeAmount":"0.00001","amount":"0.001","operateTime":1616203180000,"transferedAmount":"0.00049","fromAsset":"USDT"},{"transId":4357015,"serviceChargeAmount":"0.000002","amount":"0.0001","operateTime":1616203180000,"transferedAmount":"0.00009795","fromAsset":"ETH"}]}]}"#).unwrap();
2328            let expected_response : models::DustlogResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustlogResponse");
2329
2330            let resp = client.dustlog(params).await.expect("Expected a response");
2331            let data_future = resp.data();
2332            let actual_response = data_future.await.unwrap();
2333            assert_eq!(actual_response, expected_response);
2334        });
2335    }
2336
2337    #[test]
2338    fn dustlog_optional_params_success() {
2339        TOKIO_SHARED_RT.block_on(async {
2340            let client = MockAssetApiClient { force_error: false };
2341
2342            let params = DustlogParams::builder().account_type("SPOT".to_string()).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();
2343
2344            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"},{"transId":4359321,"serviceChargeAmount":"0.00001799","amount":"0.0009","operateTime":1615985535000,"transferedAmount":"0.00088156","fromAsset":"ETH"}]},{"operateTime":1616203180000,"totalTransferedAmount":"0.00058795","totalServiceChargeAmount":"0.000012","transId":4357015,"userAssetDribbletDetails":[{"transId":4357015,"serviceChargeAmount":"0.00001","amount":"0.001","operateTime":1616203180000,"transferedAmount":"0.00049","fromAsset":"USDT"},{"transId":4357015,"serviceChargeAmount":"0.000002","amount":"0.0001","operateTime":1616203180000,"transferedAmount":"0.00009795","fromAsset":"ETH"}]}]}"#).unwrap();
2345            let expected_response : models::DustlogResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DustlogResponse");
2346
2347            let resp = client.dustlog(params).await.expect("Expected a response");
2348            let data_future = resp.data();
2349            let actual_response = data_future.await.unwrap();
2350            assert_eq!(actual_response, expected_response);
2351        });
2352    }
2353
2354    #[test]
2355    fn dustlog_response_error() {
2356        TOKIO_SHARED_RT.block_on(async {
2357            let client = MockAssetApiClient { force_error: true };
2358
2359            let params = DustlogParams::builder().build().unwrap();
2360
2361            match client.dustlog(params).await {
2362                Ok(_) => panic!("Expected an error"),
2363                Err(err) => {
2364                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2365                }
2366            }
2367        });
2368    }
2369
2370    #[test]
2371    fn funding_wallet_required_params_success() {
2372        TOKIO_SHARED_RT.block_on(async {
2373            let client = MockAssetApiClient { force_error: false };
2374
2375            let params = FundingWalletParams::builder().build().unwrap();
2376
2377            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap();
2378            let expected_response : Vec<models::FundingWalletResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FundingWalletResponseInner>");
2379
2380            let resp = client.funding_wallet(params).await.expect("Expected a response");
2381            let data_future = resp.data();
2382            let actual_response = data_future.await.unwrap();
2383            assert_eq!(actual_response, expected_response);
2384        });
2385    }
2386
2387    #[test]
2388    fn funding_wallet_optional_params_success() {
2389        TOKIO_SHARED_RT.block_on(async {
2390            let client = MockAssetApiClient { force_error: false };
2391
2392            let params = FundingWalletParams::builder().asset("asset_example".to_string()).need_btc_valuation("need_btc_valuation_example".to_string()).recv_window(5000).build().unwrap();
2393
2394            let resp_json: Value = serde_json::from_str(r#"[{"asset":"USDT","free":"1","locked":"0","freeze":"0","withdrawing":"0","btcValuation":"0.00000091"}]"#).unwrap();
2395            let expected_response : Vec<models::FundingWalletResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FundingWalletResponseInner>");
2396
2397            let resp = client.funding_wallet(params).await.expect("Expected a response");
2398            let data_future = resp.data();
2399            let actual_response = data_future.await.unwrap();
2400            assert_eq!(actual_response, expected_response);
2401        });
2402    }
2403
2404    #[test]
2405    fn funding_wallet_response_error() {
2406        TOKIO_SHARED_RT.block_on(async {
2407            let client = MockAssetApiClient { force_error: true };
2408
2409            let params = FundingWalletParams::builder().build().unwrap();
2410
2411            match client.funding_wallet(params).await {
2412                Ok(_) => panic!("Expected an error"),
2413                Err(err) => {
2414                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2415                }
2416            }
2417        });
2418    }
2419
2420    #[test]
2421    fn get_assets_that_can_be_converted_into_bnb_required_params_success() {
2422        TOKIO_SHARED_RT.block_on(async {
2423            let client = MockAssetApiClient { force_error: false };
2424
2425            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder().build().unwrap();
2426
2427            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();
2428            let expected_response : models::GetAssetsThatCanBeConvertedIntoBnbResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
2429
2430            let resp = client.get_assets_that_can_be_converted_into_bnb(params).await.expect("Expected a response");
2431            let data_future = resp.data();
2432            let actual_response = data_future.await.unwrap();
2433            assert_eq!(actual_response, expected_response);
2434        });
2435    }
2436
2437    #[test]
2438    fn get_assets_that_can_be_converted_into_bnb_optional_params_success() {
2439        TOKIO_SHARED_RT.block_on(async {
2440            let client = MockAssetApiClient { force_error: false };
2441
2442            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder().account_type("SPOT".to_string()).recv_window(5000).build().unwrap();
2443
2444            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();
2445            let expected_response : models::GetAssetsThatCanBeConvertedIntoBnbResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetAssetsThatCanBeConvertedIntoBnbResponse");
2446
2447            let resp = client.get_assets_that_can_be_converted_into_bnb(params).await.expect("Expected a response");
2448            let data_future = resp.data();
2449            let actual_response = data_future.await.unwrap();
2450            assert_eq!(actual_response, expected_response);
2451        });
2452    }
2453
2454    #[test]
2455    fn get_assets_that_can_be_converted_into_bnb_response_error() {
2456        TOKIO_SHARED_RT.block_on(async {
2457            let client = MockAssetApiClient { force_error: true };
2458
2459            let params = GetAssetsThatCanBeConvertedIntoBnbParams::builder()
2460                .build()
2461                .unwrap();
2462
2463            match client
2464                .get_assets_that_can_be_converted_into_bnb(params)
2465                .await
2466            {
2467                Ok(_) => panic!("Expected an error"),
2468                Err(err) => {
2469                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2470                }
2471            }
2472        });
2473    }
2474
2475    #[test]
2476    fn get_cloud_mining_payment_and_refund_history_required_params_success() {
2477        TOKIO_SHARED_RT.block_on(async {
2478            let client = MockAssetApiClient { force_error: false };
2479
2480            let params = GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670,1641782889000,).build().unwrap();
2481
2482            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"},{"createTime":1666776366000,"tranId":119991507468,"type":249,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666764505000,"tranId":119977966327,"type":248,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666758189000,"tranId":119973601721,"type":248,"asset":"USDT","amount":"0.018","status":"S"},{"createTime":1666757278000,"tranId":119973028551,"type":248,"asset":"USDT","amount":"0.018","status":"S"}]}"#).unwrap();
2483            let expected_response : models::GetCloudMiningPaymentAndRefundHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse");
2484
2485            let resp = client.get_cloud_mining_payment_and_refund_history(params).await.expect("Expected a response");
2486            let data_future = resp.data();
2487            let actual_response = data_future.await.unwrap();
2488            assert_eq!(actual_response, expected_response);
2489        });
2490    }
2491
2492    #[test]
2493    fn get_cloud_mining_payment_and_refund_history_optional_params_success() {
2494        TOKIO_SHARED_RT.block_on(async {
2495            let client = MockAssetApiClient { force_error: false };
2496
2497            let params = GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670,1641782889000,).tran_id(1).client_tran_id("1".to_string()).asset("asset_example".to_string()).current(1).size(10).build().unwrap();
2498
2499            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"},{"createTime":1666776366000,"tranId":119991507468,"type":249,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666764505000,"tranId":119977966327,"type":248,"asset":"USDT","amount":"0.027","status":"S"},{"createTime":1666758189000,"tranId":119973601721,"type":248,"asset":"USDT","amount":"0.018","status":"S"},{"createTime":1666757278000,"tranId":119973028551,"type":248,"asset":"USDT","amount":"0.018","status":"S"}]}"#).unwrap();
2500            let expected_response : models::GetCloudMiningPaymentAndRefundHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetCloudMiningPaymentAndRefundHistoryResponse");
2501
2502            let resp = client.get_cloud_mining_payment_and_refund_history(params).await.expect("Expected a response");
2503            let data_future = resp.data();
2504            let actual_response = data_future.await.unwrap();
2505            assert_eq!(actual_response, expected_response);
2506        });
2507    }
2508
2509    #[test]
2510    fn get_cloud_mining_payment_and_refund_history_response_error() {
2511        TOKIO_SHARED_RT.block_on(async {
2512            let client = MockAssetApiClient { force_error: true };
2513
2514            let params =
2515                GetCloudMiningPaymentAndRefundHistoryParams::builder(1623319461670, 1641782889000)
2516                    .build()
2517                    .unwrap();
2518
2519            match client
2520                .get_cloud_mining_payment_and_refund_history(params)
2521                .await
2522            {
2523                Ok(_) => panic!("Expected an error"),
2524                Err(err) => {
2525                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2526                }
2527            }
2528        });
2529    }
2530
2531    #[test]
2532    fn get_open_symbol_list_required_params_success() {
2533        TOKIO_SHARED_RT.block_on(async {
2534            let client = MockAssetApiClient { force_error: false };
2535
2536
2537            let resp_json: Value = serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC","BNBETH"]},{"openTime":1686222232000,"symbols":["BTCUSDT"]}]"#).unwrap();
2538            let expected_response : Vec<models::GetOpenSymbolListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
2539
2540            let resp = client.get_open_symbol_list().await.expect("Expected a response");
2541            let data_future = resp.data();
2542            let actual_response = data_future.await.unwrap();
2543            assert_eq!(actual_response, expected_response);
2544        });
2545    }
2546
2547    #[test]
2548    fn get_open_symbol_list_optional_params_success() {
2549        TOKIO_SHARED_RT.block_on(async {
2550            let client = MockAssetApiClient { force_error: false };
2551
2552
2553            let resp_json: Value = serde_json::from_str(r#"[{"openTime":1686161202000,"symbols":["BNBBTC","BNBETH"]},{"openTime":1686222232000,"symbols":["BTCUSDT"]}]"#).unwrap();
2554            let expected_response : Vec<models::GetOpenSymbolListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetOpenSymbolListResponseInner>");
2555
2556            let resp = client.get_open_symbol_list().await.expect("Expected a response");
2557            let data_future = resp.data();
2558            let actual_response = data_future.await.unwrap();
2559            assert_eq!(actual_response, expected_response);
2560        });
2561    }
2562
2563    #[test]
2564    fn get_open_symbol_list_response_error() {
2565        TOKIO_SHARED_RT.block_on(async {
2566            let client = MockAssetApiClient { force_error: true };
2567
2568            match client.get_open_symbol_list().await {
2569                Ok(_) => panic!("Expected an error"),
2570                Err(err) => {
2571                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2572                }
2573            }
2574        });
2575    }
2576
2577    #[test]
2578    fn query_user_delegation_history_required_params_success() {
2579        TOKIO_SHARED_RT.block_on(async {
2580            let client = MockAssetApiClient { force_error: false };
2581
2582            let params = QueryUserDelegationHistoryParams::builder("email_example".to_string(),1623319461670,1641782889000,).build().unwrap();
2583
2584            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000},{"clientTranId":"293915892281413632","transferType":"Delegate","asset":"ETH","amount":"1","time":1695205396000}]}"#).unwrap();
2585            let expected_response : models::QueryUserDelegationHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserDelegationHistoryResponse");
2586
2587            let resp = client.query_user_delegation_history(params).await.expect("Expected a response");
2588            let data_future = resp.data();
2589            let actual_response = data_future.await.unwrap();
2590            assert_eq!(actual_response, expected_response);
2591        });
2592    }
2593
2594    #[test]
2595    fn query_user_delegation_history_optional_params_success() {
2596        TOKIO_SHARED_RT.block_on(async {
2597            let client = MockAssetApiClient { force_error: false };
2598
2599            let params = QueryUserDelegationHistoryParams::builder("email_example".to_string(),1623319461670,1641782889000,).r#type("r#type_example".to_string()).asset("asset_example".to_string()).current(1).size(10).recv_window(5000).build().unwrap();
2600
2601            let resp_json: Value = serde_json::from_str(r#"{"total":3316,"rows":[{"clientTranId":"293915932290879488","transferType":"Undelegate","asset":"ETH","amount":"1","time":1695205406000},{"clientTranId":"293915892281413632","transferType":"Delegate","asset":"ETH","amount":"1","time":1695205396000}]}"#).unwrap();
2602            let expected_response : models::QueryUserDelegationHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserDelegationHistoryResponse");
2603
2604            let resp = client.query_user_delegation_history(params).await.expect("Expected a response");
2605            let data_future = resp.data();
2606            let actual_response = data_future.await.unwrap();
2607            assert_eq!(actual_response, expected_response);
2608        });
2609    }
2610
2611    #[test]
2612    fn query_user_delegation_history_response_error() {
2613        TOKIO_SHARED_RT.block_on(async {
2614            let client = MockAssetApiClient { force_error: true };
2615
2616            let params = QueryUserDelegationHistoryParams::builder(
2617                "email_example".to_string(),
2618                1623319461670,
2619                1641782889000,
2620            )
2621            .build()
2622            .unwrap();
2623
2624            match client.query_user_delegation_history(params).await {
2625                Ok(_) => panic!("Expected an error"),
2626                Err(err) => {
2627                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2628                }
2629            }
2630        });
2631    }
2632
2633    #[test]
2634    fn query_user_universal_transfer_history_required_params_success() {
2635        TOKIO_SHARED_RT.block_on(async {
2636            let client = MockAssetApiClient { force_error: false };
2637
2638            let params = QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string(),).build().unwrap();
2639
2640            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},{"asset":"USDT","amount":"2","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11366865406,"timestamp":1544433328000}]}"#).unwrap();
2641            let expected_response : models::QueryUserUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
2642
2643            let resp = client.query_user_universal_transfer_history(params).await.expect("Expected a response");
2644            let data_future = resp.data();
2645            let actual_response = data_future.await.unwrap();
2646            assert_eq!(actual_response, expected_response);
2647        });
2648    }
2649
2650    #[test]
2651    fn query_user_universal_transfer_history_optional_params_success() {
2652        TOKIO_SHARED_RT.block_on(async {
2653            let client = MockAssetApiClient { force_error: false };
2654
2655            let params = QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string(),).start_time(1623319461670).end_time(1641782889000).current(1).size(10).from_symbol("from_symbol_example".to_string()).to_symbol("to_symbol_example".to_string()).recv_window(5000).build().unwrap();
2656
2657            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},{"asset":"USDT","amount":"2","type":"MAIN_UMFUTURE","status":"CONFIRMED","tranId":11366865406,"timestamp":1544433328000}]}"#).unwrap();
2658            let expected_response : models::QueryUserUniversalTransferHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::QueryUserUniversalTransferHistoryResponse");
2659
2660            let resp = client.query_user_universal_transfer_history(params).await.expect("Expected a response");
2661            let data_future = resp.data();
2662            let actual_response = data_future.await.unwrap();
2663            assert_eq!(actual_response, expected_response);
2664        });
2665    }
2666
2667    #[test]
2668    fn query_user_universal_transfer_history_response_error() {
2669        TOKIO_SHARED_RT.block_on(async {
2670            let client = MockAssetApiClient { force_error: true };
2671
2672            let params =
2673                QueryUserUniversalTransferHistoryParams::builder("r#type_example".to_string())
2674                    .build()
2675                    .unwrap();
2676
2677            match client.query_user_universal_transfer_history(params).await {
2678                Ok(_) => panic!("Expected an error"),
2679                Err(err) => {
2680                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2681                }
2682            }
2683        });
2684    }
2685
2686    #[test]
2687    fn query_user_wallet_balance_required_params_success() {
2688        TOKIO_SHARED_RT.block_on(async {
2689            let client = MockAssetApiClient { force_error: false };
2690
2691            let params = QueryUserWalletBalanceParams::builder().build().unwrap();
2692
2693            let resp_json: Value = serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"},{"activate":true,"balance":"0","walletName":"Funding"},{"activate":true,"balance":"0","walletName":"Cross Margin"},{"activate":true,"balance":"0","walletName":"Isolated Margin"},{"activate":true,"balance":"0.71842752","walletName":"USDⓈ-M Futures"},{"activate":true,"balance":"0","walletName":"COIN-M Futures"},{"activate":true,"balance":"0","walletName":"Earn"},{"activate":false,"balance":"0","walletName":"Options"},{"activate":true,"balance":"0","walletName":"Trading Bots"},{"activate":true,"balance":"0","walletName":"Copy Trading"}]"#).unwrap();
2694            let expected_response : Vec<models::QueryUserWalletBalanceResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
2695
2696            let resp = client.query_user_wallet_balance(params).await.expect("Expected a response");
2697            let data_future = resp.data();
2698            let actual_response = data_future.await.unwrap();
2699            assert_eq!(actual_response, expected_response);
2700        });
2701    }
2702
2703    #[test]
2704    fn query_user_wallet_balance_optional_params_success() {
2705        TOKIO_SHARED_RT.block_on(async {
2706            let client = MockAssetApiClient { force_error: false };
2707
2708            let params = QueryUserWalletBalanceParams::builder().quote_asset("BTC".to_string()).recv_window(5000).build().unwrap();
2709
2710            let resp_json: Value = serde_json::from_str(r#"[{"activate":true,"balance":"0","walletName":"Spot"},{"activate":true,"balance":"0","walletName":"Funding"},{"activate":true,"balance":"0","walletName":"Cross Margin"},{"activate":true,"balance":"0","walletName":"Isolated Margin"},{"activate":true,"balance":"0.71842752","walletName":"USDⓈ-M Futures"},{"activate":true,"balance":"0","walletName":"COIN-M Futures"},{"activate":true,"balance":"0","walletName":"Earn"},{"activate":false,"balance":"0","walletName":"Options"},{"activate":true,"balance":"0","walletName":"Trading Bots"},{"activate":true,"balance":"0","walletName":"Copy Trading"}]"#).unwrap();
2711            let expected_response : Vec<models::QueryUserWalletBalanceResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::QueryUserWalletBalanceResponseInner>");
2712
2713            let resp = client.query_user_wallet_balance(params).await.expect("Expected a response");
2714            let data_future = resp.data();
2715            let actual_response = data_future.await.unwrap();
2716            assert_eq!(actual_response, expected_response);
2717        });
2718    }
2719
2720    #[test]
2721    fn query_user_wallet_balance_response_error() {
2722        TOKIO_SHARED_RT.block_on(async {
2723            let client = MockAssetApiClient { force_error: true };
2724
2725            let params = QueryUserWalletBalanceParams::builder().build().unwrap();
2726
2727            match client.query_user_wallet_balance(params).await {
2728                Ok(_) => panic!("Expected an error"),
2729                Err(err) => {
2730                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2731                }
2732            }
2733        });
2734    }
2735
2736    #[test]
2737    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_required_params_success() {
2738        TOKIO_SHARED_RT.block_on(async {
2739            let client = MockAssetApiClient { force_error: false };
2740
2741            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
2742                .build()
2743                .unwrap();
2744
2745            let resp_json: Value =
2746                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#).unwrap();
2747            let expected_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
2748                serde_json::from_value(resp_json.clone()).expect(
2749                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
2750                );
2751
2752            let resp = client
2753                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
2754                .await
2755                .expect("Expected a response");
2756            let data_future = resp.data();
2757            let actual_response = data_future.await.unwrap();
2758            assert_eq!(actual_response, expected_response);
2759        });
2760    }
2761
2762    #[test]
2763    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_optional_params_success() {
2764        TOKIO_SHARED_RT.block_on(async {
2765            let client = MockAssetApiClient { force_error: false };
2766
2767            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
2768                .spot_bnb_burn("spot_bnb_burn_example".to_string())
2769                .interest_bnb_burn("interest_bnb_burn_example".to_string())
2770                .recv_window(5000)
2771                .build()
2772                .unwrap();
2773
2774            let resp_json: Value =
2775                serde_json::from_str(r#"{"spotBNBBurn":true,"interestBNBBurn":false}"#).unwrap();
2776            let expected_response: models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse =
2777                serde_json::from_value(resp_json.clone()).expect(
2778                    "should parse into models::ToggleBnbBurnOnSpotTradeAndMarginInterestResponse",
2779                );
2780
2781            let resp = client
2782                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
2783                .await
2784                .expect("Expected a response");
2785            let data_future = resp.data();
2786            let actual_response = data_future.await.unwrap();
2787            assert_eq!(actual_response, expected_response);
2788        });
2789    }
2790
2791    #[test]
2792    fn toggle_bnb_burn_on_spot_trade_and_margin_interest_response_error() {
2793        TOKIO_SHARED_RT.block_on(async {
2794            let client = MockAssetApiClient { force_error: true };
2795
2796            let params = ToggleBnbBurnOnSpotTradeAndMarginInterestParams::builder()
2797                .build()
2798                .unwrap();
2799
2800            match client
2801                .toggle_bnb_burn_on_spot_trade_and_margin_interest(params)
2802                .await
2803            {
2804                Ok(_) => panic!("Expected an error"),
2805                Err(err) => {
2806                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2807                }
2808            }
2809        });
2810    }
2811
2812    #[test]
2813    fn trade_fee_required_params_success() {
2814        TOKIO_SHARED_RT.block_on(async {
2815            let client = MockAssetApiClient { force_error: false };
2816
2817            let params = TradeFeeParams::builder().build().unwrap();
2818
2819            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"},{"symbol":"BNBBTC","makerCommission":"0.001","takerCommission":"0.001"}]"#).unwrap();
2820            let expected_response : Vec<models::TradeFeeResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TradeFeeResponseInner>");
2821
2822            let resp = client.trade_fee(params).await.expect("Expected a response");
2823            let data_future = resp.data();
2824            let actual_response = data_future.await.unwrap();
2825            assert_eq!(actual_response, expected_response);
2826        });
2827    }
2828
2829    #[test]
2830    fn trade_fee_optional_params_success() {
2831        TOKIO_SHARED_RT.block_on(async {
2832            let client = MockAssetApiClient { force_error: false };
2833
2834            let params = TradeFeeParams::builder().symbol("symbol_example".to_string()).recv_window(5000).build().unwrap();
2835
2836            let resp_json: Value = serde_json::from_str(r#"[{"symbol":"ADABNB","makerCommission":"0.001","takerCommission":"0.001"},{"symbol":"BNBBTC","makerCommission":"0.001","takerCommission":"0.001"}]"#).unwrap();
2837            let expected_response : Vec<models::TradeFeeResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::TradeFeeResponseInner>");
2838
2839            let resp = client.trade_fee(params).await.expect("Expected a response");
2840            let data_future = resp.data();
2841            let actual_response = data_future.await.unwrap();
2842            assert_eq!(actual_response, expected_response);
2843        });
2844    }
2845
2846    #[test]
2847    fn trade_fee_response_error() {
2848        TOKIO_SHARED_RT.block_on(async {
2849            let client = MockAssetApiClient { force_error: true };
2850
2851            let params = TradeFeeParams::builder().build().unwrap();
2852
2853            match client.trade_fee(params).await {
2854                Ok(_) => panic!("Expected an error"),
2855                Err(err) => {
2856                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2857                }
2858            }
2859        });
2860    }
2861
2862    #[test]
2863    fn user_asset_required_params_success() {
2864        TOKIO_SHARED_RT.block_on(async {
2865            let client = MockAssetApiClient { force_error: false };
2866
2867            let params = UserAssetParams::builder().build().unwrap();
2868
2869            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BCH","free":"0.9","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BNB","free":"887.47061626","locked":"0","freeze":"10.52","withdrawing":"0.1","ipoable":"0","btcValuation":"0"},{"asset":"BUSD","free":"9999.7","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"SHIB","free":"532.32","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"USDT","free":"50300000001.44911105","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"WRZ","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap();
2870            let expected_response : Vec<models::UserAssetResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::UserAssetResponseInner>");
2871
2872            let resp = client.user_asset(params).await.expect("Expected a response");
2873            let data_future = resp.data();
2874            let actual_response = data_future.await.unwrap();
2875            assert_eq!(actual_response, expected_response);
2876        });
2877    }
2878
2879    #[test]
2880    fn user_asset_optional_params_success() {
2881        TOKIO_SHARED_RT.block_on(async {
2882            let client = MockAssetApiClient { force_error: false };
2883
2884            let params = UserAssetParams::builder().asset("asset_example".to_string()).need_btc_valuation(true).recv_window(5000).build().unwrap();
2885
2886            let resp_json: Value = serde_json::from_str(r#"[{"asset":"AVAX","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BCH","free":"0.9","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"BNB","free":"887.47061626","locked":"0","freeze":"10.52","withdrawing":"0.1","ipoable":"0","btcValuation":"0"},{"asset":"BUSD","free":"9999.7","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"SHIB","free":"532.32","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"USDT","free":"50300000001.44911105","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"},{"asset":"WRZ","free":"1","locked":"0","freeze":"0","withdrawing":"0","ipoable":"0","btcValuation":"0"}]"#).unwrap();
2887            let expected_response : Vec<models::UserAssetResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::UserAssetResponseInner>");
2888
2889            let resp = client.user_asset(params).await.expect("Expected a response");
2890            let data_future = resp.data();
2891            let actual_response = data_future.await.unwrap();
2892            assert_eq!(actual_response, expected_response);
2893        });
2894    }
2895
2896    #[test]
2897    fn user_asset_response_error() {
2898        TOKIO_SHARED_RT.block_on(async {
2899            let client = MockAssetApiClient { force_error: true };
2900
2901            let params = UserAssetParams::builder().build().unwrap();
2902
2903            match client.user_asset(params).await {
2904                Ok(_) => panic!("Expected an error"),
2905                Err(err) => {
2906                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2907                }
2908            }
2909        });
2910    }
2911
2912    #[test]
2913    fn user_universal_transfer_required_params_success() {
2914        TOKIO_SHARED_RT.block_on(async {
2915            let client = MockAssetApiClient { force_error: false };
2916
2917            let params = UserUniversalTransferParams::builder(
2918                "r#type_example".to_string(),
2919                "asset_example".to_string(),
2920                dec!(1.0),
2921            )
2922            .build()
2923            .unwrap();
2924
2925            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#).unwrap();
2926            let expected_response: models::UserUniversalTransferResponse =
2927                serde_json::from_value(resp_json.clone())
2928                    .expect("should parse into models::UserUniversalTransferResponse");
2929
2930            let resp = client
2931                .user_universal_transfer(params)
2932                .await
2933                .expect("Expected a response");
2934            let data_future = resp.data();
2935            let actual_response = data_future.await.unwrap();
2936            assert_eq!(actual_response, expected_response);
2937        });
2938    }
2939
2940    #[test]
2941    fn user_universal_transfer_optional_params_success() {
2942        TOKIO_SHARED_RT.block_on(async {
2943            let client = MockAssetApiClient { force_error: false };
2944
2945            let params = UserUniversalTransferParams::builder(
2946                "r#type_example".to_string(),
2947                "asset_example".to_string(),
2948                dec!(1.0),
2949            )
2950            .from_symbol("from_symbol_example".to_string())
2951            .to_symbol("to_symbol_example".to_string())
2952            .recv_window(5000)
2953            .build()
2954            .unwrap();
2955
2956            let resp_json: Value = serde_json::from_str(r#"{"tranId":13526853623}"#).unwrap();
2957            let expected_response: models::UserUniversalTransferResponse =
2958                serde_json::from_value(resp_json.clone())
2959                    .expect("should parse into models::UserUniversalTransferResponse");
2960
2961            let resp = client
2962                .user_universal_transfer(params)
2963                .await
2964                .expect("Expected a response");
2965            let data_future = resp.data();
2966            let actual_response = data_future.await.unwrap();
2967            assert_eq!(actual_response, expected_response);
2968        });
2969    }
2970
2971    #[test]
2972    fn user_universal_transfer_response_error() {
2973        TOKIO_SHARED_RT.block_on(async {
2974            let client = MockAssetApiClient { force_error: true };
2975
2976            let params = UserUniversalTransferParams::builder(
2977                "r#type_example".to_string(),
2978                "asset_example".to_string(),
2979                dec!(1.0),
2980            )
2981            .build()
2982            .unwrap();
2983
2984            match client.user_universal_transfer(params).await {
2985                Ok(_) => panic!("Expected an error"),
2986                Err(err) => {
2987                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
2988                }
2989            }
2990        });
2991    }
2992}