mexc_rs/spot/v3/
query_order.rs

1use crate::spot::v3::enums::{OrderSide, OrderStatus, OrderType};
2use crate::spot::v3::{ApiResponse, ApiResult};
3use crate::spot::MexcSpotApiClientWithAuthentication;
4use async_trait::async_trait;
5use chrono::{DateTime, Utc};
6use rust_decimal::Decimal;
7
8#[derive(Debug)]
9pub struct QueryOrderParams<'a> {
10    pub symbol: &'a str,
11    pub order_id: Option<&'a str>,
12    pub original_client_order_id: Option<&'a str>,
13}
14
15#[derive(Debug, serde::Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct QueryOrderQuery<'a> {
18    pub symbol: &'a str,
19    pub order_id: Option<&'a str>,
20    #[serde(rename = "origClientOrderId")]
21    pub original_client_order_id: Option<&'a str>,
22    /// Max 60000
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub recv_window: Option<u64>,
25    #[serde(with = "chrono::serde::ts_milliseconds")]
26    pub timestamp: DateTime<Utc>,
27}
28
29impl<'a> From<QueryOrderParams<'a>> for QueryOrderQuery<'a> {
30    fn from(params: QueryOrderParams<'a>) -> Self {
31        Self {
32            symbol: params.symbol,
33            order_id: params.order_id,
34            original_client_order_id: params.original_client_order_id,
35            recv_window: None,
36            timestamp: Utc::now(),
37        }
38    }
39}
40
41#[derive(Debug, serde::Deserialize)]
42#[serde(rename_all = "camelCase")]
43pub struct QueryOrderOutput {
44    pub symbol: String,
45    #[serde(rename = "origClientOrderId")]
46    pub original_client_order_id: Option<String>,
47    #[serde(rename = "orderId")]
48    pub order_id: String,
49    #[serde(rename = "clientOrderId")]
50    pub client_order_id: Option<String>,
51    pub price: Decimal,
52    #[serde(rename = "origQty")]
53    pub original_quantity: Decimal,
54    #[serde(rename = "executedQty")]
55    pub executed_quantity: Decimal,
56    #[serde(rename = "cummulativeQuoteQty")]
57    pub cummulative_quote_quantity: Decimal,
58    pub status: OrderStatus,
59    #[serde(rename = "timeInForce")]
60    pub time_in_force: Option<String>,
61    #[serde(rename = "type")]
62    pub order_type: OrderType,
63    pub side: OrderSide,
64    #[serde(rename = "stopPrice")]
65    pub stop_price: Decimal,
66    pub time: DateTime<Utc>,
67    #[serde(rename = "updateTime")]
68    pub update_time: DateTime<Utc>,
69    #[serde(rename = "isWorking")]
70    pub is_working: bool,
71}
72
73#[async_trait]
74pub trait QueryOrderEndpoint {
75    async fn query_order(&self, params: QueryOrderParams<'_>) -> ApiResult<QueryOrderOutput>;
76}
77
78#[async_trait]
79impl QueryOrderEndpoint for MexcSpotApiClientWithAuthentication {
80    async fn query_order(&self, params: QueryOrderParams<'_>) -> ApiResult<QueryOrderOutput> {
81        let endpoint = format!("{}/api/v3/order", self.endpoint.as_ref());
82        let query = QueryOrderQuery::from(params);
83        let query_with_signature = self.sign_query(query)?;
84
85        let response = self
86            .reqwest_client
87            .delete(&endpoint)
88            .query(&query_with_signature)
89            .send()
90            .await?;
91
92        let api_response = response.json::<ApiResponse<QueryOrderOutput>>().await?;
93        let output = api_response.into_api_result()?;
94
95        Ok(output)
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[tokio::test]
104    async fn query_order() {
105        let client = MexcSpotApiClientWithAuthentication::new_for_test();
106        let params = QueryOrderParams {
107            symbol: "KASUSDT",
108            order_id: None,
109            original_client_order_id: Some("MY_ORDER_ID"),
110        };
111        let result = client.query_order(params).await;
112        assert!(result.is_ok());
113    }
114}