binance-api-networks
Version:
A node API wrapper for Binance (Support Networks SAPI)
642 lines (586 loc) • 23.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.candleFields = void 0;
var _crypto = _interopRequireDefault(require("crypto"));
var _lodash = _interopRequireDefault(require("lodash.zipobject"));
require("isomorphic-fetch");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
var BASE = 'https://api.binance.com';
var FUTURES = 'https://fapi.binance.com';
var defaultGetTime = function defaultGetTime() {
return Date.now();
};
var info = {
spot: {},
futures: {}
};
/**
* Build query string for uri encoded url based on json object
*/
var makeQueryString = function makeQueryString(q) {
return q ? "?".concat(Object.keys(q).map(function (k) {
return "".concat(encodeURIComponent(k), "=").concat(encodeURIComponent(q[k]));
}).join('&')) : '';
};
/**
* Get API limits info from headers
*/
var headersMapping = {
'x-mbx-used-weight-1m': 'usedWeigh1m',
'x-mbx-order-count-10s': 'orderCount10s',
'x-mbx-order-count-1m': 'orderCount1m',
'x-mbx-order-count-1h': 'orderCount1h',
'x-mbx-order-count-1d': 'orderCount1d',
'x-response-time': 'responseTime'
};
var responseHandler = function responseHandler(res) {
if (!res.headers || !res.url) {
return;
}
var marketName = res.url.includes(FUTURES) ? 'futures' : 'spot';
Object.keys(headersMapping).forEach(function (key) {
var outKey = headersMapping[key];
if (res.headers.has(key)) {
info[marketName][outKey] = res.headers.get(key);
}
});
};
/**
* Finalize API response
*/
var sendResult = function sendResult(call) {
return call.then(function (res) {
// Get API limits info from headers
responseHandler(res); // If response is ok, we can safely assume it is valid JSON
if (res.ok) {
return res.json();
} // Errors might come from the API itself or the proxy Binance is using.
// For API errors the response will be valid JSON,but for proxy errors
// it will be HTML
return res.text().then(function (text) {
var error;
try {
var json = JSON.parse(text); // The body was JSON parseable, assume it is an API response error
error = new Error(json.msg || "".concat(res.status, " ").concat(res.statusText));
error.code = json.code;
error.url = res.url;
} catch (e) {
// The body was not JSON parseable, assume it is proxy error
error = new Error("".concat(res.status, " ").concat(res.statusText, " ").concat(text));
error.response = res;
error.responseText = text;
}
throw error;
});
});
};
/**
* Util to validate existence of required parameter(s)
*/
var checkParams = function checkParams(name, payload) {
var requires = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
if (!payload) {
throw new Error('You need to pass a payload object.');
}
requires.forEach(function (r) {
if (!payload[r] && isNaN(payload[r])) {
throw new Error("Method ".concat(name, " requires ").concat(r, " parameter."));
}
});
return true;
};
/**
* Make public calls against the api
*
* @param {string} path Endpoint path
* @param {object} data The payload to be sent
* @param {string} method HTTB VERB, GET by default
* @param {object} headers
* @returns {object} The api response
*/
var publicCall = function publicCall(_ref) {
var endpoints = _ref.endpoints;
return function (path, data) {
var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'GET';
var headers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
return sendResult(fetch("".concat(!path.includes('/fapi') ? endpoints.base : endpoints.futures).concat(path).concat(makeQueryString(data)), {
method: method,
json: true,
headers: headers
}));
};
};
/**
* Factory method for partial private calls against the api
*
* @param {string} path Endpoint path
* @param {object} data The payload to be sent
* @param {string} method HTTB VERB, GET by default
* @returns {object} The api response
*/
var keyCall = function keyCall(_ref2) {
var apiKey = _ref2.apiKey,
pubCall = _ref2.pubCall;
return function (path, data) {
var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'GET';
if (!apiKey) {
throw new Error('You need to pass an API key to make this call.');
}
return pubCall(path, data, method, {
'X-MBX-APIKEY': apiKey
});
};
};
/**
* Factory method for private calls against the api
*
* @param {string} path Endpoint path
* @param {object} data The payload to be sent
* @param {string} method HTTB VERB, GET by default
* @param {object} headers
* @returns {object} The api response
*/
var privateCall = function privateCall(_ref3) {
var apiKey = _ref3.apiKey,
apiSecret = _ref3.apiSecret,
endpoints = _ref3.endpoints,
_ref3$getTime = _ref3.getTime,
getTime = _ref3$getTime === void 0 ? defaultGetTime : _ref3$getTime,
pubCall = _ref3.pubCall;
return function (path) {
var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var method = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'GET';
var noData = arguments.length > 3 ? arguments[3] : undefined;
var noExtra = arguments.length > 4 ? arguments[4] : undefined;
if (!apiKey || !apiSecret) {
throw new Error('You need to pass an API key and secret to make authenticated calls.');
}
return (data && data.useServerTime ? pubCall('/api/v3/time').then(function (r) {
return r.serverTime;
}) : Promise.resolve(getTime())).then(function (timestamp) {
if (data) {
delete data.useServerTime;
}
var signature = _crypto.default.createHmac('sha256', apiSecret).update(makeQueryString(_objectSpread(_objectSpread({}, data), {}, {
timestamp: timestamp
})).substr(1)).digest('hex');
var newData = noExtra ? data : _objectSpread(_objectSpread({}, data), {}, {
timestamp: timestamp,
signature: signature
});
return sendResult(fetch("".concat(!path.includes('/fapi') ? endpoints.base : endpoints.futures).concat(path).concat(noData ? '' : makeQueryString(newData)), {
method: method,
headers: {
'X-MBX-APIKEY': apiKey
},
json: true
}));
});
};
};
var candleFields = ['openTime', 'open', 'high', 'low', 'close', 'volume', 'closeTime', 'quoteVolume', 'trades', 'baseAssetVolume', 'quoteAssetVolume'];
/**
* Get candles for a specific pair and interval and convert response
* to a user friendly collection.
*/
exports.candleFields = candleFields;
var _candles = function candles(pubCall, payload) {
var endpoint = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '/api/v3/klines';
return checkParams('candles', payload, ['symbol']) && pubCall(endpoint, _objectSpread({
interval: '5m'
}, payload)).then(function (candles) {
return candles.map(function (candle) {
return (0, _lodash.default)(candleFields, candle);
});
});
};
/**
* Create a new order wrapper for market order simplicity
*/
var _order = function order(privCall) {
var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var url = arguments.length > 2 ? arguments[2] : undefined;
var newPayload = ['LIMIT', 'STOP_LOSS_LIMIT', 'TAKE_PROFIT_LIMIT'].includes(payload.type) || !payload.type ? _objectSpread({
timeInForce: 'GTC'
}, payload) : payload;
var requires = ['symbol', 'side'];
if (!(newPayload.type === 'MARKET' && newPayload.quoteOrderQty)) {
requires.push('quantity');
}
return checkParams('order', newPayload, requires) && privCall(url, _objectSpread({
type: 'LIMIT'
}, newPayload), 'POST');
};
var _orderOco = function orderOco(privCall) {
var payload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var url = arguments.length > 2 ? arguments[2] : undefined;
var newPayload = payload.stopLimitPrice && !payload.stopLimitTimeInForce ? _objectSpread({
stopLimitTimeInForce: 'GTC'
}, payload) : payload;
return checkParams('order', newPayload, ['symbol', 'side', 'quantity', 'price', 'stopPrice']) && privCall(url, newPayload, 'POST');
};
/**
* Zip asks and bids reponse from order book
*/
var _book = function book(pubCall, payload) {
var endpoint = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '/api/v3/depth';
return checkParams('book', payload, ['symbol']) && pubCall(endpoint, payload).then(function (_ref4) {
var lastUpdateId = _ref4.lastUpdateId,
asks = _ref4.asks,
bids = _ref4.bids;
return {
lastUpdateId: lastUpdateId,
asks: asks.map(function (a) {
return (0, _lodash.default)(['price', 'quantity'], a);
}),
bids: bids.map(function (b) {
return (0, _lodash.default)(['price', 'quantity'], b);
})
};
});
};
var _aggTrades = function aggTrades(pubCall, payload) {
var endpoint = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '/api/v3/aggTrades';
return checkParams('aggTrades', payload, ['symbol']) && pubCall(endpoint, payload).then(function (trades) {
return trades.map(function (trade) {
return {
aggId: trade.a,
symbol: payload.symbol,
price: trade.p,
quantity: trade.q,
firstId: trade.f,
lastId: trade.l,
timestamp: trade.T,
isBuyerMaker: trade.m,
wasBestPrice: trade.M
};
});
});
};
var _default = function _default(opts) {
var endpoints = {
base: opts && opts.httpBase || BASE,
futures: opts && opts.httpFutures || FUTURES
};
var pubCall = publicCall(_objectSpread(_objectSpread({}, opts), {}, {
endpoints: endpoints
}));
var privCall = privateCall(_objectSpread(_objectSpread({}, opts), {}, {
endpoints: endpoints,
pubCall: pubCall
}));
var kCall = keyCall(_objectSpread(_objectSpread({}, opts), {}, {
pubCall: pubCall
}));
return {
getInfo: function getInfo() {
return info;
},
ping: function ping() {
return pubCall('/api/v3/ping').then(function () {
return true;
});
},
time: function time() {
return pubCall('/api/v3/time').then(function (r) {
return r.serverTime;
});
},
exchangeInfo: function exchangeInfo() {
return pubCall('/api/v3/exchangeInfo');
},
book: function book(payload) {
return _book(pubCall, payload);
},
aggTrades: function aggTrades(payload) {
return _aggTrades(pubCall, payload);
},
candles: function candles(payload) {
return _candles(pubCall, payload);
},
trades: function trades(payload) {
return checkParams('trades', payload, ['symbol']) && pubCall('/api/v3/trades', payload);
},
tradesHistory: function tradesHistory(payload) {
return checkParams('tradesHitory', payload, ['symbol']) && kCall('/api/v3/historicalTrades', payload);
},
dailyStats: function dailyStats(payload) {
return pubCall('/api/v3/ticker/24hr', payload);
},
prices: function prices(payload) {
return pubCall('/api/v3/ticker/price', payload).then(function (r) {
return (Array.isArray(r) ? r : [r]).reduce(function (out, cur) {
return out[cur.symbol] = cur.price, out;
}, {});
});
},
avgPrice: function avgPrice(payload) {
return pubCall('/api/v3/avgPrice', payload);
},
allBookTickers: function allBookTickers() {
return pubCall('/api/v3/ticker/bookTicker').then(function (r) {
return (Array.isArray(r) ? r : [r]).reduce(function (out, cur) {
return out[cur.symbol] = cur, out;
}, {});
});
},
/**
* Call unmanaged private call to Binance api; you need a key and secret
*/
privateRequest: function privateRequest(method, url, payload) {
return privCall(url, payload, method);
},
/**
* Call unmanaged public call to Binance api
*/
publicRequest: function publicRequest(method, url, payload) {
return pubCall(url, payload, method);
},
order: function order(payload) {
return _order(privCall, payload, '/api/v3/order');
},
orderOco: function orderOco(payload) {
return _orderOco(privCall, payload, '/api/v3/order/oco');
},
orderTest: function orderTest(payload) {
return _order(privCall, payload, '/api/v3/order/test');
},
getOrder: function getOrder(payload) {
return privCall('/api/v3/order', payload);
},
cancelOrder: function cancelOrder(payload) {
return privCall('/api/v3/order', payload, 'DELETE');
},
cancelOpenOrders: function cancelOpenOrders(payload) {
return privCall('/api/v3/openOrders', payload, 'DELETE');
},
openOrders: function openOrders(payload) {
return privCall('/api/v3/openOrders', payload);
},
allOrders: function allOrders(payload) {
return privCall('/api/v3/allOrders', payload);
},
allOrdersOCO: function allOrdersOCO(payload) {
return privCall('/api/v3/allOrderList', payload);
},
accountInfo: function accountInfo(payload) {
return privCall('/api/v3/account', payload);
},
myTrades: function myTrades(payload) {
return privCall('/api/v3/myTrades', payload);
},
withdraw: function withdraw(payload) {
return privCall('/wapi/v3/withdraw.html', payload, 'POST');
},
withdrawHistory: function withdrawHistory(payload) {
return privCall('/wapi/v3/withdrawHistory.html', payload);
},
depositHistory: function depositHistory(payload) {
return privCall('/wapi/v3/depositHistory.html', payload);
},
depositAddress: function depositAddress(payload) {
return privCall('/wapi/v3/depositAddress.html', payload);
},
withdrawNetworks: function withdrawNetworks(payload) {
return privCall('/sapi/v1/capital/withdraw/apply', payload, 'POST');
},
withdrawHistoryNetworks: function withdrawHistoryNetworks(payload) {
return privCall('/sapi/v1/capital/withdraw/history', payload);
},
depositHistoryNetworks: function depositHistoryNetworks(payload) {
return privCall('/sapi/v1/capital/deposit/hisrec', payload);
},
depositAddressNetworks: function depositAddressNetworks(payload) {
return privCall('/sapi/v1/capital/deposit/address', payload);
},
tradeFee: function tradeFee(payload) {
return privCall('/wapi/v3/tradeFee.html', payload);
},
assetDetail: function assetDetail(payload) {
return privCall('/wapi/v3/assetDetail.html', payload);
},
universalTransfer: function universalTransfer(payload) {
return privCall('/sapi/v1/asset/transfer', payload, 'POST');
},
universalTransferHistory: function universalTransferHistory(payload) {
return privCall('/sapi/v1/asset/transfer', payload);
},
capitalConfigs: function capitalConfigs() {
return privCall('/sapi/v1/capital/config/getall');
},
capitalDepositAddress: function capitalDepositAddress(payload) {
return privCall('/sapi/v1/capital/deposit/address', payload);
},
getDataStream: function getDataStream() {
return privCall('/api/v3/userDataStream', null, 'POST', true);
},
keepDataStream: function keepDataStream(payload) {
return privCall('/api/v3/userDataStream', payload, 'PUT', false, true);
},
closeDataStream: function closeDataStream(payload) {
return privCall('/api/v3/userDataStream', payload, 'DELETE', false, true);
},
accountSnapshot: function accountSnapshot(payload) {
return privCall('/sapi/v1/accountSnapshot', payload, 'GET');
},
marginGetDataStream: function marginGetDataStream() {
return privCall('/sapi/v1/userDataStream', null, 'POST', true);
},
marginKeepDataStream: function marginKeepDataStream(payload) {
return privCall('/sapi/v1/userDataStream', payload, 'PUT', false, true);
},
marginCloseDataStream: function marginCloseDataStream(payload) {
return privCall('/sapi/v1/userDataStream', payload, 'DELETE', false, true);
},
futuresGetDataStream: function futuresGetDataStream() {
return privCall('/fapi/v1/listenKey', null, 'POST', true);
},
futuresKeepDataStream: function futuresKeepDataStream(payload) {
return privCall('/fapi/v1/listenKey', payload, 'PUT', false, true);
},
futuresCloseDataStream: function futuresCloseDataStream(payload) {
return privCall('/fapi/v1/listenKey', payload, 'DELETE', false, true);
},
marginAllOrders: function marginAllOrders(payload) {
return privCall('/sapi/v1/margin/allOrders', payload);
},
marginOrder: function marginOrder(payload) {
return _order(privCall, payload, '/sapi/v1/margin/order');
},
marginCancelOrder: function marginCancelOrder(payload) {
return privCall('/sapi/v1/margin/order', payload, 'DELETE');
},
marginOpenOrders: function marginOpenOrders(payload) {
return privCall('/sapi/v1/margin/openOrders', payload);
},
marginAccountInfo: function marginAccountInfo(payload) {
return privCall('/sapi/v1/margin/account', payload);
},
marginMyTrades: function marginMyTrades(payload) {
return privCall('/sapi/v1/margin/myTrades', payload);
},
marginRepay: function marginRepay(payload) {
return privCall('/sapi/v1/margin/repay', payload, 'POST');
},
marginLoan: function marginLoan(payload) {
return privCall('/sapi/v1/margin/loan', payload, 'POST');
},
marginIsolatedAccount: function marginIsolatedAccount(payload) {
return privCall('/sapi/v1/margin/isolated/account', payload);
},
marginMaxBorrow: function marginMaxBorrow(payload) {
return privCall('/sapi/v1/margin/maxBorrowable', payload);
},
marginCreateIsolated: function marginCreateIsolated(payload) {
return privCall('/sapi/v1/margin/isolated/create', payload, 'POST');
},
marginIsolatedTransfer: function marginIsolatedTransfer(payload) {
return privCall('/sapi/v1/margin/isolated/transfer', payload, 'POST');
},
marginIsolatedTransferHistory: function marginIsolatedTransferHistory(payload) {
return privCall('/sapi/v1/margin/isolated/transfer', payload);
},
futuresPing: function futuresPing() {
return pubCall('/fapi/v1/ping').then(function () {
return true;
});
},
futuresTime: function futuresTime() {
return pubCall('/fapi/v1/time').then(function (r) {
return r.serverTime;
});
},
futuresExchangeInfo: function futuresExchangeInfo() {
return pubCall('/fapi/v1/exchangeInfo');
},
futuresBook: function futuresBook(payload) {
return _book(pubCall, payload, '/fapi/v1/depth');
},
futuresAggTrades: function futuresAggTrades(payload) {
return _aggTrades(pubCall, payload, '/fapi/v1/aggTrades');
},
futuresMarkPrice: function futuresMarkPrice(payload) {
return pubCall('/fapi/v1/premiumIndex', payload);
},
futuresAllForceOrders: function futuresAllForceOrders(payload) {
return pubCall('/fapi/v1/allForceOrders', payload);
},
futuresCandles: function futuresCandles(payload) {
return _candles(pubCall, payload, '/fapi/v1/klines');
},
futuresTrades: function futuresTrades(payload) {
return checkParams('trades', payload, ['symbol']) && pubCall('/fapi/v1/trades', payload);
},
futuresDailyStats: function futuresDailyStats(payload) {
return pubCall('/fapi/v1/ticker/24hr', payload);
},
futuresPrices: function futuresPrices() {
return pubCall('/fapi/v1/ticker/price').then(function (r) {
return (Array.isArray(r) ? r : [r]).reduce(function (out, cur) {
return out[cur.symbol] = cur.price, out;
}, {});
});
},
futuresAllBookTickers: function futuresAllBookTickers() {
return pubCall('/fapi/v1/ticker/bookTicker').then(function (r) {
return (Array.isArray(r) ? r : [r]).reduce(function (out, cur) {
return out[cur.symbol] = cur, out;
}, {});
});
},
futuresFundingRate: function futuresFundingRate(payload) {
return checkParams('fundingRate', payload, ['symbol']) && pubCall('/fapi/v1/fundingRate', payload);
},
futuresOrder: function futuresOrder(payload) {
return _order(privCall, payload, '/fapi/v1/order');
},
futuresGetOrder: function futuresGetOrder(payload) {
return privCall('/fapi/v1/order', payload);
},
futuresCancelOrder: function futuresCancelOrder(payload) {
return privCall('/fapi/v1/order', payload, 'DELETE');
},
futuresOpenOrders: function futuresOpenOrders(payload) {
return privCall('/fapi/v1/openOrders', payload);
},
futuresAllOrders: function futuresAllOrders(payload) {
return privCall('/fapi/v1/allOrders', payload);
},
futuresPositionRisk: function futuresPositionRisk(payload) {
return privCall('/fapi/v2/positionRisk', payload);
},
futuresAccountBalance: function futuresAccountBalance(payload) {
return privCall('/fapi/v2/balance', payload);
},
futuresUserTrades: function futuresUserTrades(payload) {
return privCall('/fapi/v1/userTrades', payload);
},
futuresPositionMode: function futuresPositionMode(payload) {
return privCall('/fapi/v1/positionSide/dual', payload);
},
futuresPositionModeChange: function futuresPositionModeChange(payload) {
return privCall('/fapi/v1/positionSide/dual', payload, 'POST');
},
futuresLeverage: function futuresLeverage(payload) {
return privCall('/fapi/v1/leverage', payload, 'POST');
},
futuresMarginType: function futuresMarginType(payload) {
return privCall('/fapi/v1/marginType', payload, 'POST');
},
futuresPositionMargin: function futuresPositionMargin(payload) {
return privCall('/fapi/v1/positionMargin', payload, 'POST');
},
futuresMarginHistory: function futuresMarginHistory(payload) {
return privCall('/fapi/v1/positionMargin/history', payload);
},
futuresIncome: function futuresIncome(payload) {
return privCall('/fapi/v1/income', payload);
}
};
};
exports.default = _default;