Live Trades
Stream real-time trade executions from Deepbook pools as they occur on-chain. Each event represents a completed order fill with full execution details including price, quantities, fees, and order IDs.
Event Type
Events are emitted with type deepbook_live_trades and include complete trade metadata from the blockchain.
Endpoint
GET /deepbook/{poolName}/live-trades
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_live_trades",
"timestamp_ms": 1758629823918,
"checkpoint_id": 193054501,
"tx_hash": "FgUfRsYpC6ynW3pRvtgCLaa4WniBZYdsSLP94jrZ3pj7",
"data": {
"event_digest": "FgUfRsYpC6ynW3pRvtgCLaa4WniBZYdsSLP94jrZ3pj70",
"digest": "FgUfRsYpC6ynW3pRvtgCLaa4WniBZYdsSLP94jrZ3pj7",
"sender": "0xb117b12facd947cabb3d17d68a67b3d8d6865280edb0644cb4d25a9d86646966",
"checkpoint": 193054501,
"checkpoint_timestamp_ms": 1758629823918,
"package": "0xf6cc231ead142d35c37494a4c36d9e78c97503c0be9f9a0652f6e1127304096a",
"pool_id": "0xe05dafb5133bcffb8d59f4e12465dc0e9faeaa05e3e342a08fe135800e3e4407",
"maker_order_id": "170141183460531590950028478855175318595",
"taker_order_id": "62359236787919212896114997",
"maker_client_order_id": "5797765110082330991",
"taker_client_order_id": "8",
"price": 3380500,
"taker_fee": 646286,
"taker_fee_is_deep": true,
"maker_fee": 0,
"maker_fee_is_deep": false,
"taker_is_bid": true,
"base_quantity": 443700000000,
"quote_quantity": 1499927850,
"maker_balance_manager_id": "0x344c2734b1d211bd15212bfb7847c66a3b18803f3f5ab00f5ff6f87b6fe6d27d",
"taker_balance_manager_id": "0x939adae6836dd87de7b7a2a48a5bd703dc1add7eb304d0c580217e000ccd2b10",
"onchain_timestamp": 1758629823805
}
}
Field Reference
Event Metadata
| Field | Type | Description |
|---|---|---|
type | string | Always "deepbook_live_trades" for trade events |
timestamp_ms | number | Event timestamp in milliseconds |
checkpoint_id | number | Sui checkpoint when trade occurred |
tx_hash | string | Transaction hash containing the trade |
Trade Data
| Field | Type | Description |
|---|---|---|
pool_id | string | Deepbook pool identifier |
price | number | Execution price (in smallest units) |
base_quantity | number | Amount of base asset traded (in smallest units) |
quote_quantity | number | Amount of quote asset traded (in smallest units) |
taker_is_bid | boolean | true if taker bought, false if taker sold |
maker_order_id | string | Maker's order ID |
taker_order_id | string | Taker's order ID |
maker_client_order_id | string | Client-assigned maker order ID |
taker_client_order_id | string | Client-assigned taker order ID |
Fee Information
| Field | Type | Description |
|---|---|---|
taker_fee | number | Fee paid by taker |
taker_fee_is_deep | boolean | Whether taker paid fee in DEEP tokens |
maker_fee | number | Fee paid by maker (typically 0) |
maker_fee_is_deep | boolean | Whether maker paid fee in DEEP tokens |
Blockchain Metadata
| Field | Type | Description |
|---|---|---|
sender | string | Address that initiated the transaction |
package | string | Deepbook package address |
maker_balance_manager_id | string | Maker's balance manager address |
taker_balance_manager_id | string | Taker's balance manager address |
onchain_timestamp | number | On-chain timestamp in milliseconds |
Use Cases
Live Trade Feed
Display the latest trades in a trading interface:
const trades = [];
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_live_trades') {
const trade = {
price: data.data.price / 1e6, // Convert from smallest units (USDC decimals)
amount: data.data.base_quantity / 1e9, // Convert from smallest units (SUI decimals)
side: data.data.taker_is_bid ? 'buy' : 'sell',
timestamp: new Date(data.data.checkpoint_timestamp_ms)
};
// Add to feed and keep last 50 trades
trades.unshift(trade);
if (trades.length > 50) trades.pop();
updateTradesFeed(trades);
}
};
Volume Calculation
Track trading volume over time:
let volumeTracker = {
baseVolume: 0,
quoteVolume: 0,
tradeCount: 0,
startTime: Date.now()
};
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_live_trades') {
volumeTracker.baseVolume += data.data.base_quantity;
volumeTracker.quoteVolume += data.data.quote_quantity;
volumeTracker.tradeCount++;
// Calculate volume per hour
const elapsedHours = (Date.now() - volumeTracker.startTime) / (1000 * 60 * 60);
const hourlyVolume = volumeTracker.quoteVolume / elapsedHours;
updateVolumeDisplay(hourlyVolume);
}
};
Price Chart Updates
Build live candlestick charts:
let currentCandle = null;
const candleInterval = 60000; // 1 minute
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_live_trades') {
const price = data.data.price;
const timestamp = data.data.checkpoint_timestamp_ms;
const candleTime = Math.floor(timestamp / candleInterval) * candleInterval;
if (!currentCandle || currentCandle.time !== candleTime) {
// Start new candle
if (currentCandle) {
chartData.push(currentCandle);
updateChart(chartData);
}
currentCandle = {
time: candleTime,
open: price,
high: price,
low: price,
close: price,
volume: 0
};
}
// Update current candle
currentCandle.high = Math.max(currentCandle.high, price);
currentCandle.low = Math.min(currentCandle.low, price);
currentCandle.close = price;
currentCandle.volume += data.data.base_quantity;
updateCurrentCandle(currentCandle);
}
};
Trading Bot Trigger
Execute automated strategies based on trade activity:
const strategy = {
tradeThreshold: 1000, // Minimum trade size in base asset
priceMovementPercent: 0.5 // 0.5% price movement
};
let lastSignificantPrice = null;
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_live_trades') {
const tradeSize = data.data.base_quantity / 1e9; // Convert to SUI
const price = data.data.price;
// Check for significant trades
if (tradeSize >= strategy.tradeThreshold) {
console.log('Large trade detected:', tradeSize, 'SUI');
if (lastSignificantPrice) {
const priceChange = ((price - lastSignificantPrice) / lastSignificantPrice) * 100;
if (Math.abs(priceChange) >= strategy.priceMovementPercent) {
// Trigger strategy
executeTradingStrategy(data.data.taker_is_bid ? 'buy' : 'sell', price);
}
}
lastSignificantPrice = price;
}
}
};
Understanding Trade Sides
The taker_is_bid field indicates the taker's side:
-
true— Taker placed a buy order (bid), taking liquidity from sell side- This is a market buy or aggressive limit buy
- Typically shown as green/bullish in trading UIs
-
false— Taker placed a sell order (ask), taking liquidity from buy side- This is a market sell or aggressive limit sell
- Typically shown as red/bearish in trading UIs
Price and Quantity Conversion
All values are in smallest units based on asset decimals. Convert using pool metadata from the Get Pools endpoint.
Example for SUI_USDC
- Base asset (SUI): 9 decimals
- Quote asset (USDC): 6 decimals
// Convert price
const rawPrice = 3380500;
const humanPrice = rawPrice / Math.pow(10, 6); // = 3.3805 USDC per SUI
// Convert base quantity
const rawBaseQty = 443700000000;
const humanBaseQty = rawBaseQty / Math.pow(10, 9); // = 443.7 SUI
// Convert quote quantity
const rawQuoteQty = 1499927850;
const humanQuoteQty = rawQuoteQty / Math.pow(10, 6); // = 1499.93 USDC
Connection Example
Complete example connecting to the live trades stream:
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.onopen = () => {
console.log('Connected to Deepbook live trades stream');
};
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'deepbook_live_trades') {
console.log('Trade:', {
pool: data.data.pool_id.slice(0, 10) + '...',
price: data.data.price,
amount: data.data.base_quantity,
side: data.data.taker_is_bid ? 'BUY' : 'SELL',
time: new Date(data.data.checkpoint_timestamp_ms).toISOString()
});
}
};
eventSource.onerror = (error) => {
console.error('Stream error:', error);
eventSource.close();
// Reconnect after 5 seconds
setTimeout(() => {
location.reload(); // Simple reconnection strategy
}, 5000);
};
Best Practices
- Cache Pool Decimals — Fetch decimals once from Get Pools endpoint and reuse for all conversions
- Filter by Trade Size — Ignore dust trades by checking
base_quantitythreshold - Aggregate for Display — Don't update UI on every single trade; batch updates every 100-200ms
- Monitor Connection Health — SSE connections can drop; implement automatic reconnection with exponential backoff
- Combine with Order Book — Use both trade stream and order book depth for complete market view
Next Steps
- Order Book Depth — Stream live order book updates
- Deepbook API Overview — Query historical trade data
- What are SSE? — Learn about Server-Sent Events