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