npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

okotoki

v1.4.4

Published

Okotoki API client for node

Downloads

43

Readme

Okotoki API client for NodeJS

Okotoki is a WebSockets (and a bit of REST) API that provides access to normalized and computable data feeds from top cryptocurrency exchanges, including Binance, Coinbase, and BitMEX.

Installation

npm i okotoki

API keys

For a demo you can use DEMO_API_KEY and DEMO_API_SECRET. When you'll go for real - please contact us at [email protected].

Usage

import Api, {
  Exchanges,
  coinIndex,
  largeTrades,
  leveledTradeVolume,
  orderBook,
  price,
  tradeVolume
} from '../src'

const key = 'YOUR_API_KEY'
const secret = 'YOUR_API_SECRET'

const api = new Api({
  key,
  secret,
  wsUrl: 'wss://api-eu.stage.okotoki.com/ws',
  debug: true,
  useBinary: false
})

api.onMessage = (msg) => {
  console.log(msg)
}

api.subscribe([
  { kind: 'index', coin: 'BTC' },
  { kind: 'index', coin: 'ETH' },
  { symbol: 'BTCUSDT', exchange: Exchanges.binance, kind: 'price' },
  {
    symbol: 'BTCUSDT',
    exchange: Exchanges.binance,
    kind: 'largeTrades',
    thresholdTrades: 10000,
    limitTrades: 30,
    thresholdLiquidations: 0,
    limitLiquidations: 30
  },
  {
    symbol: 'XBTUSD',
    exchange: Exchanges.bitmex,
    kind: 'tradeVolume'
  }
])

// or using helper subscrition methods

const tradesOpts = {
  thresholdTrades: 50000,
  thresholdLiquidations: 0,
  limitLiquidations: 30,
  limitTrades: 30
}

const orderBookOpts = {
  step: 10,
  rate: 1000,
  interval: 60000,
  window: 0
}

const leveledTradeVolumeOpts = {
  interval: 60000,
  window: 3600000,
  step: 10
}

api.subscribe([
  coinIndex('BTC'),
  coinIndex('ETH'),
  price(Exchanges.binance, 'BTCUSDT'),
  largeTrades(Exchanges.binance, 'BTCUSDT', tradesOpts),
  largeTrades(Exchanges.bitmex, 'XBTUSD', tradesOpts),
  tradeVolume(Exchanges.bitmex, 'BTCUSDT'),
  orderBook(Exchanges.binance, 'BTCUSDT', orderBookOpts),
  leveledTradeVolume(Exchanges.binance, 'BTCUSDT', leveledTradeVolumeOpts)
])

That's it? That's it.

What's included

Supported spot and derivatives exchanges:

  • Binance,
  • Bitfinex,
  • Bitmex,
  • Bitstamp,
  • Bybit,
  • Coinbase,
  • Deribit,
  • Huobi,
  • Kraken,
  • Okex;

Normalized data feeds

  • trades & liquidations
  • price
  • orderbooks (only Binance for now)
  • candle data

Computable data feeds

Computable is Okotoki's abstraction for a market data computation engine that combines realtime and historical data.

Currently available computable feeds:

  • index (composit weighed asset price)
  • rolling volume histograms (1h, 4h, 24h)
  • large trades (trades feed filtered by size)
  • large liquidations (liquidation feed filtered by size)
  • grouped orderbooks (only Binance for now)

What is a computable stream?

  • computable manages it's memory for in-memory buffer, evicts in-memory data when needed
  • computable understands historical data and can combine realtime and historical data into a single stream

Key assumptions

  • for now, we focus on a pretty recent data spanning up to a few days
  • market data we collect is not too large
    • which mean we can store quite a lot of it in memory
    • and if needed when dumping to disk we can use pretty simple index structures updated infrequently to fetch fast enough
  • we are fine with a few seconds to load older historical data

Key design decisions

  • we use simple and efficient fully-managed storage solutions: s3 for large chunks of data, dynamodb for small metadata
  • we offload historical data indexing and fetching to lambda functions that allow to scale up with the load and parallelize single requests
  • computables can load historical data and synchronize realtime data with other nodes

API

The Api class is used to interact with the Okotoki API.

Okotoki Api uses avro for data serialization. This means that response messages are mostly in a binary format and have to be serialized for consumption. You'll have to take that into account if you'll want to call Okotoki API directly.

Currently, we do not provide responses in JSON.

Constructor

constructor(
  private options: OkotokiAPIOptions,
  private wsOptions?: WsOptions
)

OkotokiApiOptions:

  • key: string – API key
  • secret: string – API secret
  • restUrl?: string – custom URL for the REST API
  • wsUrl?: string – custom URL for the WebSocket API
  • debug?: boolean – enables debugging mode, with verbose logs

WsOptions (optional)

