Skip to content

Commit

Permalink
refactor dlob node & add node lists
Browse files Browse the repository at this point in the history
  • Loading branch information
soundsonacid committed Mar 6, 2024
1 parent 4a51b36 commit 478d3d0
Show file tree
Hide file tree
Showing 5 changed files with 678 additions and 14 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ thiserror = "1.0.38"
tokio = { version = "1.34.0", features = ["full"] }
tokio-tungstenite = { version = "0.21.0", features = ["native-tls"] }
regex = "1.10.2"
dashmap = "5.5.3"

[dev-dependencies]
pyth = { git = "https://github.com/drift-labs/protocol-v2.git", tag = "v2.67.0", features = [
Expand Down
261 changes: 248 additions & 13 deletions src/dlob/dlob_node.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,30 @@
use drift::state::{oracle::OraclePriceData, user::Order};
use solana_sdk::pubkey::Pubkey;

#[derive(Clone, Copy)]
pub enum NodeType {
TakingLimit,
RestingLimit,
FloatingLimit,
Market,
Trigger,
}

#[derive(PartialEq, Eq)]
pub enum SortDirection {
Ascending,
Descending
}

macro_rules! impl_order_node {
($($node_type:ident),+) => {
$(
#[derive(Clone)]
pub struct $node_type {
pub order: Order,
pub user_account: Pubkey,
pub next: Option<Box<$node_type>>,
pub previous: Option<Box<$node_type>>,
pub next: Option<*mut $node_type>,
pub previous: Option<*mut $node_type>,
}

impl $node_type {
Expand Down Expand Up @@ -48,11 +64,52 @@ macro_rules! impl_order_node {
fn is_vamm_node(&self) -> bool {
false
}

fn get_order(&self) -> &Order {
&self.order
}

fn get_next_ptr(&self) -> Option<*mut dyn DLOBNode> {
self.next.map(|ptr| ptr as *mut dyn DLOBNode)
}

fn get_prev_ptr(&self) -> Option<*mut dyn DLOBNode> {
self.previous.map(|ptr| ptr as *mut dyn DLOBNode)
}

fn get_user_account(&self) -> Pubkey {
self.user_account
}

fn set_next(&mut self, next: Option<*mut dyn DLOBNode>) {
self.next = next.map(|ptr| ptr as *mut $node_type);
}

fn set_prev(&mut self, prev: Option<*mut dyn DLOBNode>) {
self.previous = prev.map(|ptr| ptr as *mut $node_type);
}

fn set_order(&mut self, order: Order) {
self.order = order;
}
}
)+
};
}

pub fn create_node(node_type: NodeType, order: Order, user_account: Pubkey) -> Box<dyn DLOBNode> {
match node_type {
NodeType::TakingLimit => Box::new(TakingLimitOrderNode::new(order, user_account)),
NodeType::RestingLimit => Box::new(RestingLimitOrderNode::new(order, user_account)),
NodeType::FloatingLimit => Box::new(FloatingLimitOrderNode::new(order, user_account)),
NodeType::Market => Box::new(MarketOrderNode::new(order, user_account)),
NodeType::Trigger => Box::new(TriggerOrderNode::new(order, user_account)),
}
}

pub fn get_order_signature(order_id: u32, user_account: Pubkey) -> String {
format!("{}-{}", order_id, user_account.to_string())
}

pub trait DLOBNode {
fn get_price(&self, oracle_price_data: OraclePriceData, slot: u64, tick_size: u64) -> Option<u64>;
Expand All @@ -62,8 +119,31 @@ pub trait DLOBNode {
fn is_base_filled(&self) -> bool;

fn get_sort_value(&self, order: &Order) -> Option<i128>;

fn get_order(&self) -> &Order;

fn get_next_ptr(&self) -> Option<*mut dyn DLOBNode>;

fn get_prev_ptr(&self) -> Option<*mut dyn DLOBNode>;

fn get_user_account(&self) -> Pubkey;

fn set_next(&mut self, next: Option<*mut dyn DLOBNode>);

fn set_prev(&mut self, next: Option<*mut dyn DLOBNode>);

fn set_order(&mut self, order: Order);
}

pub trait DLOBNodePointerExt {
unsafe fn to_node(&self) -> Option<&dyn DLOBNode>;
}

impl DLOBNodePointerExt for Option<*mut dyn DLOBNode> {
unsafe fn to_node(&self) -> Option<&dyn DLOBNode> {
self.map(|ptr| &*ptr)
}
}
pub struct VAMMNode {
pub order: Order,
pub price: u64,
Expand All @@ -85,6 +165,34 @@ impl DLOBNode for VAMMNode {
fn get_sort_value(&self, _order: &Order) -> Option<i128> {
None
}

fn get_order(&self) -> &Order {
&self.order
}

fn get_next_ptr(&self) -> Option<*mut dyn DLOBNode> {
None
}

fn get_prev_ptr(&self) -> Option<*mut dyn DLOBNode> {
None
}

fn set_next(&mut self, _next: Option<*mut dyn DLOBNode>) {
unimplemented!()
}

fn set_prev(&mut self, _prev: Option<*mut dyn DLOBNode>) {
unimplemented!()
}

fn get_user_account(&self) -> Pubkey {
unimplemented!()
}

fn set_order(&mut self, _order: Order) {
unimplemented!()
}
}

impl VAMMNode {
Expand All @@ -103,9 +211,7 @@ mod test {
use super::*;

#[test]
fn test_macro() {
impl_order_node!(TakingLimitOrderNode, RestingLimitOrderNode, FloatingLimitOrderNode, MarketOrderNode, TriggerOrderNode);

fn test_set_next_prev() {
let mut order = Order::default();

order.slot = 100;
Expand All @@ -115,19 +221,148 @@ mod test {

let user_account = Pubkey::new_unique();

let taking_limit_order_node = TakingLimitOrderNode::new(order, user_account);
let resting_limit_order_node = RestingLimitOrderNode::new(order, user_account);
let floating_limit_order_node = FloatingLimitOrderNode::new(order, user_account);
let market_order_node = MarketOrderNode::new(order, user_account);
let trigger_order_node = TriggerOrderNode::new(order, user_account);
let vamm_node = VAMMNode::new(order, 100);
let mut taking_limit_order_node = create_node(NodeType::TakingLimit, order, user_account);
let mut resting_limit_order_node = create_node(NodeType::RestingLimit, order, user_account);
let mut floating_limit_order_node = create_node(NodeType::FloatingLimit, order, user_account);
let mut market_order_node = create_node(NodeType::Market, order, user_account);
let mut trigger_order_node = create_node(NodeType::Trigger, order, user_account);

assert_eq!(taking_limit_order_node.get_sort_value(&order), Some(100));
assert_eq!(resting_limit_order_node.get_sort_value(&order), Some(1_000));
assert_eq!(market_order_node.get_sort_value(&order), Some(100));
assert_eq!(trigger_order_node.get_sort_value(&order), Some(500));
assert_eq!(floating_limit_order_node.get_sort_value(&order), Some(5_000));
assert_eq!(vamm_node.get_sort_value(&order), None);


let mut order_2 = Order::default();

order_2.slot = 200;
order_2.price = 2_000;
order_2.trigger_price = 600;
order_2.oracle_price_offset = 6_000;

let mut taking_limit_order_node_2 = create_node(NodeType::TakingLimit, order_2, user_account);
let mut resting_limit_order_node_2 = create_node(NodeType::RestingLimit, order_2, user_account);
let mut floating_limit_order_node_2 = create_node(NodeType::FloatingLimit, order_2, user_account);
let mut market_order_node_2 = create_node(NodeType::Market, order_2, user_account);
let mut trigger_order_node_2 = create_node(NodeType::Trigger, order_2, user_account);


assert_eq!(taking_limit_order_node_2.get_sort_value(&order_2), Some(200));
assert_eq!(resting_limit_order_node_2.get_sort_value(&order_2), Some(2_000));
assert_eq!(market_order_node_2.get_sort_value(&order_2), Some(200));
assert_eq!(trigger_order_node_2.get_sort_value(&order_2), Some(600));
assert_eq!(floating_limit_order_node_2.get_sort_value(&order_2), Some(6_000));

taking_limit_order_node.set_next(Some(&mut *taking_limit_order_node_2));
resting_limit_order_node.set_next(Some(&mut *resting_limit_order_node_2));
floating_limit_order_node.set_next(Some(&mut *floating_limit_order_node_2));
market_order_node.set_next(Some(&mut *market_order_node_2));
trigger_order_node.set_next(Some(&mut *trigger_order_node_2));

assert_eq!(unsafe { taking_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_2) }, Some(200));
assert_eq!(unsafe { resting_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_2) }, Some(2_000));
assert_eq!(unsafe { market_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_2) }, Some(200));
assert_eq!(unsafe { trigger_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_2) }, Some(600));
assert_eq!(unsafe { floating_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_2) }, Some(6_000));

let mut order_3 = Order::default();

order_3.slot = 300;
order_3.price = 3_000;
order_3.trigger_price = 700;
order_3.oracle_price_offset = 7_000;

let mut taking_limit_order_node_3 = create_node(NodeType::TakingLimit, order_3, user_account);
let mut resting_limit_order_node_3 = create_node(NodeType::RestingLimit, order_3, user_account);
let mut floating_limit_order_node_3 = create_node(NodeType::FloatingLimit, order_3, user_account);
let mut market_order_node_3 = create_node(NodeType::Market, order_3, user_account);
let mut trigger_order_node_3 = create_node(NodeType::Trigger, order_3, user_account);

assert_eq!(taking_limit_order_node_3.get_sort_value(&order_3), Some(300));
assert_eq!(resting_limit_order_node_3.get_sort_value(&order_3), Some(3_000));
assert_eq!(market_order_node_3.get_sort_value(&order_3), Some(300));
assert_eq!(trigger_order_node_3.get_sort_value(&order_3), Some(700));
assert_eq!(floating_limit_order_node_3.get_sort_value(&order_3), Some(7_000));

taking_limit_order_node.set_prev(Some(&mut *taking_limit_order_node_3));
resting_limit_order_node.set_prev(Some(&mut *resting_limit_order_node_3));
floating_limit_order_node.set_prev(Some(&mut *floating_limit_order_node_3));
market_order_node.set_prev(Some(&mut *market_order_node_3));
trigger_order_node.set_prev(Some(&mut *trigger_order_node_3));

assert_eq!(unsafe { taking_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_3) }, Some(300));
assert_eq!(unsafe { resting_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_3) }, Some(3_000));
assert_eq!(unsafe { market_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_3) }, Some(300));
assert_eq!(unsafe { trigger_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_3) }, Some(700));
assert_eq!(unsafe { floating_limit_order_node.get_next_ptr().to_node().unwrap().get_sort_value(&order_3) }, Some(7_000));
}

