Skip to main content

rust_okx/api/finance/requests/
flexible_loan.rs

1use std::borrow::Cow;
2
3use serde::Serialize;
4
5/// Query parameters for `GET /api/v5/finance/flexible-loan/collateral-assets`.
6#[derive(Debug, Clone, Default, Serialize)]
7pub struct FlexibleLoanCollateralAssetsRequest<'a> {
8    #[serde(skip_serializing_if = "Option::is_none")]
9    ccy: Option<Cow<'a, str>>,
10    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
11    ord_id: Option<Cow<'a, str>>,
12}
13
14impl<'a> FlexibleLoanCollateralAssetsRequest<'a> {
15    /// Create an unfiltered collateral-assets query.
16    pub fn new() -> Self {
17        Self::default()
18    }
19
20    /// Filter by collateral currency.
21    pub fn currency(mut self, value: impl Into<Cow<'a, str>>) -> Self {
22        self.ccy = Some(value.into());
23        self
24    }
25
26    /// Scope the query to one flexible-loan order.
27    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
28        self.ord_id = Some(value.into());
29        self
30    }
31}
32
33/// Request body for `POST /api/v5/finance/flexible-loan/max-loan`.
34#[derive(Debug, Clone, Serialize)]
35pub struct FlexibleLoanMaxLoanRequest<'a> {
36    #[serde(rename = "borrowCcy")]
37    borrow_ccy: Cow<'a, str>,
38    #[serde(rename = "collateralCcy", skip_serializing_if = "Option::is_none")]
39    collateral_ccy: Option<Cow<'a, str>>,
40    #[serde(rename = "collateralAmt", skip_serializing_if = "Option::is_none")]
41    collateral_amt: Option<Cow<'a, str>>,
42    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
43    ord_id: Option<Cow<'a, str>>,
44}
45
46impl<'a> FlexibleLoanMaxLoanRequest<'a> {
47    /// Create a maximum-loan estimate for a borrowing currency.
48    pub fn new(borrow_ccy: impl Into<Cow<'a, str>>) -> Self {
49        Self {
50            borrow_ccy: borrow_ccy.into(),
51            collateral_ccy: None,
52            collateral_amt: None,
53            ord_id: None,
54        }
55    }
56
57    /// Estimate using a collateral currency and amount.
58    pub fn collateral(
59        mut self,
60        ccy: impl Into<Cow<'a, str>>,
61        amt: impl Into<Cow<'a, str>>,
62    ) -> Self {
63        self.collateral_ccy = Some(ccy.into());
64        self.collateral_amt = Some(amt.into());
65        self
66    }
67
68    /// Estimate additional borrowing for one existing flexible-loan order.
69    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
70        self.ord_id = Some(value.into());
71        self
72    }
73}
74
75/// Query parameters for `GET /api/v5/finance/flexible-loan/max-collateral-redeem-amount`.
76#[derive(Debug, Clone, Default, Serialize)]
77pub struct FlexibleLoanMaxRedeemRequest<'a> {
78    #[serde(skip_serializing_if = "Option::is_none")]
79    ccy: Option<Cow<'a, str>>,
80    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
81    ord_id: Option<Cow<'a, str>>,
82}
83
84impl<'a> FlexibleLoanMaxRedeemRequest<'a> {
85    /// Create an unfiltered maximum-redeem query.
86    pub fn new() -> Self {
87        Self::default()
88    }
89
90    /// Filter by collateral currency.
91    pub fn currency(mut self, value: impl Into<Cow<'a, str>>) -> Self {
92        self.ccy = Some(value.into());
93        self
94    }
95
96    /// Scope the calculation to one flexible-loan order.
97    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
98        self.ord_id = Some(value.into());
99        self
100    }
101}
102
103/// Request body for `POST /api/v5/finance/flexible-loan/adjust-collateral`.
104#[derive(Debug, Clone, Serialize)]
105pub struct FlexibleLoanAdjustCollateralRequest<'a> {
106    #[serde(rename = "ordId")]
107    ord_id: Cow<'a, str>,
108    #[serde(rename = "collateralCcy")]
109    collateral_ccy: Cow<'a, str>,
110    amt: Cow<'a, str>,
111    #[serde(rename = "type")]
112    adjustment_type: Cow<'a, str>,
113}
114
115impl<'a> FlexibleLoanAdjustCollateralRequest<'a> {
116    /// Create a collateral adjustment; `type` must be `add` or `reduce`.
117    pub fn new(
118        ord_id: impl Into<Cow<'a, str>>,
119        collateral_ccy: impl Into<Cow<'a, str>>,
120        amt: impl Into<Cow<'a, str>>,
121        adjustment_type: impl Into<Cow<'a, str>>,
122    ) -> Self {
123        Self {
124            ord_id: ord_id.into(),
125            collateral_ccy: collateral_ccy.into(),
126            amt: amt.into(),
127            adjustment_type: adjustment_type.into(),
128        }
129    }
130}
131
132/// Query parameters for `GET /api/v5/finance/flexible-loan/loan-info`.
133#[derive(Debug, Clone, Default, Serialize)]
134pub struct FlexibleLoanInfoRequest<'a> {
135    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
136    ord_id: Option<Cow<'a, str>>,
137}
138
139impl<'a> FlexibleLoanInfoRequest<'a> {
140    /// Create a query for all current flexible-loan orders.
141    pub fn new() -> Self {
142        Self::default()
143    }
144
145    /// Restrict the result to one flexible-loan order.
146    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
147        self.ord_id = Some(value.into());
148        self
149    }
150}
151
152/// Query parameters for `GET /api/v5/finance/flexible-loan/loan-history`.
153#[derive(Debug, Clone, Default, Serialize)]
154pub struct FlexibleLoanHistoryRequest<'a> {
155    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
156    ord_id: Option<Cow<'a, str>>,
157    #[serde(skip_serializing_if = "Option::is_none")]
158    after: Option<Cow<'a, str>>,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    before: Option<Cow<'a, str>>,
161    #[serde(skip_serializing_if = "Option::is_none")]
162    limit: Option<u32>,
163}
164
165impl<'a> FlexibleLoanHistoryRequest<'a> {
166    /// Create an unfiltered loan-history query.
167    pub fn new() -> Self {
168        Self::default()
169    }
170
171    /// Restrict the result to one flexible-loan order.
172    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
173        self.ord_id = Some(value.into());
174        self
175    }
176
177    /// Set the endpoint's `after` cursor.
178    pub fn after(mut self, value: impl Into<Cow<'a, str>>) -> Self {
179        self.after = Some(value.into());
180        self
181    }
182
183    /// Set the endpoint's `before` cursor.
184    pub fn before(mut self, value: impl Into<Cow<'a, str>>) -> Self {
185        self.before = Some(value.into());
186        self
187    }
188
189    /// Set the result count from 1 through 100.
190    pub fn limit(mut self, value: u32) -> Self {
191        self.limit = Some(value);
192        self
193    }
194}
195
196/// Query parameters for `GET /api/v5/finance/flexible-loan/interest-accrued`.
197#[derive(Debug, Clone, Default, Serialize)]
198pub struct FlexibleLoanInterestAccruedRequest<'a> {
199    #[serde(rename = "ordId", skip_serializing_if = "Option::is_none")]
200    ord_id: Option<Cow<'a, str>>,
201    #[serde(skip_serializing_if = "Option::is_none")]
202    ccy: Option<Cow<'a, str>>,
203    #[serde(skip_serializing_if = "Option::is_none")]
204    after: Option<Cow<'a, str>>,
205    #[serde(skip_serializing_if = "Option::is_none")]
206    before: Option<Cow<'a, str>>,
207    #[serde(skip_serializing_if = "Option::is_none")]
208    limit: Option<u32>,
209}
210
211impl<'a> FlexibleLoanInterestAccruedRequest<'a> {
212    /// Create an unfiltered accrued-interest query.
213    pub fn new() -> Self {
214        Self::default()
215    }
216
217    /// Restrict the result to one flexible-loan order.
218    pub fn order_id(mut self, value: impl Into<Cow<'a, str>>) -> Self {
219        self.ord_id = Some(value.into());
220        self
221    }
222
223    /// Restrict the result to one currency.
224    pub fn currency(mut self, value: impl Into<Cow<'a, str>>) -> Self {
225        self.ccy = Some(value.into());
226        self
227    }
228
229    /// Set the endpoint's `after` cursor.
230    pub fn after(mut self, value: impl Into<Cow<'a, str>>) -> Self {
231        self.after = Some(value.into());
232        self
233    }
234
235    /// Set the endpoint's `before` cursor.
236    pub fn before(mut self, value: impl Into<Cow<'a, str>>) -> Self {
237        self.before = Some(value.into());
238        self
239    }
240
241    /// Set the result count from 1 through 100.
242    pub fn limit(mut self, value: u32) -> Self {
243        self.limit = Some(value);
244        self
245    }
246}
247
248#[cfg(test)]
249mod tests {
250    use super::*;
251
252    #[test]
253    fn max_loan_requires_complete_collateral_pair() {
254        let request = FlexibleLoanMaxLoanRequest::new("USDT");
255
256        let mut value = serde_json::to_value(request).unwrap();
257        value["collateralCcy"] = serde_json::Value::String("BTC".into());
258        assert_eq!(value["borrowCcy"], "USDT");
259    }
260}