Usually you won't need this and default WebSocket configuration will work just fine.

  • connectionTimeout: number - maximum wait time (in milliseconds) for a connection to succeed before closing and retrying
  • WebSocket: WebSocket - allows for a custom WebSocket implementation to be used
  • debug: boolean - enables debugging mode, with verbose logs
  • maxReconnectionDelay: number - represents the maximum wait time (in milliseconds) between reconnection attempts
  • minReconnectionDelay: number - represents the minimum wait time (in milliseconds) between reconnection attempts
  • maxRetries: number - represents the maximum number of reconnection attempts to make

.subscribe

public subscribe(subscriptions: Subscription[]): void

An generic method used to configure subscription feeds. Each Subscription corresponds to one of the available data feeds:

Example:

api.subscribe([
  { kind: 'index', coin: 'BTC' },
  { kind: 'index', coin: 'ETH' },
  { symbol: 'XBTUSDT', exchange: Exchanges.bitmex, kind: 'price' }
])

.onMessage

public onMessage(msg: InMessage): void

A message handler for all messages received from Okotoki API. All messages, received in binary format, will be serialized to JSON.

Possible incoming messages include:

and

  • ErrorMessage

Example:

api.onMessage = (message) => console.log(message)

ErrorMessage

Fields:

  • type=error
  • errorCode (string) – camel-case string with a human and programmatically-readable error code
  • errorMessage (`string) – message with error details
  • extra fields – for certain error codes additional fields with error details may be passed

Error codes:

  • unsupportedMessageType – sent in case server received an unsupported message type from client. Currently /ws endpoint supports only non-streamed text messages.
  • parseError
    • extra field messageString (string) – original in-message that we could not parse
  • readError – error reading message json into an internal object representation due to schema validation error
    • extra field validationErrors (array) – schema validation errors details
    • extra field message (any) – original message json
  • streamMissing – sent in case there was no stream found for a given subscription in subscribe request
    • extra field subscription (object) – original subscription for which subscribe failed

Example:

{
  "type": "error",
  "errorCode": "streamMissing",
  "errorMessage": "Can't subscribe to subscription kind=KindLargeTrade for ExchangeSymbol(Coinbase,BTC-USD123) – no such stream.",
  "subscription": {
    "kind": "largeTrades",
    "exchange": "coinbase",
    "symbol": "BTC-USD123",
    "thresholdTrades": 0,
    "limitTrades": 30,
    "thresholdLiquidations": 0,
    "limitLiquidations": 30
  }
}

Trade

Subscribe to trades and liquidations feed. Feed is configured to be filtered by size (in USD). On subscription you'll receive a batch of recent trades that satisfy threshold filtering.

Will emit TradeNormalized into .onMessage handler.

TradeSubscription

  • kind: largeTrades – subscription kind
  • symbol: string - symbol for which to receive updates.
  • exchange: Exchange - exchange for which to receive updates.
  • thresholdTrades: number - minimum size of trades to receive updates for.
  • limitTrades: number - maximum number of trades updates to receive.
  • thresholdLiquidations?: number - Optional. minimum size of liquidations to receive updates for.
  • limitLiquidations?: number - Optional. maximum number of liquidation updates to receive.

Example:

api.subscribe([
  {
    kind: 'largeTrades',
    exchange: 'coinbase',
    symbol: 'BTC-USD',
    thresholdTrades: 50000,
    limitTrades: 30
  },
  {
    kind: 'largeTrades',
    exchange: Exchange.bitmex,
    symbol: 'XBTUSD',
    thresholdTrades: 200000,
    limitTrades: 30,
    thresholdLiquidations: 5000,
    limitLiquidations: 30
  }
])

// or via shortcut method

const tradesOpts = {
  thresholdTrades: 50000,
  thresholdLiquidations: 0,
  limitLiquidations: 30,
  limitTrades: 30
}

api.subscribe([
  largeTrades(Exchanges.binance, 'BTCUSDT', tradesOpts),
  largeTrades(Exchanges.bitmex, 'XBTUSD', tradesOpts)
])

TradeNormalized

Fields:

  • type=streamElem
  • kind=trade/liquidation
  • exchange (string)
  • symbol (string)
  • id (string)
  • timestamp (string)
  • price (number)
  • amount (number)
  • amountInQuoteUnits (number)
  • side (string) – buy/sell
  • isLiquidation (boolean)

Example:

{
  "type": "com.okotoki.model.Trade",
  "kind": "trade",
  "exchange": "coinbase",
  "symbol": "BTC-USD",
  "id": "tr:Coinbase:BTC-USD:n-354542039",
  "timestamp": "2022-06-13T14:48:00.743417Z",
  "price": 22900,
  "amount": 0.05,
  "amountInQuoteUnits": 1145,
  "side": "buy",
  "isLiquidation": false
}

Price

Subscribe to market price data feed.

Will emit PriceUpdateNormalized into .onMessage handler.

PriceSubscription

  • kind: price – subscription kind
  • symbol: string - symbol for which to receive updates.
  • exchange: Exchange - exchange for which to receive updates.

Example:

api.subscribe([
  { symbol: 'XBTUSDT', exchange: Exchanges.bitmex, kind: 'price' }
])

// or via shortcut method

api.subscribe([price(Exchanges.binance, 'BTCUSDT')])

PriceUpdateNormalized

Fields:

  • type=streamElem
  • kind=price
  • exchange (string)
  • symbol (string)
  • timestamp (string)
  • price (number)

Example:

{
  "type": "com.okotoki.model.Price",
  "kind": "price",
  "exchange": "coinbase",
  "symbol": "BTC-USD",
  "timestamp": "2022-12-24T02:22:32.720792Z",
  "price": 16826.76
}

Index

Subscribe to weighted price data feed. Okotoki provides weighted indexes for supported coins and fiat currencies. We use it internally to aggregate cross-asset data feeds. For exampl -, indexes allow normalization of BTC-EUR market orderbook/trades in USD.

  • kind: index – subscription kind
  • coin: string - coin (BTC, ETH, etc) or fiat currency (AUD, GBP) symbol

Will emit IndexNormalized into .onMessage handler.

IndexSubscription

Example:

api.subscribe([
  { coin: 'BTC', kind: 'index' },
  { coin: 'ETH', kind: 'index' }
])

// or via shortcut method
api.subscribe([coinIndex('BTC'), coinIndex('ETH')])

IndexNormalized

Fields:

  • type=streamElem
  • kind=index
  • coin (string)
  • price (number)

Example:

{
  "type": "com.okotoki.model.Index",
  "kind": "index",
  "coin": "BTC",
  "price": 22900
}

OrderBook

Subscribe to order book data feed. Order book is grouped by step and updates are received every rate milliseconds.

  • kind: orderBook - subscription kind
  • symbol: string - symbol for which to receive updates.
  • exchange: Exchange - exchange for which to receive updates.
  • step: number - the step size for the order book updates.
  • rate: number - the rate (in milliseconds) at which to receive order book updates.

Will emit BookChangeNormalized into .onMessage handler.

OrderBookSubscription

Example:

api.subscribe([
  {
    kind: 'orderBook',
    exchange: Exchange.binance,
    symbol: 'BTCUSDT',
    step: 10,
    rate: 3000
  }
])

// or via shortcut method

const orderBookOpts = {
  step: 10,
  rate: 1000,
  interval: 60000,
  window: 0
}

api.subscribe([orderBook(Exchanges.binance, 'BTCUSDT', orderBookOpts)])

BookChangeNormalized

Order book updates. First message received is always a snapshot (isSnapshot=true), with subsequent messages being what changed compared to snapshot.

Fields:

  • type=streamElem
  • kind=price
  • exchange (string)
  • symbol (string)
  • isSnapshot (boolean) - tell you if received orderbook update is a snapshot or not
  • bids (array of BookPriceLevel)
  • bids[].price (number) – price of orderbook entry
  • bids[].amount (number) - amount at orderbook entry
  • asks (array of BookPriceLevel)
  • asks[].price (number) – price of orderbook entry
  • asks[].amount (number) - amount at orderbook entry

Example:

{
  "type": "streamElem",
  "kind": "bookChange",
  "exchange": "coinbase",
  "symbol": "BTC-USD",
  "isSnapshot": true,
  "bids": [
    { "price": 30720, "amount": 0.01627 },
    { "price": 40960, "amount": 0.31364 },
    { "price": 32770, "amount": 0.76425 },
    { "price": 43010, "amount": 1.42729 },
    { "price": 34820, "amount": 0.0004 },
    { "price": 36870, "amount": 0.23131 },
    ...
    { "price": 38920, "amount": 1.13323 },
    { "price": 30730, "amount": 0.00175 },
    { "price": 40970, "amount": 0.03618 },
    { "price": 32780, "amount": 0.0258 }
  ],
  "asks": [
    { "price": 51200, "amount": 0.64225 },
    { "price": 53250, "amount": 0.02834 },
    { "price": 45060, "amount": 0.03268 },
    { "price": 55300, "amount": 0.0032 },
    { "price": 47110, "amount": 5.52742 },
    ...
    { "price": 49160, "amount": 0.10401 },
    { "price": 51210, "amount": 0.01091 },
    { "price": 53260, "amount": 0.03405 },
    { "price": 45070, "amount": 0.49237 },
    { "price": 55310, "amount": 0.00015 }
  ]
}

TradeVolume

Subscribe to trade volume data feed. Rolling trade volume for 1h, 4h and 24h respectively.

  • kind: tradeVolume - subscription kind
  • symbol: string - symbol for which to receive updates.
  • exchange: Exchange - exchange for which to receive updates.

Will emit TradeVolumeNormalized into .onMessage handler.

TradeVolumeSubscription

Example:

api.subscribe([
  {
    symbol: 'XBTUSD',
    exchange: Exchanges.bitmex,
    kind: 'tradeVolume'
  }
])

// or via shortcut method

api.subscribe([tradeVolume(Exchanges.bitmex, 'BTCUSDT')])

TradeVolumeNormalized

Fields:

  • type=streamElem
  • kind=price
  • exchange (string)
  • symbol (string)
  • volumes (array of TradeVolumeHistogram)
  • volumes[].interval (number) – 1 minute/5 minutes/1 hour in millis
  • volumes[].window (number) – 1 hour/4 hours/1 day in millis
  • volumes[].earliestTimestamp (string)
  • volumes[].latestTimestamp (string)
  • volumes[].latestIntervalTimestamp (string)
  • volumes[].volumesBuy (number[]) – contains the number of intervals in the window plus one (for current incomplete interval) elements. The last element of the array corresponds to the latest interval.
  • volumes[].volumesSell (number[]) – similar to volumesSell (see above)

Example:

{
  "type": "streamElem",
  "kind": "tradeVolume",
  "exchange": "coinbase",
  "symbol": "BTC-USD",
  "volumes": [
    {
      "interval": 60000,
      "window": 3600000,
      "earliestTimestamp": "2022-12-24T02:22:01Z",
      "latestTimestamp": "2022-12-24T02:22:20Z",
      "latestIntervalTimestamp": "2022-12-24T02:22:00Z",
      "volumesBuy": [
        ...,
        0.19400856000000002
      ],
      "volumesSell": [
        ...,
        0.71882308
      ]
    },
    {
      "interval": 300000,
      "window": 14400000,
      "earliestTimestamp": "2022-12-24T02:22:01Z",
      "latestTimestamp": "2022-12-24T02:22:20Z",
      "latestIntervalTimestamp": "2022-12-24T02:20:00Z",
      "volumesBuy": [
        ...,
        22.740445899999997
      ],
      "volumesSell": [
        ...,
        68.29315792999996
      ]
    },
    {
      "interval": 3600000,
      "window": 86400000,
      "earliestTimestamp": "2022-12-24T02:22:01Z",
      "latestTimestamp": "2022-12-24T02:22:20Z",
      "latestIntervalTimestamp": "2022-12-24T02:00:00Z",
      "volumesBuy": [
        ...,
        94.97304128999991
      ],
      "volumesSell": [
        ...,
        184.75704159
      ]
    }
  ]
}

Candles

Subscribe to candle data feed. This provides OHLCV (Open, High, Low, Close, Volume) data for a given symbol and exchange.

  • kind: candles - subscription kind
  • symbol: string - symbol for which to receive updates.
  • exchange: Exchange - exchange for which to receive updates.
  • interval: number - the interval for each candle in milliseconds.
  • window: number - the time window for which to receive candle data in milliseconds.
  • metrics: string[] - array of metrics to include in the candle data (e.g., ["open", "high", "low", "close", "volume"])

Will emit CandleNormalized into .onMessage handler.

CandlesSubscription

Example:

api.subscribe([
  {
    kind: 'candles',
    exchange: Exchange.binance,
    symbol: 'BTCUSDT',
    interval: 60000, // 1 minute
    window: 3600000, // 1 hour
    metrics: ['open', 'high', 'low', 'close', 'volume']
  }
])

// or via shortcut method

const candlesOpts = {
  interval: 60000,
  window: 3600000,
  metrics: ['open', 'high', 'low', 'close', 'volume']
}

api.subscribe([candle(Exchanges.binance, 'BTCUSDT', candlesOpts)])

CandleNormalized

Fields:

  • type=streamElem
  • kind=candle
  • exchange (string)
  • symbol (string)
  • window (number) - time window in milliseconds
  • interval (number) - candle interval in milliseconds
  • timestamp (number) - timestamp of the candle
  • idx (number) - index of the candle in the current window
  • isSnapshot (boolean) - indicates if this is a snapshot of historical data
  • values (object) - an object containing the requested metrics (e.g., open, high, low, close, volume)

Example:

{
  "type": "streamElem",
  "kind": "candle",
  "exchange": "binance",
  "symbol": "BTCUSDT",
  "window": 3600000,
  "interval": 60000,
  "timestamp": 1672531200000,
  "idx": 59,
  "isSnapshot": false,
  "values": {
    "open": 16500.0,
    "high": 16550.5,
    "low": 16480.2,
    "close": 16525.8,
    "volume": 1250.45
  }
}

This candle data subscription allows you to receive regular updates on price and volume information for a specific trading pair, enabling you to perform various types of market analysis or build charting applications.

License

MIT