IPC removed, replaced by WS
This commit is contained in:
1 parent
ba4217fb24
commit
656c193511
503 files changed
+28128
-34498
No files matched your search
+120
-17
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user