Orderbook Channel

Real-time orderbook updates for perpetual markets.

Channel: orderbook
Authentication: Not required

Subscribe

{
  "method": "subscribe",
  "params": {
    "channel": "orderbook",
    "market_ids": [1, 2]
  }
}
ParameterTypeRequiredDescription
market_idsnumber[]NoFilter by market IDs. Empty = all markets

Message Format

Snapshot

Sent immediately after subscribing. Contains the full orderbook state.

{
  "method": "snapshot",
  "channel": "orderbook",
  "type": "snapshot",
  "market_id": "1",
  "data": {
    "market_id": 1,
    "bids": [
      {
        "price": "50000000000000000000000",
        "quantity": "1000000000000000000",
        "order_count": 3,
        "block_number": 12345678,
        "log_index": 0
      },
      {
        "price": "49900000000000000000000",
        "quantity": "2500000000000000000",
        "order_count": 5,
        "block_number": 12345670,
        "log_index": 2
      }
    ],
    "asks": [
      {
        "price": "50100000000000000000000",
        "quantity": "800000000000000000",
        "order_count": 2,
        "block_number": 12345675,
        "log_index": 1
      },
      {
        "price": "50200000000000000000000",
        "quantity": "1200000000000000000",
        "order_count": 4,
        "block_number": 12345672,
        "log_index": 0
      }
    ]
  },
  "level_count": 4,
  "timestamp": "1703123456123456789"
}

Update

Sent when the orderbook changes. Contains only the modified price levels.

{
  "channel": "orderbook",
  "type": "update",
  "market_id": "1",
  "data": {
    "market_id": 1,
    "bids": [
      {
        "price": "50000000000000000000000",
        "quantity": "1500000000000000000",
        "order_count": 4,
        "block_number": 12345679,
        "log_index": 1
      }
    ],
    "asks": []
  },
  "checksum": 3947812456,
  "block_number": 12345679,
  "log_index": 1,
  "tx_hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
  "block_timestamp": "1703123457000000000",
  "timestamp": "1703123457123456789"
}

Level Deletion

When a price level is removed, it is sent with quantity: "0":

{
  "channel": "orderbook",
  "type": "update",
  "market_id": "1",
  "data": {
    "market_id": 1,
    "bids": [
      {
        "price": "49900000000000000000000",
        "quantity": "0",
        "order_count": 0,
        "block_number": 12345680,
        "log_index": 2
      }
    ],
    "asks": []
  },
  "checksum": 1234567890,
  "block_number": 12345680,
  "log_index": 2,
  "tx_hash": "0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890",
  "block_timestamp": "1703123458000000000",
  "timestamp": "1703123458123456789"
}

Data Fields

Snapshot Message Fields

FieldTypeDescription
methodstringAlways "snapshot"
channelstringAlways "orderbook"
typestringAlways "snapshot"
market_idstringMarket ID
dataobjectContains market_id, bids, and asks arrays
level_countnumberTotal number of price levels
timestampstringServer timestamp (nanoseconds)

Update Message Fields

FieldTypeDescription
channelstringAlways "orderbook"
typestringAlways "update"
market_idstringMarket ID
dataobjectContains market_id, bids, and asks arrays
checksumnumberCRC32 checksum for validation
block_numbernumberBlockchain block number
log_indexnumberLog index within the block
tx_hashstringTransaction hash
block_timestampstringBlockchain timestamp (nanoseconds)
timestampstringServer timestamp (nanoseconds)

Snapshot Level Object

FieldTypeDescription
pricestringPrice level (wei, 18 decimals)
quantitystringTotal quantity at this price (wei, 18 decimals)
order_countnumberNumber of orders at this price level
block_numbernumberBlock number when this level was last updated
log_indexnumberLog index within the block

Update Level Object

FieldTypeDescription
pricestringPrice level (wei, 18 decimals)
quantitystringTotal quantity at this price (wei, 18 decimals). "0" indicates deletion
order_countnumberNumber of orders at this price level
block_numbernumberBlock number when this level was last updated
log_indexnumberLog index within the block

Ordering

  • Bids: Sorted descending by price (highest first)
  • Asks: Sorted ascending by price (lowest first)

CRC32 Checksum

The checksum allows you to verify orderbook integrity. If your local orderbook state doesn't match the checksum, you should resubscribe to get a fresh snapshot.

Algorithm

The checksum is computed using CRC32-IEEE on an interleaved string of bid and ask levels:

bid_price:bid_quantity:ask_price:ask_quantity:bid_price:bid_quantity:ask_price:ask_quantity:...

Computation Steps

  1. Sort bids descending by price (highest first)
  2. Sort asks ascending by price (lowest first)
  3. Interleave levels: bids[0], asks[0], bids[1], asks[1], ...
  4. Build string: price:quantity:price:quantity:...
  5. Compute CRC32-IEEE checksum

Python Implementation

import binascii

def compute_checksum(bids, asks):
    parts = []
    max_len = max(len(bids), len(asks))

    for i in range(max_len):
        if i < len(bids):
            parts.append(bids[i]['price'])
            parts.append(bids[i]['quantity'])
        if i < len(asks):
            parts.append(asks[i]['price'])
            parts.append(asks[i]['quantity'])

    s = ':'.join(parts)
    return binascii.crc32(s.encode()) & 0xffffffff

Checksum Mismatch

If your computed checksum doesn't match the received checksum:

  1. Your local orderbook state may be corrupted
  2. Unsubscribe and resubscribe to get a fresh snapshot
  3. Check your update application logic

Examples

Subscribe to all markets

{
  "method": "subscribe",
  "params": {
    "channel": "orderbook"
  }
}

Subscribe to specific markets

{
  "method": "subscribe",
  "params": {
    "channel": "orderbook",
    "market_ids": [1, 2]
  }
}

Subscribe to single market

{
  "method": "subscribe",
  "params": {
    "channel": "orderbook",
    "market_ids": [1]
  }
}

Unsubscribe

{
  "method": "unsubscribe",
  "params": {
    "channel": "orderbook"
  }
}

Notes

Throttling

Updates are throttled to a maximum of 4 updates per second per market (250ms bucket). This prevents overwhelming clients with rapid-fire updates during high-volume trading.

Catchup Skip

If the block age is greater than 30 seconds, broadcasts may be skipped to allow the system to catch up with the blockchain.