Expand description
WebSocket execution dispatch for the Hyperliquid execution client.
Implements the two-tier execution dispatch contract from
docs/developer_guide/adapters.md (lines 1232-1296):
- The execution client registers an
OrderIdentityinWsDispatchStatewhen it submits an order, and refreshes the cached venue order id when a modify is sent so the WebSocket consumer can detect cancel-replace. - Incoming [
OrderStatusReport] and [FillReport] messages are routed throughdispatch_order_eventanddispatch_order_fill. For tracked orders these build typed [OrderEventAny] events and emit them via [ExecutionEventEmitter::send_order_event]. For untracked / external orders the dispatch falls back to forwarding the raw report.
The dispatch state lives in an Arc<WsDispatchState> shared between the
main client task (which registers identities at submission time) and the
spawned WebSocket consumer task.
§GH-3827 cancel-replace handling
Hyperliquid implements modify as a cancel-and-replace: the venue emits an
ACCEPTED(new_voi) together with a CANCELED(old_voi) under the same
client_order_id. The dispatch detects the replacement leg by comparing
report.venue_order_id to the last cached value, promotes it to an
OrderUpdated event, and suppresses the stale cancel so strategies never
observe a spurious termination.
The pending-modify marker (keyed on client_order_id) is set by
modify_order before the HTTP call and cleared on either the matching
ACCEPTED(new_voi) or any modify failure. It lets dispatch skip an
early CANCELED(old_voi) that arrives before the replacement
ACCEPTED(new_voi) on the WebSocket, regardless of whether the WS
message races ahead of the HTTP response.
A fill carrying the replacement venue_order_id during an in-flight modify
promotes the binding directly (the same OrderUpdated path as the
replacement ACCEPTED), so a dropped ACCEPTED does not strand the fill.
A fill is buffered into WsDispatchState::buffered_fills only when the
identity has no price to promote with; handle_accepted drains the buffer
on the replacement ACCEPTED. A delayed earlier-leg fill during a chained
modify is a known limitation. See GH-3972.
When neither the replacement ACCEPTED nor a fill arrives, a query that
resolves the replacement by cloid promotes the binding the same way via
promote_replacement_from_query, so a dropped ACCEPTED with no fill
cannot leave the order bound to the canceled leg.
Structs§
- Bounded
Dedup - Bounded FIFO deduplication set.
- Order
Identity - Identity metadata captured when an order is submitted through this client.
- WsDispatch
State - Per-client dispatch state shared between order submission and the WebSocket consumer task.
Enums§
- Dispatch
Outcome - Outcome of a single dispatch call.
Constants§
Functions§
- dispatch_
order_ event - Dispatches an [
OrderStatusReport] using the two-tier routing contract. - dispatch_
order_ fill - Dispatches a [
FillReport] using the two-tier routing contract. - promote_
replacement_ from_ query - Promotes a cancel-replace replacement surfaced by a query during an in-flight modify.