use crate::{
OrderId,
domain::{
event::{
CancellationReason,
Identity,
},
trade::TradeId,
},
fuel_types::{
AssetId,
Bytes32,
ContractId,
TxId,
},
parse::{
HexDisplayFromStr,
serialize_hex,
},
primitives::{
OrderType,
Side,
},
};
use serde_with::{
DisplayFromStr,
serde_as,
};
use sha2::{
Digest,
Sha256,
};
use std::collections::BTreeMap;
pub type Price = u64;
pub type Quantity = u64;
pub type MarketId = Bytes32;
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum BaseQuantity {
Quantity(Quantity),
Infinite,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum UnderlyingAsset {
Base {
remaining_quantity: Quantity,
},
Quote {
desired_base_quantity: BaseQuantity,
remaining_quote_token: Quantity,
},
}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, Hash,
)]
pub struct MarketIdAssets {
pub base_asset: AssetId,
pub quote_asset: AssetId,
}
impl MarketIdAssets {
pub fn market_id(&self) -> MarketId {
let bytes: Vec<u8> = self
.quote_asset
.into_iter()
.chain(self.base_asset.to_vec())
.collect();
let digest = Sha256::digest(bytes.as_slice());
MarketId::new(digest.into())
}
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AssetConfig {
pub symbol: String,
#[serde(serialize_with = "serialize_hex")]
pub asset: AssetId,
pub decimals: u8,
pub min_precision: u8,
pub max_precision: u8,
}
#[serde_as]
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct OrderBookConfig {
#[serde_as(as = "Option<HexDisplayFromStr>")]
pub contract_id: Option<ContractId>,
#[serde_as(as = "Option<HexDisplayFromStr>")]
pub blob_id: Option<ContractId>,
#[serde_as(as = "HexDisplayFromStr")]
pub market_id: MarketId,
#[serde_as(as = "DisplayFromStr")]
pub taker_fee: u64,
#[serde_as(as = "DisplayFromStr")]
pub maker_fee: u64,
#[serde_as(as = "DisplayFromStr")]
pub min_order: u64,
#[serde_as(as = "DisplayFromStr")]
pub dust: u64,
pub price_window: u8,
pub base: AssetConfig,
pub quote: AssetConfig,
}
#[derive(
Default, Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize,
)]
pub struct Fill {
pub order_id: OrderId,
pub quantity: Quantity,
pub price: Price,
pub timestamp: u128,
pub fee: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum HistoryStep {
Confirmed { tx_id: TxId },
}
impl HistoryStep {
pub fn kind(&self) -> String {
match self {
HistoryStep::Confirmed { .. } => "confirmed".to_string(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum OrderHistory {
Created {
tx: HistoryStep,
},
Trade {
tx: HistoryStep,
trade_id: TradeId,
},
Canceled {
tx: HistoryStep,
reason: CancellationReason,
},
}
impl OrderHistory {
pub fn kind(&self) -> String {
match self {
OrderHistory::Created { .. } => "created".to_string(),
OrderHistory::Trade { .. } => "trade".to_string(),
OrderHistory::Canceled { .. } => "canceled".to_string(),
}
}
pub fn status_kind(&self) -> String {
match self {
OrderHistory::Created { tx } => tx.kind(),
OrderHistory::Trade { tx, .. } => tx.kind(),
OrderHistory::Canceled { tx, .. } => tx.kind(),
}
}
pub fn tx_id(&self) -> TxId {
match self {
OrderHistory::Created { tx } => match tx {
HistoryStep::Confirmed { tx_id } => *tx_id,
},
OrderHistory::Trade { tx, .. } => match tx {
HistoryStep::Confirmed { tx_id } => *tx_id,
},
OrderHistory::Canceled { tx, .. } => match tx {
HistoryStep::Confirmed { tx_id } => *tx_id,
},
}
}
}
#[derive(
Copy,
Clone,
Debug,
strum_macros::EnumCount,
strum_macros::IntoStaticStr,
strum_macros::FromRepr,
PartialEq,
Eq,
enum_iterator::Sequence,
Hash,
)]
#[repr(u8)]
pub enum OrderStatus {
Active,
Canceled,
Filled,
PartiallyFilled,
}
impl TryFrom<u8> for OrderStatus {
type Error = anyhow::Error;
fn try_from(value: u8) -> Result<Self, Self::Error> {
OrderStatus::from_repr(value).ok_or_else(|| {
anyhow::anyhow!("Invalid value for OrderStatus enum: {}", value)
})
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct Order {
pub order_id: OrderId,
pub account: Identity,
pub side: Side,
pub order_type: OrderType,
pub price: Price,
pub desired_quantity: UnderlyingAsset,
pub fill: Vec<Fill>,
pub timestamp: u128,
pub order_tx_history: Vec<OrderHistory>,
pub base_decimals: u64,
}
#[serde_as]
#[derive(Default, serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)]
pub struct OrderBookBalance {
#[serde_as(as = "DisplayFromStr")]
locked: u128,
#[serde_as(as = "DisplayFromStr")]
unlocked: u128,
#[serde_as(as = "DisplayFromStr")]
fee: u128,
}
impl OrderBookBalance {
pub fn locked(&self) -> u128 {
self.locked
}
pub fn unlocked(&self) -> u128 {
self.unlocked
}
pub fn fee(&self) -> u128 {
self.fee
}
}
pub type OrderBooksBalances = BTreeMap<ContractId, OrderBookBalance>;