use crate::trade::error::TradeError;
use crate::trade::orders::Fit;
use crate::utils::json::Json;
use crate::utils::sign::goldilocks::Fp;
use crate::utils::sign::tx::{Attributes, BadTx, Tx, TxType, element, number};
use crate::utils::{Dec, Grid, MAX_SIZE_UNITS, MarketId, OrderRef, Side};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ModifyOrder {
pub market: MarketId,
pub order: OrderRef,
pub base_amount: u64,
pub price: u32,
pub trigger_price: u32,
pub attributes: Attributes,
}
impl ModifyOrder {
#[must_use]
pub const fn version(mut self, version: u64) -> ModifyOrder {
self.attributes = self.attributes.order_version(version);
self
}
#[must_use]
pub const fn with(mut self, attributes: Attributes) -> ModifyOrder {
self.attributes = attributes;
self
}
}
impl Tx for ModifyOrder {
fn tx_type(&self) -> TxType {
TxType::ModifyOrder
}
fn hash_fields(&self) -> Vec<Fp> {
vec![
element(self.market.get()),
element(self.order.index()),
element(self.base_amount),
element(self.price),
element(self.trigger_price),
]
}
fn info_fields(&self) -> Vec<(&'static str, Json)> {
vec![
("MarketIndex", number(self.market.get())),
("Index", number(self.order.index())),
("BaseAmount", number(self.base_amount)),
("Price", number(self.price)),
("TriggerPrice", number(self.trigger_price)),
]
}
fn attributes(&self) -> Attributes {
self.attributes
}
fn check(&self) -> Result<(), BadTx> {
self.attributes.check()?;
if self.base_amount > MAX_SIZE_UNITS {
return Err(BadTx::new("BaseAmount", "a size is at most 2^48 - 1 units"));
}
if self.price == 0 {
return Err(BadTx::new("Price", "a price is at least 1"));
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ModifyIntent {
market: MarketId,
order: OrderRef,
side: Side,
size: Dec,
price: Dec,
trigger: Option<Dec>,
fit: Fit,
}
impl ModifyIntent {
pub fn new(market: MarketId, order: impl Into<OrderRef>, side: Side, size: Dec, price: Dec) -> ModifyIntent {
ModifyIntent { market, order: order.into(), side, size, price, trigger: None, fit: Fit::Exact }
}
#[must_use]
pub const fn trigger(mut self, trigger: Dec) -> ModifyIntent {
self.trigger = Some(trigger);
self
}
#[must_use]
pub const fn fit(mut self, fit: Fit) -> ModifyIntent {
self.fit = fit;
self
}
pub fn build(&self, grid: Grid) -> Result<ModifyOrder, TradeError> {
let trigger_price = match self.trigger {
Some(trigger) => self.fit.trigger(grid, trigger)?,
None => 0,
};
let modify = ModifyOrder {
market: self.market,
order: self.order,
base_amount: self.fit.size(grid, self.size)?,
price: self.fit.price(grid, self.price, self.side)?,
trigger_price,
attributes: Attributes::NONE,
};
modify.check()?;
Ok(modify)
}
}
#[cfg(test)]
#[path = "tests/modify.rs"]
mod tests;