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