Skip to main content

Module 0xdee9::order_query

use 0x1::option;
use 0x2::linked_table;
use 0xdee9::clob_v2;
use 0xdee9::critbit;

Struct OrderPage

struct OrderPage has drop
Fields
orders: vector<clob_v2::Order>
has_next_page: bool
next_tick_level: option::Option<u64>
next_order_id: option::Option<u64>

Constants

const PAGE_LIMIT: u64 = 100;

Function iter_bids

public fun iter_bids<T1, T2>(pool: &clob_v2::Pool<T1, T2>, start_tick_level: option::Option<u64>, start_order_id: option::Option<u64>, min_expire_timestamp: option::Option<u64>, max_id: option::Option<u64>, ascending: bool): order_query::OrderPage
Implementation
public fun iter_bids<T1, T2>(
    pool: &Pool<T1, T2>,
    // tick level to start from
    start_tick_level: Option<u64>,
    // order id within that tick level to start from
    start_order_id: Option<u64>,
    // if provided, do not include orders with an expire timestamp less than the provided value (expired order),
    // value is in microseconds
    min_expire_timestamp: Option<u64>,
    // do not show orders with an ID larger than max_id--
    // i.e., orders added later than this one
    max_id: Option<u64>,
    // if true, the orders are returned in ascending tick level.
    ascending: bool,
): OrderPage {
    let bids = clob_v2::bids(pool);
    let mut orders = iter_ticks_internal(
        bids,
        start_tick_level,
        start_order_id,
        min_expire_timestamp,
        max_id,
        ascending
    );
    let (orders, has_next_page, next_tick_level, next_order_id) = if (vector::length(&orders) > PAGE_LIMIT) {
        let last_order = vector::pop_back(&mut orders);
        (orders, true, some(clob_v2::tick_level(&last_order)), some(clob_v2::order_id(&last_order)))
    } else {
        (orders, false, none(), none())
    };

    OrderPage {
        orders,
        has_next_page,
        next_tick_level,
        next_order_id
    }
}

Function iter_asks

public fun iter_asks<T1, T2>(pool: &clob_v2::Pool<T1, T2>, start_tick_level: option::Option<u64>, start_order_id: option::Option<u64>, min_expire_timestamp: option::Option<u64>, max_id: option::Option<u64>, ascending: bool): order_query::OrderPage
Implementation
public fun iter_asks<T1, T2>(
    pool: &Pool<T1, T2>,
    // tick level to start from
    start_tick_level: Option<u64>,
    // order id within that tick level to start from
    start_order_id: Option<u64>,
    // if provided, do not include orders with an expire timestamp less than the provided value (expired order),
    // value is in microseconds
    min_expire_timestamp: Option<u64>,
    // do not show orders with an ID larger than max_id--
    // i.e., orders added later than this one
    max_id: Option<u64>,
    // if true, the orders are returned in ascending tick level.
    ascending: bool,
): OrderPage {
    let asks = clob_v2::asks(pool);
    let mut orders = iter_ticks_internal(
        asks,
        start_tick_level,
        start_order_id,
        min_expire_timestamp,
        max_id,
        ascending
    );
    let (orders, has_next_page, next_tick_level, next_order_id) = if (vector::length(&orders) > PAGE_LIMIT) {
        let last_order = vector::pop_back(&mut orders);
        (orders, true, some(clob_v2::tick_level(&last_order)), some(clob_v2::order_id(&last_order)))
    } else {
        (orders, false, none(), none())
    };

    OrderPage {
        orders,
        has_next_page,
        next_tick_level,
        next_order_id
    }
}

Function iter_ticks_internal

fun iter_ticks_internal(ticks: &critbit::CritbitTree<clob_v2::TickLevel>, start_tick_level: option::Option<u64>, start_order_id: option::Option<u64>, min_expire_timestamp: option::Option<u64>, max_id: option::Option<u64>, ascending: bool): vector<clob_v2::Order>
Implementation
fun iter_ticks_internal(
    ticks: &CritbitTree<TickLevel>,
    // tick level to start from
    start_tick_level: Option<u64>,
    // order id within that tick level to start from
    mut start_order_id: Option<u64>,
    // if provided, do not include orders with an expire timestamp less than the provided value (expired order),
    // value is in microseconds
    min_expire_timestamp: Option<u64>,
    // do not show orders with an ID larger than max_id--
    // i.e., orders added later than this one
    max_id: Option<u64>,
    // if true, the orders are returned in ascending tick level.
    ascending: bool,
): vector<Order> {
    let mut tick_level_key = if (option::is_some(&start_tick_level)) {
        option::destroy_some(start_tick_level)
    } else {
        let (key, _) = if (ascending) {
            critbit::min_leaf(ticks)
        }else {
            critbit::max_leaf(ticks)
        };
        key
    };

    let mut orders = vector[];

    while (tick_level_key != 0 && vector::length(&orders) < PAGE_LIMIT + 1) {
        let tick_level = critbit::borrow_leaf_by_key(ticks, tick_level_key);
        let open_orders = clob_v2::open_orders(tick_level);

        let mut next_order_key = if (option::is_some(&start_order_id)) {
            let key = option::destroy_some(start_order_id);
            if (!linked_table::contains(open_orders, key)) {
                let (next_leaf, _) = if (ascending) {
                    critbit::next_leaf(ticks, tick_level_key)
                }else {
                    critbit::previous_leaf(ticks, tick_level_key)
                };
                tick_level_key = next_leaf;
                continue
            };
            start_order_id = option::none();
            some(key)
        }else {
            *linked_table::front(open_orders)
        };

        while (option::is_some(&next_order_key) && vector::length(&orders) < PAGE_LIMIT + 1) {
            let key = option::destroy_some(next_order_key);
            let order = linked_table::borrow(open_orders, key);

            // if the order id is greater than max_id, we end the iteration for this tick level.
            if (option::is_some(&max_id) && key > option::destroy_some(max_id)) {
                break
            };

            next_order_key = *linked_table::next(open_orders, key);

            // if expire timestamp is set, and if the order is expired, we skip it.
            if (option::is_none(&min_expire_timestamp) ||
                clob_v2::expire_timestamp(order) > option::destroy_some(min_expire_timestamp)) {
                vector::push_back(&mut orders, clob_v2::clone_order(order));
            };
        };
        let (next_leaf, _) = if (ascending) {
            critbit::next_leaf(ticks, tick_level_key)
        }else {
            critbit::previous_leaf(ticks, tick_level_key)
        };
        tick_level_key = next_leaf;
    };
    orders
}

Function orders

public fun orders(page: &order_query::OrderPage): &vector<clob_v2::Order>
Implementation
public fun orders(page: &OrderPage): &vector<Order> {
    &page.orders
}

Function has_next_page

public fun has_next_page(page: &order_query::OrderPage): bool
Implementation
public fun has_next_page(page: &OrderPage): bool {
    page.has_next_page
}

Function next_tick_level

public fun next_tick_level(page: &order_query::OrderPage): option::Option<u64>
Implementation
public fun next_tick_level(page: &OrderPage): Option<u64> {
    page.next_tick_level
}

Function next_order_id

public fun next_order_id(page: &order_query::OrderPage): option::Option<u64>
Implementation
public fun next_order_id(page: &OrderPage): Option<u64> {
    page.next_order_id
}

Function order_id

public fun order_id(order: &clob_v2::Order): u64
Implementation
public fun order_id(order: &Order): u64 {
    clob_v2::order_id(order)
}

Function tick_level

public fun tick_level(order: &clob_v2::Order): u64
Implementation
public fun tick_level(order: &Order): u64 {
    clob_v2::tick_level(order)
}