1use serde::{Deserialize, Serialize};
2use std::collections::{BTreeMap, HashMap};
3use ulid::Ulid;
4
5pub type OrderId = Ulid;
6
7#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
9pub struct Order {
10 pub cid: Vec<u8>,
12 pub id: OrderId,
14 pub owner: Vec<u8>,
16 pub is_bid: bool,
18 pub price: u64,
20 pub amnt: u64,
22 pub iqty: u64,
24 pub pqty: u64,
26 pub cqty: u64,
28 pub timestamp: i64,
30 pub expires_at: i64,
32 pub fee_bps: i16,
34}
35
36impl Order {
37 #[allow(clippy::too_many_arguments)]
38 pub fn new(
39 cid: Vec<u8>,
40 id: OrderId,
41 owner: Vec<u8>,
42 is_bid: bool,
43 price: u64,
44 amnt: u64,
45 iqty: u64,
46 pqty: u64,
47 cqty: u64,
48 timestamp: i64,
49 expires_at: i64,
50 fee_bps: i16,
51 ) -> Self {
52 Self {
53 cid,
54 id,
55 owner,
56 is_bid,
57 price,
58 amnt,
59 iqty,
60 pqty,
61 cqty,
62 timestamp,
63 expires_at,
64 fee_bps,
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
70pub struct Node {
71 pub prev: Option<OrderId>,
72 pub next: Option<OrderId>,
73}
74
75#[derive(Debug, thiserror::Error, PartialEq, Eq)]
76pub enum L3Error {
77 #[error("price is zero")]
78 PriceIsZero,
79 #[error("order does not exist: {0}")]
80 OrderDoesNotExist(OrderId),
81 #[error("iceberg quantity is bigger than whole amount")]
82 IcebergQuantityIsBiggerThanWholeAmount,
83}
84
85#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
86pub struct L3 {
87 pub price_head: BTreeMap<u64, OrderId>,
89 pub price_tail: BTreeMap<u64, OrderId>,
91 pub order_nodes: HashMap<OrderId, Node>,
93 pub orders: HashMap<OrderId, Order>,
95 pub dust: u64,
97 pub dormant_order: Option<OrderId>,
99}
100
101impl L3 {
102 pub fn new() -> Self {
103 Self {
104 price_head: BTreeMap::new(),
105 price_tail: BTreeMap::new(),
106 order_nodes: HashMap::new(),
107 orders: HashMap::new(),
108 dust: 1,
109 dormant_order: None,
110 }
111 }
112
113 fn ensure_price(price: u64) -> Result<(), L3Error> {
114 if price == 0 {
115 Err(L3Error::PriceIsZero)
116 } else {
117 Ok(())
118 }
119 }
120
121 pub fn set_dust(&mut self, dust: u64) {
123 self.dust = dust;
124 }
125
126 pub fn insert_id(&mut self, price: u64, id: OrderId, _amount: u128) -> Result<(), L3Error> {
129 Self::ensure_price(price)?;
130 let order_node = self.order_nodes.get_mut(&id).ok_or(L3Error::OrderDoesNotExist(id))?;
132
133 let price_tail = self.price_tail.get(&price).copied();
134
135 if let Some(price_tail) = price_tail {
137 order_node.prev = Some(price_tail);
140 order_node.next = None;
141 let price_tail_node_ptr = self.order_nodes.get_mut(&price_tail).ok_or(L3Error::OrderDoesNotExist(price_tail))?;
143 price_tail_node_ptr.next = Some(id);
144 self.price_tail.insert(price, id);
146 }
147 else {
149 order_node.prev = None;
151 order_node.next = None;
152 self.price_head.insert(price, id);
153 self.price_tail.insert(price, id);
154 }
155
156 Ok(())
157 }
158
159 pub fn pop_front(&mut self, price: u64) -> Result<(Option<Order>, bool), L3Error> {
164 Self::ensure_price(price)?;
165 let head_id = self.price_head.get(&price).copied();
166 if let Some(head_id) = head_id {
167 let order_node = self
168 .order_nodes
169 .get_mut(&head_id)
170 .ok_or(L3Error::OrderDoesNotExist(head_id))?;
171 let next = order_node.next;
172 if let Some(next) = next {
173 order_node.next = None;
174 let next_node = self
175 .order_nodes
176 .get_mut(&next)
177 .ok_or(L3Error::OrderDoesNotExist(next))?;
178 next_node.prev = None;
179 self.price_head.insert(price, next);
181 let order = self.orders.get(&head_id).ok_or(L3Error::OrderDoesNotExist(head_id))?;
183 Ok((Some(order.clone()), false))
184 } else {
185 self.price_head.remove(&price);
186 self.price_tail.remove(&price);
187 let order = self.orders.get(&head_id).ok_or(L3Error::OrderDoesNotExist(head_id))?;
189 Ok((Some(order.clone()), true))
190 }
191 } else {
192 Ok((None, true))
193 }
194 }
195
196 pub fn set_iceberg_quantity(&mut self, id: OrderId, iqty: u64) -> Result<Order, L3Error> {
197 let order = self.orders.get_mut(&id).ok_or(L3Error::OrderDoesNotExist(id))?;
198 order.iqty = iqty;
200 if order.iqty > order.amnt {
202 return Err(L3Error::IcebergQuantityIsBiggerThanWholeAmount);
203 }
204
205 let new_pqty = order.amnt - order.iqty;
206
207 order.pqty = if order.cqty >= new_pqty { new_pqty } else { order.cqty };
208 Ok(order.clone())
209 }
210
211 pub fn create_order(
213 &mut self,
214 cid: impl Into<Vec<u8>>,
215 owner: impl Into<Vec<u8>>,
216 is_bid: bool,
217 price: u64,
218 amnt: u64,
219 iqty: u64,
220 timestamp: i64,
221 expires_at: i64,
222 maker_fee_bps: i16,
223 ) -> Result<Order, L3Error> {
224 Self::ensure_price(price)?;
225 let cid = cid.into();
226 let id = Ulid::new();
228 let owner = owner.into();
229 if iqty > amnt {
230 return Err(L3Error::IcebergQuantityIsBiggerThanWholeAmount);
231 }
232 let pqty = amnt - iqty;
233 let order = Order::new(
234 cid,
235 id,
236 owner,
237 is_bid,
238 price,
239 amnt,
240 iqty,
241 pqty,
242 amnt,
243 timestamp,
244 expires_at,
245 maker_fee_bps,
246 );
247
248 self.order_nodes.insert(
250 id,
251 Node {
252 prev: None,
253 next: None,
254 },
255 );
256 self.orders.insert(id, order.clone());
257 self.insert_id(price, id, amnt as u128)?;
258
259 Ok(order)
260 }
261
262 pub fn decrease_order(
268 &mut self,
269 id: OrderId,
270 amount: u64,
271 dust: u64,
272 clear: bool,
273 ) -> Result<(u64, Option<u64>), L3Error> {
274
275 let mut amount_to_send;
276 let mut should_delete = false;
277
278 {
279 let order = match self.orders.get_mut(&id) {
280 Some(order) => order,
281 None => return Ok((0, None)),
282 };
283
284 let original = order.cqty;
285 amount_to_send = amount.min(original);
286 let decreased = original.saturating_sub(amount_to_send);
287
288 if clear || decreased <= dust {
289 amount_to_send = original;
290 should_delete = true;
291 } else {
292 order.cqty = decreased;
294 order.pqty = if order.cqty >= order.pqty { order.pqty } else { order.cqty };
297 }
298 }
299
300 if should_delete {
301 let delete_price = self.delete_order(id)?;
302 Ok((amount_to_send, delete_price))
303 } else {
304 Ok((amount_to_send, None))
305 }
306 }
307
308 pub fn delete_order(&mut self, id: OrderId) -> Result<Option<u64>, L3Error> {
311
312 let price = self
314 .orders
315 .get(&id)
316 .ok_or(L3Error::OrderDoesNotExist(id))?
317 .price;
318
319 let order_node = self.order_nodes.get_mut(&id).ok_or(L3Error::OrderDoesNotExist(id))?;
321 let prev = order_node.prev;
322 let next = order_node.next;
323
324 let mut emptied_price = None;
325 if let (Some(prev), Some(next)) = (prev, next) {
328 let prev_node = self
329 .order_nodes
330 .get_mut(&prev)
331 .ok_or(L3Error::OrderDoesNotExist(prev))?;
332 prev_node.next = Some(next);
333 }
334 else if let Some(prev) = prev {
336 let prev_node = self
337 .order_nodes
338 .get_mut(&prev)
339 .ok_or(L3Error::OrderDoesNotExist(prev))?;
340 prev_node.next = None;
341 self.price_tail.insert(price, prev);
342 }
343 else if let Some(next) = next {
345 let next_node = self
346 .order_nodes
347 .get_mut(&next)
348 .ok_or(L3Error::OrderDoesNotExist(next))?;
349 next_node.prev = None;
350 self.price_head.insert(price, next);
351 }
352 else {
354 self.price_head.remove(&price);
355 self.price_tail.remove(&price);
356 self.order_nodes.remove(&id);
357 emptied_price = Some(price);
358 }
359
360 self.orders.remove(&id);
362 Ok(emptied_price)
363 }
364
365 pub fn next_make_id(&self) -> OrderId {
367 Ulid::new()
368 }
369
370 pub fn get_order_ids(&self, price: u64, n: u32) -> Vec<OrderId> {
372 let mut result = Vec::with_capacity(n as usize);
373 let mut current = self.price_head.get(&price).copied();
374
375 while let Some(id) = current {
376 result.push(id);
377 if result.len() as u32 >= n {
378 break;
379 }
380
381 current = self.order_nodes.get(&id).and_then(|node| node.next);
382 }
383
384 result
385 }
386
387 pub fn get_orders(&self, price: u64, n: u32) -> Vec<Order> {
389 self.get_order_ids(price, n)
390 .into_iter()
391 .filter_map(|id| self.orders.get(&id).cloned())
392 .collect()
393 }
394
395 pub fn get_orders_in_range(&self, price: u64, start: u32, end: u32) -> Vec<Order> {
397 if start >= end {
398 return Vec::new();
399 }
400
401 let mut current_index = 0;
402 let mut current = self.price_head.get(&price).copied();
403 let mut result = Vec::with_capacity((end - start) as usize);
404
405 while let Some(id) = current {
406 if current_index >= start && current_index < end {
407 if let Some(order) = self.orders.get(&id) {
408 result.push(order.clone());
409 }
410 }
411
412 if current_index >= end {
413 break;
414 }
415
416 current = self.order_nodes.get(&id).and_then(|node| node.next);
417 current_index += 1;
418 }
419
420 result
421 }
422
423 pub fn head(&self, price: u64) -> Option<OrderId> {
424 self.price_head.get(&price).copied()
425 }
426
427 pub fn tail(&self, price: u64) -> Option<OrderId> {
428 self.price_tail.get(&price).copied()
429 }
430
431 pub fn is_empty(&self, price: u64) -> bool {
432 self.price_head.get(&price).is_none()
433 }
434
435 pub fn next(&self, _price: u64, current: OrderId) -> Option<OrderId> {
436 let next_node = self.order_nodes.get(¤t).and_then(|node| node.next);
438 match next_node {
439 Some(next) => Some(next),
440 None => None,
441 }
442 }
443
444 pub fn get_order(&self, id: OrderId) -> Result<&Order, L3Error> {
445 self.orders.get(&id).ok_or(L3Error::OrderDoesNotExist(id))
446 }
447
448 pub fn remove_dormant_orders(&mut self, now: i64) -> Vec<(OrderId, Order)> {
450 let expired_orders: Vec<(OrderId, Order)> = self
451 .orders
452 .iter()
453 .filter_map(|(id, order)| {
454 if order.expires_at <= now {
455 Some((*id, order.clone()))
456 } else {
457 None
458 }
459 })
460 .collect();
461
462 for (id, _) in &expired_orders {
463 let _ = self.delete_order(*id);
464 }
465
466 expired_orders
467 }
468}