Skip to main content

rust_okx/api/account/
api.rs

1use crate::client::OkxClient;
2use crate::error::Error;
3use crate::model::{InstType, ValidateRequest};
4use crate::transport::Transport;
5
6use super::endpoints::*;
7use super::internal::*;
8use super::requests::*;
9use super::responses::*;
10
11/// Accessor for the authenticated account endpoints.
12///
13/// Obtain one via [`OkxClient::account`](crate::OkxClient::account). All methods
14/// require credentials; calling them without credentials returns
15/// [`Error::Configuration`].
16pub struct Account<'a, T> {
17    client: &'a OkxClient<T>,
18}
19
20impl<'a, T: Transport> Account<'a, T> {
21    pub(crate) fn new(client: &'a OkxClient<T>) -> Self {
22        Self { client }
23    }
24
25    /// Retrieve the trading-account balance.
26    ///
27    /// `GET /api/v5/account/balance`. Authenticated. Pass `ccy` to filter to one
28    /// or more comma-separated currencies (e.g. `Some("BTC,USDT")`). The result
29    /// is a single [`AccountBalance`].
30    ///
31    /// # Errors
32    ///
33    /// Returns [`Error::Configuration`] if no credentials are set,
34    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
35    pub async fn get_balance(&self, ccy: Option<&str>) -> Result<Vec<AccountBalance>, Error> {
36        let query = BalanceQuery { ccy };
37        self.client.get(BALANCE, &query, true).await
38    }
39
40    /// Retrieve open positions.
41    ///
42    /// `GET /api/v5/account/positions`. Authenticated. Both filters are
43    /// optional; omit them to return all positions.
44    ///
45    /// # Errors
46    ///
47    /// Returns [`Error::Configuration`] if no credentials are set,
48    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
49    pub async fn get_positions(
50        &self,
51        inst_type: Option<InstType>,
52        inst_id: Option<&str>,
53    ) -> Result<Vec<Position>, Error> {
54        let query = PositionsQuery {
55            inst_type: inst_type.as_ref(),
56            inst_id,
57        };
58        self.client.get(POSITIONS, &query, true).await
59    }
60
61    /// Retrieve account position risk.
62    ///
63    /// `GET /api/v5/account/account-position-risk`. Authenticated.
64    ///
65    /// # Errors
66    ///
67    /// Returns [`Error::Configuration`] if no credentials are set,
68    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
69    pub async fn get_position_risk(
70        &self,
71        inst_type: Option<InstType>,
72    ) -> Result<Vec<PositionRisk>, Error> {
73        let query = PositionRiskQuery {
74            inst_type: inst_type.as_ref(),
75        };
76        self.client.get(POSITION_RISK, &query, true).await
77    }
78
79    /// Retrieve account configuration.
80    ///
81    /// `GET /api/v5/account/config`. Authenticated.
82    ///
83    /// # Errors
84    ///
85    /// Returns [`Error::Configuration`] if no credentials are set,
86    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
87    pub async fn get_account_config(&self) -> Result<Vec<AccountConfig>, Error> {
88        self.client.get(ACCOUNT_CONFIG, &NoQuery, true).await
89    }
90
91    /// Retrieve recent account bills.
92    ///
93    /// `GET /api/v5/account/bills`. Authenticated.
94    ///
95    /// # Errors
96    ///
97    /// Returns [`Error::InvalidRequest`] on validation failure,
98    /// [`Error::Configuration`] if no credentials are set,
99    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
100    pub async fn get_account_bills(
101        &self,
102        request: &BillsRequest,
103    ) -> Result<Vec<AccountBill>, Error> {
104        request.validate()?;
105        self.client.get(BILLS, request, true).await
106    }
107
108    /// Retrieve archived account bills.
109    ///
110    /// `GET /api/v5/account/bills-archive`. Authenticated.
111    ///
112    /// # Errors
113    ///
114    /// Returns [`Error::InvalidRequest`] on validation failure,
115    /// [`Error::Configuration`] if no credentials are set,
116    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
117    pub async fn get_account_bills_archive(
118        &self,
119        request: &BillsArchiveRequest,
120    ) -> Result<Vec<AccountBill>, Error> {
121        request.validate()?;
122        self.client.get(BILLS_ARCHIVE, request, true).await
123    }
124
125    /// Set the account position mode.
126    ///
127    /// `POST /api/v5/account/set-position-mode`. Authenticated.
128    ///
129    /// # Errors
130    ///
131    /// Returns [`Error::Configuration`] if no credentials are set,
132    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
133    pub async fn set_position_mode(
134        &self,
135        pos_mode: &str,
136    ) -> Result<Vec<SetPositionModeResult>, Error> {
137        let body = SetPositionModeBody { pos_mode };
138        self.client.post(SET_POSITION_MODE, &body, true).await
139    }
140
141    /// Set leverage for an instrument or currency.
142    ///
143    /// `POST /api/v5/account/set-leverage`. Authenticated.
144    ///
145    /// # Errors
146    ///
147    /// Returns [`Error::InvalidRequest`] on validation failure,
148    /// [`Error::Configuration`] if no credentials are set,
149    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
150    pub async fn set_leverage(
151        &self,
152        request: &SetLeverageRequest,
153    ) -> Result<Vec<LeverageInfo>, Error> {
154        request.validate()?;
155        self.client.post(SET_LEVERAGE, request, true).await
156    }
157
158    /// Retrieve leverage settings.
159    ///
160    /// `GET /api/v5/account/leverage-info`. Authenticated.
161    ///
162    /// # Errors
163    ///
164    /// Returns [`Error::InvalidRequest`] on validation failure,
165    /// [`Error::Configuration`] if no credentials are set,
166    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
167    pub async fn get_leverage(
168        &self,
169        request: &LeverageRequest,
170    ) -> Result<Vec<LeverageInfo>, Error> {
171        request.validate()?;
172        self.client.get(GET_LEVERAGE, request, true).await
173    }
174
175    /// Retrieve maximum tradable size for an instrument.
176    ///
177    /// `GET /api/v5/account/max-size`. Authenticated.
178    ///
179    /// # Errors
180    ///
181    /// Returns [`Error::InvalidRequest`] on validation failure,
182    /// [`Error::Configuration`] if no credentials are set,
183    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
184    pub async fn get_max_order_size(
185        &self,
186        request: &MaxOrderSizeRequest,
187    ) -> Result<Vec<MaxOrderSize>, Error> {
188        request.validate()?;
189        self.client.get(MAX_ORDER_SIZE, request, true).await
190    }
191
192    /// Retrieve maximum available size for an instrument.
193    ///
194    /// `GET /api/v5/account/max-avail-size`. Authenticated.
195    ///
196    /// # Errors
197    ///
198    /// Returns [`Error::InvalidRequest`] on validation failure,
199    /// [`Error::Configuration`] if no credentials are set,
200    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
201    pub async fn get_max_avail_size(
202        &self,
203        request: &MaxAvailableSizeRequest,
204    ) -> Result<Vec<MaxAvailableSize>, Error> {
205        request.validate()?;
206        self.client.get(MAX_AVAILABLE_SIZE, request, true).await
207    }
208
209    /// Increase or decrease margin for a position.
210    ///
211    /// `POST /api/v5/account/position/margin-balance`. Authenticated.
212    ///
213    /// # Errors
214    ///
215    /// Returns [`Error::InvalidRequest`] on validation failure,
216    /// [`Error::Configuration`] if no credentials are set,
217    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
218    pub async fn adjust_margin(
219        &self,
220        request: &AdjustMarginRequest,
221    ) -> Result<Vec<AdjustMarginResult>, Error> {
222        request.validate()?;
223        self.client.post(ADJUST_MARGIN, request, true).await
224    }
225
226    /// Retrieve trade fee rates.
227    ///
228    /// `GET /api/v5/account/trade-fee`. Authenticated.
229    ///
230    /// # Errors
231    ///
232    /// Returns [`Error::InvalidRequest`] on validation failure,
233    /// [`Error::Configuration`] if no credentials are set,
234    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
235    pub async fn get_fee_rates(&self, request: &FeeRatesRequest) -> Result<Vec<FeeRate>, Error> {
236        request.validate()?;
237        self.client.get(FEE_RATES, request, true).await
238    }
239
240    /// Retrieve account-available instruments.
241    ///
242    /// `GET /api/v5/account/instruments`. Authenticated.
243    ///
244    /// # Errors
245    ///
246    /// Returns [`Error::InvalidRequest`] on validation failure,
247    /// [`Error::Configuration`] if no credentials are set,
248    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
249    pub async fn get_account_instruments(
250        &self,
251        request: &AccountInstrumentsRequest,
252    ) -> Result<Vec<AccountInstrument>, Error> {
253        request.validate()?;
254        self.client.get(ACCOUNT_INSTRUMENTS, request, true).await
255    }
256
257    /// Retrieve the maximum loan amount.
258    ///
259    /// `GET /api/v5/account/max-loan`. Authenticated.
260    ///
261    /// # Errors
262    ///
263    /// Returns [`Error::InvalidRequest`] on validation failure,
264    /// [`Error::Configuration`] if no credentials are set,
265    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
266    pub async fn get_max_loan(&self, request: &MaxLoanRequest) -> Result<Vec<MaxLoan>, Error> {
267        request.validate()?;
268        self.client.get(MAX_LOAN, request, true).await
269    }
270
271    /// Retrieve interest-accrued records.
272    ///
273    /// `GET /api/v5/account/interest-accrued`. Authenticated.
274    ///
275    /// # Errors
276    ///
277    /// Returns [`Error::InvalidRequest`] on validation failure,
278    /// [`Error::Configuration`] if no credentials are set,
279    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
280    pub async fn get_interest_accrued(
281        &self,
282        request: &InterestAccruedRequest,
283    ) -> Result<Vec<InterestAccrued>, Error> {
284        request.validate()?;
285        self.client.get(INTEREST_ACCRUED, request, true).await
286    }
287
288    /// Retrieve interest rates.
289    ///
290    /// `GET /api/v5/account/interest-rate`. Authenticated.
291    ///
292    /// # Errors
293    ///
294    /// Returns [`Error::Configuration`] if no credentials are set,
295    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
296    pub async fn get_interest_rate(&self, ccy: Option<&str>) -> Result<Vec<InterestRate>, Error> {
297        let query = BalanceQuery { ccy };
298        self.client.get(INTEREST_RATE, &query, true).await
299    }
300
301    /// Set the greeks display type.
302    ///
303    /// `POST /api/v5/account/set-greeks`. Authenticated.
304    ///
305    /// # Errors
306    ///
307    /// Returns [`Error::Configuration`] if no credentials are set,
308    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
309    pub async fn set_greeks(&self, greeks_type: &str) -> Result<Vec<SetGreeksResult>, Error> {
310        let body = SetGreeksBody { greeks_type };
311        self.client.post(SET_GREEKS, &body, true).await
312    }
313
314    /// Set isolated margin transfer mode.
315    ///
316    /// `POST /api/v5/account/set-isolated-mode`. Authenticated.
317    ///
318    /// # Errors
319    ///
320    /// Returns [`Error::Configuration`] if no credentials are set,
321    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
322    pub async fn set_isolated_mode(
323        &self,
324        iso_mode: &str,
325        mode_type: &str,
326    ) -> Result<Vec<SetIsolatedModeResult>, Error> {
327        let body = SetIsolatedModeBody {
328            iso_mode,
329            mode_type,
330        };
331        self.client.post(SET_ISOLATED_MODE, &body, true).await
332    }
333
334    /// Retrieve maximum withdrawal amounts.
335    ///
336    /// `GET /api/v5/account/max-withdrawal`. Authenticated.
337    ///
338    /// # Errors
339    ///
340    /// Returns [`Error::Configuration`] if no credentials are set,
341    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
342    pub async fn get_max_withdrawal(&self, ccy: Option<&str>) -> Result<Vec<MaxWithdrawal>, Error> {
343        let query = BalanceQuery { ccy };
344        self.client.get(MAX_WITHDRAWAL, &query, true).await
345    }
346
347    /// Retrieve borrowing rate and limit information.
348    ///
349    /// `GET /api/v5/account/interest-limits`. Authenticated.
350    ///
351    /// # Errors
352    ///
353    /// Returns [`Error::InvalidRequest`] on validation failure,
354    /// [`Error::Configuration`] if no credentials are set,
355    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
356    pub async fn get_interest_limits(
357        &self,
358        request: &InterestLimitsRequest,
359    ) -> Result<Vec<InterestLimit>, Error> {
360        request.validate()?;
361        self.client.get(INTEREST_LIMITS, request, true).await
362    }
363
364    /// Calculate simulated margin information.
365    ///
366    /// `POST /api/v5/account/simulated_margin`. Authenticated. This is separate
367    /// from [`OkxClientBuilder::demo_trading`](crate::OkxClientBuilder::demo_trading),
368    /// which only toggles the OKX simulated-trading header.
369    ///
370    /// # Errors
371    ///
372    /// Returns [`Error::InvalidRequest`] on validation failure,
373    /// [`Error::Configuration`] if no credentials are set,
374    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
375    pub async fn get_simulated_margin(
376        &self,
377        request: &SimulatedMarginRequest,
378    ) -> Result<Vec<SimulatedMargin>, Error> {
379        request.validate()?;
380        self.client.post(SIMULATED_MARGIN, request, true).await
381    }
382
383    /// Retrieve greeks.
384    ///
385    /// `GET /api/v5/account/greeks`. Authenticated.
386    ///
387    /// # Errors
388    ///
389    /// Returns [`Error::Configuration`] if no credentials are set,
390    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
391    pub async fn get_greeks(&self, ccy: Option<&str>) -> Result<Vec<Greek>, Error> {
392        let query = BalanceQuery { ccy };
393        self.client.get(GREEKS, &query, true).await
394    }
395
396    /// Retrieve position history.
397    ///
398    /// `GET /api/v5/account/positions-history`. Authenticated.
399    ///
400    /// # Errors
401    ///
402    /// Returns [`Error::InvalidRequest`] on validation failure,
403    /// [`Error::Configuration`] if no credentials are set,
404    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
405    pub async fn get_positions_history(
406        &self,
407        request: &PositionsHistoryRequest,
408    ) -> Result<Vec<PositionHistory>, Error> {
409        request.validate()?;
410        self.client.get(POSITIONS_HISTORY, request, true).await
411    }
412
413    /// Retrieve account position tiers.
414    ///
415    /// `GET /api/v5/account/position-tiers`. Authenticated.
416    ///
417    /// # Errors
418    ///
419    /// Returns [`Error::InvalidRequest`] on validation failure,
420    /// [`Error::Configuration`] if no credentials are set,
421    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
422    pub async fn get_account_position_tiers(
423        &self,
424        request: &AccountPositionTiersRequest,
425    ) -> Result<Vec<AccountPositionTier>, Error> {
426        request.validate()?;
427        self.client.get(ACCOUNT_POSITION_TIERS, request, true).await
428    }
429
430    /// Retrieve the account risk state.
431    ///
432    /// `GET /api/v5/account/risk-state`. Authenticated.
433    ///
434    /// # Errors
435    ///
436    /// Returns [`Error::Configuration`] if no credentials are set,
437    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
438    pub async fn get_risk_state(&self) -> Result<Vec<RiskState>, Error> {
439        self.client.get(RISK_STATE, &NoQuery, true).await
440    }
441
442    /// Set account auto-loan mode.
443    ///
444    /// `POST /api/v5/account/set-auto-loan`. Authenticated.
445    ///
446    /// # Errors
447    ///
448    /// Returns [`Error::Configuration`] if no credentials are set,
449    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
450    pub async fn set_auto_loan(&self, auto_loan: bool) -> Result<Vec<SetAutoLoanResult>, Error> {
451        let body = SetAutoLoanBody { auto_loan };
452        self.client.post(SET_AUTO_LOAN, &body, true).await
453    }
454
455    /// Set the account level.
456    ///
457    /// `POST /api/v5/account/set-account-level`. Authenticated.
458    ///
459    /// # Errors
460    ///
461    /// Returns [`Error::Configuration`] if no credentials are set,
462    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
463    pub async fn set_account_level(
464        &self,
465        acct_lv: &str,
466    ) -> Result<Vec<SetAccountLevelResult>, Error> {
467        let body = SetAccountLevelBody { acct_lv };
468        self.client.post(SET_ACCOUNT_LEVEL, &body, true).await
469    }
470
471    /// Activate option trading.
472    ///
473    /// `POST /api/v5/account/activate-option`. Authenticated.
474    ///
475    /// # Errors
476    ///
477    /// Returns [`Error::Configuration`] if no credentials are set,
478    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
479    pub async fn activate_option(&self) -> Result<Vec<ActivateOptionResult>, Error> {
480        self.client.post(ACTIVATE_OPTION, &EmptyBody {}, true).await
481    }
482
483    /// Build simulated positions and equity.
484    ///
485    /// `POST /api/v5/account/position-builder`. Authenticated.
486    ///
487    /// # Errors
488    ///
489    /// Returns [`Error::InvalidRequest`] on validation failure,
490    /// [`Error::Configuration`] if no credentials are set,
491    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
492    pub async fn position_builder(
493        &self,
494        request: &PositionBuilderRequest,
495    ) -> Result<Vec<PositionBuilderResult>, Error> {
496        request.validate()?;
497        self.client.post(POSITION_BUILDER, request, true).await
498    }
499
500    /// Manually borrow or repay spot liabilities.
501    ///
502    /// `POST /api/v5/account/spot-manual-borrow-repay`. Authenticated.
503    ///
504    /// # Errors
505    ///
506    /// Returns [`Error::InvalidRequest`] on validation failure,
507    /// [`Error::Configuration`] if no credentials are set,
508    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
509    pub async fn spot_manual_borrow_repay(
510        &self,
511        request: &SpotManualBorrowRepayRequest,
512    ) -> Result<Vec<SpotBorrowRepayResult>, Error> {
513        request.validate()?;
514        self.client
515            .post(SPOT_MANUAL_BORROW_REPAY, request, true)
516            .await
517    }
518
519    /// Set automatic repayment for spot borrow/repay.
520    ///
521    /// `POST /api/v5/account/set-auto-repay`. Authenticated.
522    ///
523    /// # Errors
524    ///
525    /// Returns [`Error::InvalidRequest`] on validation failure,
526    /// [`Error::Configuration`] if no credentials are set,
527    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
528    pub async fn set_auto_repay(
529        &self,
530        request: &SetAutoRepayRequest,
531    ) -> Result<Vec<SetAutoRepayResult>, Error> {
532        request.validate()?;
533        self.client.post(SET_AUTO_REPAY, request, true).await
534    }
535
536    /// Retrieve spot borrow/repay history.
537    ///
538    /// `GET /api/v5/account/spot-borrow-repay-history`. Authenticated.
539    ///
540    /// # Errors
541    ///
542    /// Returns [`Error::InvalidRequest`] on validation failure,
543    /// [`Error::Configuration`] if no credentials are set,
544    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
545    pub async fn get_spot_borrow_repay_history(
546        &self,
547        request: &SpotBorrowRepayHistoryRequest,
548    ) -> Result<Vec<SpotBorrowRepayHistory>, Error> {
549        request.validate()?;
550        self.client
551            .get(SPOT_BORROW_REPAY_HISTORY, request, true)
552            .await
553    }
554
555    /// Set automatic earn for the account.
556    ///
557    /// `POST /api/v5/account/set-auto-earn`. Authenticated.
558    ///
559    /// # Errors
560    ///
561    /// Returns [`Error::InvalidRequest`] on validation failure,
562    /// [`Error::Configuration`] if no credentials are set,
563    /// [`Error::Api`] on a non-zero OKX code, or transport/decode errors.
564    pub async fn set_auto_earn(
565        &self,
566        request: &SetAutoEarnRequest,
567    ) -> Result<Vec<SetAutoEarnResult>, Error> {
568        request.validate()?;
569        self.client.post(SET_AUTO_EARN, request, true).await
570    }
571}