Order Book Depth
Stream real-time order book state changes from Deepbook pools. Each event includes current bid and ask levels with prices, quantities, and order counts—essential for depth charts, spread analysis, and liquidity monitoring.
Event Type
Events are emitted with type deepbook_order_book_depth and provide a snapshot of the current order book state.
Endpoint
GET /deepbook/{poolName}/live-trades
Note: Order book depth events are delivered on the same stream as live trades. Filter by event type to handle each appropriately.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
poolName | string | Yes | Trading pool name (e.g., "SUI_USDC") |
api-key | string | Yes | Your Surflux API key (query parameter) |
Event Structure
{
"type": "deepbook_order_book_depth",
"timestamp_ms": 1758629823918,
"checkpoint_id": 193054501,
"tx_hash": "FgUfRsYpC6ynW3pRvtgCLaa4WniBZYdsSLP94jrZ3pj7",
"data": {
"pool_id": "0xe05dafb5133bcffb8d59f4e12465dc0e9faeaa05e3e342a08fe135800e3e4407",
"bids": [
{
"price": 3380100,
"total_quantity": 2957000000000,
"order_count": 2
},
{
"price": 3380000,
"total_quantity": 2366000000000,
"order_count": 1
},
{
"price": 3379900,
"total_quantity": 443800000000,
"order_count": 1
}
],
"asks": [
{
"price": 3380500,
"total_quantity": 443700000000,
"order_count": 1
},
{
"price": 3381200,
"total_quantity": 11239000000000,
"order_count": 4
},
{
"price": 3383700,
"total_quantity": 8000000000000,
"order_count": 1
}
]
}
}
Field Reference
Event Metadata
| Field | Type | Description |
|---|---|---|
type | string | Always "deepbook_order_book_depth" for order book events |
timestamp_ms | number | Event timestamp in milliseconds |
checkpoint_id | number | Sui checkpoint when order book changed |
tx_hash | string | Transaction hash that caused the update |
Order Book Data
| Field | Type | Description |
|---|---|---|
pool_id | string | Deepbook pool identifier |
bids | array | Array of bid levels, sorted highest to lowest |
asks | array | Array of ask levels, sorted lowest to highest |
Price Level Object
Each bid and ask level contains:
| Field | Type | Description |
|---|---|---|
price | number | Price level (in smallest units) |
total_quantity | number | Total quantity available at this price |
order_count | number | Number of individual orders at this level |
Use Cases
Depth Chart Visualization
Render live order book depth charts:
let orderBook = { bids: [], asks: [] };
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
// Convert to human-readable prices and quantities
orderBook.bids = data.data.bids.map(level => ({
price: level.price / 1e6, // USDC decimals
quantity: level.total_quantity / 1e9, // SUI decimals
orders: level.order_count
}));
orderBook.asks = data.data.asks.map(level => ({
price: level.price / 1e6,
quantity: level.total_quantity / 1e9,
orders: level.order_count
}));
// Calculate cumulative quantities for depth chart
const bidsWithCumulative = calculateCumulative(orderBook.bids, 'desc');
const asksWithCumulative = calculateCumulative(orderBook.asks, 'asc');
updateDepthChart(bidsWithCumulative, asksWithCumulative);
}
};
function calculateCumulative(levels, direction) {
let cumulative = 0;
const result = [];
const sorted = direction === 'desc'
? [...levels].reverse()
: levels;
for (const level of sorted) {
cumulative += level.quantity;
result.push({ ...level, cumulative });
}
return direction === 'desc' ? result.reverse() : result;
}
Spread Calculation
Monitor bid-ask spread in real-time:
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
const bestBid = data.data.bids[0];
const bestAsk = data.data.asks[0];
if (bestBid && bestAsk) {
const spread = bestAsk.price - bestBid.price;
const spreadPercent = (spread / bestBid.price) * 100;
console.log('Spread:', {
absolute: spread / 1e6, // USDC
percent: spreadPercent.toFixed(3) + '%',
midPrice: ((bestBid.price + bestAsk.price) / 2) / 1e6
});
updateSpreadDisplay(spread, spreadPercent);
}
}
};
Liquidity Analysis
Track available liquidity at different price ranges:
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
const { bids, asks } = data.data;
// Calculate liquidity depth
const bidLiquidity = bids.reduce((sum, level) => sum + level.total_quantity, 0);
const askLiquidity = asks.reduce((sum, level) => sum + level.total_quantity, 0);
// Find liquidity imbalance
const imbalance = (bidLiquidity - askLiquidity) / (bidLiquidity + askLiquidity);
console.log('Liquidity:', {
totalBids: bidLiquidity / 1e9, // SUI
totalAsks: askLiquidity / 1e9, // SUI
imbalance: (imbalance * 100).toFixed(2) + '%',
bidLevels: bids.length,
askLevels: asks.length
});
// Positive imbalance = more buy pressure
// Negative imbalance = more sell pressure
updateLiquidityIndicator(imbalance);
}
};
Market Making Strategy
Adjust order placement based on real-time book state:
const marketMaker = {
targetSpreadBps: 10, // 0.1% spread
minLiquidity: 1000 // Minimum 1000 SUI liquidity
};
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
const { bids, asks } = data.data;
if (!bids.length || !asks.length) return;
const bestBid = bids[0].price;
const bestAsk = asks[0].price;
const midPrice = (bestBid + bestAsk) / 2;
// Calculate liquidity
const topBidLiquidity = bids[0].total_quantity / 1e9;
const topAskLiquidity = asks[0].total_quantity / 1e9;
// Check if market making opportunity exists
const currentSpreadBps = ((bestAsk - bestBid) / midPrice) * 10000;
if (currentSpreadBps > marketMaker.targetSpreadBps) {
// Wide spread - place orders inside
const newBidPrice = midPrice * (1 - marketMaker.targetSpreadBps / 20000);
const newAskPrice = midPrice * (1 + marketMaker.targetSpreadBps / 20000);
console.log('Market making opportunity:', {
currentSpread: currentSpreadBps.toFixed(2) + ' bps',
suggestedBid: newBidPrice / 1e6,
suggestedAsk: newAskPrice / 1e6
});
// Execute market making strategy
placeMarketMakerOrders(newBidPrice, newAskPrice);
}
}
};
Order Book Display
Build a traditional order book UI:
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
const { bids, asks } = data.data;
// Take top 10 levels for display
const displayBids = bids.slice(0, 10).map(level => ({
price: (level.price / 1e6).toFixed(4),
quantity: (level.total_quantity / 1e9).toFixed(2),
total: (level.total_quantity / 1e9).toFixed(2),
orders: level.order_count
}));
const displayAsks = asks.slice(0, 10).map(level => ({
price: (level.price / 1e6).toFixed(4),
quantity: (level.total_quantity / 1e9).toFixed(2),
total: (level.total_quantity / 1e9).toFixed(2),
orders: level.order_count
}));
// Render order book table
renderOrderBook({
asks: displayAsks.reverse(), // Display asks from best to worst
spread: calculateSpread(bids[0], asks[0]),
bids: displayBids
});
}
};
Understanding Order Book Structure
Bids (Buy Orders)
Bids are sorted from highest to lowest price:
bids[0]is the best bid (highest buy price)- Traders willing to buy at these prices
- Provides support in price analysis
Asks (Sell Orders)
Asks are sorted from lowest to highest price:
asks[0]is the best ask (lowest sell price)- Traders willing to sell at these prices
- Provides resistance in price analysis
The Spread
The difference between best bid and best ask:
const spread = asks[0].price - bids[0].price;
const spreadPercent = (spread / bids[0].price) * 100;
Tight spreads indicate high liquidity and active trading. Wide spreads suggest lower liquidity.
Event Frequency
Order book depth events are emitted when:
- New orders are placed
- Existing orders are filled
- Orders are cancelled or modified
Expect multiple events per second during active trading periods. Consider throttling UI updates to maintain performance:
let lastUpdate = 0;
const updateThrottle = 200; // Max 5 updates per second
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
const now = Date.now();
if (now - lastUpdate >= updateThrottle) {
updateOrderBookUI(data.data);
lastUpdate = now;
}
}
};
Price and Quantity Conversion
All values are in smallest units. Convert using pool metadata from Get Pools.
Example for SUI_USDC
- Base asset (SUI): 9 decimals
- Quote asset (USDC): 6 decimals
// Convert price level
const rawPrice = 3380100;
const humanPrice = rawPrice / Math.pow(10, 6); // = 3.3801 USDC per SUI
// Convert quantity
const rawQuantity = 2957000000000;
const humanQuantity = rawQuantity / Math.pow(10, 9); // = 2957 SUI
Connection Example
const poolName = 'SUI_USDC';
const apiKey = 'YOUR_API_KEY';
const url = `https://flux.surflux.dev/deepbook/${poolName}/live-trades?api-key=${apiKey}`;
const eventSource = new EventSource(url);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_order_book_depth') {
console.log('Order book update:', {
pool: data.data.pool_id.slice(0, 10) + '...',
bestBid: data.data.bids[0]?.price,
bestAsk: data.data.asks[0]?.price,
bidLevels: data.data.bids.length,
askLevels: data.data.asks.length,
time: new Date(data.timestamp_ms).toISOString()
});
}
};
Best Practices
- Throttle UI Updates — Don't update on every event; batch updates every 100-200ms for smooth rendering
- Limit Displayed Levels — Show top 10-20 levels in UI; full book can have 100+ levels
- Cache Pool Decimals — Fetch once and reuse for all price/quantity conversions
- Calculate Cumulative Depth — For depth charts, accumulate quantities from best price outward
- Monitor Spread — Alert on abnormally wide spreads indicating low liquidity
- Combine with Trades — Use both order book and live trades for complete market view
Next Steps
- Live Trades — Stream real-time trade executions
- Deepbook API Overview — Query historical order book snapshots
- What are SSE? — Learn about Server-Sent Events