Market data & streams

Public market data needs no trading credentials (a Decibel client with just nodeApiKey serves it). Streams normalize both venues into the same callback shapes with reconnect catch-up built in.

Market data

  • Name
    markets({ venue })
    Type
    Promise<MarketInfo[]>
    Description

    Listed markets with sizeDecimals, priceDecimals, tickSize, lotSize, minSize, maxLeverage, isActive.

  • Name
    ticker({ venue, market })
    Type
    Promise<Ticker>
    Description

    The cheapest "what's the price?" primitive — single REST round-trip, always fresh. Returns markPrice, midPrice, oraclePrice, fundingRateBps, openInterest, timestamp.

  • Name
    orderbook({ venue, market, depth? })
    Type
    Promise<OrderBook>
    Description

    L2 snapshot, bids descending / asks ascending.

  • Name
    candles({ venue, market, interval, from?, to? })
    Type
    Promise<Candle[]>
    Description

    OHLC bars. interval: 1m | 5m | 15m | 1h | 4h | 1d.

  • Name
    recentTrades({ venue, market, limit? })
    Type
    Promise<PublicTrade[]>
    Description

    Last N public taker prints.

const md = new TriaClient({
  decibel: { nodeApiKey: process.env.TRIA_TRADE_DECIBEL_NODE_API_KEY! },
})

const { markPrice } = await md.ticker({ venue: 'decibel', market: 'BTC/USD' })
const bars = await md.candles({
  venue: 'decibel',
  market: 'BTC/USD',
  interval: '1h',
})

Streams

const off = await client.subscribeFills({ venue: 'hl' }, (fill) => {
  console.log(`${fill.market} ${fill.side} ${fill.size} @ ${fill.price}`)
})

off() // stop streaming
  • Name
    subscribeFills(args, cb)
    Type
    Promise<Unsubscribe>
    Description
    Live fills, deduped by venue fill ID, with reconnect catch-up.
  • Name
    subscribePositions(args, cb)
    Type
    Promise<Unsubscribe>
    Description
    Live position snapshots.
  • Name
    subscribeOrders(args, cb)
    Type
    Promise<Unsubscribe>
    Description
    Order lifecycle — one emission per state transition; reconnect catch-up replays missed orders.
  • Name
    subscribeAccount(args, cb)
    Type
    Promise<Unsubscribe>
    Description
    Live AccountSnapshot, frame-deduped so the callback only fires on real changes.
  • Name
    onConnection(cb)
    Type
    Unsubscribe
    Description
    Global WS lifecycle: connected / disconnected / reconnecting per venue.

Three guarantees

  1. Per-fill emission, never batch. Each callback gets one Fill. Decibel pushes full snapshots; the SDK diffs by fillId so you only see unseen fills.
  2. Reconnect catch-up. On WS drop + reconnect, the SDK REST-polls fills since the last seen timestamp + 1ms and replays them, deduplicated against the live stream.
  3. Normalized shape. Both venues emit the same Fill shape — buy/sell, decimal-string sizes/prices, unix-ms timestamps.

Connection lifecycle

const off = client.onConnection((event) => {
  switch (event.status) {
    case 'connected':
      console.log(`${event.venue} WS up`)
      break
    case 'disconnected':
      console.log(`${event.venue} WS dropped`)
      break
    case 'reconnecting':
      console.log(`${event.venue} reconnecting...`)
      break
  }
})

The hook fires once per state transition per venue. If you gate critical logic on "stream is live," reset it on disconnected and re-arm on the next connected.

Was this page helpful?