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