Closed alnoki closed 1 year ago
Per the most recent Move Mondays, events are not intended to communicate all information executed on-chain, but rather, relevant deltas to state. It is additionally advised that events be designed such that indexers can make sense of them, which in the case of Econia likely involves emitting the actual price, rather than an Order ID with an encoded price. Moreover, the premier task of simply indexing an order book into orders with a size and price does not require user addresses or general custodian IDs, hence the following simpler event structure may be more appropriate for order book events:
/// Emitted when a maker order is added to or cancelled from the book.
struct MakerEvent has drop, store {
/// `CANCEL` or `PLACE`
type: bool,
/// `ASK` or `BID`
side: bool,
/// Size, in lots, of the order at time of placement or cancellation
size: u64,
/// Price, in ticks per lot, of the order
price: u64
}
/// Emitted when a taker order fills against the book. If a taker order
/// fills against multiple orders, an event is emitted for each one.
struct TakerEvent has drop, store {
/// `ASK` or `BID`, the side of the maker order filled against
side: bool,
/// Fill size, in lots
size: u64
/// Price, in ticks per lot, of the order filled against
price: u64
}
Here, only the price and size are included, since the chronology of price-time priority is encoded in the event stream itself: if an RPC endpoint is maintaining a real-time snapshot of the order book by monitoring events, it simply needs to insert/delete events as they come in.
Optionally, an event may be emitted when a user registers a MarketAccount
, which will allow indexers to determine how many users are trading on a given market:
/// Event emitted when user registers a `MarketAccount`.
struct MarketAccountRegistrationEvent has drop, store {
/// Market account ID of `MarketAccount` just registered.
market_account_id: u128
}
/// Market account map for all of a user's `MarketAccount`s.
struct MarketAccounts has key {
/// Map from market account ID to `MarketAccount`. Separated
/// into different table entries to reduce transaction
/// collisions across markets, with iterated indexing support.
map: iterable_table::IterableTable<u128, MarketAccount>,
/// Event handle for registration events.
registration_events: EventHandle<MarketAccountRegistrationEvent>
}
For notifying users that their limit orders have cleared, it may be appropriate to include the address and general custodian ID of any taker orders that have filled.
For ease of indexing, the following events are proposed:
Order book events:
A corresponding
MakerEventHandle
andTakerEventHandle
would then be fields within eachOrderBook
Market registration events
Account considerations
Since event handles rely on an account-specific GUID, it may be necessary to enforce that the number of registered markets is
U64_MAX / 2 - 1
if all order books and the registry are kept in a single resource account, since eachOrderBook
will require two event handles and the registry will require one.