WebSocket API

Order Book Checksum

Checksum validation and resynchronization for order book streams

Every order book message includes a checksum for verifying local order book integrity.

Why Checksums Matter

Order books are streamed via snapshot + incremental updates. Missing a message can desynchronize your local book. Checksum verification detects this immediately.

Snapshots return the last emitted book (the same baseline diffs are computed against), not the real-time store state. This ensures the snapshot and diff stream are always consistent — no ghost levels from changes between throttled emissions.

Algorithm

  1. Interleave bids and asks: [bid[0], ask[0], bid[1], ask[1], ...]
  2. Join as px:sz fields with : separator
  3. Compute CRC32-IEEE

Example:

Bids: [[100, 5], [99, 3]]
Asks: [[101, 2]]

Preimage: "100:5:101:2:99:3"
Checksum: <CRC32 of preimage>

TypeScript

No external library needed — implements CRC32-IEEE directly with a pre-computed lookup table.

// CRC32-IEEE lookup table (pre-computed for performance)
const CRC32_TABLE = new Uint32Array(256)

for (let i = 0; i < 256; i++) {
  let crc = i
  for (let j = 0; j < 8; j++) {
    crc = crc & 1 ? (crc >>> 1) ^ 0xedb88320 : crc >>> 1
  }
  CRC32_TABLE[i] = crc >>> 0
}

function crc32(str: string): number {
  let crc = 0xffffffff
  for (let i = 0; i < str.length; i++) {
    const byte = str.charCodeAt(i) & 0xff
    crc = (crc >>> 8) ^ CRC32_TABLE[(crc ^ byte) & 0xff]!
  }
  return (crc ^ 0xffffffff) >>> 0
}

function computeOrderBookChecksum(bids: string[][], asks: string[][]): number {
  const parts: string[] = []
  const maxLen = Math.max(bids.length, asks.length)

  for (let i = 0; i < maxLen; i++) {
    if (i < bids.length) parts.push(bids[i]![0]!, bids[i]![1]!)
    if (i < asks.length) parts.push(asks[i]![0]!, asks[i]![1]!)
  }

  return crc32(parts.join(":"))
}

function verifyOrderBookChecksum(bids: string[][], asks: string[][], expectedChecksum: number): boolean {
  return computeOrderBookChecksum(bids, asks) === expectedChecksum
}

Usage:

function onBookMessage(msg: BookMessage) {
  if (msg.type === "snapshot") {
    bids = msg.data.bids
    asks = msg.data.asks
  } else {
    applyUpdate(msg.data)
  }

  if (msg.data.checksum !== undefined && !verifyOrderBookChecksum(bids, asks, msg.data.checksum)) {
    // Resubscribe to get a fresh snapshot
    ws.send(JSON.stringify({ op: "unsub", channel: "book", params: { market: "BTC-PERP" } }))
    ws.send(JSON.stringify({ op: "sub", channel: "book", params: { market: "BTC-PERP" } }))
  }
}

Resync Procedure

On checksum mismatch, immediately unsubscribe and resubscribe for a fresh snapshot:

ws.send(JSON.stringify({ op: "unsub", channel: "book", params: { market: "BTC-PERP" } }))
ws.send(JSON.stringify({ op: "sub", channel: "book", params: { market: "BTC-PERP" } }))

On this page