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::pre_cancellation_tracker

Without this feature, today, the MM will need to wait for an order to be placed and confirmed on the orderbook, so that the MM can get the order id to be able to cancel the order - this means minimum time required to be able to submit a transaction to cancel the order is end-to-end blockchain latency (~500 ms). This adds support for an MM to pre-cancel an order, which means specify that this order with a client order id is cancelled even before the order is placed. This reduces the latency to submit a cancellation transaction from 500 ms to 0.

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

Enum PreCancellationTracker

enum PreCancellationTracker has store
Variants
V1
Fields
pre_cancellation_window_secs: u64
expiration_with_order_ids: big_ordered_map::BigOrderedMap<pre_cancellation_tracker::ExpirationAndOrderId, bool>
account_order_ids: big_ordered_map::BigOrderedMap<order_book_types::AccountClientOrderId, u64>

Struct ExpirationAndOrderId

struct ExpirationAndOrderId has copy, drop, store
Fields
expiration_time: u64
account_order_id: order_book_types::AccountClientOrderId

Constants

const DUPLICATE_ORDER_PLACEMENT: u64 = 1;

const MAX_ORDERS_GARBAGE_COLLECTED_PER_CALL: u64 = 10;

Function new_pre_cancellation_tracker

public(friend) fun new_pre_cancellation_tracker(expiration_time_secs: u64): pre_cancellation_tracker::PreCancellationTracker
Implementation
public(friend) fun new_pre_cancellation_tracker(
    expiration_time_secs: u64
): PreCancellationTracker {
    PreCancellationTracker::V1 {
        pre_cancellation_window_secs: expiration_time_secs,
        expiration_with_order_ids: order_book_utils::new_default_big_ordered_map(),
        account_order_ids: order_book_utils::new_default_big_ordered_map()
    }
}

Function pre_cancel_order_for_tracker

public(friend) fun pre_cancel_order_for_tracker(tracker: &mut pre_cancellation_tracker::PreCancellationTracker, account: address, client_order_id: string::String)
Implementation
public(friend) fun pre_cancel_order_for_tracker(
    tracker: &mut PreCancellationTracker, account: address, client_order_id: String
) {
    garbage_collect(tracker);
    let account_order_id = new_account_client_order_id(account, client_order_id);

    // If the account_order_id already exists with a previously set expiration time,
    // we update the expiration time.
    let prev_expiration_time =
        tracker.account_order_ids.remove_or_none(&account_order_id);
    if (prev_expiration_time.is_some()) {
        // If the account_order_id already exists with a previously set expiration time,
        // we update the expiration time.
        let expiration_time = prev_expiration_time.destroy_some();
        let order_id_with_expiration = ExpirationAndOrderId {
            expiration_time,
            account_order_id
        };
        // If the mapping exists, then we remove the order ID with its expiration time.
        tracker.expiration_with_order_ids.remove(&order_id_with_expiration);
    };
    let current_time = aptos_std::timestamp::now_seconds();
    let expiration_time = current_time + tracker.pre_cancellation_window_secs;
    let order_id_with_expiration = ExpirationAndOrderId {
        expiration_time,
        account_order_id
    };
    tracker.account_order_ids.add(account_order_id, expiration_time);
    tracker.expiration_with_order_ids.add(order_id_with_expiration, true);
}

Function is_pre_cancelled

public(friend) fun is_pre_cancelled(tracker: &mut pre_cancellation_tracker::PreCancellationTracker, account: address, client_order_id: string::String): bool
Implementation
public(friend) fun is_pre_cancelled(
    tracker: &mut PreCancellationTracker, account: address, client_order_id: String
): bool {
    garbage_collect(tracker);
    let account_order_id = new_account_client_order_id(account, client_order_id);
    let expiration_time_option = tracker.account_order_ids.get(&account_order_id);
    if (expiration_time_option.is_some()) {
        let current_time = aptos_std::timestamp::now_seconds();
        let expiration_time = expiration_time_option.destroy_some();
        if (current_time > expiration_time) {
            // This is possible as garbage collection may not be able to garbage collect all expired orders
            // in a single call.
            tracker.account_order_ids.remove(&account_order_id);
            let order_id_with_expiration = ExpirationAndOrderId {
                expiration_time,
                account_order_id
            };
            tracker.expiration_with_order_ids.remove(&order_id_with_expiration);
        } else {
            return true; // Order ID already exists with a valid expiration time.
        }
    };
    return false
}

Function garbage_collect

public(friend) fun garbage_collect(tracker: &mut pre_cancellation_tracker::PreCancellationTracker)
Implementation
public(friend) fun garbage_collect(
    tracker: &mut PreCancellationTracker
) {
    let i = 0;
    let current_time = aptos_std::timestamp::now_seconds();
    while (i < MAX_ORDERS_GARBAGE_COLLECTED_PER_CALL
        && !tracker.expiration_with_order_ids.is_empty()) {
        let (front_k, _) = tracker.expiration_with_order_ids.borrow_front();
        if (front_k.expiration_time < current_time) {
            tracker.expiration_with_order_ids.pop_front();
            tracker.account_order_ids.remove(&front_k.account_order_id);
        } else {
            break;
        };
        i += 1;
    };
}