asterdex_sdk/futures/endpoints/
batch.rs1use crate::futures::models::account::{BatchOrderResult, CancelAllResponse};
4use crate::futures::models::trading::PlaceOrderParams;
5use crate::rest::client::RestClient;
6use crate::rest::error::AsterDexError;
7use crate::rest::response::ApiResponse;
8
9const BATCH_ORDER_MAX: usize = 5;
10
11impl RestClient {
12 pub async fn place_batch_orders(
15 &self,
16 orders: Vec<PlaceOrderParams>,
17 ) -> Result<ApiResponse<Vec<BatchOrderResult>>, AsterDexError> {
18 if orders.len() > BATCH_ORDER_MAX {
19 return Err(AsterDexError::InvalidParams {
20 message: format!("Too many orders: max {BATCH_ORDER_MAX}, got {}", orders.len()),
21 });
22 }
23 let orders_json = serde_json::to_string(&orders).map_err(|e| AsterDexError::SerdeError {
26 message: e.to_string(),
27 })?;
28 self.signed_post("/fapi/v3/batchOrders", &[("batchOrders", &orders_json)]).await
29 }
30
31 pub async fn cancel_batch_orders(
33 &self,
34 symbol: &str,
35 order_ids: Vec<i64>,
36 ) -> Result<ApiResponse<Vec<BatchOrderResult>>, AsterDexError> {
37 let ids_json = serde_json::to_string(&order_ids).map_err(|e| AsterDexError::SerdeError {
38 message: e.to_string(),
39 })?;
40 self.signed_delete("/fapi/v3/batchOrders", &[
41 ("symbol", symbol),
42 ("orderIdList", &ids_json),
43 ]).await
44 }
45
46 pub async fn cancel_all_open_orders(
48 &self,
49 symbol: &str,
50 ) -> Result<ApiResponse<CancelAllResponse>, AsterDexError> {
51 self.signed_delete("/fapi/v3/allOpenOrders", &[("symbol", symbol)]).await
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58 use crate::auth::Credentials;
59
60 #[tokio::test]
64 async fn place_batch_orders_too_many_returns_invalid_params() {
65 let client = RestClient::new_public("http://localhost:9999").unwrap();
66 let orders: Vec<PlaceOrderParams> = (0..6).map(|_| PlaceOrderParams::default()).collect();
67 let result = client.place_batch_orders(orders).await;
68 assert!(
69 matches!(result, Err(AsterDexError::InvalidParams { .. })),
70 "expected InvalidParams, got: {:?}",
71 result
72 );
73 }
74
75 #[tokio::test]
77 async fn cancel_all_open_orders_mock() {
78 let mut server = mockito::Server::new_async().await;
79 let _mock = server
80 .mock("DELETE", "/fapi/v3/allOpenOrders")
81 .match_query(mockito::Matcher::Any)
82 .with_status(200)
83 .with_header("content-type", "application/json")
84 .with_body(r#"{"code":200,"msg":"The operation of cancel orders is done."}"#)
85 .create_async()
86 .await;
87
88 let creds = Credentials::new(
89 "0x0000000000000000000000000000000000000001",
90 "0x0000000000000000000000000000000000000002",
91 "0000000000000000000000000000000000000000000000000000000000000001",
92 714,
93 )
94 .unwrap();
95 let client = RestClient::new(&server.url(), creds).unwrap();
96 let resp = client.cancel_all_open_orders("BTCUSDT").await.unwrap();
97 assert_eq!(resp.data.code, 200);
98 }
99}