1. Build the market table
The asset universe and its market context come from two types that must be read together:metagives the static universe: asset names, size decimals, max leverage.webData2gives 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].
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.
openInterestis denominated in the base asset, not USD. Multiply bymarkPxto get the notional figure people expect to see in a market table.fundingis the current hourly rate as a decimal, so0.0000125is0.00125%per hour. Multiply by24 * 365for the annualized figure if you display APR.szDecimalsis 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
ThemarkPx 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.
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.
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:
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:
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.
Next
Leaderboard ranks traders using batch reads plus the sameallFills stream.