Bug Fixes
This commit is contained in:
1 parent
82bc086e92
commit
b1af6e078c
131 files changed
+8597
-1930
No files matched your search
+94
@@ -0,0 +1,94 @@
|
||||
"use strict"
|
||||
|
||||
const { execSync } = require ('child_process')
|
||||
const log = require ('ololog').noLocate
|
||||
const { groupBy } = require ('../ccxt.js')
|
||||
const { values } = Object
|
||||
const assert = require ('assert')
|
||||
|
||||
function cleanupOldTags () {
|
||||
|
||||
const tags = execSync ('git tag').toString ().split ('\n').filter (s => s).map (t => {
|
||||
|
||||
const [major, minor, patch] = t.replace ('v', '').split ('.').map (Number)
|
||||
|
||||
assert (major < 100)
|
||||
assert (minor < 100)
|
||||
|
||||
return {
|
||||
key: (major * 100) + minor,
|
||||
tag: t,
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
}
|
||||
})
|
||||
|
||||
const tagsByMajorMinor = values (groupBy (tags, 'key')).sort ((a, b) => a[0].key - b[0].key)
|
||||
|
||||
// Preserve all tags for first 3 minor versions
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
|
||||
const tags = tagsByMajorMinor.pop ()
|
||||
|
||||
if (tags) {
|
||||
log.green.bright ('Preserving', tags[0].tag, '...', tags[tags.length - 1].tag)
|
||||
}
|
||||
}
|
||||
|
||||
// For older versions, leave only "round" numbered versions (1/10th)
|
||||
|
||||
let tagsToDelete = []
|
||||
|
||||
for (const tags of tagsByMajorMinor) {
|
||||
|
||||
for (const { tag, patch } of tags) {
|
||||
|
||||
if (patch === 1) {
|
||||
log.green ('Preserving', tag)
|
||||
|
||||
} else {
|
||||
tagsToDelete.push (tag)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.bright.red ('Deleting', tagsToDelete.length, 'tags...')
|
||||
|
||||
if (!process.argv.includes ('--paper')) {
|
||||
|
||||
/* If it happens on a CI server, we don't want it to fail the build because of a super
|
||||
long execution time (one tag deletion takes ~5 sec...), hence that limit here */
|
||||
|
||||
if (process.argv.includes ('--limit')) {
|
||||
tagsToDelete = tagsToDelete.slice (-500)
|
||||
}
|
||||
|
||||
for (const tag of tagsToDelete) {
|
||||
|
||||
log.dim ('Deleting', tag)
|
||||
execSync (`git tag -d ${tag} && git push origin :refs/tags/${tag}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// main entry point
|
||||
|
||||
if (require.main === module) {
|
||||
|
||||
// if called directly like `node module`
|
||||
|
||||
cleanupOldTags ()
|
||||
|
||||
} else {
|
||||
|
||||
// do nothing if required as a module
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
module.exports = {
|
||||
cleanupOldTags,
|
||||
}
|
||||
+28
-12
@@ -447,15 +447,19 @@ class Transpiler {
|
||||
return 'class ' + className + '(' + baseClass + '):'
|
||||
}
|
||||
|
||||
createPythonClassHeader (ccxtImports, bodyAsString) {
|
||||
createPythonClassHeader (imports, bodyAsString) {
|
||||
return [
|
||||
"# -*- coding: utf-8 -*-\n",
|
||||
"# -*- coding: utf-8 -*-",
|
||||
"",
|
||||
"# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:",
|
||||
"# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code\n",
|
||||
... ccxtImports,
|
||||
"# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code",
|
||||
"",
|
||||
... imports,
|
||||
// 'from ' + importFrom + ' import ' + baseClass,
|
||||
... (bodyAsString.match (/basestring/) ? [
|
||||
"\n# -----------------------------------------------------------------------------\n",
|
||||
"",
|
||||
"# -----------------------------------------------------------------------------",
|
||||
"",
|
||||
"try:",
|
||||
" basestring # Python 3",
|
||||
"except NameError:",
|
||||
@@ -464,6 +468,21 @@ class Transpiler {
|
||||
]
|
||||
}
|
||||
|
||||
createPythonClassImports (baseClass, async = false) {
|
||||
|
||||
const baseClasses = {
|
||||
'Exchange': 'base.exchange',
|
||||
}
|
||||
|
||||
async = (async ? '.async_support' : '')
|
||||
|
||||
return [
|
||||
(baseClass.indexOf ('ccxt.') === 0) ?
|
||||
('import ccxt' + async + ' as ccxt') :
|
||||
('from ccxt' + async + '.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass)
|
||||
]
|
||||
}
|
||||
|
||||
createPythonClass (className, baseClass, body, methods, async = false) {
|
||||
|
||||
const pythonStandardLibraries = {
|
||||
@@ -471,6 +490,7 @@ class Transpiler {
|
||||
'hashlib': 'hashlib',
|
||||
'math': 'math',
|
||||
'json.loads': 'json',
|
||||
'sys': 'sys',
|
||||
}
|
||||
|
||||
const baseClasses = {
|
||||
@@ -479,20 +499,16 @@ class Transpiler {
|
||||
|
||||
async = (async ? '.async_support' : '')
|
||||
|
||||
const ccxtImports = [
|
||||
(baseClass.indexOf ('ccxt.') === 0) ?
|
||||
('import ccxt' + async + ' as ccxt') :
|
||||
('from ccxt' + async + '.' + safeString (baseClasses, baseClass, baseClass) + ' import ' + baseClass)
|
||||
]
|
||||
const imports = this.createPythonClassImports (baseClass, async)
|
||||
|
||||
let bodyAsString = body.join ("\n")
|
||||
|
||||
let header = this.createPythonClassHeader (ccxtImports, bodyAsString)
|
||||
let header = this.createPythonClassHeader (imports, bodyAsString)
|
||||
|
||||
const libraries = []
|
||||
|
||||
for (let library in pythonStandardLibraries) {
|
||||
const regex = new RegExp ("[^\\']" + library + "[^\\'a-zA-Z]")
|
||||
const regex = new RegExp ("[^\\'a-zA-Z]" + library + "[^\\'a-zA-Z]")
|
||||
if (bodyAsString.match (regex))
|
||||
libraries.push ('import ' + pythonStandardLibraries[library])
|
||||
}
|
||||
|
||||
+1
-2
@@ -35,7 +35,7 @@ const Exchange = require ('./js/base/Exchange')
|
||||
//-----------------------------------------------------------------------------
|
||||
// this is updated by vss.js when building
|
||||
|
||||
const version = '1.21.82'
|
||||
const version = '1.22.39'
|
||||
|
||||
Exchange.ccxtVersion = version
|
||||
|
||||
@@ -45,7 +45,6 @@ const exchanges = {
|
||||
'_1btcxe': require ('./js/_1btcxe.js'),
|
||||
'acx': require ('./js/acx.js'),
|
||||
'adara': require ('./js/adara.js'),
|
||||
'allcoin': require ('./js/allcoin.js'),
|
||||
'anxpro': require ('./js/anxpro.js'),
|
||||
'bcex': require ('./js/bcex.js'),
|
||||
'bequant': require ('./js/bequant.js'),
|
||||
|
||||
+710
-539
File diff suppressed because it is too large.
Load diff
+5
-5
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const functions = require ('./functions')
|
||||
|
||||
@@ -411,7 +411,7 @@ module.exports = class Exchange {
|
||||
}
|
||||
|
||||
setSandboxMode (enabled) {
|
||||
if (!!enabled) {
|
||||
if (!!enabled) { // eslint-disable-line no-extra-boolean-cast
|
||||
if ('test' in this.urls) {
|
||||
if (typeof this.urls['api'] === 'string') {
|
||||
this.urls['api_backup'] = this.urls['api']
|
||||
@@ -637,7 +637,7 @@ module.exports = class Exchange {
|
||||
'limits': this.limits,
|
||||
'precision': this.precision,
|
||||
}, this.fees['trading'], market))
|
||||
this.markets = deepExtend (this.markets, indexBy (values, 'symbol'))
|
||||
this.markets = indexBy (values, 'symbol')
|
||||
this.marketsById = indexBy (markets, 'id')
|
||||
this.markets_by_id = this.marketsById
|
||||
this.symbols = Object.keys (this.markets).sort ()
|
||||
@@ -1026,9 +1026,9 @@ module.exports = class Exchange {
|
||||
return this.markets;
|
||||
}
|
||||
|
||||
filterBySinceLimit (array, since = undefined, limit = undefined) {
|
||||
filterBySinceLimit (array, since = undefined, limit = undefined, key = 'timestamp') {
|
||||
if (since !== undefined && since !== null)
|
||||
array = array.filter (entry => entry.timestamp >= since)
|
||||
array = array.filter (entry => entry[key] >= since)
|
||||
if (limit !== undefined && limit !== null)
|
||||
array = array.slice (0, limit)
|
||||
return array
|
||||
|
||||
+15
-6
@@ -171,8 +171,8 @@ module.exports = class bibox extends Exchange {
|
||||
'symbol': symbol,
|
||||
'base': base,
|
||||
'quote': quote,
|
||||
'baseId': base,
|
||||
'quoteId': quote,
|
||||
'baseId': baseId,
|
||||
'quoteId': quoteId,
|
||||
'active': true,
|
||||
'info': market,
|
||||
'precision': precision,
|
||||
@@ -400,7 +400,7 @@ module.exports = class bibox extends Exchange {
|
||||
for (let i = 0; i < currencies.length; i++) {
|
||||
const currency = currencies[i];
|
||||
const id = this.safeString (currency, 'symbol');
|
||||
const name = this.safeString (currency, 'name');
|
||||
const name = currency['name']; // contains hieroglyphs causing python ASCII bug
|
||||
const code = this.safeCurrencyCode (id);
|
||||
const precision = 8;
|
||||
const deposit = this.safeValue (currency, 'enable_deposit');
|
||||
@@ -818,12 +818,21 @@ module.exports = class bibox extends Exchange {
|
||||
const response = await this.privatePostTransfer (request);
|
||||
//
|
||||
// {
|
||||
// "result":"3Jx6RZ9TNMsAoy9NUzBwZf68QBppDruSKW","cmd":"transfer/transferIn"
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "result":"{\"account\":\"PERSONALLY OMITTED\",\"memo\":\"PERSONALLY OMITTED\"}","cmd":"transfer/transferIn"
|
||||
// }
|
||||
//
|
||||
const result = JSON.parse (this.safeString (response, 'result'));
|
||||
const address = this.safeString (result, 'account');
|
||||
const tag = this.safeString (result, 'memo');
|
||||
const result = this.safeString (response, 'result');
|
||||
let address = result;
|
||||
let tag = undefined;
|
||||
if (this.isJsonEncodedObject (result)) {
|
||||
const parsed = JSON.parse (result);
|
||||
address = this.safeString (parsed, 'account');
|
||||
tag = this.safeString (parsed, 'memo');
|
||||
}
|
||||
return {
|
||||
'currency': code,
|
||||
'address': address,
|
||||
|
||||
+51
-14
@@ -85,6 +85,7 @@ module.exports = class binance extends Exchange {
|
||||
// the API structure below will need 3-layer apidefs
|
||||
'sapi': {
|
||||
'get': [
|
||||
'accountSnapshot',
|
||||
// these endpoints require this.apiKey
|
||||
'margin/asset',
|
||||
'margin/pair',
|
||||
@@ -108,13 +109,30 @@ module.exports = class binance extends Exchange {
|
||||
'futures/transfer',
|
||||
// https://binance-docs.github.io/apidocs/spot/en/#withdraw-sapi
|
||||
'capital/config/getall', // get networks for withdrawing USDT ERC20 vs USDT Omni
|
||||
'capital/deposit/address',
|
||||
'capital/deposit/hisrec',
|
||||
'capital/deposit/subAddress',
|
||||
'capital/deposit/subHisrec',
|
||||
'capital/withdraw/history',
|
||||
'sub-account/futures/account',
|
||||
'sub-account/futures/accountSummary',
|
||||
'sub-account/futures/positionRisk',
|
||||
'sub-account/margin/account',
|
||||
'sub-account/margin/accountSummary',
|
||||
'sub-account/status',
|
||||
],
|
||||
'post': [
|
||||
'asset/dust',
|
||||
'account/disableFastWithdrawSwitch',
|
||||
'account/enableFastWithdrawSwitch',
|
||||
'capital/withdraw/apply',
|
||||
'margin/transfer',
|
||||
'margin/loan',
|
||||
'margin/repay',
|
||||
'margin/order',
|
||||
'sub-account/margin/enable',
|
||||
'sub-account/margin/enable',
|
||||
'sub-account/futures/enable',
|
||||
'userDataStream',
|
||||
'futures/transfer',
|
||||
],
|
||||
@@ -185,6 +203,7 @@ module.exports = class binance extends Exchange {
|
||||
],
|
||||
'delete': [
|
||||
'order',
|
||||
'allOpenOrders',
|
||||
],
|
||||
},
|
||||
'v3': {
|
||||
@@ -849,6 +868,8 @@ module.exports = class binance extends Exchange {
|
||||
if (this.options['fetchTradesMethod'] === '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);
|
||||
}
|
||||
}
|
||||
@@ -1039,7 +1060,7 @@ module.exports = class binance extends Exchange {
|
||||
'type': uppercaseType,
|
||||
'side': side.toUpperCase (),
|
||||
};
|
||||
if (type === 'market') {
|
||||
if (uppercaseType === 'MARKET') {
|
||||
const quoteOrderQty = this.safeFloat (params, 'quoteOrderQty');
|
||||
if (quoteOrderQty !== undefined) {
|
||||
request['quoteOrderQty'] = this.costToPrecision (symbol, quoteOrderQty);
|
||||
@@ -1707,23 +1728,39 @@ module.exports = class binance extends Exchange {
|
||||
}
|
||||
const userDataStream = ((path === 'userDataStream') || (path === 'listenKey'));
|
||||
if (path === 'historicalTrades') {
|
||||
headers = {
|
||||
'X-MBX-APIKEY': this.apiKey,
|
||||
};
|
||||
if (this.apiKey) {
|
||||
headers = {
|
||||
'X-MBX-APIKEY': this.apiKey,
|
||||
};
|
||||
} else {
|
||||
throw new AuthenticationError (this.id + ' historicalTrades endpoint requires `apiKey` credential');
|
||||
}
|
||||
} else if (userDataStream) {
|
||||
// v1 special case for userDataStream
|
||||
body = this.urlencode (params);
|
||||
headers = {
|
||||
'X-MBX-APIKEY': this.apiKey,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
};
|
||||
if (this.apiKey) {
|
||||
// v1 special case for userDataStream
|
||||
body = this.urlencode (params);
|
||||
headers = {
|
||||
'X-MBX-APIKEY': this.apiKey,
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
};
|
||||
} else {
|
||||
throw new AuthenticationError (this.id + ' userDataStream endpoint requires `apiKey` credential');
|
||||
}
|
||||
}
|
||||
if ((api === 'private') || (api === 'sapi') || (api === 'wapi' && path !== 'systemStatus') || (api === 'fapiPrivate')) {
|
||||
this.checkRequiredCredentials ();
|
||||
let query = this.urlencode (this.extend ({
|
||||
'timestamp': this.nonce (),
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
}, params));
|
||||
let query = undefined;
|
||||
if ((api === 'sapi') && (path === 'asset/dust')) {
|
||||
query = this.urlencodeWithArrayRepeat (this.extend ({
|
||||
'timestamp': this.nonce (),
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
}, params));
|
||||
} else {
|
||||
query = this.urlencode (this.extend ({
|
||||
'timestamp': this.nonce (),
|
||||
'recvWindow': this.options['recvWindow'],
|
||||
}, params));
|
||||
}
|
||||
const signature = this.hmac (this.encode (query), this.encode (this.secret));
|
||||
query += '&' + 'signature=' + signature;
|
||||
headers = {
|
||||
|
||||
+9
-1
@@ -543,11 +543,19 @@ module.exports = class bitfinex extends Exchange {
|
||||
} else {
|
||||
key = 'base';
|
||||
}
|
||||
const code = market[key];
|
||||
const currency = this.safeValue (this.currencies, code);
|
||||
if (currency !== undefined) {
|
||||
const precision = this.safeInteger (currency, 'precision');
|
||||
if (precision !== undefined) {
|
||||
cost = parseFloat (this.currencyToPrecision (code, cost));
|
||||
}
|
||||
}
|
||||
return {
|
||||
'type': takerOrMaker,
|
||||
'currency': market[key],
|
||||
'rate': rate,
|
||||
'cost': parseFloat (this.currencyToPrecision (market[key], cost)),
|
||||
'cost': cost,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -33,6 +33,7 @@ module.exports = class bitfinex2 extends bitfinex {
|
||||
'fetchTickers': true,
|
||||
'fetchTradingFee': false,
|
||||
'fetchTradingFees': false,
|
||||
'fetchTransactions': false,
|
||||
'withdraw': true,
|
||||
},
|
||||
'timeframes': {
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ module.exports = class bitforex extends Exchange {
|
||||
},
|
||||
'timeframes': {
|
||||
'1m': '1min',
|
||||
'5m': 'M5',
|
||||
'5m': '5min',
|
||||
'15m': '15min',
|
||||
'30m': '30min',
|
||||
'1h': '1hour',
|
||||
@@ -46,7 +46,7 @@ module.exports = class bitforex extends Exchange {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/44310033-69e9e600-a3d8-11e8-873d-54d74d1bc4e4.jpg',
|
||||
'api': 'https://api.bitforex.com',
|
||||
'www': 'https://www.bitforex.com',
|
||||
'doc': 'https://github.com/bitforexapi/API_Docs/wiki',
|
||||
'doc': 'https://github.com/githubdev2020/API_Doc_en/wiki',
|
||||
'fees': 'https://help.bitforex.com/en_us/?cat=13',
|
||||
'referral': 'https://www.bitforex.com/en/invitationRegister?inviterId=1867438',
|
||||
},
|
||||
|
||||
+13
-2
@@ -165,8 +165,19 @@ module.exports = class btcalpha extends Exchange {
|
||||
request['limit_sell'] = limit;
|
||||
request['limit_buy'] = limit;
|
||||
}
|
||||
const reponse = await this.publicGetOrderbookPairName (this.extend (request, params));
|
||||
return this.parseOrderBook (reponse, undefined, 'buy', 'sell', 'price', 'amount');
|
||||
const response = await this.publicGetOrderbookPairName (this.extend (request, params));
|
||||
return this.parseOrderBook (response, undefined, 'buy', 'sell', 'price', 'amount');
|
||||
}
|
||||
|
||||
parseBidsAsks (bidasks, priceKey = 0, amountKey = 1) {
|
||||
const result = [];
|
||||
for (let i = 0; i < bidasks.length; i++) {
|
||||
const bidask = bidasks[i];
|
||||
if (bidask) {
|
||||
result.push (this.parseBidAsk (bidask, priceKey, amountKey));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
parseTrade (trade, market = undefined) {
|
||||
|
||||
+24
-2
@@ -28,7 +28,7 @@ module.exports = class bw extends Exchange {
|
||||
'editOrder': false,
|
||||
'fetchBalance': true,
|
||||
'fetchBidsAsks': false,
|
||||
'fetchClosedOrders': false,
|
||||
'fetchClosedOrders': true,
|
||||
'fetchCurrencies': true,
|
||||
'fetchDepositAddress': true,
|
||||
'fetchDeposits': true,
|
||||
@@ -119,6 +119,7 @@ module.exports = class bw extends Exchange {
|
||||
'exchange/entrust/controller/website/EntrustController/getUserEntrustList',
|
||||
'exchange/fund/controller/website/fundwebsitecontroller/getwithdrawaddress',
|
||||
'exchange/fund/controller/website/fundwebsitecontroller/getpayoutcoinrecord',
|
||||
'exchange/entrust/controller/website/EntrustController/getUserEntrustList',
|
||||
// the docs say that the following URLs are HTTP POST
|
||||
// in the docs header and HTTP GET in the docs body
|
||||
// the docs contradict themselves, a typo most likely
|
||||
@@ -861,6 +862,27 @@ module.exports = class bw extends Exchange {
|
||||
return this.parseOrders (orders, market, since, limit);
|
||||
}
|
||||
|
||||
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchClosedOrders() requires a symbol argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'marketId': market['id'],
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['pageSize'] = limit; // default limit is 20
|
||||
}
|
||||
if (since !== undefined) {
|
||||
request['startDateTime'] = since;
|
||||
}
|
||||
const response = await this.privateGetExchangeEntrustControllerWebsiteEntrustControllerGetUserEntrustList (this.extend (request, params));
|
||||
const data = this.safeValue (response, 'datas', {});
|
||||
const orders = this.safeValue (data, 'entrustList', []);
|
||||
return this.parseOrders (orders, market, since, limit);
|
||||
}
|
||||
|
||||
async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (symbol === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
|
||||
@@ -932,7 +954,7 @@ module.exports = class bw extends Exchange {
|
||||
const keys = Object.keys (sortedParams);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i];
|
||||
content += key + sortedParams[key];
|
||||
content += key + sortedParams[key].toString ();
|
||||
}
|
||||
} else {
|
||||
content = body;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ module.exports = class coinbaseprime extends coinbasepro {
|
||||
'urls': {
|
||||
'test': {
|
||||
'public': 'https://api-public.sandbox.prime.coinbase.com',
|
||||
'private:': 'https://api-public.sandbox.prime.coinbase.com',
|
||||
'private': 'https://api-public.sandbox.prime.coinbase.com',
|
||||
},
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/44539184-29f26e00-a70c-11e8-868f-e907fc236a7c.jpg',
|
||||
'api': {
|
||||
|
||||
+90
-16
@@ -3,7 +3,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound } = require ('./base/errors');
|
||||
const { InsufficientFunds, ArgumentsRequired, ExchangeError, InvalidOrder, InvalidAddress, AuthenticationError, NotSupported, OrderNotFound, OnMaintenance, RateLimitExceeded } = require ('./base/errors');
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -152,12 +152,14 @@ module.exports = class coinbasepro extends Exchange {
|
||||
'invalid signature': AuthenticationError,
|
||||
'Invalid Passphrase': AuthenticationError,
|
||||
'Invalid order id': InvalidOrder,
|
||||
'Private rate limit exceeded': RateLimitExceeded,
|
||||
},
|
||||
'broad': {
|
||||
'Order already done': OrderNotFound,
|
||||
'order not found': OrderNotFound,
|
||||
'price too small': InvalidOrder,
|
||||
'price too precise': InvalidOrder,
|
||||
'under maintenance': OnMaintenance,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -295,29 +297,46 @@ module.exports = class coinbasepro extends Exchange {
|
||||
return orderbook;
|
||||
}
|
||||
|
||||
async fetchTicker (symbol, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'id': market['id'],
|
||||
};
|
||||
const ticker = await this.publicGetProductsIdTicker (this.extend (request, params));
|
||||
parseTicker (ticker, market = undefined) {
|
||||
//
|
||||
// publicGetProductsIdTicker
|
||||
//
|
||||
// {
|
||||
// "trade_id":843439,
|
||||
// "price":"0.997999",
|
||||
// "size":"80.29769",
|
||||
// "time":"2020-01-28T02:13:33.012523Z",
|
||||
// "bid":"0.997094",
|
||||
// "ask":"0.998",
|
||||
// "volume":"1903188.03750000"
|
||||
// }
|
||||
//
|
||||
// publicGetProductsIdStats
|
||||
//
|
||||
// {
|
||||
// "open": "34.19000000",
|
||||
// "high": "95.70000000",
|
||||
// "low": "7.06000000",
|
||||
// "volume": "2.41000000"
|
||||
// }
|
||||
//
|
||||
const timestamp = this.parse8601 (this.safeValue (ticker, 'time'));
|
||||
const bid = this.safeFloat (ticker, 'bid');
|
||||
const ask = this.safeFloat (ticker, 'ask');
|
||||
const last = this.safeFloat (ticker, 'price');
|
||||
const symbol = (market === undefined) ? undefined : market['symbol'];
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'high': undefined,
|
||||
'low': undefined,
|
||||
'high': this.safeFloat (ticker, 'high'),
|
||||
'low': this.safeFloat (ticker, 'low'),
|
||||
'bid': bid,
|
||||
'bidVolume': undefined,
|
||||
'ask': ask,
|
||||
'askVolume': undefined,
|
||||
'vwap': undefined,
|
||||
'open': undefined,
|
||||
'open': this.safeFloat (ticker, 'open'),
|
||||
'close': last,
|
||||
'last': last,
|
||||
'previousClose': undefined,
|
||||
@@ -330,14 +349,69 @@ module.exports = class coinbasepro extends Exchange {
|
||||
};
|
||||
}
|
||||
|
||||
async fetchTicker (symbol, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const market = this.market (symbol);
|
||||
const request = {
|
||||
'id': market['id'],
|
||||
};
|
||||
// publicGetProductsIdTicker or publicGetProductsIdStats
|
||||
const method = this.safeString (this.options, 'fetchTickerMethod', 'publicGetProductsIdTicker');
|
||||
const response = await this[method] (this.extend (request, params));
|
||||
//
|
||||
// publicGetProductsIdTicker
|
||||
//
|
||||
// {
|
||||
// "trade_id":843439,
|
||||
// "price":"0.997999",
|
||||
// "size":"80.29769",
|
||||
// "time":"2020-01-28T02:13:33.012523Z",
|
||||
// "bid":"0.997094",
|
||||
// "ask":"0.998",
|
||||
// "volume":"1903188.03750000"
|
||||
// }
|
||||
//
|
||||
// publicGetProductsIdStats
|
||||
//
|
||||
// {
|
||||
// "open": "34.19000000",
|
||||
// "high": "95.70000000",
|
||||
// "low": "7.06000000",
|
||||
// "volume": "2.41000000"
|
||||
// }
|
||||
//
|
||||
return this.parseTicker (response, market);
|
||||
}
|
||||
|
||||
parseTrade (trade, market = undefined) {
|
||||
//
|
||||
// {
|
||||
// type: 'match',
|
||||
// trade_id: 82047307,
|
||||
// maker_order_id: '0f358725-2134-435e-be11-753912a326e0',
|
||||
// taker_order_id: '252b7002-87a3-425c-ac73-f5b9e23f3caf',
|
||||
// side: 'sell',
|
||||
// size: '0.00513192',
|
||||
// price: '9314.78',
|
||||
// product_id: 'BTC-USD',
|
||||
// sequence: 12038915443,
|
||||
// time: '2020-01-31T20:03:41.158814Z'
|
||||
// }
|
||||
//
|
||||
const timestamp = this.parse8601 (this.safeString2 (trade, 'time', 'created_at'));
|
||||
let symbol = undefined;
|
||||
if (market === undefined) {
|
||||
const marketId = this.safeString (trade, 'product_id');
|
||||
market = this.safeValue (this.markets_by_id, marketId);
|
||||
const marketId = this.safeString (trade, 'product_id');
|
||||
if (marketId !== undefined) {
|
||||
if (marketId in this.markets_by_id) {
|
||||
market = this.markets_by_id[marketId];
|
||||
} else {
|
||||
const [ baseId, quoteId ] = marketId.split ('-');
|
||||
const base = this.safeCurrencyCode (baseId);
|
||||
const quote = this.safeCurrencyCode (quoteId);
|
||||
symbol = base + '/' + quote;
|
||||
}
|
||||
}
|
||||
if (market) {
|
||||
if ((symbol === undefined) && (market !== undefined)) {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
let feeRate = undefined;
|
||||
@@ -861,7 +935,7 @@ module.exports = class coinbasepro extends Exchange {
|
||||
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
||||
if ((code === 400) || (code === 404)) {
|
||||
if (body[0] === '{') {
|
||||
const message = response['message'];
|
||||
const message = this.safeString (response, 'message');
|
||||
const feedback = this.id + ' ' + message;
|
||||
this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
|
||||
this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
|
||||
|
||||
-3
@@ -315,9 +315,6 @@ module.exports = class crex24 extends Exchange {
|
||||
// }
|
||||
// ]
|
||||
//
|
||||
// const log = require ('ololog').unlimited.green;
|
||||
// log (response);
|
||||
// process.exit ();
|
||||
const result = { 'info': response };
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
const balance = response[i];
|
||||
|
||||
+4
-1
@@ -444,7 +444,7 @@ module.exports = class dsx extends Exchange {
|
||||
return this.parseOrderBook (orderbook);
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
let ids = undefined;
|
||||
if (symbols === undefined) {
|
||||
@@ -461,6 +461,9 @@ module.exports = class dsx extends Exchange {
|
||||
const request = {
|
||||
'pair': ids,
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit; // default = 150, max = 2000
|
||||
}
|
||||
const response = await this.publicGetDepthPair (this.extend (request, params));
|
||||
const result = {};
|
||||
ids = Object.keys (response);
|
||||
|
||||
+23
-14
@@ -3,7 +3,7 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const Exchange = require ('./base/Exchange');
|
||||
const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance } = require ('./base/errors');
|
||||
const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded } = require ('./base/errors');
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -384,17 +384,22 @@ module.exports = class exmo extends Exchange {
|
||||
},
|
||||
},
|
||||
'exceptions': {
|
||||
'40005': AuthenticationError, // Authorization error, incorrect signature
|
||||
'40009': InvalidNonce, //
|
||||
'40015': ExchangeError, // API function do not exist
|
||||
'40016': OnMaintenance, // {"result":false,"error":"Error 40016: Maintenance work in progress"}
|
||||
'40017': AuthenticationError, // Wrong API Key
|
||||
'50052': InsufficientFunds,
|
||||
'50054': InsufficientFunds,
|
||||
'50304': OrderNotFound, // "Order was not found '123456789'" (fetching order trades for an order that does not have trades yet)
|
||||
'50173': OrderNotFound, // "Order with id X was not found." (cancelling non-existent, closed and cancelled order)
|
||||
'50319': InvalidOrder, // Price by order is less than permissible minimum for this pair
|
||||
'50321': InvalidOrder, // Price by order is more than permissible maximum for this pair
|
||||
'exact': {
|
||||
'40005': AuthenticationError, // Authorization error, incorrect signature
|
||||
'40009': InvalidNonce, //
|
||||
'40015': ExchangeError, // API function do not exist
|
||||
'40016': OnMaintenance, // {"result":false,"error":"Error 40016: Maintenance work in progress"}
|
||||
'40017': AuthenticationError, // Wrong API Key
|
||||
'50052': InsufficientFunds,
|
||||
'50054': InsufficientFunds,
|
||||
'50304': OrderNotFound, // "Order was not found '123456789'" (fetching order trades for an order that does not have trades yet)
|
||||
'50173': OrderNotFound, // "Order with id X was not found." (cancelling non-existent, closed and cancelled order)
|
||||
'50319': InvalidOrder, // Price by order is less than permissible minimum for this pair
|
||||
'50321': InvalidOrder, // Price by order is more than permissible maximum for this pair
|
||||
},
|
||||
'broad': {
|
||||
'API rate limit exceeded': RateLimitExceeded, // {"result":false,"error":"API rate limit exceeded for 99.33.55.224. Retry after 60 sec.","history":[],"begin":1579392000,"end":1579478400}
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -633,7 +638,7 @@ module.exports = class exmo extends Exchange {
|
||||
return this.parseOrderBook (result, undefined, 'bid', 'ask');
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
let ids = undefined;
|
||||
if (symbols === undefined) {
|
||||
@@ -650,6 +655,9 @@ module.exports = class exmo extends Exchange {
|
||||
const request = {
|
||||
'pair': ids,
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
const response = await this.publicGetOrderBook (this.extend (request, params));
|
||||
const result = {};
|
||||
const marketIds = Object.keys (response);
|
||||
@@ -1396,7 +1404,8 @@ module.exports = class exmo extends Exchange {
|
||||
code = (numSubParts > 1) ? errorSubParts[1] : errorSubParts[0];
|
||||
}
|
||||
const feedback = this.id + ' ' + body;
|
||||
this.throwExactlyMatchedException (this.exceptions, code, feedback);
|
||||
this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
|
||||
this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
|
||||
throw new ExchangeError (feedback);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-14
@@ -34,18 +34,18 @@ module.exports = class gateio extends Exchange {
|
||||
'fetchMyTrades': true,
|
||||
},
|
||||
'timeframes': {
|
||||
'1m': '60',
|
||||
'5m': '300',
|
||||
'10m': '600',
|
||||
'15m': '900',
|
||||
'30m': '1800',
|
||||
'1h': '3600',
|
||||
'2h': '7200',
|
||||
'4h': '14400',
|
||||
'6h': '21600',
|
||||
'12h': '43200',
|
||||
'1d': '86400',
|
||||
'1w': '604800',
|
||||
'1m': 60,
|
||||
'5m': 300,
|
||||
'10m': 600,
|
||||
'15m': 900,
|
||||
'30m': 1800,
|
||||
'1h': 3600,
|
||||
'2h': 7200,
|
||||
'4h': 14400,
|
||||
'6h': 21600,
|
||||
'12h': 43200,
|
||||
'1d': 86400,
|
||||
'1w': 604800,
|
||||
},
|
||||
'urls': {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/31784029-0313c702-b509-11e7-9ccc-bc0da6a0e435.jpg',
|
||||
@@ -165,7 +165,7 @@ module.exports = class gateio extends Exchange {
|
||||
for (let i = 0; i < markets.length; i++) {
|
||||
const market = markets[i];
|
||||
const keys = Object.keys (market);
|
||||
const id = keys[0];
|
||||
const id = this.safeString (keys, 0);
|
||||
const details = market[id];
|
||||
// all of their symbols are separated with an underscore
|
||||
// but not boe_eth_eth (BOE_ETH/ETH) which has two underscores
|
||||
@@ -731,7 +731,10 @@ module.exports = class gateio extends Exchange {
|
||||
const id = this.safeString (transaction, 'id');
|
||||
const txid = this.safeString (transaction, 'txid');
|
||||
const amount = this.safeFloat (transaction, 'amount');
|
||||
const address = this.safeString (transaction, 'address');
|
||||
let address = this.safeString (transaction, 'address');
|
||||
if (address === 'false') {
|
||||
address = undefined;
|
||||
}
|
||||
const timestamp = this.safeTimestamp (transaction, 'timestamp');
|
||||
const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
||||
const type = this.parseTransactionType (id[0]);
|
||||
|
||||
+17
@@ -87,14 +87,22 @@ module.exports = class huobipro extends Exchange {
|
||||
],
|
||||
},
|
||||
'private': {
|
||||
// todo add v2 endpoints
|
||||
// 'GET /v2/account/withdraw/quota
|
||||
// 'GET /v2/reference/currencies
|
||||
// 'GET /v2/account/deposit/address
|
||||
'get': [
|
||||
'account/accounts', // 查询当前用户的所有账户(即account-id)
|
||||
'account/accounts/{id}/balance', // 查询指定账户的余额
|
||||
'account/accounts/{sub-uid}',
|
||||
'account/history',
|
||||
'cross-margin/loan-info',
|
||||
'fee/fee-rate/get',
|
||||
'order/openOrders',
|
||||
'order/orders',
|
||||
'order/orders/{id}', // 查询某个订单详情
|
||||
'order/orders/{id}/matchresults', // 查询某个订单的成交明细
|
||||
'order/orders/getClientOrder',
|
||||
'order/history', // 查询当前委托、历史委托
|
||||
'order/matchresults', // 查询当前成交、历史成交
|
||||
'dw/withdraw-virtual/addresses', // 查询虚拟币提现地址
|
||||
@@ -104,9 +112,17 @@ module.exports = class huobipro extends Exchange {
|
||||
'points/actions',
|
||||
'points/orders',
|
||||
'subuser/aggregate-balance',
|
||||
'stable-coin/exchange_rate',
|
||||
'stable-coin/quote',
|
||||
],
|
||||
// todo add v2 endpoints
|
||||
// POST /v2/sub-user/management
|
||||
'post': [
|
||||
'futures/transfer',
|
||||
'order/batch-orders',
|
||||
'order/orders/place', // 创建并执行一个新订单 (一步下单, 推荐使用)
|
||||
'order/orders/submitCancelClientOrder',
|
||||
'order/orders/batchCancelOpenOrders',
|
||||
'order/orders', // 创建一个新的订单请求 (仅创建订单,不执行下单)
|
||||
'order/orders/{id}/place', // 执行一个订单 (仅执行已创建的订单)
|
||||
'order/orders/{id}/submitcancel', // 申请撤销一个订单请求
|
||||
@@ -120,6 +136,7 @@ module.exports = class huobipro extends Exchange {
|
||||
'dw/transfer-out/margin', // 借贷账户划出至现货账户
|
||||
'margin/orders', // 申请借贷
|
||||
'margin/orders/{id}/repay', // 归还借贷
|
||||
'stable-coin/exchange',
|
||||
'subuser/transfer',
|
||||
],
|
||||
},
|
||||
|
||||
+12
-4
@@ -71,11 +71,13 @@ module.exports = class indodax extends Exchange {
|
||||
'ATOM/IDR': { 'id': 'atom_idr', 'symbol': 'ATOM/IDR', 'base': 'ATOM', 'quote': 'IDR', 'baseId': 'atom', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'BAT/IDR': { 'id': 'bat_idr', 'symbol': 'BAT/IDR', 'base': 'BAT', 'quote': 'IDR', 'baseId': 'bat', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'BCD/IDR': { 'id': 'bcd_idr', 'symbol': 'BCD/IDR', 'base': 'BCD', 'quote': 'IDR', 'baseId': 'bcd', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'BCH/IDR': { 'id': 'bch_idr', 'symbol': 'BCH/IDR', 'base': 'BCH', 'quote': 'IDR', 'baseId': 'bch', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined }}},
|
||||
'BSV/IDR': { 'id': 'bsv_idr', 'symbol': 'BSV/IDR', 'base': 'BSV', 'quote': 'IDR', 'baseId': 'bsv', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined }}},
|
||||
'BCH/IDR': { 'id': 'bchabc_idr', 'symbol': 'BCH/IDR', 'base': 'BCH', 'quote': 'IDR', 'baseId': 'bchabc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined }}},
|
||||
'BSV/IDR': { 'id': 'bchsv_idr', 'symbol': 'BSV/IDR', 'base': 'BSV', 'quote': 'IDR', 'baseId': 'bchsv', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined }}},
|
||||
'BNB/IDR': { 'id': 'bnb_idr', 'symbol': 'BNB/IDR', 'base': 'BNB', 'quote': 'IDR', 'baseId': 'bnb', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined }}},
|
||||
'BTG/IDR': { 'id': 'btg_idr', 'symbol': 'BTG/IDR', 'base': 'BTG', 'quote': 'IDR', 'baseId': 'btg', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'BTS/IDR': { 'id': 'bts_idr', 'symbol': 'BTS/IDR', 'base': 'BTS', 'quote': 'IDR', 'baseId': 'bts', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'BTT/IDR': { 'id': 'btt_idr', 'symbol': 'BTT/IDR', 'base': 'BTT', 'quote': 'IDR', 'baseId': 'btt', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1000, 'max': undefined }}},
|
||||
'COAL/IDR': { 'id': 'coal_idr', 'symbol': 'COAL/IDR', 'base': 'COAL', 'quote': 'IDR', 'baseId': 'coal', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 50, 'max': undefined }}},
|
||||
'CRO/IDR': { 'id': 'cro_idr', 'symbol': 'CRO/IDR', 'base': 'CRO', 'quote': 'IDR', 'baseId': 'cro', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'DASH/IDR': { 'id': 'drk_idr', 'symbol': 'DASH/IDR', 'base': 'DASH', 'quote': 'IDR', 'baseId': 'drk', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'DAX/IDR': { 'id': 'dax_idr', 'symbol': 'DAX/IDR', 'base': 'DAX', 'quote': 'IDR', 'baseId': 'dax', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
@@ -85,15 +87,18 @@ module.exports = class indodax extends Exchange {
|
||||
'ETC/IDR': { 'id': 'etc_idr', 'symbol': 'ETC/IDR', 'base': 'ETC', 'quote': 'IDR', 'baseId': 'etc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'GARD/IDR': { 'id': 'gard_idr', 'symbol': 'GARD/IDR', 'base': 'GARD', 'quote': 'IDR', 'baseId': 'gard', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'GSC/IDR': { 'id': 'gsc_idr', 'symbol': 'GSC/IDR', 'base': 'GSC', 'quote': 'IDR', 'baseId': 'gsc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'GXC/IDR': { 'id': 'gxc_idr', 'symbol': 'GXC/IDR', 'base': 'GXC', 'quote': 'IDR', 'baseId': 'gxc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'GXC/IDR': { 'id': 'gxs_idr', 'symbol': 'GXC/IDR', 'base': 'GXC', 'quote': 'IDR', 'baseId': 'gxs', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'HPB/IDR': { 'id': 'hpb_idr', 'symbol': 'HPB/IDR', 'base': 'HPB', 'quote': 'IDR', 'baseId': 'hpb', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
'IGNIS/IDR': { 'id': 'ignis_idr', 'symbol': 'IGNIS/IDR', 'base': 'IGNIS', 'quote': 'IDR', 'baseId': 'ignis', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1, 'max': undefined }}},
|
||||
'INX/IDR': { 'id': 'inx_idr', 'symbol': 'INX/IDR', 'base': 'INX', 'quote': 'IDR', 'baseId': 'inx', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1, 'max': undefined }}},
|
||||
'IOTA/IDR': { 'id': 'iota_idr', 'symbol': 'IOTA/IDR', 'base': 'IOTA', 'quote': 'IDR', 'baseId': 'iota', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
'LINK/IDR': { 'id': 'link_idr', 'symbol': 'LINK/IDR', 'base': 'LINK', 'quote': 'IDR', 'baseId': 'link', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1, 'max': undefined }}},
|
||||
'LTC/IDR': { 'id': 'ltc_idr', 'symbol': 'LTC/IDR', 'base': 'LTC', 'quote': 'IDR', 'baseId': 'ltc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'MBL/IDR': { 'id': 'mbl_idr', 'symbol': 'MBL/IDR', 'base': 'MBL', 'quote': 'IDR', 'baseId': 'mbl', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'NEO/IDR': { 'id': 'neo_idr', 'symbol': 'NEO/IDR', 'base': 'NEO', 'quote': 'IDR', 'baseId': 'neo', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'NPXS/IDR': { 'id': 'npxs_idr', 'symbol': 'NPXS/IDR', 'base': 'NPXS', 'quote': 'IDR', 'baseId': 'npxs', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1, 'max': undefined }}},
|
||||
'NXT/IDR': { 'id': 'nxt_idr', 'symbol': 'NXT/IDR', 'base': 'NXT', 'quote': 'IDR', 'baseId': 'nxt', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
'OKB/IDR': { 'id': 'okb_idr', 'symbol': 'OKB/IDR', 'base': 'OKB', 'quote': 'IDR', 'baseId': 'okb', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.5, 'max': undefined }}},
|
||||
'ONT/IDR': { 'id': 'ont_idr', 'symbol': 'ONT/IDR', 'base': 'ONT', 'quote': 'IDR', 'baseId': 'ont', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
'PXG/IDR': { 'id': 'pxg_idr', 'symbol': 'PXG/IDR', 'base': 'PXG', 'quote': 'IDR', 'baseId': 'pxg', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
'QTUM/IDR': { 'id': 'qtum_idr', 'symbol': 'QTUM/IDR', 'base': 'QTUM', 'quote': 'IDR', 'baseId': 'qtum', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 5, 'max': undefined }}},
|
||||
@@ -105,13 +110,16 @@ module.exports = class indodax extends Exchange {
|
||||
'USDC/IDR': { 'id': 'usdc_idr', 'symbol': 'USDC/IDR', 'base': 'USDC', 'quote': 'IDR', 'baseId': 'usdc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'USDT/IDR': { 'id': 'usdt_idr', 'symbol': 'USDT/IDR', 'base': 'USDT', 'quote': 'IDR', 'baseId': 'usdt', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'VEX/IDR': { 'id': 'vex_idr', 'symbol': 'VEX/IDR', 'base': 'VEX', 'quote': 'IDR', 'baseId': 'vex', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': undefined, 'max': undefined }}},
|
||||
'VIDY/IDR': { 'id': 'vidy_idr', 'symbol': 'VIDY/IDR', 'base': 'VIDY', 'quote': 'IDR', 'baseId': 'vidy', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 100, 'max': undefined }}},
|
||||
'WAVES/IDR': { 'id': 'waves_idr', 'symbol': 'WAVES/IDR', 'base': 'WAVES', 'quote': 'IDR', 'baseId': 'waves', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'XEM/IDR': { 'id': 'nem_idr', 'symbol': 'XEM/IDR', 'base': 'XEM', 'quote': 'IDR', 'baseId': 'nem', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 1, 'max': undefined }}},
|
||||
'XLM/IDR': { 'id': 'str_idr', 'symbol': 'XLM/IDR', 'base': 'XLM', 'quote': 'IDR', 'baseId': 'str', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 20, 'max': undefined }}},
|
||||
'XDCE/IDR': { 'id': 'xdce_idr', 'symbol': 'XDCE/IDR', 'base': 'XDCE', 'quote': 'IDR', 'baseId': 'xdce', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 10, 'max': undefined }}},
|
||||
'XMR/IDR': { 'id': 'xmr_idr', 'symbol': 'XMR/IDR', 'base': 'XMR', 'quote': 'IDR', 'baseId': 'xmr', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'XRP/IDR': { 'id': 'xrp_idr', 'symbol': 'XRP/IDR', 'base': 'XRP', 'quote': 'IDR', 'baseId': 'xrp', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 10, 'max': undefined }}},
|
||||
'XZC/IDR': { 'id': 'xzc_idr', 'symbol': 'XZC/IDR', 'base': 'XZC', 'quote': 'IDR', 'baseId': 'xzc', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'VSYS/IDR': { 'id': 'vsys_idr', 'symbol': 'VSYS/IDR', 'base': 'VSYS', 'quote': 'IDR', 'baseId': 'vsys', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.1, 'max': undefined }}},
|
||||
'ZEC/IDR': { 'id': 'zec_idr', 'symbol': 'ZEC/IDR', 'base': 'ZEC', 'quote': 'IDR', 'baseId': 'zec', 'quoteId': 'idr', 'precision': { 'amount': 8, 'price': 0 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
// BTC markets
|
||||
'BTS/BTC': { 'id': 'bts_btc', 'symbol': 'BTS/BTC', 'base': 'BTS', 'quote': 'BTC', 'baseId': 'bts', 'quoteId': 'btc', 'precision': { 'amount': 8, 'price': 8 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
'DASH/BTC': { 'id': 'drk_btc', 'symbol': 'DASH/BTC', 'base': 'DASH', 'quote': 'BTC', 'baseId': 'drk', 'quoteId': 'btc', 'precision': { 'amount': 8, 'price': 6 }, 'limits': { 'amount': { 'min': 0.01, 'max': undefined }}},
|
||||
@@ -279,7 +287,7 @@ module.exports = class indodax extends Exchange {
|
||||
let status = this.safeString (order, 'status', 'open');
|
||||
if (status === 'filled') {
|
||||
status = 'closed';
|
||||
} else if (status === 'calcelled') {
|
||||
} else if (status === 'cancelled') {
|
||||
status = 'canceled';
|
||||
}
|
||||
let symbol = undefined;
|
||||
|
||||
+9
-9
@@ -38,15 +38,15 @@ module.exports = class kraken extends Exchange {
|
||||
},
|
||||
'marketsByAltname': {},
|
||||
'timeframes': {
|
||||
'1m': '1',
|
||||
'5m': '5',
|
||||
'15m': '15',
|
||||
'30m': '30',
|
||||
'1h': '60',
|
||||
'4h': '240',
|
||||
'1d': '1440',
|
||||
'1w': '10080',
|
||||
'2w': '21600',
|
||||
'1m': 1,
|
||||
'5m': 5,
|
||||
'15m': 15,
|
||||
'30m': 30,
|
||||
'1h': 60,
|
||||
'4h': 240,
|
||||
'1d': 1440,
|
||||
'1w': 10080,
|
||||
'2w': 21600,
|
||||
},
|
||||
'urls': {
|
||||
'logo': 'https://user-images.githubusercontent.com/1294454/27766599-22709304-5ede-11e7-9de1-9f33732e1509.jpg',
|
||||
|
||||
+54
-20
@@ -15,7 +15,7 @@ module.exports = class kucoin extends Exchange {
|
||||
'countries': [ 'SC' ],
|
||||
'rateLimit': 334,
|
||||
'version': 'v2',
|
||||
'certified': true,
|
||||
'certified': false,
|
||||
'comment': 'Platform 2.0',
|
||||
'has': {
|
||||
'fetchTime': true,
|
||||
@@ -368,24 +368,47 @@ module.exports = class kucoin extends Exchange {
|
||||
parseTicker (ticker, market = undefined) {
|
||||
//
|
||||
// {
|
||||
// 'buy': '0.00001168',
|
||||
// 'changePrice': '-0.00000018',
|
||||
// 'changeRate': '-0.0151',
|
||||
// 'datetime': 1550661146316,
|
||||
// 'high': '0.0000123',
|
||||
// 'last': '0.00001169',
|
||||
// 'low': '0.00001159',
|
||||
// 'sell': '0.00001182',
|
||||
// 'symbol': 'LOOM-BTC',
|
||||
// 'vol': '44399.5669'
|
||||
// symbol: "ETH-BTC",
|
||||
// high: "0.019518",
|
||||
// vol: "7997.82836194",
|
||||
// last: "0.019329",
|
||||
// low: "0.019",
|
||||
// buy: "0.019329",
|
||||
// sell: "0.01933",
|
||||
// changePrice: "-0.000139",
|
||||
// time: 1580553706304,
|
||||
// averagePrice: "0.01926386",
|
||||
// changeRate: "-0.0071",
|
||||
// volValue: "154.40791568183474"
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// "trading": true,
|
||||
// "symbol": "KCS-BTC",
|
||||
// "buy": 0.00011,
|
||||
// "sell": 0.00012,
|
||||
// "sort": 100,
|
||||
// "volValue": 3.13851792584, //total
|
||||
// "baseCurrency": "KCS",
|
||||
// "market": "BTC",
|
||||
// "quoteCurrency": "BTC",
|
||||
// "symbolCode": "KCS-BTC",
|
||||
// "datetime": 1548388122031,
|
||||
// "high": 0.00013,
|
||||
// "vol": 27514.34842,
|
||||
// "low": 0.0001,
|
||||
// "changePrice": -1.0e-5,
|
||||
// "changeRate": -0.0769,
|
||||
// "lastTradedPrice": 0.00012,
|
||||
// "board": 0,
|
||||
// "mark": 0
|
||||
// }
|
||||
//
|
||||
let percentage = this.safeFloat (ticker, 'changeRate');
|
||||
if (percentage !== undefined) {
|
||||
percentage = percentage * 100;
|
||||
}
|
||||
const last = this.safeFloat (ticker, 'last');
|
||||
const average = this.safeFloat (ticker, 'averagePrice');
|
||||
const last = this.safeFloat2 (ticker, 'last', 'lastTradedPrice');
|
||||
let symbol = undefined;
|
||||
const marketId = this.safeString (ticker, 'symbol');
|
||||
if (marketId !== undefined) {
|
||||
@@ -404,10 +427,11 @@ module.exports = class kucoin extends Exchange {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
}
|
||||
const timestamp = this.safeInteger2 (ticker, 'time', 'datetime');
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'timestamp': undefined,
|
||||
'datetime': undefined,
|
||||
'timestamp': timestamp,
|
||||
'datetime': this.iso8601 (timestamp),
|
||||
'high': this.safeFloat (ticker, 'high'),
|
||||
'low': this.safeFloat (ticker, 'low'),
|
||||
'bid': this.safeFloat (ticker, 'buy'),
|
||||
@@ -421,7 +445,7 @@ module.exports = class kucoin extends Exchange {
|
||||
'previousClose': undefined,
|
||||
'change': this.safeFloat (ticker, 'changePrice'),
|
||||
'percentage': percentage,
|
||||
'average': average,
|
||||
'average': this.safeFloat (ticker, 'averagePrice'),
|
||||
'baseVolume': this.safeFloat (ticker, 'vol'),
|
||||
'quoteVolume': this.safeFloat (ticker, 'volValue'),
|
||||
'info': ticker,
|
||||
@@ -995,6 +1019,19 @@ module.exports = class kucoin extends Exchange {
|
||||
// "time":1548848575203567174
|
||||
// }
|
||||
//
|
||||
// {
|
||||
// sequence: '1568787654360',
|
||||
// symbol: 'BTC-USDT',
|
||||
// side: 'buy',
|
||||
// size: '0.00536577',
|
||||
// price: '9345',
|
||||
// takerOrderId: '5e356c4a9f1a790008f8d921',
|
||||
// time: '1580559434436443257',
|
||||
// type: 'match',
|
||||
// makerOrderId: '5e356bffedf0010008fa5d7f',
|
||||
// tradeId: '5e356c4aeefabd62c62a1ece'
|
||||
// }
|
||||
//
|
||||
// fetchMyTrades (private) v2
|
||||
//
|
||||
// {
|
||||
@@ -1065,10 +1102,7 @@ module.exports = class kucoin extends Exchange {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
}
|
||||
let id = this.safeString2 (trade, 'tradeId', 'id');
|
||||
if (id !== undefined) {
|
||||
id = id.toString ();
|
||||
}
|
||||
const id = this.safeString2 (trade, 'tradeId', 'id');
|
||||
const orderId = this.safeString (trade, 'orderId');
|
||||
const takerOrMaker = this.safeString (trade, 'liquidity');
|
||||
const amount = this.safeFloat2 (trade, 'size', 'amount');
|
||||
|
||||
+7
-12
@@ -109,12 +109,9 @@ module.exports = class poloniex extends Exchange {
|
||||
},
|
||||
'fees': {
|
||||
'trading': {
|
||||
// https://github.com/ccxt/ccxt/issues/6064
|
||||
// starting from October 21, 2019 17:00 UTC
|
||||
// all spot trading fees will be reduced to 0.00%
|
||||
// until December 31, 2019 23:59 UTC
|
||||
'maker': 0.0,
|
||||
'taker': 0.0,
|
||||
// starting from Jan 8 2020
|
||||
'maker': 0.0009,
|
||||
'taker': 0.0009,
|
||||
},
|
||||
'funding': {},
|
||||
},
|
||||
@@ -325,16 +322,14 @@ module.exports = class poloniex extends Exchange {
|
||||
return orderbook;
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
const request = {
|
||||
'currencyPair': 'all',
|
||||
};
|
||||
//
|
||||
// if (limit !== undefined) {
|
||||
// request['depth'] = limit; // 100
|
||||
// }
|
||||
//
|
||||
if (limit !== undefined) {
|
||||
request['depth'] = limit; // 100
|
||||
}
|
||||
const response = await this.publicGetReturnOrderBook (this.extend (request, params));
|
||||
const marketIds = Object.keys (response);
|
||||
const result = {};
|
||||
|
||||
+107
-32
@@ -35,6 +35,7 @@ module.exports = class stex extends Exchange {
|
||||
'fetchDeposits': true,
|
||||
'fetchWithdrawals': true,
|
||||
'withdraw': true,
|
||||
'fetchFundingFees': true,
|
||||
},
|
||||
'version': 'v3',
|
||||
'urls': {
|
||||
@@ -499,6 +500,15 @@ module.exports = class stex extends Exchange {
|
||||
symbol = market['symbol'];
|
||||
}
|
||||
const last = this.safeFloat (ticker, 'last');
|
||||
const open = this.safeFloat (ticker, 'open');
|
||||
let change = undefined;
|
||||
let percentage = undefined;
|
||||
if (last !== undefined) {
|
||||
if (open !== undefined) {
|
||||
change = last - open;
|
||||
percentage = ((100 / open) * last) - 100;
|
||||
}
|
||||
}
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'timestamp': timestamp,
|
||||
@@ -510,12 +520,12 @@ module.exports = class stex extends Exchange {
|
||||
'ask': this.safeFloat (ticker, 'ask'),
|
||||
'askVolume': undefined,
|
||||
'vwap': undefined,
|
||||
'open': this.safeFloat (ticker, 'open'),
|
||||
'open': open,
|
||||
'close': last,
|
||||
'last': last,
|
||||
'previousClose': undefined, // previous day close
|
||||
'change': undefined,
|
||||
'percentage': undefined,
|
||||
'change': change,
|
||||
'percentage': percentage,
|
||||
'average': undefined,
|
||||
'baseVolume': this.safeFloat (ticker, 'volumeQuote'),
|
||||
'quoteVolume': this.safeFloat (ticker, 'volume'),
|
||||
@@ -1511,7 +1521,7 @@ module.exports = class stex extends Exchange {
|
||||
if ((code === undefined) && (currency !== undefined)) {
|
||||
code = currency['code'];
|
||||
}
|
||||
const type = ('depositId' in transaction) ? 'deposit' : 'withdrawal';
|
||||
const type = ('deposit_status_id' in transaction) ? 'deposit' : 'withdrawal';
|
||||
const amount = this.safeFloat (transaction, 'amount');
|
||||
const status = this.parseTransactionStatus (this.safeStringLower (transaction, 'status'));
|
||||
const timestamp = this.safeTimestamp2 (transaction, 'timestamp', 'created_ts');
|
||||
@@ -1549,21 +1559,20 @@ module.exports = class stex extends Exchange {
|
||||
}
|
||||
|
||||
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (code === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchDeposits() requires a currency code argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
'currencyTypeName': currency['name'],
|
||||
// 'pageSize': limit, // documented as required, but it works without it
|
||||
// 'pageNum': 0, // also works without it, most likely a typo in the docs
|
||||
// 'sort': 1, // 1 = asc, 0 = desc
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['pageSize'] = limit; // default 50
|
||||
let currency = undefined;
|
||||
const request = {};
|
||||
if (code !== undefined) {
|
||||
currency = this.currency (code);
|
||||
request['currencyId'] = currency['id'];
|
||||
}
|
||||
const response = await this.privatePostExchangeFundControllerWebsiteFundcontrollerGetPayinCoinRecord (this.extend (request, params));
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
if (since !== undefined) {
|
||||
request['timeStart'] = since;
|
||||
}
|
||||
const response = await this.profileGetDeposits (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "success": true,
|
||||
@@ -1583,31 +1592,35 @@ module.exports = class stex extends Exchange {
|
||||
// "status_color": "#BC3D51",
|
||||
// "created_at": "2018-11-28 12:32:08",
|
||||
// "timestamp": "1543409389",
|
||||
// "confirmations": "1 of 2"
|
||||
// "confirmations": "1 of 2",
|
||||
// "protocol_specific_settings": {
|
||||
// "protocol_name": "Tether OMNI",
|
||||
// "protocol_id": 10,
|
||||
// "block_explorer_url": "https://omniexplorer.info/search/"
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const deposits = this.safeValue (response, 'datas', {});
|
||||
const deposits = this.safeValue (response, 'data', []);
|
||||
return this.parseTransactions (deposits, code, since, limit);
|
||||
}
|
||||
|
||||
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
||||
if (code === undefined) {
|
||||
throw new ArgumentsRequired (this.id + ' fetchWithdrawals() requires a currency code argument');
|
||||
}
|
||||
await this.loadMarkets ();
|
||||
const currency = this.currency (code);
|
||||
const request = {
|
||||
'currencyId': currency['id'],
|
||||
// 'pageSize': limit, // documented as required, but it works without it
|
||||
// 'pageIndex': 0, // also works without it, most likely a typo in the docs
|
||||
// 'tab': 'all', // all, wait (submitted, not audited), success (auditing passed), fail (auditing failed), cancel (canceled by user)
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['pageSize'] = limit; // default 50
|
||||
let currency = undefined;
|
||||
const request = {};
|
||||
if (code !== undefined) {
|
||||
currency = this.currency (code);
|
||||
request['currencyId'] = currency['id'];
|
||||
}
|
||||
const response = await this.privateGetExchangeFundControllerWebsiteFundwebsitecontrollerGetpayoutcoinrecord (this.extend (request, params));
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
if (since !== undefined) {
|
||||
request['timeStart'] = since;
|
||||
}
|
||||
const response = await this.profileGetWithdrawals (this.extend (request, params));
|
||||
//
|
||||
// {
|
||||
// "success": true,
|
||||
@@ -1638,6 +1651,11 @@ module.exports = class stex extends Exchange {
|
||||
// "protocol_id": 10,
|
||||
// "protocol_name": "Tether OMNI",
|
||||
// "supports_new_address_creation": false
|
||||
// },
|
||||
// "protocol_specific_settings": {
|
||||
// "protocol_name": "Tether OMNI",
|
||||
// "protocol_id": 10,
|
||||
// "block_explorer_url": "https://omniexplorer.info/search/"
|
||||
// }
|
||||
// }
|
||||
// ]
|
||||
@@ -1699,6 +1717,63 @@ module.exports = class stex extends Exchange {
|
||||
return this.parseTransaction (data, currency);
|
||||
}
|
||||
|
||||
async fetchFundingFees (codes = undefined, params = {}) {
|
||||
const response = await this.publicGetCurrencies (params);
|
||||
//
|
||||
// {
|
||||
// "success": true,
|
||||
// "data": [
|
||||
// {
|
||||
// "id": 1,
|
||||
// "code": "BTC",
|
||||
// "name": "Bitcoin",
|
||||
// "active": true,
|
||||
// "delisted": false,
|
||||
// "precision": 8,
|
||||
// "minimum_tx_confirmations": 24,
|
||||
// "minimum_withdrawal_amount": "0.009",
|
||||
// "minimum_deposit_amount": "0.000003",
|
||||
// "deposit_fee_currency_id": 1,
|
||||
// "deposit_fee_currency_code": "ETH",
|
||||
// "deposit_fee_const": "0.00001",
|
||||
// "deposit_fee_percent": "0",
|
||||
// "withdrawal_fee_currency_id": 1,
|
||||
// "withdrawal_fee_currency_code": "ETH",
|
||||
// "withdrawal_fee_const": "0.0015",
|
||||
// "withdrawal_fee_percent": "0",
|
||||
// "withdrawal_limit": "string",
|
||||
// "block_explorer_url": "https://blockchain.info/tx/",
|
||||
// "protocol_specific_settings": [
|
||||
// {
|
||||
// "protocol_name": "Tether OMNI",
|
||||
// "protocol_id": 10,
|
||||
// "active": true,
|
||||
// "withdrawal_fee_currency_id": 1,
|
||||
// "withdrawal_fee_const": 0.002,
|
||||
// "withdrawal_fee_percent": 0,
|
||||
// "block_explorer_url": "https://omniexplorer.info/search/"
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
//
|
||||
const data = this.safeValue (response, 'data', []);
|
||||
const withdrawFees = {};
|
||||
const depositFees = {};
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const id = this.safeString (data[i], 'id');
|
||||
const code = this.safeCurrencyCode (id);
|
||||
withdrawFees[code] = this.safeFloat (data[i], 'withdrawal_fee_const');
|
||||
depositFees[code] = this.safeFloat (data[i], 'deposit_fee_const');
|
||||
}
|
||||
return {
|
||||
'withdraw': withdrawFees,
|
||||
'deposit': depositFees,
|
||||
'info': response,
|
||||
};
|
||||
}
|
||||
|
||||
handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
||||
if (response === undefined) {
|
||||
return; // fallback to default error handler
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
'use strict'
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const log = require ('ololog')
|
||||
, chai = require ('chai')
|
||||
, assert = chai.assert
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
module.exports = (exchange, balance, method) => {
|
||||
|
||||
let currencies = [
|
||||
'USD',
|
||||
'CNY',
|
||||
'EUR',
|
||||
'BTC',
|
||||
'ETH',
|
||||
'JPY',
|
||||
'LTC',
|
||||
'DASH',
|
||||
'DOGE',
|
||||
'UAH',
|
||||
'RUB',
|
||||
'XRP',
|
||||
]
|
||||
|
||||
// log.yellow (balance)
|
||||
|
||||
assert (typeof balance['total'] === 'object')
|
||||
assert (typeof balance['free'] === 'object')
|
||||
assert (typeof balance['used'] === 'object')
|
||||
|
||||
for (let currency of Object.keys (balance['total'])) {
|
||||
let total = balance['total'][currency]
|
||||
let free = balance['free'][currency]
|
||||
let used = balance['used'][currency]
|
||||
if (total !== undefined && free !== undefined && used !== undefined) {
|
||||
assert (total === free + used, 'free and used do not sum to total ' + exchange.id)
|
||||
}
|
||||
}
|
||||
|
||||
let result = currencies
|
||||
.filter (currency => (currency in balance) &&
|
||||
(balance[currency]['total'] !== undefined))
|
||||
|
||||
if (result.length > 0) {
|
||||
result = result.map (currency => currency + ': ' + balance[currency]['total'])
|
||||
if (exchange.currencies.length > result.length)
|
||||
result = result.join (', ') + ' + more...'
|
||||
else
|
||||
result = result.join (', ')
|
||||
|
||||
} else {
|
||||
|
||||
result = 'zero balance'
|
||||
}
|
||||
|
||||
log (result)
|
||||
|
||||
}
|
||||
+7
-62
@@ -2,15 +2,12 @@
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const log = require ('ololog')
|
||||
, ansi = require ('ansicolor').nice
|
||||
, chai = require ('chai')
|
||||
, expect = chai.expect
|
||||
, assert = chai.assert
|
||||
const log = require ('ololog')
|
||||
, testBalance = require ('./test.balance.js')
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
module.exports = async (exchange, symbol) => {
|
||||
module.exports = async (exchange) => {
|
||||
|
||||
if (!(exchange.has.fetchBalance)) {
|
||||
log (exchange.id.green, ' does not have fetchBalance')
|
||||
@@ -19,61 +16,9 @@ module.exports = async (exchange, symbol) => {
|
||||
|
||||
log ('fetching balance...')
|
||||
|
||||
let balance = await exchange.fetchBalance ()
|
||||
const response = await exchange.fetchBalance ()
|
||||
|
||||
let currencies = [
|
||||
'USD',
|
||||
'CNY',
|
||||
'EUR',
|
||||
'BTC',
|
||||
'ETH',
|
||||
'JPY',
|
||||
'LTC',
|
||||
'DASH',
|
||||
'DOGE',
|
||||
'UAH',
|
||||
'RUB',
|
||||
'XRP',
|
||||
]
|
||||
testBalance (exchange, response)
|
||||
|
||||
// log.yellow (balance)
|
||||
|
||||
assert (typeof balance['total'] === 'object')
|
||||
assert (typeof balance['free'] === 'object')
|
||||
assert (typeof balance['used'] === 'object')
|
||||
|
||||
if ('info' in balance) {
|
||||
for (let currency of Object.keys (balance['total'])) {
|
||||
let total = balance['total'][currency]
|
||||
let free = balance['free'][currency]
|
||||
let used = balance['used'][currency]
|
||||
if (total !== undefined && free !== undefined && used !== undefined) {
|
||||
assert (total === free + used, 'free and used do not sum to total ' + exchange.id)
|
||||
}
|
||||
}
|
||||
|
||||
let result = currencies
|
||||
.filter (currency => (currency in balance) &&
|
||||
(balance[currency]['total'] !== undefined))
|
||||
|
||||
if (result.length > 0) {
|
||||
result = result.map (currency => currency + ': ' + balance[currency]['total'])
|
||||
if (exchange.currencies.length > result.length)
|
||||
result = result.join (', ') + ' + more...'
|
||||
else
|
||||
result = result.join (', ')
|
||||
|
||||
} else {
|
||||
|
||||
result = 'zero balance'
|
||||
}
|
||||
|
||||
log (result)
|
||||
|
||||
} else {
|
||||
|
||||
log (exchange.omit (balance, 'info'))
|
||||
}
|
||||
|
||||
return balance
|
||||
return response
|
||||
}
|
||||
+1
@@ -14,6 +14,7 @@ const log = require ('ololog')
|
||||
module.exports = async (exchange, symbol) => {
|
||||
|
||||
const skippedExchanges = [
|
||||
'btcalpha', // issue with 404 on a documented endpoint https://travis-ci.org/ccxt/ccxt/builds/643930431#L2213
|
||||
'bitmex', // an issue with null values,to be resolved later
|
||||
'cex',
|
||||
'okex',
|
||||
|
||||
+3
-5
@@ -17,11 +17,9 @@ const printOrderBookOneLiner = (orderbook, method, symbol) => {
|
||||
|
||||
log (symbol.toString ().green,
|
||||
method,
|
||||
orderbook['datetime'],
|
||||
'bid: ' + ((bids.length > 0) ? bids[0][0] : 'N/A'),
|
||||
'bidVolume: ' + ((bids.length > 0) ? bids[0][1] : 'N/A'),
|
||||
'ask: ' + ((asks.length > 0) ? asks[0][0] : 'N/A'),
|
||||
'askVolume: ' + ((asks.length > 0) ? asks[0][1] : 'N/A'))
|
||||
orderbook['nonce'] || orderbook['datetime'],
|
||||
bids.length, 'bids:', bids[0],
|
||||
asks.length, 'asks:', asks[0])
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ module.exports = (exchange, ticker, method, symbol) => {
|
||||
assert (!('first' in ticker), '`first` field leftover in ' + exchange.id)
|
||||
assert (ticker['last'] === ticker['close'], '`last` != `close` in ' + exchange.id)
|
||||
|
||||
// log (ticker)
|
||||
log (ticker['datetime'], exchange.id, method, ticker['symbol'].green, ticker['last'])
|
||||
|
||||
keys.forEach (key => assert (key in ticker))
|
||||
|
||||
|
||||
+3
@@ -29,6 +29,9 @@ assert (exchange.parse8601 ('1986-04-26T01:23:47.000Z') === 514862627000);
|
||||
assert (exchange.parse8601 ('1986-04-26T01:23:47.559Z') === 514862627559);
|
||||
assert (exchange.parse8601 ('1986-04-26T01:23:47.062Z') === 514862627062);
|
||||
|
||||
assert (exchange.parse8601 ('1986-04-26T01:23:47.06Z') === 514862627060);
|
||||
assert (exchange.parse8601 ('1986-04-26T01:23:47.6Z') === 514862627600);
|
||||
|
||||
assert (exchange.parse8601 ('1977-13-13T00:00:00.000Z') === undefined);
|
||||
assert (exchange.parse8601 ('1986-04-26T25:71:47.000Z') === undefined);
|
||||
|
||||
|
||||
+2
@@ -134,6 +134,8 @@ assert (decimalToPrecision ('0.098765', ROUND, 1, SIGNIFICANT_DIGITS, PAD_WITH_Z
|
||||
assert (decimalToPrecision ('0', ROUND, 0, SIGNIFICANT_DIGITS) === '0');
|
||||
assert (decimalToPrecision ('-0.123', ROUND, 0, SIGNIFICANT_DIGITS) === '0');
|
||||
|
||||
assert (decimalToPrecision ('0.00000044', ROUND, 5, SIGNIFICANT_DIGITS) === '0.00000044');
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// testDecimalToPrecisionRoundingToTickSize
|
||||
|
||||
|
||||
+3
-8
@@ -9,13 +9,11 @@ const debug = process.argv.includes ('--debug') || false
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
const asTable = require ('as-table')
|
||||
, util = require ('util')
|
||||
, log = require ('ololog')
|
||||
, ansi = require ('ansicolor').nice
|
||||
, fs = require ('fs')
|
||||
, ccxt = require ('../../ccxt.js')
|
||||
, chai = require ('chai')
|
||||
, expect = chai.expect
|
||||
, assert = chai.assert
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
@@ -82,14 +80,12 @@ Object.keys (errors)
|
||||
const keysGlobal = 'keys.json'
|
||||
const keysLocal = 'keys.local.json'
|
||||
|
||||
let keysFile = fs.existsSync (keysLocal) ? keysLocal : keysGlobal
|
||||
const keysFile = fs.existsSync (keysLocal) ? keysLocal : keysGlobal
|
||||
// eslint-disable-next-line import/no-dynamic-require
|
||||
let settings = require (__dirname + '/../../' + keysFile)[exchangeId]
|
||||
const settings = require (__dirname + '/../../' + keysFile)[exchangeId]
|
||||
|
||||
if (settings) {
|
||||
const keys = Object.keys (settings)
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
const key = keys[i]
|
||||
for (const key in settings) {
|
||||
if (settings[key]) {
|
||||
settings[key] = ccxt.deepExtend (exchange[key] || {}, settings[key])
|
||||
}
|
||||
@@ -224,7 +220,6 @@ let testExchange = async exchange => {
|
||||
|
||||
await loadExchange (exchange)
|
||||
|
||||
let delay = exchange.rateLimit
|
||||
let symbol = exchange.symbols[0]
|
||||
const symbols = [
|
||||
'BTC/USD',
|
||||
|
||||
+8
-2
@@ -281,7 +281,7 @@ module.exports = class tidex extends Exchange {
|
||||
return this.parseOrderBook (orderbook);
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
let ids = undefined;
|
||||
if (symbols === undefined) {
|
||||
@@ -298,6 +298,9 @@ module.exports = class tidex extends Exchange {
|
||||
const request = {
|
||||
'pair': ids,
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit; // default = 150, max = 2000
|
||||
}
|
||||
const response = await this.publicGetDepthPair (this.extend (request, params));
|
||||
const result = {};
|
||||
ids = Object.keys (response);
|
||||
@@ -324,10 +327,13 @@ module.exports = class tidex extends Exchange {
|
||||
// sell: 0.03377798,
|
||||
// updated: 1537522009 }
|
||||
//
|
||||
const timestamp = this.safeTimestamp (ticker, 'updated');
|
||||
let timestamp = this.safeTimestamp (ticker, 'updated');
|
||||
let symbol = undefined;
|
||||
if (market !== undefined) {
|
||||
symbol = market['symbol'];
|
||||
if (!market['active']) {
|
||||
timestamp = undefined;
|
||||
}
|
||||
}
|
||||
const last = this.safeFloat (ticker, 'last');
|
||||
return {
|
||||
|
||||
+2
-2
@@ -442,7 +442,7 @@ module.exports = class upbit extends Exchange {
|
||||
return base + '/' + quote;
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
let ids = undefined;
|
||||
if (symbols === undefined) {
|
||||
@@ -505,7 +505,7 @@ module.exports = class upbit extends Exchange {
|
||||
}
|
||||
|
||||
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
||||
const orderbooks = await this.fetchOrderBooks ([ symbol ], params);
|
||||
const orderbooks = await this.fetchOrderBooks ([ symbol ], limit, params);
|
||||
return this.safeValue (orderbooks, symbol);
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -295,7 +295,7 @@ module.exports = class yobit extends Exchange {
|
||||
return this.parseOrderBook (orderbook);
|
||||
}
|
||||
|
||||
async fetchOrderBooks (symbols = undefined, params = {}) {
|
||||
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
||||
await this.loadMarkets ();
|
||||
let ids = undefined;
|
||||
if (symbols === undefined) {
|
||||
@@ -311,7 +311,11 @@ module.exports = class yobit extends Exchange {
|
||||
}
|
||||
const request = {
|
||||
'pair': ids,
|
||||
// 'ignore_invalid': true,
|
||||
};
|
||||
if (limit !== undefined) {
|
||||
request['limit'] = limit;
|
||||
}
|
||||
const response = await this.publicGetDepthPair (this.extend (request, params));
|
||||
const result = {};
|
||||
ids = Object.keys (response);
|
||||
|
||||
+11
-11
@@ -1,27 +1,27 @@
|
||||
{
|
||||
"_from": "ccxt",
|
||||
"_id": "ccxt@1.21.82",
|
||||
"_from": "ccxt@1.22.39",
|
||||
"_id": "ccxt@1.22.39",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-+HX/6WK8BM5c9OwhALl9zzMKvueZfHDXVmfrKNmQ4005hc+BtNuNe47XEs6dAylY+ll7n9JpzaoIZhy6Lipiew==",
|
||||
"_integrity": "sha512-Vq4BzYS/FwRudPKQ6BQGU3SVntYv7EAQGT+2guf+e7qm45CJMhdoVwR1z89kl42fbK39XMnl8sUnRCwsKPs38A==",
|
||||
"_location": "/ccxt",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "tag",
|
||||
"type": "version",
|
||||
"registry": true,
|
||||
"raw": "ccxt",
|
||||
"raw": "ccxt@1.22.39",
|
||||
"name": "ccxt",
|
||||
"escapedName": "ccxt",
|
||||
"rawSpec": "",
|
||||
"rawSpec": "1.22.39",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "latest"
|
||||
"fetchSpec": "1.22.39"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"#USER",
|
||||
"/"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.21.82.tgz",
|
||||
"_shasum": "6117f2d436d053c66574eaae195083fb69d64903",
|
||||
"_spec": "ccxt",
|
||||
"_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.22.39.tgz",
|
||||
"_shasum": "ca28a2dafd94089238279c9e5f2f4a041348d065",
|
||||
"_spec": "ccxt@1.22.39",
|
||||
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer",
|
||||
"author": {
|
||||
"name": "Igor Kroitor",
|
||||
@@ -520,5 +520,5 @@
|
||||
},
|
||||
"types": "./ccxt.d.ts",
|
||||
"unpkg": "dist/ccxt.browser.js",
|
||||
"version": "1.21.82"
|
||||
"version": "1.22.39"
|
||||
}
|
||||
Reference in new issue
Block a user