Skip to main content

binance_sdk/wallet/rest_api/apis/
capital_api.rs

1/*
2 * Wallet REST API
3 *
4 * Query balances, manage assets, and perform wallet operations via the Binance Wallet API.
5 *
6 * The version of the OpenAPI document: 1.0.0
7 *
8 *
9 * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
10 * https://openapi-generator.tech
11 * Do not edit the class manually.
12 */
13
14#![allow(unused_imports)]
15use async_trait::async_trait;
16use derive_builder::Builder;
17use reqwest;
18use rust_decimal::prelude::*;
19use serde::{Deserialize, Serialize};
20use serde_json::{Value, json};
21use std::collections::BTreeMap;
22
23use crate::common::{
24    config::ConfigurationRestApi,
25    models::{ParamBuildError, RestApiResponse},
26    utils::send_request,
27};
28use crate::wallet::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait 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#[allow(non_camel_case_types)]
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub enum DepositHistoryStatusEnum {
84    #[serde(rename = "0")]
85    Status0,
86    #[serde(rename = "1")]
87    Status1,
88    #[serde(rename = "2")]
89    Status2,
90    #[serde(rename = "6")]
91    Status6,
92    #[serde(rename = "7")]
93    Status7,
94    #[serde(rename = "8")]
95    Status8,
96}
97
98impl DepositHistoryStatusEnum {
99    #[must_use]
100    pub fn as_str(&self) -> &'static str {
101        match self {
102            Self::Status0 => "0",
103            Self::Status1 => "1",
104            Self::Status2 => "2",
105            Self::Status6 => "6",
106            Self::Status7 => "7",
107            Self::Status8 => "8",
108        }
109    }
110}
111
112impl std::str::FromStr for DepositHistoryStatusEnum {
113    type Err = Box<dyn std::error::Error + Send + Sync>;
114
115    fn from_str(s: &str) -> Result<Self, Self::Err> {
116        match s {
117            "0" => Ok(Self::Status0),
118            "1" => Ok(Self::Status1),
119            "2" => Ok(Self::Status2),
120            "6" => Ok(Self::Status6),
121            "7" => Ok(Self::Status7),
122            "8" => Ok(Self::Status8),
123            other => Err(format!("invalid DepositHistoryStatusEnum: {}", other).into()),
124        }
125    }
126}
127
128/// Request parameters for the [`all_coins_information`] operation.
129///
130/// This struct holds all of the inputs you can pass when calling
131/// [`all_coins_information`](#method.all_coins_information).
132#[derive(Clone, Debug, Builder, Deserialize, Default)]
133#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
134pub struct AllCoinsInformationParams {
135    ///
136    /// The `recv_window` parameter.
137    ///
138    /// This field is **optional.
139    #[builder(setter(into), default)]
140    #[serde(rename = "recvWindow", default)]
141    pub recv_window: Option<i64>,
142}
143
144impl AllCoinsInformationParams {
145    /// Create a builder for [`all_coins_information`].
146    ///
147    #[must_use]
148    pub fn builder() -> AllCoinsInformationParamsBuilder {
149        AllCoinsInformationParamsBuilder::default()
150    }
151}
152/// Request parameters for the [`deposit_address`] operation.
153///
154/// This struct holds all of the inputs you can pass when calling
155/// [`deposit_address`](#method.deposit_address).
156#[derive(Clone, Debug, Builder, Deserialize)]
157#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
158pub struct DepositAddressParams {
159    /// `coin` refers to the parent network address format that the address is using
160    ///
161    /// This field is **required.
162    #[builder(setter(into))]
163    #[serde(rename = "coin")]
164    pub coin: String,
165    ///
166    /// The `network` parameter.
167    ///
168    /// This field is **optional.
169    #[builder(setter(into), default)]
170    #[serde(rename = "network", default)]
171    pub network: Option<String>,
172    ///
173    /// The `amount` parameter.
174    ///
175    /// This field is **optional.
176    #[builder(setter(into), default)]
177    #[serde(rename = "amount", default)]
178    pub amount: Option<rust_decimal::Decimal>,
179    ///
180    /// The `recv_window` parameter.
181    ///
182    /// This field is **optional.
183    #[builder(setter(into), default)]
184    #[serde(rename = "recvWindow", default)]
185    pub recv_window: Option<i64>,
186}
187
188impl DepositAddressParams {
189    /// Create a builder for [`deposit_address`].
190    ///
191    /// Required parameters:
192    ///
193    /// * `coin` — `coin` refers to the parent network address format that the address is using
194    ///
195    #[must_use]
196    pub fn builder(coin: String) -> DepositAddressParamsBuilder {
197        DepositAddressParamsBuilder::default().coin(coin)
198    }
199}
200/// Request parameters for the [`deposit_history`] operation.
201///
202/// This struct holds all of the inputs you can pass when calling
203/// [`deposit_history`](#method.deposit_history).
204#[derive(Clone, Debug, Builder, Deserialize, Default)]
205#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
206pub struct DepositHistoryParams {
207    /// return `sourceAddress` field when set to `true`
208    ///
209    /// This field is **optional.
210    #[builder(setter(into), default)]
211    #[serde(rename = "includeSource", default)]
212    pub include_source: Option<bool>,
213    ///
214    /// The `coin` parameter.
215    ///
216    /// This field is **optional.
217    #[builder(setter(into), default)]
218    #[serde(rename = "coin", default)]
219    pub coin: Option<String>,
220    /// 0: pending, 6: credited but cannot withdraw, 7: Wrong Deposit, 8: Waiting User confirm, 1: success
221    ///
222    /// This field is **optional.
223    #[builder(setter(into), default)]
224    #[serde(rename = "status", default)]
225    pub status: Option<DepositHistoryStatusEnum>,
226    /// Default: 90 days from current timestamp
227    ///
228    /// This field is **optional.
229    #[builder(setter(into), default)]
230    #[serde(rename = "startTime", default)]
231    pub start_time: Option<i64>,
232    /// Default: present timestamp
233    ///
234    /// This field is **optional.
235    #[builder(setter(into), default)]
236    #[serde(rename = "endTime", default)]
237    pub end_time: Option<i64>,
238    ///
239    /// The `offset` parameter.
240    ///
241    /// This field is **optional.
242    #[builder(setter(into), default)]
243    #[serde(rename = "offset", default)]
244    pub offset: Option<i64>,
245    ///
246    /// The `limit` parameter.
247    ///
248    /// This field is **optional.
249    #[builder(setter(into), default)]
250    #[serde(rename = "limit", default)]
251    pub limit: Option<i64>,
252    ///
253    /// The `recv_window` parameter.
254    ///
255    /// This field is **optional.
256    #[builder(setter(into), default)]
257    #[serde(rename = "recvWindow", default)]
258    pub recv_window: Option<i64>,
259    ///
260    /// The `tx_id` parameter.
261    ///
262    /// This field is **optional.
263    #[builder(setter(into), default)]
264    #[serde(rename = "txId", default)]
265    pub tx_id: Option<String>,
266}
267
268impl DepositHistoryParams {
269    /// Create a builder for [`deposit_history`].
270    ///
271    #[must_use]
272    pub fn builder() -> DepositHistoryParamsBuilder {
273        DepositHistoryParamsBuilder::default()
274    }
275}
276/// Request parameters for the [`fetch_deposit_address_list_with_network`] operation.
277///
278/// This struct holds all of the inputs you can pass when calling
279/// [`fetch_deposit_address_list_with_network`](#method.fetch_deposit_address_list_with_network).
280#[derive(Clone, Debug, Builder, Deserialize)]
281#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
282pub struct FetchDepositAddressListWithNetworkParams {
283    /// Coin name
284    ///
285    /// This field is **required.
286    #[builder(setter(into))]
287    #[serde(rename = "coin")]
288    pub coin: String,
289    /// If network is not send, return with default network of the coin. You can get network and isDefault in networkList in the response of `Get /sapi/v1/capital/config/getall`
290    ///
291    /// This field is **optional.
292    #[builder(setter(into), default)]
293    #[serde(rename = "network", default)]
294    pub network: Option<String>,
295}
296
297impl FetchDepositAddressListWithNetworkParams {
298    /// Create a builder for [`fetch_deposit_address_list_with_network`].
299    ///
300    /// Required parameters:
301    ///
302    /// * `coin` — Coin name
303    ///
304    #[must_use]
305    pub fn builder(coin: String) -> FetchDepositAddressListWithNetworkParamsBuilder {
306        FetchDepositAddressListWithNetworkParamsBuilder::default().coin(coin)
307    }
308}
309/// Request parameters for the [`one_click_arrival_deposit_apply`] operation.
310///
311/// This struct holds all of the inputs you can pass when calling
312/// [`one_click_arrival_deposit_apply`](#method.one_click_arrival_deposit_apply).
313#[derive(Clone, Debug, Builder, Deserialize, Default)]
314#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
315pub struct OneClickArrivalDepositApplyParams {
316    /// Deposit record Id, priority use
317    ///
318    /// This field is **optional.
319    #[builder(setter(into), default)]
320    #[serde(rename = "depositId", default)]
321    pub deposit_id: Option<i64>,
322    /// Deposit txId, used when depositId is not specified
323    ///
324    /// This field is **optional.
325    #[builder(setter(into), default)]
326    #[serde(rename = "txId", default)]
327    pub tx_id: Option<String>,
328    /// Sub-accountId of Cloud user
329    ///
330    /// This field is **optional.
331    #[builder(setter(into), default)]
332    #[serde(rename = "subAccountId", default)]
333    pub sub_account_id: Option<String>,
334    /// Sub-userId of parent user
335    ///
336    /// This field is **optional.
337    #[builder(setter(into), default)]
338    #[serde(rename = "subUserId", default)]
339    pub sub_user_id: Option<i64>,
340}
341
342impl OneClickArrivalDepositApplyParams {
343    /// Create a builder for [`one_click_arrival_deposit_apply`].
344    ///
345    #[must_use]
346    pub fn builder() -> OneClickArrivalDepositApplyParamsBuilder {
347        OneClickArrivalDepositApplyParamsBuilder::default()
348    }
349}
350/// Request parameters for the [`withdraw`] operation.
351///
352/// This struct holds all of the inputs you can pass when calling
353/// [`withdraw`](#method.withdraw).
354#[derive(Clone, Debug, Builder, Deserialize)]
355#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
356pub struct WithdrawParams {
357    ///
358    /// The `coin` parameter.
359    ///
360    /// This field is **required.
361    #[builder(setter(into))]
362    #[serde(rename = "coin")]
363    pub coin: String,
364    /// Withdrawal address
365    ///
366    /// This field is **required.
367    #[builder(setter(into))]
368    #[serde(rename = "address")]
369    pub address: String,
370    /// Amount
371    ///
372    /// This field is **required.
373    #[builder(setter(into))]
374    #[serde(rename = "amount")]
375    pub amount: rust_decimal::Decimal,
376    /// client side id for withdrawal, if provide here, can be used in GET
377    /// `/sapi/v1/capital/withdraw/history` for query.
378    ///
379    /// This field is **optional.
380    #[builder(setter(into), default)]
381    #[serde(rename = "withdrawOrderId", default)]
382    pub withdraw_order_id: Option<String>,
383    /// Withdrawal network
384    ///
385    /// This field is **optional.
386    #[builder(setter(into), default)]
387    #[serde(rename = "network", default)]
388    pub network: Option<String>,
389    /// Secondary address identifier for coins like XRP,XMR etc.
390    ///
391    /// This field is **optional.
392    #[builder(setter(into), default)]
393    #[serde(rename = "addressTag", default)]
394    pub address_tag: Option<String>,
395    /// When making internal transfer, `true` for returning the fee to the destination account; `false` for
396    /// returning the fee back to the departure account. Default `false`.
397    ///
398    /// This field is **optional.
399    #[builder(setter(into), default)]
400    #[serde(rename = "transactionFeeFlag", default)]
401    pub transaction_fee_flag: Option<bool>,
402    ///
403    /// The `name` parameter.
404    ///
405    /// This field is **optional.
406    #[builder(setter(into), default)]
407    #[serde(rename = "name", default)]
408    pub name: Option<String>,
409    /// The wallet type for withdraw,0-spot wallet ,1-funding wallet. Default walletType is the current
410    /// "selected wallet" under wallet->Fiat and Spot/Funding->Deposit
411    ///
412    /// This field is **optional.
413    #[builder(setter(into), default)]
414    #[serde(rename = "walletType", default)]
415    pub wallet_type: Option<i64>,
416    ///
417    /// The `recv_window` parameter.
418    ///
419    /// This field is **optional.
420    #[builder(setter(into), default)]
421    #[serde(rename = "recvWindow", default)]
422    pub recv_window: Option<i64>,
423}
424
425impl WithdrawParams {
426    /// Create a builder for [`withdraw`].
427    ///
428    /// Required parameters:
429    ///
430    /// * `coin` — String
431    /// * `address` — Withdrawal address
432    /// * `amount` — Amount
433    ///
434    #[must_use]
435    pub fn builder(
436        coin: String,
437        address: String,
438        amount: rust_decimal::Decimal,
439    ) -> WithdrawParamsBuilder {
440        WithdrawParamsBuilder::default()
441            .coin(coin)
442            .address(address)
443            .amount(amount)
444    }
445}
446/// Request parameters for the [`withdraw_history`] operation.
447///
448/// This struct holds all of the inputs you can pass when calling
449/// [`withdraw_history`](#method.withdraw_history).
450#[derive(Clone, Debug, Builder, Deserialize, Default)]
451#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
452pub struct WithdrawHistoryParams {
453    ///
454    /// The `coin` parameter.
455    ///
456    /// This field is **optional.
457    #[builder(setter(into), default)]
458    #[serde(rename = "coin", default)]
459    pub coin: Option<String>,
460    /// client side id for withdrawal, if provided in POST `/sapi/v1/capital/withdraw/apply`, can be used here for
461    /// query.
462    ///
463    /// This field is **optional.
464    #[builder(setter(into), default)]
465    #[serde(rename = "withdrawOrderId", default)]
466    pub withdraw_order_id: Option<String>,
467    /// 0(0:Email Sent, 2:Awaiting Approval 3:Rejected 4:Processing 6:Completed)
468    ///
469    /// This field is **optional.
470    #[builder(setter(into), default)]
471    #[serde(rename = "status", default)]
472    pub status: Option<i64>,
473    /// Default: 0
474    ///
475    /// This field is **optional.
476    #[builder(setter(into), default)]
477    #[serde(rename = "offset", default)]
478    pub offset: Option<i64>,
479    ///
480    /// The `limit` parameter.
481    ///
482    /// This field is **optional.
483    #[builder(setter(into), default)]
484    #[serde(rename = "limit", default)]
485    pub limit: Option<i64>,
486    /// id list returned in the response of POST `/sapi/v1/capital/withdraw/apply`, separated by `,`
487    ///
488    /// This field is **optional.
489    #[builder(setter(into), default)]
490    #[serde(rename = "idList", default)]
491    pub id_list: Option<String>,
492    /// Default: 90 days from current timestamp
493    ///
494    /// This field is **optional.
495    #[builder(setter(into), default)]
496    #[serde(rename = "startTime", default)]
497    pub start_time: Option<i64>,
498    /// Default: present timestamp
499    ///
500    /// This field is **optional.
501    #[builder(setter(into), default)]
502    #[serde(rename = "endTime", default)]
503    pub end_time: Option<i64>,
504    ///
505    /// The `recv_window` parameter.
506    ///
507    /// This field is **optional.
508    #[builder(setter(into), default)]
509    #[serde(rename = "recvWindow", default)]
510    pub recv_window: Option<i64>,
511}
512
513impl WithdrawHistoryParams {
514    /// Create a builder for [`withdraw_history`].
515    ///
516    #[must_use]
517    pub fn builder() -> WithdrawHistoryParamsBuilder {
518        WithdrawHistoryParamsBuilder::default()
519    }
520}
521
522#[async_trait]
523impl CapitalApi for CapitalApiClient {
524    async fn all_coins_information(
525        &self,
526        params: AllCoinsInformationParams,
527    ) -> anyhow::Result<RestApiResponse<Vec<models::AllCoinsInformationResponseInner>>> {
528        let AllCoinsInformationParams { recv_window } = params;
529
530        let mut query_params = BTreeMap::new();
531        let body_params = BTreeMap::new();
532
533        if let Some(rw) = recv_window {
534            query_params.insert("recvWindow".to_string(), json!(rw));
535        }
536
537        send_request::<Vec<models::AllCoinsInformationResponseInner>>(
538            &self.configuration,
539            "/sapi/v1/capital/config/getall",
540            reqwest::Method::GET,
541            query_params,
542            body_params,
543            if HAS_TIME_UNIT {
544                self.configuration.time_unit
545            } else {
546                None
547            },
548            true,
549        )
550        .await
551    }
552
553    async fn deposit_address(
554        &self,
555        params: DepositAddressParams,
556    ) -> anyhow::Result<RestApiResponse<models::DepositAddressResponse>> {
557        let DepositAddressParams {
558            coin,
559            network,
560            amount,
561            recv_window,
562        } = params;
563
564        let mut query_params = BTreeMap::new();
565        let body_params = BTreeMap::new();
566
567        query_params.insert("coin".to_string(), json!(coin));
568
569        if let Some(rw) = network {
570            query_params.insert("network".to_string(), json!(rw));
571        }
572
573        if let Some(rw) = amount {
574            query_params.insert("amount".to_string(), json!(rw));
575        }
576
577        if let Some(rw) = recv_window {
578            query_params.insert("recvWindow".to_string(), json!(rw));
579        }
580
581        send_request::<models::DepositAddressResponse>(
582            &self.configuration,
583            "/sapi/v1/capital/deposit/address",
584            reqwest::Method::GET,
585            query_params,
586            body_params,
587            if HAS_TIME_UNIT {
588                self.configuration.time_unit
589            } else {
590                None
591            },
592            true,
593        )
594        .await
595    }
596
597    async fn deposit_history(
598        &self,
599        params: DepositHistoryParams,
600    ) -> anyhow::Result<RestApiResponse<Vec<models::DepositHistoryResponseInner>>> {
601        let DepositHistoryParams {
602            include_source,
603            coin,
604            status,
605            start_time,
606            end_time,
607            offset,
608            limit,
609            recv_window,
610            tx_id,
611        } = params;
612
613        let mut query_params = BTreeMap::new();
614        let body_params = BTreeMap::new();
615
616        if let Some(rw) = include_source {
617            query_params.insert("includeSource".to_string(), json!(rw));
618        }
619
620        if let Some(rw) = coin {
621            query_params.insert("coin".to_string(), json!(rw));
622        }
623
624        if let Some(rw) = status {
625            query_params.insert("status".to_string(), json!(rw));
626        }
627
628        if let Some(rw) = start_time {
629            query_params.insert("startTime".to_string(), json!(rw));
630        }
631
632        if let Some(rw) = end_time {
633            query_params.insert("endTime".to_string(), json!(rw));
634        }
635
636        if let Some(rw) = offset {
637            query_params.insert("offset".to_string(), json!(rw));
638        }
639
640        if let Some(rw) = limit {
641            query_params.insert("limit".to_string(), json!(rw));
642        }
643
644        if let Some(rw) = recv_window {
645            query_params.insert("recvWindow".to_string(), json!(rw));
646        }
647
648        if let Some(rw) = tx_id {
649            query_params.insert("txId".to_string(), json!(rw));
650        }
651
652        send_request::<Vec<models::DepositHistoryResponseInner>>(
653            &self.configuration,
654            "/sapi/v1/capital/deposit/hisrec",
655            reqwest::Method::GET,
656            query_params,
657            body_params,
658            if HAS_TIME_UNIT {
659                self.configuration.time_unit
660            } else {
661                None
662            },
663            true,
664        )
665        .await
666    }
667
668    async fn fetch_deposit_address_list_with_network(
669        &self,
670        params: FetchDepositAddressListWithNetworkParams,
671    ) -> anyhow::Result<RestApiResponse<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>>
672    {
673        let FetchDepositAddressListWithNetworkParams { coin, network } = params;
674
675        let mut query_params = BTreeMap::new();
676        let body_params = BTreeMap::new();
677
678        query_params.insert("coin".to_string(), json!(coin));
679
680        if let Some(rw) = network {
681            query_params.insert("network".to_string(), json!(rw));
682        }
683
684        send_request::<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>(
685            &self.configuration,
686            "/sapi/v1/capital/deposit/address/list",
687            reqwest::Method::GET,
688            query_params,
689            body_params,
690            if HAS_TIME_UNIT {
691                self.configuration.time_unit
692            } else {
693                None
694            },
695            true,
696        )
697        .await
698    }
699
700    async fn fetch_withdraw_address_list(
701        &self,
702    ) -> anyhow::Result<RestApiResponse<Vec<models::FetchWithdrawAddressListResponseInner>>> {
703        let query_params = BTreeMap::new();
704        let body_params = BTreeMap::new();
705
706        send_request::<Vec<models::FetchWithdrawAddressListResponseInner>>(
707            &self.configuration,
708            "/sapi/v1/capital/withdraw/address/list",
709            reqwest::Method::GET,
710            query_params,
711            body_params,
712            if HAS_TIME_UNIT {
713                self.configuration.time_unit
714            } else {
715                None
716            },
717            true,
718        )
719        .await
720    }
721
722    async fn fetch_withdraw_quota(
723        &self,
724    ) -> anyhow::Result<RestApiResponse<models::FetchWithdrawQuotaResponse>> {
725        let query_params = BTreeMap::new();
726        let body_params = BTreeMap::new();
727
728        send_request::<models::FetchWithdrawQuotaResponse>(
729            &self.configuration,
730            "/sapi/v1/capital/withdraw/quota",
731            reqwest::Method::GET,
732            query_params,
733            body_params,
734            if HAS_TIME_UNIT {
735                self.configuration.time_unit
736            } else {
737                None
738            },
739            true,
740        )
741        .await
742    }
743
744    async fn one_click_arrival_deposit_apply(
745        &self,
746        params: OneClickArrivalDepositApplyParams,
747    ) -> anyhow::Result<RestApiResponse<models::OneClickArrivalDepositApplyResponse>> {
748        let OneClickArrivalDepositApplyParams {
749            deposit_id,
750            tx_id,
751            sub_account_id,
752            sub_user_id,
753        } = params;
754
755        let mut query_params = BTreeMap::new();
756        let body_params = BTreeMap::new();
757
758        if let Some(rw) = deposit_id {
759            query_params.insert("depositId".to_string(), json!(rw));
760        }
761
762        if let Some(rw) = tx_id {
763            query_params.insert("txId".to_string(), json!(rw));
764        }
765
766        if let Some(rw) = sub_account_id {
767            query_params.insert("subAccountId".to_string(), json!(rw));
768        }
769
770        if let Some(rw) = sub_user_id {
771            query_params.insert("subUserId".to_string(), json!(rw));
772        }
773
774        send_request::<models::OneClickArrivalDepositApplyResponse>(
775            &self.configuration,
776            "/sapi/v1/capital/deposit/credit-apply",
777            reqwest::Method::POST,
778            query_params,
779            body_params,
780            if HAS_TIME_UNIT {
781                self.configuration.time_unit
782            } else {
783                None
784            },
785            true,
786        )
787        .await
788    }
789
790    async fn withdraw(
791        &self,
792        params: WithdrawParams,
793    ) -> anyhow::Result<RestApiResponse<models::WithdrawResponse>> {
794        let WithdrawParams {
795            coin,
796            address,
797            amount,
798            withdraw_order_id,
799            network,
800            address_tag,
801            transaction_fee_flag,
802            name,
803            wallet_type,
804            recv_window,
805        } = params;
806
807        let mut query_params = BTreeMap::new();
808        let body_params = BTreeMap::new();
809
810        query_params.insert("coin".to_string(), json!(coin));
811
812        if let Some(rw) = withdraw_order_id {
813            query_params.insert("withdrawOrderId".to_string(), json!(rw));
814        }
815
816        if let Some(rw) = network {
817            query_params.insert("network".to_string(), json!(rw));
818        }
819
820        query_params.insert("address".to_string(), json!(address));
821
822        if let Some(rw) = address_tag {
823            query_params.insert("addressTag".to_string(), json!(rw));
824        }
825
826        query_params.insert("amount".to_string(), json!(amount));
827
828        if let Some(rw) = transaction_fee_flag {
829            query_params.insert("transactionFeeFlag".to_string(), json!(rw));
830        }
831
832        if let Some(rw) = name {
833            query_params.insert("name".to_string(), json!(rw));
834        }
835
836        if let Some(rw) = wallet_type {
837            query_params.insert("walletType".to_string(), json!(rw));
838        }
839
840        if let Some(rw) = recv_window {
841            query_params.insert("recvWindow".to_string(), json!(rw));
842        }
843
844        send_request::<models::WithdrawResponse>(
845            &self.configuration,
846            "/sapi/v1/capital/withdraw/apply",
847            reqwest::Method::POST,
848            query_params,
849            body_params,
850            if HAS_TIME_UNIT {
851                self.configuration.time_unit
852            } else {
853                None
854            },
855            true,
856        )
857        .await
858    }
859
860    async fn withdraw_history(
861        &self,
862        params: WithdrawHistoryParams,
863    ) -> anyhow::Result<RestApiResponse<Vec<models::WithdrawHistoryResponseInner>>> {
864        let WithdrawHistoryParams {
865            coin,
866            withdraw_order_id,
867            status,
868            offset,
869            limit,
870            id_list,
871            start_time,
872            end_time,
873            recv_window,
874        } = params;
875
876        let mut query_params = BTreeMap::new();
877        let body_params = BTreeMap::new();
878
879        if let Some(rw) = coin {
880            query_params.insert("coin".to_string(), json!(rw));
881        }
882
883        if let Some(rw) = withdraw_order_id {
884            query_params.insert("withdrawOrderId".to_string(), json!(rw));
885        }
886
887        if let Some(rw) = status {
888            query_params.insert("status".to_string(), json!(rw));
889        }
890
891        if let Some(rw) = offset {
892            query_params.insert("offset".to_string(), json!(rw));
893        }
894
895        if let Some(rw) = limit {
896            query_params.insert("limit".to_string(), json!(rw));
897        }
898
899        if let Some(rw) = id_list {
900            query_params.insert("idList".to_string(), json!(rw));
901        }
902
903        if let Some(rw) = start_time {
904            query_params.insert("startTime".to_string(), json!(rw));
905        }
906
907        if let Some(rw) = end_time {
908            query_params.insert("endTime".to_string(), json!(rw));
909        }
910
911        if let Some(rw) = recv_window {
912            query_params.insert("recvWindow".to_string(), json!(rw));
913        }
914
915        send_request::<Vec<models::WithdrawHistoryResponseInner>>(
916            &self.configuration,
917            "/sapi/v1/capital/withdraw/history",
918            reqwest::Method::GET,
919            query_params,
920            body_params,
921            if HAS_TIME_UNIT {
922                self.configuration.time_unit
923            } else {
924                None
925            },
926            true,
927        )
928        .await
929    }
930}
931
932#[cfg(all(test, feature = "wallet"))]
933mod tests {
934    use super::*;
935    use crate::TOKIO_SHARED_RT;
936    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
937    use async_trait::async_trait;
938    use std::collections::HashMap;
939
940    struct DummyRestApiResponse<T> {
941        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
942        status: u16,
943        headers: HashMap<String, String>,
944        rate_limits: Option<Vec<RestApiRateLimit>>,
945    }
946
947    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
948        fn from(dummy: DummyRestApiResponse<T>) -> Self {
949            Self {
950                data_fn: dummy.inner,
951                status: dummy.status,
952                headers: dummy.headers,
953                rate_limits: dummy.rate_limits,
954            }
955        }
956    }
957
958    struct MockCapitalApiClient {
959        force_error: bool,
960    }
961
962    #[async_trait]
963    impl CapitalApi for MockCapitalApiClient {
964        async fn all_coins_information(
965            &self,
966            _params: AllCoinsInformationParams,
967        ) -> anyhow::Result<RestApiResponse<Vec<models::AllCoinsInformationResponseInner>>>
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":"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}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
978            let dummy_response: Vec<models::AllCoinsInformationResponseInner> =
979                serde_json::from_value(resp_json.clone())
980                    .expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
981
982            let dummy = DummyRestApiResponse {
983                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
984                status: 200,
985                headers: HashMap::new(),
986                rate_limits: None,
987            };
988
989            Ok(dummy.into())
990        }
991
992        async fn deposit_address(
993            &self,
994            _params: DepositAddressParams,
995        ) -> anyhow::Result<RestApiResponse<models::DepositAddressResponse>> {
996            if self.force_error {
997                return Err(ConnectorError::ConnectorClientError {
998                    msg: "ResponseError".to_string(),
999                    code: None,
1000                }
1001                .into());
1002            }
1003
1004            let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap_or_else(|_| serde_json::json!({}));
1005            let dummy_response: models::DepositAddressResponse =
1006                serde_json::from_value(resp_json.clone())
1007                    .expect("should parse into models::DepositAddressResponse");
1008
1009            let dummy = DummyRestApiResponse {
1010                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1011                status: 200,
1012                headers: HashMap::new(),
1013                rate_limits: None,
1014            };
1015
1016            Ok(dummy.into())
1017        }
1018
1019        async fn deposit_history(
1020            &self,
1021            _params: DepositHistoryParams,
1022        ) -> anyhow::Result<RestApiResponse<Vec<models::DepositHistoryResponseInner>>> {
1023            if self.force_error {
1024                return Err(ConnectorError::ConnectorClientError {
1025                    msg: "ResponseError".to_string(),
1026                    code: None,
1027                }
1028                .into());
1029            }
1030
1031            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}]"#).unwrap_or_else(|_| serde_json::json!({}));
1032            let dummy_response: Vec<models::DepositHistoryResponseInner> =
1033                serde_json::from_value(resp_json.clone())
1034                    .expect("should parse into Vec<models::DepositHistoryResponseInner>");
1035
1036            let dummy = DummyRestApiResponse {
1037                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1038                status: 200,
1039                headers: HashMap::new(),
1040                rate_limits: None,
1041            };
1042
1043            Ok(dummy.into())
1044        }
1045
1046        async fn fetch_deposit_address_list_with_network(
1047            &self,
1048            _params: FetchDepositAddressListWithNetworkParams,
1049        ) -> anyhow::Result<
1050            RestApiResponse<Vec<models::FetchDepositAddressListWithNetworkResponseInner>>,
1051        > {
1052            if self.force_error {
1053                return Err(ConnectorError::ConnectorClientError {
1054                    msg: "ResponseError".to_string(),
1055                    code: None,
1056                }
1057                .into());
1058            }
1059
1060            let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
1061            let dummy_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
1062
1063            let dummy = DummyRestApiResponse {
1064                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1065                status: 200,
1066                headers: HashMap::new(),
1067                rate_limits: None,
1068            };
1069
1070            Ok(dummy.into())
1071        }
1072
1073        async fn fetch_withdraw_address_list(
1074            &self,
1075        ) -> anyhow::Result<RestApiResponse<Vec<models::FetchWithdrawAddressListResponseInner>>>
1076        {
1077            if self.force_error {
1078                return Err(ConnectorError::ConnectorClientError {
1079                    msg: "ResponseError".to_string(),
1080                    code: None,
1081                }
1082                .into());
1083            }
1084
1085            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_or_else(|_| serde_json::json!({}));
1086            let dummy_response: Vec<models::FetchWithdrawAddressListResponseInner> =
1087                serde_json::from_value(resp_json.clone())
1088                    .expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1089
1090            let dummy = DummyRestApiResponse {
1091                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1092                status: 200,
1093                headers: HashMap::new(),
1094                rate_limits: None,
1095            };
1096
1097            Ok(dummy.into())
1098        }
1099
1100        async fn fetch_withdraw_quota(
1101            &self,
1102        ) -> anyhow::Result<RestApiResponse<models::FetchWithdrawQuotaResponse>> {
1103            if self.force_error {
1104                return Err(ConnectorError::ConnectorClientError {
1105                    msg: "ResponseError".to_string(),
1106                    code: None,
1107                }
1108                .into());
1109            }
1110
1111            let resp_json: Value =
1112                serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#)
1113                    .unwrap_or_else(|_| serde_json::json!({}));
1114            let dummy_response: models::FetchWithdrawQuotaResponse =
1115                serde_json::from_value(resp_json.clone())
1116                    .expect("should parse into models::FetchWithdrawQuotaResponse");
1117
1118            let dummy = DummyRestApiResponse {
1119                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1120                status: 200,
1121                headers: HashMap::new(),
1122                rate_limits: None,
1123            };
1124
1125            Ok(dummy.into())
1126        }
1127
1128        async fn one_click_arrival_deposit_apply(
1129            &self,
1130            _params: OneClickArrivalDepositApplyParams,
1131        ) -> anyhow::Result<RestApiResponse<models::OneClickArrivalDepositApplyResponse>> {
1132            if self.force_error {
1133                return Err(ConnectorError::ConnectorClientError {
1134                    msg: "ResponseError".to_string(),
1135                    code: None,
1136                }
1137                .into());
1138            }
1139
1140            let resp_json: Value = serde_json::from_str(
1141                r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1142            )
1143            .unwrap_or_else(|_| serde_json::json!({}));
1144            let dummy_response: models::OneClickArrivalDepositApplyResponse =
1145                serde_json::from_value(resp_json.clone())
1146                    .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1147
1148            let dummy = DummyRestApiResponse {
1149                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1150                status: 200,
1151                headers: HashMap::new(),
1152                rate_limits: None,
1153            };
1154
1155            Ok(dummy.into())
1156        }
1157
1158        async fn withdraw(
1159            &self,
1160            _params: WithdrawParams,
1161        ) -> anyhow::Result<RestApiResponse<models::WithdrawResponse>> {
1162            if self.force_error {
1163                return Err(ConnectorError::ConnectorClientError {
1164                    msg: "ResponseError".to_string(),
1165                    code: None,
1166                }
1167                .into());
1168            }
1169
1170            let resp_json: Value =
1171                serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#)
1172                    .unwrap_or_else(|_| serde_json::json!({}));
1173            let dummy_response: models::WithdrawResponse =
1174                serde_json::from_value(resp_json.clone())
1175                    .expect("should parse into models::WithdrawResponse");
1176
1177            let dummy = DummyRestApiResponse {
1178                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1179                status: 200,
1180                headers: HashMap::new(),
1181                rate_limits: None,
1182            };
1183
1184            Ok(dummy.into())
1185        }
1186
1187        async fn withdraw_history(
1188            &self,
1189            _params: WithdrawHistoryParams,
1190        ) -> anyhow::Result<RestApiResponse<Vec<models::WithdrawHistoryResponseInner>>> {
1191            if self.force_error {
1192                return Err(ConnectorError::ConnectorClientError {
1193                    msg: "ResponseError".to_string(),
1194                    code: None,
1195                }
1196                .into());
1197            }
1198
1199            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"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1200            let dummy_response: Vec<models::WithdrawHistoryResponseInner> =
1201                serde_json::from_value(resp_json.clone())
1202                    .expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1203
1204            let dummy = DummyRestApiResponse {
1205                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
1206                status: 200,
1207                headers: HashMap::new(),
1208                rate_limits: None,
1209            };
1210
1211            Ok(dummy.into())
1212        }
1213    }
1214
1215    #[test]
1216    fn all_coins_information_required_params_success() {
1217        TOKIO_SHARED_RT.block_on(async {
1218            let client = MockCapitalApiClient { force_error: false };
1219
1220            let params = AllCoinsInformationParams::builder().build().unwrap();
1221
1222            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}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1223            let expected_response : Vec<models::AllCoinsInformationResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
1224
1225            let resp = client.all_coins_information(params).await.expect("Expected a response");
1226            let data_future = resp.data();
1227            let actual_response = data_future.await.unwrap();
1228            assert_eq!(actual_response, expected_response);
1229        });
1230    }
1231
1232    #[test]
1233    fn all_coins_information_optional_params_success() {
1234        TOKIO_SHARED_RT.block_on(async {
1235            let client = MockCapitalApiClient { force_error: false };
1236
1237            let params = AllCoinsInformationParams::builder().recv_window(5000).build().unwrap();
1238
1239            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}]}]"#).unwrap_or_else(|_| serde_json::json!({}));
1240            let expected_response : Vec<models::AllCoinsInformationResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::AllCoinsInformationResponseInner>");
1241
1242            let resp = client.all_coins_information(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 all_coins_information_response_error() {
1251        TOKIO_SHARED_RT.block_on(async {
1252            let client = MockCapitalApiClient { force_error: true };
1253
1254            let params = AllCoinsInformationParams::builder().build().unwrap();
1255
1256            match client.all_coins_information(params).await {
1257                Ok(_) => panic!("Expected an error"),
1258                Err(err) => {
1259                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1260                }
1261            }
1262        });
1263    }
1264
1265    #[test]
1266    fn deposit_address_required_params_success() {
1267        TOKIO_SHARED_RT.block_on(async {
1268            let client = MockCapitalApiClient { force_error: false };
1269
1270            let params = DepositAddressParams::builder("BTC".to_string(),).build().unwrap();
1271
1272            let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap_or_else(|_| serde_json::json!({}));
1273            let expected_response : models::DepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepositAddressResponse");
1274
1275            let resp = client.deposit_address(params).await.expect("Expected a response");
1276            let data_future = resp.data();
1277            let actual_response = data_future.await.unwrap();
1278            assert_eq!(actual_response, expected_response);
1279        });
1280    }
1281
1282    #[test]
1283    fn deposit_address_optional_params_success() {
1284        TOKIO_SHARED_RT.block_on(async {
1285            let client = MockCapitalApiClient { force_error: false };
1286
1287            let params = DepositAddressParams::builder("BTC".to_string(),).network("network_example".to_string()).amount(dec!(1.0)).recv_window(5000).build().unwrap();
1288
1289            let resp_json: Value = serde_json::from_str(r#"{"address":"1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv","coin":"BTC","tag":"","url":"https://btc.com/1HPn8Rx2y6nNSfagQBKy27GB99Vbzg89wv"}"#).unwrap_or_else(|_| serde_json::json!({}));
1290            let expected_response : models::DepositAddressResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::DepositAddressResponse");
1291
1292            let resp = client.deposit_address(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 deposit_address_response_error() {
1301        TOKIO_SHARED_RT.block_on(async {
1302            let client = MockCapitalApiClient { force_error: true };
1303
1304            let params = DepositAddressParams::builder("BTC".to_string())
1305                .build()
1306                .unwrap();
1307
1308            match client.deposit_address(params).await {
1309                Ok(_) => panic!("Expected an error"),
1310                Err(err) => {
1311                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1312                }
1313            }
1314        });
1315    }
1316
1317    #[test]
1318    fn deposit_history_required_params_success() {
1319        TOKIO_SHARED_RT.block_on(async {
1320            let client = MockCapitalApiClient { force_error: false };
1321
1322            let params = DepositHistoryParams::builder().build().unwrap();
1323
1324            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}]"#).unwrap_or_else(|_| serde_json::json!({}));
1325            let expected_response : Vec<models::DepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::DepositHistoryResponseInner>");
1326
1327            let resp = client.deposit_history(params).await.expect("Expected a response");
1328            let data_future = resp.data();
1329            let actual_response = data_future.await.unwrap();
1330            assert_eq!(actual_response, expected_response);
1331        });
1332    }
1333
1334    #[test]
1335    fn deposit_history_optional_params_success() {
1336        TOKIO_SHARED_RT.block_on(async {
1337            let client = MockCapitalApiClient { force_error: false };
1338
1339            let params = DepositHistoryParams::builder().include_source(false).coin("BTC".to_string()).status(DepositHistoryStatusEnum::Status0).start_time(1623319461670).end_time(1641782889000).offset(0).limit(1000).recv_window(5000).tx_id("1".to_string()).build().unwrap();
1340
1341            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}]"#).unwrap_or_else(|_| serde_json::json!({}));
1342            let expected_response : Vec<models::DepositHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::DepositHistoryResponseInner>");
1343
1344            let resp = client.deposit_history(params).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 deposit_history_response_error() {
1353        TOKIO_SHARED_RT.block_on(async {
1354            let client = MockCapitalApiClient { force_error: true };
1355
1356            let params = DepositHistoryParams::builder().build().unwrap();
1357
1358            match client.deposit_history(params).await {
1359                Ok(_) => panic!("Expected an error"),
1360                Err(err) => {
1361                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1362                }
1363            }
1364        });
1365    }
1366
1367    #[test]
1368    fn fetch_deposit_address_list_with_network_required_params_success() {
1369        TOKIO_SHARED_RT.block_on(async {
1370            let client = MockCapitalApiClient { force_error: false };
1371
1372            let params = FetchDepositAddressListWithNetworkParams::builder("BTC".to_string(),).build().unwrap();
1373
1374            let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
1375            let expected_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
1376
1377            let resp = client.fetch_deposit_address_list_with_network(params).await.expect("Expected a response");
1378            let data_future = resp.data();
1379            let actual_response = data_future.await.unwrap();
1380            assert_eq!(actual_response, expected_response);
1381        });
1382    }
1383
1384    #[test]
1385    fn fetch_deposit_address_list_with_network_optional_params_success() {
1386        TOKIO_SHARED_RT.block_on(async {
1387            let client = MockCapitalApiClient { force_error: false };
1388
1389            let params = FetchDepositAddressListWithNetworkParams::builder("BTC".to_string(),).network("network_example".to_string()).build().unwrap();
1390
1391            let resp_json: Value = serde_json::from_str(r#"[{"coin":"ETH","address":"0xD316E95Fd9E8E237Cb11f8200Babbc5D8D177BA4","tag":"","isDefault":0}]"#).unwrap_or_else(|_| serde_json::json!({}));
1392            let expected_response : Vec<models::FetchDepositAddressListWithNetworkResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchDepositAddressListWithNetworkResponseInner>");
1393
1394            let resp = client.fetch_deposit_address_list_with_network(params).await.expect("Expected a response");
1395            let data_future = resp.data();
1396            let actual_response = data_future.await.unwrap();
1397            assert_eq!(actual_response, expected_response);
1398        });
1399    }
1400
1401    #[test]
1402    fn fetch_deposit_address_list_with_network_response_error() {
1403        TOKIO_SHARED_RT.block_on(async {
1404            let client = MockCapitalApiClient { force_error: true };
1405
1406            let params = FetchDepositAddressListWithNetworkParams::builder("BTC".to_string())
1407                .build()
1408                .unwrap();
1409
1410            match client.fetch_deposit_address_list_with_network(params).await {
1411                Ok(_) => panic!("Expected an error"),
1412                Err(err) => {
1413                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1414                }
1415            }
1416        });
1417    }
1418
1419    #[test]
1420    fn fetch_withdraw_address_list_required_params_success() {
1421        TOKIO_SHARED_RT.block_on(async {
1422            let client = MockCapitalApiClient { force_error: false };
1423
1424
1425            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_or_else(|_| serde_json::json!({}));
1426            let expected_response : Vec<models::FetchWithdrawAddressListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1427
1428            let resp = client.fetch_withdraw_address_list().await.expect("Expected a response");
1429            let data_future = resp.data();
1430            let actual_response = data_future.await.unwrap();
1431            assert_eq!(actual_response, expected_response);
1432        });
1433    }
1434
1435    #[test]
1436    fn fetch_withdraw_address_list_optional_params_success() {
1437        TOKIO_SHARED_RT.block_on(async {
1438            let client = MockCapitalApiClient { force_error: false };
1439
1440
1441            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_or_else(|_| serde_json::json!({}));
1442            let expected_response : Vec<models::FetchWithdrawAddressListResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::FetchWithdrawAddressListResponseInner>");
1443
1444            let resp = client.fetch_withdraw_address_list().await.expect("Expected a response");
1445            let data_future = resp.data();
1446            let actual_response = data_future.await.unwrap();
1447            assert_eq!(actual_response, expected_response);
1448        });
1449    }
1450
1451    #[test]
1452    fn fetch_withdraw_address_list_response_error() {
1453        TOKIO_SHARED_RT.block_on(async {
1454            let client = MockCapitalApiClient { force_error: true };
1455
1456            match client.fetch_withdraw_address_list().await {
1457                Ok(_) => panic!("Expected an error"),
1458                Err(err) => {
1459                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1460                }
1461            }
1462        });
1463    }
1464
1465    #[test]
1466    fn fetch_withdraw_quota_required_params_success() {
1467        TOKIO_SHARED_RT.block_on(async {
1468            let client = MockCapitalApiClient { force_error: false };
1469
1470            let resp_json: Value =
1471                serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#)
1472                    .unwrap_or_else(|_| serde_json::json!({}));
1473            let expected_response: models::FetchWithdrawQuotaResponse =
1474                serde_json::from_value(resp_json.clone())
1475                    .expect("should parse into models::FetchWithdrawQuotaResponse");
1476
1477            let resp = client
1478                .fetch_withdraw_quota()
1479                .await
1480                .expect("Expected a response");
1481            let data_future = resp.data();
1482            let actual_response = data_future.await.unwrap();
1483            assert_eq!(actual_response, expected_response);
1484        });
1485    }
1486
1487    #[test]
1488    fn fetch_withdraw_quota_optional_params_success() {
1489        TOKIO_SHARED_RT.block_on(async {
1490            let client = MockCapitalApiClient { force_error: false };
1491
1492            let resp_json: Value =
1493                serde_json::from_str(r#"{"wdQuota":"10000","usedWdQuota":"1000"}"#)
1494                    .unwrap_or_else(|_| serde_json::json!({}));
1495            let expected_response: models::FetchWithdrawQuotaResponse =
1496                serde_json::from_value(resp_json.clone())
1497                    .expect("should parse into models::FetchWithdrawQuotaResponse");
1498
1499            let resp = client
1500                .fetch_withdraw_quota()
1501                .await
1502                .expect("Expected a response");
1503            let data_future = resp.data();
1504            let actual_response = data_future.await.unwrap();
1505            assert_eq!(actual_response, expected_response);
1506        });
1507    }
1508
1509    #[test]
1510    fn fetch_withdraw_quota_response_error() {
1511        TOKIO_SHARED_RT.block_on(async {
1512            let client = MockCapitalApiClient { force_error: true };
1513
1514            match client.fetch_withdraw_quota().await {
1515                Ok(_) => panic!("Expected an error"),
1516                Err(err) => {
1517                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1518                }
1519            }
1520        });
1521    }
1522
1523    #[test]
1524    fn one_click_arrival_deposit_apply_required_params_success() {
1525        TOKIO_SHARED_RT.block_on(async {
1526            let client = MockCapitalApiClient { force_error: false };
1527
1528            let params = OneClickArrivalDepositApplyParams::builder()
1529                .build()
1530                .unwrap();
1531
1532            let resp_json: Value = serde_json::from_str(
1533                r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1534            )
1535            .unwrap_or_else(|_| serde_json::json!({}));
1536            let expected_response: models::OneClickArrivalDepositApplyResponse =
1537                serde_json::from_value(resp_json.clone())
1538                    .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1539
1540            let resp = client
1541                .one_click_arrival_deposit_apply(params)
1542                .await
1543                .expect("Expected a response");
1544            let data_future = resp.data();
1545            let actual_response = data_future.await.unwrap();
1546            assert_eq!(actual_response, expected_response);
1547        });
1548    }
1549
1550    #[test]
1551    fn one_click_arrival_deposit_apply_optional_params_success() {
1552        TOKIO_SHARED_RT.block_on(async {
1553            let client = MockCapitalApiClient { force_error: false };
1554
1555            let params = OneClickArrivalDepositApplyParams::builder()
1556                .deposit_id(1)
1557                .tx_id("1".to_string())
1558                .sub_account_id("1".to_string())
1559                .sub_user_id(1)
1560                .build()
1561                .unwrap();
1562
1563            let resp_json: Value = serde_json::from_str(
1564                r#"{"code":"000000","message":"success","data":true,"success":true}"#,
1565            )
1566            .unwrap_or_else(|_| serde_json::json!({}));
1567            let expected_response: models::OneClickArrivalDepositApplyResponse =
1568                serde_json::from_value(resp_json.clone())
1569                    .expect("should parse into models::OneClickArrivalDepositApplyResponse");
1570
1571            let resp = client
1572                .one_click_arrival_deposit_apply(params)
1573                .await
1574                .expect("Expected a response");
1575            let data_future = resp.data();
1576            let actual_response = data_future.await.unwrap();
1577            assert_eq!(actual_response, expected_response);
1578        });
1579    }
1580
1581    #[test]
1582    fn one_click_arrival_deposit_apply_response_error() {
1583        TOKIO_SHARED_RT.block_on(async {
1584            let client = MockCapitalApiClient { force_error: true };
1585
1586            let params = OneClickArrivalDepositApplyParams::builder()
1587                .build()
1588                .unwrap();
1589
1590            match client.one_click_arrival_deposit_apply(params).await {
1591                Ok(_) => panic!("Expected an error"),
1592                Err(err) => {
1593                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1594                }
1595            }
1596        });
1597    }
1598
1599    #[test]
1600    fn withdraw_required_params_success() {
1601        TOKIO_SHARED_RT.block_on(async {
1602            let client = MockCapitalApiClient { force_error: false };
1603
1604            let params = WithdrawParams::builder(
1605                "BTC".to_string(),
1606                "address_example".to_string(),
1607                dec!(1.0),
1608            )
1609            .build()
1610            .unwrap();
1611
1612            let resp_json: Value =
1613                serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#)
1614                    .unwrap_or_else(|_| serde_json::json!({}));
1615            let expected_response: models::WithdrawResponse =
1616                serde_json::from_value(resp_json.clone())
1617                    .expect("should parse into models::WithdrawResponse");
1618
1619            let resp = client.withdraw(params).await.expect("Expected a response");
1620            let data_future = resp.data();
1621            let actual_response = data_future.await.unwrap();
1622            assert_eq!(actual_response, expected_response);
1623        });
1624    }
1625
1626    #[test]
1627    fn withdraw_optional_params_success() {
1628        TOKIO_SHARED_RT.block_on(async {
1629            let client = MockCapitalApiClient { force_error: false };
1630
1631            let params = WithdrawParams::builder(
1632                "BTC".to_string(),
1633                "address_example".to_string(),
1634                dec!(1.0),
1635            )
1636            .withdraw_order_id("1".to_string())
1637            .network("network_example".to_string())
1638            .address_tag("address_tag_example".to_string())
1639            .transaction_fee_flag(true)
1640            .name("name_example".to_string())
1641            .wallet_type(0)
1642            .recv_window(5000)
1643            .build()
1644            .unwrap();
1645
1646            let resp_json: Value =
1647                serde_json::from_str(r#"{"id":"7213fea8e94b4a5593d507237e5a555b"}"#)
1648                    .unwrap_or_else(|_| serde_json::json!({}));
1649            let expected_response: models::WithdrawResponse =
1650                serde_json::from_value(resp_json.clone())
1651                    .expect("should parse into models::WithdrawResponse");
1652
1653            let resp = client.withdraw(params).await.expect("Expected a response");
1654            let data_future = resp.data();
1655            let actual_response = data_future.await.unwrap();
1656            assert_eq!(actual_response, expected_response);
1657        });
1658    }
1659
1660    #[test]
1661    fn withdraw_response_error() {
1662        TOKIO_SHARED_RT.block_on(async {
1663            let client = MockCapitalApiClient { force_error: true };
1664
1665            let params = WithdrawParams::builder(
1666                "BTC".to_string(),
1667                "address_example".to_string(),
1668                dec!(1.0),
1669            )
1670            .build()
1671            .unwrap();
1672
1673            match client.withdraw(params).await {
1674                Ok(_) => panic!("Expected an error"),
1675                Err(err) => {
1676                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1677                }
1678            }
1679        });
1680    }
1681
1682    #[test]
1683    fn withdraw_history_required_params_success() {
1684        TOKIO_SHARED_RT.block_on(async {
1685            let client = MockCapitalApiClient { force_error: false };
1686
1687            let params = WithdrawHistoryParams::builder().build().unwrap();
1688
1689            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"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1690            let expected_response : Vec<models::WithdrawHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1691
1692            let resp = client.withdraw_history(params).await.expect("Expected a response");
1693            let data_future = resp.data();
1694            let actual_response = data_future.await.unwrap();
1695            assert_eq!(actual_response, expected_response);
1696        });
1697    }
1698
1699    #[test]
1700    fn withdraw_history_optional_params_success() {
1701        TOKIO_SHARED_RT.block_on(async {
1702            let client = MockCapitalApiClient { force_error: false };
1703
1704            let params = WithdrawHistoryParams::builder().coin("BTC".to_string()).withdraw_order_id("1".to_string()).status(0).offset(0).limit(1000).id_list("id_list_example".to_string()).start_time(1623319461670).end_time(1641782889000).recv_window(5000).build().unwrap();
1705
1706            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"}]"#).unwrap_or_else(|_| serde_json::json!({}));
1707            let expected_response : Vec<models::WithdrawHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::WithdrawHistoryResponseInner>");
1708
1709            let resp = client.withdraw_history(params).await.expect("Expected a response");
1710            let data_future = resp.data();
1711            let actual_response = data_future.await.unwrap();
1712            assert_eq!(actual_response, expected_response);
1713        });
1714    }
1715
1716    #[test]
1717    fn withdraw_history_response_error() {
1718        TOKIO_SHARED_RT.block_on(async {
1719            let client = MockCapitalApiClient { force_error: true };
1720
1721            let params = WithdrawHistoryParams::builder().build().unwrap();
1722
1723            match client.withdraw_history(params).await {
1724                Ok(_) => panic!("Expected an error"),
1725                Err(err) => {
1726                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
1727                }
1728            }
1729        });
1730    }
1731}