Ir al contenido principal

L4 Order Book Dataset

Actualizado el
Jun 10, 2026

Resumen

El StreamL4Book stream delivers the full order book at individual order granularity — every resting order with user address, order ID, size, trigger info, and timestamps. On subscribe, the stream sends a complete snapshot of all resting orders, then incremental diffs per block.

gRPC Service: OrderBookStreaming
gRPC Method: StreamL4Book
API Availability: gRPC Streaming API only Update Model: Initial full snapshot, then incremental diffs per block

Cómo funciona

  1. On subscribe: The stream sends a full L4BookSnapshot containing every resting bid and ask with complete order details
  2. Per block thereafter: The stream sends L4BookDiff messages with a JSON-encoded datos string containing order_statuses (full order status objects matching the Orders stream) and book_diffs (incremental changes using raw_book_diff format matching the Book Updates stream)
  3. Apply diffs to your local copy of the snapshot to maintain current state

This is a significantly simpler way to create and maintain a local L4 order book view because the initial snapshot is built-in — no REST bootstrap or race-condition stitching is needed. On reconnect, a fresh snapshot is automatically delivered.

Data Structure

Snapshot (first message)

The initial L4BookSnapshot contains the full order book:

{
"snapshot": {
"coin": "ETH",
"time": 1764867600518,
"height": 817863403,
"bids": [
{
"user": "0x1c1c270b573d55b68b3d14722b5d5d401511bed0",
"coin": "ETH",
"side": "B",
"limit_px": "3167.4",
"sz": "1.5785",
"oid": 258166296856,
"timestamp": 1764867590000,
"trigger_condition": "N/A",
"is_trigger": false,
"trigger_px": "0",
"is_position_tpsl": false,
"reduce_only": false,
"order_type": "Limit",
"tif": "Gtc"
}
],
"asks": [
{
"user": "0xe9acfdc9322f6f924f007016c082e6891a3c653c",
"coin": "ETH",
"side": "A",
"limit_px": "3168.0",
"sz": "2.0000",
"oid": 258166160909,
"timestamp": 1764867580000,
"trigger_condition": "N/A",
"is_trigger": false,
"trigger_px": "0",
"is_position_tpsl": false,
"reduce_only": false,
"order_type": "Limit",
"tif": "Gtc"
}
]
}
}

Diff (subsequent messages)

After the snapshot, each block produces an L4BookDiff with JSON-encoded incremental changes:

{
"diff": {
"time": 1764867601000,
"height": 817863404,
"data": "{\"order_statuses\": [...], \"book_diffs\": [...]}"
}
}

Request Parameters

FieldTipoRequiredDescripción
monedacadenaSymbol to subscribe to — perps use names (e.g., "BTC", "ETH"), spot uses @index format (e.g., "@142")

Coin Naming

El moneda parameter follows Hyperliquid's naming convention, which unambiguously distinguishes perpetuals from spot:

  • Perpetuals: Human-readable names — "BTC", "ETH", "HYPE", "SOL"
  • Spot tokens: @{index} format — "@1", "@107", "@142", "@166"
  • Outcome markets (HIP-4): #N format. Each outcome has two #N coins — one per side (Yes and No). Multi-price question markets consist of multiple grouped outcomes (price buckets plus a fallback), each with its own Yes/No coin pair. Use the outcomeMeta endpoint to map coin indices to market names and sides.
  • Exception: "PURR/USDC" is the only spot coin with a readable name

There is no overlap between formats. "BTC" always refers to the BTC perpetual; spot BTC is "@142". To discover @índice mappings for spot tokens, query the meta o spotMeta info endpoints.

Response Fields

L4BookUpdate

Each message is a L4BookUpdate containing either a snapshot or a diff:

FieldTipoDescripción
snapshotL4BookSnapshotFull order book snapshot (sent on subscribe and reconnect)
diffL4BookDiffIncremental diff (sent per block after the initial snapshot)

L4BookSnapshot

FieldTipoDescripción
monedacadenaSymbol (e.g., "BTC", "ETH")
tiempouint64Block timestamp in milliseconds
alturauint64Block height
bidsL4Order[]All resting bid orders
asksL4Order[]All resting ask orders

L4BookDiff

