client.marketData reads and streams public spot trade prints, and exposes the raw spot
configuration. It uses the public transport, so no authentication is required.
Prices and quantities are decimal strings. Trade timestamps are nanosecond epochs (tsNs), with a
millisecond convenience field (tsMs) alongside.
Methods
| Method | Summary |
|---|---|
listTrades | List public trades, newest-first or as a backfill. |
getSpotConfig | Fetch the raw spot reference-data snapshot. |
subscribeTrades | Stream live trade prints for a symbol. |
listTrades(input, options?)
Returns { trades, nextPageToken }, ordered newest-first by execution time, or a gap-free
backfill page when you pass afterTradeId. Only symbolId is required.
const { trades } = await client.marketData.listTrades({
symbolId: 1,
limit: 100,
side: "buy",
});
for (const t of trades) {
console.log(t.tsMs, t.sideLabel, t.price, t.qty);
}Page through history with the returned token:
let pageToken = "";
do {
const page = await client.marketData.listTrades({ symbolId: 1, pageToken, limit: 200 });
console.log(page.trades.length);
pageToken = page.nextPageToken;
} while (pageToken !== "");GetMarketTradesInput
| Field | Type | Required | Notes |
|---|---|---|---|
symbolId | number | yes | Positive uint32 engine symbol id (1 through 4,294,967,295). |
limit | number | no | Integer from 1 through 1,000. |
side | "buy" | "sell" | no | Filter to one aggressor side. |
startTsNs | string | no | Range start, epoch nanoseconds. |
endTsNs | string | no | Range end, epoch nanoseconds. |
pageToken | string | no | Cursor from a previous nextPageToken. |
afterTradeId | string | no | Backfill cursor, a matchId. See below. |
startTsNs, endTsNs, and afterTradeId are uint64 decimal strings. A value above
18446744073709551615 throws ValidationError.
Gap-free backfill
Pass afterTradeId to walk a symbol's trades by matchId, oldest first, with no gaps, for
example to fill in trades a live stream missed. Start from "0" for the symbol's first trade, then
pass backfill.nextAfterTradeId. When nextAfterTradeId equals the afterTradeId you sent,
nothing newer is available yet: retry later with backoff. afterTradeId cannot be combined with side, startTsNs, endTsNs, or pageToken; doing so throws ValidationError.
let afterTradeId = "0";
for (;;) {
const { trades, backfill } = await client.marketData.listTrades({ symbolId: 1, afterTradeId });
for (const t of trades) store(t);
if (!backfill || backfill.nextAfterTradeId === afterTradeId) break; // caught up
afterTradeId = backfill.nextAfterTradeId;
}The result then carries backfill, whose IDs are uint64 decimal strings:
| Field | Meaning |
|---|---|
completeThroughTradeId | Every trade with a matchId at or below this exists and is returned by this walk. Newer trades may exist that are not available yet; it only grows. |
nextAfterTradeId | The afterTradeId for the next page. It never moves backwards and keeps advancing across epoch ends and empty epochs. |
epochEnds | { epoch, lastTradeId }[], ascending: every epoch that ended between afterTradeId and nextAfterTradeId, inclusive. lastTradeId is the matchId of the epoch's last trade, or the epoch's start ID when it ended without trades. |
getSpotConfig(options?)
Returns the raw SpotConfig snapshot: asset metadata, pair trading constraints and limits, pair
status, display scales, and market slippage defaults, plus the venue-wide maxOpenOrdersTotal.
This is the reference data the catalog is built from. See Pair status and limits for the
limit fields.
const config = await client.marketData.getSpotConfig();
console.log(config.assets.length, config.pairs.length);Most of the time you want the parsed, indexed catalog instead of raw config: reach for getSpotConfig only when you need the untransformed snapshot.
subscribeTrades(input)
Streams live trade prints for one symbol. Returns an idempotent unsubscribe function.
const unsubscribe = client.marketData.subscribeTrades({
symbolId: 1,
onEvent: (trade) => console.log(trade.sideLabel, trade.price, trade.qty),
onError: (ctx) => console.error(ctx.channel, ctx.error),
});
// later
unsubscribe();Each publication carries a batch of trades, and onEvent receives them one at a time in execution
order. A trade whose matchId was already emitted replaces the earlier copy, so key stored trades
by matchId. A malformed trade reaches onError without dropping the rest of its batch.
onEvent is required. onOpen, onClose, and onError are optional. See the realtime client reference for the handler contract.
The MarketTrade shape
listTrades rows and subscribeTrades events share this shape.
interface MarketTrade {
symbolId: number;
matchId: string; // stable print id, also the pagination tie-breaker
isBuy: boolean; // true when the aggressor bought
sideLabel: "buy" | "sell";
qty: string; // decimal string
price: string; // decimal string
tsNs: string; // execution time, epoch nanoseconds
tsMs: number; // same time, epoch milliseconds
}Related
- Market data guide for the task-oriented walkthrough.
- Streaming guide for the subscription model.
- Catalog reference for the parsed reference data.
- Order book for depth.
- Candles for OHLCV series.