Streaming market data
A single subscribe call can open multiple streams. The client stores
subscribed state locally, so you can handle events as they arrive or read the
current state synchronously. A CCXT-style watch* layer is also available; use
it when porting a bot from another exchange.
Market data channels are public. A client with no identity,
createClient({ wsUrl }), can read all of them. Pass an identity only when you
also need your private channels (orders, account, deposits).
import { createClient, ephemeralKey } from "@sugar-rush/sdk";// A throwaway key, generated in the browser. Persist it to keep the same// account next time. Testnet only; do not reuse it on mainnet.const identity = await ephemeralKey(localStorage.getItem("sr-key") ?? undefined);localStorage.setItem("sr-key", identity.export());const client = createClient({ wsUrl: "wss://api.sugar.rush.preview.sundae.fi/ws", identity });await client.connect();console.log(client.welcome()); // the server's welcome frame
Subscribe to multiple streams
await client.subscribe({orderbook: ["DARK-VAN", "UBE-VAN"],ticker: ["DARK-VAN"],candles: [{ symbol: "DARK-VAN", interval: "1m" }],});console.log("DARK-VAN:", client.orderBook("DARK-VAN")?.bids.length, "bid levels");console.log("UBE-VAN:", client.orderBook("UBE-VAN")?.bids.length, "bid levels");console.log("candles:", client.candles("DARK-VAN", "1m").length, "bars");
Orderbook
You receive the full book on subscribe, then one merged delta per flush window
with the changed levels. A level reported with size 0 on both sides has been
removed. Frames are seq-chained: the snapshot carries seq, and each update
carries seq + prevSeq so a client can detect a missed frame and resubscribe
(the SDKs verify the chain for you).
const book = client.orderBook("DARK-VAN");console.log("best bid:", book?.bids[0]?.price, "best ask:", book?.asks[0]?.price);client.on("orderbook", ({ symbol, book }) => { /* per-update deltas applied */ });
Ticker & candles
The ticker carries the last price, best bid/ask, and 24h stats. Candles are
OHLCV; timestamps are unix milliseconds. Raw price fields are u128 fixed-point
on the wire and every one travels with a human-decimal twin (lastPriceDecimal,
openDecimal, …); use the twin directly, or convert the raw field with the
exported priceToNumber.
import { priceToNumber } from "@sugar-rush/sdk";client.on("ticker", ({ symbol, ticker }) =>console.log(symbol, priceToNumber(ticker.lastPrice ?? 0n)));
CCXT-style layer
while (running) {const book = await client.watchOrderBook("DARK-VAN");console.log(book.bids[0]?.price, "/", book.asks[0]?.price);}