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 🙏

© 2026 – Pkg Stats / Ryan Hefner

bitfinex-node-api

v4.3.1

Published

Bitfinex Node.js API

Downloads

67

Readme

Bitfinex Node.js API CI Status npm version Coverage Status Known Vulnerabilities code style: prettier Contributor Covenant semantic-release Conventional Commits NPM license node version npm downloads GitHub top language

Node.js client for the Bitfinex v1 API — public and authenticated REST plus the v1 WebSocket endpoint — and the v2 public REST + v2 authenticated REST + v2 WebSocket endpoints.

Installation

npm install bitfinex-node-api

Usage

PublicClient

import { PublicClient } from "bitfinex-node-api";

const client = new PublicClient();
const ticker = await client.getTicker({ symbol: "BTCUSD" });
const stats = await client.getStats({ symbol: "BTCUSD" });
const book = await client.getFundingBook({
  currency: "USD",
  limit_bids: 10,
  limit_asks: 5,
});
const book = await client.getOrderBook({
  symbol: "BTCUSD",
  limit_bids: 20,
  limit_asks: 10,
  group: 1,
});
const trades = await client.getTrades({
  symbol: "BTCUSD",
  timestamp: 1444266681,
  limit_trades: 10,
});
const lends = await client.getLends({
  currency: "USD",
  timestamp: 1444266681,
  limit_lends: 10,
});
const symbols = await client.getSymbols();
const details = await client.getSymbolDetails();

PublicClientV2

