hyperliquid_sdk_rs/providers/
order_tracker.rs

1use std::collections::HashMap;
2use std::sync::{Arc, RwLock};
3use uuid::Uuid;
4
5use crate::types::requests::OrderRequest;
6use crate::types::responses::ExchangeResponseStatus;
7
8#[derive(Clone, Debug)]
9pub struct TrackedOrder {
10    pub cloid: Uuid,
11    pub order: OrderRequest,
12    pub timestamp: u64,
13    pub status: OrderStatus,
14    pub response: Option<ExchangeResponseStatus>,
15}
16
17#[derive(Clone, Debug, PartialEq)]
18pub enum OrderStatus {
19    Pending,
20    Submitted,
21    Failed(String),
22}
23
24#[derive(Clone)]
25pub struct OrderTracker {
26    orders: Arc<RwLock<HashMap<Uuid, TrackedOrder>>>,
27}
28
29impl OrderTracker {
30    pub fn new() -> Self {
31        Self {
32            orders: Arc::new(RwLock::new(HashMap::new())),
33        }
34    }
35
36    /// Track a new order
37    pub fn track_order(&self, cloid: Uuid, order: OrderRequest, timestamp: u64) {
38        let tracked = TrackedOrder {
39            cloid,
40            order,
41            timestamp,
42            status: OrderStatus::Pending,
43            response: None,
44        };
45
46        let mut orders = self.orders.write().expect("order tracker rwlock poisoned");
47        orders.insert(cloid, tracked);
48    }
49
50    /// Update order status after submission
51    pub fn update_order_status(
52        &self,
53        cloid: &Uuid,
54        status: OrderStatus,
55        response: Option<ExchangeResponseStatus>,
56    ) {
57        let mut orders = self.orders.write().expect("order tracker rwlock poisoned");
58        if let Some(order) = orders.get_mut(cloid) {
59            order.status = status;
60            order.response = response;
61        }
62    }
63
64    /// Get a specific order by CLOID
65    pub fn get_order(&self, cloid: &Uuid) -> Option<TrackedOrder> {
66        let orders = self.orders.read().expect("order tracker rwlock poisoned");
67        orders.get(cloid).cloned()
68    }
69
70    /// Get all tracked orders
71    pub fn get_all_orders(&self) -> Vec<TrackedOrder> {
72        let orders = self.orders.read().expect("order tracker rwlock poisoned");
73        orders.values().cloned().collect()
74    }
75
76    /// Get orders by status
77    pub fn get_orders_by_status(&self, status: &OrderStatus) -> Vec<TrackedOrder> {
78        let orders = self.orders.read().expect("order tracker rwlock poisoned");
79        orders
80            .values()
81            .filter(|order| &order.status == status)
82            .cloned()
83            .collect()
84    }
85
86    /// Get pending orders
87    pub fn get_pending_orders(&self) -> Vec<TrackedOrder> {
88        self.get_orders_by_status(&OrderStatus::Pending)
89    }
90
91    /// Get submitted orders
92    pub fn get_submitted_orders(&self) -> Vec<TrackedOrder> {
93        self.get_orders_by_status(&OrderStatus::Submitted)
94    }
95
96    /// Get failed orders
97    pub fn get_failed_orders(&self) -> Vec<TrackedOrder> {
98        let orders = self.orders.read().expect("order tracker rwlock poisoned");
99        orders
100            .values()
101            .filter(|order| matches!(order.status, OrderStatus::Failed(_)))
102            .cloned()
103            .collect()
104    }
105
106    /// Clear all tracked orders
107    pub fn clear(&self) {
108        let mut orders = self.orders.write().expect("order tracker rwlock poisoned");
109        orders.clear();
110    }
111
112    /// Get the number of tracked orders
113    pub fn len(&self) -> usize {
114        let orders = self.orders.read().expect("order tracker rwlock poisoned");
115        orders.len()
116    }
117
118    /// Check if tracking is empty
119    pub fn is_empty(&self) -> bool {
120        let orders = self.orders.read().expect("order tracker rwlock poisoned");
121        orders.is_empty()
122    }
123}
124
125impl Default for OrderTracker {
126    fn default() -> Self {
127        Self::new()
128    }
129}