A wrapper for the Binance REST and WebSocket APIs. Uses both promises and callbacks, and beautifies the binance API responses that normally use lots of one letter property names. For more information on the API and parameters for requests visit https://github.com/binance-exchange/binance-official-api-docs
const api = require('binance');
const binanceRest = new api.BinanceRest({
key: 'api-key', // Get this from your account on binance.com
secret: 'api-secret', // Same for this
timeout: 15000, // Optional, defaults to 15000, is the request time out in milliseconds
recvWindow: 10000, // Optional, defaults to 5000, increase if you're getting timestamp errors
disableBeautification: false,
/*
* Optional, default is false. Binance's API returns objects with lots of one letter keys. By
* default those keys will be replaced with more descriptive, longer ones.
*/
handleDrift: false,
/*
* Optional, default is false. If turned on, the library will attempt to handle any drift of
* your clock on it's own. If a request fails due to drift, it'll attempt a fix by requesting
* binance's server time, calculating the difference with your own clock, and then reattempting
* the request.
*/
baseUrl: 'https://api.binance.com/',
/*
* Optional, default is 'https://api.binance.com/'. Can be useful in case default url stops working.
* In february 2018, Binance had a major outage and when service started to be up again, only
* https://us.binance.com was working.
*/
requestOptions: {}
/*
* Options as supported by the 'request' library
* For a list of available options, see:
* https://github.com/request/request
*/
});
// You can use promises
binanceRest
.allOrders({
symbol: 'BNBBTC' // Object is transformed into a query string, timestamp is automatically added
})
.then(data => {
console.log(data);
})
.catch(err => {
console.error(err);
});
/*
* Or you can provide a callback. Also, instead of passing an object as the query, routes
* that only mandate a symbol, or symbol and timestamp, can be passed a string.
*/
binanceRest.allOrders('BNBBTC', (err, data) => {
if (err) {
console.error(err);
} else {
console.log(data);
}
});
/*
* WebSocket API
*
* Each call to onXXXX initiates a new websocket for the specified route, and calls your callback with
* the payload of each message received. Each call to onXXXX returns the instance of the websocket
* client if you want direct access(https://www.npmjs.com/package/ws).
*/
const binanceWS = new api.BinanceWS(true); // Argument specifies whether the responses should be beautified, defaults to true
binanceWS.onDepthUpdate('BNBBTC', data => {
console.log(data);
});
binanceWS.onAggTrade('BNBBTC', data => {
console.log(data);
});
binanceWS.onKline('BNBBTC', '1m', data => {
console.log(data);
});
/*
* You can use one websocket for multiple streams. There are also helpers for the stream names, but the
* documentation has all of the stream names should you want to specify them explicitly.
*/
const streams = binanceWS.streams;
binanceWS.onCombinedStream(
[
streams.depth('BNBBTC'),
streams.kline('BNBBTC', '5m'),
streams.trade('BNBBTC'),
streams.ticker('BNBBTC')
],
streamEvent => {
switch (streamEvent.stream) {
case streams.depth('BNBBTC'):
console.log(
'Depth event, update order book\n',
streamEvent.data
);
break;
case streams.kline('BNBBTC', '5m'):
console.log(
'Kline event, update 5m candle display\n',
streamEvent.data
);
break;
case streams.trade('BNBBTC'):
console.log(
'Trade event, update trade history\n',
streamEvent.data
);
break;
case streams.ticker('BNBBTC'):
console.log(
'Ticker event, update market stats\n',
streamEvent.data
);
break;
}
}
);
/*
* onUserData requires an instance of BinanceRest in order to make the necessary startUserDataStream and
* keepAliveUserDataStream calls. The webSocket instance is returned by promise rather than directly
* due to needing to request a listenKey from the server first.
*/
binanceWS
.onUserData(
binanceRest,
data => {
console.log(data);
},
60000
) // Optional, how often the keep alive should be sent in milliseconds
.then(ws => {
// websocket instance available here
});
Example responses are only included for routes where the response is beautified, and therefore different than the official docs. Click on any function call to see the related route information in the official documentation.
For testing connectivity.
Retrieves the current server time.
Retrieves the current exchange trading rules and symbol information. Includes rate limits for request and orders, as well as restrictions placed on various values when ordering.
Retrieves the order book for a given symbol.
Retrieves the most recent trades for a given symbol(up to 500).
Retrieves historical trades by tradeId. If no tradeId is specified the most recent trades are returned.
Get compressed, aggregate trades. Trades that fill at the same time, from the same order, with the same price will have the quantity aggregated.
Beautified Response
[
{
aggTradeId: 7891757,
price: '0.04840900',
quantity: '0.02800000',
firstTradeId: 8516629,
lastTradeId: 8516629,
timestamp: 1513801086350,
maker: false,
bestPriceMatch: true
},
{
aggTradeId: 7891758,
price: '0.04841100',
quantity: '0.10600000',
firstTradeId: 8516630,
lastTradeId: 8516630,
timestamp: 1513801086350,
maker: false,
bestPriceMatch: true
},
...
]
Retrieve kline/candlestick bars for a symbol. Klines are uniquely identified by their open time.
Beautified Response
[
{
openTime: 1513802580000,
open: '0.04837200',
high: '0.04859200',
low: '0.04837000',
close: '0.04837100',
volume: '181.69100000',
closeTime: 1513802639999,
quoteAssetVolume: '8.79608770',
trades: 249,
takerBaseAssetVolume: '75.74200000',
takerQuoteAssetVolume: '3.67104146',
ignored: '0'
},
{
openTime: 1513802640000,
open: '0.04837100',
high: '0.04850100',
low: '0.04837000',
close: '0.04837200',
volume: '93.56300000',
closeTime: 1513802699999,
quoteAssetVolume: '4.53177905',
trades: 149,
takerBaseAssetVolume: '20.14700000',
takerQuoteAssetVolume: '0.97561723',
ignored: '0'
},
...
]
Retrieve 24 hour price change statistics.
Retrieve latest price for a symbol or symbols.
Retrieve best price/qty on the order book for a symbol or symbols.
Places a new order.
Places a test order.
Check an order's status.
Cancel an open order.
Get all open orders for a symbol, or all symbols. Careful when accessing this with no symbol as the number of requests counted against the rate limiter is equal to the number of symbols currently trading on the exchange.
Retrieve all orders on an account, whether active, cancelled, or filled.
Places a new OCO(One-Cancels-the-Other) order.
Cancels an OCO order which includes both STOP_LOSS_LIMIT and LIMIT_MAKER type order on the basis of orderListId. Canceling an individual leg will cancel the entire OCO.
Retrieves a specific OCO order based on provided optional parameters.
Retrieves all OCO orders based on provided optional parameters.
Retrieves Open OCO orders.
Retrieve current account information including commision rates, trading permissions, and free/locked balances.
Retrieve all trades made by an account.
Make a withdrawal.
Retrieve withdrawal history for an account for a specific asset, or all assets. Includes status.
Retrieve deposit history for an account for a specific asset, or all assets. Includes status.
Generate and retrieve a deposit address for a given asset.
Retrieve account status.
For use in conjunction with the user data websocket. Returns a listen key that must be specified. onUserData()
will handle this for you when you pass it an instance of BinanceRest
.
The keep alive request needed to keep a user data websocket open. Will be automatically sent at a specified interval if using
onUserData()
.
Closes the user data stream.
Returns the latest price for all symbols. This route appears on the old API document, but does not appear in the most recent set of docs. You should probably use tickerPrice()
instead as it utilizes a route with a newer version.
Returns the best price/qty on the order book for all symbols. This route appears on an old API document, but does not appear in the most recent set of docs. You should probably use bookTicker()
instead as it utilizes a route with a newer version.
Order book price and quantity depth updates used to locally manage an order book, pushed every second. Function call returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: <symbol>@depth
Response
{
eventType: 'depthUpdate',
eventTime: 1513807798461,
symbol: 'BNBBTC',
firstUpdateId: 17962354,
lastUpdateId: 17962357, // syncs with updateId on depth route
bidDepthDelta: [
{
price: '0.00031239',
quantity: '0.00000000', //quantity of 0 means remove it
ignored: []
},
...
],
askDepthDelta: [
{
price: '0.00031388',
quantity: '0.00000000',
ignored: []
},
...
]
}
Top <levels> bids and asks, pushed every second. Valid <levels> are 5, 10, or 20. Function call returns the websocket, an instance of https://www.npmjs.com/package/ws. See official docs for response.
Stream Name: <symbol>@depth<levels>
Pushes updates to the current klines/candlesticks every second. Valid intervals are described here. Returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: <symbol>@kline_<interval>
Beautified Response
{
eventType: 'kline',
eventTime: 1513808234049,
symbol: 'ETHBTC',
kline:
{
startTime: 1513808220000,
endTime: 1513808279999,
symbol: 'ETHBTC',
interval: '1m',
firstTradeId: 8542266,
lastTradeId: 8542357,
open: '0.04854000',
close: '0.04865100',
high: '0.04865200',
low: '0.04854000',
volume: '53.30600000',
trades: 92,
final: false,
quoteVolume: '2.59145375',
volumeActive: '41.01100000',
quoteVolumeActive: '1.99422739',
ignored: '0'
}
}
Pushes trade information that is aggregated for a single taker order. Returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: <symbol>@aggTrade
Beautified Response
{
eventType: 'aggTrade',
eventTime: 1513808427335,
symbol: 'ETHBTC',
tradeId: 7915993,
price: '0.04858100',
quantity: '0.06100000',
firstTradeId: 8543066,
lastTradeId: 8543066,
time: 1513808427329,
maker: false,
ignored: true
}
Pushes raw trade information, with each trade having a unique buyer and seller. Returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: <symbol>@trade
Beautified Response
{
eventType: 'trade',
eventTime: 1515266751986,
symbol: 'BNBBTC',
tradeId: 4684001,
price: '0.00121490',
quantity: '25.00000000',
buyerOrderId: 14860825,
sellerOrderId: 14860815,
time: 1515266751974,
maker: false,
ignored: true
}
24 hour ticker stats for a single symbol pushed every second. Returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: <symbol>@ticker
Beautified Response
{
eventType: '24hrTicker',
eventTime: 1515266555314,
symbol: 'BNBBTC',
priceChange: '0.00036700',
priceChangePercent: '44.111',
weightedAveragePrice: '0.00102603',
previousClose: '0.00083200',
currentClose: '0.00119900',
closeQuantity: '256.06000000',
bestBid: '0.00119900',
bestBidQuantity: '479.82000000',
bestAskPrice: '0.00120000',
bestAskQuantity: '93.56000000',
open: '0.00083200',
high: '0.00134950',
low: '0.00080000',
baseAssetVolume: '18940498.53000000',
quoteAssetVolume: '19433.56011157',
openTime: 1515180155234,
closeTime: 1515266555234,
firstTradeId: 4399671,
lastTradeId: 4682727,
trades: 283057
}
24hr Ticker statistics for all symbols in an array, pushed every second. Returns the websocket, an instance of https://www.npmjs.com/package/ws
Stream Name: !ticker@arr
Beautified Response
{
eventType: '24hrTicker',
eventTime: 1515266555314,
symbol: 'BNBBTC',
priceChange: '0.00036700',
priceChangePercent: '44.111',
weightedAveragePrice: '0.00102603',
previousClose: '0.00083200',
currentClose: '0.00119900',
closeQuantity: '256.06000000',
bestBid: '0.00119900',
bestBidQuantity: '479.82000000',
bestAskPrice: '0.00120000',
bestAskQuantity: '93.56000000',
open: '0.00083200',
high: '0.00134950',
low: '0.00080000',
baseAssetVolume: '18940498.53000000',
quoteAssetVolume: '19433.56011157',
openTime: 1515180155234,
closeTime: 1515266555234,
firstTradeId: 4399671,
lastTradeId: 4682727,
trades: 283057
}
streams should be an array of stream names. You may specify these explicitly, or you can use some helper functions to generate them:
const binanceWS = new api.BinanceWS();
const streams = binanceWS.streams;
binanceWS.onCombinedStream(
[
streams.depth('BNBBTC'),
streams.depthLevel('BNBBTC', 5),
streams.kline('BNBBTC', '5m'),
streams.aggTrade('BNBBTC'),
streams.trade('BNBBTC'),
streams.ticker('BNBBTC'),
streams.allTickers()
],
streamEvent => {
switch (streamEvent.stream) {
case streams.depth('BNBBTC'):
console.log('Depth Event', streamEvent.data);
break;
case streams.depthLevel('BNBBTC', 5):
console.log('Depth Level Event', streamEvent.data);
break;
case streams.kline('BNBBTC', '5m'):
console.log('Kline Event', streamEvent.data);
break;
case streams.aggTrade('BNBBTC'):
console.log('AggTrade Event', streamEvent.data);
break;
case streams.trade('BNBBTC'):
console.log('Trade Event', streamEvent.data);
break;
case streams.ticker('BNBBTC'):
console.log('BNBBTC Ticker Event', streamEvent.data);
break;
case streams.allTickers():
console.log('Ticker Event', streamEvent.data);
break;
}
}
);
Will return the websocket via promise, interval
defaults to 60000(ms), and is the amount of time between calls made to keep the user stream alive. binanceRest
should be an instance of BinanceRest
that will be used to get the listenKey
and keep the stream alive.
Responses
{
eventType: 'executionReport',
eventTime: 1513808673916,
symbol: 'IOTABTC',
newClientOrderId: '81gmMRozYdU73D27Ho1W1K',
side: 'SELL',
orderType: 'LIMIT',
cancelType: 'GTC',
quantity: '10.00000000',
price: '0.00030120',
stopPrice: '0.00000000',
icebergQuantity: '0.00000000',
g: -1, // to be ignored
originalClientOrderId: 'null',
executionType: 'TRADE',
orderStatus: 'FILLED',
rejectReason: 'NONE',
orderId: 9409314,
lastTradeQuantity: '10.00000000',
accumulatedQuantity: '10.00000000',
lastTradePrice: '0.00030120',
commission: '0.00000301',
commissionAsset: 'BTC',
tradeTime: 1513808673912,
tradeId: 3023119,
I: 21799081, // ignore
w: false, // ignore
maker: true
}
{
eventType: 'outboundAccountInfo',
eventTime: 1513808673916,
makerCommission: 10,
takerCommission: 10,
buyerCommission: 0,
sellerCommission: 0,
canTrade: true,
canWithdraw: true,
canDeposit: true,
lastUpdateTime: 1499405658848,
balances: [
{
asset: 'BTC',
availableBalance: '0.00301025',
onOrderBalance: '0.00000000'
},
...
]
}
{
eventType: 'outboundAccountPosition',
eventTime: 1513808673916,
lastUpdateTime: 1499405658848,
balances: [
{
asset: 'BTC',
availableBalance: '0.00301025',
onOrderBalance: '0.00000000'
},
{
asset: 'BNB',
availableBalance: '0.00032331',
onOrderBalance: '0.00000000'
},
...
]
}
Quantities and prices used when creating orders must fall within the guidelines provided by the filters in symbolInfo responses. The code below shows how to turn a quantity and price into acceptable values for creating an order. The results vary depending on the symbol used, since different symbols have different filters.
Symbol information can be obtained from exchangeInfo([callback funcion])
const { ValueProcessor } = require('binance');
ValueProcessor.processFilters(symbolInfo, {
quantity: '30.000000001', // Also accepts 'number' values.
price: '0.00234414211'
});
// {
// quantity: '30.000',
// price: '0.002344'
// }
Most can be resolved by adjusting your recvWindow
a bit larger, but if your clock is constantly
or intermittently going out of sync with the server, the library is capable of calculating the
drift and adjusting the timestamps. You have some options. The first is to add the handleDrift
option to the constructor, setting it to true
. In this case, if your clock is ahead of the
server's, or falls behind and is outside the recvWindow
, and a request fails, the library will
calculate the drift of your clock and reattempt the request. It will also use the drift value to
adjust all subsequent calls. This may add more time to the initial requests that fail, and could
potentially affect highly time sensitive trades. The alternative is to use the
startTimeSync(interval_in_ms)
and endTimeSync
functions. The former will begin an interval,
and each time it's called the drift will be calculated and used on all subsequent requests. The
default interval is 5 minutes, and it should be specified in milliseconds. The latter will clear
the interval. You may also calculate the drift manually by calling calculateDrift()
. The
resulting value will be stored internally and used on all subsequent calls.