bpx_api_client/routes/
order.rs

1use bpx_api_types::order::{
2    CancelOpenOrdersPayload, CancelOrderPayload, ExecuteOrderPayload, Order,
3};
4
5use crate::BpxClient;
6use crate::error::{Error, Result};
7
8#[doc(hidden)]
9pub const API_ORDER: &str = "/api/v1/order";
10#[doc(hidden)]
11pub const API_ORDERS: &str = "/api/v1/orders";
12
13impl BpxClient {
14    /// Fetches a specific open order by symbol and either order ID or client ID.
15    pub async fn get_open_order(
16        &self,
17        symbol: &str,
18        order_id: Option<&str>,
19        client_id: Option<u32>,
20    ) -> Result<Order> {
21        let mut url = self.base_url.join(API_ORDER)?;
22        {
23            let mut query = url.query_pairs_mut();
24            query.append_pair("symbol", symbol);
25            if let Some(order_id) = order_id {
26                query.append_pair("orderId", order_id);
27            } else {
28                query.append_pair(
29                    "clientId",
30                    &client_id
31                        .ok_or_else(|| {
32                            Error::InvalidRequest("either order_id or client_id is required".into())
33                        })?
34                        .to_string(),
35                );
36            }
37        }
38        let res = self.get(url).await?;
39        res.json().await.map_err(Into::into)
40    }
41
42    /// Executes a new order with the given payload.
43    pub async fn execute_order(&self, payload: ExecuteOrderPayload) -> Result<Order> {
44        let endpoint = self.base_url.join(API_ORDER)?;
45        let res = self.post(endpoint, payload).await?;
46        res.json().await.map_err(Into::into)
47    }
48
49    /// Cancels a specific order by symbol and either order ID or client ID.
50    pub async fn cancel_order(
51        &self,
52        symbol: &str,
53        order_id: Option<&str>,
54        client_id: Option<u32>,
55    ) -> Result<Order> {
56        let url = self.base_url.join(API_ORDER)?;
57        let payload = CancelOrderPayload {
58            symbol: symbol.to_string(),
59            order_id: order_id.map(|s| s.to_string()),
60            client_id,
61        };
62
63        let res = self.delete(url, payload).await?;
64        res.json().await.map_err(Into::into)
65    }
66
67    /// Retrieves all open orders, optionally filtered by symbol.
68    pub async fn get_open_orders(&self, symbol: Option<&str>) -> Result<Vec<Order>> {
69        let mut url = self.base_url.join(API_ORDERS)?;
70        if let Some(s) = symbol {
71            url.query_pairs_mut().append_pair("symbol", s);
72        }
73        let res = self.get(url).await?;
74        res.json().await.map_err(Into::into)
75    }
76
77    /// Cancels all open orders matching the specified payload.
78    pub async fn cancel_open_orders(&self, payload: CancelOpenOrdersPayload) -> Result<Vec<Order>> {
79        let url = self.base_url.join(API_ORDERS)?;
80        let res = self.delete(url, payload).await?;
81        res.json().await.map_err(Into::into)
82    }
83}