IPC removed, replaced by WS

This commit is contained in:
Luis Fernando Molina committed 2020-04-06 08:33:07 +02:00
1 parent ba4217fb24
commit 656c193511
503 files changed
+28128 -34498

No files matched your search

+120 -17
View File
@@ -3,8 +3,8 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress } = require ('./base/errors');
const { ROUND } = require ('./base/functions/number');
const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied } = require ('./base/errors');
const { ROUND, TRUNCATE } = require ('./base/functions/number');
// ---------------------------------------------------------------------------
@@ -16,6 +16,7 @@ module.exports = class binance extends Exchange {
'countries': [ 'JP', 'MT' ], // Japan, Malta
'rateLimit': 500,
'certified': true,
'pro': true,
// new metainfo interface
'has': {
'fetchDepositAddress': true,
@@ -120,6 +121,15 @@ module.exports = class binance extends Exchange {
'sub-account/margin/account',
'sub-account/margin/accountSummary',
'sub-account/status',
// lending endpoints
'lending/daily/product/list',
'lending/daily/userLeftQuota',
'lending/daily/userRedemptionQuota',
'lending/daily/token/position',
'lending/union/account',
'lending/union/purchaseRecord',
'lending/union/redemptionRecord',
'lending/union/interestHistory',
],
'post': [
'asset/dust',
@@ -135,6 +145,9 @@ module.exports = class binance extends Exchange {
'sub-account/futures/enable',
'userDataStream',
'futures/transfer',
// lending
'lending/daily/purchase',
'lending/daily/redeem',
],
'put': [
'userDataStream',
@@ -174,18 +187,20 @@ module.exports = class binance extends Exchange {
'historicalTrades',
'aggTrades',
'klines',
'fundingRate',
'premiumIndex',
'ticker/24hr',
'ticker/price',
'ticker/bookTicker',
'allForceOrders',
'openInterest',
'leverageBracket',
],
'put': [ 'listenKey' ],
'post': [ 'listenKey' ],
'delete': [ 'listenKey' ],
},
'fapiPrivate': {
'get': [
'allOrders',
'openOrder',
'openOrders',
'order',
'account',
@@ -200,10 +215,15 @@ module.exports = class binance extends Exchange {
'marginType',
'order',
'leverage',
'listenKey',
],
'put': [
'listenKey',
],
'delete': [
'order',
'allOpenOrders',
'listenKey',
],
},
'v3': {
@@ -266,7 +286,7 @@ module.exports = class binance extends Exchange {
},
// exchange-specific options
'options': {
'fetchTradesMethod': 'publicGetAggTrades',
'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades
'fetchTickersMethod': 'publicGetTicker24hr',
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
'defaultLimitOrderType': 'limit', // or 'limit_maker'
@@ -287,7 +307,10 @@ module.exports = class binance extends Exchange {
'Order would trigger immediately.': InvalidOrder,
'Account has insufficient balance for requested action.': InsufficientFunds,
'Rest API trading is not enabled.': ExchangeNotAvailable,
"You don't have permission.": PermissionDenied, // {"msg":"You don't have permission.","success":false}
'Market is closed.': ExchangeNotAvailable, // {"code":-1013,"msg":"Market is closed."}
'-1000': ExchangeNotAvailable, // {"code":-1000,"msg":"An unknown error occured while processing the request."}
'-1003': RateLimitExceeded, // {"code":-1003,"msg":"Too much request weight used, current limit is 1200 request weight per 1 MINUTE. Please use the websocket for live updates to avoid polling the API."}
'-1013': InvalidOrder, // createOrder -> 'invalid quantity'/'invalid price'/MIN_NOTIONAL
'-1021': InvalidNonce, // 'your time is ahead of server'
'-1022': AuthenticationError, // {"code":-1022,"msg":"Signature for this request is not valid."}
@@ -311,13 +334,13 @@ module.exports = class binance extends Exchange {
const type = this.safeString2 (this.options, 'fetchTime', 'defaultType', 'spot');
const method = (type === 'spot') ? 'publicGetTime' : 'fapiPublicGetTime';
const response = await this[method] (params);
return this.safeFloat (response, 'serverTime');
return this.safeInteger (response, 'serverTime');
}
async loadTimeDifference () {
const serverTime = await this.fetchTime ();
const after = this.milliseconds ();
this.options['timeDifference'] = parseInt (after - serverTime);
this.options['timeDifference'] = after - serverTime;
return this.options['timeDifference'];
}
@@ -414,6 +437,7 @@ module.exports = class binance extends Exchange {
const spot = !future;
const marketType = spot ? 'spot' : 'future';
const id = this.safeString (market, 'symbol');
const lowercaseId = this.safeStringLower (market, 'symbol');
const baseId = market['baseAsset'];
const quoteId = market['quoteAsset'];
const base = this.safeCurrencyCode (baseId);
@@ -430,6 +454,7 @@ module.exports = class binance extends Exchange {
const active = (status === 'TRADING');
const entry = {
'id': id,
'lowercaseId': lowercaseId,
'symbol': symbol,
'base': base,
'quote': quote,
@@ -481,6 +506,13 @@ module.exports = class binance extends Exchange {
'max': this.safeFloat (filter, 'maxQty'),
};
}
if ('MARKET_LOT_SIZE' in filters) {
const filter = this.safeValue (filters, 'MARKET_LOT_SIZE', {});
entry['limits']['market'] = {
'min': this.safeFloat (filter, 'minQty'),
'max': this.safeFloat (filter, 'maxQty'),
};
}
if ('MIN_NOTIONAL' in filters) {
entry['limits']['cost']['min'] = this.safeFloat (filters['MIN_NOTIONAL'], 'minNotional');
}
@@ -655,7 +687,7 @@ module.exports = class binance extends Exchange {
}
async fetchStatus (params = {}) {
const response = await this.wapiGetSystemStatus ();
const response = await this.wapiGetSystemStatus (params);
let status = this.safeValue (response, 'status');
if (status !== undefined) {
status = (status === 0) ? 'ok' : 'maintenance';
@@ -865,13 +897,23 @@ module.exports = class binance extends Exchange {
// 'endTime': 789, // Timestamp in ms to get aggregate trades until INCLUSIVE.
// 'limit': 500, // default = 500, maximum = 1000
};
if (this.options['fetchTradesMethod'] === 'publicGetAggTrades') {
const defaultType = this.safeString2 (this.options, 'fetchTrades', 'defaultType', 'spot');
const type = this.safeString (params, 'type', defaultType);
const query = this.omit (params, 'type');
const defaultMethod = (type === 'future') ? 'fapiPublicGetTrades' : 'publicGetTrades';
let method = this.safeString (this.options, 'fetchTradesMethod', defaultMethod);
if (method === 'publicGetAggTrades') {
if (since !== undefined) {
request['startTime'] = since;
// https://github.com/ccxt/ccxt/issues/6400
// https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#compressedaggregate-trades-list
request['endTime'] = this.sum (since, 3600000);
}
if (type === 'future') {
method = 'fapiPublicGetAggTrades';
}
} else if ((method === 'publicGetHistoricalTrades') && (type === 'future')) {
method = 'fapiPublicGetHistoricalTrades';
}
if (limit !== undefined) {
request['limit'] = limit; // default = 500, maximum = 1000
@@ -885,8 +927,7 @@ module.exports = class binance extends Exchange {
// - 'tradeId' accepted and returned by this method is "aggregate" trade id
// which is different from actual trade id
// - setting both fromId and time window results in error
const method = this.safeValue (this.options, 'fetchTradesMethod', 'publicGetTrades');
const response = await this[method] (this.extend (request, params));
const response = await this[method] (this.extend (request, query));
//
// aggregate trades
//
@@ -933,6 +974,46 @@ module.exports = class binance extends Exchange {
}
parseOrder (order, market = undefined) {
//
// spot
//
// {
// "symbol": "LTCBTC",
// "orderId": 1,
// "clientOrderId": "myOrder1",
// "price": "0.1",
// "origQty": "1.0",
// "executedQty": "0.0",
// "cummulativeQuoteQty": "0.0",
// "status": "NEW",
// "timeInForce": "GTC",
// "type": "LIMIT",
// "side": "BUY",
// "stopPrice": "0.0",
// "icebergQty": "0.0",
// "time": 1499827319559,
// "updateTime": 1499827319559,
// "isWorking": true
// }
//
// futures
//
// {
// "symbol": "BTCUSDT",
// "orderId": 1,
// "clientOrderId": "myOrder1",
// "price": "0.1",
// "origQty": "1.0",
// "executedQty": "1.0",
// "cumQuote": "10.0",
// "status": "NEW",
// "timeInForce": "GTC",
// "type": "LIMIT",
// "side": "BUY",
// "stopPrice": "0.0",
// "updateTime": 1499827319559
// }
//
const status = this.parseOrderStatus (this.safeString (order, 'status'));
let symbol = undefined;
const marketId = this.safeString (order, 'symbol');
@@ -1017,9 +1098,11 @@ module.exports = class binance extends Exchange {
cost = parseFloat (this.costToPrecision (symbol, cost));
}
}
const clientOrderId = this.safeString (order, 'clientOrderId');
return {
'info': order,
'id': id,
'clientOrderId': clientOrderId,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'lastTradeTimestamp': undefined,
@@ -1062,10 +1145,12 @@ module.exports = class binance extends Exchange {
};
if (uppercaseType === 'MARKET') {
const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty');
const precision = market['precision']['price'];
if (quoteOrderQty !== undefined) {
request['quoteOrderQty'] = this.costToPrecision (symbol, quoteOrderQty);
request['quoteOrderQty'] = this.decimalToPrecision (quoteOrderQty, TRUNCATE, precision, this.precisionMode);
params = this.omit (params, 'quoteOrderQty');
} else if (price !== undefined) {
request['quoteOrderQty'] = this.costToPrecision (symbol, amount * price);
request['quoteOrderQty'] = this.decimalToPrecision (amount * price, TRUNCATE, precision, this.precisionMode);
} else {
request['quantity'] = this.amountToPrecision (symbol, amount);
}
@@ -1083,6 +1168,9 @@ module.exports = class binance extends Exchange {
timeInForceIsRequired = true;
} else if ((uppercaseType === 'STOP_LOSS') || (uppercaseType === 'TAKE_PROFIT')) {
stopPriceIsRequired = true;
if (market['future']) {
priceIsRequired = true;
}
} else if ((uppercaseType === 'STOP_LOSS_LIMIT') || (uppercaseType === 'TAKE_PROFIT_LIMIT')) {
stopPriceIsRequired = true;
priceIsRequired = true;
@@ -1234,11 +1322,18 @@ module.exports = class binance extends Exchange {
}
await this.loadMarkets ();
const market = this.market (symbol);
// https://github.com/ccxt/ccxt/issues/6507
const origClientOrderId = this.safeValue (params, 'origClientOrderId');
const request = {
'symbol': market['id'],
'orderId': parseInt (id),
// 'orderId': parseInt (id),
// 'origClientOrderId': id,
};
if (origClientOrderId === undefined) {
request['orderId'] = parseInt (id);
} else {
request['origClientOrderId'] = origClientOrderId;
}
const method = market['spot'] ? 'privateDeleteOrder' : 'fapiPrivateDeleteOrder';
const response = await this[method] (this.extend (request, params));
return this.parseOrder (response);
@@ -1418,6 +1513,8 @@ module.exports = class binance extends Exchange {
}
if (since !== undefined) {
request['startTime'] = since;
// max 3 months range https://github.com/ccxt/ccxt/issues/6495
request['endTime'] = this.sum (since, 7776000000);
}
const response = await this.wapiGetDepositHistory (this.extend (request, params));
//
@@ -1443,6 +1540,8 @@ module.exports = class binance extends Exchange {
}
if (since !== undefined) {
request['startTime'] = since;
// max 3 months range https://github.com/ccxt/ccxt/issues/6495
request['endTime'] = this.sum (since, 7776000000);
}
const response = await this.wapiGetWithdrawHistory (this.extend (request, params));
//
@@ -1726,7 +1825,7 @@ module.exports = class binance extends Exchange {
if (api === 'wapi') {
url += '.html';
}
const userDataStream = ((path === 'userDataStream') || (path === 'listenKey'));
const userDataStream = (path === 'userDataStream') || (path === 'listenKey');
if (path === 'historicalTrades') {
if (this.apiKey) {
headers = {
@@ -1830,9 +1929,13 @@ module.exports = class binance extends Exchange {
// checks against error codes
const error = this.safeString (response, 'code');
if (error !== undefined) {
// https://github.com/ccxt/ccxt/issues/6501
if (error === '200') {
return;
}
// a workaround for {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
// despite that their message is very confusing, it is raised by Binance
// on a temporary ban (the API key is valid, but disabled for a while)
// on a temporary ban, the API key is valid, but disabled for a while
if ((error === '-2015') && this.options['hasAlreadyAuthenticatedSuccessfully']) {
throw new DDoSProtection (this.id + ' temporary banned: ' + body);
}