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