Error: Nonce is too small - Bitfinex api

Viewed 3179

I try to call rest API from Bitfinex by using bitfinex library (https://www.npmjs.com/package/bitfinex). The documentation warned this error when running more than 1 process at the same time with the same API keys. However, I believe that I only run a process at once and even I generate new API keys, the error still happens. I'm thinking about overriding the nonce or extending it but I don't know how to do this. I haved tried some suggestions on the Internet, but still nothing worked.

Below is my code for reference:

import Bitfinex = require('bitfinex');
import pollingtoevent = require('polling-to-event');
import { Logger, LoggerFactory } from '../../common';
import { AppDataServices } from '../../data';

export class BitfinexPoller {
  private static readonly LOGGER: Logger = LoggerFactory.getLogger();
  private bitfinex: any = undefined;
  private emitter: any = undefined;
  private public_key: string = '<my-public-key>';
  private secret_key: string = '<my-secret-key>';
  private nonce: any = new Date().getTime();

  constructor(private appServices: AppDataServices) {
    BitfinexPoller.LOGGER.info('Bitfinex poller init');

    this.bitfinex = new Bitfinex(this.public_key, this.secret_key, this.nonce);

    // Lend book service
    this.emitter = pollingtoevent((done: any) => {
      this.bitfinex.lendbook('USD', (err: any, res: any, orderId: any) => {
        done(err, res);
      });
    }, { interval: 30000, eventName: 'bitfinex-lending' });

    this.emitter.on('bitfinex-lending', (data: any) => {
      BitfinexPoller.LOGGER.info(data);
      if (data.bids !== undefined) {
        for (const row of data.bids) {
          appServices.lendbookService.insert(BitfinexPoller.lendingData('BID', row));
        }
      }
      if (data.asks !== undefined) {
        for (const row of data.asks) {
          appServices.lendbookService.insert(BitfinexPoller.lendingData('ASK', row));
        }
      }
    });

    // Order book service
    this.emitter = pollingtoevent((done: any) => {
      this.bitfinex.orderbook('btcusd', (err: any, res: any, orderId: any) => {
        done(err, res);
      });
    }, { interval: 30000, eventName: 'bitfinex-order' });

    this.emitter.on('bitfinex-order', (data: any) => {
      BitfinexPoller.LOGGER.info(data);
      if (data.bids !== undefined) {
        for (const row of data.bids) {
          appServices.lendbookService.insert(BitfinexPoller.orderData('BID', row));
        }
      }
      if (data.asks !== undefined) {
        for (const row of data.asks) {
          appServices.lendbookService.insert(BitfinexPoller.orderData('ASK', row));
        }
      }
    });
  }
}
2 Answers

It's most likely you're firing off two authenticated calls in quick succession. The order that you send requests is not always the same as the order that they're processed, so the second request with the higher nonce is being processed first causing the first request to fail.

You can create and use multiple API keys for different requests or have a pool that you cycle through so you don't use the same api key multiple times in quick succession.

My solution with nodejs has been to defer the calls via promises.

Something like this:

function sleep(millis) {
  return new Promise(resolve => setTimeout(resolve, millis));
}

sleep(500).then(() => {
   //do work
  });
  sleep(600).then(() => {
   //do work
  });

Obviously if you are looking at extremely low latency and high speed this isn't for you.

Related