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 CapitalApi: Send + Sync {
34 async fn all_coins_information(
35 &self,
36 params: AllCoinsInformationParams,
37 ) -> anyhow::Result<RestApiResponse<Vec<models::AllCoinsInformationResponseInner>>>;
38 async fn deposit_address(
39 &self,
40 params: DepositAddressParams,
41 ) -> anyhow::Result<RestApiResponse<models::DepositAddressResponse>>;
42 async fn deposit_history(
43 &self,
44 params: DepositHistoryParams,
45 ) -> anyhow::Result<RestApiResponse<Vec<models::DepositHistoryResponseInner>>>;
46 async fn fetch_deposit_address_list_with_network(
47 &self,
48 params: FetchDepositAddressListWithNetworkParams,
49 ) -> anyhow::Result<RestApiResponse<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>>;
50 async fn fetch_withdraw_address_list(
51 &self,
52 ) -> anyhow::Result<RestApiResponse<Vec<models::FetchWithdrawAddressListResponseInner>>>;
53 async fn fetch_withdraw_quota(
54 &self,
55 ) -> anyhow::Result<RestApiResponse<models::FetchWithdrawQuotaResponse>>;
56 async fn one_click_arrival_deposit_apply(
57 &self,
58 params: OneClickArrivalDepositApplyParams,
59 ) -> anyhow::Result<RestApiResponse<models::OneClickArrivalDepositApplyResponse>>;
60 async fn withdraw(
61 &self,
62 params: WithdrawParams,
63 ) -> anyhow::Result<RestApiResponse<models::WithdrawResponse>>;
64 async fn withdraw_history(
65 &self,
66 params: WithdrawHistoryParams,
67 ) -> anyhow::Result<RestApiResponse<Vec<models::WithdrawHistoryResponseInner>>>;
68}
69
70#[derive(Debug, Clone)]
71pub struct CapitalApiClient {
72 configuration: ConfigurationRestApi,
73}
74
75impl CapitalApiClient {
76 pub fn new(configuration: ConfigurationRestApi) -> Self {
77 Self { configuration }
78 }
79}
80
81#[derive(Clone, Debug, Builder, Default)]
86#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
87pub struct AllCoinsInformationParams {
88 #[builder(setter(into), default)]
93 pub recv_window: Option<i64>,
94}
95
96impl AllCoinsInformationParams {
97 #[must_use]
100 pub fn builder() -> AllCoinsInformationParamsBuilder {
101 AllCoinsInformationParamsBuilder::default()
102 }
103}
104#[derive(Clone, Debug, Builder)]
109#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
110pub struct DepositAddressParams {
111 #[builder(setter(into))]
116 pub coin: String,
117 #[builder(setter(into), default)]
122 pub network: Option<String>,
123 #[builder(setter(into), default)]
128 pub amount: Option<rust_decimal::Decimal>,
129 #[builder(setter(into), default)]
134 pub recv_window: Option<i64>,
135}
136
137impl DepositAddressParams {
138 #[must_use]
145 pub fn builder(coin: String) -> DepositAddressParamsBuilder {
146 DepositAddressParamsBuilder::default().coin(coin)
147 }
148}
149#[derive(Clone, Debug, Builder, Default)]
154#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
155pub struct DepositHistoryParams {
156 #[builder(setter(into), default)]
160 pub include_source: Option<bool>,
161 #[builder(setter(into), default)]
166 pub coin: Option<String>,
167 #[builder(setter(into), default)]
171 pub status: Option<i64>,
172 #[builder(setter(into), default)]
177 pub start_time: Option<i64>,
178 #[builder(setter(into), default)]
183 pub end_time: Option<i64>,
184 #[builder(setter(into), default)]
188 pub offset: Option<i64>,
189 #[builder(setter(into), default)]
193 pub limit: Option<i64>,
194 #[builder(setter(into), default)]
199 pub recv_window: Option<i64>,
200 #[builder(setter(into), default)]
205 pub tx_id: Option<String>,
206}
207
208impl DepositHistoryParams {
209 #[must_use]
212 pub fn builder() -> DepositHistoryParamsBuilder {
213 DepositHistoryParamsBuilder::default()
214 }
215}
216#[derive(Clone, Debug, Builder)]
221#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
222pub struct FetchDepositAddressListWithNetworkParams {
223 #[builder(setter(into))]
228 pub coin: String,
229 #[builder(setter(into), default)]
234 pub network: Option<String>,
235}
236
237impl FetchDepositAddressListWithNetworkParams {
238 #[must_use]
245 pub fn builder(coin: String) -> FetchDepositAddressListWithNetworkParamsBuilder {
246 FetchDepositAddressListWithNetworkParamsBuilder::default().coin(coin)
247 }
248}
249#[derive(Clone, Debug, Builder, Default)]
254#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
255pub struct OneClickArrivalDepositApplyParams {
256 #[builder(setter(into), default)]
260 pub deposit_id: Option<i64>,
261 #[builder(setter(into), default)]
266 pub tx_id: Option<String>,
267 #[builder(setter(into), default)]
271 pub sub_account_id: Option<i64>,
272 #[builder(setter(into), default)]
276 pub sub_user_id: Option<i64>,
277}
278
279impl OneClickArrivalDepositApplyParams {
280 #[must_use]
283 pub fn builder() -> OneClickArrivalDepositApplyParamsBuilder {
284 OneClickArrivalDepositApplyParamsBuilder::default()
285 }
286}
287#[derive(Clone, Debug, Builder)]
292#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
293pub struct WithdrawParams {
294 #[builder(setter(into))]
299 pub coin: String,
300 #[builder(setter(into))]
305 pub address: String,
306 #[builder(setter(into))]
311 pub amount: rust_decimal::Decimal,
312 #[builder(setter(into), default)]
316 pub withdraw_order_id: Option<String>,
317 #[builder(setter(into), default)]
322 pub network: Option<String>,
323 #[builder(setter(into), default)]
327 pub address_tag: Option<String>,
328 #[builder(setter(into), default)]
332 pub transaction_fee_flag: Option<bool>,
333 #[builder(setter(into), default)]
337 pub name: Option<String>,
338 #[builder(setter(into), default)]
342 pub wallet_type: Option<i64>,
343 #[builder(setter(into), default)]
348 pub recv_window: Option<i64>,
349}
350
351impl WithdrawParams {
352 #[must_use]
361 pub fn builder(
362 coin: String,
363 address: String,
364 amount: rust_decimal::Decimal,
365 ) -> WithdrawParamsBuilder {
366 WithdrawParamsBuilder::default()
367 .coin(coin)
368 .address(address)
369 .amount(amount)
370 }
371}
372#[derive(Clone, Debug, Builder, Default)]
377#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
378pub struct WithdrawHistoryParams {
379 #[builder(setter(into), default)]
384 pub coin: Option<String>,
385 #[builder(setter(into), default)]
389 pub withdraw_order_id: Option<String>,
390 #[builder(setter(into), default)]
394 pub status: Option<i64>,
395 #[builder(setter(into), default)]
399 pub offset: Option<i64>,
400 #[builder(setter(into), default)]
404 pub limit: Option<i64>,
405 #[builder(setter(into), default)]
409 pub id_list: Option<String>,
410 #[builder(setter(into), default)]
415 pub start_time: Option<i64>,
416 #[builder(setter(into), default)]
421 pub end_time: Option<i64>,
422 #[builder(setter(into), default)]
427 pub recv_window: Option<i64>,
428}
429
430impl WithdrawHistoryParams {
431 #[must_use]
434 pub fn builder() -> WithdrawHistoryParamsBuilder {
435 WithdrawHistoryParamsBuilder::default()
436 }
437}
438
439#[async_trait]
440impl CapitalApi for CapitalApiClient {
441 async fn all_coins_information(
442 &self,
443 params: AllCoinsInformationParams,
444 ) -> anyhow::Result<RestApiResponse<Vec<models::AllCoinsInformationResponseInner>>> {
445 let AllCoinsInformationParams { recv_window } = params;
446
447 let mut query_params = BTreeMap::new();
448 let body_params = BTreeMap::new();
449
450 if let Some(rw) = recv_window {
451 query_params.insert("recvWindow".to_string(), json!(rw));
452 }
453
454 send_request::<Vec<models::AllCoinsInformationResponseInner>>(
455 &self.configuration,
456 "/sapi/v1/capital/config/getall",
457 reqwest::Method::GET,
458 query_params,
459 body_params,
460 if HAS_TIME_UNIT {
461 self.configuration.time_unit
462 } else {
463 None
464 },
465 true,
466 )
467 .await
468 }
469
470 async fn deposit_address(
471 &self,
472 params: DepositAddressParams,
473 ) -> anyhow::Result<RestApiResponse<models::DepositAddressResponse>> {
474 let DepositAddressParams {
475 coin,
476 network,
477 amount,
478 recv_window,
479 } = params;
480
481 let mut query_params = BTreeMap::new();
482 let body_params = BTreeMap::new();
483
484 query_params.insert("coin".to_string(), json!(coin));
485
486 if let Some(rw) = network {
487 query_params.insert("network".to_string(), json!(rw));
488 }
489
490 if let Some(rw) = amount {
491 query_params.insert("amount".to_string(), json!(rw));
492 }
493
494 if let Some(rw) = recv_window {
495 query_params.insert("recvWindow".to_string(), json!(rw));
496 }
497
498 send_request::<models::DepositAddressResponse>(
499 &self.configuration,
500 "/sapi/v1/capital/deposit/address",
501 reqwest::Method::GET,
502 query_params,
503 body_params,
504 if HAS_TIME_UNIT {
505 self.configuration.time_unit
506 } else {
507 None
508 },
509 true,
510 )
511 .await
512 }
513
514 async fn deposit_history(
515 &self,
516 params: DepositHistoryParams,
517 ) -> anyhow::Result<RestApiResponse<Vec<models::DepositHistoryResponseInner>>> {
518 let DepositHistoryParams {
519 include_source,
520 coin,
521 status,
522 start_time,
523 end_time,
524 offset,
525 limit,
526 recv_window,
527 tx_id,
528 } = params;
529
530 let mut query_params = BTreeMap::new();
531 let body_params = BTreeMap::new();
532
533 if let Some(rw) = include_source {
534 query_params.insert("includeSource".to_string(), json!(rw));
535 }
536
537 if let Some(rw) = coin {
538 query_params.insert("coin".to_string(), json!(rw));
539 }
540
541 if let Some(rw) = status {
542 query_params.insert("status".to_string(), json!(rw));
543 }
544
545 if let Some(rw) = start_time {
546 query_params.insert("startTime".to_string(), json!(rw));
547 }
548
549 if let Some(rw) = end_time {
550 query_params.insert("endTime".to_string(), json!(rw));
551 }
552
553 if let Some(rw) = offset {
554 query_params.insert("offset".to_string(), json!(rw));
555 }
556
557 if let Some(rw) = limit {
558 query_params.insert("limit".to_string(), json!(rw));
559 }
560
561 if let Some(rw) = recv_window {
562 query_params.insert("recvWindow".to_string(), json!(rw));
563 }
564
565 if let Some(rw) = tx_id {
566 query_params.insert("txId".to_string(), json!(rw));
567 }
568
569 send_request::<Vec<models::DepositHistoryResponseInner>>(
570 &self.configuration,
571 "/sapi/v1/capital/deposit/hisrec",
572 reqwest::Method::GET,
573 query_params,
574 body_params,
575 if HAS_TIME_UNIT {
576 self.configuration.time_unit
577 } else {
578 None
579 },
580 true,
581 )
582 .await
583 }
584
585 async fn fetch_deposit_address_list_with_network(
586 &self,
587 params: FetchDepositAddressListWithNetworkParams,
588 ) -> anyhow::Result<RestApiResponse<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>>
589 {
590 let FetchDepositAddressListWithNetworkParams { coin, network } = params;
591
592 let mut query_params = BTreeMap::new();
593 let body_params = BTreeMap::new();
594
595 query_params.insert("coin".to_string(), json!(coin));
596
597 if let Some(rw) = network {
598 query_params.insert("network".to_string(), json!(rw));
599 }
600
601 send_request::<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>(
602 &self.configuration,
603 "/sapi/v1/capital/deposit/address/list",
604 reqwest::Method::GET,
605 query_params,
606 body_params,
607 if HAS_TIME_UNIT {
608 self.configuration.time_unit
609 } else {
610 None
611 },
612 true,
613 )
614 .await
615 }
616
617 async fn fetch_withdraw_address_list(
618 &self,
619 ) -> anyhow::Result<RestApiResponse<Vec<models::FetchWithdrawAddressListResponseInner>>> {
620 let query_params = BTreeMap::new();
621 let body_params = BTreeMap::new();
622
623 send_request::<Vec<models::FetchWithdrawAddressListResponseInner>>(
624 &self.configuration,
625 "/sapi/v1/capital/withdraw/address/list",
626 reqwest::Method::GET,
627 query_params,
628 body_params,
629 if HAS_TIME_UNIT {
630 self.configuration.time_unit
631 } else {
632 None
633 },
634 true,
635 )
636 .await
637 }
638
639 async fn fetch_withdraw_quota(
640 &self,
641 ) -> anyhow::Result<RestApiResponse<models::FetchWithdrawQuotaResponse>> {
642 let query_params = BTreeMap::new();
643 let body_params = BTreeMap::new();
644
645 send_request::<models::FetchWithdrawQuotaResponse>(
646 &self.configuration,
647 "/sapi/v1/capital/withdraw/quota",
648 reqwest::Method::GET,
649 query_params,
650 body_params,
651 if HAS_TIME_UNIT {
652 self.configuration.time_unit
653 } else {
654 None
655 },
656 true,
657 )
658 .await
659 }
660
661 async fn one_click_arrival_deposit_apply(
662 &self,
663 params: OneClickArrivalDepositApplyParams,
664 ) -> anyhow::Result<RestApiResponse<models::OneClickArrivalDepositApplyResponse>> {
665 let OneClickArrivalDepositApplyParams {
666 deposit_id,
667 tx_id,
668 sub_account_id,
669 sub_user_id,
670 } = params;
671
672 let mut query_params = BTreeMap::new();
673 let body_params = BTreeMap::new();
674
675 if let Some(rw) = deposit_id {
676 query_params.insert("depositId".to_string(), json!(rw));
677 }
678
679 if let Some(rw) = tx_id {
680 query_params.insert("txId".to_string(), json!(rw));
681 }
682
683 if let Some(rw) = sub_account_id {
684 query_params.insert("subAccountId".to_string(), json!(rw));
685 }
686
687 if let Some(rw) = sub_user_id {
688 query_params.insert("subUserId".to_string(), json!(rw));
689 }
690
691 send_request::<models::OneClickArrivalDepositApplyResponse>(
692 &self.configuration,
693 "/sapi/v1/capital/deposit/credit-apply",
694 reqwest::Method::POST,
695 query_params,
696 body_params,
697 if HAS_TIME_UNIT {
698 self.configuration.time_unit
699 } else {
700 None
701 },
702 true,
703 )
704 .await
705 }
706
707 async fn withdraw(
708 &self,
709 params: WithdrawParams,
710 ) -> anyhow::Result<RestApiResponse<models::WithdrawResponse>> {
711 let WithdrawParams {
712 coin,
713 address,
714 amount,
715 withdraw_order_id,
716 network,
717 address_tag,
718 transaction_fee_flag,
719 name,
720 wallet_type,
721 recv_window,
722 } = params;
723
724 let mut query_params = BTreeMap::new();
725 let body_params = BTreeMap::new();
726
727 query_params.insert("coin".to_string(), json!(coin));
728
729 if let Some(rw) = withdraw_order_id {
730 query_params.insert("withdrawOrderId".to_string(), json!(rw));
731 }
732
733 if let Some(rw) = network {
734 query_params.insert("network".to_string(), json!(rw));
735 }
736
737 query_params.insert("address".to_string(), json!(address));
738
739 if let Some(rw) = address_tag {
740 query_params.insert("addressTag".to_string(), json!(rw));
741 }
742
743 query_params.insert("amount".to_string(), json!(amount));
744
745 if let Some(rw) = transaction_fee_flag {
746 query_params.insert("transactionFeeFlag".to_string(), json!(rw));
747 }
748
749 if let Some(rw) = name {
750 query_params.insert("name".to_string(), json!(rw));
751 }
752
753 if let Some(rw) = wallet_type {
754 query_params.insert("walletType".to_string(), json!(rw));
755 }
756
757 if let Some(rw) = recv_window {
758 query_params.insert("recvWindow".to_string(), json!(rw));
759 }
760
761 send_request::<models::WithdrawResponse>(
762 &self.configuration,
763 "/sapi/v1/capital/withdraw/apply",
764 reqwest::Method::POST,
765 query_params,
766 body_params,
767 if HAS_TIME_UNIT {
768 self.configuration.time_unit
769 } else {
770 None
771 },
772 true,
773 )
774 .await
775 }
776
777 async fn withdraw_history(
778 &self,
779 params: WithdrawHistoryParams,
780 ) -> anyhow::Result<RestApiResponse<Vec<models::WithdrawHistoryResponseInner>>> {
781 let WithdrawHistoryParams {
782 coin,
783 withdraw_order_id,
784 status,
785 offset,
786 limit,
787 id_list,
788 start_time,
789 end_time,
790 recv_window,
791 } = params;
792
793 let mut query_params = BTreeMap::new();
794 let body_params = BTreeMap::new();
795
796 if let Some(rw) = coin {
797 query_params.insert("coin".to_string(), json!(rw));
798 }
799
800 if let Some(rw) = withdraw_order_id {
801 query_params.insert("withdrawOrderId".to_string(), json!(rw));
802 }
803
804 if let Some(rw) = status {
805 query_params.insert("status".to_string(), json!(rw));
806 }
807
808 if let Some(rw) = offset {
809 query_params.insert("offset".to_string(), json!(rw));
810 }
811
812 if let Some(rw) = limit {
813 query_params.insert("limit".to_string(), json!(rw));
814 }
815
816 if let Some(rw) = id_list {
817 query_params.insert("idList".to_string(), json!(rw));
818 }
819
820 if let Some(rw) = start_time {
821 query_params.insert("startTime".to_string(), json!(rw));
822 }
823
824 if let Some(rw) = end_time {
825 query_params.insert("endTime".to_string(), json!(rw));
826 }
827
828 if let Some(rw) = recv_window {
829 query_params.insert("recvWindow".to_string(), json!(rw));
830 }
831
832 send_request::<Vec<models::WithdrawHistoryResponseInner>>(
833 &self.configuration,
834 "/sapi/v1/capital/withdraw/history",
835 reqwest::Method::GET,
836 query_params,
837 body_params,
838 if HAS_TIME_UNIT {
839 self.configuration.time_unit
840 } else {
841 None
842 },
843 true,
844 )
845 .await
846 }
847}
848
849#[cfg(all(test, feature = "wallet"))]
850mod tests {
851 use super::*;
852 use crate::TOKIO_SHARED_RT;
853 use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
854 use async_trait::async_trait;
855 use std::collections::HashMap;
856
857 struct DummyRestApiResponse<T> {
858 inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
859 status: u16,
860 headers: HashMap<String, String>,
861 rate_limits: Option<Vec<RestApiRateLimit>>,
862 }
863
864 impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
865 fn from(dummy: DummyRestApiResponse<T>) -> Self {
866 Self {
867 data_fn: dummy.inner,
868 status: dummy.status,
869 headers: dummy.headers,
870 rate_limits: dummy.rate_limits,
871 }
872 }
873 }
874
875 struct MockCapitalApiClient {
876 force_error: bool,
877 }
878
879 #[async_trait]
880 impl CapitalApi for MockCapitalApiClient {
881 async fn all_coins_information(
882 &self,
883 _params: AllCoinsInformationParams,
884 ) -> anyhow::Result<RestApiResponse<Vec<models::AllCoinsInformationResponseInner>>>
885 {
886 if self.force_error {
887 return Err(ConnectorError::ConnectorClientError {
888 msg: "ResponseError".to_string(),
889 code: None,
890 }
891 .into());
892 }
893
894 let resp_json: Value = serde_json::from_str(r#"[{"coin":"1MBABYDOGE","depositAllEnable":true,"withdrawAllEnable":true,"name":"1M x BABYDOGE","free":"34941.1","locked":"0","freeze":"0","withdrawing":"0","ipoing":"0","ipoable":"0","storage":"0","isLegalMoney":false,"trading":true,"networkList":[{"network":"BSC","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":false,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"BNB Smart Chain (BEP20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"10","withdrawMin":"20","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":5,"unLockConfirm":0,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":1,"busy":false,"contractAddressUrl":"https://bscscan.com/token/","contractAddress":"0xc748673057861a797275cd8a068abb95a902e8de","denomination":1000000},{"network":"ETH","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":true,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"Ethereum (ERC20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"1511","withdrawMin":"3022","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":6,"unLockConfirm":64,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":2,"busy":false,"contractAddressUrl":"https://etherscan.io/address/","contractAddress":"0xac57de9c1a09fec648e93eb98875b212db0d460b","denomination":1000000}]}]"#).unwrap();
895 let dummy_response: Vec<models::AllCoinsInformationResponseInner> =
896 serde_json::from_value(resp_json.clone())
897 .expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
898
899 let dummy = DummyRestApiResponse {
900 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
901 status: 200,
902 headers: HashMap::new(),
903 rate_limits: None,
904 };
905
906 Ok(dummy.into())
907 }
908
909 async fn deposit_address(
910 &self,
911 _params: DepositAddressParams,
912 ) -> anyhow::Result<RestApiResponse<models::DepositAddressResponse>> {
913 if self.force_error {
914 return Err(ConnectorError::ConnectorClientError {
915 msg: "ResponseError".to_string(),
916 code: None,
917 }
918 .into());
919 }
920
921 let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap();
922 let dummy_response: models::DepositAddressResponse =
923 serde_json::from_value(resp_json.clone())
924 .expect("should parse into models::DepositAddressResponse");
925
926 let dummy = DummyRestApiResponse {
927 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
928 status: 200,
929 headers: HashMap::new(),
930 rate_limits: None,
931 };
932
933 Ok(dummy.into())
934 }
935
936 async fn deposit_history(
937 &self,
938 _params: DepositHistoryParams,
939 ) -> anyhow::Result<RestApiResponse<Vec<models::DepositHistoryResponseInner>>> {
940 if self.force_error {
941 return Err(ConnectorError::ConnectorClientError {
942 msg: "ResponseError".to_string(),
943 code: None,
944 }
945 .into());
946 }
947
948 let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":1,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":0},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":1}]"#).unwrap();
949 let dummy_response: Vec<models::DepositHistoryResponseInner> =
950 serde_json::from_value(resp_json.clone())
951 .expect("should parse into Vec<models::DepositHistoryResponseInner>");
952
953 let dummy = DummyRestApiResponse {
954 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
955 status: 200,
956 headers: HashMap::new(),
957 rate_limits: None,
958 };
959
960 Ok(dummy.into())
961 }
962
963 async fn fetch_deposit_address_list_with_network(
964 &self,
965 _params: FetchDepositAddressListWithNetworkParams,
966 ) -> anyhow::Result<
967 RestApiResponse<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>,
968 > {
969 if self.force_error {
970 return Err(ConnectorError::ConnectorClientError {
971 msg: "ResponseError".to_string(),
972 code: None,
973 }
974 .into());
975 }
976
977 let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0x00003ada75e7da97ba0db2fcde72131f712455e2","tag":"","isDefault":1}]"#).unwrap();
978 let dummy_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
979
980 let dummy = DummyRestApiResponse {
981 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
982 status: 200,
983 headers: HashMap::new(),
984 rate_limits: None,
985 };
986
987 Ok(dummy.into())
988 }
989
990 async fn fetch_withdraw_address_list(
991 &self,
992 ) -> anyhow::Result<RestApiResponse<Vec<models::FetchWithdrawAddressListResponseInner>>>
993 {
994 if self.force_error {
995 return Err(ConnectorError::ConnectorClientError {
996 msg: "ResponseError".to_string(),
997 code: None,
998 }
999 .into());
1000 }
1001
1002 let resp_json: Value = serde_json::from_str(r#"[{"address":"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa","addressTag":"","coin":"BTC","name":"Satoshi","network":"BTC","origin":"bla","originType":"others","whiteStatus":true}]"#).unwrap();
1003 let dummy_response: Vec<models::FetchWithdrawAddressListResponseInner> =
1004 serde_json::from_value(resp_json.clone())
1005 .expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1006
1007 let dummy = DummyRestApiResponse {
1008 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1009 status: 200,
1010 headers: HashMap::new(),
1011 rate_limits: None,
1012 };
1013
1014 Ok(dummy.into())
1015 }
1016
1017 async fn fetch_withdraw_quota(
1018 &self,
1019 ) -> anyhow::Result<RestApiResponse<models::FetchWithdrawQuotaResponse>> {
1020 if self.force_error {
1021 return Err(ConnectorError::ConnectorClientError {
1022 msg: "ResponseError".to_string(),
1023 code: None,
1024 }
1025 .into());
1026 }
1027
1028 let resp_json: Value =
1029 serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#).unwrap();
1030 let dummy_response: models::FetchWithdrawQuotaResponse =
1031 serde_json::from_value(resp_json.clone())
1032 .expect("should parse into models::FetchWithdrawQuotaResponse");
1033
1034 let dummy = DummyRestApiResponse {
1035 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1036 status: 200,
1037 headers: HashMap::new(),
1038 rate_limits: None,
1039 };
1040
1041 Ok(dummy.into())
1042 }
1043
1044 async fn one_click_arrival_deposit_apply(
1045 &self,
1046 _params: OneClickArrivalDepositApplyParams,
1047 ) -> anyhow::Result<RestApiResponse<models::OneClickArrivalDepositApplyResponse>> {
1048 if self.force_error {
1049 return Err(ConnectorError::ConnectorClientError {
1050 msg: "ResponseError".to_string(),
1051 code: None,
1052 }
1053 .into());
1054 }
1055
1056 let resp_json: Value = serde_json::from_str(
1057 r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1058 )
1059 .unwrap();
1060 let dummy_response: models::OneClickArrivalDepositApplyResponse =
1061 serde_json::from_value(resp_json.clone())
1062 .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1063
1064 let dummy = DummyRestApiResponse {
1065 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1066 status: 200,
1067 headers: HashMap::new(),
1068 rate_limits: None,
1069 };
1070
1071 Ok(dummy.into())
1072 }
1073
1074 async fn withdraw(
1075 &self,
1076 _params: WithdrawParams,
1077 ) -> anyhow::Result<RestApiResponse<models::WithdrawResponse>> {
1078 if self.force_error {
1079 return Err(ConnectorError::ConnectorClientError {
1080 msg: "ResponseError".to_string(),
1081 code: None,
1082 }
1083 .into());
1084 }
1085
1086 let resp_json: Value =
1087 serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#).unwrap();
1088 let dummy_response: models::WithdrawResponse =
1089 serde_json::from_value(resp_json.clone())
1090 .expect("should parse into models::WithdrawResponse");
1091
1092 let dummy = DummyRestApiResponse {
1093 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1094 status: 200,
1095 headers: HashMap::new(),
1096 rate_limits: None,
1097 };
1098
1099 Ok(dummy.into())
1100 }
1101
1102 async fn withdraw_history(
1103 &self,
1104 _params: WithdrawHistoryParams,
1105 ) -> anyhow::Result<RestApiResponse<Vec<models::WithdrawHistoryResponseInner>>> {
1106 if self.force_error {
1107 return Err(ConnectorError::ConnectorClientError {
1108 msg: "ResponseError".to_string(),
1109 code: None,
1110 }
1111 .into());
1112 }
1113
1114 let resp_json: Value = serde_json::from_str(r#"[{"id":"b6ae22b3aa844210a7041aee7589627c","amount":"8.91000000","transactionFee":"0.004","coin":"USDT","status":6,"address":"0x94df8b352de7f46f64b01d3666bf6e936e44ce60","txId":"0xb5ef8c13b968a406cc62a93a8bd80f9e9a906ef1b3fcf20a2e48573c17659268","applyTime":"2019-10-12 11:12:02","network":"ETH","transferType":0,"withdrawOrderId":"WITHDRAWtest123","info":"The address is not valid. Please confirm with the recipient","confirmNo":3,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"},{"id":"156ec387f49b41df8724fa744fa82719","amount":"0.00150000","transactionFee":"0.004","coin":"BTC","status":6,"address":"1FZdVHtiBqMrWdjPyRPULCUceZPJ2WLCsB","txId":"60fd9007ebfddc753455f95fafa808c4302c836e4d1eebc5a132c36c1d8ac354","applyTime":"2019-09-24 12:43:45","network":"BTC","transferType":0,"info":"","confirmNo":2,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"}]"#).unwrap();
1115 let dummy_response: Vec<models::WithdrawHistoryResponseInner> =
1116 serde_json::from_value(resp_json.clone())
1117 .expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1118
1119 let dummy = DummyRestApiResponse {
1120 inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1121 status: 200,
1122 headers: HashMap::new(),
1123 rate_limits: None,
1124 };
1125
1126 Ok(dummy.into())
1127 }
1128 }
1129
1130 #[test]
1131 fn all_coins_information_required_params_success() {
1132 TOKIO_SHARED_RT.block_on(async {
1133 let client = MockCapitalApiClient { force_error: false };
1134
1135 let params = AllCoinsInformationParams::builder().build().unwrap();
1136
1137 let resp_json: Value = serde_json::from_str(r#"[{"coin":"1MBABYDOGE","depositAllEnable":true,"withdrawAllEnable":true,"name":"1M x BABYDOGE","free":"34941.1","locked":"0","freeze":"0","withdrawing":"0","ipoing":"0","ipoable":"0","storage":"0","isLegalMoney":false,"trading":true,"networkList":[{"network":"BSC","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":false,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"BNB Smart Chain (BEP20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"10","withdrawMin":"20","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":5,"unLockConfirm":0,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":1,"busy":false,"contractAddressUrl":"https://bscscan.com/token/","contractAddress":"0xc748673057861a797275cd8a068abb95a902e8de","denomination":1000000},{"network":"ETH","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":true,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"Ethereum (ERC20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"1511","withdrawMin":"3022","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":6,"unLockConfirm":64,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":2,"busy":false,"contractAddressUrl":"https://etherscan.io/address/","contractAddress":"0xac57de9c1a09fec648e93eb98875b212db0d460b","denomination":1000000}]}]"#).unwrap();
1138 let expected_response : Vec<models::AllCoinsInformationResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
1139
1140 let resp = client.all_coins_information(params).await.expect("Expected a response");
1141 let data_future = resp.data();
1142 let actual_response = data_future.await.unwrap();
1143 assert_eq!(actual_response, expected_response);
1144 });
1145 }
1146
1147 #[test]
1148 fn all_coins_information_optional_params_success() {
1149 TOKIO_SHARED_RT.block_on(async {
1150 let client = MockCapitalApiClient { force_error: false };
1151
1152 let params = AllCoinsInformationParams::builder().recv_window(5000).build().unwrap();
1153
1154 let resp_json: Value = serde_json::from_str(r#"[{"coin":"1MBABYDOGE","depositAllEnable":true,"withdrawAllEnable":true,"name":"1M x BABYDOGE","free":"34941.1","locked":"0","freeze":"0","withdrawing":"0","ipoing":"0","ipoable":"0","storage":"0","isLegalMoney":false,"trading":true,"networkList":[{"network":"BSC","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":false,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"BNB Smart Chain (BEP20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"10","withdrawMin":"20","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":5,"unLockConfirm":0,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":1,"busy":false,"contractAddressUrl":"https://bscscan.com/token/","contractAddress":"0xc748673057861a797275cd8a068abb95a902e8de","denomination":1000000},{"network":"ETH","coin":"1MBABYDOGE","withdrawIntegerMultiple":"0.01","isDefault":true,"depositEnable":true,"withdrawEnable":true,"depositDesc":"","withdrawDesc":"","specialTips":"","specialWithdrawTips":"","name":"Ethereum (ERC20)","resetAddressStatus":false,"addressRegex":"^(0x)[0-9A-Fa-f]{40}$","memoRegex":"","withdrawFee":"1511","withdrawMin":"3022","withdrawMax":"9999999999","withdrawInternalMin":"0.01","depositDust":"0.01","minConfirm":6,"unLockConfirm":64,"sameAddress":false,"withdrawTag":false,"estimatedArrivalTime":2,"busy":false,"contractAddressUrl":"https://etherscan.io/address/","contractAddress":"0xac57de9c1a09fec648e93eb98875b212db0d460b","denomination":1000000}]}]"#).unwrap();
1155 let expected_response : Vec<models::AllCoinsInformationResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
1156
1157 let resp = client.all_coins_information(params).await.expect("Expected a response");
1158 let data_future = resp.data();
1159 let actual_response = data_future.await.unwrap();
1160 assert_eq!(actual_response, expected_response);
1161 });
1162 }
1163
1164 #[test]
1165 fn all_coins_information_response_error() {
1166 TOKIO_SHARED_RT.block_on(async {
1167 let client = MockCapitalApiClient { force_error: true };
1168
1169 let params = AllCoinsInformationParams::builder().build().unwrap();
1170
1171 match client.all_coins_information(params).await {
1172 Ok(_) => panic!("Expected an error"),
1173 Err(err) => {
1174 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1175 }
1176 }
1177 });
1178 }
1179
1180 #[test]
1181 fn deposit_address_required_params_success() {
1182 TOKIO_SHARED_RT.block_on(async {
1183 let client = MockCapitalApiClient { force_error: false };
1184
1185 let params = DepositAddressParams::builder("coin_example".to_string(),).build().unwrap();
1186
1187 let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap();
1188 let expected_response : models::DepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepositAddressResponse");
1189
1190 let resp = client.deposit_address(params).await.expect("Expected a response");
1191 let data_future = resp.data();
1192 let actual_response = data_future.await.unwrap();
1193 assert_eq!(actual_response, expected_response);
1194 });
1195 }
1196
1197 #[test]
1198 fn deposit_address_optional_params_success() {
1199 TOKIO_SHARED_RT.block_on(async {
1200 let client = MockCapitalApiClient { force_error: false };
1201
1202 let params = DepositAddressParams::builder("coin_example".to_string(),).network("network_example".to_string()).amount(dec!(1.0)).recv_window(5000).build().unwrap();
1203
1204 let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap();
1205 let expected_response : models::DepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepositAddressResponse");
1206
1207 let resp = client.deposit_address(params).await.expect("Expected a response");
1208 let data_future = resp.data();
1209 let actual_response = data_future.await.unwrap();
1210 assert_eq!(actual_response, expected_response);
1211 });
1212 }
1213
1214 #[test]
1215 fn deposit_address_response_error() {
1216 TOKIO_SHARED_RT.block_on(async {
1217 let client = MockCapitalApiClient { force_error: true };
1218
1219 let params = DepositAddressParams::builder("coin_example".to_string())
1220 .build()
1221 .unwrap();
1222
1223 match client.deposit_address(params).await {
1224 Ok(_) => panic!("Expected an error"),
1225 Err(err) => {
1226 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1227 }
1228 }
1229 });
1230 }
1231
1232 #[test]
1233 fn deposit_history_required_params_success() {
1234 TOKIO_SHARED_RT.block_on(async {
1235 let client = MockCapitalApiClient { force_error: false };
1236
1237 let params = DepositHistoryParams::builder().build().unwrap();
1238
1239 let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":1,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":0},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":1}]"#).unwrap();
1240 let expected_response : Vec<models::DepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::DepositHistoryResponseInner>");
1241
1242 let resp = client.deposit_history(params).await.expect("Expected a response");
1243 let data_future = resp.data();
1244 let actual_response = data_future.await.unwrap();
1245 assert_eq!(actual_response, expected_response);
1246 });
1247 }
1248
1249 #[test]
1250 fn deposit_history_optional_params_success() {
1251 TOKIO_SHARED_RT.block_on(async {
1252 let client = MockCapitalApiClient { force_error: false };
1253
1254 let params = DepositHistoryParams::builder().include_source(false).coin("coin_example".to_string()).status(789).start_time(1623319461670).end_time(1641782889000).offset(0).limit(7).recv_window(5000).tx_id("1".to_string()).build().unwrap();
1255
1256 let resp_json: Value = serde_json::from_str(r#"[{"id":"769800519366885376","amount":"0.001","coin":"BNB","network":"BNB","status":1,"address":"bnb136ns6lfw4zs5hg4n85vdthaad7hq5m4gtkgf23","addressTag":"101764890","txId":"98A3EA560C6B3336D348B6C83F0F95ECE4F1F5919E94BD006E5BF3BF264FACFC","insertTime":1661493146000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":0},{"id":"769754833590042625","amount":"0.50000000","coin":"IOTA","network":"IOTA","status":1,"address":"SIZ9VLMHWATXKV99LH99CIGFJFUMLEHGWVZVNNZXRJJVWBPHYWPPBOSDORZ9EQSHCZAMPVAPGFYQAUUV9DROOXJLNW","addressTag":"","txId":"ESBFVQUTPIWQNJSPXFNHNYHSQNTGKRVKPRABQWTAXCDWOAKDKYWPTVG9BGXNVNKTLEJGESAVXIKIZ9999","insertTime":1599620082000,"completeTime":1661493146000,"transferType":0,"confirmTimes":"1/1","unlockConfirm":0,"walletType":0,"travelRuleStatus":1}]"#).unwrap();
1257 let expected_response : Vec<models::DepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::DepositHistoryResponseInner>");
1258
1259 let resp = client.deposit_history(params).await.expect("Expected a response");
1260 let data_future = resp.data();
1261 let actual_response = data_future.await.unwrap();
1262 assert_eq!(actual_response, expected_response);
1263 });
1264 }
1265
1266 #[test]
1267 fn deposit_history_response_error() {
1268 TOKIO_SHARED_RT.block_on(async {
1269 let client = MockCapitalApiClient { force_error: true };
1270
1271 let params = DepositHistoryParams::builder().build().unwrap();
1272
1273 match client.deposit_history(params).await {
1274 Ok(_) => panic!("Expected an error"),
1275 Err(err) => {
1276 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1277 }
1278 }
1279 });
1280 }
1281
1282 #[test]
1283 fn fetch_deposit_address_list_with_network_required_params_success() {
1284 TOKIO_SHARED_RT.block_on(async {
1285 let client = MockCapitalApiClient { force_error: false };
1286
1287 let params = FetchDepositAddressListWithNetworkParams::builder("coin_example".to_string(),).build().unwrap();
1288
1289 let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0x00003ada75e7da97ba0db2fcde72131f712455e2","tag":"","isDefault":1}]"#).unwrap();
1290 let expected_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
1291
1292 let resp = client.fetch_deposit_address_list_with_network(params).await.expect("Expected a response");
1293 let data_future = resp.data();
1294 let actual_response = data_future.await.unwrap();
1295 assert_eq!(actual_response, expected_response);
1296 });
1297 }
1298
1299 #[test]
1300 fn fetch_deposit_address_list_with_network_optional_params_success() {
1301 TOKIO_SHARED_RT.block_on(async {
1302 let client = MockCapitalApiClient { force_error: false };
1303
1304 let params = FetchDepositAddressListWithNetworkParams::builder("coin_example".to_string(),).network("network_example".to_string()).build().unwrap();
1305
1306 let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0},{"coin":"ETH","address":"0x00003ada75e7da97ba0db2fcde72131f712455e2","tag":"","isDefault":1}]"#).unwrap();
1307 let expected_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
1308
1309 let resp = client.fetch_deposit_address_list_with_network(params).await.expect("Expected a response");
1310 let data_future = resp.data();
1311 let actual_response = data_future.await.unwrap();
1312 assert_eq!(actual_response, expected_response);
1313 });
1314 }
1315
1316 #[test]
1317 fn fetch_deposit_address_list_with_network_response_error() {
1318 TOKIO_SHARED_RT.block_on(async {
1319 let client = MockCapitalApiClient { force_error: true };
1320
1321 let params =
1322 FetchDepositAddressListWithNetworkParams::builder("coin_example".to_string())
1323 .build()
1324 .unwrap();
1325
1326 match client.fetch_deposit_address_list_with_network(params).await {
1327 Ok(_) => panic!("Expected an error"),
1328 Err(err) => {
1329 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1330 }
1331 }
1332 });
1333 }
1334
1335 #[test]
1336 fn fetch_withdraw_address_list_required_params_success() {
1337 TOKIO_SHARED_RT.block_on(async {
1338 let client = MockCapitalApiClient { force_error: false };
1339
1340
1341 let resp_json: Value = serde_json::from_str(r#"[{"address":"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa","addressTag":"","coin":"BTC","name":"Satoshi","network":"BTC","origin":"bla","originType":"others","whiteStatus":true}]"#).unwrap();
1342 let expected_response : Vec<models::FetchWithdrawAddressListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1343
1344 let resp = client.fetch_withdraw_address_list().await.expect("Expected a response");
1345 let data_future = resp.data();
1346 let actual_response = data_future.await.unwrap();
1347 assert_eq!(actual_response, expected_response);
1348 });
1349 }
1350
1351 #[test]
1352 fn fetch_withdraw_address_list_optional_params_success() {
1353 TOKIO_SHARED_RT.block_on(async {
1354 let client = MockCapitalApiClient { force_error: false };
1355
1356
1357 let resp_json: Value = serde_json::from_str(r#"[{"address":"1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa","addressTag":"","coin":"BTC","name":"Satoshi","network":"BTC","origin":"bla","originType":"others","whiteStatus":true}]"#).unwrap();
1358 let expected_response : Vec<models::FetchWithdrawAddressListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1359
1360 let resp = client.fetch_withdraw_address_list().await.expect("Expected a response");
1361 let data_future = resp.data();
1362 let actual_response = data_future.await.unwrap();
1363 assert_eq!(actual_response, expected_response);
1364 });
1365 }
1366
1367 #[test]
1368 fn fetch_withdraw_address_list_response_error() {
1369 TOKIO_SHARED_RT.block_on(async {
1370 let client = MockCapitalApiClient { force_error: true };
1371
1372 match client.fetch_withdraw_address_list().await {
1373 Ok(_) => panic!("Expected an error"),
1374 Err(err) => {
1375 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1376 }
1377 }
1378 });
1379 }
1380
1381 #[test]
1382 fn fetch_withdraw_quota_required_params_success() {
1383 TOKIO_SHARED_RT.block_on(async {
1384 let client = MockCapitalApiClient { force_error: false };
1385
1386 let resp_json: Value =
1387 serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#).unwrap();
1388 let expected_response: models::FetchWithdrawQuotaResponse =
1389 serde_json::from_value(resp_json.clone())
1390 .expect("should parse into models::FetchWithdrawQuotaResponse");
1391
1392 let resp = client
1393 .fetch_withdraw_quota()
1394 .await
1395 .expect("Expected a response");
1396 let data_future = resp.data();
1397 let actual_response = data_future.await.unwrap();
1398 assert_eq!(actual_response, expected_response);
1399 });
1400 }
1401
1402 #[test]
1403 fn fetch_withdraw_quota_optional_params_success() {
1404 TOKIO_SHARED_RT.block_on(async {
1405 let client = MockCapitalApiClient { force_error: false };
1406
1407 let resp_json: Value =
1408 serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#).unwrap();
1409 let expected_response: models::FetchWithdrawQuotaResponse =
1410 serde_json::from_value(resp_json.clone())
1411 .expect("should parse into models::FetchWithdrawQuotaResponse");
1412
1413 let resp = client
1414 .fetch_withdraw_quota()
1415 .await
1416 .expect("Expected a response");
1417 let data_future = resp.data();
1418 let actual_response = data_future.await.unwrap();
1419 assert_eq!(actual_response, expected_response);
1420 });
1421 }
1422
1423 #[test]
1424 fn fetch_withdraw_quota_response_error() {
1425 TOKIO_SHARED_RT.block_on(async {
1426 let client = MockCapitalApiClient { force_error: true };
1427
1428 match client.fetch_withdraw_quota().await {
1429 Ok(_) => panic!("Expected an error"),
1430 Err(err) => {
1431 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1432 }
1433 }
1434 });
1435 }
1436
1437 #[test]
1438 fn one_click_arrival_deposit_apply_required_params_success() {
1439 TOKIO_SHARED_RT.block_on(async {
1440 let client = MockCapitalApiClient { force_error: false };
1441
1442 let params = OneClickArrivalDepositApplyParams::builder()
1443 .build()
1444 .unwrap();
1445
1446 let resp_json: Value = serde_json::from_str(
1447 r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1448 )
1449 .unwrap();
1450 let expected_response: models::OneClickArrivalDepositApplyResponse =
1451 serde_json::from_value(resp_json.clone())
1452 .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1453
1454 let resp = client
1455 .one_click_arrival_deposit_apply(params)
1456 .await
1457 .expect("Expected a response");
1458 let data_future = resp.data();
1459 let actual_response = data_future.await.unwrap();
1460 assert_eq!(actual_response, expected_response);
1461 });
1462 }
1463
1464 #[test]
1465 fn one_click_arrival_deposit_apply_optional_params_success() {
1466 TOKIO_SHARED_RT.block_on(async {
1467 let client = MockCapitalApiClient { force_error: false };
1468
1469 let params = OneClickArrivalDepositApplyParams::builder()
1470 .deposit_id(1)
1471 .tx_id("1".to_string())
1472 .sub_account_id(1)
1473 .sub_user_id(1)
1474 .build()
1475 .unwrap();
1476
1477 let resp_json: Value = serde_json::from_str(
1478 r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1479 )
1480 .unwrap();
1481 let expected_response: models::OneClickArrivalDepositApplyResponse =
1482 serde_json::from_value(resp_json.clone())
1483 .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1484
1485 let resp = client
1486 .one_click_arrival_deposit_apply(params)
1487 .await
1488 .expect("Expected a response");
1489 let data_future = resp.data();
1490 let actual_response = data_future.await.unwrap();
1491 assert_eq!(actual_response, expected_response);
1492 });
1493 }
1494
1495 #[test]
1496 fn one_click_arrival_deposit_apply_response_error() {
1497 TOKIO_SHARED_RT.block_on(async {
1498 let client = MockCapitalApiClient { force_error: true };
1499
1500 let params = OneClickArrivalDepositApplyParams::builder()
1501 .build()
1502 .unwrap();
1503
1504 match client.one_click_arrival_deposit_apply(params).await {
1505 Ok(_) => panic!("Expected an error"),
1506 Err(err) => {
1507 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1508 }
1509 }
1510 });
1511 }
1512
1513 #[test]
1514 fn withdraw_required_params_success() {
1515 TOKIO_SHARED_RT.block_on(async {
1516 let client = MockCapitalApiClient { force_error: false };
1517
1518 let params = WithdrawParams::builder(
1519 "coin_example".to_string(),
1520 "address_example".to_string(),
1521 dec!(1.0),
1522 )
1523 .build()
1524 .unwrap();
1525
1526 let resp_json: Value =
1527 serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#).unwrap();
1528 let expected_response: models::WithdrawResponse =
1529 serde_json::from_value(resp_json.clone())
1530 .expect("should parse into models::WithdrawResponse");
1531
1532 let resp = client.withdraw(params).await.expect("Expected a response");
1533 let data_future = resp.data();
1534 let actual_response = data_future.await.unwrap();
1535 assert_eq!(actual_response, expected_response);
1536 });
1537 }
1538
1539 #[test]
1540 fn withdraw_optional_params_success() {
1541 TOKIO_SHARED_RT.block_on(async {
1542 let client = MockCapitalApiClient { force_error: false };
1543
1544 let params = WithdrawParams::builder(
1545 "coin_example".to_string(),
1546 "address_example".to_string(),
1547 dec!(1.0),
1548 )
1549 .withdraw_order_id("1".to_string())
1550 .network("network_example".to_string())
1551 .address_tag("address_tag_example".to_string())
1552 .transaction_fee_flag(false)
1553 .name("name_example".to_string())
1554 .wallet_type(0)
1555 .recv_window(5000)
1556 .build()
1557 .unwrap();
1558
1559 let resp_json: Value =
1560 serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#).unwrap();
1561 let expected_response: models::WithdrawResponse =
1562 serde_json::from_value(resp_json.clone())
1563 .expect("should parse into models::WithdrawResponse");
1564
1565 let resp = client.withdraw(params).await.expect("Expected a response");
1566 let data_future = resp.data();
1567 let actual_response = data_future.await.unwrap();
1568 assert_eq!(actual_response, expected_response);
1569 });
1570 }
1571
1572 #[test]
1573 fn withdraw_response_error() {
1574 TOKIO_SHARED_RT.block_on(async {
1575 let client = MockCapitalApiClient { force_error: true };
1576
1577 let params = WithdrawParams::builder(
1578 "coin_example".to_string(),
1579 "address_example".to_string(),
1580 dec!(1.0),
1581 )
1582 .build()
1583 .unwrap();
1584
1585 match client.withdraw(params).await {
1586 Ok(_) => panic!("Expected an error"),
1587 Err(err) => {
1588 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1589 }
1590 }
1591 });
1592 }
1593
1594 #[test]
1595 fn withdraw_history_required_params_success() {
1596 TOKIO_SHARED_RT.block_on(async {
1597 let client = MockCapitalApiClient { force_error: false };
1598
1599 let params = WithdrawHistoryParams::builder().build().unwrap();
1600
1601 let resp_json: Value = serde_json::from_str(r#"[{"id":"b6ae22b3aa844210a7041aee7589627c","amount":"8.91000000","transactionFee":"0.004","coin":"USDT","status":6,"address":"0x94df8b352de7f46f64b01d3666bf6e936e44ce60","txId":"0xb5ef8c13b968a406cc62a93a8bd80f9e9a906ef1b3fcf20a2e48573c17659268","applyTime":"2019-10-12 11:12:02","network":"ETH","transferType":0,"withdrawOrderId":"WITHDRAWtest123","info":"The address is not valid. Please confirm with the recipient","confirmNo":3,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"},{"id":"156ec387f49b41df8724fa744fa82719","amount":"0.00150000","transactionFee":"0.004","coin":"BTC","status":6,"address":"1FZdVHtiBqMrWdjPyRPULCUceZPJ2WLCsB","txId":"60fd9007ebfddc753455f95fafa808c4302c836e4d1eebc5a132c36c1d8ac354","applyTime":"2019-09-24 12:43:45","network":"BTC","transferType":0,"info":"","confirmNo":2,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"}]"#).unwrap();
1602 let expected_response : Vec<models::WithdrawHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1603
1604 let resp = client.withdraw_history(params).await.expect("Expected a response");
1605 let data_future = resp.data();
1606 let actual_response = data_future.await.unwrap();
1607 assert_eq!(actual_response, expected_response);
1608 });
1609 }
1610
1611 #[test]
1612 fn withdraw_history_optional_params_success() {
1613 TOKIO_SHARED_RT.block_on(async {
1614 let client = MockCapitalApiClient { force_error: false };
1615
1616 let params = WithdrawHistoryParams::builder().coin("coin_example".to_string()).withdraw_order_id("1".to_string()).status(789).offset(0).limit(7).id_list("id_list_example".to_string()).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();
1617
1618 let resp_json: Value = serde_json::from_str(r#"[{"id":"b6ae22b3aa844210a7041aee7589627c","amount":"8.91000000","transactionFee":"0.004","coin":"USDT","status":6,"address":"0x94df8b352de7f46f64b01d3666bf6e936e44ce60","txId":"0xb5ef8c13b968a406cc62a93a8bd80f9e9a906ef1b3fcf20a2e48573c17659268","applyTime":"2019-10-12 11:12:02","network":"ETH","transferType":0,"withdrawOrderId":"WITHDRAWtest123","info":"The address is not valid. Please confirm with the recipient","confirmNo":3,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"},{"id":"156ec387f49b41df8724fa744fa82719","amount":"0.00150000","transactionFee":"0.004","coin":"BTC","status":6,"address":"1FZdVHtiBqMrWdjPyRPULCUceZPJ2WLCsB","txId":"60fd9007ebfddc753455f95fafa808c4302c836e4d1eebc5a132c36c1d8ac354","applyTime":"2019-09-24 12:43:45","network":"BTC","transferType":0,"info":"","confirmNo":2,"walletType":1,"txKey":"","completeTime":"2023-03-23 16:52:41"}]"#).unwrap();
1619 let expected_response : Vec<models::WithdrawHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1620
1621 let resp = client.withdraw_history(params).await.expect("Expected a response");
1622 let data_future = resp.data();
1623 let actual_response = data_future.await.unwrap();
1624 assert_eq!(actual_response, expected_response);
1625 });
1626 }
1627
1628 #[test]
1629 fn withdraw_history_response_error() {
1630 TOKIO_SHARED_RT.block_on(async {
1631 let client = MockCapitalApiClient { force_error: true };
1632
1633 let params = WithdrawHistoryParams::builder().build().unwrap();
1634
1635 match client.withdraw_history(params).await {
1636 Ok(_) => panic!("Expected an error"),
1637 Err(err) => {
1638 assert_eq!(err.to_string(), "Connector client error: ResponseError");
1639 }
1640 }
1641 });
1642 }
1643}