use crate::client::request::{body, dex, number, text, user};
use crate::client::{ApiError, Transport, info};
use crate::trade::modify::OrderRef;
use crate::utils::Address;
use serde::{Deserialize, Deserializer, de};
pub use crate::account::order::{FrontendOrder, OpenOrder, OrderKind, OrderRecord, OrderState};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OrderLookup {
Found(Box<OrderRecord>),
Unknown,
}
impl<'de> Deserialize<'de> for OrderLookup {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
#[derive(Deserialize)]
struct Raw {
status: String,
#[serde(default)]
order: Option<OrderRecord>,
}
let raw = Raw::deserialize(deserializer)?;
match (raw.status.as_str(), raw.order) {
("order", Some(order)) => Ok(OrderLookup::Found(Box::new(order))),
("unknownOid", _) => Ok(OrderLookup::Unknown),
(other, _) => Err(de::Error::custom(format!("orderStatus answered `{other}`"))),
}
}
}
#[must_use]
pub fn open_orders_request(account: Address, on: Option<&str>) -> String {
body("openOrders", [user(account)].into_iter().chain(dex(on)))
}
#[must_use]
pub fn frontend_open_orders_request(account: Address, on: Option<&str>) -> String {
body("frontendOpenOrders", [user(account)].into_iter().chain(dex(on)))
}
#[must_use]
pub fn order_status_request(account: Address, target: OrderRef) -> String {
let oid = match target {
OrderRef::Oid(oid) => number(oid),
OrderRef::Cloid(cloid) => text(&cloid.to_hex()),
};
body("orderStatus", [user(account), ("oid", oid)])
}
#[must_use]
pub fn historical_orders_request(account: Address) -> String {
body("historicalOrders", [user(account)])
}
pub async fn open_orders(
transport: &impl Transport,
account: Address,
on: Option<&str>,
) -> Result<Vec<OpenOrder>, ApiError> {
info(transport, open_orders_request(account, on)).await
}
pub async fn frontend_open_orders(
transport: &impl Transport,
account: Address,
on: Option<&str>,
) -> Result<Vec<FrontendOrder>, ApiError> {
info(transport, frontend_open_orders_request(account, on)).await
}
pub async fn order_status(
transport: &impl Transport,
account: Address,
target: OrderRef,
) -> Result<OrderLookup, ApiError> {
info(transport, order_status_request(account, target)).await
}
pub async fn historical_orders(transport: &impl Transport, account: Address) -> Result<Vec<OrderRecord>, ApiError> {
info(transport, historical_orders_request(account)).await
}
#[cfg(test)]
#[path = "tests/orders.rs"]
mod tests;