Orderbook + DLOB websocket
The DLOB (Decentralized Limit Order Book) server powers the UI orderbook and trades feed. It provides both a websocket interface for real-time updates and REST endpoints for snapshots.
Provisional endpoint. Velocity’s hosted DLOB server host is not yet finalized. This page uses dlob.velocity.exchange as a placeholder pattern (mirroring Drift’s dlob.drift.trade) — confirm the real host before shipping against it.
REST endpoints (recommended starting point)
Before wiring up websockets, you can fetch orderbook snapshots via simple HTTP requests. This is useful for polling-based UIs or quick prototyping.
L2 orderbook (aggregated by price level)
GET https://dlob.velocity.exchange/l2?marketName=SOL-PERP&depth=10&includeVamm=true&includeIndicative=trueQuery parameters:
marketName, Market symbol (e.g.SOL-PERP,BTC-PERP,SOL)depth, Number of price levels per side (default: all)includeVamm, Include AMM liquidity in the book (true/false)includeIndicative, Include indicative (non-firm) quotes (true/false)grouping, Price grouping in ticks (e.g.10for 0.01 increments)
Response shape:
{
"bids": [
{ "price": "123.45", "size": "100.5" },
{ "price": "123.40", "size": "250.0" }
],
"asks": [
{ "price": "123.50", "size": "80.2" },
{ "price": "123.55", "size": "150.0" }
],
"slot": 250000000
}L3 orderbook (individual orders)
GET https://dlob.velocity.exchange/l3?marketName=SOL-PERP&includeVamm=trueReturns every individual order with maker address and order ID , useful for building order-level analytics or matching simulations.
WebSocket connection
For real-time streaming, connect to the DLOB websocket:
- Base URL:
wss://dlob.velocity.exchange/ws
Subscribe to channels
Supported channels: orderbook, trades
const ws = new WebSocket("wss://dlob.velocity.exchange/ws");
ws.onopen = () => {
// Subscribe to orderbook updates with full liquidity
ws.send(JSON.stringify({
type: "subscribe",
channel: "orderbook",
marketType: "perp",
market: "SOL-PERP",
grouping: 10, // Price grouping (0.01 increments)
includeVamm: true, // Include AMM liquidity
includeIndicative: true // Include indicative quotes
}));
// Subscribe to trades
ws.send(JSON.stringify({
type: "subscribe",
channel: "trades",
marketType: "perp",
market: "SOL-PERP"
}));
};
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
// The channel in responses includes market info, e.g.:
// "orderbook_perp_0_grouped_10"
// "trades_perp_0"
const channel = message.channel;
// IMPORTANT: The `data` field is often a double-encoded JSON string.
// You need a second JSON.parse() to get the actual object.
const data = typeof message.data === "string"
? JSON.parse(message.data)
: message.data;
if (channel && channel.startsWith("orderbook_")) {
console.log("Bids:", data.bids);
console.log("Asks:", data.asks);
}
if (channel && channel.startsWith("trades_")) {
console.log("New trade:", data);
}
};
// Handle connection lifecycle
ws.onerror = (error) => console.error("DLOB WS error:", error);
ws.onclose = () => {
console.log("DLOB WS closed , implement reconnection logic here");
};Class WebSocketReference ↗
Class WebSocketReference ↗WebSocket.Response channel format
The channel field in websocket responses is not the same as the channel you subscribed to. It includes the market type, market index, and grouping:
| Subscribed channel | Response channel format |
|---|---|
orderbook | orderbook_perp_{marketIndex}_grouped_{grouping} |
trades | trades_perp_{marketIndex} |
For example, subscribing to orderbook for SOL-PERP with grouping: 10 produces responses with channel orderbook_perp_0_grouped_10.
Double-encoded data field
The data field in websocket messages is frequently a JSON string inside a JSON string. Always check whether data is a string before using it:
// Raw message from WS:
// { "channel": "orderbook_perp_0_grouped_10", "data": "{\"bids\":[...],\"asks\":[...]}" }
const parsed = JSON.parse(event.data); // First parse: message envelope
const book = typeof parsed.data === "string"
? JSON.parse(parsed.data) // Second parse: actual orderbook
: parsed.data;Map symbols consistently
Market symbols (e.g. SOL-PERP) match the UI. The market index in response channels corresponds to the SDK’s marketIndex , keep your market list in sync with the SDK’s market metadata to avoid mismatches.