hexbook.near logs NEP-297 events, standard
hex_orderbook, version 2.1.0:
2.x version: shapes only grow by optional fields, so the contract’s older logs (2.0.0, logged before
v3; see the changelog) parse with the same code.
Conventions. Keys are short. Amounts are decimal strings of raw units; prices raw decimal strings; hashes 64 hex
characters. Sides are "s" (sell / ask, holds base) and "b" (buy / bid, holds quote). ts and x are u64
nanoseconds written as JSON numbers that exceed 2^53: parse them with a big-integer-aware JSON parser, never as a
plain JSON.parse double.
Hashes in the examples are shortened (3ed65e74…); real logs have all 64 characters.
Batched events
Abatch logs its order_closed, order_created and place_skipped as one event
each with data as an array, one item per order; prune does the same for its
order_closed. Each array event is logged only when it has at least one item. Every other event has one object as
data. Accept both forms for these three events.
order_created
A resting order: a batch placement (arraydata), or a taker’s remainder that rests (object data; it is logged
before the trade of the same receipt).
trade
One per taker order that does not simply rest (also when it is refunded whole with no fills).order_closed
An order closed outside a trade (a trade never logsorder_closed). The refund is credited to the maker’s internal
balance.
close_order then pays the whole internal balance out (a claim follows).
claim
An internal balance paid out bymt_transfer: claim_balance, close_order’s claim, withdraw.
payout_failed
A payoutmt_transfer failed; the amount was credited to the internal balance.
deposit
A deposit into the internal balance.place_skipped
A batch placement that did not rest (not an error; nothing was debited). Batched:data is an array.
epoch
A maker’s epoch in a book was bumped (cancel_all, or batch with bump_epoch). Every order of m in b/q with a
lower epoch is dead from this receipt on.
payout_mode
An account set its payout mode:{ a, mode }, mode "internal" or "intents".
book
A book was created or its config changed. The owner re-logs the books created before this event existed withemit_book_events.
book_removed
{ b, q }: the book was removed (it had no orders).
Rebuilding state from events
Orders
order_createdopens an order. Keep{h → m, s, p, b, q, a, x, e}: fills and closes only name the hash.- A
tradefill[h, base, quote, fee, left]sets the order’s balance toleft. - After a trade an order is closed iff its fill’s
leftis0or its hash is inc;c’s amount (equal toleftwhen both appear) is refunded in the token the order held. A bid that can no longer buy one base unit and a dead order appear only inc, with their whole balance. order_closedcloses the order with refundr.epochmakes the maker’s older orders in that book dead but does not close them; nor does reachingx. They close later through a trade’scor anorder_closed. To show a live book, apply both rules at the current time.
Fills and prices
For eachtrade: base = Σ fill base, quote = Σ fill quote, average raw price = Σquote / Σbase. The taker side is s;
the makers are the m of each filled order.
Fees
tf is split over the book’s protocol taker collectors, then the trade’s refs, pro rata by pips, rounded down, dust to
the first collector. mf is split over the maker collectors the same way. Use the fee config of the latest book event
before the trade (or get_protocol_fee).
Payouts and balances
A trade’s payouts are aggregated per (token, account) across roles (one account can be taker, maker and fee collector at once), entries of 0 are dropped, and the list is sorted by token, then account. What goes in:- Makers in
miget their proceeds andcrefunds credited to their internal balance; those are not among the trade’s payouts. What they get as taker or fee collector is. np: the firstnppayouts of the sorted list are paid out bymt_transfer; the rest did not fit in the receipt’s gas and are credited to internal balances. The referrer-fee part of a credited payout goes to the taker instead. A paid payout that fails is credited later (payout_failed).
Reconcile periodically with
get_user_balance: placements debit the balance through their order_created, not an
event of their own.