Smallest path into the SDK. Build a live ticker on Polyester devnet with public market data only. No keys, wallets, or sessions. By the end you will know the realtime contract every stream shares.
About ten minutes.
PolyesterClient can call
all of it.Create a public client
Install the SDK and create a client against the devnet environment. With no auth option, the
client can still read all public market data.
// ticker.ts
import { PolyesterClient, POLYESTER_DEVNET_ENVIRONMENT } from "@polyester/sdk";
const client = new PolyesterClient({ environment: POLYESTER_DEVNET_ENVIRONMENT });
await client.catalog.ensureReady();
const SYMBOL = "BTC-USDT";
const symbolId = client.catalog.market.requireSymbolIdByPairSymbol(SYMBOL);Trading and market-data streams use the stable numeric symbolId. Resolve it from the pair symbol
through the catalog.
Stream the market overview
The market overview is one row per market with last price and 24h stats. Its stream is snapshot-then-stream: it fetches the full set first, then merges live updates and emits the merged array. It also refetches automatically on reconnect, so you always render a consistent table.
const overviewUnsub = client.marketOverview.subscribe({
onEvent: (markets) => {
const top = markets.slice(0, 5);
for (const m of top) {
const symbol = client.catalog.market.requirePairSymbolBySymbolId(m.symbolId);
console.log(symbol, m.lastPrice);
}
},
onError: (ctx) => console.error("overview error", ctx.error),
});Every stream method follows the same shape: pass an onEvent handler (plus optional onOpen, onClose, and onError), and you get back an idempotent unsubscribe function.
Add a live candle feed
Subscribe to one-minute candles for your symbol. Handlers receive fully parsed objects with decimal strings, the same shapes the request methods return.
const candleUnsub = client.candles.subscribe({
symbolId,
timeframe: "1m",
onEvent: (candle) => console.log("candle close", candle.close),
onError: (ctx) => console.error("candle error", ctx.error),
});You can seed history first with client.candles.list({ symbolId, timeframe: "1m", limit: 60 }),
then let the stream keep it current.
Render a live order book
createSubscription maintains a local order book: initial snapshot, sequence-checked deltas, and
refetch after an observed sequence gap or reconnect. Your handler sees a complete book relative to
the last applied snapshot or delta. Any depth in [1, 500] works. A connected feed that goes
silent will not fire onError or refetch; if you need continuity, watch the last onEvent and
resync with orderbook.get(). See Order book.
const book = client.orderbook.createSubscription({
symbolId,
depth: 10,
onEvent: (b) => {
const bid = b.bids[0];
const ask = b.asks[0];
if (bid && ask) console.log(`bid ${bid.price} ask ${ask.price}`);
},
onError: (ctx) => console.error("book error", ctx.error),
});
// Re-aggregate into coarser price buckets without reconnecting:
book.setBucket("10");Run it and shut down
Under the hood, one shared WebSocket client multiplexes all three streams, so this costs a single connection. Clean up on exit:
process.on("SIGINT", () => {
overviewUnsub();
candleUnsub();
book.unsubscribe();
client.realtime.disconnect();
process.exit(0);
});bun run ticker.tsYou should see the top markets, then a stream of candle closes and top-of-book updates.
Where to go next
- Market data guide for every public read and stream.
- Streaming guide for the realtime model in depth.
- Build a trading bot to act on this data.