FieldTipoDescripción
tiempouint64Block timestamp in milliseconds
alturauint64Block height
datoscadenaJSON-encoded object containing order_statuses and book_diffs, matching the existing node data format

L4Order

FieldTipoDescripción
usuariocadenaEthereum address of the order owner
monedacadenaTrading pair identifier (e.g., "ETH", "BTC")
ladocadena"A" (Ask/Sell) or "B" (Bid/Buy)
limit_pxcadenaLimit price as a decimal string
szcadenaOrder size as a decimal string
oiduint64Unique order ID
marca de tiempouint64When the order entered the book (milliseconds)
trigger_conditioncadenaTrigger condition status: "N/A", "Triggered", etc.
is_triggerboolWhether the order is a trigger/stop order
trigger_pxcadenaTrigger price as a decimal string
is_position_tpslboolWhether the order is a position take-profit/stop-loss
reduce_onlyboolWhether the order is reduce-only
order_typecadenaOrder type: "Limit", "Market", etc.
tifstring (optional)Time-in-force: "Gtc" (Good til Cancelled), "Ioc" (Immediate or Cancel), "Alo" (Add Liquidity Only)
cloidstring (optional)Client order ID (custom identifier set by user)

Proto Definition

StreamL4Book is defined in orderbook.proto:

service OrderBookStreaming {
rpc StreamL4Book (L4BookRequest) returns (stream L4BookUpdate);
}

message L4BookRequest {
string coin = 1;
}

message L4BookUpdate {
oneof update {
L4BookSnapshot snapshot = 1;
L4BookDiff diff = 2;
}
}

message L4BookSnapshot {
string coin = 1;
uint64 time = 2;
uint64 height = 3;
repeated L4Order bids = 4;
repeated L4Order asks = 5;
}

message L4BookDiff {
uint64 time = 1;
uint64 height = 2;
string data = 3;
}

message L4Order {
string user = 1;
string coin = 2;
string side = 3;
string limit_px = 4;
string sz = 5;
uint64 oid = 6;
uint64 timestamp = 7;
string trigger_condition = 8;
bool is_trigger = 9;
string trigger_px = 10;
bool is_position_tpsl = 11;
bool reduce_only = 12;
string order_type = 13;
optional string tif = 14;
optional string cloid = 15;
}

Example Updates

L4 Snapshot (initial full state)
{
"snapshot": {
"coin": "ETH",
"time": 1764867600518,
"height": 817863403,
"bids": [
{
"user": "0x1c1c270b573d55b68b3d14722b5d5d401511bed0",
"coin": "ETH",
"side": "B",
"limit_px": "3167.4",
"sz": "1.5785",
"oid": 258166296856,
"timestamp": 1764867590000,
"trigger_condition": "N/A",
"is_trigger": false,
"trigger_px": "0",
"is_position_tpsl": false,
"reduce_only": false,
"order_type": "Limit",
"tif": "Gtc"
},
{
"user": "0x999a4b5f268a8fbf33736feff360d462ad248dbf",
"coin": "ETH",
"side": "B",
"limit_px": "3167.0",
"sz": "5.0000",
"oid": 258166123456,
"timestamp": 1764867585000,
"trigger_condition": "N/A",
"is_trigger": false,
"trigger_px": "0",
"is_position_tpsl": false,
"reduce_only": false,
"order_type": "Limit",
"tif": "Gtc",
"cloid": "0x20251204000000000000000000381433"
}
],
"asks": [
{
"user": "0xe9acfdc9322f6f924f007016c082e6891a3c653c",
"coin": "ETH",
"side": "A",
"limit_px": "3168.0",
"sz": "2.0000",
"oid": 258166160909,
"timestamp": 1764867580000,
"trigger_condition": "N/A",
"is_trigger": false,
"trigger_px": "0",
"is_position_tpsl": false,
"reduce_only": false,
"order_type": "Limit",
"tif": "Alo"
}
]
}
}
L4 Diff (incremental per-block update)
{
"diff": {
"time": 1764867601000,
"height": 817863404,
"data": "{\"order_statuses\":[...],\"book_diffs\":[...]}"
}
}

El datos field is a JSON-encoded string. When parsed, it contains:

order_statuses — Full order status events, one per order changed this block. Each item matches the Orders stream event shape:

