use crate::client::BitgetClient;
use crate::consts;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CancelOrderResp {
pub code: String,
pub msg: Option<String>,
pub request_time: Option<u64>,
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct BatchCancelOrderResp {
pub code: String,
pub msg: Option<String>,
pub request_time: Option<u64>,
pub data: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Clone)]
pub struct SpotOrderV2Req {
pub symbol: String,
pub side: String,
pub order_type: String,
pub force: String,
pub price: Option<String>,
pub size: String,
pub client_oid: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct SpotOrderV2Resp {
pub order_id: Option<String>,
pub client_oid: Option<String>,
pub msg: Option<String>,
}
impl BitgetClient {
pub fn place_spot_order_v2(&self, req: &SpotOrderV2Req) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), req.symbol.clone());
params.insert("side".to_string(), req.side.clone());
params.insert("orderType".to_string(), req.order_type.clone());
params.insert("force".to_string(), req.force.clone());
if let Some(price) = &req.price {
params.insert("price".to_string(), price.clone());
}
params.insert("size".to_string(), req.size.clone());
self.request(
consts::POST,
"/api/v2/spot/trade/place-order",
¶ms,
false,
)
}
pub fn cancel_futures_order(
&self,
symbol: &str,
order_id: &str,
margin_coin: &str,
) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
params.insert("orderId".to_string(), order_id.to_string());
params.insert("marginCoin".to_string(), margin_coin.to_string());
self.request(
consts::POST,
"/api/mix/v1/order/cancel-order",
¶ms,
false,
)
}
pub fn cancel_spot_order(&self, symbol: String, order_id: String) -> Result<CancelOrderResp> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol);
params.insert("orderId".to_string(), order_id);
let resp = self.request(
consts::POST,
"/api/v2/spot/trade/cancel-order",
¶ms,
false,
)?;
serde_json::from_str(&resp).map_err(|e| e.into())
}
pub fn batch_cancel_spot_order(
&self,
symbol: String,
order_ids: Vec<String>,
) -> Result<BatchCancelOrderResp> {
#[derive(Serialize)]
struct OrderItem {
order_id: String,
symbol: String,
#[serde(skip_serializing_if = "Option::is_none")]
client_oid: Option<String>,
}
let order_list: Vec<OrderItem> = order_ids
.into_iter()
.map(|order_id| OrderItem {
order_id,
symbol: symbol.clone(),
client_oid: None,
})
.collect();
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol);
params.insert("batchMode".to_string(), "multiple".to_string());
params.insert("orderList".to_string(), serde_json::to_string(&order_list)?);
let resp = self.request(
consts::POST,
"/api/v2/spot/trade/batch-cancel-order",
¶ms,
false,
)?;
serde_json::from_str(&resp).map_err(|e| e.into())
}
pub fn cancel_futures_orders(
&self,
symbol: &str,
order_ids: &[&str],
margin_coin: &str,
) -> Result<String> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol.to_string());
params.insert("orderIds".to_string(), order_ids.join(","));
params.insert("marginCoin".to_string(), margin_coin.to_string());
self.request(
consts::POST,
"/api/mix/v1/order/cancel-batch-orders",
¶ms,
false,
)
}
pub fn cancel_spot_symbol_orders(&self, symbol: String) -> Result<CancelOrderResp> {
let mut params = BTreeMap::new();
params.insert("symbol".to_string(), symbol);
let resp = self.request(
consts::POST,
"/api/v2/spot/trade/cancel-symbol-order",
¶ms,
false,
)?;
serde_json::from_str(&resp).map_err(|e| e.into())
}
}