use num_bigint::BigUint;
use serde::{Deserialize, Serialize};
use crate::{impl_from_uint_for, AssetAmount, OrderId, SpotMarketId};
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum OrderSide {
Ask = 1,
Bid = 2,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct SpotOrderDetail {
pub side: OrderSide,
pub price: AssetAmount,
pub volume: AssetAmount,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum AmmV2ExactTokens {
ExactInput {
amount: AssetAmount,
min_out: AssetAmount,
},
ExactOutput {
amount: AssetAmount,
max_in: AssetAmount,
},
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct AmmV2OrderDetail {
pub side: OrderSide,
pub exact_tokens: AmmV2ExactTokens,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum SpotOrder {
Spot(SpotOrderDetail),
AmmV2(AmmV2OrderDetail),
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct SubmitSpotOrder {
pub market_id: SpotMarketId,
pub order: SpotOrder,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub enum OrderScope {
Exact(OrderId),
Side(OrderSide),
All,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct CancelSpotOrder {
pub market_id: SpotMarketId,
pub scope: OrderScope,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct AddAmmV2Liquidity {
pub market_id: SpotMarketId,
pub base_asset_quantity: AssetAmount,
pub quote_asset_quantity: AssetAmount,
}
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct RemoveAmmV2Liquidity {
pub market_id: SpotMarketId,
pub liquidity_token_quantity: AssetAmount,
}
impl From<BigUint> for OrderSide {
fn from(side: BigUint) -> Self {
match side {
side if side == BigUint::from(1u8) => OrderSide::Ask,
side if side == BigUint::from(2u8) => OrderSide::Bid,
_ => panic!("invalid order side"),
}
}
}
impl Into<BigUint> for OrderSide {
fn into(self) -> BigUint {
match self {
OrderSide::Ask => BigUint::from(1u8),
OrderSide::Bid => BigUint::from(2u8),
}
}
}
impl_from_uint_for!(OrderSide, u8, u16, u32, u64, u128);
#[cfg(test)]
mod tests {
use ex3_serde::{bincode, cbor};
use super::*;
#[test]
fn test_submit_order_serde() {
let submit_order = SubmitSpotOrder {
market_id: SpotMarketId::from(1u8),
order: SpotOrder::Spot(SpotOrderDetail {
side: OrderSide::Ask,
price: 100u32.into(),
volume: 100u32.into(),
}),
};
let encoded = bincode::serialize(&submit_order).unwrap();
let decoded: SubmitSpotOrder = bincode::deserialize(&encoded).unwrap();
assert_eq!(submit_order, decoded);
let encoded = cbor::serialize(&submit_order).unwrap();
let decoded: SubmitSpotOrder = cbor::deserialize(&encoded).unwrap();
assert_eq!(submit_order, decoded);
}
#[test]
fn test_cancel_order_serde() {
let cancel_order = CancelSpotOrder {
market_id: SpotMarketId::from(1u8),
scope: OrderScope::Exact(OrderId::from(1u8)),
};
let encoded = bincode::serialize(&cancel_order).unwrap();
let decoded: CancelSpotOrder = bincode::deserialize(&encoded).unwrap();
assert_eq!(cancel_order, decoded);
let encoded = cbor::serialize(&cancel_order).unwrap();
let decoded: CancelSpotOrder = cbor::deserialize(&encoded).unwrap();
assert_eq!(cancel_order, decoded);
}
#[test]
fn test_add_amm_v2_liquidity_serde() {
let add_liquidity = AddAmmV2Liquidity {
market_id: SpotMarketId::from(1u8),
base_asset_quantity: AssetAmount::from(1u8),
quote_asset_quantity: AssetAmount::from(1u8),
};
let encoded = bincode::serialize(&add_liquidity).unwrap();
let decoded: AddAmmV2Liquidity = bincode::deserialize(&encoded).unwrap();
assert_eq!(add_liquidity, decoded);
let encoded = cbor::serialize(&add_liquidity).unwrap();
let decoded: AddAmmV2Liquidity = cbor::deserialize(&encoded).unwrap();
assert_eq!(add_liquidity, decoded);
}
#[test]
fn test_remove_amm_v2_liquidity_serde() {
let remove_liquidity = RemoveAmmV2Liquidity {
market_id: SpotMarketId::from(1u8),
liquidity_token_quantity: AssetAmount::from(1u8),
};
let encoded = bincode::serialize(&remove_liquidity).unwrap();
let decoded: RemoveAmmV2Liquidity = bincode::deserialize(&encoded).unwrap();
assert_eq!(remove_liquidity, decoded);
let encoded = cbor::serialize(&remove_liquidity).unwrap();
let decoded: RemoveAmmV2Liquidity = cbor::deserialize(&encoded).unwrap();
assert_eq!(remove_liquidity, decoded);
}
}