#[test]
fn test_set_order() {
let user_account = Pubkey::new_unique();

let mut order = Order::default();

order.slot = 100;
order.price = 1_000;
order.trigger_price = 500;
order.oracle_price_offset = 5_000;

let mut taking_limit_order_node = create_node(NodeType::TakingLimit, order, user_account);
let mut resting_limit_order_node = create_node(NodeType::RestingLimit, order, user_account);
let mut floating_limit_order_node = create_node(NodeType::FloatingLimit, order, user_account);
let mut market_order_node = create_node(NodeType::Market, order, user_account);
let mut trigger_order_node = create_node(NodeType::Trigger, order, user_account);

let mut order_2 = Order::default();

order_2.slot = 200;
order_2.price = 2_000;
order_2.trigger_price = 600;
order_2.oracle_price_offset = 6_000;

taking_limit_order_node.set_order(order_2);
resting_limit_order_node.set_order(order_2);
floating_limit_order_node.set_order(order_2);
market_order_node.set_order(order_2);
trigger_order_node.set_order(order_2);

assert_eq!(taking_limit_order_node.get_order().slot, 200);
assert_eq!(resting_limit_order_node.get_order().price, 2_000);
assert_eq!(floating_limit_order_node.get_order().oracle_price_offset, 6_000);
assert_eq!(market_order_node.get_order().slot, 200);
assert_eq!(trigger_order_node.get_order().trigger_price, 600);
}

#[test]
#[should_panic(expected = "not implemented")]
fn test_vamm_node_set_next_panics() {
let order = Order::default();
let mut vamm_node = VAMMNode::new(order, 100);
vamm_node.set_next(None);
}

#[test]
#[should_panic(expected = "not implemented")]
fn test_vamm_node_set_prev_panics() {
let order = Order::default();
let mut vamm_node = VAMMNode::new(order, 100);
vamm_node.set_prev(None);
}

#[test]
#[should_panic(expected = "not implemented")]
fn test_vamm_node_get_user_account_panics() {
let order = Order::default();
let vamm_node = VAMMNode::new(order, 100);
vamm_node.get_user_account();
}

#[test]
#[should_panic(expected = "not implemented")]
fn test_vamm_node_set_order_panics() {
let order = Order::default();
let mut vamm_node = VAMMNode::new(order, 100);
vamm_node.set_order(order);
}
}
3 changes: 2 additions & 1 deletion src/dlob/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod dlob_node;
pub mod dlob_node;
pub mod node_list;
Loading

0 comments on commit 478d3d0

Please sign in to comment.