use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::spot::event::SpotEvent;
use super::event::{self, EventQueue};
use super::orderbook::{OrderBook, OrderBookError};
use super::orders::OrderId;
use super::pair::Pair;
use super::time_in_force::TimeInForce;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MatchingEngine {
pairs: HashMap<Vec<u8>, Pair>,
total_pairs: u32,
}
impl MatchingEngine {
pub fn new() -> Self {
Self {
pairs: HashMap::new(),
total_pairs: 0,
}
}
pub fn add_pair(&mut self, cid: impl Into<Vec<u8>>, client_admin_account_id: impl Into<Vec<u8>>, client_fee_account_id: impl Into<Vec<u8>>, pair_id: impl Into<Vec<u8>>, timestamp: i64) {
let pair_id_vec = pair_id.into();
if self.pairs.contains_key(&pair_id_vec) {
let cid_vec = cid.into();
self.pairs.get_mut(&pair_id_vec).unwrap().add_client(cid_vec.clone(), client_admin_account_id, client_fee_account_id);
event::emit_event(SpotEvent::SpotPairAdded {
cid: cid_vec,
pair_id: pair_id_vec,
timestamp: timestamp,
});
return;
}
let mut pair = Pair::new();
pair.pair_id = pair_id_vec.clone();
let cid_vec = cid.into();
pair.add_client(cid_vec.clone(), client_admin_account_id, client_fee_account_id);
event::emit_event(SpotEvent::SpotPairAdded {
cid: cid_vec,
pair_id: pair_id_vec.clone(),
timestamp: timestamp,
});
self.pairs.insert(pair_id_vec, pair);
self.total_pairs += 1;
}
pub fn add_pair_client(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
admin_account_id: impl Into<Vec<u8>>,
fee_account_id: impl Into<Vec<u8>>,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.add_client(cid.into(), admin_account_id, fee_account_id);
Ok(event::drain_events())
}
pub fn limit_sell(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
existing_order_id: Option<OrderId>,
owner: impl Into<Vec<u8>>,
price: u64,
amnt: u64,
iqty: u64,
timestamp: i64,
expires_at: i64,
maker_fee_bps: i16,
taker_fee_bps: i16,
time_in_force: TimeInForce,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.limit_sell(
cid,
existing_order_id,
owner,
price,
amnt,
iqty,
timestamp,
expires_at,
maker_fee_bps,
taker_fee_bps,
time_in_force,
)?;
let events = event::drain_events();
Ok(events)
}
pub fn limit_buy(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
existing_order_id: Option<OrderId>,
owner: impl Into<Vec<u8>>,
price: u64,
amount: u64,
public_amount: u64,
timestamp: i64,
expires_at: i64,
maker_fee_bps: i16,
taker_fee_bps: i16,
time_in_force: TimeInForce,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.limit_buy(
cid,
existing_order_id,
owner,
price,
amount,
public_amount,
timestamp,
expires_at,
maker_fee_bps,
taker_fee_bps,
time_in_force,
)?;
let events = event::drain_events();
Ok(events)
}
pub fn market_sell(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
existing_order_id: Option<OrderId>,
owner: impl Into<Vec<u8>>,
amount: u64,
public_amount: u64,
timestamp: i64,
expires_at: i64,
maker_fee_bps: i16,
taker_fee_bps: i16,
time_in_force: TimeInForce,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.market_sell(
cid,
existing_order_id,
owner,
amount,
public_amount,
timestamp,
expires_at,
maker_fee_bps,
taker_fee_bps,
time_in_force,
)?;
let events = event::drain_events();
Ok(events)
}
pub fn market_buy(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
existing_order_id: Option<OrderId>,
owner: impl Into<Vec<u8>>,
amount: u64,
public_amount: u64,
timestamp: i64,
expires_at: i64,
maker_fee_bps: i16,
taker_fee_bps: i16,
time_in_force: TimeInForce,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.market_buy(
cid,
existing_order_id,
owner,
amount,
public_amount,
timestamp,
expires_at,
maker_fee_bps,
taker_fee_bps,
time_in_force,
)?;
let events = event::drain_events();
Ok(events)
}
pub fn cancel_order(
&mut self,
cid: impl Into<Vec<u8>>,
pair_id: impl Into<Vec<u8>>,
order_id: OrderId,
owner: impl Into<Vec<u8>>,
is_bid: bool,
) -> Result<EventQueue, OrderBookError> {
let pair_id_vec = pair_id.into();
let pair = self.pairs.get_mut(&pair_id_vec).unwrap();
pair.cancel_order(cid, pair_id_vec, is_bid, order_id, owner)?;
let events = event::drain_events();
Ok(events)
}
pub fn pair_count(&self) -> usize {
self.pairs.len()
}
pub fn has_pair(&self, pair_id: &Vec<u8>) -> bool {
self.pairs.contains_key(&pair_id.clone())
}
pub fn orderbook(&self, pair_id: &[u8]) -> Option<&OrderBook> {
self.pairs.get(pair_id).map(|p| &p.orderbook)
}
}
impl Default for MatchingEngine {
fn default() -> Self {
Self::new()
}
}