rust_okx/api/trade/api.rs
1use crate::client::OkxClient;
2use crate::error::Error;
3use crate::model::{ValidateRequest, collection_length};
4use crate::transport::Transport;
5
6use super::endpoints::*;
7use super::internal::*;
8use super::requests::*;
9use super::responses::*;
10
11/// Accessor for the authenticated trading endpoints.
12///
13/// Obtain one via [`OkxClient::trade`](crate::OkxClient::trade). All methods
14/// require credentials.
15pub struct Trade<'a, T> {
16 client: &'a OkxClient<T>,
17}
18
19impl<'a, T: Transport> Trade<'a, T> {
20 pub(crate) fn new(client: &'a OkxClient<T>) -> Self {
21 Self { client }
22 }
23
24 /// Place an order.
25 ///
26 /// `POST /api/v5/trade/order`. Authenticated. Build the request with
27 /// [`PlaceOrderRequest::new`] plus optional setters. The returned vector
28 /// contains one [`PlaceOrderResult`]; inspect its
29 /// [`s_code`](PlaceOrderResult::s_code) to confirm acceptance (`"0"`).
30 ///
31 /// # Errors
32 ///
33 /// Returns [`Error::Configuration`] without credentials, [`Error::Api`] on a
34 /// non-zero top-level OKX code, or transport/decode errors.
35 pub async fn place_order(
36 &self,
37 request: &PlaceOrderRequest,
38 ) -> Result<Vec<PlaceOrderResult>, Error> {
39 self.client.post(ORDER, request, true).await
40 }
41
42 /// Place multiple orders.
43 ///
44 /// `POST /api/v5/trade/batch-orders`. Authenticated.
45 ///
46 /// # Errors
47 ///
48 /// See [`place_order`](Self::place_order).
49 pub async fn place_multiple_orders(
50 &self,
51 requests: &[PlaceOrderRequest],
52 ) -> Result<Vec<PlaceOrderResult>, Error> {
53 self.client.post(BATCH_ORDERS, &requests, true).await
54 }
55
56 /// Cancel an order by its OKX order ID.
57 ///
58 /// `POST /api/v5/trade/cancel-order`. Authenticated.
59 ///
60 /// # Errors
61 ///
62 /// See [`place_order`](Self::place_order).
63 pub async fn cancel_order(
64 &self,
65 inst_id: &str,
66 ord_id: &str,
67 ) -> Result<Vec<CancelOrderResult>, Error> {
68 let body = CancelOrderBody { inst_id, ord_id };
69 self.client.post(CANCEL_ORDER, &body, true).await
70 }
71
72 /// Cancel multiple orders.
73 ///
74 /// `POST /api/v5/trade/cancel-batch-orders`. Authenticated.
75 ///
76 /// # Errors
77 ///
78 /// See [`place_order`](Self::place_order).
79 pub async fn cancel_multiple_orders(
80 &self,
81 requests: &[CancelOrderRequest],
82 ) -> Result<Vec<CancelOrderResult>, Error> {
83 self.client.post(CANCEL_BATCH_ORDERS, &requests, true).await
84 }
85
86 /// Amend an existing order.
87 ///
88 /// `POST /api/v5/trade/amend-order`. Authenticated.
89 ///
90 /// # Errors
91 ///
92 /// See [`place_order`](Self::place_order).
93 pub async fn amend_order(
94 &self,
95 request: &AmendOrderRequest,
96 ) -> Result<Vec<AmendOrderResult>, Error> {
97 self.client.post(AMEND_ORDER, request, true).await
98 }
99
100 /// Amend multiple existing orders.
101 ///
102 /// `POST /api/v5/trade/amend-batch-orders`. Authenticated.
103 ///
104 /// # Errors
105 ///
106 /// See [`place_order`](Self::place_order).
107 pub async fn amend_multiple_orders(
108 &self,
109 requests: &[AmendOrderRequest],
110 ) -> Result<Vec<AmendOrderResult>, Error> {
111 self.client.post(AMEND_BATCH_ORDERS, &requests, true).await
112 }
113
114 /// Close positions for an instrument.
115 ///
116 /// `POST /api/v5/trade/close-position`. Authenticated.
117 ///
118 /// # Errors
119 ///
120 /// See [`place_order`](Self::place_order).
121 pub async fn close_positions(
122 &self,
123 request: &ClosePositionRequest,
124 ) -> Result<Vec<ClosePositionResult>, Error> {
125 self.client.post(CLOSE_POSITION, request, true).await
126 }
127
128 /// Retrieve the details of a single order by its OKX order ID.
129 ///
130 /// `GET /api/v5/trade/order`. Authenticated.
131 ///
132 /// # Errors
133 ///
134 /// See [`place_order`](Self::place_order).
135 pub async fn get_order(&self, inst_id: &str, ord_id: &str) -> Result<Vec<Order>, Error> {
136 let query = GetOrderQuery { inst_id, ord_id };
137 self.client.get(ORDER, &query, true).await
138 }
139
140 /// Retrieve pending orders.
141 ///
142 /// `GET /api/v5/trade/orders-pending`. Authenticated.
143 ///
144 /// # Errors
145 ///
146 /// See [`place_order`](Self::place_order).
147 pub async fn get_order_list(&self, request: &OrderListRequest) -> Result<Vec<Order>, Error> {
148 self.client.get(ORDERS_PENDING, request, true).await
149 }
150
151 /// Retrieve order history for the recent window.
152 ///
153 /// `GET /api/v5/trade/orders-history`. Authenticated.
154 ///
155 /// # Errors
156 ///
157 /// See [`place_order`](Self::place_order).
158 pub async fn get_orders_history(
159 &self,
160 request: &OrderHistoryRequest,
161 ) -> Result<Vec<Order>, Error> {
162 self.client.get(ORDERS_HISTORY, request, true).await
163 }
164
165 /// Retrieve archived order history.
166 ///
167 /// `GET /api/v5/trade/orders-history-archive`. Authenticated.
168 ///
169 /// # Errors
170 ///
171 /// See [`place_order`](Self::place_order).
172 pub async fn get_orders_history_archive(
173 &self,
174 request: &OrderHistoryRequest,
175 ) -> Result<Vec<Order>, Error> {
176 self.client.get(ORDERS_HISTORY_ARCHIVE, request, true).await
177 }
178
179 /// Retrieve recent fills.
180 ///
181 /// `GET /api/v5/trade/fills`. Authenticated.
182 ///
183 /// # Errors
184 ///
185 /// See [`place_order`](Self::place_order).
186 pub async fn get_fills(&self, request: &FillsRequest) -> Result<Vec<Fill>, Error> {
187 self.client.get(FILLS, request, true).await
188 }
189
190 /// Retrieve historical fills.
191 ///
192 /// `GET /api/v5/trade/fills-history`. Authenticated.
193 ///
194 /// # Errors
195 ///
196 /// See [`place_order`](Self::place_order).
197 pub async fn get_fills_history(
198 &self,
199 request: &FillHistoryRequest,
200 ) -> Result<Vec<FillHistory>, Error> {
201 request.validate()?;
202 self.client.get(FILLS_HISTORY, request, true).await
203 }
204
205 /// Place an algo order.
206 ///
207 /// `POST /api/v5/trade/order-algo`. Authenticated.
208 ///
209 /// # Errors
210 ///
211 /// See [`place_order`](Self::place_order).
212 pub async fn place_algo_order(
213 &self,
214 request: &AlgoOrderRequest,
215 ) -> Result<Vec<AlgoOrderResult>, Error> {
216 request.validate()?;
217 self.client.post(ORDER_ALGO, request, true).await
218 }
219
220 /// Cancel algo orders.
221 ///
222 /// `POST /api/v5/trade/cancel-algos`. Authenticated.
223 ///
224 /// # Errors
225 ///
226 /// See [`place_order`](Self::place_order).
227 pub async fn cancel_algo_orders(
228 &self,
229 requests: &[CancelAlgoOrderRequest],
230 ) -> Result<Vec<AlgoOrderResult>, Error> {
231 collection_length("requests", requests.len(), 1, 10)?;
232 for request in requests {
233 request.validate()?;
234 }
235 self.client.post(CANCEL_ALGOS, &requests, true).await
236 }
237
238 /// Amend an algo order.
239 ///
240 /// `POST /api/v5/trade/amend-algos`. Authenticated.
241 ///
242 /// # Errors
243 ///
244 /// See [`place_order`](Self::place_order).
245 pub async fn amend_algo_order(
246 &self,
247 request: &AmendAlgoOrderRequest,
248 ) -> Result<Vec<AlgoOrderResult>, Error> {
249 request.validate()?;
250 self.client.post(AMEND_ALGOS, request, true).await
251 }
252
253 /// Retrieve pending algo orders.
254 ///
255 /// `GET /api/v5/trade/orders-algo-pending`. Authenticated.
256 ///
257 /// # Errors
258 ///
259 /// See [`place_order`](Self::place_order).
260 pub async fn get_algo_order_list(
261 &self,
262 request: &AlgoOrderListRequest,
263 ) -> Result<Vec<AlgoOrder>, Error> {
264 request.validate()?;
265 self.client.get(ORDERS_ALGO_PENDING, request, true).await
266 }
267
268 /// Retrieve algo order history.
269 ///
270 /// `GET /api/v5/trade/orders-algo-history`. Authenticated.
271 ///
272 /// # Errors
273 ///
274 /// See [`place_order`](Self::place_order).
275 pub async fn get_algo_orders_history(
276 &self,
277 request: &AlgoOrderHistoryRequest,
278 ) -> Result<Vec<AlgoOrder>, Error> {
279 request.validate()?;
280 self.client.get(ORDERS_ALGO_HISTORY, request, true).await
281 }
282
283 /// Retrieve details for an algo order.
284 ///
285 /// `GET /api/v5/trade/order-algo`. Authenticated.
286 ///
287 /// # Errors
288 ///
289 /// See [`place_order`](Self::place_order).
290 pub async fn get_algo_order_details(
291 &self,
292 request: &AlgoOrderDetailsRequest,
293 ) -> Result<Vec<AlgoOrder>, Error> {
294 request.validate()?;
295 self.client.get(ORDER_ALGO_DETAILS, request, true).await
296 }
297
298 /// Retrieve the easy-convert currency list.
299 ///
300 /// `GET /api/v5/trade/easy-convert-currency-list`. Authenticated.
301 ///
302 /// # Errors
303 ///
304 /// See [`place_order`](Self::place_order).
305 pub async fn get_easy_convert_currency_list(&self) -> Result<Vec<EasyConvertCurrency>, Error> {
306 self.client
307 .get(EASY_CONVERT_CURRENCY_LIST, &NoQuery, true)
308 .await
309 }
310
311 /// Execute an easy-convert request.
312 ///
313 /// `POST /api/v5/trade/easy-convert`. Authenticated.
314 ///
315 /// # Errors
316 ///
317 /// See [`place_order`](Self::place_order).
318 pub async fn easy_convert(
319 &self,
320 request: &EasyConvertRequest,
321 ) -> Result<Vec<EasyConvertResult>, Error> {
322 request.validate()?;
323 self.client.post(EASY_CONVERT, request, true).await
324 }
325
326 /// Retrieve easy-convert history.
327 ///
328 /// `GET /api/v5/trade/easy-convert-history`. Authenticated.
329 ///
330 /// # Errors
331 ///
332 /// See [`place_order`](Self::place_order).
333 pub async fn get_easy_convert_history(
334 &self,
335 request: &EasyConvertHistoryRequest,
336 ) -> Result<Vec<EasyConvertHistory>, Error> {
337 request.validate()?;
338 self.client.get(EASY_CONVERT_HISTORY, request, true).await
339 }
340
341 /// Retrieve one-click-repay currency pairs.
342 ///
343 /// `GET /api/v5/trade/one-click-repay-currency-list`. Authenticated.
344 ///
345 /// # Errors
346 ///
347 /// See [`place_order`](Self::place_order).
348 pub async fn get_one_click_repay_currency_list(
349 &self,
350 request: &OneClickRepayCurrencyListRequest,
351 ) -> Result<Vec<OneClickRepayCurrency>, Error> {
352 request.validate()?;
353 self.client
354 .get(ONE_CLICK_REPAY_CURRENCY_LIST, request, true)
355 .await
356 }
357
358 /// Execute one-click repay.
359 ///
360 /// `POST /api/v5/trade/one-click-repay`. Authenticated.
361 ///
362 /// # Errors
363 ///
364 /// See [`place_order`](Self::place_order).
365 pub async fn one_click_repay(
366 &self,
367 request: &OneClickRepayRequest,
368 ) -> Result<Vec<OneClickRepayResult>, Error> {
369 request.validate()?;
370 self.client.post(ONE_CLICK_REPAY, request, true).await
371 }
372
373 /// Retrieve one-click-repay history.
374 ///
375 /// `GET /api/v5/trade/one-click-repay-history`. Authenticated.
376 ///
377 /// # Errors
378 ///
379 /// See [`place_order`](Self::place_order).
380 pub async fn get_one_click_repay_history(
381 &self,
382 request: &OneClickRepayHistoryRequest,
383 ) -> Result<Vec<OneClickRepayHistory>, Error> {
384 request.validate()?;
385 self.client
386 .get(ONE_CLICK_REPAY_HISTORY, request, true)
387 .await
388 }
389
390 /// Retrieve one-click-repay v2 currency pairs.
391 ///
392 /// `GET /api/v5/trade/one-click-repay-currency-list-v2`. Authenticated.
393 ///
394 /// # Errors
395 ///
396 /// See [`place_order`](Self::place_order).
397 pub async fn get_one_click_repay_currency_list_v2(
398 &self,
399 request: &OneClickRepayCurrencyListRequest,
400 ) -> Result<Vec<OneClickRepayCurrency>, Error> {
401 request.validate()?;
402 self.client
403 .get(ONE_CLICK_REPAY_CURRENCY_LIST_V2, request, true)
404 .await
405 }
406
407 /// Execute one-click repay v2.
408 ///
409 /// `POST /api/v5/trade/one-click-repay-v2`. Authenticated.
410 ///
411 /// # Errors
412 ///
413 /// See [`place_order`](Self::place_order).
414 pub async fn one_click_repay_v2(
415 &self,
416 request: &OneClickRepayRequest,
417 ) -> Result<Vec<OneClickRepayResult>, Error> {
418 request.validate()?;
419 self.client.post(ONE_CLICK_REPAY_V2, request, true).await
420 }
421
422 /// Retrieve one-click-repay v2 history.
423 ///
424 /// `GET /api/v5/trade/one-click-repay-history-v2`. Authenticated.
425 ///
426 /// # Errors
427 ///
428 /// See [`place_order`](Self::place_order).
429 pub async fn get_one_click_repay_history_v2(
430 &self,
431 request: &OneClickRepayHistoryRequest,
432 ) -> Result<Vec<OneClickRepayHistory>, Error> {
433 request.validate()?;
434 self.client
435 .get(ONE_CLICK_REPAY_HISTORY_V2, request, true)
436 .await
437 }
438}