Node.JS Client 2.0.0 — Beta Release

Cris Mihalache
Bitfinex
Published in
5 min readJan 3, 2018

Today we’re happy to announce the v2.0.0 beta release of our Node.JS API client, featuring better support for version 2 of our WebSocket and REST APIs along with highly sought after helpers for managing your orders and data.

In this article we’ll go over the new features, and provide a few examples to give you an idea of what you can do with our APIs.

As always, you can find the full server API documentation on our website:

Compatibility

This release breaks compatibility with v1.x of our node client, although in many places by providing functionality which previously had to be implemented by end-users. We don’t do this lightly, and have marked this release as beta to give you time to submit feedback.

If you have any issues, suggestions, or questions which are not answered by the documentation, feel free to open a ticket on our issue tracker.

Updated WebSocket v2 Client

Most of the changes in this release reside in the WSv2 client, which interacts with version 2 of our WebSocket server API and has been revised based on user feedback and common use cases.

Many utility methods have been added — one example being onMaintenanceStart, which registers a listener that is triggered when a server maintenance period begins, enabling you to handle this case in your logic.

We’ve also replaced the transform logic with high-level model classes (i.e. the ‘Order’ model) which expose field names that match our docs and provide extra functionality.

A list of major changes & new features follows; A full changelog is available here.

Improved Connection Reliability

During times of high platform load, or network congestion, your WebSocket might disconnect. To help, we’ve added reconnect() as a utility method, along with delayed auto-reconnection via a constructor flag.

A packet watchdog has also been added, which will call reconnect() if no packet has been received within the watchdog delay, along with automatic sequence number validation:

const ws = new WSv2({
autoReconnect: true,
reconnectDelay: 1000,
seqAudit: true,
packetWDDelay: 10 * 1000
})
ws.on('open', () => {
// …
})
ws.open()

Sequence numbers can be manually enabled with enableSequencing(), and will be included as the last value(s) in message arrays. Passing true will enable automatic auditing, where an error is emitted on sequence mismatch.

If you’ve been experiencing network errors in the past and weren’t sure of the cause, these flags are a great way to check.

Models: OrderBook, Trade, and more!

The transform logic has been rewritten with the help of model classes for each data type. By creating a WSv2 client with transform: true, data will be transformed where possible before being passed on to listeners.

Transformed objects have high-level methods to help with common tasks in some cases, like OrderBook’s bidAmount() and midPrice(). When parsing the original arrays, the model definitions also provide documentation on field indexes:

// lib/models/trade.js
class Trade extends Model {
serialize () {
return [
this.id,
this.pair,
this.mtsCreate,
this.orderID,
this.execAmount,
this.execPrice,
this.orderType,
this.orderPrice,
this.maker ? 1 : 0,
this.fee,
this.feeCurrency
]
}
// …

Calling serialize() on any model will generate a ws2-format data packet, whilst calling unserialize() on any packet will generate the corresponding model.

We recommend disabling transforms in high-throughput use cases if the instantiation becomes a performance issue. When using managed data (see below), the data is stored in raw array format internally and only transformed when passed to listeners.

Promisified Order Model

The Order model deserves special mention, as it provides methods for execution and can keep itself updated if provided a WSv2 instance:

const o = new Order({
cid: Date.now(),
symbol: 'tETHUSD',
amount: 2,
price: 750,
type: Order.type.EXCHANGE_LIMIT
}, ws2)
o.registerListeners() // hooks into ws2o.on('update', () => {
const fillAmount = o.getLastFillAmount()
// the order object has been updated ('status', 'amount', etc)
})
o.on('close', () => {
o.removeListeners()
// executed or cancelled, consult ‘status’
})
o.submit().then(() => {
// order submission confirmed
})

Order instances provide submit(), cancel(), and recreate() (with current parameters), all three of which return promises that resolve on confirmation.

Note that the WSv2 client does not automatically update Order instances. for that you need to call registerListeners() on an existing order model.

Listener Methods

Many listener methods have been added, and match the documentation where possible. Among these are:

  • onOrderSnapshot({ symbol, gid, cbGID }, cb)
  • onOrderBook({ symbol, prec, len, cbGID }, cb)
  • onTrade({ pair, cbGID }, cb)
  • onTicker({ symbol, cbGID }, cb)
  • onServerRestart(cb)
  • and more!

Listeners can filter by channel-specific keys, like prec and len for orderbooks and gid for orders.

Listeners themselves can be grouped together by cbGID, enabling them all to be removed at once via removeListeners(cbGID).

Before a listener can receive data, the WSv2 instance needs to subscribe to the relevant channels via one of:

  • subscribeTicker(symbol)
  • subscribeTrades(symbol)
  • subscribeOrderBook(symbol, prec = ‘P0’, len = ‘25’)
  • subscribeCandles(key)

Subscriptions per-channel are automatically counted to prevent duplicate subscribe() calls, and channels are unsubscribed from once a matching number of unsubscribe() calls have been made. For manual channel subscriptions, managedSubscribe() and managedUnsubscribe() are available.

For direct un-counted subscriptions, use subscribe() and unsubscribe().

Data Management: Candles & Order Books

For cases where you need to sync an order book or candle dataset over time, manageCandles and manageOrderBooks are available as flags in the WSv2 constructor and enable local persistent candle & OB datasets.

This data is then passed to the relevant listeners instead of the individual update packets, and respects the value of transform passed to WSv2.

const ws = new WSv2({
manageOrderBooks: true,
manageCandles: true,
transform: true
// …
})
ws.onOrderBook({ symbol: 'tBTCUSD' }, (ob) => {
const mid = ob.midPrice()
// ob is a full OrderBook instance
})
ws.onCandle({ key: 'trade:30m:tBTCUSD' }, (candles) => {
// candles is a sorted array of Candle instances
// see candles[0] for the latest (updated) candle
})
ws.on(‘open’, () => {
ws.subscribeOrderBook('tBTCUSD')
ws.subscribeCandles('trade:30m:tBTCUSD')
})
ws.open()

Other Changes

The RESTv2 client has been brought up to date to match our documentation, and has had its transform system modified to return model instances like WSv2.

Some methods from RESTv1 which provide functionality that is unavailable on v2 have been passed-through to RESTv2 for now. In the future, the internal implementation of these methods can be expected to change, but the method signature will remain the same. Examples are withdraw() and deposit().

Alongside this, the RESTv1 and WSv1 clients have been mildly refactored without breaking changes. They are deprecated and will be removed from future releases.

We’ve also added new examples and updated the repo API docs!

Moving Forwards

During the beta period, we will be finalizing the API and tweaking the clients based on your feedback before the final 2.0.0 release.

In the future, we will be adding more utility methods and functionality to ease the development of integrations, and enable more powerful trading systems.

For now, upgrade your node client to v2.0.0-beta and let us know what you think!

We’ve recently open-sourced a number of the development libraries most essential to Bitfinex. If you are interested in learning more, visit our Github.

Stay up to date with Bitfinex on Twitter, Facebook & LinkedIn.

Join us on our mission to create the most innovative & industry-leading cryptocurrency exchange.

--

--