Skip to main content

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}