Skip to main content

binance_sdk/crypto_loan/rest_api/apis/
stable_rate_api.rs

1/*
2 * Crypto Loan REST API
3 *
4 * Access Binance Crypto Loans to query assets, subscribe to loans, and manage loan positions.
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::crypto_loan::rest_api::models;
29
30const HAS_TIME_UNIT: bool = false;
31
32#[async_trait]
33pub trait StableRateApi: Send + Sync {
34    async fn get_crypto_loans_income_history(
35        &self,
36        params: GetCryptoLoansIncomeHistoryParams,
37    ) -> anyhow::Result<RestApiResponse<Vec<models::GetCryptoLoansIncomeHistoryResponseInner>>>;
38    async fn get_loan_borrow_history(
39        &self,
40        params: GetLoanBorrowHistoryParams,
41    ) -> anyhow::Result<RestApiResponse<models::GetLoanBorrowHistoryResponse>>;
42    async fn get_loan_ltv_adjustment_history(
43        &self,
44        params: GetLoanLtvAdjustmentHistoryParams,
45    ) -> anyhow::Result<RestApiResponse<models::GetLoanLtvAdjustmentHistoryResponse>>;
46    async fn get_loan_repayment_history(
47        &self,
48        params: GetLoanRepaymentHistoryParams,
49    ) -> anyhow::Result<RestApiResponse<models::GetLoanRepaymentHistoryResponse>>;
50}
51
52#[derive(Debug, Clone)]
53pub struct StableRateApiClient {
54    configuration: ConfigurationRestApi,
55}
56
57impl StableRateApiClient {
58    pub fn new(configuration: ConfigurationRestApi) -> Self {
59        Self { configuration }
60    }
61}
62
63#[allow(non_camel_case_types)]
64#[derive(Debug, Clone, Serialize, Deserialize)]
65pub enum GetCryptoLoansIncomeHistoryTypeEnum {
66    #[serde(rename = "borrowIn")]
67    Borrowin,
68    #[serde(rename = "collateralSpent")]
69    Collateralspent,
70    #[serde(rename = "repayAmount")]
71    Repayamount,
72    #[serde(rename = "collateralReturn")]
73    Collateralreturn,
74    #[serde(rename = "addCollateral")]
75    Addcollateral,
76    #[serde(rename = "removeCollateral")]
77    Removecollateral,
78    #[serde(rename = "collateralReturnAfterLiquidation")]
79    Collateralreturnafterliquidation,
80}
81
82impl GetCryptoLoansIncomeHistoryTypeEnum {
83    #[must_use]
84    pub fn as_str(&self) -> &'static str {
85        match self {
86            Self::Borrowin => "borrowIn",
87            Self::Collateralspent => "collateralSpent",
88            Self::Repayamount => "repayAmount",
89            Self::Collateralreturn => "collateralReturn",
90            Self::Addcollateral => "addCollateral",
91            Self::Removecollateral => "removeCollateral",
92            Self::Collateralreturnafterliquidation => "collateralReturnAfterLiquidation",
93        }
94    }
95}
96
97impl std::str::FromStr for GetCryptoLoansIncomeHistoryTypeEnum {
98    type Err = Box<dyn std::error::Error + Send + Sync>;
99
100    fn from_str(s: &str) -> Result<Self, Self::Err> {
101        match s {
102            "borrowIn" => Ok(Self::Borrowin),
103            "collateralSpent" => Ok(Self::Collateralspent),
104            "repayAmount" => Ok(Self::Repayamount),
105            "collateralReturn" => Ok(Self::Collateralreturn),
106            "addCollateral" => Ok(Self::Addcollateral),
107            "removeCollateral" => Ok(Self::Removecollateral),
108            "collateralReturnAfterLiquidation" => Ok(Self::Collateralreturnafterliquidation),
109            other => Err(format!("invalid GetCryptoLoansIncomeHistoryTypeEnum: {}", other).into()),
110        }
111    }
112}
113
114/// Request parameters for the [`get_crypto_loans_income_history`] operation.
115///
116/// This struct holds all of the inputs you can pass when calling
117/// [`get_crypto_loans_income_history`](#method.get_crypto_loans_income_history).
118#[derive(Clone, Debug, Builder, Deserialize, Default)]
119#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
120pub struct GetCryptoLoansIncomeHistoryParams {
121    ///
122    /// The `asset` parameter.
123    ///
124    /// This field is **optional.
125    #[builder(setter(into), default)]
126    #[serde(rename = "asset", default)]
127    pub asset: Option<String>,
128    /// All types will be returned by default.
129    ///
130    /// This field is **optional.
131    #[builder(setter(into), default)]
132    #[serde(rename = "type", default)]
133    pub r#type: Option<GetCryptoLoansIncomeHistoryTypeEnum>,
134    ///
135    /// The `start_time` parameter.
136    ///
137    /// This field is **optional.
138    #[builder(setter(into), default)]
139    #[serde(rename = "startTime", default)]
140    pub start_time: Option<i64>,
141    ///
142    /// The `end_time` parameter.
143    ///
144    /// This field is **optional.
145    #[builder(setter(into), default)]
146    #[serde(rename = "endTime", default)]
147    pub end_time: Option<i64>,
148    /// Number of records to return
149    ///
150    /// This field is **optional.
151    #[builder(setter(into), default)]
152    #[serde(rename = "limit", default)]
153    pub limit: Option<i64>,
154    /// Request validity window in milliseconds
155    ///
156    /// This field is **optional.
157    #[builder(setter(into), default)]
158    #[serde(rename = "recvWindow", default)]
159    pub recv_window: Option<i64>,
160}
161
162impl GetCryptoLoansIncomeHistoryParams {
163    /// Create a builder for [`get_crypto_loans_income_history`].
164    ///
165    #[must_use]
166    pub fn builder() -> GetCryptoLoansIncomeHistoryParamsBuilder {
167        GetCryptoLoansIncomeHistoryParamsBuilder::default()
168    }
169}
170/// Request parameters for the [`get_loan_borrow_history`] operation.
171///
172/// This struct holds all of the inputs you can pass when calling
173/// [`get_loan_borrow_history`](#method.get_loan_borrow_history).
174#[derive(Clone, Debug, Builder, Deserialize, Default)]
175#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
176pub struct GetLoanBorrowHistoryParams {
177    /// orderId in `POST /sapi/v1/loan/borrow`
178    ///
179    /// This field is **optional.
180    #[builder(setter(into), default)]
181    #[serde(rename = "orderId", default)]
182    pub order_id: Option<i64>,
183    ///
184    /// The `loan_coin` parameter.
185    ///
186    /// This field is **optional.
187    #[builder(setter(into), default)]
188    #[serde(rename = "loanCoin", default)]
189    pub loan_coin: Option<String>,
190    ///
191    /// The `collateral_coin` parameter.
192    ///
193    /// This field is **optional.
194    #[builder(setter(into), default)]
195    #[serde(rename = "collateralCoin", default)]
196    pub collateral_coin: Option<String>,
197    ///
198    /// The `start_time` parameter.
199    ///
200    /// This field is **optional.
201    #[builder(setter(into), default)]
202    #[serde(rename = "startTime", default)]
203    pub start_time: Option<i64>,
204    ///
205    /// The `end_time` parameter.
206    ///
207    /// This field is **optional.
208    #[builder(setter(into), default)]
209    #[serde(rename = "endTime", default)]
210    pub end_time: Option<i64>,
211    /// Current querying page
212    ///
213    /// This field is **optional.
214    #[builder(setter(into), default)]
215    #[serde(rename = "current", default)]
216    pub current: Option<i64>,
217    /// Number of records to return
218    ///
219    /// This field is **optional.
220    #[builder(setter(into), default)]
221    #[serde(rename = "limit", default)]
222    pub limit: Option<i64>,
223    /// Request validity window in milliseconds
224    ///
225    /// This field is **optional.
226    #[builder(setter(into), default)]
227    #[serde(rename = "recvWindow", default)]
228    pub recv_window: Option<i64>,
229}
230
231impl GetLoanBorrowHistoryParams {
232    /// Create a builder for [`get_loan_borrow_history`].
233    ///
234    #[must_use]
235    pub fn builder() -> GetLoanBorrowHistoryParamsBuilder {
236        GetLoanBorrowHistoryParamsBuilder::default()
237    }
238}
239/// Request parameters for the [`get_loan_ltv_adjustment_history`] operation.
240///
241/// This struct holds all of the inputs you can pass when calling
242/// [`get_loan_ltv_adjustment_history`](#method.get_loan_ltv_adjustment_history).
243#[derive(Clone, Debug, Builder, Deserialize, Default)]
244#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
245pub struct GetLoanLtvAdjustmentHistoryParams {
246    /// orderId in `POST /sapi/v1/loan/borrow`
247    ///
248    /// This field is **optional.
249    #[builder(setter(into), default)]
250    #[serde(rename = "orderId", default)]
251    pub order_id: Option<i64>,
252    ///
253    /// The `loan_coin` parameter.
254    ///
255    /// This field is **optional.
256    #[builder(setter(into), default)]
257    #[serde(rename = "loanCoin", default)]
258    pub loan_coin: Option<String>,
259    ///
260    /// The `collateral_coin` parameter.
261    ///
262    /// This field is **optional.
263    #[builder(setter(into), default)]
264    #[serde(rename = "collateralCoin", default)]
265    pub collateral_coin: Option<String>,
266    ///
267    /// The `start_time` parameter.
268    ///
269    /// This field is **optional.
270    #[builder(setter(into), default)]
271    #[serde(rename = "startTime", default)]
272    pub start_time: Option<i64>,
273    ///
274    /// The `end_time` parameter.
275    ///
276    /// This field is **optional.
277    #[builder(setter(into), default)]
278    #[serde(rename = "endTime", default)]
279    pub end_time: Option<i64>,
280    /// Current querying page
281    ///
282    /// This field is **optional.
283    #[builder(setter(into), default)]
284    #[serde(rename = "current", default)]
285    pub current: Option<i64>,
286    /// Number of records to return
287    ///
288    /// This field is **optional.
289    #[builder(setter(into), default)]
290    #[serde(rename = "limit", default)]
291    pub limit: Option<i64>,
292    /// Request validity window in milliseconds
293    ///
294    /// This field is **optional.
295    #[builder(setter(into), default)]
296    #[serde(rename = "recvWindow", default)]
297    pub recv_window: Option<i64>,
298}
299
300impl GetLoanLtvAdjustmentHistoryParams {
301    /// Create a builder for [`get_loan_ltv_adjustment_history`].
302    ///
303    #[must_use]
304    pub fn builder() -> GetLoanLtvAdjustmentHistoryParamsBuilder {
305        GetLoanLtvAdjustmentHistoryParamsBuilder::default()
306    }
307}
308/// Request parameters for the [`get_loan_repayment_history`] operation.
309///
310/// This struct holds all of the inputs you can pass when calling
311/// [`get_loan_repayment_history`](#method.get_loan_repayment_history).
312#[derive(Clone, Debug, Builder, Deserialize, Default)]
313#[builder(pattern = "owned", build_fn(error = "ParamBuildError"))]
314pub struct GetLoanRepaymentHistoryParams {
315    /// orderId in `POST /sapi/v1/loan/borrow`
316    ///
317    /// This field is **optional.
318    #[builder(setter(into), default)]
319    #[serde(rename = "orderId", default)]
320    pub order_id: Option<i64>,
321    ///
322    /// The `loan_coin` parameter.
323    ///
324    /// This field is **optional.
325    #[builder(setter(into), default)]
326    #[serde(rename = "loanCoin", default)]
327    pub loan_coin: Option<String>,
328    ///
329    /// The `collateral_coin` parameter.
330    ///
331    /// This field is **optional.
332    #[builder(setter(into), default)]
333    #[serde(rename = "collateralCoin", default)]
334    pub collateral_coin: Option<String>,
335    ///
336    /// The `start_time` parameter.
337    ///
338    /// This field is **optional.
339    #[builder(setter(into), default)]
340    #[serde(rename = "startTime", default)]
341    pub start_time: Option<i64>,
342    ///
343    /// The `end_time` parameter.
344    ///
345    /// This field is **optional.
346    #[builder(setter(into), default)]
347    #[serde(rename = "endTime", default)]
348    pub end_time: Option<i64>,
349    /// Current querying page
350    ///
351    /// This field is **optional.
352    #[builder(setter(into), default)]
353    #[serde(rename = "current", default)]
354    pub current: Option<i64>,
355    /// Number of records to return
356    ///
357    /// This field is **optional.
358    #[builder(setter(into), default)]
359    #[serde(rename = "limit", default)]
360    pub limit: Option<i64>,
361    /// Request validity window in milliseconds
362    ///
363    /// This field is **optional.
364    #[builder(setter(into), default)]
365    #[serde(rename = "recvWindow", default)]
366    pub recv_window: Option<i64>,
367}
368
369impl GetLoanRepaymentHistoryParams {
370    /// Create a builder for [`get_loan_repayment_history`].
371    ///
372    #[must_use]
373    pub fn builder() -> GetLoanRepaymentHistoryParamsBuilder {
374        GetLoanRepaymentHistoryParamsBuilder::default()
375    }
376}
377
378#[async_trait]
379impl StableRateApi for StableRateApiClient {
380    async fn get_crypto_loans_income_history(
381        &self,
382        params: GetCryptoLoansIncomeHistoryParams,
383    ) -> anyhow::Result<RestApiResponse<Vec<models::GetCryptoLoansIncomeHistoryResponseInner>>>
384    {
385        let GetCryptoLoansIncomeHistoryParams {
386            asset,
387            r#type,
388            start_time,
389            end_time,
390            limit,
391            recv_window,
392        } = params;
393
394        let mut query_params = BTreeMap::new();
395        let body_params = BTreeMap::new();
396
397        if let Some(rw) = asset {
398            query_params.insert("asset".to_string(), json!(rw));
399        }
400
401        if let Some(rw) = r#type {
402            query_params.insert("type".to_string(), json!(rw));
403        }
404
405        if let Some(rw) = start_time {
406            query_params.insert("startTime".to_string(), json!(rw));
407        }
408
409        if let Some(rw) = end_time {
410            query_params.insert("endTime".to_string(), json!(rw));
411        }
412
413        if let Some(rw) = limit {
414            query_params.insert("limit".to_string(), json!(rw));
415        }
416
417        if let Some(rw) = recv_window {
418            query_params.insert("recvWindow".to_string(), json!(rw));
419        }
420
421        send_request::<Vec<models::GetCryptoLoansIncomeHistoryResponseInner>>(
422            &self.configuration,
423            "/sapi/v1/loan/income",
424            reqwest::Method::GET,
425            query_params,
426            body_params,
427            if HAS_TIME_UNIT {
428                self.configuration.time_unit
429            } else {
430                None
431            },
432            true,
433        )
434        .await
435    }
436
437    async fn get_loan_borrow_history(
438        &self,
439        params: GetLoanBorrowHistoryParams,
440    ) -> anyhow::Result<RestApiResponse<models::GetLoanBorrowHistoryResponse>> {
441        let GetLoanBorrowHistoryParams {
442            order_id,
443            loan_coin,
444            collateral_coin,
445            start_time,
446            end_time,
447            current,
448            limit,
449            recv_window,
450        } = params;
451
452        let mut query_params = BTreeMap::new();
453        let body_params = BTreeMap::new();
454
455        if let Some(rw) = order_id {
456            query_params.insert("orderId".to_string(), json!(rw));
457        }
458
459        if let Some(rw) = loan_coin {
460            query_params.insert("loanCoin".to_string(), json!(rw));
461        }
462
463        if let Some(rw) = collateral_coin {
464            query_params.insert("collateralCoin".to_string(), json!(rw));
465        }
466
467        if let Some(rw) = start_time {
468            query_params.insert("startTime".to_string(), json!(rw));
469        }
470
471        if let Some(rw) = end_time {
472            query_params.insert("endTime".to_string(), json!(rw));
473        }
474
475        if let Some(rw) = current {
476            query_params.insert("current".to_string(), json!(rw));
477        }
478
479        if let Some(rw) = limit {
480            query_params.insert("limit".to_string(), json!(rw));
481        }
482
483        if let Some(rw) = recv_window {
484            query_params.insert("recvWindow".to_string(), json!(rw));
485        }
486
487        send_request::<models::GetLoanBorrowHistoryResponse>(
488            &self.configuration,
489            "/sapi/v1/loan/borrow/history",
490            reqwest::Method::GET,
491            query_params,
492            body_params,
493            if HAS_TIME_UNIT {
494                self.configuration.time_unit
495            } else {
496                None
497            },
498            true,
499        )
500        .await
501    }
502
503    async fn get_loan_ltv_adjustment_history(
504        &self,
505        params: GetLoanLtvAdjustmentHistoryParams,
506    ) -> anyhow::Result<RestApiResponse<models::GetLoanLtvAdjustmentHistoryResponse>> {
507        let GetLoanLtvAdjustmentHistoryParams {
508            order_id,
509            loan_coin,
510            collateral_coin,
511            start_time,
512            end_time,
513            current,
514            limit,
515            recv_window,
516        } = params;
517
518        let mut query_params = BTreeMap::new();
519        let body_params = BTreeMap::new();
520
521        if let Some(rw) = order_id {
522            query_params.insert("orderId".to_string(), json!(rw));
523        }
524
525        if let Some(rw) = loan_coin {
526            query_params.insert("loanCoin".to_string(), json!(rw));
527        }
528
529        if let Some(rw) = collateral_coin {
530            query_params.insert("collateralCoin".to_string(), json!(rw));
531        }
532
533        if let Some(rw) = start_time {
534            query_params.insert("startTime".to_string(), json!(rw));
535        }
536
537        if let Some(rw) = end_time {
538            query_params.insert("endTime".to_string(), json!(rw));
539        }
540
541        if let Some(rw) = current {
542            query_params.insert("current".to_string(), json!(rw));
543        }
544
545        if let Some(rw) = limit {
546            query_params.insert("limit".to_string(), json!(rw));
547        }
548
549        if let Some(rw) = recv_window {
550            query_params.insert("recvWindow".to_string(), json!(rw));
551        }
552
553        send_request::<models::GetLoanLtvAdjustmentHistoryResponse>(
554            &self.configuration,
555            "/sapi/v1/loan/ltv/adjustment/history",
556            reqwest::Method::GET,
557            query_params,
558            body_params,
559            if HAS_TIME_UNIT {
560                self.configuration.time_unit
561            } else {
562                None
563            },
564            true,
565        )
566        .await
567    }
568
569    async fn get_loan_repayment_history(
570        &self,
571        params: GetLoanRepaymentHistoryParams,
572    ) -> anyhow::Result<RestApiResponse<models::GetLoanRepaymentHistoryResponse>> {
573        let GetLoanRepaymentHistoryParams {
574            order_id,
575            loan_coin,
576            collateral_coin,
577            start_time,
578            end_time,
579            current,
580            limit,
581            recv_window,
582        } = params;
583
584        let mut query_params = BTreeMap::new();
585        let body_params = BTreeMap::new();
586
587        if let Some(rw) = order_id {
588            query_params.insert("orderId".to_string(), json!(rw));
589        }
590
591        if let Some(rw) = loan_coin {
592            query_params.insert("loanCoin".to_string(), json!(rw));
593        }
594
595        if let Some(rw) = collateral_coin {
596            query_params.insert("collateralCoin".to_string(), json!(rw));
597        }
598
599        if let Some(rw) = start_time {
600            query_params.insert("startTime".to_string(), json!(rw));
601        }
602
603        if let Some(rw) = end_time {
604            query_params.insert("endTime".to_string(), json!(rw));
605        }
606
607        if let Some(rw) = current {
608            query_params.insert("current".to_string(), json!(rw));
609        }
610
611        if let Some(rw) = limit {
612            query_params.insert("limit".to_string(), json!(rw));
613        }
614
615        if let Some(rw) = recv_window {
616            query_params.insert("recvWindow".to_string(), json!(rw));
617        }
618
619        send_request::<models::GetLoanRepaymentHistoryResponse>(
620            &self.configuration,
621            "/sapi/v1/loan/repay/history",
622            reqwest::Method::GET,
623            query_params,
624            body_params,
625            if HAS_TIME_UNIT {
626                self.configuration.time_unit
627            } else {
628                None
629            },
630            true,
631        )
632        .await
633    }
634}
635
636#[cfg(all(test, feature = "crypto_loan"))]
637mod tests {
638    use super::*;
639    use crate::TOKIO_SHARED_RT;
640    use crate::{errors::ConnectorError, models::DataFuture, models::RestApiRateLimit};
641    use async_trait::async_trait;
642    use std::collections::HashMap;
643
644    struct DummyRestApiResponse<T> {
645        inner: Box<dyn FnOnce() -> DataFuture<Result<T, ConnectorError>> + Send + Sync>,
646        status: u16,
647        headers: HashMap<String, String>,
648        rate_limits: Option<Vec<RestApiRateLimit>>,
649    }
650
651    impl<T> From<DummyRestApiResponse<T>> for RestApiResponse<T> {
652        fn from(dummy: DummyRestApiResponse<T>) -> Self {
653            Self {
654                data_fn: dummy.inner,
655                status: dummy.status,
656                headers: dummy.headers,
657                rate_limits: dummy.rate_limits,
658            }
659        }
660    }
661
662    struct MockStableRateApiClient {
663        force_error: bool,
664    }
665
666    #[async_trait]
667    impl StableRateApi for MockStableRateApiClient {
668        async fn get_crypto_loans_income_history(
669            &self,
670            _params: GetCryptoLoansIncomeHistoryParams,
671        ) -> anyhow::Result<RestApiResponse<Vec<models::GetCryptoLoansIncomeHistoryResponseInner>>>
672        {
673            if self.force_error {
674                return Err(ConnectorError::ConnectorClientError {
675                    msg: "ResponseError".to_string(),
676                    code: None,
677                }
678                .into());
679            }
680
681            let resp_json: Value = serde_json::from_str(r#"[{"asset":"BUSD","type":"borrowIn","amount":"100","timestamp":1633771139847,"tranId":"80423589583"}]"#).unwrap_or_else(|_| serde_json::json!({}));
682            let dummy_response: Vec<models::GetCryptoLoansIncomeHistoryResponseInner> =
683                serde_json::from_value(resp_json.clone()).expect(
684                    "should parse into Vec<models::GetCryptoLoansIncomeHistoryResponseInner>",
685                );
686
687            let dummy = DummyRestApiResponse {
688                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
689                status: 200,
690                headers: HashMap::new(),
691                rate_limits: None,
692            };
693
694            Ok(dummy.into())
695        }
696
697        async fn get_loan_borrow_history(
698            &self,
699            _params: GetLoanBorrowHistoryParams,
700        ) -> anyhow::Result<RestApiResponse<models::GetLoanBorrowHistoryResponse>> {
701            if self.force_error {
702                return Err(ConnectorError::ConnectorClientError {
703                    msg: "ResponseError".to_string(),
704                    code: None,
705                }
706                .into());
707            }
708
709            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","initialLoanAmount":"10000","hourlyInterestRate":"0.000057","loanTerm":"7","collateralCoin":"BNB","initialCollateralAmount":"49.27565492","borrowTime":1575018510000,"status":"Repaid"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
710            let dummy_response: models::GetLoanBorrowHistoryResponse =
711                serde_json::from_value(resp_json.clone())
712                    .expect("should parse into models::GetLoanBorrowHistoryResponse");
713
714            let dummy = DummyRestApiResponse {
715                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
716                status: 200,
717                headers: HashMap::new(),
718                rate_limits: None,
719            };
720
721            Ok(dummy.into())
722        }
723
724        async fn get_loan_ltv_adjustment_history(
725            &self,
726            _params: GetLoanLtvAdjustmentHistoryParams,
727        ) -> anyhow::Result<RestApiResponse<models::GetLoanLtvAdjustmentHistoryResponse>> {
728            if self.force_error {
729                return Err(ConnectorError::ConnectorClientError {
730                    msg: "ResponseError".to_string(),
731                    code: None,
732                }
733                .into());
734            }
735
736            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","collateralCoin":"BNB","direction":"ADDITIONAL","amount":"5.235","preLTV":"0.78","afterLTV":"0.56","adjustTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
737            let dummy_response: models::GetLoanLtvAdjustmentHistoryResponse =
738                serde_json::from_value(resp_json.clone())
739                    .expect("should parse into models::GetLoanLtvAdjustmentHistoryResponse");
740
741            let dummy = DummyRestApiResponse {
742                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
743                status: 200,
744                headers: HashMap::new(),
745                rate_limits: None,
746            };
747
748            Ok(dummy.into())
749        }
750
751        async fn get_loan_repayment_history(
752            &self,
753            _params: GetLoanRepaymentHistoryParams,
754        ) -> anyhow::Result<RestApiResponse<models::GetLoanRepaymentHistoryResponse>> {
755            if self.force_error {
756                return Err(ConnectorError::ConnectorClientError {
757                    msg: "ResponseError".to_string(),
758                    code: None,
759                }
760                .into());
761            }
762
763            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","repayAmount":"10000","collateralCoin":"BNB","collateralUsed":"0","collateralReturn":"49.27565492","repayType":"1","repayStatus":"Repaid","repayTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
764            let dummy_response: models::GetLoanRepaymentHistoryResponse =
765                serde_json::from_value(resp_json.clone())
766                    .expect("should parse into models::GetLoanRepaymentHistoryResponse");
767
768            let dummy = DummyRestApiResponse {
769                inner: Box::new(move || Box::pin(async move { Ok(dummy_response) })),
770                status: 200,
771                headers: HashMap::new(),
772                rate_limits: None,
773            };
774
775            Ok(dummy.into())
776        }
777    }
778
779    #[test]
780    fn get_crypto_loans_income_history_required_params_success() {
781        TOKIO_SHARED_RT.block_on(async {
782            let client = MockStableRateApiClient { force_error: false };
783
784            let params = GetCryptoLoansIncomeHistoryParams::builder().build().unwrap();
785
786            let resp_json: Value = serde_json::from_str(r#"[{"asset":"BUSD","type":"borrowIn","amount":"100","timestamp":1633771139847,"tranId":"80423589583"}]"#).unwrap_or_else(|_| serde_json::json!({}));
787            let expected_response : Vec<models::GetCryptoLoansIncomeHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetCryptoLoansIncomeHistoryResponseInner>");
788
789            let resp = client.get_crypto_loans_income_history(params).await.expect("Expected a response");
790            let data_future = resp.data();
791            let actual_response = data_future.await.unwrap();
792            assert_eq!(actual_response, expected_response);
793        });
794    }
795
796    #[test]
797    fn get_crypto_loans_income_history_optional_params_success() {
798        TOKIO_SHARED_RT.block_on(async {
799            let client = MockStableRateApiClient { force_error: false };
800
801            let params = GetCryptoLoansIncomeHistoryParams::builder().asset("BUSD".to_string()).r#type(GetCryptoLoansIncomeHistoryTypeEnum::Borrowin).start_time(1623319461670).end_time(1641782889000).limit(10).recv_window(5000).build().unwrap();
802
803            let resp_json: Value = serde_json::from_str(r#"[{"asset":"BUSD","type":"borrowIn","amount":"100","timestamp":1633771139847,"tranId":"80423589583"}]"#).unwrap_or_else(|_| serde_json::json!({}));
804            let expected_response : Vec<models::GetCryptoLoansIncomeHistoryResponseInner> = serde_json::from_value(resp_json.clone()).expect("should parse into Vec<models::GetCryptoLoansIncomeHistoryResponseInner>");
805
806            let resp = client.get_crypto_loans_income_history(params).await.expect("Expected a response");
807            let data_future = resp.data();
808            let actual_response = data_future.await.unwrap();
809            assert_eq!(actual_response, expected_response);
810        });
811    }
812
813    #[test]
814    fn get_crypto_loans_income_history_response_error() {
815        TOKIO_SHARED_RT.block_on(async {
816            let client = MockStableRateApiClient { force_error: true };
817
818            let params = GetCryptoLoansIncomeHistoryParams::builder()
819                .build()
820                .unwrap();
821
822            match client.get_crypto_loans_income_history(params).await {
823                Ok(_) => panic!("Expected an error"),
824                Err(err) => {
825                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
826                }
827            }
828        });
829    }
830
831    #[test]
832    fn get_loan_borrow_history_required_params_success() {
833        TOKIO_SHARED_RT.block_on(async {
834            let client = MockStableRateApiClient { force_error: false };
835
836            let params = GetLoanBorrowHistoryParams::builder().build().unwrap();
837
838            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","initialLoanAmount":"10000","hourlyInterestRate":"0.000057","loanTerm":"7","collateralCoin":"BNB","initialCollateralAmount":"49.27565492","borrowTime":1575018510000,"status":"Repaid"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
839            let expected_response : models::GetLoanBorrowHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanBorrowHistoryResponse");
840
841            let resp = client.get_loan_borrow_history(params).await.expect("Expected a response");
842            let data_future = resp.data();
843            let actual_response = data_future.await.unwrap();
844            assert_eq!(actual_response, expected_response);
845        });
846    }
847
848    #[test]
849    fn get_loan_borrow_history_optional_params_success() {
850        TOKIO_SHARED_RT.block_on(async {
851            let client = MockStableRateApiClient { force_error: false };
852
853            let params = GetLoanBorrowHistoryParams::builder().order_id(1).loan_coin("BUSD".to_string()).collateral_coin("BNB".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).limit(10).recv_window(5000).build().unwrap();
854
855            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"orderId":100000001,"loanCoin":"BUSD","initialLoanAmount":"10000","hourlyInterestRate":"0.000057","loanTerm":"7","collateralCoin":"BNB","initialCollateralAmount":"49.27565492","borrowTime":1575018510000,"status":"Repaid"}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
856            let expected_response : models::GetLoanBorrowHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanBorrowHistoryResponse");
857
858            let resp = client.get_loan_borrow_history(params).await.expect("Expected a response");
859            let data_future = resp.data();
860            let actual_response = data_future.await.unwrap();
861            assert_eq!(actual_response, expected_response);
862        });
863    }
864
865    #[test]
866    fn get_loan_borrow_history_response_error() {
867        TOKIO_SHARED_RT.block_on(async {
868            let client = MockStableRateApiClient { force_error: true };
869
870            let params = GetLoanBorrowHistoryParams::builder().build().unwrap();
871
872            match client.get_loan_borrow_history(params).await {
873                Ok(_) => panic!("Expected an error"),
874                Err(err) => {
875                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
876                }
877            }
878        });
879    }
880
881    #[test]
882    fn get_loan_ltv_adjustment_history_required_params_success() {
883        TOKIO_SHARED_RT.block_on(async {
884            let client = MockStableRateApiClient { force_error: false };
885
886            let params = GetLoanLtvAdjustmentHistoryParams::builder().build().unwrap();
887
888            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","collateralCoin":"BNB","direction":"ADDITIONAL","amount":"5.235","preLTV":"0.78","afterLTV":"0.56","adjustTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
889            let expected_response : models::GetLoanLtvAdjustmentHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanLtvAdjustmentHistoryResponse");
890
891            let resp = client.get_loan_ltv_adjustment_history(params).await.expect("Expected a response");
892            let data_future = resp.data();
893            let actual_response = data_future.await.unwrap();
894            assert_eq!(actual_response, expected_response);
895        });
896    }
897
898    #[test]
899    fn get_loan_ltv_adjustment_history_optional_params_success() {
900        TOKIO_SHARED_RT.block_on(async {
901            let client = MockStableRateApiClient { force_error: false };
902
903            let params = GetLoanLtvAdjustmentHistoryParams::builder().order_id(1).loan_coin("BUSD".to_string()).collateral_coin("BNB".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).limit(10).recv_window(5000).build().unwrap();
904
905            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","collateralCoin":"BNB","direction":"ADDITIONAL","amount":"5.235","preLTV":"0.78","afterLTV":"0.56","adjustTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
906            let expected_response : models::GetLoanLtvAdjustmentHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanLtvAdjustmentHistoryResponse");
907
908            let resp = client.get_loan_ltv_adjustment_history(params).await.expect("Expected a response");
909            let data_future = resp.data();
910            let actual_response = data_future.await.unwrap();
911            assert_eq!(actual_response, expected_response);
912        });
913    }
914
915    #[test]
916    fn get_loan_ltv_adjustment_history_response_error() {
917        TOKIO_SHARED_RT.block_on(async {
918            let client = MockStableRateApiClient { force_error: true };
919
920            let params = GetLoanLtvAdjustmentHistoryParams::builder()
921                .build()
922                .unwrap();
923
924            match client.get_loan_ltv_adjustment_history(params).await {
925                Ok(_) => panic!("Expected an error"),
926                Err(err) => {
927                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
928                }
929            }
930        });
931    }
932
933    #[test]
934    fn get_loan_repayment_history_required_params_success() {
935        TOKIO_SHARED_RT.block_on(async {
936            let client = MockStableRateApiClient { force_error: false };
937
938            let params = GetLoanRepaymentHistoryParams::builder().build().unwrap();
939
940            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","repayAmount":"10000","collateralCoin":"BNB","collateralUsed":"0","collateralReturn":"49.27565492","repayType":"1","repayStatus":"Repaid","repayTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
941            let expected_response : models::GetLoanRepaymentHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanRepaymentHistoryResponse");
942
943            let resp = client.get_loan_repayment_history(params).await.expect("Expected a response");
944            let data_future = resp.data();
945            let actual_response = data_future.await.unwrap();
946            assert_eq!(actual_response, expected_response);
947        });
948    }
949
950    #[test]
951    fn get_loan_repayment_history_optional_params_success() {
952        TOKIO_SHARED_RT.block_on(async {
953            let client = MockStableRateApiClient { force_error: false };
954
955            let params = GetLoanRepaymentHistoryParams::builder().order_id(1).loan_coin("BUSD".to_string()).collateral_coin("BNB".to_string()).start_time(1623319461670).end_time(1641782889000).current(1).limit(10).recv_window(5000).build().unwrap();
956
957            let resp_json: Value = serde_json::from_str(r#"{"rows":[{"loanCoin":"BUSD","repayAmount":"10000","collateralCoin":"BNB","collateralUsed":"0","collateralReturn":"49.27565492","repayType":"1","repayStatus":"Repaid","repayTime":1575018510000,"orderId":756783308056935400}],"total":1}"#).unwrap_or_else(|_| serde_json::json!({}));
958            let expected_response : models::GetLoanRepaymentHistoryResponse = serde_json::from_value(resp_json.clone()).expect("should parse into models::GetLoanRepaymentHistoryResponse");
959
960            let resp = client.get_loan_repayment_history(params).await.expect("Expected a response");
961            let data_future = resp.data();
962            let actual_response = data_future.await.unwrap();
963            assert_eq!(actual_response, expected_response);
964        });
965    }
966
967    #[test]
968    fn get_loan_repayment_history_response_error() {
969        TOKIO_SHARED_RT.block_on(async {
970            let client = MockStableRateApiClient { force_error: true };
971
972            let params = GetLoanRepaymentHistoryParams::builder().build().unwrap();
973
974            match client.get_loan_repayment_history(params).await {
975                Ok(_) => panic!("Expected an error"),
976                Err(err) => {
977                    assert_eq!(err.to_string(), "Connector client error: ResponseError");
978                }
979            }
980        });
981    }
982}