Skip to main content
The market explorer switches from one address to the whole venue: every perp asset with its mark price, open interest, funding rate and 24-hour change; a live order book for a selected coin; and a streaming tape of every fill on the exchange.

1. Build the market table

The asset universe and its market context come from two types that must be read together:
  • meta gives the static universe: asset names, size decimals, max leverage.
  • webData2 gives the live context per asset: mark price, open interest, funding, 24-hour volume.
Pin webData2 to GoldRush for this read. webData2 is served by several providers, but they don’t all populate the assetCtxs slice. Leave the request unpinned and the waterfall may hand you a response whose assetCtxs is an empty array, which renders every price, open interest, and funding cell in your table as null. Pinning removes the ambiguity. The meta read alongside it needs no pin: every provider serves it.

The positional join

Here’s the part that’s easy to get wrong. webData2.assetCtxs is a bare array with no coin field on its entries. It’s joined to meta.universe by index, so that assetCtxs[i] is the context for universe[i].
Two consequences follow, and both are load-bearing: Index alignment is the join key, so you must not filter the universe before indexing into assetCtxs. Filtering delisted assets first shifts every subsequent index by one and silently mislabels the entire rest of the table, showing BTC’s open interest against ETH. Filter inside the loop, after you’ve read ctxs[i]. The arrays can be different lengths. assetCtxs is not guaranteed to be as long as universe, so guard every access.
A few field notes:
  • openInterest is denominated in the base asset, not USD. Multiply by markPx to get the notional figure people expect to see in a market table.
  • funding is the current hourly rate as a decimal, so 0.0000125 is 0.00125% per hour. Multiply by 24 * 365 for the annualized figure if you display APR.
  • szDecimals is the asset’s size precision. Use it to format sizes correctly rather than picking a fixed decimal count for the whole table.

2. Overlay live mids

The markPx values in assetCtxs are a snapshot. Rather than re-polling webData2 on a tight loop, reuse the live price store from the wallet tracker. The allFills stream is already giving you a last-trade price per coin, and it’s the same one subscription regardless of how many assets you display.
Refresh webData2 on a slow interval of 30 to 60 seconds for the fields the tape can’t give you (open interest, funding, 24-hour volume), and let the stream carry price.

3. Add a live order book

l2Book is available over both REST and WebSocket. For a live book, subscribe: a polling loop costs a request per tick and still lags.
The coin field accepts a single asset ("BTC") or an array (["BTC", "ETH"]). Omitting it streams every asset, at 50 credits per minute rather than 0.5 per coin. Only take the wildcard if you genuinely need all 200-plus books.
levels is a two-element array, [bids, asks], each sorted best-first. So levels[0][0] is the highest bid and levels[1][0] is the lowest ask. Each level carries px (price), sz (total size at that price) and n (number of orders). Cumulative depth, for a depth chart or a ladder:
If you’re rendering a book for one coin at a time, unsubscribe from the previous coin when the user switches. Subscriptions are billed per minute and matched for unsubscribe by exact body, so leaving old ones open is a slow, silent cost leak.
For a high-frequency book you can subscribe to l2BookDiff instead: a full snapshot first, then per-block changed levels only, at a fifth the cost. You maintain the book locally, replacing each level and deleting it when sz is "0". See the WebSocket guide for the snapshot/diff handling.

4. Add the trade tape

You already have the subscription (allFills, opened for the price store), so the tape costs nothing extra. Same [address, fill] tuple envelope as userFills:
The address half of each tuple is what makes this more than a price ticker: it links each fill to a trader, so a “largest fills” view doubles as trader discovery. Click through to the wallet tracker for whoever just moved size.
allFills carries the entire venue, with thousands of events per minute in active markets. Cap your buffer (as above), and never re-render per message. Accumulate into an array and flush to the UI on a timer.

Next

Leaderboard ranks traders using batch reads plus the same allFills stream.