use serde_json::json;
use whisky::WError;
use crate::{
order::{
BuildPlaceOrderTransactionResponse, CancelAllOrdersResponse, CancelOrderResponse,
SubmitPlaceOrderTransactionResponse,
},
OrderSide, OrderType,
};
use super::Api;
pub struct Order {
pub api: Api,
pub path_url: String,
}
impl Order {
pub fn new(api: Api) -> Self {
Order {
api,
path_url: "/order".to_string(),
}
}
pub async fn build_place_order_transaction(
&self,
symbol: &str,
side: OrderSide,
order_type: OrderType,
base_quantity: Option<String>,
quote_quantity: Option<String>,
price: Option<String>,
max_slippage_basis_point: Option<String>,
post_only: Option<bool>,
) -> Result<BuildPlaceOrderTransactionResponse, WError> {
if symbol.is_empty() {
return Err(WError::new(
"build_place_order_transaction",
"Missing required parameter: symbol",
));
}
match (&base_quantity, "e_quantity) {
(None, None) => {
return Err(WError::new(
"build_place_order_transaction",
"Either base_quantity or quote_quantity must be provided",
));
}
(Some(_), Some(_)) => {
return Err(WError::new(
"build_place_order_transaction",
"Cannot provide both base_quantity and quote_quantity",
));
}
_ => {}
}
if order_type == OrderType::Limit && price.is_none() {
return Err(WError::new(
"build_place_order_transaction",
"Missing required parameter: price for limit order",
));
}
let mut payload = json!({
"symbol": symbol,
"side": side,
"type": order_type,
"post_only": post_only.unwrap_or(false),
});
if let Some(base_qty) = base_quantity {
payload["base_quantity"] = json!(base_qty);
}
if let Some(quote_qty) = quote_quantity {
payload["quote_quantity"] = json!(quote_qty);
}
if let Some(p) = price {
payload["price"] = json!(p);
}
if let Some(slippage) = max_slippage_basis_point {
payload["max_slippage_basis_point"] = json!(slippage);
}
let url = format!("{}/build", self.path_url);
let response = self.api.post(&url, payload).await?;
Ok(serde_json::from_str(&response)
.map_err(WError::from_err("build_place_order_transaction"))?)
}
pub async fn submit_place_order_transaction(
&self,
order_id: &str,
signed_tx: &str,
) -> Result<SubmitPlaceOrderTransactionResponse, WError> {
let payload = json!({
"order_id": order_id,
"signed_tx": signed_tx,
});
let url = format!("{}/submit", self.path_url);
let response = self.api.post(&url, payload).await?;
Ok(serde_json::from_str(&response)
.map_err(WError::from_err("submit_place_order_transaction"))?)
}
pub async fn cancel_order(&self, order_id: &str) -> Result<CancelOrderResponse, WError> {
let url = format!("{}/{}/cancel", self.path_url, order_id);
let response = self.api.post(&url, json!({})).await?;
Ok(serde_json::from_str(&response).map_err(WError::from_err("cancel_order"))?)
}
pub async fn cancel_all_orders(
&self,
symbol: &str,
) -> Result<CancelAllOrdersResponse, WError> {
let url = format!("{}/cancel-all", self.path_url);
let payload = json!({
"symbol": symbol,
});
let response = self.api.post(&url, payload).await?;
Ok(serde_json::from_str(&response).map_err(WError::from_err("cancel_all_orders"))?)
}
}