Skip to main content

rust_okx/api/finance/
api.rs

1use crate::api::finance::internal::CancelRedeemBody;
2use crate::client::OkxClient;
3use crate::error::Error;
4use crate::transport::Transport;
5
6use super::endpoints::*;
7use super::internal::{AmountBody, DaysQuery, NoParams, SetLendingRateBody, optional_ccy};
8use super::requests::*;
9use super::responses::*;
10/// Accessor for OKX finance endpoint groups.
11///
12/// Obtain one via [`OkxClient::finance`](crate::OkxClient::finance).
13pub struct Finance<'a, T> {
14    client: &'a OkxClient<T>,
15}
16
17impl<'a, T: Transport> Finance<'a, T> {
18    pub(crate) fn new(client: &'a OkxClient<T>) -> Self {
19        Self { client }
20    }
21
22    /// Access Savings endpoints.
23    pub fn savings(&self) -> Savings<'_, T> {
24        Savings {
25            client: self.client,
26        }
27    }
28
29    /// Access Staking/DeFi endpoints.
30    pub fn staking_defi(&self) -> StakingDefi<'_, T> {
31        StakingDefi {
32            client: self.client,
33        }
34    }
35
36    /// Access ETH staking endpoints.
37    pub fn eth_staking(&self) -> EthStaking<'_, T> {
38        EthStaking {
39            client: self.client,
40        }
41    }
42
43    /// Access SOL staking endpoints.
44    pub fn sol_staking(&self) -> SolStaking<'_, T> {
45        SolStaking {
46            client: self.client,
47        }
48    }
49
50    /// Access Flexible Loan endpoints.
51    pub fn flexible_loan(&self) -> FlexibleLoan<'_, T> {
52        FlexibleLoan {
53            client: self.client,
54        }
55    }
56}
57
58/// Accessor for Savings endpoints.
59pub struct Savings<'a, T> {
60    client: &'a OkxClient<T>,
61}
62
63impl<T: Transport> Savings<'_, T> {
64    /// Retrieve savings balances.
65    ///
66    /// `GET /api/v5/finance/savings/balance`. Authenticated.
67    ///
68    /// # Errors
69    ///
70    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero
71    /// OKX code, or transport/decode errors.
72    pub async fn get_saving_balance(&self, ccy: Option<&str>) -> Result<Vec<SavingBalance>, Error> {
73        let query = optional_ccy(ccy);
74        self.client.get(SAVINGS_BALANCE, &query, true).await
75    }
76
77    /// Purchase or redeem savings.
78    ///
79    /// `POST /api/v5/finance/savings/purchase-redempt`. Authenticated.
80    ///
81    /// # Errors
82    ///
83    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero
84    /// OKX code, or transport/decode errors.
85    pub async fn purchase_redemption(
86        &self,
87        request: &SavingsPurchaseRedemptionRequest,
88    ) -> Result<Vec<SavingsPurchaseRedemptionResult>, Error> {
89        self.client
90            .post(SAVINGS_PURCHASE_REDEMPT, request, true)
91            .await
92    }
93
94    /// Set the savings lending rate.
95    ///
96    /// `POST /api/v5/finance/savings/set-lending-rate`. Authenticated.
97    ///
98    /// # Errors
99    ///
100    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero
101    /// OKX code, or transport/decode errors.
102    pub async fn set_lending_rate(
103        &self,
104        ccy: &str,
105        rate: &str,
106    ) -> Result<Vec<SetLendingRateResult>, Error> {
107        let body = SetLendingRateBody { ccy, rate };
108        self.client
109            .post(SAVINGS_SET_LENDING_RATE, &body, true)
110            .await
111    }
112
113    /// Retrieve lending history.
114    ///
115    /// `GET /api/v5/finance/savings/lending-history`. Authenticated.
116    ///
117    /// # Errors
118    ///
119    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero
120    /// OKX code, or transport/decode errors.
121    pub async fn get_lending_history(
122        &self,
123        request: &FinanceHistoryRequest,
124    ) -> Result<Vec<LendingHistory>, Error> {
125        self.client
126            .get(SAVINGS_LENDING_HISTORY, request, true)
127            .await
128    }
129
130    /// Retrieve public borrow history.
131    ///
132    /// `GET /api/v5/finance/savings/lending-rate-history`. Public.
133    ///
134    /// # Errors
135    ///
136    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
137    pub async fn get_public_borrow_history(
138        &self,
139        request: &FinanceHistoryRequest,
140    ) -> Result<Vec<PublicBorrowHistory>, Error> {
141        self.client
142            .get(SAVINGS_PUBLIC_BORROW_HISTORY, request, false)
143            .await
144    }
145
146    /// Retrieve public borrow info.
147    ///
148    /// `GET /api/v5/finance/savings/lending-rate-summary`. Public.
149    ///
150    /// # Errors
151    ///
152    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
153    pub async fn get_public_borrow_info(
154        &self,
155        ccy: Option<&str>,
156    ) -> Result<Vec<PublicBorrowInfo>, Error> {
157        let query = optional_ccy(ccy);
158        self.client
159            .get(SAVINGS_PUBLIC_BORROW_INFO, &query, false)
160            .await
161    }
162}
163
164/// Accessor for Staking/DeFi endpoints.
165pub struct StakingDefi<'a, T> {
166    client: &'a OkxClient<T>,
167}
168
169impl<T: Transport> StakingDefi<'_, T> {
170    /// Retrieve Staking/DeFi offers.
171    ///
172    /// `GET /api/v5/finance/staking-defi/offers`. Authenticated.
173    ///
174    /// # Errors
175    ///
176    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
177    pub async fn get_offers(
178        &self,
179        request: &StakingDefiOffersRequest,
180    ) -> Result<Vec<StakingDefiOffer>, Error> {
181        self.client.get(STAKING_DEFI_OFFERS, request, true).await
182    }
183
184    /// Purchase a Staking/DeFi product.
185    ///
186    /// `POST /api/v5/finance/staking-defi/purchase`. Authenticated.
187    ///
188    /// # Errors
189    ///
190    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
191    pub async fn purchase(
192        &self,
193        request: &StakingDefiPurchaseRequest,
194    ) -> Result<Vec<StakingDefiOrder>, Error> {
195        self.client.post(STAKING_DEFI_PURCHASE, request, true).await
196    }
197
198    /// Redeem a Staking/DeFi order.
199    ///
200    /// `POST /api/v5/finance/staking-defi/redeem`. Authenticated.
201    ///
202    /// # Errors
203    ///
204    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
205    pub async fn redeem(
206        &self,
207        request: &StakingDefiRedeemRequest,
208    ) -> Result<Vec<StakingDefiOrder>, Error> {
209        self.client.post(STAKING_DEFI_REDEEM, request, true).await
210    }
211
212    /// Cancel a Staking/DeFi order.
213    ///
214    /// `POST /api/v5/finance/staking-defi/cancel`. Authenticated.
215    ///
216    /// # Errors
217    ///
218    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
219    pub async fn cancel(
220        &self,
221        request: &StakingDefiCancelRequest,
222    ) -> Result<Vec<StakingDefiOrder>, Error> {
223        self.client.post(STAKING_DEFI_CANCEL, request, true).await
224    }
225
226    /// Retrieve active Staking/DeFi orders.
227    ///
228    /// `GET /api/v5/finance/staking-defi/orders-active`. Authenticated.
229    ///
230    /// # Errors
231    ///
232    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
233    pub async fn get_active_orders(
234        &self,
235        request: &StakingDefiActiveOrdersRequest,
236    ) -> Result<Vec<StakingDefiOrder>, Error> {
237        self.client
238            .get(STAKING_DEFI_ACTIVE_ORDERS, request, true)
239            .await
240    }
241
242    /// Retrieve Staking/DeFi order history.
243    ///
244    /// `GET /api/v5/finance/staking-defi/orders-history`. Authenticated.
245    ///
246    /// # Errors
247    ///
248    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
249    pub async fn get_orders_history(
250        &self,
251        request: &StakingDefiOrderHistoryRequest,
252    ) -> Result<Vec<StakingDefiOrder>, Error> {
253        self.client
254            .get(STAKING_DEFI_ORDERS_HISTORY, request, true)
255            .await
256    }
257}
258
259/// Accessor for ETH staking endpoints.
260pub struct EthStaking<'a, T> {
261    client: &'a OkxClient<T>,
262}
263
264impl<T: Transport> EthStaking<'_, T> {
265    /// Retrieve ETH staking product info.
266    ///
267    /// `GET /api/v5/finance/staking-defi/eth/product-info`. Authenticated.
268    ///
269    /// # Errors
270    ///
271    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
272    pub async fn product_info(&self) -> Result<Vec<StakingProductInfo>, Error> {
273        self.client.get(ETH_PRODUCT_INFO, &NoParams {}, true).await
274    }
275
276    /// Purchase ETH staking.
277    ///
278    /// `POST /api/v5/finance/staking-defi/eth/purchase`. Authenticated.
279    ///
280    /// # Errors
281    ///
282    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
283    pub async fn purchase(&self, amt: &str) -> Result<Vec<StakingOrder>, Error> {
284        let body = AmountBody { amt };
285        self.client.post(ETH_PURCHASE, &body, true).await
286    }
287
288    /// Redeem ETH staking.
289    ///
290    /// `POST /api/v5/finance/staking-defi/eth/redeem`. Authenticated.
291    ///
292    /// # Errors
293    ///
294    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
295    pub async fn redeem(&self, amt: &str) -> Result<Vec<StakingOrder>, Error> {
296        let body = AmountBody { amt };
297        self.client.post(ETH_REDEEM, &body, true).await
298    }
299
300    /// Cancel redeem ETH staking.
301    ///
302    /// `POST /api/v5/finance/staking-defi/eth/cancel-redeem`. Authenticated.
303    ///
304    /// # Errors
305    ///
306    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
307    pub async fn cancel_redeem(&self, ord_id: &str) -> Result<Vec<CancelRedeem>, Error> {
308        let body = CancelRedeemBody { ord_id };
309        self.client.post(ETH_CANCEL_REDEEM, &body, true).await
310    }
311
312    /// Retrieve ETH staking balance.
313    ///
314    /// `GET /api/v5/finance/staking-defi/eth/balance`. Authenticated.
315    ///
316    /// # Errors
317    ///
318    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
319    pub async fn balance(&self) -> Result<Vec<StakingBalance>, Error> {
320        self.client.get(ETH_BALANCE, &NoParams {}, true).await
321    }
322
323    /// Retrieve ETH staking purchase/redeem history.
324    ///
325    /// `GET /api/v5/finance/staking-defi/eth/purchase-redeem-history`. Authenticated.
326    ///
327    /// # Errors
328    ///
329    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
330    pub async fn purchase_redeem_history(
331        &self,
332        request: &FinanceHistoryRequest,
333    ) -> Result<Vec<StakingHistory>, Error> {
334        self.client.get(ETH_HISTORY, request, true).await
335    }
336
337    /// Retrieve ETH staking APY history.
338    ///
339    /// `GET /api/v5/finance/staking-defi/eth/apy-history`. Public.
340    ///
341    /// # Errors
342    ///
343    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
344    pub async fn apy_history(&self, days: &str) -> Result<Vec<StakingApyHistory>, Error> {
345        let query = DaysQuery { days };
346        self.client.get(ETH_APY_HISTORY, &query, false).await
347    }
348}
349
350/// Accessor for SOL staking endpoints.
351pub struct SolStaking<'a, T> {
352    client: &'a OkxClient<T>,
353}
354
355impl<T: Transport> SolStaking<'_, T> {
356    /// Retrieve SOL staking product info.
357    ///
358    /// `GET /api/v5/finance/staking-defi/sol/product-info`. Authenticated.
359    ///
360    /// # Errors
361    ///
362    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
363    pub async fn product_info(&self) -> Result<StakingProductInfo, Error> {
364        self.client.get(SOL_PRODUCT_INFO, &NoParams {}, true).await
365    }
366
367    /// Purchase SOL staking.
368    ///
369    /// `POST /api/v5/finance/staking-defi/sol/purchase`. Authenticated.
370    ///
371    /// # Errors
372    ///
373    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
374    pub async fn purchase(&self, amt: &str) -> Result<Vec<StakingOrder>, Error> {
375        let body = AmountBody { amt };
376        self.client.post(SOL_PURCHASE, &body, true).await
377    }
378
379    /// Redeem SOL staking.
380    ///
381    /// `POST /api/v5/finance/staking-defi/sol/redeem`. Authenticated.
382    ///
383    /// # Errors
384    ///
385    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
386    pub async fn redeem(&self, amt: &str) -> Result<Vec<StakingOrder>, Error> {
387        let body = AmountBody { amt };
388        self.client.post(SOL_REDEEM, &body, true).await
389    }
390
391    /// Retrieve SOL staking balance.
392    ///
393    /// `GET /api/v5/finance/staking-defi/sol/balance`. Authenticated.
394    ///
395    /// # Errors
396    ///
397    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
398    pub async fn balance(&self) -> Result<Vec<StakingBalance>, Error> {
399        self.client.get(SOL_BALANCE, &NoParams {}, true).await
400    }
401
402    /// Retrieve SOL staking purchase/redeem history.
403    ///
404    /// `GET /api/v5/finance/staking-defi/sol/purchase-redeem-history`. Authenticated.
405    ///
406    /// # Errors
407    ///
408    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
409    pub async fn purchase_redeem_history(
410        &self,
411        request: &FinanceHistoryRequest,
412    ) -> Result<Vec<StakingHistory>, Error> {
413        self.client.get(SOL_HISTORY, request, true).await
414    }
415
416    /// Retrieve SOL staking APY history.
417    ///
418    /// `GET /api/v5/finance/staking-defi/sol/apy-history`. Public.
419    ///
420    /// # Errors
421    ///
422    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
423    pub async fn apy_history(&self, days: &str) -> Result<Vec<StakingApyHistory>, Error> {
424        let query = DaysQuery { days };
425        self.client.get(SOL_APY_HISTORY, &query, false).await
426    }
427}
428
429/// Accessor for Flexible Loan endpoints.
430pub struct FlexibleLoan<'a, T> {
431    client: &'a OkxClient<T>,
432}
433
434impl<T: Transport> FlexibleLoan<'_, T> {
435    /// Retrieve borrowable currencies.
436    ///
437    /// `GET /api/v5/finance/flexible-loan/borrow-currencies`. Authenticated.
438    ///
439    /// # Errors
440    ///
441    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
442    pub async fn borrow_currencies(&self) -> Result<Vec<FlexibleLoanCurrency>, Error> {
443        self.client
444            .get(FLEX_BORROW_CURRENCIES, &NoParams {}, true)
445            .await
446    }
447
448    /// Retrieve collateral assets.
449    ///
450    /// `GET /api/v5/finance/flexible-loan/collateral-assets`. Public.
451    ///
452    /// # Errors
453    ///
454    /// Returns [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
455    pub async fn collateral_assets(
456        &self,
457        request: &FlexibleLoanCollateralAssetsRequest,
458    ) -> Result<Vec<FlexibleLoanCollateralAsset>, Error> {
459        self.client
460            .get(FLEX_COLLATERAL_ASSETS, request, false)
461            .await
462    }
463
464    /// Estimate maximum flexible-loan amount.
465    ///
466    /// `POST /api/v5/finance/flexible-loan/max-loan`. Authenticated.
467    ///
468    /// # Errors
469    ///
470    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
471    pub async fn max_loan(
472        &self,
473        request: &FlexibleLoanMaxLoanRequest,
474    ) -> Result<Vec<FlexibleLoanMaxLoan>, Error> {
475        self.client.post(FLEX_MAX_LOAN, request, true).await
476    }
477
478    /// Retrieve maximum collateral redeem amount.
479    ///
480    /// `GET /api/v5/finance/flexible-loan/max-collateral-redeem-amount`. Authenticated.
481    ///
482    /// # Errors
483    ///
484    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
485    pub async fn max_collateral_redeem_amount(
486        &self,
487        request: &FlexibleLoanMaxRedeemRequest,
488    ) -> Result<Vec<FlexibleLoanMaxRedeem>, Error> {
489        self.client.get(FLEX_MAX_REDEEM, request, true).await
490    }
491
492    /// Adjust flexible-loan collateral.
493    ///
494    /// `POST /api/v5/finance/flexible-loan/adjust-collateral`. Authenticated.
495    ///
496    /// # Errors
497    ///
498    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
499    pub async fn adjust_collateral(
500        &self,
501        request: &FlexibleLoanAdjustCollateralRequest,
502    ) -> Result<Vec<FlexibleLoanOrder>, Error> {
503        self.client
504            .post(FLEX_ADJUST_COLLATERAL, request, true)
505            .await
506    }
507
508    /// Retrieve flexible-loan info.
509    ///
510    /// `GET /api/v5/finance/flexible-loan/loan-info`. Authenticated.
511    ///
512    /// # Errors
513    ///
514    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
515    pub async fn loan_info(
516        &self,
517        request: &FlexibleLoanInfoRequest,
518    ) -> Result<Vec<FlexibleLoanInfo>, Error> {
519        self.client.get(FLEX_LOAN_INFO, request, true).await
520    }
521
522    /// Retrieve flexible-loan history.
523    ///
524    /// `GET /api/v5/finance/flexible-loan/loan-history`. Authenticated.
525    ///
526    /// # Errors
527    ///
528    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
529    pub async fn loan_history(
530        &self,
531        request: &FlexibleLoanHistoryRequest,
532    ) -> Result<Vec<FlexibleLoanHistory>, Error> {
533        self.client.get(FLEX_LOAN_HISTORY, request, true).await
534    }
535
536    /// Retrieve flexible-loan accrued interest.
537    ///
538    /// `GET /api/v5/finance/flexible-loan/interest-accrued`. Authenticated.
539    ///
540    /// # Errors
541    ///
542    /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
543    pub async fn interest_accrued(
544        &self,
545        request: &FlexibleLoanInterestAccruedRequest,
546    ) -> Result<Vec<FlexibleLoanInterest>, Error> {
547        self.client.get(FLEX_INTEREST_ACCRUED, request, true).await
548    }
549}