{
"order": {
"coin": "ETH",
"side": "B",
"limitPx": "3167.4",
"sz": "1.5785",
"oid": 258166296856,
"timestamp": 1764867590000,
"triggerCondition": "N/A",
"isTrigger": false,
"triggerPx": "0.0",
"isPositionTpsl": false,
"reduceOnly": false,
"orderType": "Limit",
"tif": "Gtc",
"cloid": "0x...",
"user": null
},
"status": "filled",
"time": "2025-12-04T17:00:00.518000000",
"user": "0x1c1c270b573d55b68b3d14722b5d5d401511bed0"
}

book_diffs — Incremental order book changes. Each item uses the same raw_book_diff format as the Book Updates stream:

// New order or size update
{
"coin": "ETH",
"oid": 258166296857,
"px": "3168.0",
"raw_book_diff": { "new": { "sz": "2.0000" } },
"side": "A",
"user": "0xe9acfdc9322f6f924f007016c082e6891a3c653c"
}

// Order removed (cancelled or filled)
{
"coin": "ETH",
"oid": 258166296856,
"px": "3167.4",
"raw_book_diff": "remove",
"side": "B",
"user": "0x1c1c270b573d55b68b3d14722b5d5d401511bed0"
}
Trigger/Stop-Loss Order
{
"user": "0x7a475736bf02d67bf51b00414ab766ef4da9214d",
"coin": "BTC",
"side": "A",
"limit_px": "90000.0",
"sz": "0.5000",
"oid": 258166400000,
"timestamp": 1764867595000,
"trigger_condition": "Triggered",
"is_trigger": true,
"trigger_px": "91000.0",
"is_position_tpsl": true,
"reduce_only": true,
"order_type": "Limit",
"tif": "Gtc"
}

API Usage

Transmisión gRPC
// Perp order book
const request = {
coin: 'ETH'
};

// Spot order book (@ index format)
const spotRequest = {
coin: '@142'
};

gRPC Only

StreamL4Book is only available via the gRPC Streaming API (OrderBookStreaming service). It is not available through JSON-RPC or WebSocket.

Comparison: L4 Book vs L2 Book vs Book Updates Dataset

CaracterísticaStreamL4BookStreamL2BookNOVEDADES SOBRE EL LIBRO
GranularityIndividual ordersAggregated by price levelIndividual order-level diffs
Includes current stateYes — initial snapshotYes — every messageNo — forward-only
Needs REST bootstrapNoNo
Client state managementApply diffs to snapshotNingunoBuild from scratch
Per-order detailsUser, oid, triggers, timestamps, tifTotal size and count onlyUser, oid, size
BandwidthHigher (full order details)Medium (capped by n_levels)Low (diffs only)
Ideal paraHFT, quant desks, MEVMost customersCustomers who only need book updates

Important Notes


  • Snapshot on subscribe and reconnect: The stream always starts with a full snapshot, so reconnects are handled automatically
  • DATA_LOSS reconnection: The stream may emit gRPC DATA_LOSS status errors during transient issues. Implement auto-reconnect logic on DATA_LOSS — a fresh snapshot is delivered on each new connection, so no manual state recovery is needed.
  • Apply diffs to local state: After the initial snapshot, apply each L4BookDiff to maintain the current book. Each book_diffs item uses raw_book_diff: {"new": {"sz": "..."}} to add/update an order, or raw_book_diff: "remove" to remove one — the same format as the Book Updates stream.
  • Typed alternative available: If you only need per-order add/update/remove movement without parsing the JSON-encoded datos string, StreamL4BookUpdates delivers the same order-level changes as typed protobuf diffs.
  • zstd compression strongly recommended: L4 messages can be large due to full order details. Enable zstd compression on your gRPC channel to significantly reduce bandwidth.

  • StreamL2Book - Aggregated price levels — simpler, lower bandwidth, no client-side state management
  • StreamL4BookUpdates - Typed per-order add/update/remove diffs, no JSON parsing required
  • Book Updates - Forward-only incremental diffs via StreamData (legacy approach)
  • Orders - Order lifecycle events (open, filled, canceled, etc.)
  • Trades - Executed trade data with maker/taker information
Comparte este documento