Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Module 0x7::pending_order_book_index

(work in progress)

use 0x1::big_ordered_map;
use 0x1::error;
use 0x1::option;
use 0x1::timestamp;
use 0x5::order_book_types;
use 0x7::order_book_utils;

Struct PendingUpOrderKey

struct PendingUpOrderKey has copy, drop, store
Fields
price: u64
tie_breaker: order_book_types::IncreasingIdx

Struct PendingDownOrderKey

struct PendingDownOrderKey has copy, drop, store
Fields
price: u64
tie_breaker: order_book_types::DecreasingIdx

Struct PendingTimeKey

struct PendingTimeKey has copy, drop, store
Fields
time: u64
tie_breaker: order_book_types::IncreasingIdx

Enum PendingOrderBookIndex

enum PendingOrderBookIndex has store
Variants
V1
Fields
price_move_down_index: big_ordered_map::BigOrderedMap<pending_order_book_index::PendingDownOrderKey, order_book_types::OrderId>
price_move_up_index: big_ordered_map::BigOrderedMap<pending_order_book_index::PendingUpOrderKey, order_book_types::OrderId>
time_based_index: big_ordered_map::BigOrderedMap<pending_order_book_index::PendingTimeKey, order_book_types::OrderId>

Function new_pending_order_book_index

public(friend) fun new_pending_order_book_index(): pending_order_book_index::PendingOrderBookIndex
Implementation
public(friend) fun new_pending_order_book_index(): PendingOrderBookIndex {
    PendingOrderBookIndex::V1 {
        price_move_up_index: order_book_utils::new_default_big_ordered_map(),
        price_move_down_index: order_book_utils::new_default_big_ordered_map(),
        time_based_index: order_book_utils::new_default_big_ordered_map()
    }
}

Function cancel_pending_order

public(friend) fun cancel_pending_order(self: &mut pending_order_book_index::PendingOrderBookIndex, trigger_condition: order_book_types::TriggerCondition, unique_priority_idx: order_book_types::IncreasingIdx)
Implementation
public(friend) fun cancel_pending_order(
    self: &mut PendingOrderBookIndex,
    trigger_condition: TriggerCondition,
    unique_priority_idx: IncreasingIdx
) {
    let (price_move_down_index, price_move_up_index, time_based_index) =
        trigger_condition.get_trigger_condition_indices();
    if (price_move_up_index.is_some()) {
        self.price_move_up_index.remove(
            &PendingUpOrderKey {
                price: price_move_up_index.destroy_some(),
                tie_breaker: unique_priority_idx
            }
        );
    };
    if (price_move_down_index.is_some()) {
        self.price_move_down_index.remove(
            &PendingDownOrderKey {
                price: price_move_down_index.destroy_some(),
                tie_breaker: unique_priority_idx.into_decreasing_idx_type()
            }
        );
    };
    if (time_based_index.is_some()) {
        self.time_based_index.remove(
            &PendingTimeKey {
                time: time_based_index.destroy_some(),
                tie_breaker: unique_priority_idx
            }
        );
    };
}

Function place_pending_order

public(friend) fun place_pending_order(self: &mut pending_order_book_index::PendingOrderBookIndex, order_id: order_book_types::OrderId, trigger_condition: order_book_types::TriggerCondition, unique_priority_idx: order_book_types::IncreasingIdx)
Implementation
public(friend) fun place_pending_order(
    self: &mut PendingOrderBookIndex,
    order_id: OrderId,
    trigger_condition: TriggerCondition,
    unique_priority_idx: IncreasingIdx
) {
    // Add this order to the pending order book index
    let (price_move_down_index, price_move_up_index, time_based_index) =
        trigger_condition.get_trigger_condition_indices();
    if (price_move_up_index.is_some()) {
        self.price_move_up_index.add(
            PendingUpOrderKey {
                price: price_move_up_index.destroy_some(),
                tie_breaker: unique_priority_idx
            },
            order_id
        );
    } else if (price_move_down_index.is_some()) {
        self.price_move_down_index.add(
            PendingDownOrderKey {
                price: price_move_down_index.destroy_some(),
                // Use a descending tie breaker to ensure that for price move down orders,
                // orders with the same price are processed in FIFO order
                tie_breaker: unique_priority_idx.into_decreasing_idx_type()
            },
            order_id
        );
    } else if (time_based_index.is_some()) {
        self.time_based_index.add(
            PendingTimeKey {
                time: time_based_index.destroy_some(),
                tie_breaker: unique_priority_idx
            },
            order_id
        );
    };
}

Function take_ready_price_move_up_orders

fun take_ready_price_move_up_orders(self: &mut pending_order_book_index::PendingOrderBookIndex, current_price: u64, orders: &mut vector<order_book_types::OrderId>, limit: u64)
Implementation
inline fun take_ready_price_move_up_orders(
    self: &mut PendingOrderBookIndex,
    current_price: u64,
    orders: &mut vector<OrderId>,
    limit: u64
) {
    while (!self.price_move_up_index.is_empty() && orders.length() < limit) {
        let (key, order_id) = self.price_move_up_index.borrow_front();
        if (current_price >= key.price) {
            orders.push_back(*order_id);
            self.price_move_up_index.remove(&key);
        } else {
            break;
        }
    };
}

Function take_ready_price_move_down_orders

fun take_ready_price_move_down_orders(self: &mut pending_order_book_index::PendingOrderBookIndex, current_price: u64, orders: &mut vector<order_book_types::OrderId>, limit: u64)
Implementation
inline fun take_ready_price_move_down_orders(
    self: &mut PendingOrderBookIndex,
    current_price: u64,
    orders: &mut vector<OrderId>,
    limit: u64
) {
    while (!self.price_move_down_index.is_empty() && orders.length() < limit) {
        let (key, order_id) = self.price_move_down_index.borrow_back();
        if (current_price <= key.price) {
            orders.push_back(*order_id);
            self.price_move_down_index.remove(&key);
        } else {
            break;
        }
    };
}

Function take_ready_price_based_orders

public(friend) fun take_ready_price_based_orders(self: &mut pending_order_book_index::PendingOrderBookIndex, current_price: u64, order_limit: u64): vector<order_book_types::OrderId>
Implementation
public(friend) fun take_ready_price_based_orders(
    self: &mut PendingOrderBookIndex, current_price: u64, order_limit: u64
): vector<OrderId> {
    let orders = vector::empty();
    self.take_ready_price_move_up_orders(
        current_price,
        &mut orders,
        math64::ceil_div(order_limit, 2)
    );
    self.take_ready_price_move_down_orders(current_price, &mut orders, order_limit);
    // Try to fill the rest of the space if available.
    self.take_ready_price_move_up_orders(current_price, &mut orders, order_limit);
    orders
}

Function take_ready_time_based_orders

public(friend) fun take_ready_time_based_orders(self: &mut pending_order_book_index::PendingOrderBookIndex, order_limit: u64): vector<order_book_types::OrderId>
Implementation
public(friend) fun take_ready_time_based_orders(
    self: &mut PendingOrderBookIndex, order_limit: u64
): vector<OrderId> {
    let orders = vector::empty();
    while (!self.time_based_index.is_empty() && orders.length() < order_limit) {
        let current_time = timestamp::now_seconds();
        let (time, order_id) = self.time_based_index.borrow_front();
        if (current_time >= time.time) {
            orders.push_back(*order_id);
            self.time_based_index.remove(&time);
        } else {
            break;
        }
    };
    orders
}