Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

binance

Package Overview
Dependencies
Maintainers
1
Versions
171
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

binance - npm Package Compare versions

Comparing version 1.3.7 to 1.3.8

9

CHANGELOG.md
# Changelog
## 1.3.8
- Optimise local imports.
- Cleaning, including indentation.
- Deprecate yarn in favour of npm.
- Fix tests.
- Expose utility method for generating custom order ID.
- Add example on providing custom order ID.
- Update docs.
## 1.3.7

@@ -4,0 +13,0 @@

6

lib/binance.js
module.exports = {
BinanceRest: require('./rest.js'),
BinanceWS: require('./ws.js'),
ValueProcessor: require('./processor.js')
BinanceRest: require('./rest'),
BinanceWS: require('./ws'),
ValueProcessor: require('./processor')
};

@@ -7,493 +7,511 @@ const request = require('request');

const Beautifier = require('./beautifier.js');
const Beautifier = require('./beautifier');
class BinanceRest {
constructor({
key,
secret,
recvWindow = false,
timeout = 15000,
disableBeautification = false,
handleDrift = false,
baseUrl = 'https://api.binance.com/',
requestOptions = {}
}) {
this.key = key;
this.secret = secret;
this.recvWindow = recvWindow;
this.timeout = timeout;
this.disableBeautification = disableBeautification;
this.handleDrift = handleDrift;
this.requestOptions = requestOptions;
constructor({
key,
secret,
recvWindow = false,
timeout = 15000,
disableBeautification = false,
handleDrift = false,
baseUrl = 'https://api.binance.com/',
requestOptions = {}
}) {
this.key = key;
this.secret = secret;
this.recvWindow = recvWindow;
this.timeout = timeout;
this.disableBeautification = disableBeautification;
this.handleDrift = handleDrift;
this.requestOptions = requestOptions;
this._beautifier = new Beautifier();
this._baseUrl = baseUrl;
// had trailing slash if necessary
if ('/' != this._baseUrl.substr(-1)) {
this._baseUrl += '/';
}
this._drift = 0;
this._syncInterval = 0;
this._beautifier = new Beautifier();
this._baseUrl = baseUrl;
// had trailing slash if necessary
if ('/' != this._baseUrl.substr(-1)) {
this._baseUrl += '/';
}
getBaseUrl() {
return this._baseUrl;
}
this._drift = 0;
this._syncInterval = 0;
}
_makeRequest(query, callback, route, security, method, attempt = 0) {
assert(
_.isUndefined(callback) || _.isFunction(callback),
'callback must be a function or undefined'
);
assert(_.isObject(query), 'query must be an object');
getBaseUrl() {
return this._baseUrl;
}
let queryString;
const type = _.last(route.split('/')),
options = Object.assign(
{
url: `${this._baseUrl}${route}`,
timeout: this.timeout
},
this.requestOptions
);
_makeRequest(query, callback, route, security, method, attempt = 0) {
assert(
_.isUndefined(callback) || _.isFunction(callback),
'callback must be a function or undefined'
);
assert(_.isObject(query), 'query must be an object');
if (security === 'SIGNED') {
if (this.recvWindow) {
query.recvWindow = this.recvWindow;
}
queryString = qs.stringify(query);
options.url += '?' + queryString;
if (options.url.substr(options.url.length - 1) !== '?') {
options.url += '&';
}
options.url += `signature=${this._sign(queryString)}`;
} else {
queryString = qs.stringify(query);
if (queryString) {
options.url += '?' + queryString;
}
let queryString;
const type = _.last(route.split('/')),
options = Object.assign(
{
url: `${this._baseUrl}${route}`,
timeout: this.timeout
},
this.requestOptions
);
if (security === 'SIGNED') {
if (this.recvWindow) {
query.recvWindow = this.recvWindow;
}
queryString = qs.stringify(query);
options.url += '?' + queryString;
if (options.url.substr(options.url.length - 1) !== '?') {
options.url += '&';
}
options.url += `signature=${this._sign(queryString)}`;
} else {
queryString = qs.stringify(query);
if (queryString) {
options.url += '?' + queryString;
}
}
if (security === 'API-KEY' || security === 'SIGNED') {
options.headers = { 'X-MBX-APIKEY': this.key };
}
if (method) {
options.method = method;
}
const action = cb => {
request(options, (err, response, body) => {
let payload;
try {
payload = JSON.parse(body);
} catch (e) {
payload = body;
}
if (security === 'API-KEY' || security === 'SIGNED') {
options.headers = { 'X-MBX-APIKEY': this.key };
}
if (method) {
options.method = method;
}
const action = cb => {
request(options, (err, response, body) => {
let payload;
try {
payload = JSON.parse(body);
} catch (e) {
payload = body;
}
if (err) {
cb(err, payload);
} else if (
response.statusCode < 200 ||
response.statusCode > 299
) {
/*
* If we get a response that the timestamp is ahead of the server,
* calculate the drift and then attempt the request again
*/
if (
response.statusCode === 400 &&
payload.code === -1021 &&
this.handleDrift &&
attempt === 0
) {
this.calculateDrift().then(() => {
query.timestamp = this._getTime() + this._drift;
return this._makeRequest(
query,
cb,
route,
security,
method,
++attempt
);
});
} else {
cb(
new Error(`Response code ${response.statusCode}`),
payload
);
}
} else {
if (_.isArray(payload)) {
payload = _.map(payload, item => {
return this._doBeautifications(item, type);
});
} else {
payload = this._doBeautifications(payload);
}
cb(err, payload);
}
if (err) {
cb(err, payload);
} else if (
response.statusCode < 200 ||
response.statusCode > 299
) {
/*
* If we get a response that the timestamp is ahead of the server,
* calculate the drift and then attempt the request again
*/
if (
response.statusCode === 400 &&
payload.code === -1021 &&
this.handleDrift &&
attempt === 0
) {
this.calculateDrift().then(() => {
query.timestamp = this._getTime() + this._drift;
return this._makeRequest(
query,
cb,
route,
security,
method,
++attempt
);
});
};
if (callback) {
action(callback);
} else {
cb(
new Error(`Response code ${response.statusCode}`),
payload
);
}
} else {
return new Promise((resolve, reject) =>
action((err, payload) => {
if (err) {
if (payload === undefined) {
reject(err);
} else {
reject(payload);
}
} else {
resolve(payload);
}
})
);
if (_.isArray(payload)) {
payload = _.map(payload, item => {
return this._doBeautifications(item, type);
});
} else {
payload = this._doBeautifications(payload);
}
cb(err, payload);
}
});
};
if (callback) {
action(callback);
} else {
return new Promise((resolve, reject) =>
action((err, payload) => {
if (err) {
if (payload === undefined) {
reject(err);
} else {
reject(payload);
}
} else {
resolve(payload);
}
})
);
}
}
_doBeautifications(response, route) {
if (this.disableBeautification) {
return response;
}
return this._beautifier.beautify(response, route);
_doBeautifications(response, route) {
if (this.disableBeautification) {
return response;
}
return this._beautifier.beautify(response, route);
}
_sign(queryString) {
return crypto
.createHmac('sha256', this.secret)
.update(queryString)
.digest('hex');
}
_sign(queryString) {
return crypto
.createHmac('sha256', this.secret)
.update(queryString)
.digest('hex');
}
_setTimestamp(query) {
if (!query.timestamp) {
query.timestamp = this._getTime() + this._drift;
}
_setTimestamp(query) {
if (!query.timestamp) {
query.timestamp = this._getTime() + this._drift;
}
}
_getTime() {
return new Date().getTime();
}
_getTime() {
return new Date().getTime();
}
calculateDrift() {
const systemTime = this._getTime();
return this.time().then(response => {
// Calculate the approximate trip time from here to binance
const transitTime = parseInt((this._getTime() - systemTime) / 2);
this._drift = response.serverTime - (systemTime + transitTime);
});
generateNewOrderId() {
const chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
let randomstring = 'x-U5D79M5B';
for (let i = 0; i < 20; i++) {
const rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum, rnum + 1);
}
return randomstring;
}
startTimeSync(interval = 300000, onRecalculateDriftCb) {
return new Promise((resolve, reject) => {
// If there's already an interval running, clear it and reset values
if (this._syncInterval !== 0) {
this.endTimeSync();
return resolve();
}
calculateDrift() {
const systemTime = this._getTime();
return this.time().then(response => {
// Calculate the approximate trip time from here to binance
const transitTime = parseInt((this._getTime() - systemTime) / 2);
this._drift = response.serverTime - (systemTime + transitTime);
});
}
// Calculate initial drift value and setup interval to periodically update it
this.calculateDrift()
.then(resolve)
.catch(reject);
startTimeSync(interval = 300000, onRecalculateDriftCb) {
return new Promise((resolve, reject) => {
// If there's already an interval running, clear it and reset values
if (this._syncInterval !== 0) {
this.endTimeSync();
return resolve();
}
this._syncInterval = setInterval(() => {
const promise = this.calculateDrift();
// Calculate initial drift value and setup interval to periodically update it
this.calculateDrift()
.then(resolve)
.catch(reject);
if (_.isFunction(onRecalculateDriftCb)) {
onRecalculateDriftCb(promise);
}
}, interval);
});
}
this._syncInterval = setInterval(() => {
const promise = this.calculateDrift();
endTimeSync() {
clearInterval(this._syncInterval);
this._drift = 0;
this._syncInterval = 0;
}
if (_.isFunction(onRecalculateDriftCb)) {
onRecalculateDriftCb(promise);
}
}, interval);
});
}
// Public APIs
ping(callback) {
return this._makeRequest({}, callback, 'api/v1/ping');
}
endTimeSync() {
clearInterval(this._syncInterval);
this._drift = 0;
this._syncInterval = 0;
}
time(callback) {
return this._makeRequest({}, callback, 'api/v1/time');
}
// Public APIs
ping(callback) {
return this._makeRequest({}, callback, 'api/v1/ping');
}
depth(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
time(callback) {
return this._makeRequest({}, callback, 'api/v1/time');
}
return this._makeRequest(query, callback, 'api/v1/depth');
depth(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
trades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
return this._makeRequest(query, callback, 'api/v1/depth');
}
return this._makeRequest(query, callback, 'api/v1/trades');
trades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
historicalTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
return this._makeRequest(query, callback, 'api/v1/trades');
}
return this._makeRequest(
query,
callback,
'api/v1/historicalTrades',
'API-KEY'
);
historicalTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
aggTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
return this._makeRequest(
query,
callback,
'api/v1/historicalTrades',
'API-KEY'
);
}
return this._makeRequest(query, callback, 'api/v1/aggTrades');
aggTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
exchangeInfo(callback) {
return this._makeRequest({}, callback, 'api/v1/exchangeInfo');
}
return this._makeRequest(query, callback, 'api/v1/aggTrades');
}
klines(query = {}, callback) {
return this._makeRequest(query, callback, 'api/v1/klines');
}
exchangeInfo(callback) {
return this._makeRequest({}, callback, 'api/v1/exchangeInfo');
}
ticker24hr(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
klines(query = {}, callback) {
return this._makeRequest(query, callback, 'api/v1/klines');
}
return this._makeRequest(query, callback, 'api/v1/ticker/24hr');
ticker24hr(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
tickerPrice(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
return this._makeRequest(query, callback, 'api/v1/ticker/24hr');
}
return this._makeRequest(query, callback, 'api/v3/ticker/price');
tickerPrice(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
bookTicker(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
return this._makeRequest(query, callback, 'api/v3/ticker/price');
}
return this._makeRequest(query, callback, 'api/v3/ticker/bookTicker');
bookTicker(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
allBookTickers(callback) {
return this._makeRequest({}, callback, 'api/v1/ticker/allBookTickers');
}
return this._makeRequest(query, callback, 'api/v3/ticker/bookTicker');
}
allPrices(callback) {
return this._makeRequest({}, callback, 'api/v1/ticker/allPrices');
}
allBookTickers(callback) {
return this._makeRequest({}, callback, 'api/v1/ticker/allBookTickers');
}
// Private APIs
newOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/order',
'SIGNED',
'POST'
);
}
allPrices(callback) {
return this._makeRequest({}, callback, 'api/v1/ticker/allPrices');
}
testOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/order/test',
'SIGNED',
'POST'
);
// Private APIs
newOrder(query = {}, callback) {
this._setTimestamp(query);
if (!query.newClientOrderId) {
query.newClientOrderId = this.generateNewOrderId();
}
return this._makeRequest(
query,
callback,
'api/v3/order',
'SIGNED',
'POST'
);
}
queryOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/order', 'SIGNED');
testOrder(query = {}, callback) {
this._setTimestamp(query);
if (!query.newClientOrderId) {
query.newClientOrderId = this.generateNewOrderId();
}
console.log('query: ', query);
cancelOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/order',
'SIGNED',
'DELETE'
);
}
return this._makeRequest(
query,
callback,
'api/v3/order/test',
'SIGNED',
'POST'
);
}
openOrders(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/openOrders',
'SIGNED'
);
}
queryOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/order', 'SIGNED');
}
allOrders(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/allOrders', 'SIGNED');
}
cancelOrder(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/order',
'SIGNED',
'DELETE'
);
}
account(query = {}, callback) {
if (_.isFunction(query)) {
callback = query;
query = {};
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/account', 'SIGNED');
openOrders(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'api/v3/openOrders',
'SIGNED'
);
}
myTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/myTrades', 'SIGNED');
allOrders(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/allOrders', 'SIGNED');
}
withdraw(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/withdraw.html',
'SIGNED',
'POST'
);
account(query = {}, callback) {
if (_.isFunction(query)) {
callback = query;
query = {};
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/account', 'SIGNED');
}
depositHistory(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/depositHistory.html',
'SIGNED'
);
myTrades(query = {}, callback) {
if (_.isString(query)) {
query = { symbol: query };
}
this._setTimestamp(query);
return this._makeRequest(query, callback, 'api/v3/myTrades', 'SIGNED');
}
withdrawHistory(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/withdrawHistory.html',
'SIGNED'
);
}
withdraw(query = {}, callback) {
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/withdraw.html',
'SIGNED',
'POST'
);
}
depositAddress(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/depositAddress.html',
'SIGNED'
);
depositHistory(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/depositHistory.html',
'SIGNED'
);
}
depositAddressWithNetwork(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'sapi/v1/capital/deposit/hisrec',
'SIGNED'
);
withdrawHistory(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/withdrawHistory.html',
'SIGNED'
);
}
allCoinsInformation(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'sapi/v1/capital/config/getall',
'SIGNED'
);
depositAddress(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/depositAddress.html',
'SIGNED'
);
}
accountStatus(callback) {
const query = {};
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/accountStatus.html',
'SIGNED'
);
depositAddressWithNetwork(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'sapi/v1/capital/deposit/hisrec',
'SIGNED'
);
}
startUserDataStream(callback) {
return this._makeRequest(
{},
callback,
'api/v1/userDataStream',
'API-KEY',
'POST'
);
allCoinsInformation(query = {}, callback) {
if (_.isString(query)) {
query = { asset: query };
}
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'sapi/v1/capital/config/getall',
'SIGNED'
);
}
keepAliveUserDataStream(query = {}, callback) {
return this._makeRequest(
query,
callback,
'api/v1/userDataStream',
'API-KEY',
'PUT'
);
}
accountStatus(callback) {
const query = {};
this._setTimestamp(query);
return this._makeRequest(
query,
callback,
'wapi/v3/accountStatus.html',
'SIGNED'
);
}
closeUserDataStream(query = {}, callback) {
return this._makeRequest(
query,
callback,
'api/v1/userDataStream',
'API-KEY',
'DELETE'
);
}
startUserDataStream(callback) {
return this._makeRequest(
{},
callback,
'api/v1/userDataStream',
'API-KEY',
'POST'
);
}
keepAliveUserDataStream(query = {}, callback) {
return this._makeRequest(
query,
callback,
'api/v1/userDataStream',
'API-KEY',
'PUT'
);
}
closeUserDataStream(query = {}, callback) {
return this._makeRequest(
query,
callback,
'api/v1/userDataStream',
'API-KEY',
'DELETE'
);
}
}
module.exports = BinanceRest;
const WebSocket = require('ws');
const _ = require('underscore');
const Beautifier = require('./beautifier.js');
const Beautifier = require('./beautifier');
const BinanceErrors = Object.freeze({
INVALID_LISTEN_KEY: -1125
INVALID_LISTEN_KEY: -1125
});
class BinanceWS {
constructor(beautify = true) {
this._baseUrl = 'wss://stream.binance.com:9443/ws/';
this._combinedBaseUrl = 'wss://stream.binance.com:9443/stream?streams=';
this._sockets = {};
this._beautifier = new Beautifier();
this._beautify = beautify;
constructor(beautify = true) {
this._baseUrl = 'wss://stream.binance.com:9443/ws/';
this._combinedBaseUrl = 'wss://stream.binance.com:9443/stream?streams=';
this._sockets = {};
this._beautifier = new Beautifier();
this._beautify = beautify;
this.streams = {
depth: symbol => `${symbol.toLowerCase()}@depth`,
depthLevel: (symbol, level) =>
`${symbol.toLowerCase()}@depth${level}`,
kline: (symbol, interval) =>
`${symbol.toLowerCase()}@kline_${interval}`,
aggTrade: symbol => `${symbol.toLowerCase()}@aggTrade`,
trade: symbol => `${symbol.toLowerCase()}@trade`,
ticker: symbol => `${symbol.toLowerCase()}@ticker`,
allTickers: () => '!ticker@arr'
};
this.streams = {
depth: symbol => `${symbol.toLowerCase()}@depth`,
depthLevel: (symbol, level) =>
`${symbol.toLowerCase()}@depth${level}`,
kline: (symbol, interval) =>
`${symbol.toLowerCase()}@kline_${interval}`,
aggTrade: symbol => `${symbol.toLowerCase()}@aggTrade`,
trade: symbol => `${symbol.toLowerCase()}@trade`,
ticker: symbol => `${symbol.toLowerCase()}@ticker`,
allTickers: () => '!ticker@arr'
};
// Reference to the setInterval timer for sending keep alive requests in onUserData
this._userDataRefresh = {
intervaId: false,
failCount: 0
};
// Reference to the setInterval timer for sending keep alive requests in onUserData
this._userDataRefresh = {
intervaId: false,
failCount: 0
};
}
_setupWebSocket(eventHandler, path, isCombined) {
if (this._sockets[path]) {
return this._sockets[path];
}
path = (isCombined ? this._combinedBaseUrl : this._baseUrl) + path;
const ws = new WebSocket(path);
_setupWebSocket(eventHandler, path, isCombined) {
if (this._sockets[path]) {
return this._sockets[path];
ws.on('message', message => {
let event;
try {
event = JSON.parse(message);
} catch (e) {
event = message;
}
if (this._beautify) {
if (event.stream) {
event.data = this._beautifyResponse(event.data);
} else {
event = this._beautifyResponse(event);
}
path = (isCombined ? this._combinedBaseUrl : this._baseUrl) + path;
const ws = new WebSocket(path);
}
ws.on('message', message => {
let event;
try {
event = JSON.parse(message);
} catch (e) {
event = message;
}
if (this._beautify) {
if (event.stream) {
event.data = this._beautifyResponse(event.data);
} else {
event = this._beautifyResponse(event);
}
}
eventHandler(event);
});
eventHandler(event);
});
ws.on('error', () => {
// node.js EventEmitters will throw and then exit if no error listener is registered
});
ws.on('error', () => {
// node.js EventEmitters will throw and then exit if no error listener is registered
});
return ws;
}
return ws;
_beautifyResponse(data) {
if (_.isArray(data)) {
return _.map(data, event => {
if (event.e) {
return this._beautifier.beautify(event, event.e + 'Event');
}
return event;
});
} else if (data.e) {
return this._beautifier.beautify(data, data.e + 'Event');
}
return data;
}
_beautifyResponse(data) {
if (_.isArray(data)) {
return _.map(data, event => {
if (event.e) {
return this._beautifier.beautify(event, event.e + 'Event');
}
return event;
});
} else if (data.e) {
return this._beautifier.beautify(data, data.e + 'Event');
}
return data;
_clearUserDataInterval() {
if (this._userDataRefresh.intervaId) {
clearInterval(this._userDataRefresh.intervaId);
}
_clearUserDataInterval() {
if (this._userDataRefresh.intervaId) {
clearInterval(this._userDataRefresh.intervaId);
}
this._userDataRefresh.intervaId = false;
this._userDataRefresh.failCount = 0;
}
this._userDataRefresh.intervaId = false;
this._userDataRefresh.failCount = 0;
}
_sendUserDataKeepAlive(binanceRest, response) {
return binanceRest.keepAliveUserDataStream(response).catch(e => {
this._userDataRefresh.failCount++;
const msg =
'Failed requesting keepAliveUserDataStream for onUserData listener';
if (e && e.code === BinanceErrors.INVALID_LISTEN_KEY) {
console.error(
new Date(),
msg,
'listen key expired - clearing keepAlive interval',
e
);
this._clearUserDataInterval();
return;
}
console.error(
new Date(),
msg,
'failCount: ',
this._userDataRefresh.failCount,
e
);
});
}
_sendUserDataKeepAlive(binanceRest, response) {
return binanceRest.keepAliveUserDataStream(response).catch(e => {
this._userDataRefresh.failCount++;
const msg =
'Failed requesting keepAliveUserDataStream for onUserData listener';
if (e && e.code === BinanceErrors.INVALID_LISTEN_KEY) {
console.error(
new Date(),
msg,
'listen key expired - clearing keepAlive interval',
e
);
this._clearUserDataInterval();
return;
}
console.error(
new Date(),
msg,
'failCount: ',
this._userDataRefresh.failCount,
e
);
});
}
onDepthUpdate(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.depth(symbol));
}
onDepthUpdate(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.depth(symbol));
}
onDepthLevelUpdate(symbol, level, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.depthLevel(symbol, level)
);
}
onDepthLevelUpdate(symbol, level, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.depthLevel(symbol, level)
);
}
onKline(symbol, interval, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.kline(symbol, interval)
);
}
onKline(symbol, interval, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.kline(symbol, interval)
);
}
onAggTrade(symbol, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.aggTrade(symbol)
);
}
onAggTrade(symbol, eventHandler) {
return this._setupWebSocket(
eventHandler,
this.streams.aggTrade(symbol)
);
}
onTrade(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.trade(symbol));
}
onTrade(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.trade(symbol));
}
onTicker(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.ticker(symbol));
}
onTicker(symbol, eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.ticker(symbol));
}
onAllTickers(eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.allTickers());
}
onAllTickers(eventHandler) {
return this._setupWebSocket(eventHandler, this.streams.allTickers());
}
onUserData(binanceRest, eventHandler, interval = 60000) {
this._clearUserDataInterval();
return binanceRest.startUserDataStream().then(response => {
this._userDataRefresh.intervaId = setInterval(
() => this._sendUserDataKeepAlive(binanceRest, response),
interval
);
this._userDataRefresh.failCount = 0;
onUserData(binanceRest, eventHandler, interval = 60000) {
this._clearUserDataInterval();
return binanceRest.startUserDataStream().then(response => {
this._userDataRefresh.intervaId = setInterval(
() => this._sendUserDataKeepAlive(binanceRest, response),
interval
);
this._userDataRefresh.failCount = 0;
return this._setupWebSocket(eventHandler, response.listenKey);
});
}
return this._setupWebSocket(eventHandler, response.listenKey);
});
}
onCombinedStream(streams, eventHandler) {
return this._setupWebSocket(eventHandler, streams.join('/'), true);
}
onCombinedStream(streams, eventHandler) {
return this._setupWebSocket(eventHandler, streams.join('/'), true);
}
}
module.exports = BinanceWS;
{
"name": "binance",
"version": "1.3.7",
"description": "node.js wrapper for the Binance REST and WebSocket APIs",
"main": "./lib/binance.js",
"files": [
"lib/*"
],
"scripts": {
"test": "mocha",
"cover": "nyc --reporter=html --reporter=text mocha",
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint lib test util && prettier --check lib/**/* test/**/* util/**/*",
"lintfix": "eslint lib test util --fix && prettier --write lib/**/* test/**/* util/**/*",
"precommit": "yarn test && yarn lint"
},
"dependencies": {
"bignumber.js": "^9.0.0",
"request": "^2.88.2",
"underscore": "^1.8.3",
"ws": "^3.3.1"
},
"repository": {
"type": "git",
"url": "https://github.com/tiagosiebler/binance"
},
"bugs": {
"url": "https://github.com/tiagosiebler/binance/issues"
},
"homepage": "https://github.com/tiagosiebler/binance#readme",
"keywords": [
"api",
"bitcoin",
"ethereum",
"cryptocurrency",
"binance",
"btc",
"eth"
],
"author": "Zoey Garvey",
"contributors": [
"Clifford Roche <clifford.roche@gmail.com> (http://www.cliffordroche.ca)",
"Aslam Hadi H <aslamhadi@gmail.com> (https://www.commitcode.com)",
"Andrey Vorobyov <vorandrew@gmail.com>",
"Gavy Aggarwal (http://gavyaggarwal.com/)",
"Tiago Siebler (https://github.com/tiagosiebler)",
"Tony Pettigrew (https://github.com/NeverEnder4)",
"Chris <apexearth@gmail.com> (https://github.com/apexearth)"
],
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/tiagosiebler"
},
"license": "MIT",
"devDependencies": {
"chai": "^4.1.1",
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"mocha": "^7.1.0",
"mock-require": "^2.0.2",
"nyc": "^15.0.0",
"prettier": "^1.19.1",
"sinon": "^9.0.1"
}
"name": "binance",
"version": "1.3.8",
"description": "node.js wrapper for the Binance REST and WebSocket APIs",
"main": "./lib/binance.js",
"files": [
"lib/*"
],
"scripts": {
"test": "npx mocha",
"cover": "nyc --reporter=html --reporter=text mocha",
"coveralls": "nyc report --reporter=text-lcov | coveralls",
"lint": "eslint lib test util && prettier --check lib/**/* test/**/* util/**/*",
"lintfix": "eslint lib test util --fix && prettier --write lib/**/* test/**/* util/**/*",
"precommit": "npm run test && npm run lint"
},
"dependencies": {
"bignumber.js": "^9.0.0",
"request": "^2.88.2",
"underscore": "^1.8.3",
"ws": "^3.3.1"
},
"repository": {
"type": "git",
"url": "https://github.com/tiagosiebler/binance"
},
"bugs": {
"url": "https://github.com/tiagosiebler/binance/issues"
},
"homepage": "https://github.com/tiagosiebler/binance#readme",
"keywords": [
"api",
"bitcoin",
"ethereum",
"cryptocurrency",
"binance",
"btc",
"eth"
],
"author": "Zoey Garvey",
"contributors": [
"Clifford Roche <clifford.roche@gmail.com> (http://www.cliffordroche.ca)",
"Aslam Hadi H <aslamhadi@gmail.com> (https://www.commitcode.com)",
"Andrey Vorobyov <vorandrew@gmail.com>",
"Gavy Aggarwal (http://gavyaggarwal.com/)",
"Tiago Siebler (https://github.com/tiagosiebler)",
"Tony Pettigrew (https://github.com/NeverEnder4)",
"Chris <apexearth@gmail.com> (https://github.com/apexearth)"
],
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/tiagosiebler"
},
"license": "MIT",
"devDependencies": {
"chai": "^4.1.1",
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"mocha": "^7.1.0",
"mock-require": "^2.0.2",
"nyc": "^15.0.0",
"prettier": "^1.19.1",
"sinon": "^9.0.1"
}
}

@@ -7,4 +7,3 @@ ![npm downloads](https://img.shields.io/npm/dt/binance.svg)

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
A wrapper for the Binance REST and WebSocket APIs. Uses promises 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

@@ -59,14 +58,2 @@ # Usage/Example

/*
* 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

@@ -268,4 +255,22 @@ *

Places a new order.
Places a new order. Example:
```javascript
const customOrderId = binanceRest.generateNewOrderId();
binanceRest
.newOrder({
symbol: 'BTCUSDT',
quantity: 0.1,
side: 'BUY',
type: 'MARKET',
newClientOrderId: customOrderId,
})
.then(orderData => {
console.log(orderData);
})
.catch(err => {
console.error(err);
});
```
### **[testOrder(query _object_, [callback _function_])](https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#test-new-order-trade)**

@@ -693,18 +698,10 @@

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.
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.
# License
[MIT](LICENSE)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc