Zum Hauptinhalt springen

L4 Order Book Dataset

Aktualisiert am
Jun 10, 2026

Übersicht

Die 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

So funktioniert es

  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 Daten 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

FeldTypRequiredBeschreibung
MünzeZeichenketteJaSymbol to subscribe to — perps use names (e.g., "BTC", "ETH"), spot uses @index format (e.g., "@142")

Coin Naming

Die Münze 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 @index mappings for spot tokens, query the meta oder spotMeta info endpoints.

Response Fields

L4BookUpdate

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

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

L4BookSnapshot

FeldTypBeschreibung
MünzeZeichenketteSymbol (e.g., "BTC", "ETH")
Zeituint64Block timestamp in milliseconds
Höheuint64Block height
bidsL4Order[]All resting bid orders
asksL4Order[]All resting ask orders

L4BookDiff

FeldTypBeschreibung
Zeituint64Block timestamp in milliseconds
Höheuint64Block height
DatenZeichenketteJSON-encoded object containing order_statuses and book_diffs, matching the existing node data format

L4Order

FeldTypBeschreibung
userZeichenketteEthereum address of the order owner
MünzeZeichenketteTrading pair identifier (e.g., "ETH", "BTC")
SeiteZeichenkette"A" (Ask/Sell) or "B" (Bid/Buy)
limit_pxZeichenketteLimit price as a decimal string
szZeichenketteOrder size as a decimal string
oiduint64Unique order ID
Zeitstempeluint64When the order entered the book (milliseconds)
trigger_conditionZeichenketteTrigger condition status: "N/A", "Triggered", etc.
is_triggerboolWhether the order is a trigger/stop order
trigger_pxZeichenketteTrigger 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_typeZeichenketteOrder 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\":[...]}"
}
}

Die Daten 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

gRPC Streaming
// 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

FunktionStreamL4BookStreamL2BookBUCH_AKTUELLES
GranularityIndividual ordersAggregated by price levelIndividual order-level diffs
Includes current stateYes — initial snapshotYes — every messageNo — forward-only
Needs REST bootstrapNeinNeinJa
Client state managementApply diffs to snapshotKeineBuild 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)
Am besten geeignet fürHFT, 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 Daten 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
Dieses Dokument teilen