Client for the Bitfinex v2 public REST endpoints (https://api-pub.bitfinex.com/v2/). Positional arrays are decoded into typed objects with named fields. Trading and funding pairs share the same endpoints; the decoded payload is discriminated by a type field. Trading symbols start with t (e.g. tBTCUSD); funding currencies start with f (e.g. fUSD).

import { PublicClientV2 } from "bitfinex-node-api";

const client = new PublicClientV2();
const { status } = await client.getPlatformStatus(); // 0 = maintenance, 1 = operative
const ticker = await client.getTicker({ symbol: "tBTCUSD" });
// { type: "trading_ticker", symbol, bid, bid_size, ask, ask_size,
//   daily_change, daily_change_relative, last_price, volume, high, low }
const funding = await client.getTicker({ symbol: "fUSD" });
// { type: "funding_ticker", symbol, frr, bid, bid_period, bid_size,
//   ask, ask_period, ask_size, daily_change, daily_change_relative,
//   last_price, volume, high, low, frr_amount_available }
const tickers = await client.getTickers({ symbols: ["tBTCUSD", "fUSD"] });
const all = await client.getTickers({ symbols: "ALL" });
const history = await client.getTickersHistory({
  symbols: ["tBTCUSD"],
  limit: 100,
});
const trades = await client.getTrades({
  symbol: "tBTCUSD",
  limit: 100,
  sort: -1,
});
// [{ type: "trading_trade", id, mts, amount, price }, ...]
// or for funding: [{ type: "funding_trade", id, mts, amount, rate, period }, ...]
const book = await client.getBook({
  symbol: "tBTCUSD",
  precision: "P0",
  len: 25,
});
// Aggregated trading: { type: "book", price, count, amount }
// Raw trading (R0):   { type: "raw_book", order_id, price, amount }
// Aggregated funding: { type: "funding_book", rate, period, count, amount }
// Raw funding (R0):   { type: "raw_funding_book", offer_id, period, rate, amount }
const last = await client.getStats({
  key: "pos.size",
  size: "1m",
  symbol: "tBTCUSD",
  side: "long",
  section: "last",
});
const hist = await client.getStats({
  key: "funding.size",
  size: "1m",
  symbol: "fUSD",
  section: "hist",
  limit: 100,
});
const last = await client.getCandles({
  timeframe: "1D",
  symbol: "tBTCUSD",
  section: "last",
});
const hist = await client.getCandles({
  timeframe: "1m",
  symbol: "fUSD",
  section: "hist",
  aggr: 30,
  period_start: "2",
  period_end: "30",
  limit: 100,
});
const configs = await client.getConfigs({
  configs: ["pub:list:currency", "pub:list:pair:exchange"],
});
const status = await client.getDerivativesStatus({ keys: ["tBTCF0:USTF0"] });
const history = await client.getDerivativesStatusHistory({
  key: "tBTCF0:USTF0",
  limit: 100,
});
const liquidations = await client.getLiquidations({ limit: 50 });
const board = await client.getLeaderboards({
  key: "plu",
  timeframe: "3h",
  symbol: "tBTCUSD",
  limit: 25,
});
const stats = await client.getFundingStats({ symbol: "fUSD", limit: 100 });
const vasps = await client.getVASPs(); // [{ id, name }, ...]
const avg = await client.getMarketAveragePrice({
  symbol: "tBTCUSD",
  amount: "1.0",
});
// { rate_avg, amount }
const fx = await client.getForeignExchangeRate({ ccy1: "BTC", ccy2: "USD" });
// { current_rate }

Error envelope

When a v2 endpoint replies with ["error", CODE, MESSAGE] (the documented maintenance error ["error", 20060, "maintenance"] is one example), PublicClientV2 detects the envelope in both get and post and rejects with a BitfinexError so decoders never run on the malformed body.

import { BitfinexError, PublicClientV2 } from "bitfinex-node-api";

const client = new PublicClientV2();
try {
  await client.getBook({ symbol: "tBTCUSD" });
} catch (error) {
  if (error instanceof BitfinexError) {
    // error.code   — number (e.g. 20060 for maintenance)
    // error.message — `Bitfinex error <code>: <text>`
  }
}

AuthenticatedClient

import { AuthenticatedClient } from "bitfinex-node-api";

const client = new AuthenticatedClient({
  key: "BitfinexAPIKey",
  secret: "BitfinexAPISecret",
});
const info = await client.getAccountInfo();
const fees = await client.getAccountFees();
const summary = await client.getSummary();
const address = await client.getDepositAddress({
  method: "bitcoin",
  wallet_name: "trading",
  renew: 1,
});
const permissions = await client.getKeyPermissions();
const margin = await client.getMarginInformation();
const balances = await client.getWalletBalances();
const result = await client.transfer({
  amount: "1.00954735",
  currency: "BTC",
  walletfrom: "trading",
  walletto: "exchange",
});
const result = await client.withdraw({
  amount: "1.0",
  withdraw_type: "bitcoin",
  address: "1DKwqRhDmVyHJDL4FUYpDmQMYA3Rsxtvur",
  walletselected: "exchange",
});
const order = await client.newOrder({
  amount: "1",
  price: "3",
  type: "limit",
  symbol: "ETCUSD",
  side: "buy",
  is_postonly: true,
});
const result = await client.newOrders({
  orders: [
    {
      amount: "1",
      price: "3",
      type: "limit",
      symbol: "ETCUSD",
      side: "buy",
      is_postonly: true,
    },
    {
      amount: "2",
      price: "2",
      type: "limit",
      symbol: "ETCUSD",
      side: "buy",
    },
  ],
});
const order = await client.cancelOrder({ order_id: 446915287 });
const { result } = await client.cancelOrders({ order_ids: [1, 2] });
const { result } = await client.cancelAllOrders();
const order = await client.replaceOrder({
  order_id: 1,
  amount: "3",
  price: "101",
  type: "limit",
  symbol: "ETCUSD",
  side: "sell",
  is_postonly: true,
});
const order = await client.getOrder({ order_id: 448411153 });
const orders = await client.getOrders();
const orders = await client.getOrderHistory({ limit: 50 });
const positions = await client.getPositions();
const position = await client.claimPosition({
  position_id: 943715,
  amount: "1.0",
});
const history = await client.getBalanceHistory({
  currency: "USD",
  since: "1444277602.0",
});
const history = await client.getDepositsWithdrawals({
  currency: "BTC",
  since: "1444277602.0",
  limit: 10,
});
const trades = await client.getPastTrades({
  symbol: "BTCEUR",
  limit_trades: 25,
  reverse: 1,
});
const offer = await client.newOffer({
  currency: "USD",
  amount: "50.0",
  rate: "20.0",
  period: 2,
  direction: "lend",
});
const offer = await client.cancelOffer({ offer_id: 13800585 });
const offer = await client.offerStatus({ offer_id: 13800585 });
const credits = await client.activeCredits();
const offers = await client.getOffers();
const offers = await client.offersHistory({ limit: 25 });
const trades = await client.getFundingTrades({
  symbol: "USD",
  limit_trades: 1,
  until: "1444141858.0",
});
const funds = await client.getTakenFunds();
const funds = await client.getUnusedFunds();
const funds = await client.getTotalFunds();
const funding = await client.closeFunding({ swap_id: 11576737 });
const response = await client.closePosition({ position_id: 943715 });

AuthenticatedClientV2

Client for the Bitfinex v2 authenticated REST endpoints. The default base URL is https://api.bitfinex.com/v2/ — distinct from the public https://api-pub.bitfinex.com/v2/ host that PublicClientV2 uses; override via the url option if needed. The class extends PublicClientV2, so all v2 public methods are available on the same instance, but they will hit whichever host the auth client was configured with (so by default the public methods on an AuthenticatedClientV2 instance go to api.bitfinex.com, which serves them with stricter rate limits than api-pub.bitfinex.com). For high-volume public data, prefer a dedicated PublicClientV2 instance. Each request is signed with HMAC-SHA384 over /api/v2/{path}{nonce}{body} and sent with the bfx-apikey, bfx-nonce, bfx-signature headers. Responses use the same BitfinexError envelope handling as PublicClientV2, and write endpoints return a typed INotificationV2<T> envelope.

import { AuthenticatedClientV2 } from "bitfinex-node-api";

const client = new AuthenticatedClientV2({
  key: "BitfinexAPIKey",
  secret: "BitfinexAPISecret",
});

The default nonce generator (createMonotonicNonce()) is anchored to Date.now() * 1000 (microsecond resolution) and bumps +1 whenever a second call lands inside the same millisecond, so concurrent Promise.all and fast sequential usage stay strictly increasing as Bitfinex requires. You can still provide a custom generator via the nonce constructor option or the client.nonce = ... setter.

Wallets

const wallets = await client.getWallets();

Orders

const all = await client.getActiveOrders();
const btc = await client.getActiveOrders({ symbol: "tBTCUSD", id: [1] });
const result = await client.submitOrder({
  type: "EXCHANGE LIMIT",
  symbol: "tBTCUSD",
  amount: "0.01",
  price: "50000",
});
await client.updateOrder({ id: 1, price: "51000" });
await client.cancelOrder({ id: 1 });
await client.cancelOrdersMultiple({ all: 1 });
await client.orderMulti({
  ops: [
    [
      "on",
      { type: "LIMIT", symbol: "tBTCUSD", amount: "0.01", price: "50000" },
    ],
    ["oc", { id: 1 }],
  ],
});
await client.getOrdersHistory({ symbol: "tBTCUSD", limit: 25 });
await client.getOrderTrades({ symbol: "tETHUSD", id: 33963608932 });
await client.getTradesHistory({ limit: 50, sort: -1 });
await client.getOtcOrdersHistory({ symbol: "tBTCUSD" });
await client.getLedgers({ currency: "USD", limit: 100 });

Positions

await client.getMarginInfo({ key: "base" });
await client.getMarginInfo({ key: "tBTCUSD" });
await client.getPositions();
await client.claimPosition({ id: 142031891 });
await client.increasePosition({ symbol: "tBTCUSD", amount: "0.1" });
await client.getIncreasePositionInfo({ symbol: "tBTCUSD" });
await client.derivPositionCollateralSet({
  symbol: "tBTCF0:USTF0",
  collateral: 100,
});
await client.derivPositionCollateralLimits({ symbol: "tBTCF0:USTF0" });

Margin Funding

await client.submitFundingOffer({
  type: "LIMIT",
  symbol: "fUSD",
  amount: "50",
  rate: "0.001",
  period: 2,
});
await client.cancelAllFundingOffers({ currency: "USD" });
await client.getFundingLoans({ symbol: "fUSD" });
await client.getFundingInfo({ key: "fUST" });

Account actions

await client.transfer({
  from: "exchange",
  to: "margin",
  currency: "UST",
  amount: "100",
});
await client.getDepositAddress({ wallet: "exchange", method: "bitcoin" });
await client.withdraw({
  wallet: "exchange",
  method: "ethereum",
  amount: "0.1",
  address: "0xabc...",
});
await client.setAlert({ type: "price", symbol: "tETHUSD", price: "185" });
await client.deleteAlert({ symbol: "tBTCUSD", price: 600 });
await client.getUserSettings({ keys: ["bit"] });
await client.setUserSettings({ settings: [["bit", "finex"]] });

Thalex Derivatives

await client.thalexDeposit({
  provider: "thalex",
  amount: "1000",
  ccy: "USE",
  tfaToken: { method: "u2f" },
});
await client.thalexFreeTransferCount({ provider: "thalex" });

WebSocketClient

The v1 WebSocket endpoint (wss://api.bitfinex.com/ws/1). Raw array frames are parsed into typed objects with named fields. Every channel message carries channel_id and type so consumers can discriminate without parsing positional arrays.

import { WebSocketClient } from "bitfinex-node-api";

const ws = new WebSocketClient({
  key: "BitfinexAPIKey", // optional, only required for `auth`
  secret: "BitfinexAPISecret", // optional, only required for `auth`
});

ws.on("message", (message) => {
  console.log(message);
});

await ws.connect();
  • connect / disconnect
await ws.connect();
await ws.disconnect();
const pong = await ws.ping();
  • subscribeTicker — push every ticker update for a pair. Funding currencies such as USD/fUSD are emitted as funding_ticker messages.
const subscription = await ws.subscribeTicker({ pair: "BTCUSD" });
// Incoming `message` payload:
// {
//   channel_id: 56771,
//   type: "ticker",
//   bid: 76892,
//   bid_size: 5.80585799,
//   ask: 76926,
//   ask_size: 7.03177505,
//   daily_change: 810,
//   daily_change_perc: 0.01064893,
//   last_price: 76874,
//   volume: 1438.81140233,
//   high: 76984,
//   low: 74027,
// }
const subscription = await ws.subscribeTicker({ pair: "USD" });
// Incoming `message` payload:
// {
//   channel_id: 57169,
//   type: "funding_ticker",
//   currency: "USD",
//   frr: 0.00039778,
//   bid: 0.00029,
//   bid_period: 2,
//   bid_size: 21298086.02518276,
//   ask: 0.00008723,
//   ask_period: 2,
//   ask_size: 123300.84010007,
//   daily_change: -0.000015,
//   daily_change_perc: -0.15,
//   last_price: 0.00007587,
//   volume: 1000,
//   high: 0.0004,
//   low: 0.00007,
//   frr_amount_available: 42,
// }
  • subscribeTrades — pushes one initial snapshot of recent trades, then trade_executed (te) and trade_updated (tu) live events. Funding currencies such as USD/fUSD are emitted as funding trade messages.
const subscription = await ws.subscribeTrades({ pair: "BTCUSD" });
// Snapshot:
// { channel_id, type: "trades_snapshot", trades: [{ id, timestamp, price, amount }, ...] }
// Live update:
// { channel_id, type: "trade_executed", seq, timestamp, price, amount }
// { channel_id, type: "trade_updated", seq, id, timestamp, price, amount }
// Funding snapshot:
// { channel_id, type: "funding_trades_snapshot", currency,
//   trades: [{ id, timestamp, amount, rate, period }, ...] }
// Funding live update:
// { channel_id, type: "funding_trade_executed", currency, id, timestamp, amount, rate, period }
// { channel_id, type: "funding_trade_updated", currency, id, timestamp, amount, rate, period }
  • subscribeBook — aggregated order book (precP0P3). Funding currencies such as USD/fUSD are emitted as funding book messages.
const subscription = await ws.subscribeBook({
  pair: "BTCUSD",
  prec: "P0",
  freq: "F0",
  len: 25,
});
// Snapshot:
// { channel_id, type: "book_snapshot", book: [{ price, count, amount }, ...] }
// Update:
// { channel_id, type: "book_update", price, count, amount }
// Funding snapshot:
// { channel_id, type: "funding_book_snapshot", currency,
//   book: [{ rate, period, count, amount }, ...] }
// Funding update:
// { channel_id, type: "funding_book_update", currency, rate, period, count, amount }
  • subscribeRawBook — raw order book at order-id granularity (prec = R0). Funding currencies are emitted as raw funding book messages.
const subscription = await ws.subscribeRawBook({ pair: "BTCUSD", len: 100 });
// Snapshot:
// { channel_id, type: "raw_book_snapshot", book: [{ order_id, price, amount }, ...] }
// Update:
// { channel_id, type: "raw_book_update", order_id, price, amount }
// Funding snapshot:
// { channel_id, type: "raw_funding_book_snapshot", currency,
//   book: [{ offer_id, period, rate, amount }, ...] }
// Funding update:
// { channel_id, type: "raw_funding_book_update", currency, offer_id, period, rate, amount }
  • Heartbeats are emitted on any channel that has not pushed data for a second:
// { channel_id, type: "heartbeat" }
  • unsubscribe
await ws.unsubscribe({ chanId: subscription.chanId });
  • auth — authenticate to receive private channels. v1 accepts only the documented five fields (event, apiKey, authSig, authNonce, authPayload); the v2 extensions filter/dms/calc are not supported.
const response = await ws.auth();

Once authenticated the server pushes private events on channel id 0. This client decodes wallet snapshots and updates:

// { channel_id: 0, type: "wallet_snapshot",
//   wallets: [{ wallet_type, currency, balance, unsettled_interest, balance_available }, ...] }
// { channel_id: 0, type: "wallet_update",
//   wallet_type, currency, balance, unsettled_interest, balance_available }

Every other private message comes through as a generic envelope with the v1 mnemonic carried in type and the raw payload preserved:

// { channel_id: 0, type: "os" | "on" | "ou" | "oc" | ..., payload: [...] }

Refer to the official docs to interpret each payload:

| type | Reference | | ----------------------- | ------------------------------------------------------------------------------- | | os/on/ou/oc | Orders | | ps/pn/pu/pc | Positions | | te/tu | Trades | | fos/fon/fou/foc | Funding offers | | fcs/fcn/fcu/fcc | Funding credits | | fls/fln/flu/flc | Funding loans | | fte/ftu | Funding trades | | bu | Balance info | | miu | Margin info | | fiu | Funding info | | n | Notifications |

  • unauth — drop the authenticated session without closing the socket. Failure comes back as {event: "error", code: 10201, ...} and is surfaced as a rejection.
await ws.unauth();
  • send — send any raw payload to the server.
await ws.send({ event: "ping" });

Aborting requests

Every method that returns a promise accepts an AbortSignal:

const controller = new AbortController();
setTimeout(() => {
  controller.abort();
}, 1000);
const sub = await ws.subscribeTicker({ signal: controller.signal });

WebSocketClientV2

Client for the Bitfinex v2 WebSocket API. The default URL is wss://api-pub.bitfinex.com/ws/2 (public); when key and secret are supplied it defaults to the authenticated host wss://api.bitfinex.com/ws/2. Override either via the ws_url option. Raw positional array frames are parsed into typed objects discriminated by a type field (and channel_id). v2 subscriptions use symbol (e.g. tBTCUSD, fUSD), unlike the v1 client's pair.

import { WebSocketClientV2 } from "bitfinex-node-api";

const ws = new WebSocketClientV2({
  key: "BitfinexAPIKey", // optional, only required for `auth`
  secret: "BitfinexAPISecret", // optional, only required for `auth`
});

ws.on("message", (message) => {
  console.log(message);
});

await ws.connect();
  • connect / disconnect
await ws.connect();
await ws.disconnect();
  • pingdocs. The client tags each ping with an auto-incrementing cid and resolves with the matching pong.
const pong = await ws.ping(); // { event: "pong", ts, cid }
  • conf — change connection settings via bitwise flags. The exported ConfFlags enumerates TIMESTAMP, SEQ_ALL, OB_CHECKSUM, BULK_UPDATES.
import { ConfFlags } from "bitfinex-node-api";

await ws.conf({ flags: ConfFlags.OB_CHECKSUM }); // 131072
// Checksum frames then arrive as { channel_id, type: "checksum", checksum }
  • subscribeTicker — trading symbols emit ticker, funding currencies emit funding_ticker.
const subscription = await ws.subscribeTicker({ symbol: "tBTCUSD" });
// { channel_id, type: "ticker", symbol, bid, bid_size, ask, ask_size,
//   daily_change, daily_change_relative, last_price, volume, high, low }
  • subscribeTrades — one trades_snapshot then trade_executed/trade_updated (te/tu). Funding currencies emit funding_* variants. The v2 trade layout is [ID, MTS, AMOUNT, PRICE].
const subscription = await ws.subscribeTrades({ symbol: "tBTCUSD" });
const book = await ws.subscribeBook({ symbol: "tBTCUSD", prec: "P0", len: 25 });
const raw = await ws.subscribeRawBook({ symbol: "tBTCUSD", len: 25 });
const candles = await ws.subscribeCandles({ key: "trade:1m:tBTCUSD" });
// { channel_id, type: "candles_snapshot" | "candle_update", key, ... }
  • subscribeStatusderiv:SYMBOL emits derivatives_status, liq:global emits liquidation_feed.
const deriv = await ws.subscribeStatus({ key: "deriv:tBTCF0:USTF0" });
const liq = await ws.subscribeStatus({ key: "liq:global" });
  • unsubscribe
await ws.unsubscribe({ chanId: subscription.chanId });
  • auth — authenticate to receive account events on channel id 0. dms: 4 enables the Dead-Man-Switch (cancel all orders on disconnect); filter narrows the delivered events.
const response = await ws.auth({ dms: 4, filter: ["trading", "wallet"] });

Once authenticated, account frames are decoded into typed messages:

// { channel_id: 0, type: "wallet_snapshot", wallets: [...] }
// { channel_id: 0, type: "wallet_update", wallet_type, currency, balance, ... }
// { channel_id: 0, type: "position_snapshot" | "position_new" | "position_update" | "position_close", ... }
// { channel_id: 0, type: "order_snapshot" | "order_new" | "order_update" | "order_cancel", ... }
// { channel_id: 0, type: "balance_update", aum, aum_net }
// { channel_id: 0, type: "funding_offer_snapshot" | "funding_offer_new" | ..., ... }
// { channel_id: 0, type: "funding_credit_snapshot" | ..., ... }
// { channel_id: 0, type: "funding_loan_snapshot" | ..., ... }
// { channel_id: 0, type: "notification", mts, notification_type, status, text, ... }

Account frames whose payload is not decoded (e.g. te/tu account trades, miu margin info, fiu funding info, historical snapshots) come through as a generic envelope with the v2 mnemonic:

// { channel_id: 0, type: "auth_envelope", mnemonic: "miu", payload: [...] }
  • unauth / send
await ws.unauth();
await ws.send({ event: "ping", cid: 1234 });

Every method accepts an AbortSignal, and async iterators are available for all public channels (tickers, trades, books, rawBooks, candles, status):

for await (const update of ws.tickers({ symbol: "tBTCUSD" })) {
  console.log(update);
}

Signature

v1 signature (base64 payload + HMAC-SHA384, headers X-BFX-*):

import { signature } from "bitfinex-node-api";

const headers = signature({
  key: "BitfinexAPIKey",
  secret: "BitfinexAPISecret",
  payload: Buffer.from(JSON.stringify({ request, nonce })).toString("base64"),
});

v2 signature (HMAC-SHA384 over /api/v2/{path}{nonce}{body}, headers bfx-apikey/bfx-nonce/bfx-signature):

import { signatureV2 } from "bitfinex-node-api";

const body = JSON.stringify({});
const nonce = `${Date.now() * 1000}`;
const headers = signatureV2({
  key: "BitfinexAPIKey",
  secret: "BitfinexAPISecret",
  path: "auth/r/wallets",
  nonce,
  body,
});

Test

npm test