diff --git a/TaskServer/TradingBot.js b/TaskServer/TradingBot.js
index 1a2852487..c0af44f59 100644
--- a/TaskServer/TradingBot.js
+++ b/TaskServer/TradingBot.js
@@ -121,6 +121,7 @@
const CONDITIONS_FOLDER_NAME = "Simulation-Conditions";
const STRATEGIES_FOLDER_NAME = "Simulation-Strategies";
const TRADES_FOLDER_NAME = "Simulation-Trades";
+ const SNAPSHOTS_FOLDER_NAME = "Snapshots";
const ONE_DAY_IN_MILISECONDS = 24 * 60 * 60 * 1000;
@@ -129,6 +130,10 @@
let strategiesArray
let tradesArray
+ let snapshotHeaders
+ let triggerOnSnapshot
+ let takePositionSnapshot
+
let tradingSystem = {};
tradingSimulation.runSimulation(
@@ -142,7 +147,7 @@
writeFiles,
callBackFunction)
- function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray) {
+ function writeFiles(pTradingSystem, pRecordsArray, pConditionsArray, pStrategiesArray, pTradesArray, pSnapshotHeaders, pTriggerOnSnapshot, pTakePositionSnapshot) {
tradingSystem = pTradingSystem
recordsArray = pRecordsArray
@@ -150,11 +155,16 @@
strategiesArray = pStrategiesArray
tradesArray = pTradesArray
+ snapshotHeaders = pSnapshotHeaders
+ triggerOnSnapshot = pTriggerOnSnapshot
+ takePositionSnapshot = pTakePositionSnapshot
+
if (timeFrame > global.dailyFilePeriods[0][0]) {
writeMarketFiles()
} else {
writeDailyFiles()
}
+
}
function writeMarketFiles() {
@@ -474,7 +484,7 @@
}
- callBackFunction(global.DEFAULT_OK_RESPONSE);
+ writeSnapshotFiles();
}
catch (err) {
@@ -489,97 +499,52 @@
}
}
- }
+ function writeSnapshotFiles() {
- function writeDailyFiles() {
- if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
+ writeSnapshotFile(triggerOnSnapshot, 'Trigger-On', onFinish)
- writeRecordsFile();
+ function onFinish() {
+ writeSnapshotFile(takePositionSnapshot, 'Take-Position', callBackFunction)
+ }
+
+ }
- /* TODO : NEXT function is a work in progress, not used today */
- function writeFinalResults() {
+ function writeSnapshotFile(snapshotArray, pFileName, callBack) {
try {
- if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> Entering function."); }
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> Entering function."); }
- if ( // We only write this file if we are at the head of the market.
- Math.trunc(currentDay.valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
- !==
- Math.trunc((new Date()).valueOf() / ONE_DAY_IN_MILISECONDS) * ONE_DAY_IN_MILISECONDS
- ) {
- writeRecordsFile();
- return;
- }
-
- let separator = "";
let fileRecordCounter = 0;
let fileContent = "";
+ let separator = "\r\n";
- for (let i = 0; i < recordsArray.length; i++) {
-
- let record = recordsArray[i];
-
- /* Will only add to the file the records of the current day */
-
- if (record.begin < currentDay.valueOf()) { continue; }
-
- fileContent = fileContent + separator + '[' +
- record.begin + "," +
- record.end + "," +
- record.type + "," +
- record.marketRate + "," +
- record.amount + "," +
- record.balanceA + "," +
- record.balanceB + "," +
- record.profit + "," +
- record.lastTradeProfitLoss + "," +
- record.stopLoss + "," +
- record.roundtrips + "," +
- record.hits + "," +
- record.fails + "," +
- record.hitRatio + "," +
- record.ROI + "," +
- record.periods + "," +
- record.days + "," +
- record.anualizedRateOfReturn + "," +
- record.positionRate + "," +
- record.lastTradeROI + "," +
- record.strategy + "," +
- record.strategyStageNumber + "," +
- record.takeProfit + "," +
- record.stopLossPhase + "," +
- record.takeProfitPhase + "," +
- JSON.stringify(record.executionRecord) + "," +
- record.positionSize + "," +
- record.initialBalanceA + "," +
- record.minimumBalanceA + "," +
- record.maximumBalanceA + "," +
- record.initialBalanceB + "," +
- record.minimumBalanceB + "," +
- record.maximumBalanceB + "," +
- record.baseAsset + "," +
- record.quotedAsset + "," +
- record.marketBaseAsset + "," +
- record.marketQuotedAsset + "," +
- record.positionPeriods + "," +
- record.positionDays + "," +
- record.distanceToLastTriggerOn + "," +
- record.distanceToLastTriggerOff + "," +
- record.distanceToLastTakePosition + "," +
- record.distanceToLastClosePosition + "]";
-
- if (separator === "") { separator = ","; }
+ parseRecord(snapshotHeaders)
+ for (let i = 0; i < snapshotArray.length; i++) {
+ let record = snapshotArray[i];
+ parseRecord(record)
fileRecordCounter++;
+ }
+
+ function parseRecord(record) {
+ for (let j = 0; j < record.length; j++) {
+ let property = record[j]
+
+ fileContent = fileContent + '' + property
+ if (j !== record.length - 1) {
+ fileContent = fileContent + ","
+ }
+ }
+ fileContent = fileContent + separator
}
- fileContent = "[" + fileContent + "]";
+ fileContent = "" + fileContent + "";
- let fileName = 'Data.json';
- let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SIMULATED_RECORDS_FOLDER_NAME + "/" + "Multi-Period-Daily" + "/" + timeFrameLabel;
+ let fileName = pFileName + '.csv';
+ let filePath = bot.filePathRoot + "/Output/" + bot.SESSION.folderName + "/" + SNAPSHOTS_FOLDER_NAME + "/" + "Multi-Period-Market" + "/" + timeFrameLabel;
filePath += '/' + fileName
fileStorage.createTextFile(filePath, fileContent + '\n', onFileCreated);
@@ -588,35 +553,42 @@
try {
- if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> Entering function."); }
- if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> fileContent = " + fileContent); }
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> Entering function."); }
+ if (LOG_FILE_CONTENT === true) { logger.write(MODULE_NAME, "[INFO] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> fileContent = " + fileContent); }
if (err.result !== global.DEFAULT_OK_RESPONSE.result) {
- logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
- logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> filePath = " + filePath);
- logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> market = " + market.baseAsset + "_" + market.quotedAsset);
+ logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
+ logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> filePath = " + filePath);
+ logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> market = " + market.baseAsset + "_" + market.quotedAsset);
callBackFunction(err);
return;
}
- writeRecordsFile();
+ callBack(global.DEFAULT_OK_RESPONSE);
}
catch (err) {
- logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> onFileCreated -> err = " + err.stack);
+ logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> onFileCreated -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
}
catch (err) {
- logger.write(MODULE_NAME, "[ERROR] start -> writeDailyFiles -> writeFinalResults -> err = " + err.stack);
+ logger.write(MODULE_NAME, "[ERROR] start -> writeMarketFiles -> writeSnapshotFile -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
}
}
+ }
+
+ function writeDailyFiles() {
+ if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] start -> writeDailyFiles -> Entering function."); }
+
+ writeRecordsFile();
+
function writeRecordsFile() {
try {
diff --git a/TaskServer/TradingSimulation.js b/TaskServer/TradingSimulation.js
index 1e924e89c..9fc408d30 100644
--- a/TaskServer/TradingSimulation.js
+++ b/TaskServer/TradingSimulation.js
@@ -39,6 +39,10 @@
} else {
processingDailyFiles = true
}
+
+ let snapshotHeaders
+ let triggerOnSnapshot = [];
+ let takePositionSnapshot = [];
let recordsArray = [];
let conditionsArray = [];
@@ -500,6 +504,14 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Entering function."); }
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Processing candle # " + currentCandleIndex); }
+ /* We are going to take snapshots of the values of indicators at key moments of the sumulation. */
+
+ let snapshotKeys = new Map()
+ snapshotLoopHeaders = []
+ snapshotDataRecord = []
+ addToTriggerOnSnapshot = false
+ addToTakePositionSnapshot = false
+
let announcementsToBeMade = []
let candle = candles[currentCandleIndex];
@@ -767,7 +779,9 @@
if (initialDefinition.positionSize !== undefined) {
if (initialDefinition.positionSize.formula !== undefined) {
try {
- positionSize = eval(initialDefinition.positionSize.formula.code);
+ let code = initialDefinition.positionSize.formula.code
+ positionSize = eval(code);
+ addCodeToSnapshot(code)
} catch (err) {
initialDefinition.positionSize.formula.error = err.message
}
@@ -794,7 +808,9 @@
if (initialDefinition.positionRate !== undefined) {
if (initialDefinition.positionRate.formula !== undefined) {
try {
+ let code = initialDefinition.positionRate.formula.code
positionRate = eval(initialDefinition.positionRate.formula.code);
+ addCodeToSnapshot(code)
} catch (err) {
initialDefinition.positionRate.formula.error = err.message
}
@@ -821,7 +837,9 @@
if (phase.formula !== undefined) {
try {
- formulaValue = eval(phase.formula.code);
+ let code = phase.formula.code
+ formulaValue = eval(code);
+ addCodeToSnapshot(code)
if (formulaValue === Infinity) {
formulaError = "Formula evaluates to Infinity."
formulaValue = MAX_STOP_LOSS_VALUE
@@ -910,7 +928,9 @@
if (phase.formula !== undefined) {
try {
- formulaValue = eval(phase.formula.code);
+ let code = phase.formula.code
+ formulaValue = eval(code);
+ addCodeToSnapshot(code)
if (formulaValue === Infinity) {
formulaValue = MAX_TAKE_PROFIT_VALUE
if (takeProfitStage === 'Open Stage') {
@@ -1007,7 +1027,9 @@
if (phase.formula !== undefined) {
try {
- formulaValue = eval(phase.formula.code);
+ let code = phase.formula.code
+ formulaValue = eval(code);
+ addCodeToSnapshot(code)
if (formulaValue === Infinity) {
formulaError = ""
formulaValue = MAX_STOP_LOSS_VALUE
@@ -1096,7 +1118,9 @@
if (phase.formula !== undefined) {
try {
- formulaValue = eval(phase.formula.code);
+ let code = phase.formula.code
+ formulaValue = eval(code);
+ addCodeToSnapshot(code)
if (formulaValue === Infinity) {
formulaError = "Formula evaluates to Infinity."
formulaValue = MAX_TAKE_PROFIT_VALUE
@@ -1181,7 +1205,9 @@
let value
try {
- value = eval(node.code);
+ let code = node.code
+ value = eval(code);
+ addCodeToSnapshot(code)
} catch (err) {
/*
One possible error is that the conditions references a .previous that is undefined. For this
@@ -1319,6 +1345,7 @@
}
checkAnnouncements(triggerStage.triggerOn)
+ addToTriggerOnSnapshot = true
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Switching to Trigger Stage because conditions at Trigger On Event were met."); }
break;
@@ -1452,6 +1479,7 @@
currentTrade.takePositionSituation = situation.name
checkAnnouncements(triggerStage.takePosition)
+ addToTakePositionSnapshot = true
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> loop -> Conditions at the Take Position Event were met."); }
break;
@@ -2186,6 +2214,7 @@
}
takePositionAtSimulation()
+
return
function putOpeningOrder() {
@@ -2914,6 +2943,21 @@
}
}
+ /* Add to Snapshot */
+ if (addToTakePositionSnapshot === true) {
+ takePositionSnapshot.push(snapshotDataRecord)
+ addToTakePositionSnapshot = false
+ }
+
+ if (addToTriggerOnSnapshot === true) {
+ triggerOnSnapshot.push(snapshotDataRecord)
+ addToTriggerOnSnapshot = false
+ }
+
+ if (snapshotHeaders === undefined) {
+ snapshotHeaders = JSON.parse(JSON.stringify(snapshotLoopHeaders))
+ }
+
makeAnnoucements() // After everything at the simulation level was done, we will do the annoucements that are pending.
}
@@ -3005,10 +3049,63 @@
}
}
}
+
+ function addCodeToSnapshot(code) {
+ if (code === undefined) { return }
+
+ try {
+ let instructionsArray = code.split(' ')
+ for (let i = 0; i < instructionsArray.length; i++) {
+ let instruction = instructionsArray[i]
+ instruction = instruction.replace('(', '')
+ instruction = instruction.replace(')', '')
+ instruction = instruction.replace(//g, '')
+ instruction = instruction.replace(/<=/g, '')
+ instruction = instruction.replace(/>=/g, '')
+ instruction = instruction.replace(/!=/g, '')
+ instruction = instruction.replace(/!==/g, '')
+ instruction = instruction.replace(/==/g, '')
+ instruction = instruction.replace(/===/g, '')
+ if (instruction.indexOf('chart') >= 0) {
+ let parts = instruction.split('.')
+ let timeFrame = parts[1]
+ let product = parts[2]
+ let property
+ checkPrevious(3)
+ function checkPrevious(index) {
+ property = parts[index]
+ if (property === 'previous') {
+ product = product + '.previous'
+ checkPrevious(index + 1)
+ }
+ }
+
+ // Example: chart.at01hs.popularSMA.sma200 - chart.at01hs.popularSMA.sma100 < 10
+ if (timeFrame !== 'atAnyTimeFrame') {
+ timeFrame = timeFrame.substring(2, 4) + '-' + timeFrame.substring(4, 7)
+ }
+ let key = timeFrame + '-' + product + '-' + property
+ let existingKey = snapshotKeys.get(key)
+
+ if (existingKey === undefined) {// means that at the current loop this property of this product was not used before.
+ snapshotKeys.set(key, key)
+ snapshotLoopHeaders.push(key)
+
+ let value = eval(instruction)
+ snapshotDataRecord.push(value)
+ }
+ }
+ }
+ }
+ catch (err) {
+ logger.write(MODULE_NAME, "[ERROR] runSimulation -> addCodeToSnapshot -> code = " + code);
+ logger.write(MODULE_NAME, "[ERROR] runSimulation -> addCodeToSnapshot -> err = " + err.stack);
+ callBackFunction(global.DEFAULT_FAIL_RESPONSE);
+ }
+ }
}
-
-
function controlLoop() {
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> controlLoop -> Entering function."); }
@@ -3114,7 +3211,7 @@
if (FULL_LOG === true) { logger.write(MODULE_NAME, "[INFO] runSimulation -> callback -> recordsArray.length = " + recordsArray.length); }
- callback(tradingSystem, recordsArray, conditionsArray, strategiesArray, tradesArray);
+ callback(tradingSystem, recordsArray, conditionsArray, strategiesArray, tradesArray, snapshotHeaders, triggerOnSnapshot, takePositionSnapshot);
}
function getElement(pArray, currentCandle, datasetName) {
@@ -3156,6 +3253,7 @@
}
}
}
+
catch (err) {
logger.write(MODULE_NAME, "[ERROR] runSimulation -> err = " + err.stack);
callBackFunction(global.DEFAULT_FAIL_RESPONSE);
diff --git a/TaskServer/node_modules/ccxt/build/export-exchanges.js b/TaskServer/node_modules/ccxt/build/export-exchanges.js
index 6ed8fd0cd..e46845674 100644
--- a/TaskServer/node_modules/ccxt/build/export-exchanges.js
+++ b/TaskServer/node_modules/ccxt/build/export-exchanges.js
@@ -333,9 +333,21 @@ function exportKeywordsToPackageJson (exchanges) {
// ----------------------------------------------------------------------------
-function exportEverything () {
+function flatten (nested, result = []) {
+ for (const key in nested) {
+ result.push (key)
+ if (Object.keys (nested[key]).length)
+ flatten (nested[key], result)
+ }
+ return result
+}
+
+function exportEverything () {
const ids = getIncludedExchangeIds ()
+ const errorHierarchy = require ('../js/base/errorHierarchy.js')
+ const flat = flatten (errorHierarchy)
+ flat.push ('error_hierarchy')
const replacements = [
{
@@ -353,6 +365,16 @@ function exportEverything () {
regex: /(?:from ccxt\.[^\.]+ import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]exchanges/,
replacement: ids.map (id => ('from ccxt.' + id + ' import ' + id).padEnd (60) + '# noqa: F401').join ("\n") + "\n\nexchanges",
},
+ {
+ file: './python/ccxt/__init__.py',
+ regex: /(?:from ccxt\.base\.errors import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]/,
+ replacement: flat.map (error => ('from ccxt.base.errors' + ' import ' + error).padEnd (60) + '# noqa: F401').join ("\n") + "\n\n",
+ },
+ {
+ file: './python/ccxt/async_support/__init__.py',
+ regex: /(?:from ccxt\.base\.errors import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]/,
+ replacement: flat.map (error => ('from ccxt.base.errors' + ' import ' + error).padEnd (60) + '# noqa: F401').join ("\n") + "\n\n",
+ },
{
file: './python/ccxt/async_support/__init__.py',
regex: /(?:from ccxt\.async_support\.[^\.]+ import [^\s]+\s+\# noqa\: F401[\r]?[\n])+[\r]?[\n]exchanges/,
diff --git a/TaskServer/node_modules/ccxt/build/transpile.js b/TaskServer/node_modules/ccxt/build/transpile.js
index b55ffae59..10854e928 100644
--- a/TaskServer/node_modules/ccxt/build/transpile.js
+++ b/TaskServer/node_modules/ccxt/build/transpile.js
@@ -199,6 +199,7 @@ class Transpiler {
[ /(^|[^a-zA-Z0-9_])(?:let|const|var)\s/g, '$1' ],
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
[ /Object\.keys\s*\((.*)\)/g, 'list($1.keys())' ],
+ [ /Object\.values\s*\((.*)\)/g, 'list($1.values())' ],
[ /\[([^\]]+)\]\.join\s*\(([^\)]+)\)/g, "$2.join([$1])" ],
[ /hash \(([^,]+)\, \'(sha[0-9])\'/g, "hash($1, '$2'" ],
[ /hmac \(([^,]+)\, ([^,]+)\, \'(md5)\'/g, 'hmac($1, $2, hashlib.$3' ],
@@ -330,6 +331,7 @@ class Transpiler {
[ /(^|[^a-zA-Z0-9_])(?:let|const|var)\s/g, '$1' ],
[ /Object\.keys\s*\((.*)\)\.length/g, '$1' ],
[ /Object\.keys\s*\((.*)\)/g, 'is_array($1) ? array_keys($1) : array()' ],
+ [ /Object\.values\s*\((.*)\)/g, 'is_array($1) ? array_values($1) : array()' ],
[ /([^\s]+\s*\(\))\.toString \(\)/g, '(string) $1' ],
[ /([^\s]+)\.toString \(\)/g, '(string) $1' ],
[ /throw new Error \((.*)\)/g, 'throw new \\Exception($1)' ],
diff --git a/TaskServer/node_modules/ccxt/ccxt.js b/TaskServer/node_modules/ccxt/ccxt.js
index 15b32440d..d6ed88a1f 100644
--- a/TaskServer/node_modules/ccxt/ccxt.js
+++ b/TaskServer/node_modules/ccxt/ccxt.js
@@ -35,7 +35,7 @@ const Exchange = require ('./js/base/Exchange')
//-----------------------------------------------------------------------------
// this is updated by vss.js when building
-const version = '1.25.80'
+const version = '1.27.45'
Exchange.ccxtVersion = version
@@ -44,7 +44,6 @@ Exchange.ccxtVersion = version
const exchanges = {
'_1btcxe': require ('./js/_1btcxe.js'),
'acx': require ('./js/acx.js'),
- 'adara': require ('./js/adara.js'),
'anxpro': require ('./js/anxpro.js'),
'aofex': require ('./js/aofex.js'),
'bcex': require ('./js/bcex.js'),
@@ -115,8 +114,8 @@ const exchanges = {
'fybse': require ('./js/fybse.js'),
'gateio': require ('./js/gateio.js'),
'gemini': require ('./js/gemini.js'),
+ 'hbtc': require ('./js/hbtc.js'),
'hitbtc': require ('./js/hitbtc.js'),
- 'hitbtc2': require ('./js/hitbtc2.js'),
'hollaex': require ('./js/hollaex.js'),
'huobipro': require ('./js/huobipro.js'),
'huobiru': require ('./js/huobiru.js'),
diff --git a/TaskServer/node_modules/ccxt/dist/ccxt.browser.js b/TaskServer/node_modules/ccxt/dist/ccxt.browser.js
index 9ff7c58aa..acbb6ec4f 100644
--- a/TaskServer/node_modules/ccxt/dist/ccxt.browser.js
+++ b/TaskServer/node_modules/ccxt/dist/ccxt.browser.js
@@ -43,7 +43,7 @@ const Exchange = require ('./js/base/Exchange')
//-----------------------------------------------------------------------------
// this is updated by vss.js when building
-const version = '1.25.80'
+const version = '1.27.45'
Exchange.ccxtVersion = version
@@ -52,7 +52,6 @@ Exchange.ccxtVersion = version
const exchanges = {
'_1btcxe': require ('./js/_1btcxe.js'),
'acx': require ('./js/acx.js'),
- 'adara': require ('./js/adara.js'),
'anxpro': require ('./js/anxpro.js'),
'aofex': require ('./js/aofex.js'),
'bcex': require ('./js/bcex.js'),
@@ -123,8 +122,8 @@ const exchanges = {
'fybse': require ('./js/fybse.js'),
'gateio': require ('./js/gateio.js'),
'gemini': require ('./js/gemini.js'),
+ 'hbtc': require ('./js/hbtc.js'),
'hitbtc': require ('./js/hitbtc.js'),
- 'hitbtc2': require ('./js/hitbtc2.js'),
'hollaex': require ('./js/hollaex.js'),
'huobipro': require ('./js/huobipro.js'),
'huobiru': require ('./js/huobiru.js'),
@@ -178,7 +177,7 @@ module.exports = Object.assign ({ version, Exchange, 'exchanges': Object.keys (e
//-----------------------------------------------------------------------------
-},{"./js/_1btcxe.js":3,"./js/acx.js":4,"./js/adara.js":5,"./js/anxpro.js":6,"./js/aofex.js":7,"./js/base/Exchange":8,"./js/base/errors":10,"./js/base/functions":11,"./js/bcex.js":22,"./js/bequant.js":23,"./js/bibox.js":24,"./js/bigone.js":25,"./js/binance.js":26,"./js/binanceje.js":27,"./js/binanceus.js":28,"./js/bit2c.js":29,"./js/bitbank.js":30,"./js/bitbay.js":31,"./js/bitfinex.js":32,"./js/bitfinex2.js":33,"./js/bitflyer.js":34,"./js/bitforex.js":35,"./js/bithumb.js":36,"./js/bitkk.js":37,"./js/bitmart.js":38,"./js/bitmax.js":39,"./js/bitmex.js":40,"./js/bitso.js":41,"./js/bitstamp.js":42,"./js/bitstamp1.js":43,"./js/bittrex.js":44,"./js/bitz.js":45,"./js/bl3p.js":46,"./js/bleutrade.js":47,"./js/braziliex.js":48,"./js/btcalpha.js":49,"./js/btcbox.js":50,"./js/btcmarkets.js":51,"./js/btctradeim.js":52,"./js/btctradeua.js":53,"./js/btcturk.js":54,"./js/buda.js":55,"./js/bw.js":56,"./js/bybit.js":57,"./js/bytetrade.js":58,"./js/cex.js":59,"./js/chilebit.js":60,"./js/coinbase.js":61,"./js/coinbaseprime.js":62,"./js/coinbasepro.js":63,"./js/coincheck.js":64,"./js/coinegg.js":65,"./js/coinex.js":66,"./js/coinfalcon.js":67,"./js/coinfloor.js":68,"./js/coingi.js":69,"./js/coinmarketcap.js":70,"./js/coinmate.js":71,"./js/coinone.js":72,"./js/coinspot.js":73,"./js/coolcoin.js":74,"./js/coss.js":75,"./js/crex24.js":76,"./js/deribit.js":77,"./js/digifinex.js":78,"./js/dsx.js":79,"./js/exmo.js":80,"./js/exx.js":81,"./js/fcoin.js":82,"./js/fcoinjp.js":83,"./js/flowbtc.js":84,"./js/foxbit.js":85,"./js/ftx.js":86,"./js/fybse.js":87,"./js/gateio.js":88,"./js/gemini.js":89,"./js/hitbtc.js":90,"./js/hitbtc2.js":91,"./js/hollaex.js":92,"./js/huobipro.js":93,"./js/huobiru.js":94,"./js/ice3x.js":95,"./js/idex.js":96,"./js/independentreserve.js":97,"./js/indodax.js":98,"./js/itbit.js":99,"./js/kkex.js":100,"./js/kraken.js":101,"./js/kucoin.js":102,"./js/kuna.js":103,"./js/lakebtc.js":104,"./js/latoken.js":105,"./js/lbank.js":106,"./js/liquid.js":107,"./js/livecoin.js":108,"./js/luno.js":109,"./js/lykke.js":110,"./js/mercado.js":111,"./js/mixcoins.js":112,"./js/oceanex.js":113,"./js/okcoin.js":114,"./js/okex.js":115,"./js/paymium.js":116,"./js/poloniex.js":117,"./js/rightbtc.js":118,"./js/southxchange.js":119,"./js/stex.js":157,"./js/stronghold.js":158,"./js/surbitcoin.js":159,"./js/theocean.js":160,"./js/therock.js":161,"./js/tidebit.js":162,"./js/tidex.js":163,"./js/timex.js":164,"./js/topq.js":165,"./js/upbit.js":166,"./js/vaultoro.js":167,"./js/vbtc.js":168,"./js/whitebit.js":169,"./js/xbtce.js":170,"./js/yobit.js":171,"./js/zaif.js":172,"./js/zb.js":173}],3:[function(require,module,exports){
+},{"./js/_1btcxe.js":3,"./js/acx.js":4,"./js/anxpro.js":5,"./js/aofex.js":6,"./js/base/Exchange":7,"./js/base/errors":9,"./js/base/functions":10,"./js/bcex.js":21,"./js/bequant.js":22,"./js/bibox.js":23,"./js/bigone.js":24,"./js/binance.js":25,"./js/binanceje.js":26,"./js/binanceus.js":27,"./js/bit2c.js":28,"./js/bitbank.js":29,"./js/bitbay.js":30,"./js/bitfinex.js":31,"./js/bitfinex2.js":32,"./js/bitflyer.js":33,"./js/bitforex.js":34,"./js/bithumb.js":35,"./js/bitkk.js":36,"./js/bitmart.js":37,"./js/bitmax.js":38,"./js/bitmex.js":39,"./js/bitso.js":40,"./js/bitstamp.js":41,"./js/bitstamp1.js":42,"./js/bittrex.js":43,"./js/bitz.js":44,"./js/bl3p.js":45,"./js/bleutrade.js":46,"./js/braziliex.js":47,"./js/btcalpha.js":48,"./js/btcbox.js":49,"./js/btcmarkets.js":50,"./js/btctradeim.js":51,"./js/btctradeua.js":52,"./js/btcturk.js":53,"./js/buda.js":54,"./js/bw.js":55,"./js/bybit.js":56,"./js/bytetrade.js":57,"./js/cex.js":58,"./js/chilebit.js":59,"./js/coinbase.js":60,"./js/coinbaseprime.js":61,"./js/coinbasepro.js":62,"./js/coincheck.js":63,"./js/coinegg.js":64,"./js/coinex.js":65,"./js/coinfalcon.js":66,"./js/coinfloor.js":67,"./js/coingi.js":68,"./js/coinmarketcap.js":69,"./js/coinmate.js":70,"./js/coinone.js":71,"./js/coinspot.js":72,"./js/coolcoin.js":73,"./js/coss.js":74,"./js/crex24.js":75,"./js/deribit.js":76,"./js/digifinex.js":77,"./js/dsx.js":78,"./js/exmo.js":79,"./js/exx.js":80,"./js/fcoin.js":81,"./js/fcoinjp.js":82,"./js/flowbtc.js":83,"./js/foxbit.js":84,"./js/ftx.js":85,"./js/fybse.js":86,"./js/gateio.js":87,"./js/gemini.js":88,"./js/hbtc.js":89,"./js/hitbtc.js":90,"./js/hollaex.js":91,"./js/huobipro.js":92,"./js/huobiru.js":93,"./js/ice3x.js":94,"./js/idex.js":95,"./js/independentreserve.js":96,"./js/indodax.js":97,"./js/itbit.js":98,"./js/kkex.js":99,"./js/kraken.js":100,"./js/kucoin.js":101,"./js/kuna.js":102,"./js/lakebtc.js":103,"./js/latoken.js":104,"./js/lbank.js":105,"./js/liquid.js":106,"./js/livecoin.js":107,"./js/luno.js":108,"./js/lykke.js":109,"./js/mercado.js":110,"./js/mixcoins.js":111,"./js/oceanex.js":112,"./js/okcoin.js":113,"./js/okex.js":114,"./js/paymium.js":115,"./js/poloniex.js":116,"./js/rightbtc.js":117,"./js/southxchange.js":118,"./js/stex.js":156,"./js/stronghold.js":157,"./js/surbitcoin.js":158,"./js/theocean.js":159,"./js/therock.js":160,"./js/tidebit.js":161,"./js/tidex.js":162,"./js/timex.js":163,"./js/topq.js":164,"./js/upbit.js":165,"./js/vaultoro.js":166,"./js/vbtc.js":167,"./js/whitebit.js":168,"./js/xbtce.js":169,"./js/yobit.js":170,"./js/zaif.js":171,"./js/zb.js":172}],3:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -485,7 +484,7 @@ module.exports = class _1btcxe extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],4:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],4:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -960,1264 +959,7 @@ module.exports = class acx extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],5:[function(require,module,exports){
-'use strict';
-
-// ---------------------------------------------------------------------------
-
-const Exchange = require ('./base/Exchange');
-const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound } = require ('./base/errors');
-
-// ---------------------------------------------------------------------------
-
-module.exports = class adara extends Exchange {
- describe () {
- return this.deepExtend (super.describe (), {
- 'id': 'adara',
- 'name': 'Adara',
- 'countries': [ 'MT' ],
- 'version': 'v1',
- 'rateLimit': 1000,
- 'certified': false,
- // new metainfo interface
- 'has': {
- 'CORS': false,
- 'fetchCurrencies': true,
- 'fetchOrderBooks': false,
- 'createMarketOrder': false,
- 'fetchDepositAddress': false,
- 'fetchClosedOrders': true,
- 'fetchMyTrades': false,
- 'fetchOHLCV': false,
- 'fetchOrder': true,
- 'fetchOpenOrders': true,
- 'fetchTickers': true,
- 'withdraw': false,
- 'fetchDeposits': false,
- 'fetchWithdrawals': false,
- 'fetchTransactions': false,
- },
- 'requiredCredentials': {
- 'apiKey': true,
- 'secret': true,
- 'token': false,
- },
- 'urls': {
- 'logo': 'https://user-images.githubusercontent.com/1294454/49189583-0466a780-f380-11e8-9248-57a631aad2d6.jpg',
- 'api': 'https://api.adara.io',
- 'www': 'https://adara.io',
- 'doc': 'https://api.adara.io/v1',
- 'fees': 'https://adara.io/fees',
- },
- 'api': {
- 'public': {
- 'get': [
- 'currencies',
- 'limits',
- 'market',
- 'marketDepth',
- 'marketInfo',
- 'orderBook',
- 'quote/',
- 'quote/{id}',
- 'symbols',
- 'trade',
- ],
- 'post': [
- 'confirmContactEmail',
- 'restorePassword',
- 'user', // sign up
- ],
- },
- 'private': {
- 'get': [
- 'balance',
- 'order',
- 'order/{id}',
- 'currencyBalance',
- 'apiKey', // the list of apiKeys
- 'user/{id}',
- ],
- 'post': [
- 'order',
- 'recovery',
- 'user',
- 'apiKey', // sign in and optionally create an apiKey
- 'contact',
- ],
- 'patch': [
- 'order/{id}',
- 'user/{id}', // change password
- 'customer', // update user info
- ],
- 'delete': [
- 'apiKey',
- ],
- },
- },
- 'fees': {
- 'trading': {
- 'tierBased': false,
- 'percentage': true,
- 'maker': 0.001,
- 'taker': 0.001,
- },
- 'funding': {
- 'tierBased': false,
- 'percentage': false,
- 'withdraw': {},
- 'deposit': {},
- },
- },
- 'exceptions': {
- 'exact': {
- 'Insufficient funds': InsufficientFunds,
- 'Amount is too small': InvalidOrder,
- 'operation has invalid value': InvalidOrder,
- "closed order can't be changed": InvalidOrder,
- 'Order is not found': OrderNotFound,
- 'AUTH': AuthenticationError,
- 'You are not authorized': AuthenticationError,
- 'Bad Request': BadRequest,
- '500': ExchangeError,
- },
- 'broad': {},
- },
- });
- }
-
- async fetchMarkets (params = {}) {
- const request = {
- 'include': 'from,to',
- };
- const response = await this.publicGetSymbols (this.extend (request, params));
- const included = this.safeValue (response, 'included', []);
- const includedByType = this.groupBy (included, 'type');
- const currencies = this.safeValue (includedByType, 'currency', []);
- const currenciesById = this.indexBy (currencies, 'id');
- //
- // { meta: { total: 61 },
- // data: [ { id: "XRPUSD",
- // type: "symbol",
- // attributes: { allowTrade: false,
- // createdAt: "2018-10-23T09:31:06.830Z",
- // digits: 5,
- // fullName: "XRPUSD",
- // makerFee: "0.0250",
- // name: "XRPUSD",
- // takerFee: "0.0250",
- // updatedAt: "2018-10-23T09:31:06.830Z" },
- // relationships: { from: { data: { id: "XRP", type: "currency" } },
- // to: { data: { id: "USD", type: "currency" } } } },
- // { id: "XRPETH",
- // type: "symbol",
- // attributes: { allowTrade: true,
- // createdAt: "2018-10-09T22:34:28.268Z",
- // digits: 8,
- // fullName: "XRPETH",
- // makerFee: "0.0025",
- // name: "XRPETH",
- // takerFee: "0.0025",
- // updatedAt: "2018-10-09T22:34:28.268Z" },
- // relationships: { from: { data: { id: "XRP", type: "currency" } },
- // to: { data: { id: "ETH", type: "currency" } } } } ],
- // included: [ { id: "XRP",
- // type: "currency",
- // attributes: { accuracy: 4,
- // active: true,
- // allowDeposit: true,
- // allowTrade: false,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Ripple",
- // shortName: "XRP",
- // transactionUriTemplate: "https://www.ripplescan.com/transactions/:txId",
- // walletUriTemplate: "https://www.ripplescan.com/accounts/:address",
- // withdrawFee: "0.20000000",
- // withdrawMinAmount: "22.00000000" },
- // relationships: { } },
- // { id: "ETH",
- // type: "currency",
- // attributes: { accuracy: 8,
- // active: true,
- // allowDeposit: true,
- // allowTrade: true,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Ethereum",
- // shortName: "ETH",
- // transactionUriTemplate: "https://etherscan.io/tx/:txId",
- // walletUriTemplate: "https://etherscan.io/address/:address",
- // withdrawFee: "0.00800000",
- // withdrawMinAmount: "0.02000000" },
- // relationships: { } },
- // { id: "USD",
- // type: "currency",
- // attributes: { accuracy: 6,
- // active: true,
- // allowDeposit: false,
- // allowTrade: true,
- // allowWallet: false,
- // allowWithdraw: false,
- // name: "USD",
- // shortName: "USD",
- // transactionUriTemplate: null,
- // walletUriTemplate: null,
- // withdrawFee: "0.00000000",
- // withdrawMinAmount: "0.00000000" },
- // relationships: { } } ] }
- //
- const result = [];
- const markets = response['data'];
- for (let i = 0; i < markets.length; i++) {
- const market = markets[i];
- const id = this.safeString (market, 'id');
- const attributes = this.safeValue (market, 'attributes', {});
- const relationships = this.safeValue (market, 'relationships', {});
- const fromRelationship = this.safeValue (relationships, 'from', {});
- const toRelationship = this.safeValue (relationships, 'to', {});
- const fromRelationshipData = this.safeValue (fromRelationship, 'data', {});
- const toRelationshipData = this.safeValue (toRelationship, 'data', {});
- const baseId = this.safeString (fromRelationshipData, 'id');
- const quoteId = this.safeString (toRelationshipData, 'id');
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- const baseCurrency = this.safeValue (currenciesById, baseId, {});
- const baseCurrencyAttributes = this.safeValue (baseCurrency, 'attributes', {});
- const symbol = base + '/' + quote;
- const amountPrecision = this.safeInteger (baseCurrencyAttributes, 'accuracy', 8);
- const pricePrecision = this.safeInteger (attributes, 'digits', 8);
- const precision = {
- 'amount': amountPrecision,
- 'price': pricePrecision,
- };
- const active = this.safeValue (attributes, 'allowTrade');
- const maker = this.safeFloat (attributes, 'makerFee');
- const taker = this.safeFloat (attributes, 'takerFee');
- result.push ({
- 'info': market,
- 'id': id,
- 'symbol': symbol,
- 'base': base,
- 'quote': quote,
- 'baseId': baseId,
- 'quoteId': quoteId,
- 'active': active,
- 'maker': maker,
- 'taker': taker,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': Math.pow (10, -precision['amount']),
- 'max': undefined,
- },
- 'price': {
- 'min': Math.pow (10, -precision['price']),
- 'max': undefined,
- },
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- },
- });
- }
- return result;
- }
-
- async fetchCurrencies (params = {}) {
- const response = await this.publicGetCurrencies (params);
- //
- // { meta: { total: 22 },
- // data: [ { id: "USD",
- // type: "currency",
- // attributes: { accuracy: 6,
- // active: true,
- // allowDeposit: false,
- // allowTrade: true,
- // allowWallet: false,
- // allowWithdraw: false,
- // name: "USD",
- // shortName: "USD",
- // transactionUriTemplate: null,
- // walletUriTemplate: null,
- // withdrawFee: "0.00000000",
- // withdrawMinAmount: "0.00000000" },
- // relationships: { } },
- // { id: "BTC",
- // type: "currency",
- // attributes: { accuracy: 8,
- // active: true,
- // allowDeposit: true,
- // allowTrade: true,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Bitcoin",
- // shortName: "BTC",
- // transactionUriTemplate: "https://blockexplorer.com/tx/:txId",
- // walletUriTemplate: "https://blockexplorer.com/address/:address",
- // withdrawFee: "0.00050000",
- // withdrawMinAmount: "0.00200000" },
- // relationships: { } } ],
- // included: [] }
- //
- const currencies = response['data'];
- const result = {};
- for (let i = 0; i < currencies.length; i++) {
- const currency = currencies[i];
- const id = this.safeString (currency, 'id');
- const attributes = this.safeValue (currency, 'attributes', {});
- const code = this.commonCurrencyCode (id);
- const precision = this.safeInteger (attributes, 'accuracy');
- const fee = this.safeFloat (attributes, 'withdrawFee');
- const active = this.safeValue (attributes, 'active');
- const allowDeposit = this.safeValue (attributes, 'allowDeposit');
- const allowWithdraw = this.safeValue (attributes, 'allowWithdraw');
- result[code] = {
- 'id': id,
- 'code': code,
- 'info': currency,
- 'name': this.safeString (attributes, 'name'),
- 'active': (active && allowDeposit && allowWithdraw),
- 'fee': fee,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': Math.pow (10, -precision),
- 'max': Math.pow (10, precision),
- },
- 'price': {
- 'min': Math.pow (10, -precision),
- 'max': Math.pow (10, precision),
- },
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- 'withdraw': {
- 'min': this.safeFloat (attributes, 'withdrawMinAmount'),
- 'max': Math.pow (10, precision),
- },
- },
- };
- }
- return result;
- }
-
- async fetchBalance (params = {}) {
- await this.loadMarkets ();
- const response = await this.privateGetBalance (params);
- //
- // { data: [ { type: "balance",
- // id: "U4f0f0940-39bf-45a8-90bc-12d2899db4f1_BALANCE_FOR_ETH",
- // attributes: { totalBalance: 10000,
- // onOrders: 0,
- // normalizedTotalBalance: 310,
- // normalizedOnOrders: 0,
- // percentage: 3.004116443856034,
- // serializedAt: 1543324487949 },
- // relationships: { currency: { data: { type: "currency", id: "ETH" } },
- // normalizedCurrency: { data: { type: "currency", id: "BTC" } } } } ],
- // included: [ { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543324487948 },
- // relationships: { } },
- // { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543324487948 } } ] }
- //
- const result = { 'info': response };
- const data = this.safeValue (response, 'data');
- if (data !== undefined) {
- for (let i = 0; i < data.length; i++) {
- const balance = data[i];
- const attributes = this.safeValue (balance, 'attributes', {});
- const relationships = this.safeValue (balance, 'relationships', {});
- const currencyRelationship = this.safeValue (relationships, 'currency', {});
- const currencyRelationshipData = this.safeValue (currencyRelationship, 'data');
- const currencyId = this.safeString (currencyRelationshipData, 'id');
- const code = this.commonCurrencyCode (currencyId);
- const account = this.account ();
- account['total'] = this.safeFloat (attributes, 'totalBalance');
- account['used'] = this.safeFloat (attributes, 'onOrders');
- result[code] = account;
- }
- }
- return this.parseBalance (result);
- }
-
- getSymbolFromMarketId (marketId, market = undefined) {
- if (marketId === undefined) {
- return undefined;
- }
- market = this.safeValue (this.markets_by_id, marketId, market);
- if (market !== undefined) {
- return market['symbol'];
- }
- const [ baseId, quoteId ] = marketId.split ('-');
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- return base + '/' + quote;
- }
-
- parseOrderBook (orderbook, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 'price', amountKey = 'amount') {
- const bids = [];
- const asks = [];
- const numBidAsks = orderbook.length;
- if (numBidAsks > 0) {
- timestamp = this.safeInteger (orderbook[0]['attributes'], 'serializedAt');
- }
- for (let i = 0; i < orderbook.length; i++) {
- const bidask = orderbook[i];
- const attributes = this.safeValue (bidask, 'attributes', {});
- const currenTimestamp = this.safeInteger (attributes, 'serializedAt');
- timestamp = Math.max (timestamp, currenTimestamp);
- const id = this.safeString (bidask, 'id');
- if (id.indexOf ('OBID') >= 0) {
- bids.push (this.parseBidAsk (bidask['attributes'], priceKey, amountKey));
- } else if (id.indexOf ('OSID') >= 0) {
- asks.push (this.parseBidAsk (bidask['attributes'], priceKey, amountKey));
- } else {
- throw new ExchangeError (this.id + ' parseOrderBook encountered an unrecognized bidask format: ' + this.json (bidask));
- }
- }
- return {
- 'bids': this.sortBy (bids, 0, true),
- 'asks': this.sortBy (asks, 0),
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'nonce': undefined,
- };
- }
-
- async fetchOrderBook (symbol, limit = undefined, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const filters = 'filters[symbol]';
- const request = {};
- request[filters] = market['id'];
- const response = await this.publicGetOrderBook (this.extend (request, params));
- //
- // { data: [ { type: "orderBook",
- // id: "OBID0SLTCETHS0",
- // attributes: { price: 1,
- // amount: 4,
- // serializedAt: 1543116143473 } },
- // { type: "orderBook",
- // id: "OSID3SLTCETHS0",
- // attributes: { price: 12,
- // amount: 12,
- // serializedAt: 1543116143474 } } ] }
- //
- return this.parseOrderBook (response['data'], undefined, 'bids', 'asks', 'price', 'amount');
- }
-
- parseTicker (ticker, market = undefined) {
- //
- // { type: "quote",
- // id: "XRPETH",
- // attributes: { currentPrice: 1,
- // low: 1,
- // high: 1,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543109275996 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } }
- //
- const symbol = this.getSymbolFromMarketId (this.safeString (ticker, 'id'), market);
- const attributes = this.safeValue (ticker, 'attributes', {});
- const timestamp = this.safeInteger (attributes, 'serializedAt');
- const last = this.safeFloat (attributes, 'currentPrice');
- const change = this.safeFloat (attributes, 'change');
- let open = undefined;
- if (change !== undefined) {
- if (last !== undefined) {
- open = last - change;
- }
- }
- const percentage = this.safeFloat (attributes, 'percentChange');
- return {
- 'symbol': symbol,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'high': this.safeFloat (attributes, 'high'),
- 'low': this.safeFloat (attributes, 'low'),
- 'bid': undefined,
- 'bidVolume': undefined,
- 'ask': undefined,
- 'askVolume': undefined,
- 'vwap': undefined,
- 'open': open,
- 'close': last,
- 'last': last,
- 'previousClose': undefined,
- 'change': change,
- 'percentage': percentage,
- 'average': undefined,
- 'baseVolume': this.safeFloat (ticker, 'baseVolume'),
- 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'),
- 'info': ticker,
- };
- }
-
- async fetchTickers (symbols = undefined, params = {}) {
- await this.loadMarkets ();
- const response = await this.publicGetQuote (params);
- const data = this.safeValue (response, 'data', []);
- //
- // { data: [ { type: "quote",
- // id: "XRPETH",
- // attributes: { currentPrice: 1,
- // low: 1,
- // high: 1,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543109275996 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- // included: [ { type: "currency",
- // id: "XRP",
- // attributes: { name: "Ripple",
- // shortName: "XRP",
- // active: true,
- // accuracy: 4,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543109275996 },
- // relationships: { } },
- // { type: "symbol",
- // id: "XRPETH",
- // attributes: { fullName: "XRPETH",
- // digits: 8,
- // allowTrade: true,
- // serializedAt: 1543109275996 },
- // relationships: { from: { data: { type: "currency", id: "XRP" } },
- // to: { data: { type: "currency", id: "ETH" } } } } ] }
- //
- const result = {};
- for (let t = 0; t < data.length; t++) {
- const ticker = this.parseTicker (data[t]);
- const symbol = ticker['symbol'];
- result[symbol] = ticker;
- }
- return result;
- }
-
- async fetchTicker (symbol, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const request = {
- 'id': market['id'],
- };
- const response = await this.publicGetQuoteId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543111444033 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543111444033 } },
- // { type: "symbol",
- // id: "ETHBTC",
- // attributes: { fullName: "ETHBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543111444033 },
- // relationships: { from: { data: { type: "currency", id: "ETH" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "quote",
- // id: "ETHBTC",
- // attributes: { currentPrice: 34,
- // low: 34,
- // high: 34,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543111444033 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } } (fetchTicker @ adara.js:546)
- //
- return this.parseTicker (response['data']);
- }
-
- parseTrade (trade, market = undefined) {
- //
- // fetchTrades
- //
- //
- // { type: "trade",
- // id: "1542988964359136846136847",
- // attributes: { price: 34,
- // amount: 4,
- // total: 136,
- // operation: "buy",
- // createdAt: "2018-11-23T16:02:44.359Z",
- // serializedAt: 1543112364995 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- //
- const id = this.safeString (trade, 'id', 'uuid');
- const attributes = this.safeValue (trade, 'attributes', {});
- const relationships = this.safeValue (trade, 'relationships', {});
- const symbolRelationship = this.safeValue (relationships, 'symbol', {});
- const symbolRelationshipData = this.safeValue (symbolRelationship, 'data', {});
- const marketId = this.safeString (symbolRelationshipData, 'id');
- market = this.safeValue (this.markets_by_id, marketId, market);
- let symbol = undefined;
- let feeCurrency = undefined;
- if (market !== undefined) {
- symbol = market['symbol'];
- feeCurrency = market['quote'];
- } else if (marketId !== undefined) {
- const baseIdLength = marketId.length - 3;
- const baseId = marketId.slice (0, baseIdLength);
- const quoteId = marketId.slice (baseIdLength);
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- symbol = base + '/' + quote;
- feeCurrency = quote;
- }
- const orderId = undefined;
- const timestamp = this.parse8601 (this.safeString (attributes, 'createdAt'));
- const side = this.safeString (attributes, 'operation');
- const price = this.safeFloat (attributes, 'price');
- const amount = this.safeFloat (attributes, 'amount');
- let cost = this.safeFloat (attributes, 'total');
- if (cost === undefined) {
- if (amount !== undefined) {
- if (price !== undefined) {
- cost = parseFloat (this.costToPrecision (symbol, price * amount));
- }
- }
- }
- const feeCost = this.safeFloat (attributes, 'fee');
- let fee = undefined;
- if (feeCost !== undefined) {
- fee = {
- 'cost': feeCost,
- 'currency': feeCurrency,
- };
- }
- return {
- 'id': id,
- 'info': trade,
- 'order': orderId,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'symbol': symbol,
- 'type': undefined,
- 'side': side,
- 'takerOrMaker': undefined,
- 'price': price,
- 'amount': amount,
- 'cost': cost,
- 'fee': fee,
- };
- }
-
- async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
- let market = undefined;
- if (symbol !== undefined) {
- market = this.market (symbol);
- }
- const request = {
- // 'id': market['id'],
- };
- const response = await this.publicGetTrade (this.extend (request, params));
- //
- // { data: [ { type: "trade",
- // id: "1542988964359136846136847",
- // attributes: { price: 34,
- // amount: 4,
- // total: 136,
- // operation: "buy",
- // createdAt: "2018-11-23T16:02:44.359Z",
- // serializedAt: 1543112364995 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- // included: [ { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543112364995 },
- // relationships: { } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // ...
- // serializedAt: 1543112364995 },
- // relationships: { } },
- // { type: "symbol",
- // id: "ETHBTC",
- // attributes: { fullName: "ETHBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543112364995 },
- // relationships: { from: { data: { type: "currency", id: "ETH" } },
- // to: { data: { type: "currency", id: "BTC" } } } } }
- //
- return this.parseTrades (response['data'], market, since, limit);
- }
-
- async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const request = {
- 'data': {
- 'type': 'order',
- 'attributes': {
- 'amount': parseFloat (this.amountToPrecision (symbol, amount)),
- 'operation': side,
- 'orderType': type,
- 'price': parseFloat (this.priceToPrecision (symbol, price)),
- },
- 'relationships': {
- 'symbol': {
- 'data': {
- 'id': market['id'],
- 'type': 'symbol',
- },
- },
- },
- },
- 'included': [
- {
- 'id': market['id'],
- 'type': 'symbol',
- },
- ],
- };
- const response = await this.privatePostOrder (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543434477449 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543434477449 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543434477449 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543434477449,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0,
- // fee: 0,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: null,
- // status: "open",
- // filled: 0,
- // flags: [] },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } } }
- //
- return this.parseOrder (response['data']);
- }
-
- async cancelOrder (id, symbol = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'id': id,
- 'data': {
- 'attributes': {
- 'status': 'canceled',
- },
- },
- };
- const response = await this.privatePatchOrderId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543437874742 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543437874742 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543437874742 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "order",
- // id: "34794",
- // attributes: { serializedAt: 1543437874742,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 110,
- // price: 0.000034,
- // averagePrice: 0,
- // fee: 0,
- // timeOpen: "2018-11-28T20:42:35.486Z",
- // timeClose: null,
- // status: "canceled",
- // filled: 0,
- // flags: [] },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } } }
- //
- return this.parseOrder (response['data']);
- }
-
- parseOrderStatus (status) {
- const statuses = {
- 'open': 'open',
- 'closed': 'closed',
- 'canceled': 'canceled',
- };
- return this.safeString (statuses, status, status);
- }
-
- parseOrder (order, market = undefined) {
- //
- // { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543435013349,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } }
- //
- const id = this.safeString (order, 'id');
- const attributes = this.safeValue (order, 'attributes', {});
- const relationships = this.safeValue (order, 'relationships', {});
- const symbolRelationship = this.safeValue (relationships, 'symbol', {});
- const symbolRelationshipData = this.safeValue (symbolRelationship, 'data', {});
- const tradesRelationship = this.safeValue (relationships, 'trades', {});
- const tradesRelationshipData = this.safeValue (tradesRelationship, 'data');
- const marketId = this.safeString (symbolRelationshipData, 'id');
- market = this.safeValue (this.markets_by_id, marketId, market);
- let feeCurrency = undefined;
- let symbol = undefined;
- if (market !== undefined) {
- symbol = market['symbol'];
- feeCurrency = market['quote'];
- } else if (marketId !== undefined) {
- const baseIdLength = marketId.length - 3;
- const baseId = marketId.slice (0, baseIdLength);
- const quoteId = marketId.slice (baseIdLength);
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- symbol = base + '/' + quote;
- feeCurrency = quote;
- }
- const timestamp = this.parse8601 (this.safeString (attributes, 'timeOpen'));
- const side = this.safeString (attributes, 'operation');
- const type = this.safeString (attributes, 'orderType');
- const status = this.parseOrderStatus (this.safeString (attributes, 'status'));
- const lastTradeTimestamp = this.parse8601 (this.safeString (attributes, 'timeClose'));
- const price = this.safeFloat (attributes, 'price');
- const amount = this.safeFloat (attributes, 'amount');
- const filled = this.safeFloat (attributes, 'filled');
- let remaining = undefined;
- if (amount !== undefined) {
- if (filled !== undefined) {
- remaining = Math.max (0, amount - filled);
- }
- }
- let cost = undefined;
- const average = this.safeFloat (attributes, 'averagePrice');
- if (cost === undefined) {
- if ((average !== undefined) && (filled !== undefined)) {
- cost = parseFloat (this.costToPrecision (symbol, average * filled));
- }
- }
- let fee = undefined;
- const feeCost = this.safeFloat (attributes, 'fee');
- if (feeCost !== undefined) {
- fee = {
- 'currency': feeCurrency,
- 'cost': feeCost,
- };
- }
- let trades = undefined;
- if (tradesRelationshipData !== undefined) {
- const numTrades = tradesRelationshipData.length;
- if (numTrades > 0) {
- trades = this.parseTrades (tradesRelationshipData, market);
- }
- }
- const result = {
- 'info': order,
- 'id': id,
- 'clientOrderId': undefined,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'lastTradeTimestamp': lastTradeTimestamp,
- 'symbol': symbol,
- 'type': type,
- 'side': side,
- 'price': price,
- 'cost': cost,
- 'average': average,
- 'amount': amount,
- 'filled': filled,
- 'remaining': remaining,
- 'status': status,
- 'fee': fee,
- 'trades': trades,
- };
- return result;
- }
-
- async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'include': 'trades',
- };
- let market = undefined;
- if (symbol !== undefined) {
- market = this.market (symbol);
- const filters = 'filters[symbol]';
- request[filters] = market['id'];
- }
- const response = await this.privateGetOrder (this.extend (request, params));
- //
- // { data: [ { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543436770259,
- // operation: "buy",
- // orderType: "limit",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } },
- // trades: { data: [{ type: "trade", id: "34789_34793" }] } } } ],
- // included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543436770259 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543436770259 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543436770259 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } },
- // { type: "trade",
- // id: "34789_34793",
- // attributes: { fee: 0.0001925,
- // price: 0.000035,
- // amount: 220,
- // total: 0.0077,
- // operation: "buy",
- // createdAt: "2018-11-28T19:47:57.451Z" } } ],
- // meta: { total: 1 } }
- //
- return this.parseOrdersResponse (response, market, since, limit);
- }
-
- async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- const filters = 'filters[status][]';
- const request = {};
- request[filters] = 'open';
- return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
- }
-
- async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- const filters = 'filters[status][]';
- const request = {};
- request[filters] = 'closed';
- return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
- }
-
- parseOrdersResponse (response, market = undefined, since = undefined, limit = undefined) {
- const included = this.safeValue (response, 'included', []);
- const includedByType = this.groupBy (included, 'type');
- const unparsedTrades = this.safeValue (includedByType, 'trade', []);
- const trades = this.parseTrades (unparsedTrades, market);
- const tradesById = this.indexBy (trades, 'id');
- const orders = this.parseOrders (this.safeValue (response, 'data', []), market, since, limit);
- const result = [];
- for (let i = 0; i < orders.length; i++) {
- const order = orders[i];
- const orderTrades = [];
- const orderFee = this.safeValue (order, 'fee', {});
- const orderFeeCurrency = this.safeString (orderFee, 'currency');
- if (order['trades'] !== undefined) {
- for (let j = 0; j < order['trades'].length; j++) {
- const orderTrade = order['trades'][j];
- const orderTradeId = orderTrade['id'];
- if (orderTradeId in tradesById) {
- orderTrades.push (this.deepExtend (tradesById[orderTradeId], {
- 'order': order['id'],
- 'type': order['type'],
- 'symbol': order['symbol'],
- 'fee': {
- 'currency': orderFeeCurrency,
- },
- }));
- }
- }
- }
- const numOrderTrades = orderTrades.length;
- if (numOrderTrades > 0) {
- order['trades'] = orderTrades;
- }
- result.push (order);
- }
- return result;
- }
-
- async fetchOrder (id, symbol = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'id': id,
- 'include': 'trades',
- };
- const response = await this.privateGetOrderId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543436451996 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543436451996 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543436451996 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } },
- // { type: "trade",
- // id: "34789_34793",
- // attributes: { fee: 0.0001925,
- // price: 0.000035,
- // amount: 220,
- // total: 0.0077,
- // operation: "buy",
- // createdAt: "2018-11-28T19:47:57.451Z" } } ],
- // data: { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543436451996,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } },
- // trades: { data: [{ type: "trade", id: "34789_34793" }] } } } }
- //
- const data = this.safeValue (response, 'data');
- response['data'] = [];
- response['data'].push (data);
- const orders = this.parseOrdersResponse (response);
- const ordersById = this.indexBy (orders, 'id');
- if (id in ordersById) {
- return ordersById[id];
- }
- throw new OrderNotFound (this.id + ' fetchOrder could not find order id ' + id.toString ());
- }
-
- nonce () {
- return this.milliseconds ();
- }
-
- sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- let payload = '/' + this.implodeParams (path, params);
- let url = this.urls['api'] + '/' + this.version + payload;
- const query = this.omit (params, this.extractParams (path));
- if (method === 'GET') {
- if (Object.keys (query).length) {
- url += '?' + this.urlencode (query);
- }
- }
- if (api === 'private') {
- const nonce = this.nonce ();
- let expiredAt = this.sum (nonce, this.safeInteger (this.options, 'expiredAt', 10000));
- expiredAt = expiredAt.toString ();
- if ((method === 'POST') || (method === 'PATCH')) {
- body = this.json (query);
- payload = body;
- }
- if (this.token) {
- headers = {
- 'Cookie': 'token=' + this.token,
- };
- } else {
- this.checkRequiredCredentials ();
- const auth = method + payload + 'expiredAt=' + expiredAt;
- const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha512', 'base64');
- headers = {
- 'X-ADX-EXPIRE': expiredAt,
- 'X-ADX-APIKEY': this.apiKey,
- 'X-ADX-SIGNATURE': signature,
- };
- }
- if (method !== 'GET') {
- headers['Content-Type'] = 'application/json';
- }
- }
- return { 'url': url, 'method': method, 'body': body, 'headers': headers };
- }
-
- handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
- if (response === undefined) {
- return; // fallback to default error handler
- }
- const errors = this.safeValue (response, 'errors', []);
- const numErrors = errors.length;
- if (numErrors > 0) {
- const error = errors[0];
- const code = this.safeString (error, 'code');
- const status = this.safeString (error, 'status');
- const title = this.safeString (error, 'title');
- const detail = this.safeString (error, 'detail');
- const feedback = this.id + ' ' + this.json (response);
- this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], status, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], title, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], detail, feedback);
- this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
- throw new ExchangeError (feedback); // unknown message
- }
- }
-};
-
-},{"./base/Exchange":8,"./base/errors":10}],6:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],5:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -3440,7 +2182,7 @@ module.exports = class anxpro extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],7:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],6:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -3473,6 +2215,7 @@ module.exports = class aofex extends Exchange {
'fetchOpenOrders': true,
'fetchClosedOrders': true,
'fetchClosedOrder': true,
+ 'fetchOrderTrades': true,
'fetchTradingFee': true,
},
'timeframes': {
@@ -4002,7 +2745,7 @@ module.exports = class aofex extends Exchange {
//
const id = this.safeString (trade, 'id');
const ctime = this.parse8601 (this.safeString (trade, 'ctime'));
- const timestamp = this.safeTimestamp (trade, 'ts', ctime);
+ const timestamp = this.safeTimestamp (trade, 'ts', ctime) - 28800000; // 8 hours, adjust to UTC;
let symbol = undefined;
if ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
@@ -4168,7 +2911,7 @@ module.exports = class aofex extends Exchange {
base = market['base'];
quote = market['quote'];
}
- const timestamp = this.parse8601 (this.safeString (order, 'ctime'));
+ const timestamp = this.parse8601 (this.safeString (order, 'ctime')) - 28800000; // 8 hours, adjust to UTC
const orderType = this.safeString (order, 'type');
const type = (orderType === '2') ? 'limit' : 'market';
const side = this.safeString (order, 'side');
@@ -4326,11 +3069,16 @@ module.exports = class aofex extends Exchange {
return this.parseOrder (order);
}
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ const response = await this.fetchClosedOrder (id, symbol, params);
+ return this.safeValue (response, 'trades', []);
+ }
+
async fetchOrdersWithMethod (method, symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const request = {
// 'from': 'BM7442641584965237751ZMAKJ5', // query start order_sn
- // 'direct': 'prev', // next
+ 'direct': 'prev', // next
};
let market = undefined;
if (symbol !== undefined) {
@@ -4561,7 +3309,7 @@ module.exports = class aofex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],8:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],7:[function(require,module,exports){
(function (Buffer){
"use strict";
@@ -4853,8 +3601,9 @@ module.exports = class Exchange {
const config = deepExtend (this.describe (), userConfig)
// merge to this
- for (const [property, value] of Object.entries (config))
+ for (const [property, value] of Object.entries (config)) {
this[property] = deepExtend (this[property], value)
+ }
if (!this.httpAgent) {
this.httpAgent = defaultFetch.http ? new defaultFetch.http.Agent ({ 'keepAlive': true }) : undefined
@@ -4869,13 +3618,15 @@ module.exports = class Exchange {
this['has' + capitalize (k)] = !!this.has[k] // converts 'emulated' to true
}
- if (this.api)
+ if (this.api) {
this.defineRestApi (this.api, 'request')
+ }
this.initRestRateLimiter ()
- if (this.markets)
+ if (this.markets) {
this.setMarkets (this.markets)
+ }
}
defaults () {
@@ -4907,20 +3658,23 @@ module.exports = class Exchange {
checkAddress (address) {
- if (address === undefined)
+ if (address === undefined) {
throw new InvalidAddress (this.id + ' address is undefined')
+ }
// check the address is not the same letter like 'aaaaa' nor too short nor has a space
- if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' '))
+ if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' ')) {
throw new InvalidAddress (this.id + ' address is invalid or has less than ' + this.minFundingAddressLength.toString () + ' characters: "' + this.json (address) + '"')
+ }
return address
}
initRestRateLimiter () {
- if (this.rateLimit === undefined)
+ if (this.rateLimit === undefined) {
throw new Error (this.id + '.rateLimit property is not configured')
+ }
this.tokenBucket = this.extend ({
delay: 1,
@@ -4951,15 +3705,17 @@ module.exports = class Exchange {
const promise =
fetchImplementation (url, this.extend (params, this.fetchOptions))
.catch ((e) => {
- if (isNode)
+ if (isNode) {
throw new ExchangeNotAvailable ([ this.id, method, url, e.type, e.message ].join (' '))
+ }
throw e // rethrow all unknown errors
})
- .then (response => this.handleRestResponse (response, url, method, headers, body))
+ .then ((response) => this.handleRestResponse (response, url, method, headers, body))
return timeout (this.timeout, promise).catch ((e) => {
- if (e instanceof TimedOut)
+ if (e instanceof TimedOut) {
throw new RequestTimeout (this.id + ' ' + method + ' ' + url + ' request timed out (' + this.timeout + ' ms)')
+ }
throw e
})
}
@@ -5007,16 +3763,20 @@ module.exports = class Exchange {
let underscore = type + '_' + lowercaseMethod + '_' + underscoreSuffix
if ('suffixes' in options) {
- if ('camelcase' in options['suffixes'])
+ if ('camelcase' in options['suffixes']) {
camelcase += options['suffixes']['camelcase']
- if ('underscore' in options.suffixes)
+ }
+ if ('underscore' in options.suffixes) {
underscore += options['suffixes']['underscore']
+ }
}
- if ('underscore_suffix' in options)
+ if ('underscore_suffix' in options) {
underscore += options.underscoreSuffix;
- if ('camelcase_suffix' in options)
+ }
+ if ('camelcase_suffix' in options) {
camelcase += options.camelcaseSuffix;
+ }
let partial = async params => this[methodName] (path, type, uppercaseMethod, params || {})
@@ -5159,7 +3919,7 @@ module.exports = class Exchange {
getResponseHeaders (response) {
const result = {}
response.headers.forEach ((value, key) => {
- key = key.split ('-').map (word => capitalize (word)).join ('-')
+ key = key.split ('-').map ((word) => capitalize (word)).join ('-')
result[key] = value
})
return result
@@ -5197,7 +3957,7 @@ module.exports = class Exchange {
}
setMarkets (markets, currencies = undefined) {
- const values = Object.values (markets).map (market => deepExtend ({
+ const values = Object.values (markets).map ((market) => deepExtend ({
'limits': this.limits,
'precision': this.precision,
}, this.fees['trading'], market))
@@ -5368,6 +4128,22 @@ module.exports = class Exchange {
throw new NotSupported (this.id + ' fetchOrder not supported yet');
}
+ fetchUnifiedOrder (order, params = {}) {
+ return this.fetchOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
+ }
+
+ createOrder (symbol, type, side, amount, price = undefined, params = {}) {
+ throw new NotSupported (this.id + ' createOrder not supported yet');
+ }
+
+ cancelOrder (id, symbol = undefined, params = {}) {
+ throw new NotSupported (this.id + ' cancelOrder not supported yet');
+ }
+
+ cancelUnifiedOrder (order, params = {}) {
+ return this.cancelOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
+ }
+
fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported (this.id + ' fetchOrders not supported yet');
}
@@ -6021,7 +4797,7 @@ module.exports = class Exchange {
}).call(this,require("buffer").Buffer)
-},{"../static_dependencies/BN/bn":120,"./errors":10,"./functions":11,"buffer":179}],9:[function(require,module,exports){
+},{"../static_dependencies/BN/bn":119,"./errors":9,"./functions":10,"buffer":178}],8:[function(require,module,exports){
'use strict';
const errorHierarchy = {
@@ -6067,7 +4843,7 @@ const errorHierarchy = {
module.exports = errorHierarchy;
-},{}],10:[function(require,module,exports){
+},{}],9:[function(require,module,exports){
'use strict';
const errorHierarchy = require ('./errorHierarchy.js')
@@ -6120,7 +4896,7 @@ module.exports = subclass (
errorHierarchy
)
-},{"./errorHierarchy.js":9}],11:[function(require,module,exports){
+},{"./errorHierarchy.js":8}],10:[function(require,module,exports){
'use strict';
/* ------------------------------------------------------------------------ */
@@ -6150,7 +4926,7 @@ module.exports = unCamelCasePropertyNames (Object.assign ({}
/* ------------------------------------------------------------------------ */
-},{"./functions/crypto":12,"./functions/encode":13,"./functions/generic":14,"./functions/misc":15,"./functions/number":16,"./functions/platform":17,"./functions/string":18,"./functions/throttle":19,"./functions/time":20,"./functions/type":21}],12:[function(require,module,exports){
+},{"./functions/crypto":11,"./functions/encode":12,"./functions/generic":13,"./functions/misc":14,"./functions/number":15,"./functions/platform":16,"./functions/string":17,"./functions/throttle":18,"./functions/time":19,"./functions/type":20}],11:[function(require,module,exports){
'use strict'
/* ------------------------------------------------------------------------ */
@@ -6299,7 +5075,7 @@ module.exports = {
/* ------------------------------------------------------------------------ */
-},{"../../static_dependencies/BN/bn.js":120,"../../static_dependencies/crypto-js/crypto-js":121,"./../../static_dependencies/elliptic/lib/elliptic":122,"./../../static_dependencies/node-rsa/NodeRSA":137,"./../errors":10,"./encode":13,"./string":18}],13:[function(require,module,exports){
+},{"../../static_dependencies/BN/bn.js":119,"../../static_dependencies/crypto-js/crypto-js":120,"./../../static_dependencies/elliptic/lib/elliptic":121,"./../../static_dependencies/node-rsa/NodeRSA":136,"./../errors":9,"./encode":12,"./string":17}],12:[function(require,module,exports){
"use strict";
/* ------------------------------------------------------------------------ */
@@ -6372,7 +5148,7 @@ module.exports['byteArrayToWordArray'] = byteArrayToWordArray
/* ------------------------------------------------------------------------ */
-},{"../../static_dependencies/BN/bn":120,"../../static_dependencies/crypto-js/crypto-js":121,"../../static_dependencies/qs/index":153}],14:[function(require,module,exports){
+},{"../../static_dependencies/BN/bn":119,"../../static_dependencies/crypto-js/crypto-js":120,"../../static_dependencies/qs/index":152}],13:[function(require,module,exports){
"use strict";
/* ------------------------------------------------------------------------ */
@@ -6613,7 +5389,7 @@ module.exports =
}
-},{"./type":21}],15:[function(require,module,exports){
+},{"./type":20}],14:[function(require,module,exports){
'use strict';
const { ROUND_UP, ROUND_DOWN } = require ('./number')
@@ -6746,7 +5522,7 @@ module.exports = {
/* ------------------------------------------------------------------------ */
-},{"./../errors":10,"./number":16}],16:[function(require,module,exports){
+},{"./../errors":9,"./number":15}],15:[function(require,module,exports){
'use strict'
/* ------------------------------------------------------------------------
@@ -6794,23 +5570,27 @@ function numberToString (x) { // avoids scientific notation for too large and to
if (typeof x === 'string') return x
+ const s = x.toString ()
if (Math.abs (x) < 1.0) {
- const s = x.toString ()
const e = parseInt (s.split ('e-')[1])
const neg = (s[0] === '-')
if (e) {
x *= Math.pow (10, e - 1)
x = (neg ? '-' : '') + '0.' + (new Array (e)).join ('0') + x.toString ().substring (neg ? 3 : 2)
+ return x
}
} else {
- let e = parseInt (x.toString ().split ('+')[1])
- if (e > 20) {
- e -= 20
- x /= Math.pow (10, e)
- x += (new Array (e + 1)).join ('0')
+ const parts = s.split ('e')
+ if (parts[1]) {
+ let e = parseInt (parts[1])
+ const m = parts[0].split ('.')
+ if (m[1]) {
+ e -= m[1].length
+ }
+ return m[0] + m[1] + (new Array (e + 1)).join ('0')
}
}
- return x.toString ()
+ return s;
}
//-----------------------------------------------------------------------------
@@ -7079,7 +5859,7 @@ module.exports = {
/* ------------------------------------------------------------------------ */
-},{}],17:[function(require,module,exports){
+},{}],16:[function(require,module,exports){
(function (process){
"use strict";
@@ -7120,7 +5900,7 @@ module.exports = {
defaultFetch,
}
}).call(this,require('_process'))
-},{"../../static_dependencies/fetch-ponyfill/fetch-node":135,"_process":201}],18:[function(require,module,exports){
+},{"../../static_dependencies/fetch-ponyfill/fetch-node":134,"_process":200}],17:[function(require,module,exports){
"use strict";
/* ------------------------------------------------------------------------ */
@@ -7143,7 +5923,7 @@ module.exports =
/* ------------------------------------------------------------------------ */
-},{}],19:[function(require,module,exports){
+},{}],18:[function(require,module,exports){
"use strict";
/* ------------------------------------------------------------------------ */
@@ -7209,7 +5989,7 @@ module.exports = {
/* ------------------------------------------------------------------------ */
-},{"./time":20}],20:[function(require,module,exports){
+},{"./time":19}],19:[function(require,module,exports){
'use strict';
/* ------------------------------------------------------------------------ */
@@ -7396,7 +6176,7 @@ module.exports =
/* ------------------------------------------------------------------------ */
-},{}],21:[function(require,module,exports){
+},{}],20:[function(require,module,exports){
"use strict";
/* ------------------------------------------------------------------------ */
@@ -7463,7 +6243,7 @@ module.exports = {
/* ------------------------------------------------------------------------ */
-},{}],22:[function(require,module,exports){
+},{}],21:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -8144,7 +6924,7 @@ module.exports = class bcex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],23:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],22:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -8178,7 +6958,7 @@ module.exports = class bequant extends hitbtc {
}
};
-},{"./hitbtc":90}],24:[function(require,module,exports){
+},{"./hitbtc":90}],23:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -9148,7 +7928,7 @@ module.exports = class bibox extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],25:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],24:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -10406,13 +9186,13 @@ module.exports = class bigone extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],26:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],25:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied } = require ('./base/errors');
+const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied, NotSupported } = require ('./base/errors');
const { ROUND, TRUNCATE } = require ('./base/functions/number');
// ---------------------------------------------------------------------------
@@ -10446,6 +9226,7 @@ module.exports = class binance extends Exchange {
'fetchTransactions': false,
'fetchTradingFee': true,
'fetchTradingFees': true,
+ 'cancelAllOrders': true,
},
'timeframes': {
'1m': '1m',
@@ -10466,6 +9247,10 @@ module.exports = class binance extends Exchange {
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/29604020-d5483cdc-87ee-11e7-94c7-d1a8d9169293.jpg',
+ 'test': {
+ 'fapiPublic': 'https://testnet.binancefuture.com/fapi/v1',
+ 'fapiPrivate': 'https://testnet.binancefuture.com/fapi/v1',
+ },
'api': {
'web': 'https://www.binance.com',
'wapi': 'https://api.binance.com/wapi/v3',
@@ -10539,6 +9324,8 @@ module.exports = class binance extends Exchange {
'lending/union/purchaseRecord',
'lending/union/redemptionRecord',
'lending/union/interestHistory',
+ 'lending/project/list',
+ 'lending/project/position/list',
],
'post': [
'asset/dust',
@@ -10555,6 +9342,7 @@ module.exports = class binance extends Exchange {
'userDataStream',
'futures/transfer',
// lending
+ 'lending/customizedFixed/purchase',
'lending/daily/purchase',
'lending/daily/redeem',
],
@@ -10620,6 +9408,8 @@ module.exports = class binance extends Exchange {
'income',
],
'post': [
+ 'batchOrders',
+ 'positionSide/dual',
'positionMargin',
'marginType',
'order',
@@ -10630,6 +9420,7 @@ module.exports = class binance extends Exchange {
'listenKey',
],
'delete': [
+ 'batchOrders',
'order',
'allOpenOrders',
'listenKey',
@@ -10676,6 +9467,7 @@ module.exports = class binance extends Exchange {
'order/test',
],
'delete': [
+ 'openOrders', // added on 2020-04-25 for canceling all open orders per symbol
'orderList', // oco
'order',
],
@@ -10698,7 +9490,6 @@ module.exports = class binance extends Exchange {
'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades
'fetchTickersMethod': 'publicGetTicker24hr',
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
- 'defaultLimitOrderType': 'limit', // or 'limit_maker'
'defaultType': 'spot', // 'spot', 'future'
'hasAlreadyAuthenticatedSuccessfully': false,
'warnOnFetchOpenOrdersWithoutSymbol': true,
@@ -10735,6 +9526,32 @@ module.exports = class binance extends Exchange {
});
}
+ setSandboxMode (enabled) {
+ if (enabled) { // eslint-disable-line no-extra-boolean-cast
+ if ('test' in this.urls) {
+ const type = this.safeString (this.options, 'defaultType', 'spot');
+ if (type !== 'future') {
+ throw new NotSupported (this.id + ' does not have a sandbox URL for ' + type + " markets, set exchange.options['defaultType'] = 'future' or don't use the sandbox for " + this.id);
+ }
+ if (typeof this.urls['api'] === 'string') {
+ this.urls['api_backup'] = this.urls['api'];
+ this.urls['api'] = this.urls['test'];
+ } else {
+ this.urls['api_backup'] = this.extend ({}, this.urls['api']);
+ this.urls['api'] = this.extend ({}, this.urls['test']);
+ }
+ } else {
+ throw new NotSupported (this.id + ' does not have a sandbox URL');
+ }
+ } else if ('api_backup' in this.urls) {
+ if (typeof this.urls['api'] === 'string') {
+ this.urls['api'] = this.urls['api_backup'];
+ } else {
+ this.urls['api'] = this.extend ({}, this.urls['api_backup']);
+ }
+ }
+ }
+
nonce () {
return this.milliseconds () - this.options['timeDifference'];
}
@@ -10885,7 +9702,7 @@ module.exports = class binance extends Exchange {
'max': undefined,
},
'cost': {
- 'min': -1 * Math.log10 (precision['amount']),
+ 'min': undefined,
'max': undefined,
},
},
@@ -11129,7 +9946,7 @@ module.exports = class binance extends Exchange {
async fetchBidsAsks (symbols = undefined, params = {}) {
await this.loadMarkets ();
- const defaultType = this.safeString2 (this.options, 'fetchOpenOrders', 'defaultType', 'spot');
+ const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot');
const type = this.safeString (params, 'type', defaultType);
const query = this.omit (params, 'type');
const method = (type === 'spot') ? 'publicGetTickerBookTicker' : 'fapiPublicGetTickerBookTicker';
@@ -11146,12 +9963,12 @@ module.exports = class binance extends Exchange {
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
return [
- ohlcv[0],
- parseFloat (ohlcv[1]),
- parseFloat (ohlcv[2]),
- parseFloat (ohlcv[3]),
- parseFloat (ohlcv[4]),
- parseFloat (ohlcv[5]),
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 5),
];
}
@@ -11279,6 +10096,10 @@ module.exports = class binance extends Exchange {
if (market !== undefined) {
symbol = market['symbol'];
}
+ let cost = undefined;
+ if ((price !== undefined) && (amount !== undefined)) {
+ cost = price * amount;
+ }
return {
'info': trade,
'timestamp': timestamp,
@@ -11287,11 +10108,11 @@ module.exports = class binance extends Exchange {
'id': id,
'order': orderId,
'type': undefined,
- 'takerOrMaker': takerOrMaker,
'side': side,
+ 'takerOrMaker': takerOrMaker,
'price': price,
'amount': amount,
- 'cost': price * amount,
+ 'cost': cost,
'fee': fee,
};
}
@@ -11589,6 +10410,8 @@ module.exports = class binance extends Exchange {
} else if (uppercaseType === 'STOP') {
stopPriceIsRequired = true;
priceIsRequired = true;
+ } else if (uppercaseType === 'STOP_MARKET') {
+ stopPriceIsRequired = true;
}
if (priceIsRequired) {
if (price === undefined) {
@@ -11748,6 +10571,27 @@ module.exports = class binance extends Exchange {
return this.parseOrder (response);
}
+ async cancelAllOrders (symbol = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' cancelAllOrders requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const defaultType = this.safeString2 (this.options, 'cancelAllOrders', 'defaultType', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ const method = (type === 'spot') ? 'privateDeleteOpenOrders' : 'fapiPrivateDeleteAllOpenOrders';
+ const response = await this[method] (this.extend (request, query));
+ if (Array.isArray (response)) {
+ return this.parseOrders (response, market);
+ } else {
+ return response;
+ }
+ }
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
@@ -11980,10 +10824,7 @@ module.exports = class binance extends Exchange {
}
parseTransactionStatusByType (status, type = undefined) {
- if (type === undefined) {
- return status;
- }
- const statuses = {
+ const statusesByType = {
'deposit': {
'0': 'pending',
'1': 'ok',
@@ -11998,32 +10839,38 @@ module.exports = class binance extends Exchange {
'6': 'ok', // Completed
},
};
- return (status in statuses[type]) ? statuses[type][status] : status;
+ const statuses = this.safeValue (statusesByType, type, {});
+ return this.safeString (statuses, status, status);
}
parseTransaction (transaction, currency = undefined) {
//
// fetchDeposits
- // { insertTime: 1517425007000,
- // amount: 0.3,
- // address: "0x0123456789abcdef",
- // addressTag: "",
- // txId: "0x0123456789abcdef",
- // asset: "ETH",
- // status: 1 }
+ //
+ // {
+ // insertTime: 1517425007000,
+ // amount: 0.3,
+ // address: "0x0123456789abcdef",
+ // addressTag: "",
+ // txId: "0x0123456789abcdef",
+ // asset: "ETH",
+ // status: 1
+ // }
//
// fetchWithdrawals
//
- // { amount: 14,
- // address: "0x0123456789abcdef...",
+ // {
+ // amount: 14,
+ // address: "0x0123456789abcdef...",
// successTime: 1514489710000,
- // transactionFee: 0.01,
- // addressTag: "",
- // txId: "0x0123456789abcdef...",
- // id: "0123456789abcdef...",
- // asset: "ETH",
- // applyTime: 1514488724000,
- // status: 6 }
+ // transactionFee: 0.01,
+ // addressTag: "",
+ // txId: "0x0123456789abcdef...",
+ // id: "0123456789abcdef...",
+ // asset: "ETH",
+ // applyTime: 1514488724000,
+ // status: 6
+ // }
//
const id = this.safeString (transaction, 'id');
const address = this.safeString (transaction, 'address');
@@ -12033,7 +10880,7 @@ module.exports = class binance extends Exchange {
tag = undefined;
}
}
- const txid = this.safeValue (transaction, 'txId');
+ const txid = this.safeString (transaction, 'txId');
const currencyId = this.safeString (transaction, 'asset');
const code = this.safeCurrencyCode (currencyId, currency);
let timestamp = undefined;
@@ -12263,6 +11110,11 @@ module.exports = class binance extends Exchange {
'timestamp': this.nonce (),
'recvWindow': this.options['recvWindow'],
}, params));
+ } else if (path === 'batchOrders') {
+ query = this.rawencode (this.extend ({
+ 'timestamp': this.nonce (),
+ 'recvWindow': this.options['recvWindow'],
+ }, params));
} else {
query = this.urlencode (this.extend ({
'timestamp': this.nonce (),
@@ -12369,7 +11221,7 @@ module.exports = class binance extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],27:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],26:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -12424,7 +11276,7 @@ module.exports = class binanceje extends binance {
};
-},{"./binance.js":26}],28:[function(require,module,exports){
+},{"./binance.js":25}],27:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -12458,10 +11310,10 @@ module.exports = class binanceus extends binance {
},
'fees': {
'trading': {
- 'tierBased': false,
+ 'tierBased': true,
'percentage': true,
- 'taker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
- 'maker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
+ 'taker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
+ 'maker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
},
},
});
@@ -12469,7 +11321,7 @@ module.exports = class binanceus extends binance {
};
-},{"./binance.js":26}],29:[function(require,module,exports){
+},{"./binance.js":25}],28:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -12891,7 +11743,7 @@ module.exports = class bit2c extends Exchange {
};
-},{"./base/Exchange":8,"./base/errors":10}],30:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],29:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -13460,13 +12312,13 @@ module.exports = class bitbank extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],31:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],30:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded } = require ('./base/errors');
+const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -13516,6 +12368,7 @@ module.exports = class bitbay extends Exchange {
'https://github.com/BitBayNet/API',
'https://docs.bitbay.net/v1.0.1-en/reference',
],
+ 'support': 'https://support.bitbay.net',
'fees': 'https://bitbay.net/en/fees',
},
'api': {
@@ -13580,8 +12433,60 @@ module.exports = class bitbay extends Exchange {
},
'fees': {
'trading': {
+ 'maker': 0.0,
+ 'taker': 0.1 / 100,
+ 'percentage': true,
+ 'tierBased': false,
+ },
+ 'fiat': {
'maker': 0.30 / 100,
'taker': 0.43 / 100,
+ 'percentage': true,
+ 'tierBased': true,
+ 'tiers': {
+ 'taker': [
+ [ 0.0043, 0 ],
+ [ 0.0042, 1250 ],
+ [ 0.0041, 3750 ],
+ [ 0.0040, 7500 ],
+ [ 0.0039, 10000 ],
+ [ 0.0038, 15000 ],
+ [ 0.0037, 20000 ],
+ [ 0.0036, 25000 ],
+ [ 0.0035, 37500 ],
+ [ 0.0034, 50000 ],
+ [ 0.0033, 75000 ],
+ [ 0.0032, 100000 ],
+ [ 0.0031, 150000 ],
+ [ 0.0030, 200000 ],
+ [ 0.0029, 250000 ],
+ [ 0.0028, 375000 ],
+ [ 0.0027, 500000 ],
+ [ 0.0026, 625000 ],
+ [ 0.0025, 875000 ],
+ ],
+ 'maker': [
+ [ 0.0030, 0 ],
+ [ 0.0029, 1250 ],
+ [ 0.0028, 3750 ],
+ [ 0.0028, 7500 ],
+ [ 0.0027, 10000 ],
+ [ 0.0026, 15000 ],
+ [ 0.0025, 20000 ],
+ [ 0.0025, 25000 ],
+ [ 0.0024, 37500 ],
+ [ 0.0023, 50000 ],
+ [ 0.0023, 75000 ],
+ [ 0.0022, 100000 ],
+ [ 0.0021, 150000 ],
+ [ 0.0021, 200000 ],
+ [ 0.0020, 250000 ],
+ [ 0.0019, 375000 ],
+ [ 0.0018, 500000 ],
+ [ 0.0018, 625000 ],
+ [ 0.0017, 875000 ],
+ ],
+ },
},
'funding': {
'withdraw': {
@@ -13598,6 +12503,9 @@ module.exports = class bitbay extends Exchange {
},
},
},
+ 'options': {
+ 'fiatCurrencies': [ 'EUR', 'USD', 'GBP', 'PLN' ],
+ },
'exceptions': {
'400': ExchangeError, // At least one parameter wasn't set
'401': InvalidOrder, // Invalid order type
@@ -13622,12 +12530,14 @@ module.exports = class bitbay extends Exchange {
'OFFER_NOT_FOUND': OrderNotFound,
'OFFER_WOULD_HAVE_BEEN_PARTIALLY_FILLED': OrderImmediatelyFillable,
'ACTION_LIMIT_EXCEEDED': RateLimitExceeded,
+ 'UNDER_MAINTENANCE': OnMaintenance,
},
});
}
async fetchMarkets (params = {}) {
const response = await this.v1_01PublicGetTradingTicker (params);
+ const fiatCurrencies = this.safeValue (this.options, 'fiatCurrencies', []);
//
// {
// status: 'Ok',
@@ -13666,6 +12576,12 @@ module.exports = class bitbay extends Exchange {
'amount': this.safeInteger (first, 'scale'),
'price': this.safeInteger (second, 'scale'),
};
+ let fees = this.safeValue (this.fees, 'trading', {});
+ if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) {
+ fees = this.safeValue (this.fees, 'fiat', {});
+ }
+ const maker = this.safeFloat (fees, 'maker');
+ const taker = this.safeFloat (fees, 'taker');
// todo: check that the limits have ben interpreted correctly
// todo: parse the fees page
result.push ({
@@ -13677,7 +12593,8 @@ module.exports = class bitbay extends Exchange {
'quoteId': quoteId,
'precision': precision,
'active': undefined,
- 'fee': undefined,
+ 'maker': maker,
+ 'taker': taker,
'limits': {
'amount': {
'min': this.safeFloat (first, 'minOffer'),
@@ -14676,7 +13593,7 @@ module.exports = class bitbay extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],32:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],31:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -15584,12 +14501,12 @@ module.exports = class bitfinex extends Exchange {
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
return [
- ohlcv[0],
- ohlcv[1],
- ohlcv[3],
- ohlcv[4],
- ohlcv[2],
- ohlcv[5],
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 5),
];
}
@@ -15861,7 +14778,7 @@ module.exports = class bitfinex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],33:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],32:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -16563,6 +15480,7 @@ module.exports = class bitfinex2 extends bitfinex {
'PARTIALLY FILLED': 'open',
'EXECUTED': 'closed',
'CANCELED': 'canceled',
+ 'CANCELED was: PARTIALLY FILLED': 'canceled',
'INSUFFICIENT MARGIN': 'canceled',
'INSUFFICIENT BALANCE (G1) was: PARTIALLY FILLED': 'canceled',
'RSN_DUST': 'rejected',
@@ -17055,7 +15973,7 @@ module.exports = class bitfinex2 extends bitfinex {
}
};
-},{"./base/errors":10,"./bitfinex.js":32}],34:[function(require,module,exports){
+},{"./base/errors":9,"./bitfinex.js":31}],33:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -17547,7 +16465,7 @@ module.exports = class bitflyer extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],35:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],34:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -18149,13 +17067,13 @@ module.exports = class bitforex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],36:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],35:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -18168,7 +17086,12 @@ module.exports = class bithumb extends Exchange {
'rateLimit': 500,
'has': {
'CORS': true,
+ 'createOrder': true,
+ 'cancelOrder': true,
+ 'createMarketOrder': true,
'fetchTickers': true,
+ 'fetchOpenOrders': true,
+ 'fetchOrder': true,
'withdraw': true,
},
'urls': {
@@ -18200,8 +17123,8 @@ module.exports = class bithumb extends Exchange {
'info/ticker',
'info/orders',
'info/user_transactions',
- 'trade/place',
'info/order_detail',
+ 'trade/place',
'trade/cancel',
'trade/btc_withdrawal',
'trade/krw_deposit',
@@ -18317,15 +17240,53 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
if (limit !== undefined) {
- request['count'] = limit; // max = 50
+ request['count'] = limit; // default 30, max 30
}
const response = await this.publicGetOrderbookCurrency (this.extend (request, params));
- const orderbook = this.safeValue (response, 'data');
- const timestamp = this.safeInteger (orderbook, 'timestamp');
- return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'price', 'quantity');
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "timestamp":"1587621553942",
+ // "payment_currency":"KRW",
+ // "order_currency":"BTC",
+ // "bids":[
+ // {"price":"8652000","quantity":"0.0043"},
+ // {"price":"8651000","quantity":"0.0049"},
+ // {"price":"8650000","quantity":"8.4791"},
+ // ],
+ // "asks":[
+ // {"price":"8654000","quantity":"0.119"},
+ // {"price":"8655000","quantity":"0.254"},
+ // {"price":"8658000","quantity":"0.119"},
+ // ]
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
+ const timestamp = this.safeInteger (data, 'timestamp');
+ return this.parseOrderBook (data, timestamp, 'bids', 'asks', 'price', 'quantity');
}
parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker, fetchTickers
+ //
+ // {
+ // "opening_price":"227100",
+ // "closing_price":"228400",
+ // "min_price":"222300",
+ // "max_price":"230000",
+ // "units_traded":"82618.56075337",
+ // "acc_trade_value":"18767376138.6031",
+ // "prev_closing_price":"227100",
+ // "units_traded_24H":"151871.13484676",
+ // "acc_trade_value_24H":"34247610416.8974",
+ // "fluctate_24H":"8700",
+ // "fluctate_rate_24H":"3.96",
+ // "date":"1587710327264", // fetchTickers inject this
+ // }
+ //
const timestamp = this.safeInteger (ticker, 'date');
let symbol = undefined;
if (market !== undefined) {
@@ -18376,9 +17337,31 @@ module.exports = class bithumb extends Exchange {
async fetchTickers (symbols = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.publicGetTickerAll (params);
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "BTC":{
+ // "opening_price":"9045000",
+ // "closing_price":"9132000",
+ // "min_price":"8938000",
+ // "max_price":"9168000",
+ // "units_traded":"4619.79967497",
+ // "acc_trade_value":"42021363832.5187",
+ // "prev_closing_price":"9041000",
+ // "units_traded_24H":"8793.5045804",
+ // "acc_trade_value_24H":"78933458515.4962",
+ // "fluctate_24H":"530000",
+ // "fluctate_rate_24H":"6.16"
+ // },
+ // "date":"1587710878669"
+ // }
+ // }
+ //
const result = {};
- const timestamp = this.safeInteger (response['data'], 'date');
- const tickers = this.omit (response['data'], 'date');
+ const data = this.safeValue (response, 'data', {});
+ const timestamp = this.safeInteger (data, 'date');
+ const tickers = this.omit (data, 'date');
const ids = Object.keys (tickers);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
@@ -18405,19 +17388,72 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
const response = await this.publicGetTickerCurrency (this.extend (request, params));
- return this.parseTicker (response['data'], market);
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "opening_price":"227100",
+ // "closing_price":"228400",
+ // "min_price":"222300",
+ // "max_price":"230000",
+ // "units_traded":"82618.56075337",
+ // "acc_trade_value":"18767376138.6031",
+ // "prev_closing_price":"227100",
+ // "units_traded_24H":"151871.13484676",
+ // "acc_trade_value_24H":"34247610416.8974",
+ // "fluctate_24H":"8700",
+ // "fluctate_rate_24H":"3.96",
+ // "date":"1587710327264"
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
+ return this.parseTicker (data, market);
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "transaction_date":"2020-04-23 22:21:46",
+ // "type":"ask",
+ // "units_traded":"0.0125",
+ // "price":"8667000",
+ // "total":"108337"
+ // }
+ //
+ // fetchOrder (private)
+ //
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // }
+ //
// a workaround for their bug in date format, hours are not 0-padded
- const parts = trade['transaction_date'].split (' ');
- const transaction_date = parts[0];
- let transaction_time = parts[1];
- if (transaction_time.length < 8) {
- transaction_time = '0' + transaction_time;
+ let timestamp = undefined;
+ const transactionDatetime = this.safeString (trade, 'transaction_date');
+ if (transactionDatetime !== undefined) {
+ const parts = transactionDatetime.split (' ');
+ const numParts = parts.length;
+ if (numParts > 1) {
+ const transactionDate = parts[0];
+ let transactionTime = parts[1];
+ if (transactionTime.length < 8) {
+ transactionTime = '0' + transactionTime;
+ }
+ timestamp = this.parse8601 (transactionDate + ' ' + transactionTime);
+ } else {
+ timestamp = this.safeIntegerProduct (trade, 'transaction_date', 0.001);
+ }
+ }
+ if (timestamp !== undefined) {
+ timestamp -= 9 * 3600000; // they report UTC + 9 hours, server in Korean timezone
}
- let timestamp = this.parse8601 (transaction_date + ' ' + transaction_time);
- timestamp -= 9 * 3600000; // they report UTC + 9 hours (server in Korean timezone)
const type = undefined;
let side = this.safeString (trade, 'type');
side = (side === 'ask') ? 'sell' : 'buy';
@@ -18428,12 +17464,24 @@ module.exports = class bithumb extends Exchange {
}
const price = this.safeFloat (trade, 'price');
const amount = this.safeFloat (trade, 'units_traded');
- let cost = undefined;
- if (amount !== undefined) {
- if (price !== undefined) {
- cost = price * amount;
+ let cost = this.safeFloat (trade, 'total');
+ if (cost === undefined) {
+ if (amount !== undefined) {
+ if (price !== undefined) {
+ cost = price * amount;
+ }
}
}
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'fee');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'fee_currency');
+ const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId);
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ };
+ }
return {
'id': id,
'info': trade,
@@ -18447,7 +17495,7 @@ module.exports = class bithumb extends Exchange {
'price': price,
'amount': amount,
'cost': cost,
- 'fee': undefined,
+ 'fee': fee,
};
}
@@ -18461,57 +17509,276 @@ module.exports = class bithumb extends Exchange {
request['count'] = limit; // default 20, max 100
}
const response = await this.publicGetTransactionHistoryCurrency (this.extend (request, params));
- return this.parseTrades (response['data'], market, since, limit);
+ //
+ // {
+ // "status":"0000",
+ // "data":[
+ // {
+ // "transaction_date":"2020-04-23 22:21:46",
+ // "type":"ask",
+ // "units_traded":"0.0125",
+ // "price":"8667000",
+ // "total":"108337"
+ // },
+ // ]
+ // }
+ //
+ const data = this.safeValue (response, 'data', []);
+ return this.parseTrades (data, market, since, limit);
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
- let request = undefined;
- let method = 'privatePostTrade';
+ const request = {
+ 'order_currency': market['id'],
+ 'Payment_currency': market['quote'],
+ 'units': amount,
+ };
+ let method = 'privatePostTradePlace';
if (type === 'limit') {
- request = {
- 'order_currency': market['id'],
- 'Payment_currency': market['quote'],
- 'units': amount,
- 'price': price,
- 'type': (side === 'buy') ? 'bid' : 'ask',
- };
- method += 'Place';
- } else if (type === 'market') {
- request = {
- 'currency': market['id'],
- 'units': amount,
- };
- method += 'Market' + this.capitalize (side);
+ request['price'] = price;
+ request['type'] = (side === 'buy') ? 'bid' : 'ask';
+ } else {
+ method = 'privatePostTradeMarket' + this.capitalize (side);
}
const response = await this[method] (this.extend (request, params));
const id = this.safeString (response, 'order_id');
+ if (id === undefined) {
+ throw new InvalidOrder (this.id + ' createOrder did not return an order id');
+ }
return {
'info': response,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
'id': id,
};
}
+ async fetchOrder (id, symbol = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'order_id': id,
+ 'count': 1,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
+ };
+ const response = await this.privatePostInfoOrderDetail (this.extend (request, params));
+ //
+ // {
+ // "status": "0000",
+ // "data": {
+ // "transaction_date": "1572497603668315",
+ // "type": "bid",
+ // "order_status": "Completed",
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_price": "8601000",
+ // "order_qty": "0.007",
+ // "cancel_date": "",
+ // "cancel_type": "",
+ // "contract": [
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // },
+ // ]
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data');
+ return this.parseOrder (this.extend (data, { 'order_id': id }), market);
+ }
+
+ parseOrderStatus (status) {
+ const statuses = {
+ 'Pending': 'open',
+ 'Completed': 'closed',
+ 'Cancel': 'canceled',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ parseOrder (order, market = undefined) {
+ //
+ // fetchOrder
+ //
+ // {
+ // "transaction_date": "1572497603668315",
+ // "type": "bid",
+ // "order_status": "Completed",
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_price": "8601000",
+ // "order_qty": "0.007",
+ // "cancel_date": "",
+ // "cancel_type": "",
+ // "contract": [
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // },
+ // ]
+ // }
+ //
+ // fetchOpenOrders
+ //
+ // {
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_id": "C0101000007408440032",
+ // "order_date": "1571728739360570",
+ // "type": "bid",
+ // "units": "5.0",
+ // "units_remaining": "5.0",
+ // "price": "501000",
+ // }
+ //
+ const timestamp = this.safeIntegerProduct (order, 'order_date', 0.001);
+ const sideProperty = this.safeValue2 (order, 'type', 'side');
+ const side = (sideProperty === 'bid') ? 'buy' : 'sell';
+ const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
+ let price = this.safeFloat2 (order, 'order_price', 'price');
+ let type = 'limit';
+ if (price === 0) {
+ price = undefined;
+ type = 'market';
+ }
+ const amount = this.safeFloat2 (order, 'order_qty', 'units');
+ let remaining = this.safeFloat (order, 'units_remaining');
+ if (remaining === undefined) {
+ if (status === 'closed') {
+ remaining = 0;
+ } else {
+ remaining = amount;
+ }
+ }
+ let filled = undefined;
+ if ((amount !== undefined) && (remaining !== undefined)) {
+ filled = amount - remaining;
+ }
+ let symbol = undefined;
+ const baseId = this.safeString (order, 'order_currency');
+ const quoteId = this.safeString (order, 'payment_currency');
+ const base = this.safeCurrencyCode (baseId);
+ const quote = this.safeCurrencyCode (quoteId);
+ if ((base !== undefined) && (quote !== undefined)) {
+ symbol = base + '/' + quote;
+ }
+ if ((symbol === undefined) && (market !== undefined)) {
+ symbol = market['symbol'];
+ }
+ const rawTrades = this.safeValue (order, 'contract');
+ let trades = undefined;
+ const id = this.safeString (order, 'order_id');
+ if (rawTrades !== undefined) {
+ trades = this.parseTrades (rawTrades, market, undefined, undefined, {
+ 'side': side,
+ 'symbol': symbol,
+ 'order': id,
+ });
+ }
+ return {
+ 'info': order,
+ 'id': id,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
+ 'price': price,
+ 'amount': amount,
+ 'cost': undefined,
+ 'average': undefined,
+ 'filled': filled,
+ 'remaining': remaining,
+ 'status': status,
+ 'fee': undefined,
+ 'trades': trades,
+ };
+ }
+
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ if (limit === undefined) {
+ limit = 100;
+ }
+ const request = {
+ 'count': limit,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
+ };
+ if (since !== undefined) {
+ request['after'] = since;
+ }
+ const response = await this.privatePostInfoOrders (this.extend (request, params));
+ //
+ // {
+ // "status": "0000",
+ // "data": [
+ // {
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_id": "C0101000007408440032",
+ // "order_date": "1571728739360570",
+ // "type": "bid",
+ // "units": "5.0",
+ // "units_remaining": "5.0",
+ // "price": "501000",
+ // }
+ // ]
+ // }
+ //
+ const data = this.safeValue (response, 'data', []);
+ return this.parseOrders (data, market, since, limit);
+ }
+
async cancelOrder (id, symbol = undefined, params = {}) {
const side_in_params = ('side' in params);
if (!side_in_params) {
- throw new ExchangeError (this.id + ' cancelOrder requires a `side` parameter (sell or buy) and a `currency` parameter');
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
- const currency = this.safeString (params, 'currency');
- if (currency === undefined) {
- throw new ExchangeError (this.id + ' cancelOrder requires a `currency` parameter (a currency id)');
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
+ const market = this.market (symbol);
const side = (params['side'] === 'buy') ? 'bid' : 'ask';
params = this.omit (params, [ 'side', 'currency' ]);
+ // https://github.com/ccxt/ccxt/issues/6771
const request = {
'order_id': id,
'type': side,
- 'currency': currency,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
};
return await this.privatePostTradeCancel (this.extend (request, params));
}
+ cancelUnifiedOrder (order, params = {}) {
+ const request = {
+ 'side': order['side'],
+ };
+ return this.cancelOrder (order['id'], order['symbol'], this.extend (request, params));
+ }
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
this.checkAddress (address);
await this.loadMarkets ();
@@ -18524,7 +17791,7 @@ module.exports = class bithumb extends Exchange {
if (currency === 'XRP' || currency === 'XMR') {
const destination = this.safeString (params, 'destination');
if ((tag === undefined) && (destination === undefined)) {
- throw new ExchangeError (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
+ throw new ArgumentsRequired (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
} else if (tag !== undefined) {
request['destination'] = tag;
}
@@ -18602,7 +17869,7 @@ module.exports = class bithumb extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],37:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],36:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -18630,7 +17897,7 @@ module.exports = class bitkk extends zb {
}
};
-},{"./zb.js":173}],38:[function(require,module,exports){
+},{"./zb.js":172}],37:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -18668,6 +17935,7 @@ module.exports = class bitmart extends Exchange {
'fetchClosedOrders': true,
'fetchCanceledOrders': true,
'fetchOrder': true,
+ 'signIn': true,
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/61835713-a2662f80-ae85-11e9-9d00-6442919701fd.jpg',
@@ -18675,6 +17943,7 @@ module.exports = class bitmart extends Exchange {
'www': 'https://www.bitmart.com/',
'doc': 'https://github.com/bitmartexchange/bitmart-official-api-docs',
'referral': 'http://www.bitmart.com/?r=rQCFLh',
+ 'fees': 'https://www.bitmart.com/fee/en',
},
'requiredCredentials': {
'apiKey': true,
@@ -19558,7 +18827,7 @@ module.exports = class bitmart extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],39:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],38:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -20748,7 +20017,7 @@ module.exports = class bitmax extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],40:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],39:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -22079,7 +21348,7 @@ module.exports = class bitmex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],41:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],40:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -22648,7 +21917,7 @@ module.exports = class bitso extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],42:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],41:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -23785,11 +23054,19 @@ module.exports = class bitstamp extends Exchange {
body = this.urlencode (query);
contentType = 'application/x-www-form-urlencoded';
headers['Content-Type'] = contentType;
+ } else {
+ // sending an empty POST request will trigger
+ // an API0020 error returned by the exchange
+ // therefore for empty requests we send a dummy object
+ // https://github.com/ccxt/ccxt/issues/6846
+ body = this.urlencode ({ 'foo': 'bar' });
+ contentType = 'application/x-www-form-urlencoded';
+ headers['Content-Type'] = contentType;
}
}
const authBody = body ? body : '';
const auth = xAuth + method + url.replace ('https://', '') + contentType + xAuthNonce + xAuthTimestamp + xAuthVersion + authBody;
- const signature = this.encode (this.hmac (this.encode (auth), this.encode (this.secret)));
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret));
headers['X-Auth-Signature'] = signature;
}
}
@@ -23846,7 +23123,7 @@ module.exports = class bitstamp extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],43:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],42:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -24139,7 +23416,7 @@ module.exports = class bitstamp1 extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],44:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],43:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -25681,7 +24958,7 @@ module.exports = class bittrex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],45:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],44:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -26334,7 +25611,7 @@ module.exports = class bitz extends Exchange {
}
} else {
if (since !== undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
}
}
const response = await this.marketGetKline (this.extend (request, params));
@@ -26897,7 +26174,7 @@ module.exports = class bitz extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],46:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],45:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -27132,7 +26409,7 @@ module.exports = class bl3p extends Exchange {
}
};
-},{"./base/Exchange":8}],47:[function(require,module,exports){
+},{"./base/Exchange":7}],46:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -27208,6 +26485,9 @@ module.exports = class bleutrade extends Exchange {
],
},
'v3Private': {
+ 'get': [
+ 'statement',
+ ],
'post': [
'getbalance',
'getbalances',
@@ -27324,8 +26604,8 @@ module.exports = class bleutrade extends Exchange {
// MarketCurrencyLong: 'Litecoin',
// BaseCurrencyLong: 'Tether' }
const id = this.safeString (market, 'MarketName');
- const baseId = this.safeString (market, 'MarketCurrency');
- const quoteId = this.safeString (market, 'BaseCurrency');
+ const baseId = this.safeString (market, 'MarketAsset');
+ const quoteId = this.safeString (market, 'BaseAsset');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
const symbol = base + '/' + quote;
@@ -27970,7 +27250,7 @@ module.exports = class bleutrade extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],48:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],47:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -28590,7 +27870,7 @@ module.exports = class braziliex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],49:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],48:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -29068,7 +28348,7 @@ module.exports = class btcalpha extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],50:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],49:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -29487,7 +28767,7 @@ module.exports = class btcbox extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],51:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],50:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -30247,7 +29527,7 @@ module.exports = class btcmarkets extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],52:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],51:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -30320,7 +29600,7 @@ module.exports = class btctradeim extends coinegg {
}
};
-},{"./base/errors":10,"./coinegg.js":65}],53:[function(require,module,exports){
+},{"./base/errors":9,"./coinegg.js":64}],52:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -30341,6 +29621,7 @@ module.exports = class btctradeua extends Exchange {
'CORS': false,
'createMarketOrder': false,
'fetchOpenOrders': true,
+ 'signIn': true,
},
'urls': {
'referral': 'https://btc-trade.com.ua/registration/22689',
@@ -30706,7 +29987,7 @@ module.exports = class btctradeua extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],54:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],53:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -31029,13 +30310,13 @@ module.exports = class btcturk extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],55:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],54:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied } = require ('./base/errors');
+const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -31724,7 +31005,7 @@ module.exports = class buda extends Exchange {
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
if (code === undefined) {
- throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
+ throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
}
const currency = this.currency (code);
const request = {
@@ -31739,7 +31020,7 @@ module.exports = class buda extends Exchange {
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
if (code === undefined) {
- throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
+ throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
}
const currency = this.currency (code);
const request = {
@@ -31819,7 +31100,7 @@ module.exports = class buda extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],56:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],55:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -33006,14 +32287,14 @@ module.exports = class bw extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],57:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],56:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { TICK_SIZE } = require ('./base/functions/number');
-const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce } = require ('./base/errors');
+const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce, NotSupported } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -33057,7 +32338,7 @@ module.exports = class bybit extends Exchange {
'30m': '30',
'1h': '60',
'2h': '120',
- '3h': '180',
+ '4h': '240',
'6h': '360',
'12h': '720',
'1d': 'D',
@@ -33072,6 +32353,7 @@ module.exports = class bybit extends Exchange {
'www': 'https://www.bybit.com/',
'doc': [
'https://bybit-exchange.github.io/docs/inverse/',
+ 'https://bybit-exchange.github.io/docs/linear/',
'https://github.com/bybit-exchange',
],
'fees': 'https://help.bybit.com/hc/en-us/articles/360039261154',
@@ -33125,6 +32407,41 @@ module.exports = class bybit extends Exchange {
'position/trading-stop',
],
},
+ 'publicLinear': {
+ 'get': [
+ 'kline',
+ 'recent-trading-records',
+ 'funding/prev-funding-rate',
+ 'mark-price-kline',
+ ],
+ },
+ 'privateLinear': {
+ 'get': [
+ 'order/list',
+ 'order/search',
+ 'stop-order/list',
+ 'stop-order/search',
+ 'position/list',
+ 'position/set-auto-add-margin',
+ 'position/set-leverage',
+ 'position/switch-isolated',
+ 'position/trading-stop',
+ 'position/add-margin',
+ 'trade/execution/list',
+ 'trade/closed-pnl/list',
+ 'risk-limit',
+ 'funding/prev-funding',
+ 'funding/predicted-funding',
+ ],
+ 'post': [
+ 'order/create',
+ 'order/cancel',
+ 'order/cancelAll',
+ 'stop-order/create',
+ 'stop-order/cancel',
+ 'stop-order/cancelAll',
+ ],
+ },
'position': {
'post': [
'change-position-margin',
@@ -33236,6 +32553,9 @@ module.exports = class bybit extends Exchange {
},
'precisionMode': TICK_SIZE,
'options': {
+ 'marketTypes': {
+ 'BTC/USDT': 'linear',
+ },
'code': 'BTC',
'fetchBalance': {
'code': 'BTC',
@@ -33318,6 +32638,8 @@ module.exports = class bybit extends Exchange {
// }
//
const markets = this.safeValue (response, 'result', []);
+ const options = this.safeValue (this.options, 'fetchMarkets', {});
+ const linearQuoteCurrencies = this.safeValue (options, 'linear', { 'USDT': true });
const result = [];
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
@@ -33326,6 +32648,8 @@ module.exports = class bybit extends Exchange {
const quoteId = this.safeString (market, 'quote_currency');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
+ const linear = (quote in linearQuoteCurrencies);
+ const inverse = !linear;
const symbol = base + '/' + quote;
const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {});
const priceFilter = this.safeValue (market, 'price_filter', {});
@@ -33342,6 +32666,12 @@ module.exports = class bybit extends Exchange {
'precision': precision,
'taker': this.safeFloat (market, 'taker_fee'),
'maker': this.safeFloat (market, 'maker_fee'),
+ 'type': 'future',
+ 'spot': false,
+ 'future': true,
+ 'option': false,
+ 'linear': linear,
+ 'inverse': inverse,
'limits': {
'amount': {
'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'),
@@ -33356,10 +32686,6 @@ module.exports = class bybit extends Exchange {
'max': undefined,
},
},
- 'type': 'future',
- 'spot': false,
- 'future': true,
- 'option': false,
'info': market,
});
}
@@ -33619,13 +32945,25 @@ module.exports = class bybit extends Exchange {
// turnover: '162.32773718999994'
// },
//
+ // {
+ // "id":143536,
+ // "symbol":"BTCUSDT",
+ // "period":"15",
+ // "start_at":1587883500,
+ // "volume":1.035,
+ // "open":7540.5,
+ // "high":7541,
+ // "low":7540.5,
+ // "close":7541
+ // }
+ //
return [
- this.safeTimestamp (ohlcv, 'open_time'),
+ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'),
this.safeFloat (ohlcv, 'open'),
this.safeFloat (ohlcv, 'high'),
this.safeFloat (ohlcv, 'low'),
this.safeFloat (ohlcv, 'close'),
- this.safeFloat (ohlcv, 'turnover'),
+ this.safeFloat2 (ohlcv, 'turnover', 'volume'),
];
}
@@ -33650,7 +32988,13 @@ module.exports = class bybit extends Exchange {
if (limit !== undefined) {
request['limit'] = limit; // max 200, default 200
}
- const response = await this.publicGetKlineList (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'publicLinearGetKline' : 'publicGetKlineList';
+ const response = await this[method] (this.extend (request, params));
+ //
+ // inverse perpetual BTC/USD
+ //
// {
// ret_code: 0,
// ret_msg: 'OK',
@@ -33671,6 +33015,30 @@ module.exports = class bybit extends Exchange {
// ],
// time_now: '1583953082.397330'
// }
+ //
+ // linear perpetual BTC/USDT
+ //
+ // {
+ // "ret_code":0,
+ // "ret_msg":"OK",
+ // "ext_code":"",
+ // "ext_info":"",
+ // "result":[
+ // {
+ // "id":143536,
+ // "symbol":"BTCUSDT",
+ // "period":"15",
+ // "start_at":1587883500,
+ // "volume":1.035,
+ // "open":7540.5,
+ // "high":7541,
+ // "low":7540.5,
+ // "close":7541
+ // }
+ // ],
+ // "time_now":"1587884120.168077"
+ // }
+ //
const result = this.safeValue (response, 'result', {});
return this.parseOHLCVs (result, market, timeframe, since, limit);
}
@@ -33697,6 +33065,8 @@ module.exports = class bybit extends Exchange {
// "exec_id": "256e5ef8-abfe-5772-971b-f944e15e0d68",
// "exec_price": "8178.5",
// "exec_qty": 1,
+ // // the docs say the exec_time field is "abandoned" now
+ // // the user should use "trade_time_ms"
// "exec_time": "1571676941.70682",
// "exec_type": "Trade", //Exec Type Enum
// "exec_value": "0.00012227",
@@ -33711,30 +33081,35 @@ module.exports = class bybit extends Exchange {
// "order_type": "Market", //Order Type Enum
// "side": "Buy", //Side Enum
// "symbol": "BTCUSD", //Symbol Enum
- // "user_id": 1
+ // "user_id": 1,
+ // "trade_time_ms": 1577480599000
// }
//
const id = this.safeString2 (trade, 'id', 'exec_id');
let symbol = undefined;
let base = undefined;
const marketId = this.safeString (trade, 'symbol');
+ let amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
+ let cost = this.safeFloat (trade, 'exec_value');
+ const price = this.safeFloat2 (trade, 'price', 'exec_price');
if (marketId in this.markets_by_id) {
market = this.markets_by_id[marketId];
symbol = market['symbol'];
base = market['base'];
}
- if ((symbol === undefined) && (market !== undefined)) {
- symbol = market['symbol'];
- base = market['base'];
+ if (market !== undefined) {
+ if (symbol === undefined) {
+ symbol = market['symbol'];
+ base = market['base'];
+ }
+ // if private trade
+ if ('exec_fee' in trade) {
+ if (market['inverse']) {
+ amount = this.safeFloat (trade, 'exec_value');
+ cost = this.safeFloat (trade, 'exec_qty');
+ }
+ }
}
- let timestamp = this.parse8601 (this.safeString (trade, 'time'));
- if (timestamp === undefined) {
- timestamp = this.safeTimestamp (trade, 'exec_time');
- }
- const side = this.safeStringLower (trade, 'side');
- const price = this.safeFloat2 (trade, 'price', 'exec_price');
- const amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
- let cost = this.safeFloat (trade, 'exec_value');
if (cost === undefined) {
if (amount !== undefined) {
if (price !== undefined) {
@@ -33742,6 +33117,11 @@ module.exports = class bybit extends Exchange {
}
}
}
+ let timestamp = this.parse8601 (this.safeString (trade, 'time'));
+ if (timestamp === undefined) {
+ timestamp = this.safeInteger (trade, 'trade_time_ms');
+ }
+ const side = this.safeStringLower (trade, 'side');
const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind');
const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker';
const feeCost = this.safeFloat (trade, 'exec_fee');
@@ -33780,7 +33160,10 @@ module.exports = class bybit extends Exchange {
if (limit !== undefined) {
request['count'] = limit; // default 500, max 1000
}
- const response = await this.publicGetTradingRecords (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'publicLinearGetRecentTradingRecords' : 'publicGetTradingRecords';
+ const response = await this[method] (this.extend (request, params));
//
// {
// ret_code: 0,
@@ -33894,8 +33277,8 @@ module.exports = class bybit extends Exchange {
// "last_exec_time": 0,
// "last_exec_price": 0,
// "leaves_qty": 1,
- // "cum_exec_qty": 0,
- // "cum_exec_value": 0,
+ // "cum_exec_qty": 0, // in contracts, where 1 contract = 1 quote currency unit (USD for inverse contracts)
+ // "cum_exec_value": 0, // in contract's underlying currency (BTC for inverse contracts)
// "cum_exec_fee": 0,
// "reject_reason": "",
// "order_link_id": "",
@@ -33903,18 +33286,69 @@ module.exports = class bybit extends Exchange {
// "updated_at": "2019-11-30T11:03:43.455Z"
// }
//
+ // fetchOrder
+ //
+ // {
+ // "user_id" : 599946,
+ // "symbol" : "BTCUSD",
+ // "side" : "Buy",
+ // "order_type" : "Limit",
+ // "price" : "7948",
+ // "qty" : 10,
+ // "time_in_force" : "GoodTillCancel",
+ // "order_status" : "Filled",
+ // "ext_fields" : {
+ // "o_req_num" : -1600687220498,
+ // "xreq_type" : "x_create"
+ // },
+ // "last_exec_time" : "1588150113.968422",
+ // "last_exec_price" : "7948",
+ // "leaves_qty" : 0,
+ // "leaves_value" : "0",
+ // "cum_exec_qty" : 10,
+ // "cum_exec_value" : "0.00125817",
+ // "cum_exec_fee" : "-0.00000031",
+ // "reject_reason" : "",
+ // "cancel_type" : "",
+ // "order_link_id" : "",
+ // "created_at" : "2020-04-29T08:45:24.399146Z",
+ // "updated_at" : "2020-04-29T08:48:33.968422Z",
+ // "order_id" : "dd2504b9-0157-406a-99e1-efa522373944"
+ // }
+ //
+ const marketId = this.safeString (order, 'symbol');
+ let symbol = undefined;
+ let base = undefined;
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
const id = this.safeString (order, 'order_id');
const price = this.safeFloat (order, 'price');
const average = this.safeFloat (order, 'average_price');
- const amount = this.safeFloat (order, 'qty');
- let filled = this.safeFloat (order, 'cum_exec_qty');
- let remaining = this.safeFloat (order, 'leaves_qty');
+ let amount = undefined;
+ let cost = undefined;
+ let filled = undefined;
+ let remaining = undefined;
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ base = market['base'];
+ if (market['inverse']) {
+ cost = this.safeFloat (order, 'cum_exec_qty');
+ filled = this.safeFloat (order, 'cum_exec_value');
+ remaining = this.safeFloat (order, 'leaves_value');
+ amount = this.sum (filled, remaining);
+ } else {
+ amount = this.safeFloat (order, 'qty');
+ cost = this.safeFloat (order, 'cum_exec_value');
+ filled = this.safeFloat (order, 'cum_exec_qty');
+ remaining = this.safeFloat (order, 'leaves_qty');
+ }
+ }
let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time');
if (lastTradeTimestamp === 0) {
lastTradeTimestamp = undefined;
}
- let cost = this.safeFloat (order, 'cum_exec_value');
if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) {
filled = amount - remaining;
}
@@ -33929,22 +33363,6 @@ module.exports = class bybit extends Exchange {
}
}
const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
- const marketId = this.safeString (order, 'symbol');
- let symbol = undefined;
- let base = undefined;
- if (marketId in this.markets_by_id) {
- market = this.markets_by_id[marketId];
- symbol = market['symbol'];
- base = market['base'];
- }
- if (market !== undefined) {
- if (symbol === undefined) {
- symbol = market['symbol'];
- }
- if (base === undefined) {
- base = market['base'];
- }
- }
const side = this.safeStringLower (order, 'side');
let feeCost = this.safeFloat (order, 'cum_exec_fee');
let fee = undefined;
@@ -33996,7 +33414,9 @@ module.exports = class bybit extends Exchange {
// conditional orders ---------------------------------------------
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
};
- let method = 'privateGetOrder';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearGetOrderSearch' : 'privateGetOrder';
const stopOrderId = this.safeString (params, 'stop_order_id');
if (stopOrderId === undefined) {
const orderLinkId = this.safeString (params, 'order_link_id');
@@ -34004,7 +33424,7 @@ module.exports = class bybit extends Exchange {
request['order_id'] = id;
}
} else {
- method = 'privateGetStopOrder';
+ method = (marketType === 'linear') ? 'privateLinearGetStopOrderSearch' : 'privateGetStopOrder';
}
const response = await this[method] (this.extend (request, params));
//
@@ -34116,12 +33536,14 @@ module.exports = class bybit extends Exchange {
}
const stopPx = this.safeValue (params, 'stop_px');
const basePrice = this.safeValue (params, 'base_price');
- let method = 'privatePostOrderCreate';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearPostOrderCreate' : 'privatePostOrderCreate';
if (stopPx !== undefined) {
if (basePrice === undefined) {
throw new ArgumentsRequired (this.id + ' createOrder requires both the stop_px and base_price params for a conditional ' + type + ' order');
} else {
- method = 'openapiPostStopOrderCreate';
+ method = (marketType === 'linear') ? 'privateLinearPostStopOrderCreate' : 'openapiPostStopOrderCreate';
request['stop_px'] = this.priceToPrecision (symbol, stopPx);
request['base_price'] = this.priceToPrecision (symbol, basePrice);
params = this.omit (params, [ 'stop_px', 'base_price' ]);
@@ -34215,6 +33637,11 @@ module.exports = class bybit extends Exchange {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' editOrder requires an symbol argument');
}
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ if (marketType === 'linear') {
+ throw new NotSupported (this.id + ' does not support editOrder for ' + marketType + ' ' + symbol + ' market type');
+ }
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
@@ -34292,7 +33719,9 @@ module.exports = class bybit extends Exchange {
// conditional orders ---------------------------------------------
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
};
- let method = 'privatePostOrderCancel';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeValue (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearPostOrderCancel' : 'privatePostOrderCancel';
const stopOrderId = this.safeString (params, 'stop_order_id');
if (stopOrderId === undefined) {
const orderLinkId = this.safeString (params, 'order_link_id');
@@ -34300,7 +33729,7 @@ module.exports = class bybit extends Exchange {
request['order_id'] = id;
}
} else {
- method = 'openapiPostStopOrderCancel';
+ method = (marketType === 'linear') ? 'privateLinearPostStopOrderCancel' : 'openapiPostStopOrderCancel';
}
const response = await this[method] (this.extend (request, params));
const result = this.safeValue (response, 'result', {});
@@ -34317,7 +33746,10 @@ module.exports = class bybit extends Exchange {
'symbol': market['id'],
};
const options = this.safeValue (this.options, 'cancelAllOrders');
- const method = this.safeString (options, 'method', 'privatePostOrderCancelAll');
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const defaultMethod = (marketType === 'linear') ? 'privateLinearPostOrderCancelAll' : 'privatePostOrderCancelAll';
+ const method = this.safeString (options, 'method', defaultMethod);
const response = await this[method] (this.extend (request, params));
const result = this.safeValue (response, 'result', []);
return this.parseOrders (result, market);
@@ -34346,7 +33778,9 @@ module.exports = class bybit extends Exchange {
request['limit'] = limit;
}
const options = this.safeValue (this.options, 'fetchOrders', {});
- let defaultMethod = 'openapiGetOrderList';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let defaultMethod = (marketType === 'linear') ? 'privateLinearGetOrderList' : 'openapiGetOrderList';
let query = params;
if (('stop_order_id' in params) || ('stop_order_status' in params)) {
let stopOrderStatus = this.safeValue (params, 'stopOrderStatus');
@@ -34357,7 +33791,7 @@ module.exports = class bybit extends Exchange {
request['stop_order_status'] = stopOrderStatus;
query = this.omit (params, 'stop_order_status');
}
- defaultMethod = 'openapiGetStopOrderList';
+ defaultMethod = (marketType === 'linear') ? 'privateLinearGetStopOrderList' : 'openapiGetStopOrderList';
}
const method = this.safeString (options, 'method', defaultMethod);
const response = await this[method] (this.extend (request, query));
@@ -34533,12 +33967,15 @@ module.exports = class bybit extends Exchange {
request['symbol'] = market['id'];
}
if (since !== undefined) {
- request['start_time'] = parseInt (since / 1000);
+ request['start_time'] = since;
}
if (limit !== undefined) {
request['limit'] = limit; // default 20, max 50
}
- const response = await this.privateGetExecutionList (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'privateLinearGetTradeExecutionList' : 'privateGetExecutionList';
+ const response = await this[method] (this.extend (request, params));
//
// {
// "ret_code": 0,
@@ -34873,6 +34310,11 @@ module.exports = class bybit extends Exchange {
if (Object.keys (params).length) {
request += '?' + this.rawencode (params);
}
+ } else if (api === 'publicLinear') {
+ request = '/public/linear/' + request;
+ if (Object.keys (params).length) {
+ request += '?' + this.rawencode (params);
+ }
} else {
this.checkRequiredCredentials ();
if (api === 'openapi') {
@@ -34880,14 +34322,16 @@ module.exports = class bybit extends Exchange {
} else if (api === 'private') {
// private v2
request = '/' + this.version + '/' + api + '/' + request;
+ } else if (api === 'privateLinear') {
+ request = '/private/linear/' + request;
} else {
// position, user
- request += '/' + api + '/' + request;
+ request = '/' + api + '/' + request;
}
const timestamp = this.nonce ();
const query = this.extend (params, {
'api_key': this.apiKey,
- 'recvWindow': this.options['recvWindow'],
+ 'recv_window': this.options['recvWindow'],
'timestamp': timestamp,
});
const auth = this.rawencode (this.keysort (query));
@@ -34933,7 +34377,7 @@ module.exports = class bybit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],58:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],57:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -34983,9 +34427,15 @@ module.exports = class bytetrade extends Exchange {
'1M': '1M',
},
'urls': {
- 'test': 'https://api-v2-test.byte-trade.com',
+ 'test': {
+ 'market': 'https://api-v2-test.byte-trade.com',
+ 'public': 'https://api-v2-test.byte-trade.com',
+ },
'logo': 'https://user-images.githubusercontent.com/1294454/67288762-2f04a600-f4e6-11e9-9fd6-c60641919491.jpg',
- 'api': 'https://api-v2.byte-trade.com',
+ 'api': {
+ 'market': 'https://api-v2.bytetrade.com',
+ 'public': 'https://api-v2.bytetrade.com',
+ },
'www': 'https://www.byte-trade.com',
'doc': 'https://github.com/Bytetrade/bytetrade-official-api-docs/wiki',
},
@@ -36158,7 +35608,7 @@ module.exports = class bytetrade extends Exchange {
this.numberToLE (address.length, 1),
this.stringToBinary (this.encode (address)),
this.numberToLE (parseInt (coinId), 4),
- this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
+ this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
this.numberToLE (1, 1),
this.numberToLE (this.integerDivide (assetFee, eightBytes), 8),
@@ -36191,7 +35641,7 @@ module.exports = class bytetrade extends Exchange {
this.numberToLE (middleAddress.length, 1),
this.stringToBinary (this.encode (middleAddress)),
this.numberToLE (parseInt (coinId), 4),
- this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
+ this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
this.numberToLE (0, 1),
this.numberToLE (1, 1),
@@ -36294,7 +35744,7 @@ module.exports = class bytetrade extends Exchange {
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- let url = this.urls['api'];
+ let url = this.urls['api'][api];
url += '/' + path;
if (Object.keys (params).length) {
url += '?' + this.urlencode (params);
@@ -36321,7 +35771,7 @@ module.exports = class bytetrade extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],59:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],58:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -36888,9 +36338,45 @@ module.exports = class cex extends Exchange {
request['order_type'] = type;
}
const response = await this.privatePostPlaceOrderPair (this.extend (request, params));
+ //
+ // {
+ // "id": "12978363524",
+ // "time": 1586610022259,
+ // "type": "buy",
+ // "price": "0.033934",
+ // "amount": "0.10722802",
+ // "pending": "0.10722802",
+ // "complete": false
+ // }
+ //
+ const placedAmount = this.safeFloat (response, 'amount');
+ const remaining = this.safeFloat (response, 'pending');
+ const timestamp = this.safeValue (response, 'time');
+ const complete = this.safeValue (response, 'complete');
+ const status = complete ? 'closed' : 'open';
+ let filled = undefined;
+ if ((placedAmount !== undefined) && (remaining !== undefined)) {
+ filled = Math.max (placedAmount - remaining, 0);
+ }
return {
+ 'id': this.safeString (response, 'id'),
'info': response,
- 'id': response['id'],
+ 'clientOrderId': undefined,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'type': type,
+ 'side': this.safeString (response, 'type'),
+ 'symbol': symbol,
+ 'status': status,
+ 'price': this.safeFloat (response, 'price'),
+ 'amount': placedAmount,
+ 'cost': undefined,
+ 'average': undefined,
+ 'remaining': remaining,
+ 'filled': filled,
+ 'fee': undefined,
+ 'trades': undefined,
};
}
@@ -37506,7 +36992,7 @@ module.exports = class cex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],60:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],59:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -37540,7 +37026,7 @@ module.exports = class chilebit extends foxbit {
}
};
-},{"./foxbit.js":85}],61:[function(require,module,exports){
+},{"./foxbit.js":84}],60:[function(require,module,exports){
'use strict';
// ----------------------------------------------------------------------------
@@ -38727,7 +38213,7 @@ module.exports = class coinbase extends Exchange {
};
-},{"./base/Exchange":8,"./base/errors":10}],62:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],61:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -38760,7 +38246,7 @@ module.exports = class coinbaseprime extends coinbasepro {
}
};
-},{"./coinbasepro.js":63}],63:[function(require,module,exports){
+},{"./coinbasepro.js":62}],62:[function(require,module,exports){
'use strict';
// ----------------------------------------------------------------------------
@@ -39723,7 +39209,7 @@ module.exports = class coinbasepro extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],64:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],63:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -40158,7 +39644,7 @@ module.exports = class coincheck extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],65:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],64:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -40665,7 +40151,7 @@ module.exports = class coinegg extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],66:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],65:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -41580,7 +41066,7 @@ module.exports = class coinex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],67:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],66:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -42031,7 +41517,7 @@ module.exports = class coinfalcon extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],68:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],67:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -42554,7 +42040,7 @@ module.exports = class coinfloor extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],69:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],68:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -42903,7 +42389,7 @@ module.exports = class coingi extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],70:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],69:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -43237,7 +42723,7 @@ module.exports = class coinmarketcap extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],71:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],70:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -43801,6 +43287,7 @@ module.exports = class coinmate extends Exchange {
const statuses = {
'FILLED': 'closed',
'CANCELLED': 'canceled',
+ 'PARTIALLY_FILLED': 'open',
'OPEN': 'open',
};
return this.safeString (statuses, status, status);
@@ -43863,12 +43350,15 @@ module.exports = class coinmate extends Exchange {
const price = this.safeFloat (order, 'price');
const amount = this.safeFloat2 (order, 'originalAmount', 'amount');
const remaining = this.safeFloat (order, 'remainingAmount', amount);
- const status = this.parseOrderStatus (this.safeString (order, 'status'));
+ let status = this.parseOrderStatus (this.safeString (order, 'status'));
const type = this.parseOrderType (this.safeString (order, 'orderTradeType'));
let filled = undefined;
let cost = undefined;
if ((amount !== undefined) && (remaining !== undefined)) {
- filled = amount - remaining;
+ filled = Math.min (amount - remaining, 0);
+ if (remaining === 0) {
+ status = 'closed';
+ }
if (price !== undefined) {
cost = filled * price;
}
@@ -44014,7 +43504,7 @@ module.exports = class coinmate extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],72:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],71:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -44541,7 +44031,7 @@ module.exports = class coinone extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],73:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],72:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -44714,7 +44204,7 @@ module.exports = class coinspot extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],74:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],73:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -44786,7 +44276,7 @@ module.exports = class coolcoin extends coinegg {
}
};
-},{"./coinegg.js":65}],75:[function(require,module,exports){
+},{"./coinegg.js":64}],74:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -45731,7 +45221,7 @@ module.exports = class coss extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],76:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],75:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -45863,7 +45353,6 @@ module.exports = class crex24 extends Exchange {
'fetchClosedOrdersMethod': 'tradingGetOrderHistory', // or 'tradingGetActiveOrders'
'fetchTickersMethod': 'publicGetTicker24hr',
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
- 'defaultLimitOrderType': 'limit', // or 'limit_maker'
'hasAlreadyAuthenticatedSuccessfully': false,
'warnOnFetchOpenOrdersWithoutSymbol': true,
'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision
@@ -47035,7 +46524,7 @@ module.exports = class crex24 extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],77:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],76:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -47563,11 +47052,13 @@ module.exports = class deribit extends Exchange {
'info': response,
};
const balance = this.safeValue (response, 'result', {});
+ const currencyId = this.safeString (balance, 'currency');
+ const currencyCode = this.safeCurrencyCode (currencyId);
const account = this.account ();
account['free'] = this.safeFloat (balance, 'availableFunds');
account['used'] = this.safeFloat (balance, 'maintenanceMargin');
account['total'] = this.safeFloat (balance, 'equity');
- result[code] = account;
+ result[currencyCode] = account;
return this.parseBalance (result);
}
@@ -47921,7 +47412,7 @@ module.exports = class deribit extends Exchange {
// M = maker, T = taker, MT = both
takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker';
}
- const feeCost = this.safeFloat (trade, 'feeCost');
+ const feeCost = this.safeFloat (trade, 'fee');
let fee = undefined;
if (feeCost !== undefined) {
const feeCurrencyId = this.safeString (trade, 'fee_currency');
@@ -48749,7 +48240,7 @@ module.exports = class deribit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],78:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],77:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -49928,7 +49419,7 @@ module.exports = class digifinex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],79:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],78:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -51200,13 +50691,13 @@ module.exports = class dsx extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],80:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],79:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded } = require ('./base/errors');
+const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded, BadRequest, PermissionDenied } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -51217,7 +50708,7 @@ module.exports = class exmo extends Exchange {
'name': 'EXMO',
'countries': [ 'ES', 'RU' ], // Spain, Russia
'rateLimit': 350, // once every 350 ms ≈ 180 requests per minute ≈ 3 requests per second
- 'version': 'v1',
+ 'version': 'v1.1',
'has': {
'CORS': false,
'fetchClosedOrders': 'emulated',
@@ -51235,6 +50726,21 @@ module.exports = class exmo extends Exchange {
'fetchFundingFees': true,
'fetchCurrencies': true,
'fetchTransactions': true,
+ 'fetchOHLCV': true,
+ },
+ 'timeframes': {
+ '1m': '1',
+ '5m': '5',
+ '15m': '15',
+ '30m': '30',
+ '45m': '45',
+ '1h': '60',
+ '2h': '120',
+ '3h': '180',
+ '4h': '240',
+ '1d': 'D',
+ '1w': 'W',
+ '1M': 'M',
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg',
@@ -51265,6 +50771,7 @@ module.exports = class exmo extends Exchange {
'pair_settings',
'ticker',
'trades',
+ 'candles_history',
],
},
'private': {
@@ -51272,6 +50779,8 @@ module.exports = class exmo extends Exchange {
'user_info',
'order_create',
'order_cancel',
+ 'stop_market_order_create',
+ 'stop_market_order_cancel',
'user_open_orders',
'user_trades',
'user_cancelled_orders',
@@ -51306,86 +50815,90 @@ module.exports = class exmo extends Exchange {
'error': '',
'data': {
'limits': [
- { 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'ALGO/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'ALGO/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '50' },
+ { 'pair': 'ATOM/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '50000000' },
+ { 'pair': 'ATOM/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'BTC/USD', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
- { 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
- { 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
- { 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
- { 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
- { 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
- { 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
- { 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
- { 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
- { 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
- { 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'BTC/RUB', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '2000000', 'min_a': '10', 'max_a': '50000000' },
{ 'pair': 'BTC/EUR', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
{ 'pair': 'BTC/UAH', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '15000000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'BTC/GBP', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ETH/GBP', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'XRP/GBP', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'USDT/GBP', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'BTC/PLN', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '20000000', 'min_a': '50', 'max_a': '2000000' },
{ 'pair': 'BTC/TRY', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '800000', 'min_a': '40', 'max_a': '6000000' },
+ { 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
{ 'pair': 'BTC/USDT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.01', 'max_p': '30000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/BTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ETH/USD', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/RUB', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '100000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
+ { 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
{ 'pair': 'ADA/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ADA/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '5000' },
{ 'pair': 'ADA/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
- { 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
- { 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'ALGO/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ALGO/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'ALGO/EUR', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ATOM/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'ATOM/EUR', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
+ { 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
+ { 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'BTCZ/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
+ { 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
+ { 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'DAI/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'DAI/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '0.5', 'max_a': '30000000' },
{ 'pair': 'DAI/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
{ 'pair': 'DAI/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
+ { 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'DCR/RUB', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '3000000' },
{ 'pair': 'DCR/UAH', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.25', 'max_a': '1000000' },
{ 'pair': 'DCR/BTC', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '1000000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
- { 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
+ { 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ETH/EUR', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/UAH', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '1000000', 'min_a': '90', 'max_a': '15000000' },
{ 'pair': 'ETH/PLN', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '2000000' },
{ 'pair': 'ETH/TRY', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.1', 'max_p': '80000', 'min_a': '10', 'max_a': '6000000' },
+ { 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/USDT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/LTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '100000', 'min_a': '0.05', 'max_a': '100000' },
- { 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
- { 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
- { 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
+ { 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
+ { 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'GNT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'GNT/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
{ 'pair': 'GUSD/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
@@ -51400,84 +50913,94 @@ module.exports = class exmo extends Exchange {
{ 'pair': 'KICK/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'KICK/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
{ 'pair': 'KICK/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
- { 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
- { 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
- { 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
+ { 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
+ { 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
+ { 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
+ { 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'MKR/BTC', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.000001', 'max_a': '100' },
{ 'pair': 'MKR/DAI', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.5', 'max_p': '500000', 'min_a': '0.005', 'max_a': '500000' },
- { 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
+ { 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
{ 'pair': 'MNX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
{ 'pair': 'MNX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'MNX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
- { 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
- { 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
- { 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
- { 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
+ { 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
+ { 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
+ { 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
+ { 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
+ { 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
+ { 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
+ { 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
+ { 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
+ { 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
+ { 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
+ { 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
+ { 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
+ { 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
+ { 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
{ 'pair': 'ROOBEE/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
- { 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
+ { 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'TRX/EUR', 'min_q': '0.01', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'USDC/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'USDC/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
{ 'pair': 'USDC/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '1000' },
{ 'pair': 'USDC/USDT', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'USDT/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'USDT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '10', 'max_a': '50000000' },
- { 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
+ { 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
+ { 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'VLX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
- { 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
- { 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
- { 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
- { 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
- { 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
- { 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
- { 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
- { 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
- { 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
+ { 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
+ { 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
+ { 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
+ { 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
+ { 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
+ { 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
+ { 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
+ { 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
+ { 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
{ 'pair': 'XTZ/USD', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '100000' },
{ 'pair': 'XTZ/RUB', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '500000' },
{ 'pair': 'XTZ/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
{ 'pair': 'XTZ/ETH', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '1000' },
- { 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ZRX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'ZRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ZRX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
@@ -51540,6 +51063,8 @@ module.exports = class exmo extends Exchange {
{ 'prov': 'CRON', 'dep': '0%', 'wd': '5 CRON' },
{ 'prov': 'ONT', 'dep': '0%', 'wd': '1 ONT' },
{ 'prov': 'ONG', 'dep': '0%', 'wd': '5 ONG' },
+ { 'prov': 'ALGO', 'dep': '0%', 'wd': '0.01 ALGO' },
+ { 'prov': 'ATOM', 'dep': '0%', 'wd': '' },
],
},
{
@@ -51548,9 +51073,10 @@ module.exports = class exmo extends Exchange {
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Payeer', 'dep': '3.95%', 'wd': '-' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.99%' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 USD', 'wd': '-' },
{ 'prov': 'Visa', 'dep': '3.45%', 'wd': '-' },
+ { 'prov': 'Frick Bank', 'dep': '0 USD', 'wd': '-' },
],
},
{
@@ -51558,22 +51084,24 @@ module.exports = class exmo extends Exchange {
'title': 'EUR',
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
+ { 'prov': 'Visa/MasterCard', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
{ 'prov': 'Visa', 'dep': '2.95%', 'wd': '-' },
- { 'prov': 'SEPA', 'dep': '10 EUR', 'wd': '50 EUR' },
+ { 'prov': 'Frick Internal Transfer', 'dep': '0 EUR', 'wd': '-' },
+ { 'prov': 'SEPA Frick Bank', 'dep': '0 EUR', 'wd': '-' },
+ { 'prov': 'WIRE Frick Bank', 'dep': '0%', 'wd': '-' },
+ { 'prov': 'SEPA Weg Ag', 'dep': '-', 'wd': '1 EUR' },
],
},
{
'group': 'rub',
'title': 'RUB',
'items': [
- { 'prov': 'Payeer', 'dep': '2.49%', 'wd': '-' },
+ { 'prov': 'Payeer', 'dep': '2.49%', 'wd': '3.99%' },
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Qiwi', 'dep': '0.99%', 'wd': '2%' },
- { 'prov': 'Yandex Money', 'dep': '1.95%', 'wd': '-' },
- { 'prov': 'Enfins', 'dep': '0%', 'wd': '1.49%' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '2.49%' },
- { 'prov': 'Visa/MasterCard', 'dep': '1.99%', 'wd': '4.49% + 60 RUB' },
+ { 'prov': 'Qiwi', 'dep': '1.49%', 'wd': '2.49%' },
+ { 'prov': 'Yandex Money', 'dep': '1.49%', 'wd': '-' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
+ { 'prov': 'Visa/MasterCard', 'dep': '2.99%', 'wd': '3.99% + 60 RUB' },
],
},
{
@@ -51581,7 +51109,6 @@ module.exports = class exmo extends Exchange {
'title': 'PLN',
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 1 PLN', 'wd': '-' },
],
},
{
@@ -51591,6 +51118,7 @@ module.exports = class exmo extends Exchange {
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Visa', 'dep': '3.05%', 'wd': '-' },
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 2 TRY', 'wd': '-' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
],
},
{
@@ -51599,17 +51127,18 @@ module.exports = class exmo extends Exchange {
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Terminal', 'dep': '2.6%', 'wd': '-' },
- { 'prov': 'Enfins', 'dep': '0%', 'wd': '1.95%' },
- { 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '2.99%' },
+ { 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '-' },
+ { 'prov': 'Visa/MasterCard EasyTransfer', 'dep': '-', 'wd': '2.99%' },
],
},
{
'group': 'kzt',
'title': 'KZT',
'items': [
+ { 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Visa/MasterCard RoyalPay', 'dep': '-', 'wd': '2.99% + 450 KZT' },
{ 'prov': 'Visa/MasterCard', 'dep': '3.5%', 'wd': '-' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '1.49%' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
],
},
],
@@ -51623,6 +51152,7 @@ module.exports = class exmo extends Exchange {
'40015': ExchangeError, // API function do not exist
'40016': OnMaintenance, // {"result":false,"error":"Error 40016: Maintenance work in progress"}
'40017': AuthenticationError, // Wrong API Key
+ '40032': PermissionDenied, // {"result":false,"error":"Error 40032: Access is denied for this API key"}
'40034': RateLimitExceeded, // {"result":false,"error":"Error 40034: Access is denied, rate limit is exceeded"}
'50052': InsufficientFunds,
'50054': InsufficientFunds,
@@ -51632,6 +51162,8 @@ module.exports = class exmo extends Exchange {
'50321': InvalidOrder, // Price by order is more than permissible maximum for this pair
},
'broad': {
+ 'range period is too long': BadRequest,
+ 'invalid syntax': BadRequest,
'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}
},
},
@@ -51793,8 +51325,21 @@ module.exports = class exmo extends Exchange {
}
async fetchMarkets (params = {}) {
- const fees = await this.fetchTradingFees ();
const response = await this.publicGetPairSettings (params);
+ //
+ // {
+ // "EXM_ETH": {
+ // "min_quantity": "1",
+ // "max_quantity": "1000",
+ // "min_price": "1",
+ // "max_price": "1000",
+ // "max_amount": "1000",
+ // "min_amount": "1",
+ // "commission_taker_percent": "0.2",
+ // "commission_maker_percent": "0.2"
+ // },
+ // }
+ //
const keys = Object.keys (response);
const result = [];
for (let i = 0; i < keys.length; i++) {
@@ -51804,6 +51349,8 @@ module.exports = class exmo extends Exchange {
const [ baseId, quoteId ] = symbol.split ('/');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
+ const taker = this.safeFloat (market, 'commission_taker_percent');
+ const maker = this.safeFloat (market, 'commission_maker_percent');
result.push ({
'id': id,
'symbol': symbol,
@@ -51812,8 +51359,8 @@ module.exports = class exmo extends Exchange {
'baseId': baseId,
'quoteId': quoteId,
'active': true,
- 'taker': fees['taker'],
- 'maker': fees['maker'],
+ 'taker': taker / 100,
+ 'maker': maker / 100,
'limits': {
'amount': {
'min': this.safeFloat (market, 'min_quantity'),
@@ -51838,6 +51385,74 @@ module.exports = class exmo extends Exchange {
return result;
}
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ 'resolution': this.timeframes[timeframe],
+ };
+ const options = this.safeValue (this.options, 'fetchOHLCV');
+ const maxLimit = this.safeInteger (options, 'maxLimit', 3000);
+ const duration = this.parseTimeframe (timeframe);
+ const now = this.milliseconds ();
+ if (since === undefined) {
+ if (limit === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument or a limit argument');
+ } else {
+ if (limit > maxLimit) {
+ throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
+ }
+ request['from'] = parseInt (now / 1000) - limit * duration - 1;
+ request['to'] = parseInt (now / 1000);
+ }
+ } else {
+ request['from'] = parseInt (since / 1000) - 1;
+ if (limit === undefined) {
+ request['to'] = parseInt (now / 1000);
+ } else {
+ if (limit > maxLimit) {
+ throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
+ }
+ const to = this.sum (since, limit * duration * 1000);
+ request['to'] = parseInt (to / 1000);
+ }
+ }
+ const response = await this.publicGetCandlesHistory (this.extend (request, params));
+ //
+ // {
+ // "candles":[
+ // {"t":1584057600000,"o":0.02235144,"c":0.02400233,"h":0.025171,"l":0.02221,"v":5988.34031761},
+ // {"t":1584144000000,"o":0.0240373,"c":0.02367413,"h":0.024399,"l":0.0235,"v":2027.82522329},
+ // {"t":1584230400000,"o":0.02363458,"c":0.02319242,"h":0.0237948,"l":0.02223196,"v":1707.96944997},
+ // ]
+ // }
+ //
+ const candles = this.safeValue (response, 'candles', []);
+ return this.parseOHLCVs (candles, market, timeframe, since, limit);
+ }
+
+ parseOHLCV (ohlcv, market = undefined, timeframe = '5m', since = undefined, limit = undefined) {
+ //
+ // {
+ // "t":1584057600000,
+ // "o":0.02235144,
+ // "c":0.02400233,
+ // "h":0.025171,
+ // "l":0.02221,
+ // "v":5988.34031761
+ // }
+ //
+ return [
+ this.safeInteger (ohlcv, 't'),
+ this.safeFloat (ohlcv, 'o'),
+ this.safeFloat (ohlcv, 'h'),
+ this.safeFloat (ohlcv, 'l'),
+ this.safeFloat (ohlcv, 'c'),
+ this.safeFloat (ohlcv, 'v'),
+ ];
+ }
+
async fetchBalance (params = {}) {
await this.loadMarkets ();
const response = await this.privatePostUserInfo (params);
@@ -51961,8 +51576,36 @@ module.exports = class exmo extends Exchange {
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "trade_id":165087520,
+ // "date":1587470005,
+ // "type":"buy",
+ // "quantity":"1.004",
+ // "price":"0.02491461",
+ // "amount":"0.02501426"
+ // },
+ //
+ // fetchMyTrades, fetchOrderTrades
+ //
+ // {
+ // "trade_id": 3,
+ // "date": 1435488248,
+ // "type": "buy",
+ // "pair": "BTC_USD",
+ // "order_id": 12345,
+ // "quantity": 1,
+ // "price": 100,
+ // "amount": 100,
+ // "exec_type": "taker",
+ // "commission_amount": "0.02",
+ // "commission_currency": "BTC",
+ // "commission_percent": "0.2"
+ // }
+ //
const timestamp = this.safeTimestamp (trade, 'date');
- let fee = undefined;
let symbol = undefined;
const id = this.safeString (trade, 'trade_id');
const orderId = this.safeString (trade, 'order_id');
@@ -51971,24 +51614,35 @@ module.exports = class exmo extends Exchange {
const cost = this.safeFloat (trade, 'amount');
const side = this.safeString (trade, 'type');
const type = undefined;
- if (market !== undefined) {
+ const marketId = this.safeString (trade, 'pair');
+ 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 ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
- if (market['taker'] !== market['maker']) {
- throw new ExchangeError (this.id + ' parseTrade can not deduce proper fee costs, taker and maker fees now differ');
- }
- if ((side === 'buy') && (amount !== undefined)) {
- fee = {
- 'currency': market['base'],
- 'cost': amount * market['taker'],
- 'rate': market['taker'],
- };
- } else if ((side === 'sell') && (cost !== undefined)) {
- fee = {
- 'currency': market['quote'],
- 'cost': cost * market['taker'],
- 'rate': market['taker'],
- };
+ }
+ const takerOrMaker = this.safeString (trade, 'exec_type');
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'commission_amount');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'commission_currency');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ let feeRate = this.safeFloat (trade, 'commission_percent');
+ if (feeRate !== undefined) {
+ feeRate /= 1000;
}
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ 'rate': feeRate,
+ };
}
return {
'id': id,
@@ -51999,7 +51653,7 @@ module.exports = class exmo extends Exchange {
'order': orderId,
'type': type,
'side': side,
- 'takerOrMaker': undefined,
+ 'takerOrMaker': takerOrMaker,
'price': price,
'amount': amount,
'cost': cost,
@@ -52014,6 +51668,28 @@ module.exports = class exmo extends Exchange {
'pair': market['id'],
};
const response = await this.publicGetTrades (this.extend (request, params));
+ //
+ // {
+ // "ETH_BTC":[
+ // {
+ // "trade_id":165087520,
+ // "date":1587470005,
+ // "type":"buy",
+ // "quantity":"1.004",
+ // "price":"0.02491461",
+ // "amount":"0.02501426"
+ // },
+ // {
+ // "trade_id":165087369,
+ // "date":1587469938,
+ // "type":"buy",
+ // "quantity":"0.94",
+ // "price":"0.02492348",
+ // "amount":"0.02342807"
+ // }
+ // ]
+ // }
+ //
const data = this.safeValue (response, market['id'], []);
return this.parseTrades (data, market, since, limit);
}
@@ -52171,6 +51847,31 @@ module.exports = class exmo extends Exchange {
'order_id': id.toString (),
};
const response = await this.privatePostOrderTrades (this.extend (request, params));
+ //
+ // {
+ // "type": "buy",
+ // "in_currency": "BTC",
+ // "in_amount": "1",
+ // "out_currency": "USD",
+ // "out_amount": "100",
+ // "trades": [
+ // {
+ // "trade_id": 3,
+ // "date": 1435488248,
+ // "type": "buy",
+ // "pair": "BTC_USD",
+ // "order_id": 12345,
+ // "quantity": 1,
+ // "price": 100,
+ // "amount": 100,
+ // "exec_type": "taker",
+ // "commission_amount": "0.02",
+ // "commission_currency": "BTC",
+ // "commission_percent": "0.2"
+ // }
+ // ]
+ // }
+ //
const trades = this.safeValue (response, 'trades');
return this.parseTrades (trades, market, since, limit);
}
@@ -52618,9 +52319,10 @@ module.exports = class exmo extends Exchange {
if (response === undefined) {
return; // fallback to default error handler
}
- if ('result' in response) {
+ if (('result' in response) || ('errmsg' in response)) {
//
// {"result":false,"error":"Error 50052: Insufficient funds"}
+ // {"s":"error","errmsg":"strconv.ParseInt: parsing \"\": invalid syntax"}
//
let success = this.safeValue (response, 'result', false);
if (typeof success === 'string') {
@@ -52632,7 +52334,7 @@ module.exports = class exmo extends Exchange {
}
if (!success) {
let code = undefined;
- const message = this.safeString (response, 'error');
+ const message = this.safeString2 (response, 'error', 'errmsg');
const errorParts = message.split (':');
const numParts = errorParts.length;
if (numParts > 1) {
@@ -52649,7 +52351,7 @@ module.exports = class exmo extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],81:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],80:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -53102,7 +52804,7 @@ module.exports = class exx extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],82:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],81:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -53836,7 +53538,7 @@ module.exports = class fcoin extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],83:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],82:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -53862,7 +53564,7 @@ module.exports = class fcoinjp extends fcoin {
}
};
-},{"./fcoin.js":82}],84:[function(require,module,exports){
+},{"./fcoin.js":81}],83:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -54141,7 +53843,7 @@ module.exports = class flowbtc extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],85:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],84:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -54400,7 +54102,7 @@ module.exports = class foxbit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],86:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],85:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -54983,6 +54685,7 @@ module.exports = class ftx extends Exchange {
// {
// "fee": 20.1374935,
// "feeRate": 0.0005,
+ // "feeCurrency": "USD",
// "future": "EOS-0329",
// "id": 11215,
// "liquidity": "taker",
@@ -55029,8 +54732,11 @@ module.exports = class ftx extends Exchange {
let fee = undefined;
const feeCost = this.safeFloat (trade, 'fee');
if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'feeCurrency');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
fee = {
'cost': feeCost,
+ 'currency': feeCurrencyCode,
'rate': this.safeFloat (trade, 'feeRate'),
};
}
@@ -55836,7 +55542,7 @@ module.exports = class ftx extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],87:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],86:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -56033,7 +55739,7 @@ module.exports = class fybse extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],88:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],87:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -56200,6 +55906,26 @@ module.exports = class gateio extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetMarketinfo (params);
+ //
+ // {
+ // "result":"true",
+ // "pairs":[
+ // {
+ // "usdt_cnyx":{
+ // "decimal_places":3,
+ // "amount_decimal_places":3,
+ // "min_amount":1,
+ // "min_amount_a":1,
+ // "min_amount_b":3,
+ // "fee":0.02,
+ // "trade_disabled":0,
+ // "buy_disabled":0,
+ // "sell_disabled":0
+ // }
+ // },
+ // ]
+ // }
+ //
const markets = this.safeValue (response, 'pairs');
if (!markets) {
throw new ExchangeError (this.id + ' fetchMarkets got an unrecognized response');
@@ -56226,14 +55952,14 @@ module.exports = class gateio extends Exchange {
const symbol = base + '/' + quote;
const precision = {
'amount': 8,
- 'price': details['decimal_places'],
+ 'price': this.safeInteger (details, 'decimal_places'),
};
const amountLimits = {
- 'min': details['min_amount'],
+ 'min': this.safeFloat (details, 'min_amount'),
'max': undefined,
};
const priceLimits = {
- 'min': Math.pow (10, -details['decimal_places']),
+ 'min': Math.pow (10, -precision['price']),
'max': undefined,
};
const defaultCost = amountLimits['min'] * priceLimits['min'];
@@ -56247,9 +55973,13 @@ module.exports = class gateio extends Exchange {
'price': priceLimits,
'cost': costLimits,
};
- const active = true;
+ const disabled = this.safeValue (details, 'trade_disabled');
+ const active = !disabled;
+ const uppercaseId = id.toUpperCase ();
+ const fee = this.safeFloat (details, 'fee');
result.push ({
'id': id,
+ 'uppercaseId': uppercaseId,
'symbol': symbol,
'base': base,
'quote': quote,
@@ -56257,8 +55987,8 @@ module.exports = class gateio extends Exchange {
'quoteId': quoteId,
'info': market,
'active': active,
- 'maker': details['fee'] / 100,
- 'taker': details['fee'] / 100,
+ 'maker': fee / 100,
+ 'taker': fee / 100,
'precision': precision,
'limits': limits,
});
@@ -56520,22 +56250,64 @@ module.exports = class gateio extends Exchange {
parseOrder (order, market = undefined) {
//
- // {'amount': '0.00000000',
- // 'currencyPair': 'xlm_usdt',
- // 'fee': '0.0113766632239302 USDT',
- // 'feeCurrency': 'USDT',
- // 'feePercentage': 0.18,
- // 'feeValue': '0.0113766632239302',
- // 'filledAmount': '30.14004987',
- // 'filledRate': 0.2097,
- // 'initialAmount': '30.14004987',
- // 'initialRate': '0.2097',
- // 'left': 0,
- // 'orderNumber': '998307286',
- // 'rate': '0.2097',
- // 'status': 'closed',
- // 'timestamp': 1531158583,
- // 'type': 'sell'},
+ // createOrder
+ //
+ // {
+ // "fee": "0 ZEC",
+ // "code": 0,
+ // "rate": "0.0055",
+ // "side": 2,
+ // "type": "buy",
+ // "ctime": 1586460839.138,
+ // "market": "ZEC_BTC",
+ // "result": "true",
+ // "status": "open",
+ // "iceberg": "0",
+ // "message": "Success",
+ // "feeValue": "0",
+ // "filledRate": "0.005500000",
+ // "leftAmount": "0.60607456",
+ // "feeCurrency": "ZEC",
+ // "orderNumber": 10755887009,
+ // "filledAmount": "0",
+ // "feePercentage": 0.002,
+ // "initialAmount": "0.60607456"
+ // }
+ //
+ // {
+ // 'amount': '0.00000000',
+ // 'currencyPair': 'xlm_usdt',
+ // 'fee': '0.0113766632239302 USDT',
+ // 'feeCurrency': 'USDT',
+ // 'feePercentage': 0.18,
+ // 'feeValue': '0.0113766632239302',
+ // 'filledAmount': '30.14004987',
+ // 'filledRate': 0.2097,
+ // 'initialAmount': '30.14004987',
+ // 'initialRate': '0.2097',
+ // 'left': 0,
+ // 'orderNumber': '998307286',
+ // 'rate': '0.2097',
+ // 'status': 'closed',
+ // 'timestamp': 1531158583,
+ // 'type': 'sell'
+ // }
+ //
+ // {
+ // "orderNumber": 10802237760,
+ // "orderType": 1,
+ // "type": "buy",
+ // "rate": "0.54250000",
+ // "amount": "45.55638518",
+ // "total": "24.71433896",
+ // "initialRate": "0.54250000",
+ // "initialAmount": "45.55638518",
+ // "filledRate": "0.54250000",
+ // "filledAmount": "0",
+ // "currencyPair": "nano_usdt",
+ // "timestamp": 1586556143,
+ // "status": "open"
+ // }
//
const id = this.safeString2 (order, 'orderNumber', 'id');
let symbol = undefined;
@@ -56556,12 +56328,15 @@ module.exports = class gateio extends Exchange {
} else if (side === '2') {
side = 'buy';
}
- const price = this.safeFloat2 (order, 'initialRate', 'price');
+ const price = this.safeFloat2 (order, 'initialRate', 'rate');
const average = this.safeFloat (order, 'filledRate');
const amount = this.safeFloat2 (order, 'initialAmount', 'amount');
const filled = this.safeFloat (order, 'filledAmount');
// In the order status response, this field has a different name.
- const remaining = this.safeFloat2 (order, 'leftAmount', 'left');
+ let remaining = this.safeFloat2 (order, 'leftAmount', 'left');
+ if (remaining === undefined) {
+ remaining = amount - filled;
+ }
const feeCost = this.safeFloat (order, 'feeValue');
const feeCurrencyId = this.safeString (order, 'feeCurrency');
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
@@ -56687,7 +56462,7 @@ module.exports = class gateio extends Exchange {
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
- throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol param');
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -56866,7 +56641,7 @@ module.exports = class gateio extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],89:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],88:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -57049,8 +56824,7 @@ module.exports = class gemini extends Exchange {
if (numTables < 2) {
throw new NotSupported (error);
}
- // tables[1] = tables[1].replace ("\n", ''); // eslint-disable-line quotes
- const rows = tables[1].split ("
\n"); // eslint-disable-line quotes
+ const rows = tables[1].split ("\n
\n"); // eslint-disable-line quotes
const numRows = rows.length;
if (numRows < 2) {
throw new NotSupported (error);
@@ -57061,66 +56835,73 @@ module.exports = class gemini extends Exchange {
const row = rows[i];
const cells = row.split ("\n"); // eslint-disable-line quotes
const numCells = cells.length;
- if (numCells < 7) {
+ if (numCells < 9) {
throw new NotSupported (error);
}
- //
// [
- // 'btcusd',
- // ' | USD', // quote
- // ' | BTC', // base
- // ' | 0.00001 BTC (1e-5)', // min amount
- // ' | 0.00000001 BTC (1e-8)', // amount min tick size
- // ' | 0.01 USD', // price min tick size
- // ' |
\n'
+ // 'BTC', // currency
+ // ' | 0.00001 BTC (1e-5)', // min order size
+ // ' | 0.00000001 BTC (1e-8)', // tick size
+ // ' | 0.01 USD', // usd price increment
+ // ' | N/A', // btc price increment
+ // ' | 0.0001 ETH (1e-4)', // eth price increment
+ // ' | 0.0001 BCH (1e-4)', // bch price increment
+ // ' | 0.001 LTC (1e-3)', // ltc price increment
+ // ''
// ]
//
- let id = cells[0].replace (' | ', '');
- id = id.replace ('', '');
- id = id.replace ('', '');
- let baseId = cells[2].replace (' | ', '');
- let quoteId = cells[1].replace (' | ', '');
- const minAmountAsString = cells[3].replace (' | ', '');
- const amountTickSizeAsString = cells[4].replace (' | ', '');
- const priceTickSizeAsString = cells[5].replace (' | ', '');
- const minAmount = minAmountAsString.split (' ');
- const amountPrecision = amountTickSizeAsString.split (' ');
- const pricePrecision = priceTickSizeAsString.split (' ');
- baseId = baseId.toLowerCase ();
- quoteId = quoteId.toLowerCase ();
+ const uppercaseBaseId = cells[0].replace (' | ', '');
+ const baseId = uppercaseBaseId.toLowerCase ();
const base = this.safeCurrencyCode (baseId);
- const quote = this.safeCurrencyCode (quoteId);
- const symbol = base + '/' + quote;
- const precision = {
- 'amount': this.precisionFromString (amountPrecision[0]),
- 'price': this.precisionFromString (pricePrecision[0]),
- };
- const active = undefined;
- result.push ({
- 'id': id,
- 'info': row,
- 'symbol': symbol,
- 'base': base,
- 'quote': quote,
- 'baseId': baseId,
- 'quoteId': quoteId,
- 'active': active,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': parseFloat (minAmount[0]),
- 'max': undefined,
+ const quoteIds = [ 'usd', 'btc', 'eth', 'bch', 'ltc' ];
+ const minAmountString = cells[1].replace (' | ', '');
+ const minAmountParts = minAmountString.split (' ');
+ const minAmount = this.safeFloat (minAmountParts, 0);
+ const amountPrecisionString = cells[2].replace (' | ', '');
+ const amountPrecisionParts = amountPrecisionString.split (' ');
+ const amountPrecision = this.precisionFromString (amountPrecisionParts[0]);
+ for (let j = 0; j < quoteIds.length; j++) {
+ const quoteId = quoteIds[j];
+ const quote = this.safeCurrencyCode (quoteId);
+ const pricePrecisionIndex = this.sum (3, j);
+ const pricePrecisionString = cells[pricePrecisionIndex].replace (' | ', '');
+ if (pricePrecisionString === 'N/A') {
+ continue;
+ }
+ const pricePrecisionParts = pricePrecisionString.split (' ');
+ const pricePrecision = this.precisionFromString (pricePrecisionParts[0]);
+ const symbol = base + '/' + quote;
+ const id = baseId + quoteId;
+ const active = undefined;
+ result.push ({
+ 'id': id,
+ 'info': row,
+ 'symbol': symbol,
+ 'base': base,
+ 'quote': quote,
+ 'baseId': baseId,
+ 'quoteId': quoteId,
+ 'active': active,
+ 'precision': {
+ 'amount': amountPrecision,
+ 'price': pricePrecision,
},
- 'price': {
- 'min': undefined,
- 'max': undefined,
+ 'limits': {
+ 'amount': {
+ 'min': minAmount,
+ 'max': undefined,
+ },
+ 'price': {
+ 'min': undefined,
+ 'max': undefined,
+ },
+ 'cost': {
+ 'min': undefined,
+ 'max': undefined,
+ },
},
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- },
- });
+ });
+ }
}
return result;
}
@@ -57569,7 +57350,2028 @@ module.exports = class gemini extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],90:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],89:[function(require,module,exports){
+'use strict';
+
+// ---------------------------------------------------------------------------
+
+const Exchange = require ('./base/Exchange');
+const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors');
+const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
+
+// ---------------------------------------------------------------------------
+
+module.exports = class hbtc extends Exchange {
+ describe () {
+ return this.deepExtend (super.describe (), {
+ 'id': 'hbtc',
+ 'name': 'HBTC',
+ 'countries': [ 'CN' ],
+ 'rateLimit': 2000,
+ 'version': 'v1',
+ 'has': {
+ 'CORS': false,
+ 'fetchTime': true,
+ 'fetchBidAsk': true,
+ 'fetchBidsAsks': true,
+ 'fetchTickers': true,
+ 'fetchTicker': true,
+ 'fetchDepositAddress': false,
+ 'fetchOHLCV': true,
+ 'fetchOrder': true,
+ 'fetchOrders': false,
+ 'fetchOpenOrders': true,
+ 'fetchClosedOrders': true,
+ 'fetchTradingLimits': true,
+ 'fetchMarkets': true,
+ 'fetchMyTrades': true,
+ 'withdraw': true,
+ 'fetchCurrencies': false,
+ 'fetchDeposits': true,
+ 'fetchWithdrawals': true,
+ 'fetchAccounts': true,
+ 'fetchLedger': true,
+ },
+ 'timeframes': {
+ '1m': '1m',
+ '3m': '3m',
+ '5m': '5m',
+ '15m': '15m',
+ '30m': '30m',
+ '1h': '1h',
+ '2h': '2h',
+ '4h': '4h',
+ '6h': '6h',
+ '8h': '8h',
+ '12h': '12h',
+ '1d': '1d',
+ '3d': '3d',
+ '1w': '1w',
+ '1M': '1M',
+ },
+ 'urls': {
+ 'logo': 'https://user-images.githubusercontent.com/51840849/80134449-70663300-85a7-11ea-8942-e204cdeaab5d.jpg', // 交易所LOGO
+ 'api': {
+ 'quote': 'https://api.hbtc.com/openapi/quote', // 市场API数据端点
+ 'contract': 'https://api.hbtc.com/openapi/contract', // 合约API数据端点
+ 'option': 'https://api.hbtc.com/openapi/option', // 合约API数据端点
+ 'public': 'https://api.hbtc.com/openapi', // 公共API数据端点
+ 'private': 'https://api.hbtc.com/openapi', // 私有API数据端点
+ 'zendesk': 'https://hbtc.zendesk.com/hc/en-us',
+ },
+ 'www': 'https://www.hbtc.com', // 公司主页
+ 'referral': 'https://www.hbtc.com/register/O2S8NS', // 邀请链接
+ 'doc': 'https://github.com/bhexopen/BHEX-OpenApi/tree/master/doc', // openapi文档地址
+ 'fees': 'https://hbtc.zendesk.com/hc/zh-cn/articles/360009274694', // 费率介绍
+ },
+ 'api': {
+ 'public': {
+ 'get': [
+ 'ping',
+ 'time',
+ 'brokerInfo', // 查询当前broker交易规则和symbol信息
+ 'getOptions',
+ ],
+ },
+ 'quote': {
+ 'get': [
+ 'depth', // 获取深度
+ 'depth/merged',
+ 'trades', // 获取当前最新成交
+ 'klines', // 获取K线数据
+ 'ticker/24hr', // 获取24小时价格变化数据
+ 'ticker/price',
+ 'ticker/bookTicker',
+ 'contract/index', // 获取合约标的指数价格
+ 'contract/depth', // 获取合约深度
+ 'contract/depth/merged',
+ 'contract/trades', // 获取合约最近成交,
+ 'contract/klines', // 获取合约的K线数据
+ 'contract/ticker/24hr',
+ 'option/index',
+ 'option/depth',
+ 'option/depth/merged',
+ 'option/trades',
+ 'option/klines',
+ 'option/ticker/24hr',
+ ],
+ },
+ 'contract': {
+ 'get': [
+ // public
+ 'insurance',
+ 'fundingRate', // 获取资金费率信息
+ // private
+ 'openOrders', // 查询合约当前委托
+ 'historyOrders', // 查询合约历史委托
+ 'getOrder', // 查询合约订单详情
+ 'myTrades', // 查询合约历史成交
+ 'positions', // 查询合约当前持仓
+ 'account', // 查询合约账户信息
+ ],
+ 'post': [
+ 'order', // 创建合约订单
+ 'modifyMargin', // 修改保证金
+ ],
+ 'delete': [
+ 'order/cancel', // 取消合约订单
+ 'order/batchCancel',
+ ],
+ },
+ 'option': {
+ 'get': [
+ 'openOrders',
+ 'positions',
+ 'historyOrders',
+ // 'getOrder',
+ 'myTrades',
+ 'settlements',
+ 'account',
+ ],
+ 'post': [
+ 'order',
+ ],
+ 'delete': [
+ 'order/cancel',
+ ],
+ },
+ 'private': {
+ 'get': [
+ 'order', // 查询订单
+ 'openOrders', // 查询当前委托
+ 'historyOrders', // 查询历史委托
+ 'account', // 获取当前账户信息
+ 'myTrades', // 查询历史成交
+ 'depositOrders',
+ 'withdrawalOrders',
+ 'withdraw/detail',
+ 'balance_flow',
+ ],
+ 'post': [
+ 'order', // 创建新订单
+ 'order/test',
+ 'userDataStream',
+ 'subAccount/query',
+ 'transfer',
+ 'user/transfer',
+ 'withdraw',
+ ],
+ 'put': [
+ 'userDataStream',
+ ],
+ 'delete': [
+ 'order', // 取消订单
+ 'userDataStream',
+ ],
+ },
+ },
+ 'precisionMode': TICK_SIZE,
+ 'fees': {
+ 'trading': {
+ 'tierBased': false,
+ 'percentage': true,
+ 'maker': 0.002, // MAKER费率
+ 'taker': 0.002, // TAKER费率
+ },
+ },
+ 'exceptions': {
+ 'exact': {
+ // general server or network errors
+ '-1000': ExchangeError, // An unknown error occured while processing the request
+ '-1001': ExchangeError, // Internal error, unable to process your request. Please try again
+ '-1002': AuthenticationError, // You are not authorized to execute this request. Request need API Key included in. We suggest that API Key be included in any request
+ '-1003': RateLimitExceeded, // Too many requests, please use the websocket for live updates
+ '-1004': BadRequest,
+ '-1005': PermissionDenied,
+ '-1006': BadResponse, // An unexpected response was received from the message bus. Execution status unknown. OPEN API server find some exception in execute request.Please report to Customer service
+ '-1007': RequestTimeout, // Timeout waiting for response from backend server. Send status unknown, execution status unknown
+ '-1014': InvalidOrder, // Unsupported order combination
+ '-1015': RateLimitExceeded, // Reach the rate limit.Please slow down your request speed
+ '-1016': ExchangeNotAvailable, // This service is no longer available
+ '-1020': NotSupported, // This operation is not supported
+ '-1021': BadRequest, // Timestamp for this request is outside of the recvWindow
+ '-1022': AuthenticationError, // Signature for this request is not valid
+ // request issues
+ '-1100': BadRequest, // Illegal characters found in a parameter
+ '-1101': BadRequest, // Too many parameters sent for this endpoint
+ '-1102': BadRequest, // A mandatory parameter was not sent, was empty/null, or malformed
+ '-1103': BadRequest, // An unknown parameter was sent
+ '-1104': BadRequest, // Not all sent parameters were read
+ '-1105': BadRequest, // A parameter was empty
+ '-1106': BadRequest, // A parameter was sent when not required
+ '-1111': BadRequest, // Precision is over the maximum defined for this asset
+ '-1112': NullResponse, // No orders on book for symbol
+ '-1114': InvalidOrder, // TimeInForce parameter sent when not required
+ '-1115': InvalidOrder, // Invalid timeInForce
+ '-1116': InvalidOrder, // Invalid orderType
+ '-1117': InvalidOrder, // Invalid side
+ '-1118': InvalidOrder, // New client order ID was empty
+ '-1119': InvalidOrder, // Original client order ID was empty
+ '-1120': BadRequest, // Invalid interval
+ '-1121': BadSymbol, // Invalid symbol
+ '-1125': AuthenticationError, // This listenKey does not exist
+ '-1127': BadRequest, // Lookup interval is too big
+ '-1128': BadRequest, // Combination of optional parameters invalid
+ '-1130': BadRequest, // Invalid data sent for a parameter
+ '-1131': InsufficientFunds,
+ '-1132': InvalidOrder, // Order price too high
+ '-1133': InvalidOrder, // Order price lower than the minimum,please check general broker info
+ '-1134': InvalidOrder, // Order price decimal too long,please check general broker info
+ '-1135': InvalidOrder, // Order quantity too large
+ '-1136': InvalidOrder, // Order quantity lower than the minimum
+ '-1137': InvalidOrder, // Order quantity decimal too long
+ '-1138': InvalidOrder, // Order price exceeds permissible range
+ '-1139': InvalidOrder, // Order has been filled
+ '-1140': InvalidOrder, // Transaction amount lower than the minimum
+ '-1141': InvalidOrder, // Duplicate clientOrderId
+ '-1142': InvalidOrder, // Order has been canceled
+ '-1143': OrderNotFound, // Cannot be found on order book
+ '-1144': InvalidOrder, // Order has been locked
+ '-1145': InvalidOrder, // This order type does not support cancellation
+ '-1146': RequestTimeout, // Order creation timeout
+ '-1147': RequestTimeout, // Order cancellation timeout
+ '-1149': InvalidOrder, // Create order failed
+ '-1187': InvalidAddress, // Withdrawal address not in whitelist
+ '-2010': InvalidOrder, // NEW_ORDER_REJECTED
+ '-2011': InvalidOrder, // CANCEL_REJECTED
+ '-2013': OrderNotFound, // Order does not exist
+ '-2014': AuthenticationError, // API-key format invalid
+ '-2015': AuthenticationError, // Invalid API-key, IP, or permissions for action
+ '-2016': ExchangeError, // No trading window could be found for the symbol. Try ticker/24hrs instead
+ },
+ },
+ // exchange-specific options
+ 'options': {
+ 'fetchTickers': {
+ 'method': 'quoteGetTicker24hr',
+ },
+ },
+ });
+ }
+
+ async fetchTime (params = {}) {
+ const response = await this.publicGetTime (params);
+ //
+ // {
+ // "serverTime": 1527777538000
+ // }
+ //
+ return this.safeInteger (response, 'serverTime');
+ }
+
+ parseMarket (market, type = 'spot') {
+ const filters = this.safeValue (market, 'filters', []);
+ const id = this.safeString (market, 'symbol');
+ let baseId = this.safeString (market, 'baseAsset');
+ const quoteId = this.safeString (market, 'quoteAsset');
+ let base = this.safeCurrencyCode (baseId);
+ const quote = this.safeCurrencyCode (quoteId);
+ let symbol = base + '/' + quote;
+ let spot = true;
+ let future = false;
+ let option = false;
+ let inverse = false;
+ if (type === 'future') {
+ symbol = id;
+ spot = false;
+ future = true;
+ inverse = this.safeValue (market, 'inverse', false);
+ baseId = this.safeString (market, 'underlying');
+ base = this.safeCurrencyCode (baseId);
+ } else if (type === 'option') {
+ symbol = id;
+ spot = false;
+ option = true;
+ }
+ let amountMin = undefined;
+ let amountMax = undefined;
+ let priceMin = undefined;
+ let priceMax = undefined;
+ let costMin = undefined;
+ for (let j = 0; j < filters.length; j++) {
+ const filter = filters[j];
+ const filterType = this.safeString (filter, 'filterType');
+ if (filterType === 'LOT_SIZE') {
+ amountMin = this.safeFloat (filter, 'minQty');
+ amountMax = this.safeFloat (filter, 'maxQty');
+ }
+ if (filterType === 'PRICE_FILTER') {
+ priceMin = this.safeFloat (filter, 'minPrice');
+ priceMax = this.safeFloat (filter, 'maxPrice');
+ }
+ if (filterType === 'MIN_NOTIONAL') {
+ costMin = this.safeFloat (filter, 'minNotional');
+ }
+ }
+ if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) {
+ costMin = amountMin * priceMin;
+ }
+ const precision = {
+ 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'),
+ 'amount': this.safeFloat (market, 'baseAssetPrecision'),
+ };
+ const limits = {
+ 'amount': {
+ 'min': amountMin,
+ 'max': amountMax,
+ },
+ 'price': {
+ 'min': priceMin,
+ 'max': priceMax,
+ },
+ 'cost': {
+ 'min': costMin,
+ 'max': undefined,
+ },
+ };
+ return {
+ 'id': id,
+ 'symbol': symbol,
+ 'base': base,
+ 'quote': quote,
+ 'baseId': baseId,
+ 'quoteId': quoteId,
+ 'active': true,
+ 'type': type,
+ 'spot': spot,
+ 'future': future,
+ 'option': option,
+ 'inverse': inverse,
+ 'precision': precision,
+ 'limits': limits,
+ 'info': market,
+ };
+ }
+
+ async fetchMarkets (params = {}) {
+ const response = await this.publicGetBrokerInfo (params);
+ //
+ // {
+ // "timezone":"UTC",
+ // "serverTime":"1588015885118",
+ // "brokerFilters":[],
+ // "symbols":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.01","maxPrice":"100000.00000000","tickSize":"0.01","filterType":"PRICE_FILTER"},
+ // {"minQty":"0.0005","maxQty":"100000.00000000","stepSize":"0.000001","filterType":"LOT_SIZE"},
+ // {"minNotional":"5","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTCUSDT",
+ // "symbolName":"BTCUSDT",
+ // "status":"TRADING",
+ // "baseAsset":"BTC",
+ // "baseAssetPrecision":"0.000001",
+ // "quoteAsset":"USDT",
+ // "quotePrecision":"0.01",
+ // "icebergAllowed":false
+ // },
+ // ],
+ // "options":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.01","maxPrice":"100000.00000000","tickSize":"0.01","filterType":"PRICE_FILTER"},
+ // {"minQty":"0.01","maxQty":"100000.00000000","stepSize":"0.001","filterType":"LOT_SIZE"},
+ // {"minNotional":"1","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC0501CS8500",
+ // "symbolName":"BTC0501CS8500",
+ // "status":"TRADING",
+ // "baseAsset":"BTC0501CS8500",
+ // "baseAssetPrecision":"0.001",
+ // "quoteAsset":"BUSDT",
+ // "quotePrecision":"0.01",
+ // "icebergAllowed":false
+ // },
+ // ],
+ // "contracts":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-PERP-REV",
+ // "symbolName":"BTC-PERP-REV",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-PERP-REV",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"USDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":true,
+ // "index":"BTCUSDT",
+ // "marginToken":"TBTC",
+ // "marginPrecision":"0.00000001",
+ // "contractMultiplier":"1.0",
+ // "underlying":"TBTC",
+ // "riskLimits":[
+ // {"riskLimitId":"200000001","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"200000002","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"200000003","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"200000004","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-SWAP",
+ // "symbolName":"BTC-SWAP",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-SWAP",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"USDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":true,
+ // "index":"BTCUSDT",
+ // "marginToken":"BTC",
+ // "marginPrecision":"0.00000001",
+ // "contractMultiplier":"1.0",
+ // "underlying":"BTC",
+ // "riskLimits":[
+ // {"riskLimitId":"500000001","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"500000002","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"500000003","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"500000004","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-PERP-BUSDT",
+ // "symbolName":"BTC-PERP-BUSDT",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-PERP-BUSDT",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"BUSDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":false,
+ // "index":"BTCUSDT",
+ // "marginToken":"BUSDT",
+ // "marginPrecision":"0.0001",
+ // "contractMultiplier":"0.0001",
+ // "underlying":"TBTC",
+ // "riskLimits":[
+ // {"riskLimitId":"600000132","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"600000133","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"600000134","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"600000135","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // ]
+ // }
+ //
+ const result = [];
+ const symbols = this.safeValue (response, 'symbols', []);
+ for (let i = 0; i < symbols.length; i++) {
+ const market = this.parseMarket (symbols[i], 'spot');
+ result.push (market);
+ }
+ const options = this.safeValue (response, 'options', []);
+ for (let i = 0; i < options.length; i++) {
+ const market = this.parseMarket (options[i], 'option');
+ result.push (market);
+ }
+ const contracts = this.safeValue (response, 'contracts', []);
+ for (let i = 0; i < contracts.length; i++) {
+ const market = this.parseMarket (contracts[i], 'future');
+ result.push (market);
+ }
+ return result;
+ }
+
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 40, max 40
+ }
+ const response = await this.quoteGetDepth (this.extend (request, params));
+ //
+ // {
+ // "time":1588068913453,
+ // "bids":[
+ // ["0.025278","0.0202"],
+ // ["0.025277","16.1132"],
+ // ["0.025276","7.9056"],
+ // ]
+ // "asks":[
+ // ["0.025302","5.9999"],
+ // ["0.025303","34.9151"],
+ // ["0.025304","92.391"],
+ // ]
+ // }
+ //
+ const timestamp = this.safeInteger (response, 'time');
+ return this.parseOrderBook (response, timestamp);
+ }
+
+ async fetchTicker (symbol, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const response = await this.quoteGetTicker24hr (this.extend (request, params));
+ //
+ // {
+ // "time":1588069860794,
+ // "symbol":"BNB0501PS16",
+ // "bestBidPrice":"0.2129",
+ // "bestAskPrice":"0.3163",
+ // "volume":"33547",
+ // "quoteVolume":"10801.987",
+ // "lastPrice":"0.2625",
+ // "highPrice":"0.3918",
+ // "lowPrice":"0.2625",
+ // "openPrice":"0.362",
+ // }
+ //
+ return this.parseTicker (response, market);
+ }
+
+ parseTickers (rawTickers, symbols = undefined) {
+ const tickers = [];
+ for (let i = 0; i < rawTickers.length; i++) {
+ tickers.push (this.parseTicker (rawTickers[i]));
+ }
+ return this.filterByArray (tickers, 'symbol', symbols);
+ }
+
+ async fetchBidAsk (symbol, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const response = await this.quoteGetTickerBookTicker (this.extend (request, params));
+ //
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // }
+ //
+ return this.parseTicker (response, market);
+ }
+
+ async fetchBidsAsks (symbols = undefined, params = {}) {
+ await this.loadMarkets ();
+ const response = await this.quoteGetTickerBookTicker (params);
+ //
+ // [
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // },
+ // {
+ // "symbol": "ETHBTC",
+ // "bidPrice": "0.07946700",
+ // "bidQty": "9.00000000",
+ // "askPrice": "100000.00000000",
+ // "askQty": "1000.00000000"
+ // },
+ // ]
+ //
+ return this.parseTickers (response, symbols);
+ }
+
+ async fetchTickers (symbols = undefined, params = {}) {
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchTickers', {});
+ const defaultMethod = this.safeString (options, 'method', 'quoteGetTicker24hr');
+ const defaultType = this.safeString (options, 'type', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ let method = defaultMethod;
+ if (type === 'future') {
+ method = 'quoteGetContractTicker24hr';
+ } else if (type === 'option') {
+ method = 'quoteGetOptionTicker24hr';
+ }
+ const response = await this[method] (query);
+ //
+ // [
+ // {
+ // "time": 1538725500422,
+ // "symbol": "ETHBTC",
+ // "lastPrice": "4.00000200",
+ // "openPrice": "99.00000000",
+ // "highPrice": "100.00000000",
+ // "lowPrice": "0.10000000",
+ // "volume": "8913.30000000"
+ // },
+ // ]
+ //
+ return this.parseTickers (response, symbols);
+ }
+
+ async fetchBalance (params = {}) {
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchBalance', {});
+ const defaultType = this.safeString (options, 'type', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ let method = 'privateGetAccount';
+ if (type === 'future') {
+ method = 'contractGetAccount';
+ } else if (type === 'option') {
+ method = 'optionGetAccount';
+ }
+ const response = await this[method] (query);
+ //
+ // spot
+ //
+ // {
+ // 'balances': [
+ // {
+ // 'asset': 'ALGO',
+ // 'free': '0',
+ // 'locked': '0'
+ // },
+ // {
+ // 'asset': 'BHT',
+ // 'free': '0',
+ // 'locked': '0'
+ // }
+ // ]
+ // }
+ //
+ // contract
+ //
+ // {
+ // "BUSDT":{
+ // "total":"1000",
+ // "availableMargin":"1000",
+ // "positionMargin":"0",
+ // "orderMargin":"0",
+ // "tokenId":"BUSDT"
+ // },
+ // "TBTC":{
+ // "total":"0.5",
+ // "availableMargin":"0.5",
+ // "positionMargin":"0",
+ // "orderMargin":"0",
+ // "tokenId":"TBTC"
+ // }
+ // }
+ //
+ // option
+ //
+ // {
+ // "optionAsset":"",
+ // "balances":[
+ // {
+ // "tokenName":"USDT",
+ // "free":"0.0",
+ // "locked":"0.0",
+ // "margin":"0.0"
+ // },
+ // {
+ // "tokenName":"BUSDT",
+ // "free":"0.0",
+ // "locked":"0.0",
+ // "margin":"0.0"
+ // }
+ // ]
+ // }
+ //
+ const balances = this.safeValue (response, 'balances');
+ const result = { 'info': response };
+ if (balances !== undefined) {
+ for (let i = 0; i < balances.length; i++) {
+ const balance = balances[i];
+ const currencyId = this.safeString2 (balance, 'asset', 'tokenName');
+ const code = this.safeCurrencyCode (currencyId);
+ const account = this.account ();
+ account['free'] = this.safeFloat (balance, 'free');
+ account['used'] = this.safeFloat (balance, 'locked');
+ result[code] = account;
+ }
+ } else {
+ const currencyIds = Object.keys (response);
+ for (let i = 0; i < currencyIds.length; i++) {
+ const currencyId = currencyIds[i];
+ const code = this.safeCurrencyCode (currencyId);
+ const balance = response[currencyId];
+ const account = this.account ();
+ account['free'] = this.safeFloat (balance, 'availableMargin');
+ account['total'] = this.safeFloat (balance, 'total');
+ result[code] = account;
+ }
+ }
+ return this.parseBalance (result);
+ }
+
+ async fetchTrades (symbol, since = undefined, limit = 50, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ const response = await this.quoteGetTrades (this.extend (request, params));
+ //
+ // [
+ // {"price":"0.025344","time":1588084082060,"qty":"1","isBuyerMaker":false},
+ // {"price":"0.02535","time":1588084086021,"qty":"0.553","isBuyerMaker":true},
+ // {"price":"0.025348","time":1588084097037,"qty":"1","isBuyerMaker":false},
+ // ]
+ //
+ return this.parseTrades (response, market, since, limit);
+ }
+
+ parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
+ //
+ // [
+ // 1587906000000, // open time
+ // "0.1761", // open
+ // "0.1761", // high
+ // "0.1761", // low
+ // "0.1761", // close
+ // "0", // base volume
+ // 0, // close time
+ // "0", // quote volume
+ // 0, // number of trades
+ // "0", // taker buy base asset volume
+ // "0" // taker buy quote asset volume
+ // ]
+ //
+ return [
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 5),
+ ];
+ }
+
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ 'interval': this.timeframes[timeframe],
+ };
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 500
+ }
+ const response = await this.quoteGetKlines (this.extend (request, params));
+ //
+ // [
+ // [1587906000000,"0.1761","0.1761","0.1761","0.1761","0",0,"0",0,"0","0"],
+ // [1587906180000,"0.1761","0.1761","0.1761","0.1761","0",0,"0",0,"0","0"],
+ // [1587906360000,"0.1761","0.1848","0.1761","0.1848","53",0,"9.7944",1,"0","0"],
+ // ]
+ //
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
+ }
+
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if only fromId is set,it will get orders < that fromId in descending order
+ // if only toId is set, it will get orders > that toId in ascending order
+ // if fromId is set and toId is set, it will get orders < that fromId and > that toId in descending order
+ // if fromId is not set and toId it not set, most recent order are returned in descending order
+ // 'fromId': '43287482374',
+ // 'toId': '43287482374',
+ // 'endTime': this.milliseconds (), // optional, spot only
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchMyTrades', {});
+ const fetchMyTradesType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchMyTradesType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ // spot default 500, max 1000
+ // futures and options default 20, max 1000
+ request['limit'] = limit;
+ }
+ let method = 'privateGetMyTrades';
+ if (type === 'future') {
+ method = 'contractGetMyTrades';
+ } else {
+ if (type === 'option') {
+ method = 'optionGetMyTrades';
+ } else {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a `symbol` argument for ' + type + ' markets');
+ }
+ const market = this.market (symbol);
+ request['symbol'] = market['id'];
+ // spot only?
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ }
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // "id":"616384027512920576",
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616384027202542080",
+ // "matchOrderId":"605124954767266560",
+ // "price":"6826.06",
+ // "qty":"0.1",
+ // "commission":"0.682606",
+ // "commissionAsset":"BUSDT",
+ // "time":"1588214701982",
+ // "isBuyer":false,
+ // "isMaker":false,
+ // "fee":{
+ // "feeTokenId":"BUSDT",
+ // "feeTokenName":"BUSDT",
+ // "fee":"0.682606"
+ // }
+ // }
+ // ]
+ //
+ return this.parseTrades (response, market, since, limit);
+ }
+
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const orderSide = side.toUpperCase ();
+ const orderType = type.toUpperCase ();
+ const request = {
+ 'symbol': market['id'],
+ // BUY or SELL for spot and options
+ 'side': orderSide,
+ // GTC, FOK, IOC for spot and options
+ // GTC, FOK, IOC, LIMIT_MAKER for futures
+ // 'timeInForce': 'GTC',
+ };
+ let query = params;
+ let method = 'privatePostOrder';
+ if (market['type'] === 'future') {
+ if ((orderSide !== 'BUY_OPEN') && (orderSide !== 'SELL_OPEN') && (orderSide !== 'BUY_CLOSE') && (orderSide !== 'SELL_CLOSE')) {
+ throw new NotSupported (this.id + ' createOrder() does not support order side ' + side + ' for ' + market['type'] + ' markets, only BUY_OPEN, SELL_OPEN, BUY_CLOSE and SELL_CLOSE are supported');
+ }
+ if ((orderType !== 'LIMIT') && (orderType !== 'STOP')) {
+ throw new NotSupported (this.id + ' createOrder() does not support order type ' + type + ' for ' + market['type'] + ' markets, only LIMIT and STOP are supported');
+ }
+ const clientOrderId = this.safeValue (params, 'clientOrderId');
+ if (clientOrderId === undefined) {
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a clientOrderId parameter for ' + market['type'] + ' markets, supply clientOrderId in the params argument');
+ }
+ const leverage = this.safeValue (params, 'leverage');
+ if (leverage === undefined && (orderSide === 'BUY_OPEN' || orderSide === 'SELL_OPEN')) {
+ throw new NotSupported (this.id + ' createOrder() requires a leverage parameter for ' + market['type'] + ' markets if orderSide is BUY_OPEN or SELL_OPEN');
+ }
+ method = 'contractPostOrder';
+ const priceType = this.safeString (params, 'priceType');
+ if (priceType === undefined) {
+ request['price'] = this.priceToPrecision (symbol, price);
+ } else {
+ request['priceType'] = priceType;
+ if (priceType === 'INPUT') {
+ request['price'] = this.priceToPrecision (symbol, price);
+ }
+ }
+ request['orderType'] = type.toUpperCase (); // LIMIT, STOP
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ // request['leverage'] = 1; // not required for closing orders
+ request['leverage'] = leverage;
+ request['clientOrderId'] = clientOrderId;
+ // optional
+ // request['priceType'] = 'INPUT', // INPUT, OPPONENT, QUEUE, OVER, MARKET
+ // request['triggerPrice'] = 123.45;
+ } else {
+ if (market['type'] === 'option') {
+ method = 'optionPostOrder';
+ }
+ const newClientOrderId = this.safeValue2 (params, 'clientOrderId', 'newClientOrderId');
+ if (newClientOrderId !== undefined) {
+ request['newClientOrderId'] = newClientOrderId;
+ }
+ request['type'] = orderType;
+ if (type === 'limit') {
+ request['price'] = this.priceToPrecision (symbol, price);
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ } else if (type === 'market') {
+ // for market buy it requires the amount of quote currency to spend
+ if (side === 'buy') {
+ const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true);
+ if (createMarketBuyOrderRequiresPrice) {
+ if (price !== undefined) {
+ amount = amount * price;
+ } else {
+ throw new InvalidOrder (this.id + " createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false and supply the total cost value in the 'amount' argument (the exchange-specific behaviour)");
+ }
+ }
+ const precision = market['precision']['price'];
+ request['quantity'] = this.decimalToPrecision (amount, TRUNCATE, precision, this.precisionMode);
+ } else {
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ }
+ }
+ }
+ query = this.omit (query, [ 'clientOrderId', 'newClientOrderId' ]);
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // {
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616376654496877056",
+ // "clientOrderId":"158821382304516955",
+ // "transactTime":"1588213823080",
+ // "price":"0",
+ // "origQty":"1000",
+ // "executedQty":"0",
+ // "status":"NEW",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"BUY"
+ // }
+ //
+ // contract
+ //
+ // {
+ // 'time': '1570759718825',
+ // 'updateTime': '0',
+ // 'orderId': '469961015902208000',
+ // 'clientOrderId': '6423344174',
+ // 'symbol': 'BTC-PERP-REV',
+ // 'price': '8200',
+ // 'leverage': '12.08',
+ // 'origQty': '5',
+ // 'executedQty': '0',
+ // 'avgPrice': '0',
+ // 'marginLocked': '0.00005047',
+ // 'orderType': 'LIMIT',
+ // 'side': 'BUY_OPEN',
+ // 'fees': [],
+ // 'timeInForce': 'GTC',
+ // 'status': 'NEW',
+ // 'priceType': 'INPUT'
+ // }
+ //
+ return this.parseOrder (response, market);
+ }
+
+ async cancelOrder (id, symbol = undefined, params = {}) {
+ await this.loadMarkets ();
+ const clientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
+ const request = {};
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'cancelOrder', {});
+ const cancelOrderType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', cancelOrderType);
+ let query = this.omit (params, 'type');
+ if (clientOrderId !== undefined) {
+ request['origClientOrderId'] = clientOrderId;
+ query = this.omit (query, [ 'origClientOrderId', 'clientOrderId' ]);
+ } else {
+ request['orderId'] = id;
+ }
+ let method = 'privateDeleteOrder';
+ const orderType = this.safeString (query, 'orderType');
+ if (orderType !== undefined) {
+ type = 'future';
+ }
+ if (type === 'future') {
+ method = 'contractDeleteOrderCancel';
+ if (orderType === undefined) {
+ throw new ArgumentsRequired (this.id + " cancelOrder() requires an orderType parameter, pass the { 'orderType': 'LIMIT' } or { 'orderType': 'STOP' } in params argument");
+ }
+ request['orderType'] = orderType;
+ } else {
+ if (type === 'option') {
+ method = 'optionDeleteOrderCancel';
+ }
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // {
+ // 'exchangeId': '301',
+ // 'symbol': 'BHTUSDT',
+ // 'clientOrderId': '0',
+ // 'orderId': '499890200602846976',
+ // 'status': 'CANCELED'
+ // }
+ //
+ // futures
+ //
+ // {
+ // "time":"1588353669383",
+ // "updateTime":"0",
+ // "orderId":"617549770304599296",
+ // "clientOrderId":"test-001",
+ // "symbol":"BTC-PERP-REV",
+ // "price":"10000",
+ // "leverage":"1",
+ // "origQty":"100",
+ // "executedQty":"0",
+ // "avgPrice":"0",
+ // "marginLocked":"0",
+ // "orderType":"LIMIT",
+ // "side":"SELL_OPEN",
+ // "fees":[],
+ // "timeInForce":"GTC",
+ // "status":"CANCELED",
+ // "priceType":"INPUT",
+ // }
+ //
+ return this.parseOrder (response);
+ }
+
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if orderId is set, it will get orders < that orderId otherwise most recent orders are returned
+ // 'orderId': '43287482374',
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchOpenOrders', {});
+ const fetchOpenOrdersType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchOpenOrdersType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ let method = 'privateGetOpenOrders';
+ if (type === 'future') {
+ method = 'contractGetOpenOrders';
+ } else if (type === 'option') {
+ method = 'optionGetOpenOrders';
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // 'orderId': '499902955766523648',
+ // 'clientOrderId': '157432907618453',
+ // 'exchangeId': '301',
+ // 'symbol': 'BHTUSDT',
+ // 'price': '0.01',
+ // 'origQty': '50',
+ // 'executedQty': '0',
+ // 'cummulativeQuoteQty': '0',
+ // 'avgPrice': '0',
+ // 'status': 'NEW',
+ // 'timeInForce': 'GTC',
+ // 'type': 'LIMIT',
+ // 'side': 'BUY',
+ // 'stopPrice': '0.0',
+ // 'icebergQty': '0.0',
+ // 'time': '1574329076202',
+ // 'updateTime': '0',
+ // 'isWorking': true
+ // }
+ // ]
+ //
+ // futures
+ //
+ // [
+ // {
+ // "time":"1588353669383",
+ // "updateTime":"0",
+ // "orderId":"617549770304599296",
+ // "clientOrderId":"test-001",
+ // "symbol":"BTC-PERP-REV",
+ // "price":"10000",
+ // "leverage":"1",
+ // "origQty":"100",
+ // "executedQty":"0",
+ // "avgPrice":"0",
+ // "marginLocked":"0.01",
+ // "orderType":"LIMIT",
+ // "side":"SELL_OPEN",
+ // "fees":[],
+ // "timeInForce":"GTC",
+ // "status":"NEW",
+ // "priceType":"INPUT"
+ // }
+ // ]
+ //
+ return this.parseOrders (response, market, since, limit);
+ }
+
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if orderId is set, it will get orders < that orderId otherwise most recent orders are returned
+ // 'orderId': '43287482374',
+ // 'endTime': this.milliseconds (), // optional
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchClosedOrders', {});
+ const fetchClosedOrdersType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchClosedOrdersType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ let method = 'privateGetHistoryOrders';
+ if (type === 'future') {
+ method = 'contractGetHistoryOrders';
+ } else if (type === 'option') {
+ method = 'optionGetHistoryOrders';
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // "orderId":"616384027202542080",
+ // "clientOrderId":"158821470194414688",
+ // "exchangeId":"301",
+ // "symbol":"TBTCBUSDT",
+ // "price":"0",
+ // "origQty":"0.1",
+ // "executedQty":"0.1",
+ // "cummulativeQuoteQty":"682.606",
+ // "avgPrice":"6826.06",
+ // "status":"FILLED",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"SELL",
+ // "stopPrice":"0.0",
+ // "icebergQty":"0.0",
+ // "time":"1588214701974",
+ // "updateTime":"0",
+ // "isWorking":true
+ // }
+ // ]
+ //
+ return this.parseOrders (response, market, since, limit);
+ }
+
+ async fetchOrder (id, symbol = undefined, params = {}) {
+ await this.loadMarkets ();
+ const clientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
+ const request = {};
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchOrder', {});
+ const fetchOrderType = this.safeString (options, 'type', defaultType);
+ const type = this.safeString (params, 'type', fetchOrderType);
+ let query = this.omit (params, 'type');
+ if (clientOrderId !== undefined) {
+ request['origClientOrderId'] = clientOrderId;
+ query = this.omit (query, [ 'origClientOrderId', 'clientOrderId' ]);
+ } else {
+ request['orderId'] = id;
+ }
+ let method = 'privateGetOrder';
+ if (type === 'future') {
+ method = 'contractGetGetOrder';
+ } else if (type === 'option') {
+ method = 'optionGetGetOrder';
+ }
+ const response = await this[method] (this.extend (request, query));
+ return this.parseOrder (response);
+ }
+
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let currency = undefined;
+ const request = {
+ // 'fromId': 'string', // if fromId is set, it will get deposits > that fromId, otherwise most recent deposits are returned
+ };
+ if (code !== undefined) {
+ currency = this.currency (code);
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit;
+ }
+ const response = await this.privateGetDepositOrders (this.extend (request, params));
+ //
+ // [
+ // {
+ // 'time': '1565769575929',
+ // 'orderId': '428100569859739648',
+ // 'token': 'USDT',
+ // 'address': '',
+ // 'addressTag': '',
+ // 'fromAddress': '',
+ // 'fromAddressTag': '',
+ // 'quantity': '1100',
+ // },
+ // ]
+ //
+ return this.parseTransactions (response, currency, since, limit);
+ }
+
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let currency = undefined;
+ const request = {
+ // 'fromId': 'string', // if fromId is set, it will get deposits > that fromId, otherwise most recent deposits are returned
+ };
+ if (code !== undefined) {
+ currency = this.currency (code);
+ request['token'] = currency['id'];
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ const response = await this.privateGetWithdrawalOrders (this.extend (request, params));
+ //
+ // [
+ // {
+ // "time":"1536232111669",
+ // "orderId":"90161227158286336",
+ // "accountId":"517256161325920",
+ // "tokenId":"BHC",
+ // "tokenName":"BHC",
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
+ // "addressExt":"address tag",
+ // "quantity":"14", // Withdrawal qty
+ // "arriveQuantity":"14", // Arrived qty
+ // "statusCode":"PROCESSING_STATUS",
+ // "status":3,
+ // "txid":"",
+ // "txidUrl":"",
+ // "walletHandleTime":"1536232111669",
+ // "feeTokenId":"BHC",
+ // "feeTokenName":"BHC",
+ // "fee":"0.1",
+ // "requiredConfirmNum":0, // Required confirmations
+ // "confirmNum":0, // Confirmations
+ // "kernelId":"", // BEAM and GRIN only
+ // "isInternalTransfer": false // True if this transfer is internal
+ // }
+ // ]
+ //
+ return this.parseTransactions (response, currency, since, limit);
+ }
+
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
+ this.checkAddress (address);
+ await this.loadMarkets ();
+ const currency = this.currency (code);
+ const clientOrderId = this.safeString (params, 'clientOrderId', this.uuid ());
+ const request = {
+ 'clientOrderId': clientOrderId,
+ 'tokenId': currency['id'],
+ 'address': address, // the withdrawal address must be in current tag list in your PC/APP client
+ 'withdrawQuantity': amount,
+ // 'chainType': 'OMNI', // OMNI, ERC20, TRC20
+ };
+ if (tag !== undefined) {
+ request['addressExt'] = tag;
+ }
+ const response = await this.privatePostWithdraw (this.extend (request, params));
+ //
+ // {
+ // "status": 0,
+ // "success": true,
+ // "needBrokerAudit": false, // Whether this request needs broker auit
+ // "orderId": "423885103582776064" // Id for successful withdrawal
+ // }
+ //
+ return {
+ 'info': response,
+ 'id': this.safeString (response, 'orderId'),
+ };
+ }
+
+ async fetchAccounts (params = {}) {
+ const response = await this.privatePostSubAccountQuery (params);
+ //
+ // [
+ // {
+ // "accountId": "122216245228131",
+ // "accountName": "createSubAccountByCurl", // sub-account name
+ // "accountType": 1, // 1 token trading, 2 options, 3 futures
+ // "accountIndex": 1, // 0 main account, 1 sub-account
+ // },
+ // ]
+ //
+ const result = [];
+ for (let i = 0; i < response.length; i++) {
+ const account = response[i];
+ const accountId = this.safeString (account, 'accountId');
+ const accountType = this.safeString (account, 'accountType');
+ let type = accountType;
+ if (accountType === '1') {
+ type = 'spot';
+ } else if (accountType === '2') {
+ type = 'option';
+ } else if (accountType === '3') {
+ type = 'future';
+ }
+ result.push ({
+ 'id': accountId,
+ 'type': type,
+ 'currency': undefined,
+ 'info': account,
+ });
+ }
+ return result;
+ }
+
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const request = {
+ 'accountType': 1, // spot 1, options 2, futures 3
+ 'accountIndex': 0, // main 0, sub-account 1
+ 'fromFlowId': '', // flowId to start from
+ 'endFlowId': '', // flowId to end with
+ 'endTime': 1588450533040,
+ };
+ let currency = undefined;
+ if (code !== undefined) {
+ currency = this.currency (code);
+ request['tokenId'] = currency['id'];
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 500
+ }
+ const response = await this.privateGetBalanceFlow (this.extend (request, params));
+ //
+ // [
+ // {
+ // "id": "539870570957903104",
+ // "accountId": "122216245228131",
+ // "tokenId": "BTC",
+ // "tokenName": "BTC",
+ // "flowTypeValue": 51,
+ // "flowType": "USER_ACCOUNT_TRANSFER",
+ // "flowName": "Transfer",
+ // "change": "-12.5",
+ // "total": "379.624059937852365", // after change
+ // "created": "1579093587214"
+ // },
+ // {
+ // "id": "536072393645448960",
+ // "accountId": "122216245228131",
+ // "tokenId": "USDT",
+ // "tokenName": "USDT",
+ // "flowTypeValue": 7,
+ // "flowType": "AIRDROP",
+ // "flowName": "Airdrop",
+ // "change": "-2000",
+ // "total": "918662.0917630848",
+ // "created": "1578640809195"
+ // }
+ // ]
+ //
+ return this.parseLedger (response, currency, since, limit);
+ }
+
+ parseLedgerEntry (item, currency = undefined) {
+ //
+ // {
+ // "id": "539870570957903104",
+ // "accountId": "122216245228131",
+ // "tokenId": "BTC",
+ // "tokenName": "BTC",
+ // "flowTypeValue": 51,
+ // "flowType": "USER_ACCOUNT_TRANSFER",
+ // "flowName": "Transfer",
+ // "change": "-12.5",
+ // "total": "379.624059937852365", // after change
+ // "created": "1579093587214"
+ // }
+ //
+ // {
+ // "id": "536072393645448960",
+ // "accountId": "122216245228131",
+ // "tokenId": "USDT",
+ // "tokenName": "USDT",
+ // "flowTypeValue": 7,
+ // "flowType": "AIRDROP",
+ // "flowName": "Airdrop",
+ // "change": "-2000",
+ // "total": "918662.0917630848",
+ // "created": "1578640809195"
+ // }
+ //
+ const currencyId = this.safeString (item, 'tokenId');
+ const code = this.safeCurrencyCode (currencyId, currency);
+ const amount = this.safeFloat (item, 'change');
+ const after = this.safeFloat (item, 'total');
+ const direction = (amount < 0) ? 'out' : 'in';
+ let before = undefined;
+ if (after !== undefined && amount !== undefined) {
+ const difference = (direction === 'out') ? amount : -amount;
+ before = this.sum (after, difference);
+ }
+ const timestamp = this.safeInteger (item, 'created');
+ const type = this.parseLedgerEntryType (this.safeString (item, 'flowType'));
+ const id = this.safeString (item, 'id');
+ const account = this.safeString (item, 'accountId');
+ return {
+ 'id': id,
+ 'currency': code,
+ 'account': account,
+ 'referenceAccount': undefined,
+ 'referenceId': undefined,
+ 'status': undefined,
+ 'amount': amount,
+ 'before': before,
+ 'after': after,
+ 'fee': undefined,
+ 'direction': direction,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'type': type,
+ 'info': item,
+ };
+ }
+
+ parseLedgerEntryType (type) {
+ const types = {
+ 'TRADE': 'trade',
+ 'FEE': 'fee',
+ 'TRANSFER': 'transfer',
+ 'DEPOSIT': 'transaction',
+ 'MAKER_REWARD': 'rebate',
+ 'PNL': 'pnl',
+ 'SETTLEMENT': 'settlement',
+ 'LIQUIDATION': 'liquidation',
+ 'FUNDING_SETTLEMENT': 'settlement',
+ 'USER_ACCOUNT_TRANSFER': 'transfer',
+ 'OTC_BUY_COIN': 'trade',
+ 'OTC_SELL_COIN': 'trade',
+ 'OTC_FEE': 'fee',
+ 'OTC_TRADE': 'trade',
+ 'ACTIVITY_AWARD': 'referral',
+ 'INVITATION_REFERRAL_BONUS': 'referral',
+ 'REGISTER_BONUS': 'referral',
+ 'AIRDROP': 'airdrop',
+ 'MINE_REWARD': 'reward',
+ };
+ return this.safeString (types, type, type);
+ }
+
+ parseTransactionStatus (status) {
+ const statuses = {
+ 'BROKER_AUDITING_STATUS': 'pending',
+ 'BROKER_REJECT_STATUS': 'failed',
+ 'AUDITING_STATUS': 'pending',
+ 'AUDIT_REJECT_STATUS': 'failed',
+ 'PROCESSING_STATUS': 'pending',
+ 'WITHDRAWAL_SUCCESS_STATUS': 'ok',
+ 'WITHDRAWAL_FAILURE_STATUS': 'failed',
+ 'BLOCK_MINING_STATUS': 'ok',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ parseTransaction (transaction, currency = undefined) {
+ //
+ // fetchDeposits
+ //
+ // {
+ // 'time': '1565769575929',
+ // 'orderId': '428100569859739648',
+ // 'token': 'USDT',
+ // 'address': '',
+ // 'addressTag': '',
+ // 'fromAddress': '',
+ // 'fromAddressTag': '',
+ // 'quantity': '1100',
+ // }
+ //
+ // fetchWithdrawals
+ //
+ // {
+ // "time":"1536232111669",
+ // "orderId":"90161227158286336",
+ // "accountId":"517256161325920",
+ // "tokenId":"BHC",
+ // "tokenName":"BHC",
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
+ // "addressExt":"address tag",
+ // "quantity":"14", // Withdrawal qty
+ // "arriveQuantity":"14", // Arrived qty
+ // "statusCode":"PROCESSING_STATUS",
+ // "status":3,
+ // "txid":"",
+ // "txidUrl":"",
+ // "walletHandleTime":"1536232111669",
+ // "feeTokenId":"BHC",
+ // "feeTokenName":"BHC",
+ // "fee":"0.1",
+ // "requiredConfirmNum":0, // Required confirmations
+ // "confirmNum":0, // Confirmations
+ // "kernelId":"", // BEAM and GRIN only
+ // "isInternalTransfer": false // True if this transfer is internal
+ // }
+ //
+ const id = this.safeString (transaction, 'orderId');
+ const address = this.safeString (transaction, 'address');
+ let tag = this.safeString2 (transaction, 'addressExt', 'addressTag');
+ if (tag !== undefined) {
+ if (tag.length < 1) {
+ tag = undefined;
+ }
+ }
+ const addressFrom = this.safeString (transaction, 'fromAddress');
+ let tagFrom = this.safeString (transaction, 'fromAddressTag');
+ if (tagFrom !== undefined) {
+ if (tagFrom.length < 1) {
+ tagFrom = undefined;
+ }
+ }
+ const currencyId = this.safeString (transaction, 'tokenId');
+ const code = this.safeCurrencyCode (currencyId, currency);
+ const timestamp = this.safeInteger (transaction, 'time');
+ let txid = this.safeString (transaction, 'txid');
+ if (txid === '') {
+ txid = undefined;
+ }
+ let type = undefined;
+ let status = this.parseTransactionStatus (this.safeString (transaction, 'statusCode'));
+ if (status === undefined) {
+ type = 'deposit';
+ status = 'ok';
+ } else {
+ type = 'withdrawal';
+ }
+ const amount = this.safeFloat (transaction, 'quantity');
+ const feeCost = this.safeFloat (transaction, 'fee');
+ let fee = undefined;
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (transaction, 'feeTokenId');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ fee = {
+ 'currency': feeCurrencyCode,
+ 'cost': feeCost,
+ };
+ }
+ return {
+ 'info': transaction,
+ 'id': id,
+ 'txid': txid,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'addressFrom': addressFrom,
+ 'address': address,
+ 'addressTo': address,
+ 'tagFrom': tagFrom,
+ 'tag': tag,
+ 'tagTo': tag,
+ 'type': type,
+ 'amount': amount,
+ 'currency': code,
+ 'status': status,
+ 'updated': undefined,
+ 'fee': fee,
+ };
+ }
+
+ parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker, fetchTickers
+ //
+ // {
+ // "time":1588069860794,
+ // "symbol":"BNB0501PS16",
+ // "bestBidPrice":"0.2129",
+ // "bestAskPrice":"0.3163",
+ // "volume":"33547",
+ // "quoteVolume":"10801.987",
+ // "lastPrice":"0.2625",
+ // "highPrice":"0.3918",
+ // "lowPrice":"0.2625",
+ // "openPrice":"0.362",
+ // }
+ //
+ // fetchBidAsk, fetchBidAsks
+ //
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // }
+ //
+ let symbol = undefined;
+ const marketId = this.safeString (ticker, 'symbol');
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ const timestamp = this.safeInteger (ticker, 'time');
+ const open = this.safeFloat (ticker, 'openPrice');
+ const close = this.safeFloat (ticker, 'lastPrice');
+ let change = undefined;
+ let percentage = undefined;
+ let average = undefined;
+ if ((open !== undefined) && (close !== undefined)) {
+ change = close - open;
+ average = this.sum (open, close) / 2;
+ if ((close !== undefined) && (close > 0)) {
+ percentage = (change / open) * 100;
+ }
+ }
+ const quoteVolume = this.safeFloat (ticker, 'quoteVolume');
+ const baseVolume = this.safeFloat (ticker, 'volume');
+ let vwap = undefined;
+ if (baseVolume !== undefined && quoteVolume !== undefined && baseVolume > 0) {
+ vwap = quoteVolume / baseVolume;
+ }
+ return {
+ 'symbol': symbol,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'high': this.safeFloat (ticker, 'highPrice'),
+ 'low': this.safeFloat (ticker, 'lowPrice'),
+ 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'),
+ 'bidVolume': this.safeFloat (ticker, 'bidQty'),
+ 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'),
+ 'askVolume': this.safeFloat (ticker, 'askQty'),
+ 'vwap': vwap,
+ 'open': open,
+ 'close': close,
+ 'last': close,
+ 'previousClose': undefined,
+ 'change': change,
+ 'percentage': percentage,
+ 'average': average,
+ 'baseVolume': baseVolume,
+ 'quoteVolume': quoteVolume,
+ 'info': ticker,
+ };
+ }
+
+ parseTrade (trade, market) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "price":"0.025344",
+ // "time":1588084082060,
+ // "qty":"1",
+ // "isBuyerMaker":false
+ // }
+ //
+ // fetchMyTrades (private)
+ //
+ // spot
+ //
+ // {
+ // "id":"616384027512920576",
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616384027202542080",
+ // "matchOrderId":"605124954767266560",
+ // "price":"6826.06",
+ // "qty":"0.1",
+ // "commission":"0.682606",
+ // "commissionAsset":"BUSDT",
+ // "time":"1588214701982",
+ // "isBuyer":false,
+ // "isMaker":false,
+ // "fee":{
+ // "feeTokenId":"BUSDT",
+ // "feeTokenName":"BUSDT",
+ // "fee":"0.682606"
+ // }
+ // }
+ //
+ const id = this.safeString (trade, 'id');
+ const timestamp = this.safeFloat (trade, 'time');
+ const type = undefined;
+ const orderId = this.safeString (trade, 'orderId');
+ const price = this.safeFloat (trade, 'price');
+ const amount = this.safeFloat (trade, 'qty');
+ let cost = undefined;
+ if (price !== undefined) {
+ if (amount !== undefined) {
+ cost = price * amount;
+ }
+ }
+ let side = undefined;
+ let takerOrMaker = undefined;
+ if ('isBuyerMaker' in trade) {
+ side = trade['isBuyerMaker'] ? 'sell' : 'buy';
+ } else {
+ const isMaker = this.safeValue (trade, 'isMaker');
+ if (isMaker !== undefined) {
+ takerOrMaker = isMaker ? 'maker' : 'taker';
+ }
+ const isBuyer = this.safeValue (trade, 'isBuyer');
+ side = isBuyer ? 'buy' : 'sell';
+ }
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'commission');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'commissionAsset');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ };
+ }
+ let symbol = undefined;
+ if ((symbol === undefined) && (market !== undefined)) {
+ symbol = market['symbol'];
+ }
+ return {
+ 'id': id,
+ 'info': trade,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'symbol': symbol,
+ 'type': type,
+ 'order': orderId,
+ 'side': side,
+ 'takerOrMaker': takerOrMaker,
+ 'price': price,
+ 'amount': amount,
+ 'cost': cost,
+ 'fee': fee,
+ };
+ }
+
+ parseOrder (order, market = undefined) {
+ //
+ // createOrder
+ //
+ // {
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616376654496877056",
+ // "clientOrderId":"158821382304516955",
+ // "transactTime":"1588213823080",
+ // "price":"0",
+ // "origQty":"1000",
+ // "executedQty":"0",
+ // "status":"NEW",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"BUY"
+ // }
+ //
+ // fetchOrder, fetchOpenOrders, fetchClosedOrders
+ //
+ // spot
+ //
+ // {
+ // "orderId":"616384027202542080",
+ // "clientOrderId":"158821470194414688",
+ // "exchangeId":"301",
+ // "symbol":"TBTCBUSDT",
+ // "price":"0",
+ // "origQty":"0.1",
+ // "executedQty":"0.1",
+ // "cummulativeQuoteQty":"682.606",
+ // "avgPrice":"6826.06",
+ // "status":"FILLED",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"SELL",
+ // "stopPrice":"0.0",
+ // "icebergQty":"0.0",
+ // "time":"1588214701974",
+ // "updateTime":"0",
+ // "isWorking":true
+ // }
+ //
+ // future
+ //
+ // {
+ // time: "1588353669383",
+ // updateTime: "0",
+ // orderId: "617549770304599296",
+ // clientOrderId: "test-001",
+ // symbol: "BTC-PERP-REV",
+ // price: "10000",
+ // leverage: "1",
+ // origQty: "100",
+ // executedQty: "0",
+ // avgPrice: "0",
+ // marginLocked: "0",
+ // orderType: "LIMIT",
+ // side: "SELL_OPEN",
+ // fees: [],
+ // timeInForce: "GTC",
+ // status: "CANCELED",
+ // priceType: "INPUT"
+ // }
+ //
+ //
+ const id = this.safeString (order, 'orderId');
+ const clientOrderId = this.safeString (order, 'clientOrderId');
+ let timestamp = this.safeInteger (order, 'time');
+ if (timestamp === undefined) {
+ timestamp = this.safeInteger (order, 'transactTime');
+ }
+ let symbol = undefined;
+ if (market === undefined) {
+ let marketId = this.safeString (order, 'symbol');
+ if (marketId !== undefined) {
+ marketId = marketId.toUpperCase ();
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
+ }
+ }
+ let type = this.safeStringLower (order, 'type');
+ const side = this.safeStringLower (order, 'side');
+ let price = this.safeFloat (order, 'price');
+ let average = this.safeFloat (order, 'avgPrice');
+ let amount = undefined;
+ let cost = this.safeFloat (order, 'cummulativeQuoteQty');
+ let filled = undefined;
+ let remaining = undefined;
+ if (type === undefined) {
+ type = this.safeStringLower (order, 'orderType');
+ if ((market !== undefined) && market['inverse']) {
+ cost = this.safeFloat (order, 'executedQty');
+ amount = undefined;
+ }
+ if (cost === 0.0) {
+ filled = 0;
+ }
+ } else {
+ amount = this.safeFloat (order, 'origQty');
+ if (type === 'market') {
+ price = undefined;
+ if (side === 'buy') {
+ amount = undefined;
+ }
+ }
+ filled = this.safeFloat (order, 'executedQty');
+ if (filled !== undefined) {
+ if (amount !== undefined) {
+ remaining = amount - filled;
+ }
+ }
+ }
+ if (average === 0.0) {
+ average = undefined;
+ }
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ const result = {
+ 'info': order,
+ 'id': id,
+ 'clientOrderId': clientOrderId,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
+ 'price': price,
+ 'average': average,
+ 'cost': cost,
+ 'amount': amount,
+ 'filled': filled,
+ 'remaining': remaining,
+ 'status': status,
+ 'trades': undefined,
+ 'fee': undefined,
+ 'fees': undefined,
+ };
+ const fees = this.safeValue (order, 'fees', []);
+ const numFees = fees.length;
+ if (numFees > 0) {
+ result['fees'] = [];
+ for (let i = 0; i < fees.length; i++) {
+ const feeCost = this.safeFloat (fees[i], 'fee');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (fees[i], 'feeToken');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ result['fees'].push ({
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ });
+ }
+ }
+ }
+ return result;
+ }
+
+ parseOrderStatus (status) {
+ const statuses = {
+ 'NEW': 'open',
+ 'CANCELED': 'canceled',
+ 'FILLED': 'closed',
+ 'PENDING_CANCEL': 'canceled',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
+ let url = this.urls['api'][api] + '/' + this.version + '/' + this.implodeParams (path, params);
+ const query = this.omit (params, this.extractParams (path));
+ const isPublicContract = (api === 'contract') && ((path === 'insurance') || (path === 'fundingRate'));
+ if ((api === 'public') || (api === 'quote') || isPublicContract) {
+ if (Object.keys (params).length) {
+ url += '?' + this.urlencode (params);
+ }
+ } else {
+ const timestamp = this.milliseconds ();
+ this.checkRequiredCredentials ();
+ const request = this.extend ({
+ 'timestamp': timestamp,
+ }, query);
+ // 准备待签名数据
+ const auth = this.urlencode (request);
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256');
+ request['signature'] = signature;
+ headers = {
+ 'X-BH-APIKEY': this.apiKey,
+ };
+ if (method === 'POST') {
+ body = this.urlencode (request);
+ headers = this.extend ({
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ }, headers);
+ } else {
+ url += '?' + this.urlencode (request);
+ }
+ }
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
+ }
+
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
+ if (response === undefined) {
+ return; // fallback to default error handler
+ }
+ if ('code' in response) {
+ const code = this.safeString (response, 'code');
+ if (code !== '0') {
+ const feedback = this.id + ' ' + body;
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
+ throw new ExchangeError (feedback);
+ }
+ }
+ }
+};
+
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],90:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -58302,14 +60104,13 @@ module.exports = class hitbtc extends Exchange {
}
parseOHLCV (ohlcv, market = undefined, timeframe = '1d', since = undefined, limit = undefined) {
- const timestamp = this.parse8601 (ohlcv['timestamp']);
return [
- timestamp,
- parseFloat (ohlcv['open']),
- parseFloat (ohlcv['max']),
- parseFloat (ohlcv['min']),
- parseFloat (ohlcv['close']),
- parseFloat (ohlcv['volume']),
+ this.parse8601 (this.safeString (ohlcv, 'timestamp')),
+ this.safeFloat (ohlcv, 'open'),
+ this.safeFloat (ohlcv, 'max'),
+ this.safeFloat (ohlcv, 'min'),
+ this.safeFloat (ohlcv, 'close'),
+ this.safeFloat (ohlcv, 'volume'),
];
}
@@ -59098,26 +60899,7 @@ module.exports = class hitbtc extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],91:[function(require,module,exports){
-'use strict';
-
-// ---------------------------------------------------------------------------
-
-const hitbtc = require ('./hitbtc');
-
-// ---------------------------------------------------------------------------
-
-module.exports = class hitbtc2 extends hitbtc {
- describe () {
- // this is a temporary stub for backward compatibility
- // https://github.com/ccxt/ccxt/issues/6678
- return this.deepExtend (super.describe (), {
- 'id': 'hitbtc2',
- });
- }
-};
-
-},{"./hitbtc":90}],92:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],91:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -60349,7 +62131,7 @@ module.exports = class hollaex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],93:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],92:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -60515,12 +62297,14 @@ module.exports = class huobipro extends Exchange {
'exceptions': {
'exact': {
// err-code
+ 'bad-request': BadRequest,
'api-not-support-temp-addr': PermissionDenied, // {"status":"error","err-code":"api-not-support-temp-addr","err-msg":"API withdrawal does not support temporary addresses","data":null}
'timeout': RequestTimeout, // {"ts":1571653730865,"status":"error","err-code":"timeout","err-msg":"Request Timeout"}
'gateway-internal-error': ExchangeNotAvailable, // {"status":"error","err-code":"gateway-internal-error","err-msg":"Failed to load data. Try again later.","data":null}
'account-frozen-balance-insufficient-error': InsufficientFunds, // {"status":"error","err-code":"account-frozen-balance-insufficient-error","err-msg":"trade account balance is not enough, left: `0.0027`","data":null}
'invalid-amount': InvalidOrder, // eg "Paramemter `amount` is invalid."
'order-limitorder-amount-min-error': InvalidOrder, // limit order amount error, min: `0.001`
+ 'order-limitorder-amount-max-error': InvalidOrder, // market order amount error, max: `1000000`
'order-marketorder-amount-min-error': InvalidOrder, // market order amount error, min: `0.01`
'order-limitorder-price-min-error': InvalidOrder, // limit order price error
'order-limitorder-price-max-error': InvalidOrder, // limit order price error
@@ -60683,6 +62467,8 @@ module.exports = class huobipro extends Exchange {
}
parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker
//
// {
// "amount": 26228.672978342216,
@@ -60698,25 +62484,47 @@ module.exports = class huobipro extends Exchange {
// "bid": [ 9146.86, 0.080758 ],
// }
//
+ // fetchTickers
+ // {
+ // symbol: "bhdht",
+ // open: 2.3938,
+ // high: 2.4151,
+ // low: 2.3323,
+ // close: 2.3909,
+ // amount: 628.992,
+ // vol: 1493.71841095,
+ // count: 2088,
+ // bid: 2.3643,
+ // bidSize: 0.7136,
+ // ask: 2.4061,
+ // askSize: 0.4156
+ // }
+ //
let symbol = undefined;
if (market !== undefined) {
symbol = market['symbol'];
}
const timestamp = this.safeInteger (ticker, 'ts');
let bid = undefined;
- let ask = undefined;
let bidVolume = undefined;
+ let ask = undefined;
let askVolume = undefined;
if ('bid' in ticker) {
if (Array.isArray (ticker['bid'])) {
bid = this.safeFloat (ticker['bid'], 0);
bidVolume = this.safeFloat (ticker['bid'], 1);
+ } else {
+ bid = this.safeFloat (ticker, 'bid');
+ bidVolume = this.safeValue (ticker, 'bidSize');
}
}
if ('ask' in ticker) {
if (Array.isArray (ticker['ask'])) {
ask = this.safeFloat (ticker['ask'], 0);
askVolume = this.safeFloat (ticker['ask'], 1);
+ } else {
+ ask = this.safeFloat (ticker, 'ask');
+ askVolume = this.safeValue (ticker, 'askSize');
}
}
const open = this.safeFloat (ticker, 'open');
@@ -61751,7 +63559,7 @@ module.exports = class huobipro extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],94:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],93:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -61785,13 +63593,13 @@ module.exports = class huobiru extends huobipro {
}
};
-},{"./huobipro.js":93}],95:[function(require,module,exports){
+},{"./huobipro.js":92}],94:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, AuthenticationError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -62009,7 +63817,7 @@ module.exports = class ice3x extends Exchange {
const type = this.safeString (params, 'type');
if ((type !== 'ask') && (type !== 'bid')) {
// eslint-disable-next-line quotes
- throw new ExchangeError (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
+ throw new ArgumentsRequired (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
} else {
request['items_per_page'] = limit;
}
@@ -62269,7 +64077,7 @@ module.exports = class ice3x extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],96:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],95:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -63361,7 +65169,7 @@ module.exports = class idex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],97:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],96:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -63795,7 +65603,7 @@ module.exports = class independentreserve extends Exchange {
}
};
-},{"./base/Exchange":8}],98:[function(require,module,exports){
+},{"./base/Exchange":7}],97:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -64160,7 +65968,7 @@ module.exports = class indodax extends Exchange {
async fetchOrder (id, symbol = undefined, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + ' fetchOrder requires a symbol');
+ throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -64207,7 +66015,7 @@ module.exports = class indodax extends Exchange {
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + ' fetchOrders requires a symbol');
+ throw new ArgumentsRequired (this.id + ' fetchOrders requires a symbol argument');
}
await this.loadMarkets ();
const request = {};
@@ -64256,7 +66064,7 @@ module.exports = class indodax extends Exchange {
}
const side = this.safeValue (params, 'side');
if (side === undefined) {
- throw new ExchangeError (this.id + ' cancelOrder requires an extra "side" param');
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires an extra "side" param');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -64362,13 +66170,13 @@ module.exports = class indodax extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],99:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],98:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, AuthenticationError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -64619,7 +66427,7 @@ module.exports = class itbit extends Exchange {
await this.loadMarkets ();
const walletId = this.safeString (params, 'walletId');
if (walletId === undefined) {
- throw new ExchangeError (this.id + ' fetchMyTrades requires a walletId parameter');
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a walletId parameter');
}
const request = {
'walletId': walletId,
@@ -64998,7 +66806,7 @@ module.exports = class itbit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],100:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],99:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -65584,7 +67392,7 @@ module.exports = class kkex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],101:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],100:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -65623,6 +67431,7 @@ module.exports = class kraken extends Exchange {
'withdraw': true,
'fetchLedgerEntry': true,
'fetchLedger': true,
+ 'fetchOrderTrades': 'emulated',
},
'marketsByAltname': {},
'timeframes': {
@@ -65641,7 +67450,7 @@ module.exports = class kraken extends Exchange {
'api': {
'public': 'https://api.kraken.com',
'private': 'https://api.kraken.com',
- 'zendesk': 'https://support.kraken.com/hc/en-us/articles',
+ 'zendesk': 'https://kraken.zendesk.com/api/v2/help_center/en-us/articles', // use the public zendesk api to receive article bodies and bypass new anti-spam protections
},
'www': 'https://www.kraken.com',
'doc': 'https://www.kraken.com/features/api',
@@ -65736,9 +67545,9 @@ module.exports = class kraken extends Exchange {
'get': [
// we should really refrain from putting fixed fee numbers and stop hardcoding
// we will be using their web APIs to scrape all numbers from these articles
- '205893708-What-is-the-minimum-order-size-',
- '201396777-What-are-the-deposit-fees-',
- '201893608-What-are-the-withdrawal-fees-',
+ '205893708', // -What-is-the-minimum-order-size-
+ '360000292886', // -What-are-the-deposit-fees-
+ '201893608', // -What-are-the-withdrawal-fees-
],
},
'public': {
@@ -65821,12 +67630,14 @@ module.exports = class kraken extends Exchange {
return this.decimalToPrecision (fee, TRUNCATE, this.markets[symbol]['precision']['amount'], DECIMAL_PLACES);
}
- async fetchMinOrderAmounts () {
- const html = await this.zendeskGet205893708WhatIsTheMinimumOrderSize ();
+ async fetchMinOrderAmounts (params = {}) {
+ const response = await this.zendeskGet205893708 (params);
+ const article = this.safeValue (response, 'article');
+ const html = this.safeString (article, 'body');
const parts = html.split (' | ');
const numParts = parts.length;
if (numParts < 3) {
- throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://support.kraken.com/hc/en-us/articles/205893708-What-is-the-minimum-order-size-');
+ throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://kraken.zendesk.com/api/v2/help_center/en-us/articles/205893708');
}
const result = {};
// skip the part before the header and the header itself
@@ -65849,6 +67660,52 @@ module.exports = class kraken extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetAssetPairs (params);
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "ADAETH":{
+ // "altname":"ADAETH",
+ // "wsname":"ADA\/ETH",
+ // "aclass_base":"currency",
+ // "base":"ADA",
+ // "aclass_quote":"currency",
+ // "quote":"XETH",
+ // "lot":"unit",
+ // "pair_decimals":7,
+ // "lot_decimals":8,
+ // "lot_multiplier":1,
+ // "leverage_buy":[],
+ // "leverage_sell":[],
+ // "fees":[
+ // [0,0.26],
+ // [50000,0.24],
+ // [100000,0.22],
+ // [250000,0.2],
+ // [500000,0.18],
+ // [1000000,0.16],
+ // [2500000,0.14],
+ // [5000000,0.12],
+ // [10000000,0.1]
+ // ],
+ // "fees_maker":[
+ // [0,0.16],
+ // [50000,0.14],
+ // [100000,0.12],
+ // [250000,0.1],
+ // [500000,0.08],
+ // [1000000,0.06],
+ // [2500000,0.04],
+ // [5000000,0.02],
+ // [10000000,0]
+ // ],
+ // "fee_volume_currency":"ZUSD",
+ // "margin_call":80,
+ // "margin_stop":40
+ // },
+ // }
+ // }
+ //
const fetchMinOrderAmounts = this.safeValue (this.options, 'fetchMinOrderAmounts', false);
let limits = {};
if (fetchMinOrderAmounts) {
@@ -66028,6 +67885,13 @@ module.exports = class kraken extends Exchange {
};
}
+ parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
+ const price = this.safeFloat (bidask, priceKey);
+ const amount = this.safeFloat (bidask, amountKey);
+ const timestamp = this.safeInteger (bidask, 2);
+ return [ price, amount, timestamp ];
+ }
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
@@ -66041,7 +67905,27 @@ module.exports = class kraken extends Exchange {
request['count'] = limit; // 100
}
const response = await this.publicGetDepth (this.extend (request, params));
- const orderbook = response['result'][market['id']];
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "XETHXXBT":{
+ // "asks":[
+ // ["0.023480","4.000",1586321307],
+ // ["0.023490","50.095",1586321306],
+ // ["0.023500","28.535",1586321302],
+ // ],
+ // "bids":[
+ // ["0.023470","59.580",1586321307],
+ // ["0.023460","20.000",1586321301],
+ // ["0.023440","67.832",1586321306],
+ // ]
+ // }
+ // }
+ // }
+ //
+ const result = this.safeValue (response, 'result', {});
+ const orderbook = this.safeValue (result, market['id']);
return this.parseOrderBook (orderbook);
}
@@ -66295,26 +68179,46 @@ module.exports = class kraken extends Exchange {
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // [
+ // "0.032310", // price
+ // "4.28169434", // amount
+ // 1541390792.763, // timestamp
+ // "s", // sell or buy
+ // "l", // limit or market
+ // ""
+ // ]
+ //
+ // fetchOrderTrades (private)
+ //
+ // {
+ // id: 'TIMIRG-WUNNE-RRJ6GT', // injected from outside
+ // ordertxid: 'OQRPN2-LRHFY-HIFA7D',
+ // postxid: 'TKH2SE-M7IF5-CFI7LT',
+ // pair: 'USDCUSDT',
+ // time: 1586340086.457,
+ // type: 'sell',
+ // ordertype: 'market',
+ // price: '0.99860000',
+ // cost: '22.16892001',
+ // fee: '0.04433784',
+ // vol: '22.20000000',
+ // margin: '0.00000000',
+ // misc: ''
+ // }
+ //
let timestamp = undefined;
let side = undefined;
let type = undefined;
let price = undefined;
let amount = undefined;
+ let cost = undefined;
let id = undefined;
let order = undefined;
let fee = undefined;
- const marketId = this.safeString (trade, 'pair');
- const foundMarket = this.findMarketByAltnameOrId (marketId);
let symbol = undefined;
- if (foundMarket !== undefined) {
- market = foundMarket;
- } else if (marketId !== undefined) {
- // delisted market ids go here
- market = this.getDelistedMarketById (marketId);
- }
- if (market !== undefined) {
- symbol = market['symbol'];
- }
if (Array.isArray (trade)) {
timestamp = this.safeTimestamp (trade, 2);
side = (trade[3] === 's') ? 'sell' : 'buy';
@@ -66325,17 +68229,27 @@ module.exports = class kraken extends Exchange {
if (tradeLength > 6) {
id = this.safeString (trade, 6); // artificially added as per #1794
}
+ } else if (typeof trade === 'string') {
+ id = trade;
} else if ('ordertxid' in trade) {
+ const marketId = this.safeString (trade, 'pair');
+ const foundMarket = this.findMarketByAltnameOrId (marketId);
+ if (foundMarket !== undefined) {
+ market = foundMarket;
+ } else if (marketId !== undefined) {
+ // delisted market ids go here
+ market = this.getDelistedMarketById (marketId);
+ }
order = trade['ordertxid'];
id = this.safeString2 (trade, 'id', 'postxid');
timestamp = this.safeTimestamp (trade, 'time');
- side = trade['type'];
- type = trade['ordertype'];
+ side = this.safeString (trade, 'type');
+ type = this.safeString (trade, 'ordertype');
price = this.safeFloat (trade, 'price');
amount = this.safeFloat (trade, 'vol');
if ('fee' in trade) {
let currency = undefined;
- if (market) {
+ if (market !== undefined) {
currency = market['quote'];
}
fee = {
@@ -66344,6 +68258,14 @@ module.exports = class kraken extends Exchange {
};
}
}
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ if (price !== undefined) {
+ if (amount !== undefined) {
+ cost = price * amount;
+ }
+ }
return {
'id': id,
'order': order,
@@ -66356,7 +68278,7 @@ module.exports = class kraken extends Exchange {
'takerOrMaker': undefined,
'price': price,
'amount': amount,
- 'cost': price * amount,
+ 'cost': cost,
'fee': fee,
};
}
@@ -66573,6 +68495,11 @@ module.exports = class kraken extends Exchange {
const status = this.parseOrderStatus (this.safeString (order, 'status'));
const id = this.safeString (order, 'id');
const clientOrderId = this.safeString (order, 'userref');
+ const rawTrades = this.safeValue (order, 'trades');
+ let trades = undefined;
+ if (rawTrades !== undefined) {
+ trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id });
+ }
return {
'id': id,
'clientOrderId': clientOrderId,
@@ -66591,8 +68518,7 @@ module.exports = class kraken extends Exchange {
'average': average,
'remaining': remaining,
'fee': fee,
- // 'trades': this.parseTrades (order['trades'], market),
- 'trades': undefined,
+ 'trades': trades,
};
}
@@ -66613,16 +68539,129 @@ module.exports = class kraken extends Exchange {
async fetchOrder (id, symbol = undefined, params = {}) {
await this.loadMarkets ();
- const response = await this.privatePostQueryOrders (this.extend ({
+ const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
+ const request = {
'trades': true, // whether or not to include trades in output (optional, default false)
- 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
+ // 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
// 'userref': 'optional', // restrict results to given user reference id (optional)
- }, params));
- const orders = response['result'];
+ };
+ let query = params;
+ if (clientOrderId !== undefined) {
+ request['userref'] = clientOrderId;
+ query = this.omit (params, [ 'userref', 'clientOrderId' ]);
+ } else {
+ request['txid'] = id;
+ }
+ const response = await this.privatePostQueryOrders (this.extend (request, query));
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "OTLAS3-RRHUF-NDWH5A":{
+ // "refid":null,
+ // "userref":null,
+ // "status":"closed",
+ // "reason":null,
+ // "opentm":1586822919.3342,
+ // "closetm":1586822919.365,
+ // "starttm":0,
+ // "expiretm":0,
+ // "descr":{
+ // "pair":"XBTUSDT",
+ // "type":"sell",
+ // "ordertype":"market",
+ // "price":"0",
+ // "price2":"0",
+ // "leverage":"none",
+ // "order":"sell 0.21804000 XBTUSDT @ market",
+ // "close":""
+ // },
+ // "vol":"0.21804000",
+ // "vol_exec":"0.21804000",
+ // "cost":"1493.9",
+ // "fee":"3.8",
+ // "price":"6851.5",
+ // "stopprice":"0.00000",
+ // "limitprice":"0.00000",
+ // "misc":"",
+ // "oflags":"fciq",
+ // "trades":["TT5UC3-GOIRW-6AZZ6R"]
+ // }
+ // }
+ // }
+ //
+ const orders = this.safeValue (response, 'result', []);
const order = this.parseOrder (this.extend ({ 'id': id }, orders[id]));
return this.extend ({ 'info': response }, order);
}
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ const orderTrades = this.safeValue (params, 'trades');
+ const tradeIds = [];
+ if (orderTrades === undefined) {
+ throw new ArgumentsRequired (this.id + " fetchOrderTrades requires a unified order structure in the params argument or a 'trades' param (an array of trade id strings)");
+ } else {
+ for (let i = 0; i < orderTrades.length; i++) {
+ const orderTrade = orderTrades[i];
+ if (typeof orderTrade === 'string') {
+ tradeIds.push (orderTrade);
+ } else {
+ tradeIds.push (orderTrade['id']);
+ }
+ }
+ }
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchOrderTrades', {});
+ const batchSize = this.safeInteger (options, 'batchSize', 20);
+ let numBatches = parseInt (tradeIds / batchSize);
+ numBatches = this.sum (numBatches, 1);
+ const numTradeIds = tradeIds.length;
+ let result = [];
+ for (let j = 0; j < numBatches; j++) {
+ const requestIds = [];
+ for (let k = 0; k < batchSize; k++) {
+ const index = this.sum (j * batchSize, k);
+ if (index < numTradeIds) {
+ requestIds.push (tradeIds[index]);
+ }
+ }
+ const request = {
+ 'txid': requestIds.join (','),
+ };
+ const response = await this.privatePostQueryTrades (request);
+ //
+ // {
+ // error: [],
+ // result: {
+ // 'TIMIRG-WUNNE-RRJ6GT': {
+ // ordertxid: 'OQRPN2-LRHFY-HIFA7D',
+ // postxid: 'TKH2SE-M7IF5-CFI7LT',
+ // pair: 'USDCUSDT',
+ // time: 1586340086.457,
+ // type: 'sell',
+ // ordertype: 'market',
+ // price: '0.99860000',
+ // cost: '22.16892001',
+ // fee: '0.04433784',
+ // vol: '22.20000000',
+ // margin: '0.00000000',
+ // misc: ''
+ // }
+ // }
+ // }
+ //
+ const rawTrades = this.safeValue (response, 'result');
+ const ids = Object.keys (rawTrades);
+ for (let i = 0; i < ids.length; i++) {
+ rawTrades[ids[i]]['id'] = ids[i];
+ }
+ const trades = this.parseTrades (rawTrades, undefined, since, limit);
+ const tradesFilteredBySymbol = this.filterBySymbol (trades, symbol);
+ result = this.arrayConcat (result, tradesFilteredBySymbol);
+ }
+ return result;
+ }
+
async fetchOrdersByIds (ids, symbol = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.privatePostQueryOrders (this.extend ({
@@ -66835,11 +68874,11 @@ module.exports = class kraken extends Exchange {
}
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
// https://www.kraken.com/en-us/help/api#deposit-status
if (code === undefined) {
throw new ArgumentsRequired (this.id + ' fetchDeposits requires a currency code argument');
}
+ await this.loadMarkets ();
const currency = this.currency (code);
const request = {
'asset': currency['id'],
@@ -66862,11 +68901,11 @@ module.exports = class kraken extends Exchange {
}
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
// https://www.kraken.com/en-us/help/api#withdraw-status
if (code === undefined) {
throw new ArgumentsRequired (this.id + ' fetchWithdrawals requires a currency code argument');
}
+ await this.loadMarkets ();
const currency = this.currency (code);
const request = {
'asset': currency['id'],
@@ -66915,7 +68954,7 @@ module.exports = class kraken extends Exchange {
}
method = this.options['depositMethods'][code][0]['method'];
} else {
- throw new ExchangeError (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
}
}
const request = {
@@ -67028,7 +69067,7 @@ module.exports = class kraken extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],102:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],101:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -67100,7 +69139,9 @@ module.exports = class kucoin extends Exchange {
'public': {
'get': [
'timestamp',
+ 'status',
'symbols',
+ 'markets',
'market/allTickers',
'market/orderbook/level{level}',
'market/orderbook/level2',
@@ -67112,6 +69153,9 @@ module.exports = class kucoin extends Exchange {
'market/stats',
'currencies',
'currencies/{currency}',
+ 'prices',
+ 'mark-price/{symbol}/current',
+ 'margin/config',
],
'post': [
'bullet-public',
@@ -67123,6 +69167,10 @@ module.exports = class kucoin extends Exchange {
'accounts/{accountId}',
'accounts/{accountId}/ledgers',
'accounts/{accountId}/holds',
+ 'accounts/transferable',
+ 'sub/user',
+ 'sub-accounts',
+ 'sub-accounts/{subUserId}',
'deposit-addresses',
'deposits',
'hist-deposits',
@@ -67132,8 +69180,20 @@ module.exports = class kucoin extends Exchange {
'withdrawals/quotas',
'orders',
'orders/{orderId}',
+ 'limit/orders',
'fills',
'limit/fills',
+ 'margin/account',
+ 'margin/borrow',
+ 'margin/borrow/outstanding',
+ 'margin/borrow/borrow/repaid',
+ 'margin/lend/active',
+ 'margin/lend/done',
+ 'margin/lend/trade/unsettled',
+ 'margin/lend/trade/settled',
+ 'margin/lend/assets',
+ 'margin/market',
+ 'margin/margin/trade/last',
],
'post': [
'accounts',
@@ -67142,11 +69202,19 @@ module.exports = class kucoin extends Exchange {
'deposit-addresses',
'withdrawals',
'orders',
+ 'orders/multi',
+ 'margin/borrow',
+ 'margin/repay/all',
+ 'margin/repay/single',
+ 'margin/lend',
+ 'margin/toggle-auto-lend',
'bullet-private',
],
'delete': [
'withdrawals/{withdrawalId}',
+ 'orders',
'orders/{orderId}',
+ 'margin/lend/{orderId}',
],
},
},
@@ -67278,18 +69346,20 @@ module.exports = class kucoin extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetSymbols (params);
//
- // { quoteCurrency: 'BTC',
- // symbol: 'KCS-BTC',
- // quoteMaxSize: '9999999',
- // quoteIncrement: '0.000001',
- // baseMinSize: '0.01',
- // quoteMinSize: '0.00001',
- // enableTrading: true,
- // priceIncrement: '0.00000001',
- // name: 'KCS-BTC',
- // baseIncrement: '0.01',
- // baseMaxSize: '9999999',
- // baseCurrency: 'KCS' }
+ // {
+ // quoteCurrency: 'BTC',
+ // symbol: 'KCS-BTC',
+ // quoteMaxSize: '9999999',
+ // quoteIncrement: '0.000001',
+ // baseMinSize: '0.01',
+ // quoteMinSize: '0.00001',
+ // enableTrading: true,
+ // priceIncrement: '0.00000001',
+ // name: 'KCS-BTC',
+ // baseIncrement: '0.01',
+ // baseMaxSize: '9999999',
+ // baseCurrency: 'KCS'
+ // }
//
const data = response['data'];
const result = [];
@@ -67375,20 +69445,27 @@ module.exports = class kucoin extends Exchange {
async fetchAccounts (params = {}) {
const response = await this.privateGetAccounts (params);
//
- // { code: "200000",
- // data: [ { balance: "0.00009788",
+ // {
+ // code: "200000",
+ // data: [
+ // {
+ // balance: "0.00009788",
// available: "0.00009788",
- // holds: "0",
- // currency: "BTC",
- // id: "5c6a4fd399a1d81c4f9cc4d0",
- // type: "trade" },
- // ...,
- // { balance: "0.00000001",
+ // holds: "0",
+ // currency: "BTC",
+ // id: "5c6a4fd399a1d81c4f9cc4d0",
+ // type: "trade"
+ // },
+ // {
+ // balance: "0.00000001",
// available: "0.00000001",
- // holds: "0",
- // currency: "ETH",
- // id: "5c6a49ec99a1d819392e8e9f",
- // type: "trade" } ] }
+ // holds: "0",
+ // currency: "ETH",
+ // id: "5c6a49ec99a1d819392e8e9f",
+ // type: "trade"
+ // }
+ // ]
+ // }
//
const data = this.safeValue (response, 'data');
const result = [];
@@ -67672,30 +69749,72 @@ module.exports = class kucoin extends Exchange {
};
}
+ async fetchL3OrderBook (symbol, limit = undefined, params = {}) {
+ return await this.fetchOrderBook (symbol, limit, { 'level': 3 });
+ }
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
- let level = '2';
- if (limit !== undefined) {
- if ((limit !== 20) && (limit !== 100)) {
- throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
+ const level = this.safeInteger (params, 'level', 2);
+ let levelLimit = level.toString ();
+ if (level === '2') {
+ if (limit !== undefined) {
+ if ((limit !== 20) && (limit !== 100)) {
+ throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
+ }
+ levelLimit += '_' + limit.toString ();
}
- level += '_' + limit.toString ();
}
await this.loadMarkets ();
const marketId = this.marketId (symbol);
- const request = this.extend ({ 'symbol': marketId, 'level': level }, params);
- const response = await this.publicGetMarketOrderbookLevelLevel (request);
+ const request = { 'symbol': marketId, 'level': levelLimit };
+ const response = await this.publicGetMarketOrderbookLevelLevel (this.extend (request, params));
//
- // { sequence: '1547731421688',
- // asks: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ],
- // bids: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ], }
+ // 'market/orderbook/level2'
+ // 'market/orderbook/level2_20'
+ // 'market/orderbook/level2_100'
//
- const data = response['data'];
+ // {
+ // "code":"200000",
+ // "data":{
+ // "sequence":"1583235112106",
+ // "asks":[
+ // // ...
+ // ["0.023197","12.5067468"],
+ // ["0.023194","1.8"],
+ // ["0.023191","8.1069672"]
+ // ],
+ // "bids":[
+ // ["0.02319","1.6000002"],
+ // ["0.023189","2.2842325"],
+ // ],
+ // "time":1586584067274
+ // }
+ // }
+ //
+ // 'market/orderbook/level3'
+ //
+ // {
+ // "code":"200000",
+ // "data":{
+ // "sequence":"1583731857120",
+ // "asks":[
+ // // id, price, size, timestamp in nanoseconds
+ // ["5e915f8acd26670009675300","6925.7","0.2","1586585482194286069"],
+ // ["5e915f8ace35a200090bba48","6925.7","0.001","1586585482229569826"],
+ // ["5e915f8a8857740009ca7d33","6926","0.00001819","1586585482149148621"],
+ // ],
+ // "bids":[
+ // ["5e915f8acca406000ac88194","6925.6","0.05","1586585482384384842"],
+ // ["5e915f93cd26670009676075","6925.6","0.08","1586585491334914600"],
+ // ["5e915f906aa6e200099b49f6","6925.4","0.2","1586585488941126340"],
+ // ],
+ // "time":1586585492487
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
const timestamp = this.safeInteger (data, 'time');
- // level can be a string such as 2_20 or 2_100
- const levelString = this.safeString (request, 'level');
- const levelParts = levelString.split ('_');
- const offset = parseInt (levelParts[0]);
- const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', offset - 2, offset - 1);
+ const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', level - 2, level - 1);
orderbook['nonce'] = this.safeInteger (data, 'sequence');
return orderbook;
}
@@ -67746,7 +69865,7 @@ module.exports = class kucoin extends Exchange {
'datetime': this.iso8601 (timestamp),
'fee': undefined,
'status': 'open',
- 'clientOid': clientOid,
+ 'clientOrderId': clientOid,
'info': data,
};
if (!this.safeValue (params, 'quoteAmount')) {
@@ -68729,7 +70848,7 @@ module.exports = class kucoin extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],103:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],102:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -68750,11 +70869,12 @@ module.exports = class kuna extends acx {
'has': {
'CORS': false,
'fetchTickers': true,
- 'fetchOHLCV': false,
+ 'fetchOHLCV': 'emulated',
'fetchOpenOrders': true,
'fetchMyTrades': true,
'withdraw': false,
},
+ 'timeframes': undefined,
'urls': {
'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4',
'logo': 'https://user-images.githubusercontent.com/1294454/31697638-912824fa-b3c1-11e7-8c36-cf9606eb94ac.jpg',
@@ -68923,15 +71043,34 @@ module.exports = class kuna extends acx {
const response = await this.privateGetTradesMy (this.extend (request, params));
return this.parseTrades (response, market, since, limit);
}
+
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limits = undefined, params = {}) {
+ await this.loadMarkets ();
+ const trades = await this.fetchTrades (symbol, since, limits, params);
+ const ohlcvc = this.buildOHLCVC (trades, timeframe, since, limits);
+ const result = [];
+ for (let i = 0; i < ohlcvc.length; i++) {
+ const ohlcv = ohlcvc[i];
+ result.push ([
+ ohlcv[0],
+ ohlcv[1],
+ ohlcv[2],
+ ohlcv[3],
+ ohlcv[4],
+ ohlcv[5],
+ ]);
+ }
+ return result;
+ }
};
-},{"./acx.js":4,"./base/errors":10}],104:[function(require,module,exports){
+},{"./acx.js":4,"./base/errors":9}],103:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -68942,6 +71081,7 @@ module.exports = class lakebtc extends Exchange {
'name': 'LakeBTC',
'countries': [ 'US' ],
'version': 'api_v2',
+ 'rateLimit': 1000,
'has': {
'CORS': true,
'createMarketOrder': false,
@@ -68983,6 +71123,14 @@ module.exports = class lakebtc extends Exchange {
'taker': 0.2 / 100,
},
},
+ 'exceptions': {
+ 'broad': {
+ 'Signature': AuthenticationError,
+ 'invalid symbol': BadSymbol,
+ 'Volume doit': InvalidOrder,
+ 'insufficient_balance': InsufficientFunds,
+ },
+ },
});
}
@@ -69176,45 +71324,73 @@ module.exports = class lakebtc extends Exchange {
} else {
this.checkRequiredCredentials ();
const nonce = this.nonce ();
+ const nonceAsString = nonce.toString ();
+ const requestId = this.seconds ();
let queryParams = '';
if ('params' in params) {
const paramsList = params['params'];
- queryParams = paramsList.join (',');
+ const stringParams = [];
+ for (let i = 0; i < paramsList.length; i++) {
+ let param = paramsList[i];
+ if (typeof paramsList !== 'string') {
+ param = param.toString ();
+ }
+ stringParams.push (param);
+ }
+ queryParams = stringParams.join (',');
+ body = {
+ 'method': path,
+ 'params': params['params'],
+ 'id': requestId,
+ };
+ } else {
+ body = {
+ 'method': path,
+ 'params': '',
+ 'id': requestId,
+ };
}
- const query = this.urlencode ({
- 'tonce': nonce,
- 'accesskey': this.apiKey,
- 'requestmethod': method.toLowerCase (),
- 'id': nonce,
- 'method': path,
- 'params': queryParams,
- });
- body = this.json ({
- 'method': path,
- 'params': queryParams,
- 'id': nonce,
- });
+ body = this.json (body);
+ let query = [
+ 'tonce=' + nonceAsString,
+ 'accesskey=' + this.apiKey,
+ 'requestmethod=' + method.toLowerCase (),
+ 'id=' + requestId.toString (),
+ 'method=' + path,
+ 'params=' + queryParams,
+ ];
+ query = query.join ('&');
const signature = this.hmac (this.encode (query), this.encode (this.secret), 'sha1');
const auth = this.encode (this.apiKey + ':' + signature);
+ const signature64 = this.decode (this.stringToBase64 (auth));
headers = {
- 'Json-Rpc-Tonce': nonce.toString (),
- 'Authorization': 'Basic ' + this.decode (this.stringToBase64 (auth)),
+ 'Json-Rpc-Tonce': nonceAsString,
+ 'Authorization': 'Basic ' + signature64,
'Content-Type': 'application/json',
};
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
- async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- const response = await this.fetch2 (path, api, method, params, headers, body);
- if ('error' in response) {
- throw new ExchangeError (this.id + ' ' + this.json (response));
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
+ if (response === undefined) {
+ return; // fallback to the default error handler
+ }
+ //
+ // {"error":"Failed to submit order: invalid symbol"}
+ // {"error":"Failed to submit order: La validation a échoué : Volume doit être supérieur ou égal à 1.0"}
+ // {"error":"Failed to submit order: insufficient_balance"}
+ //
+ const feedback = this.id + ' ' + body;
+ const error = this.safeString (response, 'error');
+ if (error !== undefined) {
+ this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
+ throw new ExchangeError (feedback); // unknown message
}
- return response;
}
};
-},{"./base/Exchange":8,"./base/errors":10}],105:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],104:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -70115,13 +72291,13 @@ module.exports = class latoken extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],106:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],105:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder } = require ('./base/errors');
+const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -70457,10 +72633,10 @@ module.exports = class lbank extends Exchange {
await this.loadMarkets ();
const market = this.market (symbol);
if (since === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a `since` argument');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `since` argument');
}
if (limit === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a `limit` argument');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `limit` argument');
}
const request = {
'symbol': market['id'],
@@ -70788,7 +72964,7 @@ module.exports = class lbank extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],107:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],106:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -70968,7 +73144,7 @@ module.exports = class liquid extends Exchange {
}
async fetchMarkets (params = {}) {
- const markets = await this.publicGetProducts ();
+ const spot = await this.publicGetProducts (params);
//
// [
// {
@@ -70999,20 +73175,69 @@ module.exports = class liquid extends Exchange {
// },
// ]
//
+ const perpetual = await this.publicGetProducts ({ 'perpetual': '1' });
+ //
+ // [
+ // {
+ // "id": "603",
+ // "product_type": "Perpetual",
+ // "code": "CASH",
+ // "name": null,
+ // "market_ask": "1143900",
+ // "market_bid": "1143250",
+ // "currency": "JPY",
+ // "currency_pair_code": "P-BTCJPY",
+ // "pusher_channel": "product_cash_p-btcjpy_603",
+ // "taker_fee": "0.0",
+ // "maker_fee": "0.0",
+ // "low_market_bid": "1124450.0",
+ // "high_market_ask": "1151750.0",
+ // "volume_24h": "0.1756",
+ // "last_price_24h": "1129850.0",
+ // "last_traded_price": "1144700.0",
+ // "last_traded_quantity": "0.014",
+ // "quoted_currency": "JPY",
+ // "base_currency": "P-BTC",
+ // "tick_size": "50.0",
+ // "perpetual_enabled": true,
+ // "index_price": "1142636.03935",
+ // "mark_price": "1143522.18417",
+ // "funding_rate": "0.00033",
+ // "fair_price": "1143609.31009",
+ // "timestamp": "1581558659.195353100",
+ // },
+ // ]
+ //
const currencies = await this.fetchCurrencies ();
const currenciesByCode = this.indexBy (currencies, 'code');
const result = [];
+ const markets = this.arrayConcat (spot, perpetual);
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
- const id = market['id'].toString ();
- const baseId = market['base_currency'];
- const quoteId = market['quoted_currency'];
+ const id = this.safeString (market, 'id');
+ const baseId = this.safeString (market, 'base_currency');
+ const quoteId = this.safeString (market, 'quoted_currency');
+ const productType = this.safeString (market, 'product_type');
+ let type = 'spot';
+ let spot = true;
+ let swap = false;
+ if (productType === 'Perpetual') {
+ spot = false;
+ swap = true;
+ type = 'swap';
+ }
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
- const symbol = base + '/' + quote;
+ let symbol = undefined;
+ if (swap) {
+ symbol = this.safeString (market, 'currency_pair_code');
+ } else {
+ symbol = base + '/' + quote;
+ }
const maker = this.safeFloat (market, 'maker_fee');
const taker = this.safeFloat (market, 'taker_fee');
- const active = !market['disabled'];
+ const disabled = this.safeValue (market, 'disabled', false);
+ const active = !disabled;
const baseCurrency = this.safeValue (currenciesByCode, base);
const quoteCurrency = this.safeValue (currenciesByCode, quote);
const precision = {
@@ -71056,6 +73281,9 @@ module.exports = class liquid extends Exchange {
'quote': quote,
'baseId': baseId,
'quoteId': quoteId,
+ 'type': type,
+ 'spot': spot,
+ 'swap': swap,
'maker': maker,
'taker': taker,
'limits': limits,
@@ -71184,7 +73412,7 @@ module.exports = class liquid extends Exchange {
return this.parseTicker (response, market);
}
- parseTrade (trade, market) {
+ parseTrade (trade, market = undefined) {
// { id: 12345,
// quantity: "6.789",
// price: "98765.4321",
@@ -71211,13 +73439,17 @@ module.exports = class liquid extends Exchange {
}
}
const id = this.safeString (trade, 'id');
+ let symbol = undefined;
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
return {
'info': trade,
'id': id,
'order': orderId,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
- 'symbol': market['symbol'],
+ 'symbol': symbol,
'type': undefined,
'side': side,
'takerOrMaker': takerOrMaker,
@@ -71720,7 +73952,7 @@ module.exports = class liquid extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],108:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],107:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -72162,7 +74394,18 @@ module.exports = class livecoin extends Exchange {
}
}
let symbol = undefined;
- if (market !== undefined) {
+ const marketId = this.safeString (trade, 'symbol');
+ 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 ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
}
return {
@@ -72183,16 +74426,17 @@ module.exports = class livecoin extends Exchange {
}
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- if (symbol === undefined) {
- throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
- }
await this.loadMarkets ();
- const market = this.market (symbol);
const request = {
- 'currencyPair': market['id'],
- // orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
+ // 'currencyPair': market['id'],
+ // 'orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
// 'offset': 0, // page offset, position of the first item on the page
};
+ let market = undefined;
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['currencyPair'] = market['id'];
+ }
if (limit !== undefined) {
request['limit'] = limit;
}
@@ -72638,7 +74882,7 @@ module.exports = class livecoin extends Exchange {
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],109:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],108:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -73117,7 +75361,7 @@ module.exports = class luno extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],110:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],109:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -73598,7 +75842,7 @@ module.exports = class lykke extends Exchange {
}
};
-},{"./base/Exchange":8}],111:[function(require,module,exports){
+},{"./base/Exchange":7}],110:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -74000,17 +76244,17 @@ module.exports = class mercado extends Exchange {
if (code === 'BRL') {
const account_ref = ('account_ref' in params);
if (!account_ref) {
- throw new ExchangeError (this.id + ' requires account_ref parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires account_ref parameter to withdraw ' + code);
}
} else if (code !== 'LTC') {
const tx_fee = ('tx_fee' in params);
if (!tx_fee) {
- throw new ExchangeError (this.id + ' requires tx_fee parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires tx_fee parameter to withdraw ' + code);
}
if (code === 'XRP') {
if (tag === undefined) {
if (!('destination_tag' in params)) {
- throw new ExchangeError (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
}
} else {
request['destination_tag'] = tag;
@@ -74107,7 +76351,7 @@ module.exports = class mercado extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],112:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],111:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -74332,7 +76576,7 @@ module.exports = class mixcoins extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],113:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],112:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -75045,7 +77289,7 @@ module.exports = class oceanex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],114:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],113:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -75082,13 +77326,13 @@ module.exports = class okcoin extends okex {
}
};
-},{"./okex.js":115}],115:[function(require,module,exports){
+},{"./okex.js":114}],114:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
// ---------------------------------------------------------------------------
@@ -75146,6 +77390,9 @@ module.exports = class okex extends Exchange {
'doc': 'https://www.okex.com/docs/en/',
'fees': 'https://www.okex.com/pages/products/fees.html',
'referral': 'https://www.okex.com/join/1888677',
+ 'test': {
+ 'rest': 'https://testnet.okex.com',
+ },
},
'api': {
'general': {
@@ -75433,8 +77680,9 @@ module.exports = class okex extends Exchange {
'30034': ExchangeError, // { "code": 30034, "message": "exchange ID does not exist" }
'30035': ExchangeError, // { "code": 30035, "message": "trading is not supported in this website" }
'30036': ExchangeError, // { "code": 30036, "message": "no relevant data" }
- '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
'30037': ExchangeNotAvailable, // { "code": 30037, "message": "endpoint is offline or unavailable" }
+ // '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
+ '30038': OnMaintenance, // {"client_oid":"","code":"30038","error_code":"30038","error_message":"Matching engine is being upgraded. Please try in about 1 minute.","message":"Matching engine is being upgraded. Please try in about 1 minute.","order_id":"-1","result":false}
// futures
'32001': AccountSuspended, // { "code": 32001, "message": "futures account suspended" }
'32002': PermissionDenied, // { "code": 32002, "message": "futures account does not exist" }
@@ -75877,14 +78125,6 @@ module.exports = class okex extends Exchange {
'price': this.safeFloat (market, 'tick_size'),
};
const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size');
- let minPrice = this.safeFloat (market, 'tick_size');
- if (precision['price'] !== undefined) {
- minPrice = Math.pow (10, -precision['price']);
- }
- let minCost = undefined;
- if (minAmount !== undefined && minPrice !== undefined) {
- minCost = minAmount * minPrice;
- }
const active = true;
const fees = this.safeValue2 (this.fees, marketType, 'trading', {});
return this.extend (fees, {
@@ -75908,11 +78148,11 @@ module.exports = class okex extends Exchange {
'max': undefined,
},
'price': {
- 'min': minPrice,
+ 'min': precision['price'],
'max': undefined,
},
'cost': {
- 'min': minCost,
+ 'min': precision['price'],
'max': undefined,
},
},
@@ -76445,8 +78685,18 @@ module.exports = class okex extends Exchange {
'instrument_id': market['id'],
'granularity': this.timeframes[timeframe],
};
+ const duration = this.parseTimeframe (timeframe);
if (since !== undefined) {
+ if (limit !== undefined) {
+ request['end'] = this.iso8601 (this.sum (since, limit * duration * 1000));
+ }
request['start'] = this.iso8601 (since);
+ } else {
+ const now = this.milliseconds ();
+ if (limit !== undefined) {
+ request['start'] = this.iso8601 (now - limit * duration * 1000);
+ request['end'] = this.iso8601 (now);
+ }
}
const response = await this[method] (this.extend (request, params));
//
@@ -76926,28 +79176,7 @@ module.exports = class okex extends Exchange {
// "result":true
// }
//
- const timestamp = this.milliseconds ();
- const id = this.safeString (response, 'order_id');
- return {
- 'info': response,
- 'id': id,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'lastTradeTimestamp': undefined,
- 'status': undefined,
- 'symbol': symbol,
- 'type': type,
- 'side': side,
- 'price': price,
- 'amount': amount,
- 'filled': undefined,
- 'remaining': undefined,
- 'cost': undefined,
- 'trades': undefined,
- 'fee': undefined,
- 'clientOrderId': undefined,
- 'average': undefined,
- };
+ return this.parseOrder (response, market);
}
async cancelOrder (id, symbol = undefined, params = {}) {
@@ -77387,9 +79616,11 @@ module.exports = class okex extends Exchange {
}
parseDepositAddresses (addresses) {
- const result = [];
+ const result = {};
for (let i = 0; i < addresses.length; i++) {
- result.push (this.parseDepositAddress (addresses[i]));
+ const address = this.parseDepositAddress (addresses[i]);
+ const code = address['currency'];
+ result[code] = address;
}
return result;
}
@@ -77435,11 +79666,11 @@ module.exports = class okex extends Exchange {
// ]
//
const addresses = this.parseDepositAddresses (response);
- const numAddresses = addresses.length;
- if (numAddresses < 1) {
+ const address = this.safeValue (addresses, code);
+ if (address === undefined) {
throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first');
}
- return addresses[0];
+ return address;
}
async withdraw (code, amount, address, tag = undefined, params = {}) {
@@ -77451,7 +79682,7 @@ module.exports = class okex extends Exchange {
}
const fee = this.safeString (params, 'fee');
if (fee === undefined) {
- throw new ExchangeError (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
+ throw new ArgumentsRequired (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
}
const request = {
'currency': currency['id'],
@@ -78293,7 +80524,7 @@ module.exports = class okex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],116:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],115:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -78323,6 +80554,7 @@ module.exports = class paymium extends Exchange {
'https://github.com/Paymium/api-documentation',
'https://www.paymium.com/page/developers',
],
+ 'referral': 'https://www.paymium.com/page/sign-up?referral=eDAzPoRQFMvaAB8sf-qj',
},
'api': {
'public': {
@@ -78337,12 +80569,12 @@ module.exports = class paymium extends Exchange {
},
'private': {
'get': [
- 'merchant/get_payment/{UUID}',
+ 'merchant/get_payment/{uuid}',
'user',
'user/addresses',
'user/addresses/{btc_address}',
'user/orders',
- 'user/orders/{UUID}',
+ 'user/orders/{uuid}',
'user/price_alerts',
],
'post': [
@@ -78353,7 +80585,7 @@ module.exports = class paymium extends Exchange {
'merchant/create_payment',
],
'delete': [
- 'user/orders/{UUID}/cancel',
+ 'user/orders/{uuid}/cancel',
'user/price_alerts/{id}',
],
},
@@ -78500,9 +80732,9 @@ module.exports = class paymium extends Exchange {
async cancelOrder (id, symbol = undefined, params = {}) {
const request = {
- 'UUID': id,
+ 'uuid': id,
};
- return await this.privateDeleteUserOrdersUUIDCancel (this.extend (request, params));
+ return await this.privateDeleteUserOrdersUuidCancel (this.extend (request, params));
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
@@ -78516,18 +80748,24 @@ module.exports = class paymium extends Exchange {
this.checkRequiredCredentials ();
const nonce = this.nonce ().toString ();
let auth = nonce + url;
+ headers = {
+ 'Api-Key': this.apiKey,
+ 'Api-Nonce': nonce,
+ };
if (method === 'POST') {
if (Object.keys (query).length) {
body = this.json (query);
auth += body;
+ headers['Content-Type'] = 'application/json';
+ }
+ } else {
+ if (Object.keys (query).length) {
+ const queryString = this.urlencode (query);
+ auth += queryString;
+ url += '?' + queryString;
}
}
- headers = {
- 'Api-Key': this.apiKey,
- 'Api-Signature': this.hmac (this.encode (auth), this.encode (this.secret)),
- 'Api-Nonce': nonce,
- 'Content-Type': 'application/json',
- };
+ headers['Api-Signature'] = this.hmac (this.encode (auth), this.encode (this.secret));
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
@@ -78541,13 +80779,13 @@ module.exports = class paymium extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],117:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],116:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -78714,6 +80952,7 @@ module.exports = class poloniex extends Exchange {
'Permission denied': PermissionDenied,
'Connection timed out. Please try again.': RequestTimeout,
'Internal error. Please try again.': ExchangeNotAvailable,
+ 'Currently in maintenance mode.': OnMaintenance,
'Order not found, or you are not the person who placed it.': OrderNotFound,
'Invalid API key/secret pair.': AuthenticationError,
'Please do not make more than 8 API calls per second.': DDoSProtection,
@@ -79995,7 +82234,7 @@ module.exports = class poloniex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],118:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],117:[function(require,module,exports){
'use strict';
const Exchange = require ('./base/Exchange');
@@ -80760,7 +82999,7 @@ module.exports = class rightbtc extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10,"./base/functions/number":16}],119:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9,"./base/functions/number":15}],118:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -81130,7 +83369,7 @@ module.exports = class southxchange extends Exchange {
}
};
-},{"./base/Exchange":8}],120:[function(require,module,exports){
+},{"./base/Exchange":7}],119:[function(require,module,exports){
(function (module, exports) {
'use strict';
@@ -84658,7 +86897,7 @@ module.exports = class southxchange extends Exchange {
};
})(typeof module === 'undefined' || module, this);
-},{"buffer":179}],121:[function(require,module,exports){
+},{"buffer":178}],120:[function(require,module,exports){
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
@@ -90647,7 +92886,7 @@ module.exports = class southxchange extends Exchange {
return CryptoJS;
}));
-},{}],122:[function(require,module,exports){
+},{}],121:[function(require,module,exports){
'use strict';
var elliptic = exports;
@@ -90670,7 +92909,7 @@ elliptic.curves = require('./elliptic/curves');
// Protocols
elliptic.ec = require('./elliptic/ec');
-},{"./elliptic/curve":125,"./elliptic/curves":128,"./elliptic/ec":129,"./elliptic/utils":133}],123:[function(require,module,exports){
+},{"./elliptic/curve":124,"./elliptic/curves":127,"./elliptic/ec":128,"./elliptic/utils":132}],122:[function(require,module,exports){
'use strict';
var BN = require('../../../../BN/bn');
@@ -91047,7 +93286,7 @@ BasePoint.prototype.dblp = function dblp(k) {
return r;
};
-},{"../../../../BN/bn":120,"../../elliptic":122}],124:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121}],123:[function(require,module,exports){
'use strict';
var curve = require('../curve');
@@ -91482,7 +93721,7 @@ Point.prototype.eqXToP = function eqXToP(x) {
Point.prototype.toP = Point.prototype.normalize;
Point.prototype.mixedAdd = Point.prototype.add;
-},{"../../../../BN/bn":120,"../../elliptic":122,"../curve":125}],125:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121,"../curve":124}],124:[function(require,module,exports){
'use strict';
var curve = exports;
@@ -91492,7 +93731,7 @@ curve.short = require('./short');
curve.mont = require('./mont');
curve.edwards = require('./edwards');
-},{"./base":123,"./edwards":124,"./mont":126,"./short":127}],126:[function(require,module,exports){
+},{"./base":122,"./edwards":123,"./mont":125,"./short":126}],125:[function(require,module,exports){
'use strict';
var curve = require('../curve');
@@ -91674,7 +93913,7 @@ Point.prototype.getX = function getX() {
return this.x.fromRed();
};
-},{"../../../../BN/bn":120,"../../elliptic":122,"../curve":125}],127:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121,"../curve":124}],126:[function(require,module,exports){
'use strict';
var curve = require('../curve');
@@ -92614,7 +94853,7 @@ JPoint.prototype.isInfinity = function isInfinity() {
return this.z.cmpn(0) === 0;
};
-},{"../../../../BN/bn":120,"../../elliptic":122,"../curve":125}],128:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121,"../curve":124}],127:[function(require,module,exports){
'use strict';
var curves = exports;
@@ -92820,7 +95059,7 @@ defineCurve('secp256k1', {
]
});
-},{"../elliptic":122,"./precomputed/secp256k1":132}],129:[function(require,module,exports){
+},{"../elliptic":121,"./precomputed/secp256k1":131}],128:[function(require,module,exports){
'use strict';
var BN = require('../../../../BN/bn');
@@ -93062,7 +95301,7 @@ EC.prototype.getKeyRecoveryParam = function(e, signature, Q, enc) {
throw new Error('Unable to find valid recovery factor');
};
-},{"../../../../BN/bn":120,"../../elliptic":122,"../../hmac-drbg/hmac-drbg":134,"./key":130,"./signature":131}],130:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121,"../../hmac-drbg/hmac-drbg":133,"./key":129,"./signature":130}],129:[function(require,module,exports){
'use strict';
var BN = require('../../../../BN/bn');
@@ -93183,7 +95422,7 @@ KeyPair.prototype.inspect = function inspect() {
' pub: ' + (this.pub && this.pub.inspect()) + ' >';
};
-},{"../../../../BN/bn":120,"../../elliptic":122}],131:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121}],130:[function(require,module,exports){
'use strict';
var BN = require('../../../../BN/bn');
@@ -93209,7 +95448,7 @@ function Signature(options, enc) {
}
module.exports = Signature;
-},{"../../../../BN/bn":120,"../../elliptic":122}],132:[function(require,module,exports){
+},{"../../../../BN/bn":119,"../../elliptic":121}],131:[function(require,module,exports){
module.exports = {
doubles: {
step: 4,
@@ -93991,7 +96230,7 @@ module.exports = {
}
};
-},{}],133:[function(require,module,exports){
+},{}],132:[function(require,module,exports){
'use strict';
var utils = exports;
@@ -94149,7 +96388,7 @@ function wordArrayToBuffer(wordArray) {
utils.wordArrayToBuffer = wordArrayToBuffer;
-},{"../../../BN/bn":120}],134:[function(require,module,exports){
+},{"../../../BN/bn":119}],133:[function(require,module,exports){
'use strict';
var CryptoJS = require('../../../crypto-js/crypto-js');
@@ -94265,7 +96504,7 @@ HmacDRBG.prototype.generate = function generate(len, enc, add, addEnc) {
return utils.wordArrayToBuffer(res);
};
-},{"../../../../base/functions/encode":13,"../../../crypto-js/crypto-js":121,"../elliptic/utils":133}],135:[function(require,module,exports){
+},{"../../../../base/functions/encode":12,"../../../crypto-js/crypto-js":120,"../elliptic/utils":132}],134:[function(require,module,exports){
'use strict';
var fetch = require('../node-fetch/index');
@@ -94306,7 +96545,7 @@ module.exports = function (context) {
};
};
-},{"../node-fetch/index":136}],136:[function(require,module,exports){
+},{"../node-fetch/index":135}],135:[function(require,module,exports){
(function (global,Buffer){
'use strict';
@@ -95874,7 +98113,7 @@ exports.Response = Response;
exports.FetchError = FetchError;
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"buffer":179,"http":221,"https":184,"stream":220,"url":227,"zlib":178}],137:[function(require,module,exports){
+},{"buffer":178,"http":220,"https":183,"stream":219,"url":226,"zlib":177}],136:[function(require,module,exports){
(function (Buffer){
/*!
* RSA library for Node.js
@@ -96101,7 +98340,7 @@ module.exports = (function () {
})();
}).call(this,require("buffer").Buffer)
-},{"./formats/formats.js":144,"./libs/rsa.js":148,"./schemes/schemes.js":150,"./utils":151,"buffer":179}],138:[function(require,module,exports){
+},{"./formats/formats.js":143,"./libs/rsa.js":147,"./schemes/schemes.js":149,"./utils":150,"buffer":178}],137:[function(require,module,exports){
// Copyright 2011 Mark Cavage All rights reserved.
@@ -96116,7 +98355,7 @@ module.exports = {
};
-},{}],139:[function(require,module,exports){
+},{}],138:[function(require,module,exports){
// Copyright 2011 Mark Cavage All rights reserved.
var errors = require('./errors');
@@ -96139,7 +98378,7 @@ for (var e in errors) {
module.exports[e] = errors[e];
}
-},{"./errors":138,"./reader":140,"./types":141}],140:[function(require,module,exports){
+},{"./errors":137,"./reader":139,"./types":140}],139:[function(require,module,exports){
(function (Buffer){
// Copyright 2011 Mark Cavage All rights reserved.
@@ -96405,7 +98644,7 @@ Reader.prototype._readTag = function (tag) {
module.exports = Reader;
}).call(this,require("buffer").Buffer)
-},{"./errors":138,"./types":141,"assert":174,"buffer":179}],141:[function(require,module,exports){
+},{"./errors":137,"./types":140,"assert":173,"buffer":178}],140:[function(require,module,exports){
// Copyright 2011 Mark Cavage All rights reserved.
@@ -96443,7 +98682,7 @@ module.exports = {
Context: 128
};
-},{}],142:[function(require,module,exports){
+},{}],141:[function(require,module,exports){
// Copyright 2011 Mark Cavage All rights reserved.
// If you have no idea what ASN.1 or BER is, see this:
@@ -96462,7 +98701,7 @@ module.exports = {
BerReader: Ber.Reader,
};
-},{"./ber/index":139}],143:[function(require,module,exports){
+},{"./ber/index":138}],142:[function(require,module,exports){
var _ = require('../utils')._;
var utils = require('../utils');
@@ -96535,7 +98774,7 @@ module.exports = {
}
};
-},{"../utils":151}],144:[function(require,module,exports){
+},{"../utils":150}],143:[function(require,module,exports){
var _ = require('../utils')._;
module.exports = {
@@ -96568,7 +98807,7 @@ module.exports = {
},
};
-},{"../utils":151,"./components":143,"./pkcs1":145,"./pkcs8":146}],145:[function(require,module,exports){
+},{"../utils":150,"./components":142,"./pkcs1":144,"./pkcs8":145}],144:[function(require,module,exports){
(function (Buffer){
var ber = require('../asn1/index').Ber;
var _ = require('../utils')._;
@@ -96720,7 +98959,7 @@ module.exports = {
};
}).call(this,require("buffer").Buffer)
-},{"../asn1/index":142,"../utils":151,"buffer":179}],146:[function(require,module,exports){
+},{"../asn1/index":141,"../utils":150,"buffer":178}],145:[function(require,module,exports){
(function (Buffer){
var ber = require('../asn1/index').Ber;
var _ = require('../utils')._;
@@ -96911,7 +99150,7 @@ module.exports = {
};
}).call(this,require("buffer").Buffer)
-},{"../asn1/index":142,"../utils":151,"buffer":179}],147:[function(require,module,exports){
+},{"../asn1/index":141,"../utils":150,"buffer":178}],146:[function(require,module,exports){
(function (Buffer){
/*
* Basic JavaScript BN library - subset useful for RSA encryption.
@@ -98167,7 +100406,7 @@ BigInteger.prototype.square = bnSquare;
module.exports = BigInteger;
}).call(this,require("buffer").Buffer)
-},{"../utils":151,"buffer":179}],148:[function(require,module,exports){
+},{"../utils":150,"buffer":178}],147:[function(require,module,exports){
/*
* RSA Encryption / Decryption with PKCS1 v2 Padding.
*
@@ -98316,7 +100555,7 @@ module.exports.Key = (function () {
})();
-},{"../schemes/schemes.js":150,"../utils":151,"../utils.js":151,"./jsbn.js":147}],149:[function(require,module,exports){
+},{"../schemes/schemes.js":149,"../utils":150,"../utils.js":150,"./jsbn.js":146}],148:[function(require,module,exports){
(function (Buffer){
/**
* PKCS1 padding and signature scheme
@@ -98496,7 +100735,7 @@ function wordArrayToBuffer(wordArray) {
}
}).call(this,require("buffer").Buffer)
-},{"../../crypto-js/crypto-js":121,"../libs/jsbn":147,"buffer":179,"constants":181}],150:[function(require,module,exports){
+},{"../../crypto-js/crypto-js":120,"../libs/jsbn":146,"buffer":178,"constants":180}],149:[function(require,module,exports){
module.exports = {
pkcs1: require('./pkcs1'),
@@ -98519,7 +100758,7 @@ module.exports = {
}
};
-},{"./pkcs1":149}],151:[function(require,module,exports){
+},{"./pkcs1":148}],150:[function(require,module,exports){
/*
* Utils functions
*
@@ -98619,7 +100858,7 @@ module.exports.trimSurroundingText = function (data, opening, closing) {
return data.substring(trimStartIndex, trimEndIndex);
}
-},{}],152:[function(require,module,exports){
+},{}],151:[function(require,module,exports){
'use strict';
var replace = String.prototype.replace;
@@ -98639,7 +100878,7 @@ module.exports = {
RFC3986: 'RFC3986'
};
-},{}],153:[function(require,module,exports){
+},{}],152:[function(require,module,exports){
'use strict';
var stringify = require('./stringify');
@@ -98652,7 +100891,7 @@ module.exports = {
stringify: stringify
};
-},{"./formats":152,"./parse":154,"./stringify":155}],154:[function(require,module,exports){
+},{"./formats":151,"./parse":153,"./stringify":154}],153:[function(require,module,exports){
'use strict';
var utils = require('./utils');
@@ -98896,7 +101135,7 @@ module.exports = function (str, opts) {
return utils.compact(obj);
};
-},{"./utils":156}],155:[function(require,module,exports){
+},{"./utils":155}],154:[function(require,module,exports){
'use strict';
var utils = require('./utils');
@@ -99167,7 +101406,7 @@ module.exports = function (object, opts) {
return joined.length > 0 ? prefix + joined : '';
};
-},{"./formats":152,"./utils":156}],156:[function(require,module,exports){
+},{"./formats":151,"./utils":155}],155:[function(require,module,exports){
'use strict';
var has = Object.prototype.hasOwnProperty;
@@ -99399,7 +101638,7 @@ module.exports = {
merge: merge
};
-},{}],157:[function(require,module,exports){
+},{}],156:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -101200,7 +103439,7 @@ module.exports = class stex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],158:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],157:[function(require,module,exports){
'use strict';
// ----------------------------------------------------------------------------
@@ -101993,7 +104232,7 @@ module.exports = class stronghold extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],159:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],158:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -102027,7 +104266,7 @@ module.exports = class surbitcoin extends foxbit {
}
};
-},{"./foxbit.js":85}],160:[function(require,module,exports){
+},{"./foxbit.js":84}],159:[function(require,module,exports){
'use strict';
const Exchange = require ('./base/Exchange');
@@ -102210,6 +104449,9 @@ module.exports = class theocean extends Exchange {
}
async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
+ if (since === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument');
+ }
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
@@ -102217,9 +104459,6 @@ module.exports = class theocean extends Exchange {
'quoteTokenAddress': market['quoteId'],
'interval': this.timeframes[timeframe],
};
- if (since === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a since argument');
- }
since = parseInt (since);
request['startTime'] = since;
const response = await this.publicGetCandlesticks (this.extend (request, params));
@@ -102942,7 +105181,7 @@ module.exports = class theocean extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],161:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],160:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -104173,13 +106412,13 @@ module.exports = class therock extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],162:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],161:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');
+const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -104636,7 +106875,7 @@ module.exports = class tidebit extends Exchange {
const currency = this.currency (code);
const id = this.safeString (params, 'id');
if (id === undefined) {
- throw new ExchangeError (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
+ throw new ArgumentsRequired (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
}
const request = {
'id': id,
@@ -104706,7 +106945,7 @@ module.exports = class tidebit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],163:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],162:[function(require,module,exports){
'use strict';
const Exchange = require ('./base/Exchange');
@@ -105569,7 +107808,7 @@ module.exports = class tidex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],164:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],163:[function(require,module,exports){
'use strict';
const Exchange = require ('./base/Exchange');
@@ -105614,6 +107853,7 @@ module.exports = class timex extends Exchange {
'api': 'https://plasma-relay-backend.timex.io',
'www': 'https://timex.io',
'doc': 'https://docs.timex.io',
+ 'referral': 'https://timex.io/?refcode=1x27vNkTbP1uwkCck',
},
'api': {
'custody': {
@@ -106464,7 +108704,21 @@ module.exports = class timex extends Exchange {
// "active": true,
// "withdrawalFee": "50000000000000000",
// "purchaseCommissions": []
- // },
+ // }
+ //
+ // https://github.com/ccxt/ccxt/issues/6878
+ //
+ // {
+ // "symbol":"XRP",
+ // "name":"Ripple",
+ // "address":"0x0dc8882914f3ddeebf4cec6dc20edb99df3def6c",
+ // "decimals":6,
+ // "tradeDecimals":16,
+ // "depositEnabled":true,
+ // "withdrawalEnabled":true,
+ // "transferEnabled":true,
+ // "active":true
+ // }
//
const id = this.safeString (currency, 'symbol');
const code = this.safeCurrencyCode (id);
@@ -106473,20 +108727,22 @@ module.exports = class timex extends Exchange {
const active = this.safeValue (currency, 'active');
// const fee = this.safeFloat (currency, 'withdrawalFee');
const feeString = this.safeString (currency, 'withdrawalFee');
- const feeStringLen = feeString.length;
const tradeDecimals = this.safeInteger (currency, 'tradeDecimals');
let fee = undefined;
- const dotIndex = feeStringLen - tradeDecimals;
- if (dotIndex > 0) {
- const whole = feeString.slice (0, dotIndex);
- const fraction = feeString.slice (-dotIndex);
- fee = parseFloat (whole + '.' + fraction);
- } else {
- let fraction = '.';
- for (let i = 0; i < -dotIndex; i++) {
- fraction += '0';
+ if ((feeString !== undefined) && (tradeDecimals !== undefined)) {
+ const feeStringLen = feeString.length;
+ const dotIndex = feeStringLen - tradeDecimals;
+ if (dotIndex > 0) {
+ const whole = feeString.slice (0, dotIndex);
+ const fraction = feeString.slice (-dotIndex);
+ fee = parseFloat (whole + '.' + fraction);
+ } else {
+ let fraction = '.';
+ for (let i = 0; i < -dotIndex; i++) {
+ fraction += '0';
+ }
+ fee = parseFloat (fraction + feeString);
}
- fee = parseFloat (fraction + feeString);
}
return {
'id': code,
@@ -106677,7 +108933,7 @@ module.exports = class timex extends Exchange {
this.safeFloat (ohlcv, 'high'),
this.safeFloat (ohlcv, 'low'),
this.safeFloat (ohlcv, 'close'),
- this.safeFloat (ohlcv, 'volumeQuote'),
+ this.safeFloat (ohlcv, 'volume'),
];
}
@@ -106808,7 +109064,7 @@ module.exports = class timex extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],165:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],164:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -106835,7 +109091,7 @@ module.exports = class topq extends bw {
}
};
-},{"./bw.js":56}],166:[function(require,module,exports){
+},{"./bw.js":55}],165:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -108162,9 +110418,11 @@ module.exports = class upbit extends Exchange {
}
parseDepositAddresses (addresses) {
- const result = [];
+ const result = {};
for (let i = 0; i < addresses.length; i++) {
- result.push (this.parseDepositAddress (addresses[i]));
+ const address = this.parseDepositAddress (addresses[i]);
+ const code = address['currency'];
+ result[code] = address;
}
return result;
}
@@ -108366,7 +110624,7 @@ module.exports = class upbit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],167:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],166:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -108571,7 +110829,7 @@ module.exports = class vaultoro extends Exchange {
}
};
-},{"./base/Exchange":8}],168:[function(require,module,exports){
+},{"./base/Exchange":7}],167:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -108605,7 +110863,7 @@ module.exports = class vbtc extends foxbit {
}
};
-},{"./foxbit.js":85}],169:[function(require,module,exports){
+},{"./foxbit.js":84}],168:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -109237,7 +111495,7 @@ module.exports = class whitebit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],170:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],169:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -109602,7 +111860,7 @@ module.exports = class xbtce extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],171:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],170:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -109772,11 +112030,12 @@ module.exports = class yobit extends Exchange {
'api key dont have trade permission': AuthenticationError,
'invalid parameter': InvalidOrder,
'invalid order': InvalidOrder,
+ 'The given order has already been cancelled': InvalidOrder,
'Requests too often': DDoSProtection,
'not available': ExchangeNotAvailable,
'data unavailable': ExchangeNotAvailable,
'external service unavailable': ExchangeNotAvailable,
- 'Total transaction amount': ExchangeError, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
+ 'Total transaction amount': InvalidOrder, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
'Insufficient funds': InsufficientFunds,
'invalid key': AuthenticationError,
'invalid nonce': InvalidNonce, // {"success":0,"error":"invalid nonce (has already been used)"}'
@@ -110537,7 +112796,7 @@ module.exports = class yobit extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],172:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],171:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -111049,7 +113308,7 @@ module.exports = class zaif extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],173:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],172:[function(require,module,exports){
'use strict';
// ---------------------------------------------------------------------------
@@ -111505,7 +113764,7 @@ module.exports = class zb extends Exchange {
async fetchOrders (symbol = undefined, since = undefined, limit = 50, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + 'fetchOrders requires a symbol parameter');
+ throw new ArgumentsRequired (this.id + 'fetchOrders requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -111533,7 +113792,7 @@ module.exports = class zb extends Exchange {
async fetchOpenOrders (symbol = undefined, since = undefined, limit = 10, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + 'fetchOpenOrders requires a symbol parameter');
+ throw new ArgumentsRequired (this.id + 'fetchOpenOrders requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -111700,7 +113959,7 @@ module.exports = class zb extends Exchange {
}
};
-},{"./base/Exchange":8,"./base/errors":10}],174:[function(require,module,exports){
+},{"./base/Exchange":7,"./base/errors":9}],173:[function(require,module,exports){
(function (global){
'use strict';
@@ -112194,7 +114453,7 @@ var objectKeys = Object.keys || function (obj) {
};
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"util/":232}],175:[function(require,module,exports){
+},{"util/":231}],174:[function(require,module,exports){
'use strict'
exports.byteLength = byteLength
@@ -112310,9 +114569,9 @@ function fromByteArray (uint8) {
return parts.join('')
}
-},{}],176:[function(require,module,exports){
+},{}],175:[function(require,module,exports){
-},{}],177:[function(require,module,exports){
+},{}],176:[function(require,module,exports){
(function (process,Buffer){
'use strict';
/* eslint camelcase: "off" */
@@ -112724,7 +114983,7 @@ Zlib.prototype._reset = function () {
exports.Zlib = Zlib;
}).call(this,require('_process'),require("buffer").Buffer)
-},{"_process":201,"assert":174,"buffer":179,"pako/lib/zlib/constants":191,"pako/lib/zlib/deflate.js":193,"pako/lib/zlib/inflate.js":195,"pako/lib/zlib/zstream":199}],178:[function(require,module,exports){
+},{"_process":200,"assert":173,"buffer":178,"pako/lib/zlib/constants":190,"pako/lib/zlib/deflate.js":192,"pako/lib/zlib/inflate.js":194,"pako/lib/zlib/zstream":198}],177:[function(require,module,exports){
(function (process){
'use strict';
@@ -113336,7 +115595,7 @@ util.inherits(DeflateRaw, Zlib);
util.inherits(InflateRaw, Zlib);
util.inherits(Unzip, Zlib);
}).call(this,require('_process'))
-},{"./binding":177,"_process":201,"assert":174,"buffer":179,"stream":220,"util":232}],179:[function(require,module,exports){
+},{"./binding":176,"_process":200,"assert":173,"buffer":178,"stream":219,"util":231}],178:[function(require,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
@@ -115052,7 +117311,7 @@ function numberIsNaN (obj) {
return obj !== obj // eslint-disable-line no-self-compare
}
-},{"base64-js":175,"ieee754":185}],180:[function(require,module,exports){
+},{"base64-js":174,"ieee754":184}],179:[function(require,module,exports){
module.exports = {
"100": "Continue",
"101": "Switching Protocols",
@@ -115118,7 +117377,7 @@ module.exports = {
"511": "Network Authentication Required"
}
-},{}],181:[function(require,module,exports){
+},{}],180:[function(require,module,exports){
module.exports={
"O_RDONLY": 0,
"O_WRONLY": 1,
@@ -115329,7 +117588,7 @@ module.exports={
"UV_UDP_REUSEADDR": 4
}
-},{}],182:[function(require,module,exports){
+},{}],181:[function(require,module,exports){
(function (Buffer){
// Copyright Joyent, Inc. and other Node contributors.
//
@@ -115440,7 +117699,7 @@ function objectToString(o) {
}
}).call(this,{"isBuffer":require("../../is-buffer/index.js")})
-},{"../../is-buffer/index.js":187}],183:[function(require,module,exports){
+},{"../../is-buffer/index.js":186}],182:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -115744,7 +118003,7 @@ function isUndefined(arg) {
return arg === void 0;
}
-},{}],184:[function(require,module,exports){
+},{}],183:[function(require,module,exports){
var http = require('http')
var url = require('url')
@@ -115777,7 +118036,7 @@ function validateParams (params) {
return params
}
-},{"http":221,"url":227}],185:[function(require,module,exports){
+},{"http":220,"url":226}],184:[function(require,module,exports){
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
var e, m
var eLen = nBytes * 8 - mLen - 1
@@ -115863,7 +118122,7 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) {
buffer[offset + i - d] |= s * 128
}
-},{}],186:[function(require,module,exports){
+},{}],185:[function(require,module,exports){
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
@@ -115888,7 +118147,7 @@ if (typeof Object.create === 'function') {
}
}
-},{}],187:[function(require,module,exports){
+},{}],186:[function(require,module,exports){
/*!
* Determine if an object is a Buffer
*
@@ -115911,14 +118170,14 @@ function isSlowBuffer (obj) {
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
}
-},{}],188:[function(require,module,exports){
+},{}],187:[function(require,module,exports){
var toString = {}.toString;
module.exports = Array.isArray || function (arr) {
return toString.call(arr) == '[object Array]';
};
-},{}],189:[function(require,module,exports){
+},{}],188:[function(require,module,exports){
'use strict';
@@ -116025,7 +118284,7 @@ exports.setTyped = function (on) {
exports.setTyped(TYPED_OK);
-},{}],190:[function(require,module,exports){
+},{}],189:[function(require,module,exports){
'use strict';
// Note: adler32 takes 12% for level 0 and 2% for level 6.
@@ -116078,7 +118337,7 @@ function adler32(adler, buf, len, pos) {
module.exports = adler32;
-},{}],191:[function(require,module,exports){
+},{}],190:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -116148,7 +118407,7 @@ module.exports = {
//Z_NULL: null // Use -1 or null inline, depending on var type
};
-},{}],192:[function(require,module,exports){
+},{}],191:[function(require,module,exports){
'use strict';
// Note: we can't get significant speed boost here.
@@ -116209,7 +118468,7 @@ function crc32(crc, buf, len, pos) {
module.exports = crc32;
-},{}],193:[function(require,module,exports){
+},{}],192:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -118085,7 +120344,7 @@ exports.deflatePrime = deflatePrime;
exports.deflateTune = deflateTune;
*/
-},{"../utils/common":189,"./adler32":190,"./crc32":192,"./messages":197,"./trees":198}],194:[function(require,module,exports){
+},{"../utils/common":188,"./adler32":189,"./crc32":191,"./messages":196,"./trees":197}],193:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -118432,7 +120691,7 @@ module.exports = function inflate_fast(strm, start) {
return;
};
-},{}],195:[function(require,module,exports){
+},{}],194:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -119990,7 +122249,7 @@ exports.inflateSyncPoint = inflateSyncPoint;
exports.inflateUndermine = inflateUndermine;
*/
-},{"../utils/common":189,"./adler32":190,"./crc32":192,"./inffast":194,"./inftrees":196}],196:[function(require,module,exports){
+},{"../utils/common":188,"./adler32":189,"./crc32":191,"./inffast":193,"./inftrees":195}],195:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -120335,7 +122594,7 @@ module.exports = function inflate_table(type, lens, lens_index, codes, table, ta
return 0;
};
-},{"../utils/common":189}],197:[function(require,module,exports){
+},{"../utils/common":188}],196:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -120369,7 +122628,7 @@ module.exports = {
'-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */
};
-},{}],198:[function(require,module,exports){
+},{}],197:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -121591,7 +123850,7 @@ exports._tr_flush_block = _tr_flush_block;
exports._tr_tally = _tr_tally;
exports._tr_align = _tr_align;
-},{"../utils/common":189}],199:[function(require,module,exports){
+},{"../utils/common":188}],198:[function(require,module,exports){
'use strict';
// (C) 1995-2013 Jean-loup Gailly and Mark Adler
@@ -121640,7 +123899,7 @@ function ZStream() {
module.exports = ZStream;
-},{}],200:[function(require,module,exports){
+},{}],199:[function(require,module,exports){
(function (process){
'use strict';
@@ -121687,7 +123946,7 @@ function nextTick(fn, arg1, arg2, arg3) {
}
}).call(this,require('_process'))
-},{"_process":201}],201:[function(require,module,exports){
+},{"_process":200}],200:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
@@ -121873,7 +124132,7 @@ process.chdir = function (dir) {
};
process.umask = function() { return 0; };
-},{}],202:[function(require,module,exports){
+},{}],201:[function(require,module,exports){
(function (global){
/*! https://mths.be/punycode v1.4.1 by @mathias */
;(function(root) {
@@ -122410,7 +124669,7 @@ process.umask = function() { return 0; };
}(this));
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],203:[function(require,module,exports){
+},{}],202:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -122496,7 +124755,7 @@ var isArray = Array.isArray || function (xs) {
return Object.prototype.toString.call(xs) === '[object Array]';
};
-},{}],204:[function(require,module,exports){
+},{}],203:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -122583,16 +124842,16 @@ var objectKeys = Object.keys || function (obj) {
return res;
};
-},{}],205:[function(require,module,exports){
+},{}],204:[function(require,module,exports){
'use strict';
exports.decode = exports.parse = require('./decode');
exports.encode = exports.stringify = require('./encode');
-},{"./decode":203,"./encode":204}],206:[function(require,module,exports){
+},{"./decode":202,"./encode":203}],205:[function(require,module,exports){
module.exports = require('./lib/_stream_duplex.js');
-},{"./lib/_stream_duplex.js":207}],207:[function(require,module,exports){
+},{"./lib/_stream_duplex.js":206}],206:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -122717,7 +124976,7 @@ function forEach(xs, f) {
f(xs[i], i);
}
}
-},{"./_stream_readable":209,"./_stream_writable":211,"core-util-is":182,"inherits":186,"process-nextick-args":200}],208:[function(require,module,exports){
+},{"./_stream_readable":208,"./_stream_writable":210,"core-util-is":181,"inherits":185,"process-nextick-args":199}],207:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -122765,7 +125024,7 @@ function PassThrough(options) {
PassThrough.prototype._transform = function (chunk, encoding, cb) {
cb(null, chunk);
};
-},{"./_stream_transform":210,"core-util-is":182,"inherits":186}],209:[function(require,module,exports){
+},{"./_stream_transform":209,"core-util-is":181,"inherits":185}],208:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
@@ -123775,7 +126034,7 @@ function indexOf(xs, x) {
return -1;
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./_stream_duplex":207,"./internal/streams/BufferList":212,"./internal/streams/destroy":213,"./internal/streams/stream":214,"_process":201,"core-util-is":182,"events":183,"inherits":186,"isarray":188,"process-nextick-args":200,"safe-buffer":219,"string_decoder/":225,"util":176}],210:[function(require,module,exports){
+},{"./_stream_duplex":206,"./internal/streams/BufferList":211,"./internal/streams/destroy":212,"./internal/streams/stream":213,"_process":200,"core-util-is":181,"events":182,"inherits":185,"isarray":187,"process-nextick-args":199,"safe-buffer":218,"string_decoder/":224,"util":175}],209:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -123990,7 +126249,7 @@ function done(stream, er, data) {
return stream.push(null);
}
-},{"./_stream_duplex":207,"core-util-is":182,"inherits":186}],211:[function(require,module,exports){
+},{"./_stream_duplex":206,"core-util-is":181,"inherits":185}],210:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
@@ -124657,7 +126916,7 @@ Writable.prototype._destroy = function (err, cb) {
cb(err);
};
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./_stream_duplex":207,"./internal/streams/destroy":213,"./internal/streams/stream":214,"_process":201,"core-util-is":182,"inherits":186,"process-nextick-args":200,"safe-buffer":219,"util-deprecate":229}],212:[function(require,module,exports){
+},{"./_stream_duplex":206,"./internal/streams/destroy":212,"./internal/streams/stream":213,"_process":200,"core-util-is":181,"inherits":185,"process-nextick-args":199,"safe-buffer":218,"util-deprecate":228}],211:[function(require,module,exports){
'use strict';
/**/
@@ -124732,7 +126991,7 @@ module.exports = function () {
return BufferList;
}();
-},{"safe-buffer":219}],213:[function(require,module,exports){
+},{"safe-buffer":218}],212:[function(require,module,exports){
'use strict';
/**/
@@ -124805,13 +127064,13 @@ module.exports = {
destroy: destroy,
undestroy: undestroy
};
-},{"process-nextick-args":200}],214:[function(require,module,exports){
+},{"process-nextick-args":199}],213:[function(require,module,exports){
module.exports = require('events').EventEmitter;
-},{"events":183}],215:[function(require,module,exports){
+},{"events":182}],214:[function(require,module,exports){
module.exports = require('./readable').PassThrough
-},{"./readable":216}],216:[function(require,module,exports){
+},{"./readable":215}],215:[function(require,module,exports){
exports = module.exports = require('./lib/_stream_readable.js');
exports.Stream = exports;
exports.Readable = exports;
@@ -124820,13 +127079,13 @@ exports.Duplex = require('./lib/_stream_duplex.js');
exports.Transform = require('./lib/_stream_transform.js');
exports.PassThrough = require('./lib/_stream_passthrough.js');
-},{"./lib/_stream_duplex.js":207,"./lib/_stream_passthrough.js":208,"./lib/_stream_readable.js":209,"./lib/_stream_transform.js":210,"./lib/_stream_writable.js":211}],217:[function(require,module,exports){
+},{"./lib/_stream_duplex.js":206,"./lib/_stream_passthrough.js":207,"./lib/_stream_readable.js":208,"./lib/_stream_transform.js":209,"./lib/_stream_writable.js":210}],216:[function(require,module,exports){
module.exports = require('./readable').Transform
-},{"./readable":216}],218:[function(require,module,exports){
+},{"./readable":215}],217:[function(require,module,exports){
module.exports = require('./lib/_stream_writable.js');
-},{"./lib/_stream_writable.js":211}],219:[function(require,module,exports){
+},{"./lib/_stream_writable.js":210}],218:[function(require,module,exports){
/* eslint-disable node/no-deprecated-api */
var buffer = require('buffer')
var Buffer = buffer.Buffer
@@ -124890,7 +127149,7 @@ SafeBuffer.allocUnsafeSlow = function (size) {
return buffer.SlowBuffer(size)
}
-},{"buffer":179}],220:[function(require,module,exports){
+},{"buffer":178}],219:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -125019,7 +127278,7 @@ Stream.prototype.pipe = function(dest, options) {
return dest;
};
-},{"events":183,"inherits":186,"readable-stream/duplex.js":206,"readable-stream/passthrough.js":215,"readable-stream/readable.js":216,"readable-stream/transform.js":217,"readable-stream/writable.js":218}],221:[function(require,module,exports){
+},{"events":182,"inherits":185,"readable-stream/duplex.js":205,"readable-stream/passthrough.js":214,"readable-stream/readable.js":215,"readable-stream/transform.js":216,"readable-stream/writable.js":217}],220:[function(require,module,exports){
(function (global){
var ClientRequest = require('./lib/request')
var extend = require('xtend')
@@ -125101,7 +127360,7 @@ http.METHODS = [
'UNSUBSCRIBE'
]
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./lib/request":223,"builtin-status-codes":180,"url":227,"xtend":233}],222:[function(require,module,exports){
+},{"./lib/request":222,"builtin-status-codes":179,"url":226,"xtend":232}],221:[function(require,module,exports){
(function (global){
exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream)
@@ -125174,7 +127433,7 @@ function isFunction (value) {
xhr = null // Help gc
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],223:[function(require,module,exports){
+},{}],222:[function(require,module,exports){
(function (process,global,Buffer){
var capability = require('./capability')
var inherits = require('inherits')
@@ -125484,7 +127743,7 @@ var unsafeHeaders = [
]
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"./capability":222,"./response":224,"_process":201,"buffer":179,"inherits":186,"readable-stream":216,"to-arraybuffer":226}],224:[function(require,module,exports){
+},{"./capability":221,"./response":223,"_process":200,"buffer":178,"inherits":185,"readable-stream":215,"to-arraybuffer":225}],223:[function(require,module,exports){
(function (process,global,Buffer){
var capability = require('./capability')
var inherits = require('inherits')
@@ -125670,7 +127929,7 @@ IncomingMessage.prototype._onXHRProgress = function () {
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("buffer").Buffer)
-},{"./capability":222,"_process":201,"buffer":179,"inherits":186,"readable-stream":216}],225:[function(require,module,exports){
+},{"./capability":221,"_process":200,"buffer":178,"inherits":185,"readable-stream":215}],224:[function(require,module,exports){
'use strict';
var Buffer = require('safe-buffer').Buffer;
@@ -125943,7 +128202,7 @@ function simpleWrite(buf) {
function simpleEnd(buf) {
return buf && buf.length ? this.write(buf) : '';
}
-},{"safe-buffer":219}],226:[function(require,module,exports){
+},{"safe-buffer":218}],225:[function(require,module,exports){
var Buffer = require('buffer').Buffer
module.exports = function (buf) {
@@ -125972,7 +128231,7 @@ module.exports = function (buf) {
}
}
-},{"buffer":179}],227:[function(require,module,exports){
+},{"buffer":178}],226:[function(require,module,exports){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
@@ -126706,7 +128965,7 @@ Url.prototype.parseHost = function() {
if (host) this.hostname = host;
};
-},{"./util":228,"punycode":202,"querystring":205}],228:[function(require,module,exports){
+},{"./util":227,"punycode":201,"querystring":204}],227:[function(require,module,exports){
'use strict';
module.exports = {
@@ -126724,7 +128983,7 @@ module.exports = {
}
};
-},{}],229:[function(require,module,exports){
+},{}],228:[function(require,module,exports){
(function (global){
/**
@@ -126795,16 +129054,16 @@ function config (name) {
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],230:[function(require,module,exports){
-arguments[4][186][0].apply(exports,arguments)
-},{"dup":186}],231:[function(require,module,exports){
+},{}],229:[function(require,module,exports){
+arguments[4][185][0].apply(exports,arguments)
+},{"dup":185}],230:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
-},{}],232:[function(require,module,exports){
+},{}],231:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
@@ -127394,7 +129653,7 @@ function hasOwnProperty(obj, prop) {
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{"./support/isBuffer":231,"_process":201,"inherits":230}],233:[function(require,module,exports){
+},{"./support/isBuffer":230,"_process":200,"inherits":229}],232:[function(require,module,exports){
module.exports = extend
var hasOwnProperty = Object.prototype.hasOwnProperty;
diff --git a/TaskServer/node_modules/ccxt/js/adara.js b/TaskServer/node_modules/ccxt/js/adara.js
deleted file mode 100644
index d816df1c3..000000000
--- a/TaskServer/node_modules/ccxt/js/adara.js
+++ /dev/null
@@ -1,1255 +0,0 @@
-'use strict';
-
-// ---------------------------------------------------------------------------
-
-const Exchange = require ('./base/Exchange');
-const { ExchangeError, BadRequest, AuthenticationError, InvalidOrder, InsufficientFunds, OrderNotFound } = require ('./base/errors');
-
-// ---------------------------------------------------------------------------
-
-module.exports = class adara extends Exchange {
- describe () {
- return this.deepExtend (super.describe (), {
- 'id': 'adara',
- 'name': 'Adara',
- 'countries': [ 'MT' ],
- 'version': 'v1',
- 'rateLimit': 1000,
- 'certified': false,
- // new metainfo interface
- 'has': {
- 'CORS': false,
- 'fetchCurrencies': true,
- 'fetchOrderBooks': false,
- 'createMarketOrder': false,
- 'fetchDepositAddress': false,
- 'fetchClosedOrders': true,
- 'fetchMyTrades': false,
- 'fetchOHLCV': false,
- 'fetchOrder': true,
- 'fetchOpenOrders': true,
- 'fetchTickers': true,
- 'withdraw': false,
- 'fetchDeposits': false,
- 'fetchWithdrawals': false,
- 'fetchTransactions': false,
- },
- 'requiredCredentials': {
- 'apiKey': true,
- 'secret': true,
- 'token': false,
- },
- 'urls': {
- 'logo': 'https://user-images.githubusercontent.com/1294454/49189583-0466a780-f380-11e8-9248-57a631aad2d6.jpg',
- 'api': 'https://api.adara.io',
- 'www': 'https://adara.io',
- 'doc': 'https://api.adara.io/v1',
- 'fees': 'https://adara.io/fees',
- },
- 'api': {
- 'public': {
- 'get': [
- 'currencies',
- 'limits',
- 'market',
- 'marketDepth',
- 'marketInfo',
- 'orderBook',
- 'quote/',
- 'quote/{id}',
- 'symbols',
- 'trade',
- ],
- 'post': [
- 'confirmContactEmail',
- 'restorePassword',
- 'user', // sign up
- ],
- },
- 'private': {
- 'get': [
- 'balance',
- 'order',
- 'order/{id}',
- 'currencyBalance',
- 'apiKey', // the list of apiKeys
- 'user/{id}',
- ],
- 'post': [
- 'order',
- 'recovery',
- 'user',
- 'apiKey', // sign in and optionally create an apiKey
- 'contact',
- ],
- 'patch': [
- 'order/{id}',
- 'user/{id}', // change password
- 'customer', // update user info
- ],
- 'delete': [
- 'apiKey',
- ],
- },
- },
- 'fees': {
- 'trading': {
- 'tierBased': false,
- 'percentage': true,
- 'maker': 0.001,
- 'taker': 0.001,
- },
- 'funding': {
- 'tierBased': false,
- 'percentage': false,
- 'withdraw': {},
- 'deposit': {},
- },
- },
- 'exceptions': {
- 'exact': {
- 'Insufficient funds': InsufficientFunds,
- 'Amount is too small': InvalidOrder,
- 'operation has invalid value': InvalidOrder,
- "closed order can't be changed": InvalidOrder,
- 'Order is not found': OrderNotFound,
- 'AUTH': AuthenticationError,
- 'You are not authorized': AuthenticationError,
- 'Bad Request': BadRequest,
- '500': ExchangeError,
- },
- 'broad': {},
- },
- });
- }
-
- async fetchMarkets (params = {}) {
- const request = {
- 'include': 'from,to',
- };
- const response = await this.publicGetSymbols (this.extend (request, params));
- const included = this.safeValue (response, 'included', []);
- const includedByType = this.groupBy (included, 'type');
- const currencies = this.safeValue (includedByType, 'currency', []);
- const currenciesById = this.indexBy (currencies, 'id');
- //
- // { meta: { total: 61 },
- // data: [ { id: "XRPUSD",
- // type: "symbol",
- // attributes: { allowTrade: false,
- // createdAt: "2018-10-23T09:31:06.830Z",
- // digits: 5,
- // fullName: "XRPUSD",
- // makerFee: "0.0250",
- // name: "XRPUSD",
- // takerFee: "0.0250",
- // updatedAt: "2018-10-23T09:31:06.830Z" },
- // relationships: { from: { data: { id: "XRP", type: "currency" } },
- // to: { data: { id: "USD", type: "currency" } } } },
- // { id: "XRPETH",
- // type: "symbol",
- // attributes: { allowTrade: true,
- // createdAt: "2018-10-09T22:34:28.268Z",
- // digits: 8,
- // fullName: "XRPETH",
- // makerFee: "0.0025",
- // name: "XRPETH",
- // takerFee: "0.0025",
- // updatedAt: "2018-10-09T22:34:28.268Z" },
- // relationships: { from: { data: { id: "XRP", type: "currency" } },
- // to: { data: { id: "ETH", type: "currency" } } } } ],
- // included: [ { id: "XRP",
- // type: "currency",
- // attributes: { accuracy: 4,
- // active: true,
- // allowDeposit: true,
- // allowTrade: false,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Ripple",
- // shortName: "XRP",
- // transactionUriTemplate: "https://www.ripplescan.com/transactions/:txId",
- // walletUriTemplate: "https://www.ripplescan.com/accounts/:address",
- // withdrawFee: "0.20000000",
- // withdrawMinAmount: "22.00000000" },
- // relationships: { } },
- // { id: "ETH",
- // type: "currency",
- // attributes: { accuracy: 8,
- // active: true,
- // allowDeposit: true,
- // allowTrade: true,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Ethereum",
- // shortName: "ETH",
- // transactionUriTemplate: "https://etherscan.io/tx/:txId",
- // walletUriTemplate: "https://etherscan.io/address/:address",
- // withdrawFee: "0.00800000",
- // withdrawMinAmount: "0.02000000" },
- // relationships: { } },
- // { id: "USD",
- // type: "currency",
- // attributes: { accuracy: 6,
- // active: true,
- // allowDeposit: false,
- // allowTrade: true,
- // allowWallet: false,
- // allowWithdraw: false,
- // name: "USD",
- // shortName: "USD",
- // transactionUriTemplate: null,
- // walletUriTemplate: null,
- // withdrawFee: "0.00000000",
- // withdrawMinAmount: "0.00000000" },
- // relationships: { } } ] }
- //
- const result = [];
- const markets = response['data'];
- for (let i = 0; i < markets.length; i++) {
- const market = markets[i];
- const id = this.safeString (market, 'id');
- const attributes = this.safeValue (market, 'attributes', {});
- const relationships = this.safeValue (market, 'relationships', {});
- const fromRelationship = this.safeValue (relationships, 'from', {});
- const toRelationship = this.safeValue (relationships, 'to', {});
- const fromRelationshipData = this.safeValue (fromRelationship, 'data', {});
- const toRelationshipData = this.safeValue (toRelationship, 'data', {});
- const baseId = this.safeString (fromRelationshipData, 'id');
- const quoteId = this.safeString (toRelationshipData, 'id');
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- const baseCurrency = this.safeValue (currenciesById, baseId, {});
- const baseCurrencyAttributes = this.safeValue (baseCurrency, 'attributes', {});
- const symbol = base + '/' + quote;
- const amountPrecision = this.safeInteger (baseCurrencyAttributes, 'accuracy', 8);
- const pricePrecision = this.safeInteger (attributes, 'digits', 8);
- const precision = {
- 'amount': amountPrecision,
- 'price': pricePrecision,
- };
- const active = this.safeValue (attributes, 'allowTrade');
- const maker = this.safeFloat (attributes, 'makerFee');
- const taker = this.safeFloat (attributes, 'takerFee');
- result.push ({
- 'info': market,
- 'id': id,
- 'symbol': symbol,
- 'base': base,
- 'quote': quote,
- 'baseId': baseId,
- 'quoteId': quoteId,
- 'active': active,
- 'maker': maker,
- 'taker': taker,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': Math.pow (10, -precision['amount']),
- 'max': undefined,
- },
- 'price': {
- 'min': Math.pow (10, -precision['price']),
- 'max': undefined,
- },
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- },
- });
- }
- return result;
- }
-
- async fetchCurrencies (params = {}) {
- const response = await this.publicGetCurrencies (params);
- //
- // { meta: { total: 22 },
- // data: [ { id: "USD",
- // type: "currency",
- // attributes: { accuracy: 6,
- // active: true,
- // allowDeposit: false,
- // allowTrade: true,
- // allowWallet: false,
- // allowWithdraw: false,
- // name: "USD",
- // shortName: "USD",
- // transactionUriTemplate: null,
- // walletUriTemplate: null,
- // withdrawFee: "0.00000000",
- // withdrawMinAmount: "0.00000000" },
- // relationships: { } },
- // { id: "BTC",
- // type: "currency",
- // attributes: { accuracy: 8,
- // active: true,
- // allowDeposit: true,
- // allowTrade: true,
- // allowWallet: true,
- // allowWithdraw: true,
- // name: "Bitcoin",
- // shortName: "BTC",
- // transactionUriTemplate: "https://blockexplorer.com/tx/:txId",
- // walletUriTemplate: "https://blockexplorer.com/address/:address",
- // withdrawFee: "0.00050000",
- // withdrawMinAmount: "0.00200000" },
- // relationships: { } } ],
- // included: [] }
- //
- const currencies = response['data'];
- const result = {};
- for (let i = 0; i < currencies.length; i++) {
- const currency = currencies[i];
- const id = this.safeString (currency, 'id');
- const attributes = this.safeValue (currency, 'attributes', {});
- const code = this.commonCurrencyCode (id);
- const precision = this.safeInteger (attributes, 'accuracy');
- const fee = this.safeFloat (attributes, 'withdrawFee');
- const active = this.safeValue (attributes, 'active');
- const allowDeposit = this.safeValue (attributes, 'allowDeposit');
- const allowWithdraw = this.safeValue (attributes, 'allowWithdraw');
- result[code] = {
- 'id': id,
- 'code': code,
- 'info': currency,
- 'name': this.safeString (attributes, 'name'),
- 'active': (active && allowDeposit && allowWithdraw),
- 'fee': fee,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': Math.pow (10, -precision),
- 'max': Math.pow (10, precision),
- },
- 'price': {
- 'min': Math.pow (10, -precision),
- 'max': Math.pow (10, precision),
- },
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- 'withdraw': {
- 'min': this.safeFloat (attributes, 'withdrawMinAmount'),
- 'max': Math.pow (10, precision),
- },
- },
- };
- }
- return result;
- }
-
- async fetchBalance (params = {}) {
- await this.loadMarkets ();
- const response = await this.privateGetBalance (params);
- //
- // { data: [ { type: "balance",
- // id: "U4f0f0940-39bf-45a8-90bc-12d2899db4f1_BALANCE_FOR_ETH",
- // attributes: { totalBalance: 10000,
- // onOrders: 0,
- // normalizedTotalBalance: 310,
- // normalizedOnOrders: 0,
- // percentage: 3.004116443856034,
- // serializedAt: 1543324487949 },
- // relationships: { currency: { data: { type: "currency", id: "ETH" } },
- // normalizedCurrency: { data: { type: "currency", id: "BTC" } } } } ],
- // included: [ { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543324487948 },
- // relationships: { } },
- // { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543324487948 } } ] }
- //
- const result = { 'info': response };
- const data = this.safeValue (response, 'data');
- if (data !== undefined) {
- for (let i = 0; i < data.length; i++) {
- const balance = data[i];
- const attributes = this.safeValue (balance, 'attributes', {});
- const relationships = this.safeValue (balance, 'relationships', {});
- const currencyRelationship = this.safeValue (relationships, 'currency', {});
- const currencyRelationshipData = this.safeValue (currencyRelationship, 'data');
- const currencyId = this.safeString (currencyRelationshipData, 'id');
- const code = this.commonCurrencyCode (currencyId);
- const account = this.account ();
- account['total'] = this.safeFloat (attributes, 'totalBalance');
- account['used'] = this.safeFloat (attributes, 'onOrders');
- result[code] = account;
- }
- }
- return this.parseBalance (result);
- }
-
- getSymbolFromMarketId (marketId, market = undefined) {
- if (marketId === undefined) {
- return undefined;
- }
- market = this.safeValue (this.markets_by_id, marketId, market);
- if (market !== undefined) {
- return market['symbol'];
- }
- const [ baseId, quoteId ] = marketId.split ('-');
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- return base + '/' + quote;
- }
-
- parseOrderBook (orderbook, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 'price', amountKey = 'amount') {
- const bids = [];
- const asks = [];
- const numBidAsks = orderbook.length;
- if (numBidAsks > 0) {
- timestamp = this.safeInteger (orderbook[0]['attributes'], 'serializedAt');
- }
- for (let i = 0; i < orderbook.length; i++) {
- const bidask = orderbook[i];
- const attributes = this.safeValue (bidask, 'attributes', {});
- const currenTimestamp = this.safeInteger (attributes, 'serializedAt');
- timestamp = Math.max (timestamp, currenTimestamp);
- const id = this.safeString (bidask, 'id');
- if (id.indexOf ('OBID') >= 0) {
- bids.push (this.parseBidAsk (bidask['attributes'], priceKey, amountKey));
- } else if (id.indexOf ('OSID') >= 0) {
- asks.push (this.parseBidAsk (bidask['attributes'], priceKey, amountKey));
- } else {
- throw new ExchangeError (this.id + ' parseOrderBook encountered an unrecognized bidask format: ' + this.json (bidask));
- }
- }
- return {
- 'bids': this.sortBy (bids, 0, true),
- 'asks': this.sortBy (asks, 0),
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'nonce': undefined,
- };
- }
-
- async fetchOrderBook (symbol, limit = undefined, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const filters = 'filters[symbol]';
- const request = {};
- request[filters] = market['id'];
- const response = await this.publicGetOrderBook (this.extend (request, params));
- //
- // { data: [ { type: "orderBook",
- // id: "OBID0SLTCETHS0",
- // attributes: { price: 1,
- // amount: 4,
- // serializedAt: 1543116143473 } },
- // { type: "orderBook",
- // id: "OSID3SLTCETHS0",
- // attributes: { price: 12,
- // amount: 12,
- // serializedAt: 1543116143474 } } ] }
- //
- return this.parseOrderBook (response['data'], undefined, 'bids', 'asks', 'price', 'amount');
- }
-
- parseTicker (ticker, market = undefined) {
- //
- // { type: "quote",
- // id: "XRPETH",
- // attributes: { currentPrice: 1,
- // low: 1,
- // high: 1,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543109275996 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } }
- //
- const symbol = this.getSymbolFromMarketId (this.safeString (ticker, 'id'), market);
- const attributes = this.safeValue (ticker, 'attributes', {});
- const timestamp = this.safeInteger (attributes, 'serializedAt');
- const last = this.safeFloat (attributes, 'currentPrice');
- const change = this.safeFloat (attributes, 'change');
- let open = undefined;
- if (change !== undefined) {
- if (last !== undefined) {
- open = last - change;
- }
- }
- const percentage = this.safeFloat (attributes, 'percentChange');
- return {
- 'symbol': symbol,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'high': this.safeFloat (attributes, 'high'),
- 'low': this.safeFloat (attributes, 'low'),
- 'bid': undefined,
- 'bidVolume': undefined,
- 'ask': undefined,
- 'askVolume': undefined,
- 'vwap': undefined,
- 'open': open,
- 'close': last,
- 'last': last,
- 'previousClose': undefined,
- 'change': change,
- 'percentage': percentage,
- 'average': undefined,
- 'baseVolume': this.safeFloat (ticker, 'baseVolume'),
- 'quoteVolume': this.safeFloat (ticker, 'quoteVolume'),
- 'info': ticker,
- };
- }
-
- async fetchTickers (symbols = undefined, params = {}) {
- await this.loadMarkets ();
- const response = await this.publicGetQuote (params);
- const data = this.safeValue (response, 'data', []);
- //
- // { data: [ { type: "quote",
- // id: "XRPETH",
- // attributes: { currentPrice: 1,
- // low: 1,
- // high: 1,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543109275996 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- // included: [ { type: "currency",
- // id: "XRP",
- // attributes: { name: "Ripple",
- // shortName: "XRP",
- // active: true,
- // accuracy: 4,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543109275996 },
- // relationships: { } },
- // { type: "symbol",
- // id: "XRPETH",
- // attributes: { fullName: "XRPETH",
- // digits: 8,
- // allowTrade: true,
- // serializedAt: 1543109275996 },
- // relationships: { from: { data: { type: "currency", id: "XRP" } },
- // to: { data: { type: "currency", id: "ETH" } } } } ] }
- //
- const result = {};
- for (let t = 0; t < data.length; t++) {
- const ticker = this.parseTicker (data[t]);
- const symbol = ticker['symbol'];
- result[symbol] = ticker;
- }
- return result;
- }
-
- async fetchTicker (symbol, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const request = {
- 'id': market['id'],
- };
- const response = await this.publicGetQuoteId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543111444033 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543111444033 } },
- // { type: "symbol",
- // id: "ETHBTC",
- // attributes: { fullName: "ETHBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543111444033 },
- // relationships: { from: { data: { type: "currency", id: "ETH" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "quote",
- // id: "ETHBTC",
- // attributes: { currentPrice: 34,
- // low: 34,
- // high: 34,
- // baseVolume: 0,
- // quoteVolume: 0,
- // change: 0,
- // percentChange: 0,
- // serializedAt: 1543111444033 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } } (fetchTicker @ adara.js:546)
- //
- return this.parseTicker (response['data']);
- }
-
- parseTrade (trade, market = undefined) {
- //
- // fetchTrades
- //
- //
- // { type: "trade",
- // id: "1542988964359136846136847",
- // attributes: { price: 34,
- // amount: 4,
- // total: 136,
- // operation: "buy",
- // createdAt: "2018-11-23T16:02:44.359Z",
- // serializedAt: 1543112364995 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- //
- const id = this.safeString (trade, 'id', 'uuid');
- const attributes = this.safeValue (trade, 'attributes', {});
- const relationships = this.safeValue (trade, 'relationships', {});
- const symbolRelationship = this.safeValue (relationships, 'symbol', {});
- const symbolRelationshipData = this.safeValue (symbolRelationship, 'data', {});
- const marketId = this.safeString (symbolRelationshipData, 'id');
- market = this.safeValue (this.markets_by_id, marketId, market);
- let symbol = undefined;
- let feeCurrency = undefined;
- if (market !== undefined) {
- symbol = market['symbol'];
- feeCurrency = market['quote'];
- } else if (marketId !== undefined) {
- const baseIdLength = marketId.length - 3;
- const baseId = marketId.slice (0, baseIdLength);
- const quoteId = marketId.slice (baseIdLength);
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- symbol = base + '/' + quote;
- feeCurrency = quote;
- }
- const orderId = undefined;
- const timestamp = this.parse8601 (this.safeString (attributes, 'createdAt'));
- const side = this.safeString (attributes, 'operation');
- const price = this.safeFloat (attributes, 'price');
- const amount = this.safeFloat (attributes, 'amount');
- let cost = this.safeFloat (attributes, 'total');
- if (cost === undefined) {
- if (amount !== undefined) {
- if (price !== undefined) {
- cost = parseFloat (this.costToPrecision (symbol, price * amount));
- }
- }
- }
- const feeCost = this.safeFloat (attributes, 'fee');
- let fee = undefined;
- if (feeCost !== undefined) {
- fee = {
- 'cost': feeCost,
- 'currency': feeCurrency,
- };
- }
- return {
- 'id': id,
- 'info': trade,
- 'order': orderId,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'symbol': symbol,
- 'type': undefined,
- 'side': side,
- 'takerOrMaker': undefined,
- 'price': price,
- 'amount': amount,
- 'cost': cost,
- 'fee': fee,
- };
- }
-
- async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
- let market = undefined;
- if (symbol !== undefined) {
- market = this.market (symbol);
- }
- const request = {
- // 'id': market['id'],
- };
- const response = await this.publicGetTrade (this.extend (request, params));
- //
- // { data: [ { type: "trade",
- // id: "1542988964359136846136847",
- // attributes: { price: 34,
- // amount: 4,
- // total: 136,
- // operation: "buy",
- // createdAt: "2018-11-23T16:02:44.359Z",
- // serializedAt: 1543112364995 },
- // relationships: { symbol: { data: { type: "symbol", id: "ETHBTC" } } } } ],
- // included: [ { type: "currency",
- // id: "ETH",
- // attributes: { name: "Ethereum",
- // shortName: "ETH",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543112364995 },
- // relationships: { } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // ...
- // serializedAt: 1543112364995 },
- // relationships: { } },
- // { type: "symbol",
- // id: "ETHBTC",
- // attributes: { fullName: "ETHBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543112364995 },
- // relationships: { from: { data: { type: "currency", id: "ETH" } },
- // to: { data: { type: "currency", id: "BTC" } } } } }
- //
- return this.parseTrades (response['data'], market, since, limit);
- }
-
- async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
- await this.loadMarkets ();
- const market = this.market (symbol);
- const request = {
- 'data': {
- 'type': 'order',
- 'attributes': {
- 'amount': parseFloat (this.amountToPrecision (symbol, amount)),
- 'operation': side,
- 'orderType': type,
- 'price': parseFloat (this.priceToPrecision (symbol, price)),
- },
- 'relationships': {
- 'symbol': {
- 'data': {
- 'id': market['id'],
- 'type': 'symbol',
- },
- },
- },
- },
- 'included': [
- {
- 'id': market['id'],
- 'type': 'symbol',
- },
- ],
- };
- const response = await this.privatePostOrder (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543434477449 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543434477449 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543434477449 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543434477449,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0,
- // fee: 0,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: null,
- // status: "open",
- // filled: 0,
- // flags: [] },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } } }
- //
- return this.parseOrder (response['data']);
- }
-
- async cancelOrder (id, symbol = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'id': id,
- 'data': {
- 'attributes': {
- 'status': 'canceled',
- },
- },
- };
- const response = await this.privatePatchOrderId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543437874742 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543437874742 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543437874742 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } } ],
- // data: { type: "order",
- // id: "34794",
- // attributes: { serializedAt: 1543437874742,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 110,
- // price: 0.000034,
- // averagePrice: 0,
- // fee: 0,
- // timeOpen: "2018-11-28T20:42:35.486Z",
- // timeClose: null,
- // status: "canceled",
- // filled: 0,
- // flags: [] },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } } }
- //
- return this.parseOrder (response['data']);
- }
-
- parseOrderStatus (status) {
- const statuses = {
- 'open': 'open',
- 'closed': 'closed',
- 'canceled': 'canceled',
- };
- return this.safeString (statuses, status, status);
- }
-
- parseOrder (order, market = undefined) {
- //
- // { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543435013349,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } } } }
- //
- const id = this.safeString (order, 'id');
- const attributes = this.safeValue (order, 'attributes', {});
- const relationships = this.safeValue (order, 'relationships', {});
- const symbolRelationship = this.safeValue (relationships, 'symbol', {});
- const symbolRelationshipData = this.safeValue (symbolRelationship, 'data', {});
- const tradesRelationship = this.safeValue (relationships, 'trades', {});
- const tradesRelationshipData = this.safeValue (tradesRelationship, 'data');
- const marketId = this.safeString (symbolRelationshipData, 'id');
- market = this.safeValue (this.markets_by_id, marketId, market);
- let feeCurrency = undefined;
- let symbol = undefined;
- if (market !== undefined) {
- symbol = market['symbol'];
- feeCurrency = market['quote'];
- } else if (marketId !== undefined) {
- const baseIdLength = marketId.length - 3;
- const baseId = marketId.slice (0, baseIdLength);
- const quoteId = marketId.slice (baseIdLength);
- const base = this.commonCurrencyCode (baseId);
- const quote = this.commonCurrencyCode (quoteId);
- symbol = base + '/' + quote;
- feeCurrency = quote;
- }
- const timestamp = this.parse8601 (this.safeString (attributes, 'timeOpen'));
- const side = this.safeString (attributes, 'operation');
- const type = this.safeString (attributes, 'orderType');
- const status = this.parseOrderStatus (this.safeString (attributes, 'status'));
- const lastTradeTimestamp = this.parse8601 (this.safeString (attributes, 'timeClose'));
- const price = this.safeFloat (attributes, 'price');
- const amount = this.safeFloat (attributes, 'amount');
- const filled = this.safeFloat (attributes, 'filled');
- let remaining = undefined;
- if (amount !== undefined) {
- if (filled !== undefined) {
- remaining = Math.max (0, amount - filled);
- }
- }
- let cost = undefined;
- const average = this.safeFloat (attributes, 'averagePrice');
- if (cost === undefined) {
- if ((average !== undefined) && (filled !== undefined)) {
- cost = parseFloat (this.costToPrecision (symbol, average * filled));
- }
- }
- let fee = undefined;
- const feeCost = this.safeFloat (attributes, 'fee');
- if (feeCost !== undefined) {
- fee = {
- 'currency': feeCurrency,
- 'cost': feeCost,
- };
- }
- let trades = undefined;
- if (tradesRelationshipData !== undefined) {
- const numTrades = tradesRelationshipData.length;
- if (numTrades > 0) {
- trades = this.parseTrades (tradesRelationshipData, market);
- }
- }
- const result = {
- 'info': order,
- 'id': id,
- 'clientOrderId': undefined,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'lastTradeTimestamp': lastTradeTimestamp,
- 'symbol': symbol,
- 'type': type,
- 'side': side,
- 'price': price,
- 'cost': cost,
- 'average': average,
- 'amount': amount,
- 'filled': filled,
- 'remaining': remaining,
- 'status': status,
- 'fee': fee,
- 'trades': trades,
- };
- return result;
- }
-
- async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'include': 'trades',
- };
- let market = undefined;
- if (symbol !== undefined) {
- market = this.market (symbol);
- const filters = 'filters[symbol]';
- request[filters] = market['id'];
- }
- const response = await this.privateGetOrder (this.extend (request, params));
- //
- // { data: [ { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543436770259,
- // operation: "buy",
- // orderType: "limit",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } },
- // trades: { data: [{ type: "trade", id: "34789_34793" }] } } } ],
- // included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543436770259 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543436770259 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543436770259 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } },
- // { type: "trade",
- // id: "34789_34793",
- // attributes: { fee: 0.0001925,
- // price: 0.000035,
- // amount: 220,
- // total: 0.0077,
- // operation: "buy",
- // createdAt: "2018-11-28T19:47:57.451Z" } } ],
- // meta: { total: 1 } }
- //
- return this.parseOrdersResponse (response, market, since, limit);
- }
-
- async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- const filters = 'filters[status][]';
- const request = {};
- request[filters] = 'open';
- return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
- }
-
- async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- const filters = 'filters[status][]';
- const request = {};
- request[filters] = 'closed';
- return await this.fetchOrders (symbol, since, limit, this.extend (request, params));
- }
-
- parseOrdersResponse (response, market = undefined, since = undefined, limit = undefined) {
- const included = this.safeValue (response, 'included', []);
- const includedByType = this.groupBy (included, 'type');
- const unparsedTrades = this.safeValue (includedByType, 'trade', []);
- const trades = this.parseTrades (unparsedTrades, market);
- const tradesById = this.indexBy (trades, 'id');
- const orders = this.parseOrders (this.safeValue (response, 'data', []), market, since, limit);
- const result = [];
- for (let i = 0; i < orders.length; i++) {
- const order = orders[i];
- const orderTrades = [];
- const orderFee = this.safeValue (order, 'fee', {});
- const orderFeeCurrency = this.safeString (orderFee, 'currency');
- if (order['trades'] !== undefined) {
- for (let j = 0; j < order['trades'].length; j++) {
- const orderTrade = order['trades'][j];
- const orderTradeId = orderTrade['id'];
- if (orderTradeId in tradesById) {
- orderTrades.push (this.deepExtend (tradesById[orderTradeId], {
- 'order': order['id'],
- 'type': order['type'],
- 'symbol': order['symbol'],
- 'fee': {
- 'currency': orderFeeCurrency,
- },
- }));
- }
- }
- }
- const numOrderTrades = orderTrades.length;
- if (numOrderTrades > 0) {
- order['trades'] = orderTrades;
- }
- result.push (order);
- }
- return result;
- }
-
- async fetchOrder (id, symbol = undefined, params = {}) {
- await this.loadMarkets ();
- const request = {
- 'id': id,
- 'include': 'trades',
- };
- const response = await this.privateGetOrderId (this.extend (request, params));
- //
- // { included: [ { type: "currency",
- // id: "XLM",
- // attributes: { name: "Stellar",
- // shortName: "XLM",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: false,
- // serializedAt: 1543436451996 } },
- // { type: "currency",
- // id: "BTC",
- // attributes: { name: "Bitcoin",
- // shortName: "BTC",
- // active: true,
- // accuracy: 8,
- // allowDeposit: true,
- // allowWithdraw: true,
- // allowWallet: true,
- // allowTrade: true,
- // serializedAt: 1543436451996 } },
- // { type: "symbol",
- // id: "XLMBTC",
- // attributes: { fullName: "XLMBTC",
- // digits: 6,
- // allowTrade: true,
- // serializedAt: 1543436451996 },
- // relationships: { from: { data: { type: "currency", id: "XLM" } },
- // to: { data: { type: "currency", id: "BTC" } } } },
- // { type: "trade",
- // id: "34789_34793",
- // attributes: { fee: 0.0001925,
- // price: 0.000035,
- // amount: 220,
- // total: 0.0077,
- // operation: "buy",
- // createdAt: "2018-11-28T19:47:57.451Z" } } ],
- // data: { type: "order",
- // id: "34793",
- // attributes: { serializedAt: 1543436451996,
- // operation: "buy",
- // orderType: "limit",
- // clientId: "4733ea40-7d5c-4ddc-aec5-eb41baf90555",
- // amount: 220,
- // price: 0.000035,
- // averagePrice: 0.000035,
- // fee: 0.0001925,
- // timeOpen: "2018-11-28T19:47:57.435Z",
- // timeClose: "2018-11-28T19:47:57.452Z",
- // status: "closed",
- // filled: 220,
- // flags: null },
- // relationships: { symbol: { data: { type: "symbol", id: "XLMBTC" } },
- // trades: { data: [{ type: "trade", id: "34789_34793" }] } } } }
- //
- const data = this.safeValue (response, 'data');
- response['data'] = [];
- response['data'].push (data);
- const orders = this.parseOrdersResponse (response);
- const ordersById = this.indexBy (orders, 'id');
- if (id in ordersById) {
- return ordersById[id];
- }
- throw new OrderNotFound (this.id + ' fetchOrder could not find order id ' + id.toString ());
- }
-
- nonce () {
- return this.milliseconds ();
- }
-
- sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- let payload = '/' + this.implodeParams (path, params);
- let url = this.urls['api'] + '/' + this.version + payload;
- const query = this.omit (params, this.extractParams (path));
- if (method === 'GET') {
- if (Object.keys (query).length) {
- url += '?' + this.urlencode (query);
- }
- }
- if (api === 'private') {
- const nonce = this.nonce ();
- let expiredAt = this.sum (nonce, this.safeInteger (this.options, 'expiredAt', 10000));
- expiredAt = expiredAt.toString ();
- if ((method === 'POST') || (method === 'PATCH')) {
- body = this.json (query);
- payload = body;
- }
- if (this.token) {
- headers = {
- 'Cookie': 'token=' + this.token,
- };
- } else {
- this.checkRequiredCredentials ();
- const auth = method + payload + 'expiredAt=' + expiredAt;
- const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha512', 'base64');
- headers = {
- 'X-ADX-EXPIRE': expiredAt,
- 'X-ADX-APIKEY': this.apiKey,
- 'X-ADX-SIGNATURE': signature,
- };
- }
- if (method !== 'GET') {
- headers['Content-Type'] = 'application/json';
- }
- }
- return { 'url': url, 'method': method, 'body': body, 'headers': headers };
- }
-
- handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
- if (response === undefined) {
- return; // fallback to default error handler
- }
- const errors = this.safeValue (response, 'errors', []);
- const numErrors = errors.length;
- if (numErrors > 0) {
- const error = errors[0];
- const code = this.safeString (error, 'code');
- const status = this.safeString (error, 'status');
- const title = this.safeString (error, 'title');
- const detail = this.safeString (error, 'detail');
- const feedback = this.id + ' ' + this.json (response);
- this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], status, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], title, feedback);
- this.throwExactlyMatchedException (this.exceptions['exact'], detail, feedback);
- this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
- throw new ExchangeError (feedback); // unknown message
- }
- }
-};
diff --git a/TaskServer/node_modules/ccxt/js/aofex.js b/TaskServer/node_modules/ccxt/js/aofex.js
index f5e72f678..779d280c7 100644
--- a/TaskServer/node_modules/ccxt/js/aofex.js
+++ b/TaskServer/node_modules/ccxt/js/aofex.js
@@ -30,6 +30,7 @@ module.exports = class aofex extends Exchange {
'fetchOpenOrders': true,
'fetchClosedOrders': true,
'fetchClosedOrder': true,
+ 'fetchOrderTrades': true,
'fetchTradingFee': true,
},
'timeframes': {
@@ -559,7 +560,7 @@ module.exports = class aofex extends Exchange {
//
const id = this.safeString (trade, 'id');
const ctime = this.parse8601 (this.safeString (trade, 'ctime'));
- const timestamp = this.safeTimestamp (trade, 'ts', ctime);
+ const timestamp = this.safeTimestamp (trade, 'ts', ctime) - 28800000; // 8 hours, adjust to UTC;
let symbol = undefined;
if ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
@@ -725,7 +726,7 @@ module.exports = class aofex extends Exchange {
base = market['base'];
quote = market['quote'];
}
- const timestamp = this.parse8601 (this.safeString (order, 'ctime'));
+ const timestamp = this.parse8601 (this.safeString (order, 'ctime')) - 28800000; // 8 hours, adjust to UTC
const orderType = this.safeString (order, 'type');
const type = (orderType === '2') ? 'limit' : 'market';
const side = this.safeString (order, 'side');
@@ -883,11 +884,16 @@ module.exports = class aofex extends Exchange {
return this.parseOrder (order);
}
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ const response = await this.fetchClosedOrder (id, symbol, params);
+ return this.safeValue (response, 'trades', []);
+ }
+
async fetchOrdersWithMethod (method, symbol = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
const request = {
// 'from': 'BM7442641584965237751ZMAKJ5', // query start order_sn
- // 'direct': 'prev', // next
+ 'direct': 'prev', // next
};
let market = undefined;
if (symbol !== undefined) {
diff --git a/TaskServer/node_modules/ccxt/js/base/Exchange.js b/TaskServer/node_modules/ccxt/js/base/Exchange.js
index 52cdf8b0e..f818dd8a6 100644
--- a/TaskServer/node_modules/ccxt/js/base/Exchange.js
+++ b/TaskServer/node_modules/ccxt/js/base/Exchange.js
@@ -288,8 +288,9 @@ module.exports = class Exchange {
const config = deepExtend (this.describe (), userConfig)
// merge to this
- for (const [property, value] of Object.entries (config))
+ for (const [property, value] of Object.entries (config)) {
this[property] = deepExtend (this[property], value)
+ }
if (!this.httpAgent) {
this.httpAgent = defaultFetch.http ? new defaultFetch.http.Agent ({ 'keepAlive': true }) : undefined
@@ -304,13 +305,15 @@ module.exports = class Exchange {
this['has' + capitalize (k)] = !!this.has[k] // converts 'emulated' to true
}
- if (this.api)
+ if (this.api) {
this.defineRestApi (this.api, 'request')
+ }
this.initRestRateLimiter ()
- if (this.markets)
+ if (this.markets) {
this.setMarkets (this.markets)
+ }
}
defaults () {
@@ -342,20 +345,23 @@ module.exports = class Exchange {
checkAddress (address) {
- if (address === undefined)
+ if (address === undefined) {
throw new InvalidAddress (this.id + ' address is undefined')
+ }
// check the address is not the same letter like 'aaaaa' nor too short nor has a space
- if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' '))
+ if ((unique (address).length === 1) || address.length < this.minFundingAddressLength || address.includes (' ')) {
throw new InvalidAddress (this.id + ' address is invalid or has less than ' + this.minFundingAddressLength.toString () + ' characters: "' + this.json (address) + '"')
+ }
return address
}
initRestRateLimiter () {
- if (this.rateLimit === undefined)
+ if (this.rateLimit === undefined) {
throw new Error (this.id + '.rateLimit property is not configured')
+ }
this.tokenBucket = this.extend ({
delay: 1,
@@ -386,15 +392,17 @@ module.exports = class Exchange {
const promise =
fetchImplementation (url, this.extend (params, this.fetchOptions))
.catch ((e) => {
- if (isNode)
+ if (isNode) {
throw new ExchangeNotAvailable ([ this.id, method, url, e.type, e.message ].join (' '))
+ }
throw e // rethrow all unknown errors
})
- .then (response => this.handleRestResponse (response, url, method, headers, body))
+ .then ((response) => this.handleRestResponse (response, url, method, headers, body))
return timeout (this.timeout, promise).catch ((e) => {
- if (e instanceof TimedOut)
+ if (e instanceof TimedOut) {
throw new RequestTimeout (this.id + ' ' + method + ' ' + url + ' request timed out (' + this.timeout + ' ms)')
+ }
throw e
})
}
@@ -442,16 +450,20 @@ module.exports = class Exchange {
let underscore = type + '_' + lowercaseMethod + '_' + underscoreSuffix
if ('suffixes' in options) {
- if ('camelcase' in options['suffixes'])
+ if ('camelcase' in options['suffixes']) {
camelcase += options['suffixes']['camelcase']
- if ('underscore' in options.suffixes)
+ }
+ if ('underscore' in options.suffixes) {
underscore += options['suffixes']['underscore']
+ }
}
- if ('underscore_suffix' in options)
+ if ('underscore_suffix' in options) {
underscore += options.underscoreSuffix;
- if ('camelcase_suffix' in options)
+ }
+ if ('camelcase_suffix' in options) {
camelcase += options.camelcaseSuffix;
+ }
let partial = async params => this[methodName] (path, type, uppercaseMethod, params || {})
@@ -594,7 +606,7 @@ module.exports = class Exchange {
getResponseHeaders (response) {
const result = {}
response.headers.forEach ((value, key) => {
- key = key.split ('-').map (word => capitalize (word)).join ('-')
+ key = key.split ('-').map ((word) => capitalize (word)).join ('-')
result[key] = value
})
return result
@@ -632,7 +644,7 @@ module.exports = class Exchange {
}
setMarkets (markets, currencies = undefined) {
- const values = Object.values (markets).map (market => deepExtend ({
+ const values = Object.values (markets).map ((market) => deepExtend ({
'limits': this.limits,
'precision': this.precision,
}, this.fees['trading'], market))
@@ -803,6 +815,22 @@ module.exports = class Exchange {
throw new NotSupported (this.id + ' fetchOrder not supported yet');
}
+ fetchUnifiedOrder (order, params = {}) {
+ return this.fetchOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
+ }
+
+ createOrder (symbol, type, side, amount, price = undefined, params = {}) {
+ throw new NotSupported (this.id + ' createOrder not supported yet');
+ }
+
+ cancelOrder (id, symbol = undefined, params = {}) {
+ throw new NotSupported (this.id + ' cancelOrder not supported yet');
+ }
+
+ cancelUnifiedOrder (order, params = {}) {
+ return this.cancelOrder (this.safeValue (order, 'id'), this.safeValue (order, 'symbol'), params);
+ }
+
fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
throw new NotSupported (this.id + ' fetchOrders not supported yet');
}
diff --git a/TaskServer/node_modules/ccxt/js/base/functions/number.js b/TaskServer/node_modules/ccxt/js/base/functions/number.js
index e2f28933c..82c8f0f28 100644
--- a/TaskServer/node_modules/ccxt/js/base/functions/number.js
+++ b/TaskServer/node_modules/ccxt/js/base/functions/number.js
@@ -45,23 +45,27 @@ function numberToString (x) { // avoids scientific notation for too large and to
if (typeof x === 'string') return x
+ const s = x.toString ()
if (Math.abs (x) < 1.0) {
- const s = x.toString ()
const e = parseInt (s.split ('e-')[1])
const neg = (s[0] === '-')
if (e) {
x *= Math.pow (10, e - 1)
x = (neg ? '-' : '') + '0.' + (new Array (e)).join ('0') + x.toString ().substring (neg ? 3 : 2)
+ return x
}
} else {
- let e = parseInt (x.toString ().split ('+')[1])
- if (e > 20) {
- e -= 20
- x /= Math.pow (10, e)
- x += (new Array (e + 1)).join ('0')
+ const parts = s.split ('e')
+ if (parts[1]) {
+ let e = parseInt (parts[1])
+ const m = parts[0].split ('.')
+ if (m[1]) {
+ e -= m[1].length
+ }
+ return m[0] + m[1] + (new Array (e + 1)).join ('0')
}
}
- return x.toString ()
+ return s;
}
//-----------------------------------------------------------------------------
diff --git a/TaskServer/node_modules/ccxt/js/binance.js b/TaskServer/node_modules/ccxt/js/binance.js
index 5853cb91a..9c4cddc24 100644
--- a/TaskServer/node_modules/ccxt/js/binance.js
+++ b/TaskServer/node_modules/ccxt/js/binance.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied } = require ('./base/errors');
+const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, InvalidAddress, RateLimitExceeded, PermissionDenied, NotSupported } = require ('./base/errors');
const { ROUND, TRUNCATE } = require ('./base/functions/number');
// ---------------------------------------------------------------------------
@@ -37,6 +37,7 @@ module.exports = class binance extends Exchange {
'fetchTransactions': false,
'fetchTradingFee': true,
'fetchTradingFees': true,
+ 'cancelAllOrders': true,
},
'timeframes': {
'1m': '1m',
@@ -57,6 +58,10 @@ module.exports = class binance extends Exchange {
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/29604020-d5483cdc-87ee-11e7-94c7-d1a8d9169293.jpg',
+ 'test': {
+ 'fapiPublic': 'https://testnet.binancefuture.com/fapi/v1',
+ 'fapiPrivate': 'https://testnet.binancefuture.com/fapi/v1',
+ },
'api': {
'web': 'https://www.binance.com',
'wapi': 'https://api.binance.com/wapi/v3',
@@ -130,6 +135,8 @@ module.exports = class binance extends Exchange {
'lending/union/purchaseRecord',
'lending/union/redemptionRecord',
'lending/union/interestHistory',
+ 'lending/project/list',
+ 'lending/project/position/list',
],
'post': [
'asset/dust',
@@ -146,6 +153,7 @@ module.exports = class binance extends Exchange {
'userDataStream',
'futures/transfer',
// lending
+ 'lending/customizedFixed/purchase',
'lending/daily/purchase',
'lending/daily/redeem',
],
@@ -211,6 +219,8 @@ module.exports = class binance extends Exchange {
'income',
],
'post': [
+ 'batchOrders',
+ 'positionSide/dual',
'positionMargin',
'marginType',
'order',
@@ -221,6 +231,7 @@ module.exports = class binance extends Exchange {
'listenKey',
],
'delete': [
+ 'batchOrders',
'order',
'allOpenOrders',
'listenKey',
@@ -267,6 +278,7 @@ module.exports = class binance extends Exchange {
'order/test',
],
'delete': [
+ 'openOrders', // added on 2020-04-25 for canceling all open orders per symbol
'orderList', // oco
'order',
],
@@ -289,7 +301,6 @@ module.exports = class binance extends Exchange {
'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades
'fetchTickersMethod': 'publicGetTicker24hr',
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
- 'defaultLimitOrderType': 'limit', // or 'limit_maker'
'defaultType': 'spot', // 'spot', 'future'
'hasAlreadyAuthenticatedSuccessfully': false,
'warnOnFetchOpenOrdersWithoutSymbol': true,
@@ -326,6 +337,32 @@ module.exports = class binance extends Exchange {
});
}
+ setSandboxMode (enabled) {
+ if (enabled) { // eslint-disable-line no-extra-boolean-cast
+ if ('test' in this.urls) {
+ const type = this.safeString (this.options, 'defaultType', 'spot');
+ if (type !== 'future') {
+ throw new NotSupported (this.id + ' does not have a sandbox URL for ' + type + " markets, set exchange.options['defaultType'] = 'future' or don't use the sandbox for " + this.id);
+ }
+ if (typeof this.urls['api'] === 'string') {
+ this.urls['api_backup'] = this.urls['api'];
+ this.urls['api'] = this.urls['test'];
+ } else {
+ this.urls['api_backup'] = this.extend ({}, this.urls['api']);
+ this.urls['api'] = this.extend ({}, this.urls['test']);
+ }
+ } else {
+ throw new NotSupported (this.id + ' does not have a sandbox URL');
+ }
+ } else if ('api_backup' in this.urls) {
+ if (typeof this.urls['api'] === 'string') {
+ this.urls['api'] = this.urls['api_backup'];
+ } else {
+ this.urls['api'] = this.extend ({}, this.urls['api_backup']);
+ }
+ }
+ }
+
nonce () {
return this.milliseconds () - this.options['timeDifference'];
}
@@ -476,7 +513,7 @@ module.exports = class binance extends Exchange {
'max': undefined,
},
'cost': {
- 'min': -1 * Math.log10 (precision['amount']),
+ 'min': undefined,
'max': undefined,
},
},
@@ -720,7 +757,7 @@ module.exports = class binance extends Exchange {
async fetchBidsAsks (symbols = undefined, params = {}) {
await this.loadMarkets ();
- const defaultType = this.safeString2 (this.options, 'fetchOpenOrders', 'defaultType', 'spot');
+ const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot');
const type = this.safeString (params, 'type', defaultType);
const query = this.omit (params, 'type');
const method = (type === 'spot') ? 'publicGetTickerBookTicker' : 'fapiPublicGetTickerBookTicker';
@@ -737,12 +774,12 @@ module.exports = class binance extends Exchange {
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
return [
- ohlcv[0],
- parseFloat (ohlcv[1]),
- parseFloat (ohlcv[2]),
- parseFloat (ohlcv[3]),
- parseFloat (ohlcv[4]),
- parseFloat (ohlcv[5]),
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 5),
];
}
@@ -870,6 +907,10 @@ module.exports = class binance extends Exchange {
if (market !== undefined) {
symbol = market['symbol'];
}
+ let cost = undefined;
+ if ((price !== undefined) && (amount !== undefined)) {
+ cost = price * amount;
+ }
return {
'info': trade,
'timestamp': timestamp,
@@ -878,11 +919,11 @@ module.exports = class binance extends Exchange {
'id': id,
'order': orderId,
'type': undefined,
- 'takerOrMaker': takerOrMaker,
'side': side,
+ 'takerOrMaker': takerOrMaker,
'price': price,
'amount': amount,
- 'cost': price * amount,
+ 'cost': cost,
'fee': fee,
};
}
@@ -1180,6 +1221,8 @@ module.exports = class binance extends Exchange {
} else if (uppercaseType === 'STOP') {
stopPriceIsRequired = true;
priceIsRequired = true;
+ } else if (uppercaseType === 'STOP_MARKET') {
+ stopPriceIsRequired = true;
}
if (priceIsRequired) {
if (price === undefined) {
@@ -1339,6 +1382,27 @@ module.exports = class binance extends Exchange {
return this.parseOrder (response);
}
+ async cancelAllOrders (symbol = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' cancelAllOrders requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const defaultType = this.safeString2 (this.options, 'cancelAllOrders', 'defaultType', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ const method = (type === 'spot') ? 'privateDeleteOpenOrders' : 'fapiPrivateDeleteAllOpenOrders';
+ const response = await this[method] (this.extend (request, query));
+ if (Array.isArray (response)) {
+ return this.parseOrders (response, market);
+ } else {
+ return response;
+ }
+ }
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
@@ -1571,10 +1635,7 @@ module.exports = class binance extends Exchange {
}
parseTransactionStatusByType (status, type = undefined) {
- if (type === undefined) {
- return status;
- }
- const statuses = {
+ const statusesByType = {
'deposit': {
'0': 'pending',
'1': 'ok',
@@ -1589,32 +1650,38 @@ module.exports = class binance extends Exchange {
'6': 'ok', // Completed
},
};
- return (status in statuses[type]) ? statuses[type][status] : status;
+ const statuses = this.safeValue (statusesByType, type, {});
+ return this.safeString (statuses, status, status);
}
parseTransaction (transaction, currency = undefined) {
//
// fetchDeposits
- // { insertTime: 1517425007000,
- // amount: 0.3,
- // address: "0x0123456789abcdef",
- // addressTag: "",
- // txId: "0x0123456789abcdef",
- // asset: "ETH",
- // status: 1 }
+ //
+ // {
+ // insertTime: 1517425007000,
+ // amount: 0.3,
+ // address: "0x0123456789abcdef",
+ // addressTag: "",
+ // txId: "0x0123456789abcdef",
+ // asset: "ETH",
+ // status: 1
+ // }
//
// fetchWithdrawals
//
- // { amount: 14,
- // address: "0x0123456789abcdef...",
+ // {
+ // amount: 14,
+ // address: "0x0123456789abcdef...",
// successTime: 1514489710000,
- // transactionFee: 0.01,
- // addressTag: "",
- // txId: "0x0123456789abcdef...",
- // id: "0123456789abcdef...",
- // asset: "ETH",
- // applyTime: 1514488724000,
- // status: 6 }
+ // transactionFee: 0.01,
+ // addressTag: "",
+ // txId: "0x0123456789abcdef...",
+ // id: "0123456789abcdef...",
+ // asset: "ETH",
+ // applyTime: 1514488724000,
+ // status: 6
+ // }
//
const id = this.safeString (transaction, 'id');
const address = this.safeString (transaction, 'address');
@@ -1624,7 +1691,7 @@ module.exports = class binance extends Exchange {
tag = undefined;
}
}
- const txid = this.safeValue (transaction, 'txId');
+ const txid = this.safeString (transaction, 'txId');
const currencyId = this.safeString (transaction, 'asset');
const code = this.safeCurrencyCode (currencyId, currency);
let timestamp = undefined;
@@ -1854,6 +1921,11 @@ module.exports = class binance extends Exchange {
'timestamp': this.nonce (),
'recvWindow': this.options['recvWindow'],
}, params));
+ } else if (path === 'batchOrders') {
+ query = this.rawencode (this.extend ({
+ 'timestamp': this.nonce (),
+ 'recvWindow': this.options['recvWindow'],
+ }, params));
} else {
query = this.urlencode (this.extend ({
'timestamp': this.nonce (),
diff --git a/TaskServer/node_modules/ccxt/js/binanceus.js b/TaskServer/node_modules/ccxt/js/binanceus.js
index e8c600cfc..aafd7745e 100644
--- a/TaskServer/node_modules/ccxt/js/binanceus.js
+++ b/TaskServer/node_modules/ccxt/js/binanceus.js
@@ -31,10 +31,10 @@ module.exports = class binanceus extends binance {
},
'fees': {
'trading': {
- 'tierBased': false,
+ 'tierBased': true,
'percentage': true,
- 'taker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
- 'maker': 0.0, // 0.1% trading fee, zero fees for all trading pairs before November 1
+ 'taker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
+ 'maker': 0.001, // 0.1% trading fee, zero fees for all trading pairs before November 1
},
},
});
diff --git a/TaskServer/node_modules/ccxt/js/bitbay.js b/TaskServer/node_modules/ccxt/js/bitbay.js
index c2180de6e..f800a571f 100644
--- a/TaskServer/node_modules/ccxt/js/bitbay.js
+++ b/TaskServer/node_modules/ccxt/js/bitbay.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded } = require ('./base/errors');
+const { InvalidNonce, InsufficientFunds, AuthenticationError, InvalidOrder, ExchangeError, OrderNotFound, AccountSuspended, BadSymbol, OrderImmediatelyFillable, RateLimitExceeded, OnMaintenance } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -53,6 +53,7 @@ module.exports = class bitbay extends Exchange {
'https://github.com/BitBayNet/API',
'https://docs.bitbay.net/v1.0.1-en/reference',
],
+ 'support': 'https://support.bitbay.net',
'fees': 'https://bitbay.net/en/fees',
},
'api': {
@@ -117,8 +118,60 @@ module.exports = class bitbay extends Exchange {
},
'fees': {
'trading': {
+ 'maker': 0.0,
+ 'taker': 0.1 / 100,
+ 'percentage': true,
+ 'tierBased': false,
+ },
+ 'fiat': {
'maker': 0.30 / 100,
'taker': 0.43 / 100,
+ 'percentage': true,
+ 'tierBased': true,
+ 'tiers': {
+ 'taker': [
+ [ 0.0043, 0 ],
+ [ 0.0042, 1250 ],
+ [ 0.0041, 3750 ],
+ [ 0.0040, 7500 ],
+ [ 0.0039, 10000 ],
+ [ 0.0038, 15000 ],
+ [ 0.0037, 20000 ],
+ [ 0.0036, 25000 ],
+ [ 0.0035, 37500 ],
+ [ 0.0034, 50000 ],
+ [ 0.0033, 75000 ],
+ [ 0.0032, 100000 ],
+ [ 0.0031, 150000 ],
+ [ 0.0030, 200000 ],
+ [ 0.0029, 250000 ],
+ [ 0.0028, 375000 ],
+ [ 0.0027, 500000 ],
+ [ 0.0026, 625000 ],
+ [ 0.0025, 875000 ],
+ ],
+ 'maker': [
+ [ 0.0030, 0 ],
+ [ 0.0029, 1250 ],
+ [ 0.0028, 3750 ],
+ [ 0.0028, 7500 ],
+ [ 0.0027, 10000 ],
+ [ 0.0026, 15000 ],
+ [ 0.0025, 20000 ],
+ [ 0.0025, 25000 ],
+ [ 0.0024, 37500 ],
+ [ 0.0023, 50000 ],
+ [ 0.0023, 75000 ],
+ [ 0.0022, 100000 ],
+ [ 0.0021, 150000 ],
+ [ 0.0021, 200000 ],
+ [ 0.0020, 250000 ],
+ [ 0.0019, 375000 ],
+ [ 0.0018, 500000 ],
+ [ 0.0018, 625000 ],
+ [ 0.0017, 875000 ],
+ ],
+ },
},
'funding': {
'withdraw': {
@@ -135,6 +188,9 @@ module.exports = class bitbay extends Exchange {
},
},
},
+ 'options': {
+ 'fiatCurrencies': [ 'EUR', 'USD', 'GBP', 'PLN' ],
+ },
'exceptions': {
'400': ExchangeError, // At least one parameter wasn't set
'401': InvalidOrder, // Invalid order type
@@ -159,12 +215,14 @@ module.exports = class bitbay extends Exchange {
'OFFER_NOT_FOUND': OrderNotFound,
'OFFER_WOULD_HAVE_BEEN_PARTIALLY_FILLED': OrderImmediatelyFillable,
'ACTION_LIMIT_EXCEEDED': RateLimitExceeded,
+ 'UNDER_MAINTENANCE': OnMaintenance,
},
});
}
async fetchMarkets (params = {}) {
const response = await this.v1_01PublicGetTradingTicker (params);
+ const fiatCurrencies = this.safeValue (this.options, 'fiatCurrencies', []);
//
// {
// status: 'Ok',
@@ -203,6 +261,12 @@ module.exports = class bitbay extends Exchange {
'amount': this.safeInteger (first, 'scale'),
'price': this.safeInteger (second, 'scale'),
};
+ let fees = this.safeValue (this.fees, 'trading', {});
+ if (this.inArray (base, fiatCurrencies) || this.inArray (quote, fiatCurrencies)) {
+ fees = this.safeValue (this.fees, 'fiat', {});
+ }
+ const maker = this.safeFloat (fees, 'maker');
+ const taker = this.safeFloat (fees, 'taker');
// todo: check that the limits have ben interpreted correctly
// todo: parse the fees page
result.push ({
@@ -214,7 +278,8 @@ module.exports = class bitbay extends Exchange {
'quoteId': quoteId,
'precision': precision,
'active': undefined,
- 'fee': undefined,
+ 'maker': maker,
+ 'taker': taker,
'limits': {
'amount': {
'min': this.safeFloat (first, 'minOffer'),
diff --git a/TaskServer/node_modules/ccxt/js/bitfinex.js b/TaskServer/node_modules/ccxt/js/bitfinex.js
index 883301578..95768e94f 100644
--- a/TaskServer/node_modules/ccxt/js/bitfinex.js
+++ b/TaskServer/node_modules/ccxt/js/bitfinex.js
@@ -905,12 +905,12 @@ module.exports = class bitfinex extends Exchange {
parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
return [
- ohlcv[0],
- ohlcv[1],
- ohlcv[3],
- ohlcv[4],
- ohlcv[2],
- ohlcv[5],
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 5),
];
}
diff --git a/TaskServer/node_modules/ccxt/js/bitfinex2.js b/TaskServer/node_modules/ccxt/js/bitfinex2.js
index 89beea91a..86d97b188 100644
--- a/TaskServer/node_modules/ccxt/js/bitfinex2.js
+++ b/TaskServer/node_modules/ccxt/js/bitfinex2.js
@@ -699,6 +699,7 @@ module.exports = class bitfinex2 extends bitfinex {
'PARTIALLY FILLED': 'open',
'EXECUTED': 'closed',
'CANCELED': 'canceled',
+ 'CANCELED was: PARTIALLY FILLED': 'canceled',
'INSUFFICIENT MARGIN': 'canceled',
'INSUFFICIENT BALANCE (G1) was: PARTIALLY FILLED': 'canceled',
'RSN_DUST': 'rejected',
diff --git a/TaskServer/node_modules/ccxt/js/bithumb.js b/TaskServer/node_modules/ccxt/js/bithumb.js
index 057ea9b0a..88324e947 100644
--- a/TaskServer/node_modules/ccxt/js/bithumb.js
+++ b/TaskServer/node_modules/ccxt/js/bithumb.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -16,7 +16,12 @@ module.exports = class bithumb extends Exchange {
'rateLimit': 500,
'has': {
'CORS': true,
+ 'createOrder': true,
+ 'cancelOrder': true,
+ 'createMarketOrder': true,
'fetchTickers': true,
+ 'fetchOpenOrders': true,
+ 'fetchOrder': true,
'withdraw': true,
},
'urls': {
@@ -48,8 +53,8 @@ module.exports = class bithumb extends Exchange {
'info/ticker',
'info/orders',
'info/user_transactions',
- 'trade/place',
'info/order_detail',
+ 'trade/place',
'trade/cancel',
'trade/btc_withdrawal',
'trade/krw_deposit',
@@ -165,15 +170,53 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
if (limit !== undefined) {
- request['count'] = limit; // max = 50
+ request['count'] = limit; // default 30, max 30
}
const response = await this.publicGetOrderbookCurrency (this.extend (request, params));
- const orderbook = this.safeValue (response, 'data');
- const timestamp = this.safeInteger (orderbook, 'timestamp');
- return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'price', 'quantity');
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "timestamp":"1587621553942",
+ // "payment_currency":"KRW",
+ // "order_currency":"BTC",
+ // "bids":[
+ // {"price":"8652000","quantity":"0.0043"},
+ // {"price":"8651000","quantity":"0.0049"},
+ // {"price":"8650000","quantity":"8.4791"},
+ // ],
+ // "asks":[
+ // {"price":"8654000","quantity":"0.119"},
+ // {"price":"8655000","quantity":"0.254"},
+ // {"price":"8658000","quantity":"0.119"},
+ // ]
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
+ const timestamp = this.safeInteger (data, 'timestamp');
+ return this.parseOrderBook (data, timestamp, 'bids', 'asks', 'price', 'quantity');
}
parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker, fetchTickers
+ //
+ // {
+ // "opening_price":"227100",
+ // "closing_price":"228400",
+ // "min_price":"222300",
+ // "max_price":"230000",
+ // "units_traded":"82618.56075337",
+ // "acc_trade_value":"18767376138.6031",
+ // "prev_closing_price":"227100",
+ // "units_traded_24H":"151871.13484676",
+ // "acc_trade_value_24H":"34247610416.8974",
+ // "fluctate_24H":"8700",
+ // "fluctate_rate_24H":"3.96",
+ // "date":"1587710327264", // fetchTickers inject this
+ // }
+ //
const timestamp = this.safeInteger (ticker, 'date');
let symbol = undefined;
if (market !== undefined) {
@@ -224,9 +267,31 @@ module.exports = class bithumb extends Exchange {
async fetchTickers (symbols = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.publicGetTickerAll (params);
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "BTC":{
+ // "opening_price":"9045000",
+ // "closing_price":"9132000",
+ // "min_price":"8938000",
+ // "max_price":"9168000",
+ // "units_traded":"4619.79967497",
+ // "acc_trade_value":"42021363832.5187",
+ // "prev_closing_price":"9041000",
+ // "units_traded_24H":"8793.5045804",
+ // "acc_trade_value_24H":"78933458515.4962",
+ // "fluctate_24H":"530000",
+ // "fluctate_rate_24H":"6.16"
+ // },
+ // "date":"1587710878669"
+ // }
+ // }
+ //
const result = {};
- const timestamp = this.safeInteger (response['data'], 'date');
- const tickers = this.omit (response['data'], 'date');
+ const data = this.safeValue (response, 'data', {});
+ const timestamp = this.safeInteger (data, 'date');
+ const tickers = this.omit (data, 'date');
const ids = Object.keys (tickers);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
@@ -253,19 +318,72 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
const response = await this.publicGetTickerCurrency (this.extend (request, params));
- return this.parseTicker (response['data'], market);
+ //
+ // {
+ // "status":"0000",
+ // "data":{
+ // "opening_price":"227100",
+ // "closing_price":"228400",
+ // "min_price":"222300",
+ // "max_price":"230000",
+ // "units_traded":"82618.56075337",
+ // "acc_trade_value":"18767376138.6031",
+ // "prev_closing_price":"227100",
+ // "units_traded_24H":"151871.13484676",
+ // "acc_trade_value_24H":"34247610416.8974",
+ // "fluctate_24H":"8700",
+ // "fluctate_rate_24H":"3.96",
+ // "date":"1587710327264"
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
+ return this.parseTicker (data, market);
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "transaction_date":"2020-04-23 22:21:46",
+ // "type":"ask",
+ // "units_traded":"0.0125",
+ // "price":"8667000",
+ // "total":"108337"
+ // }
+ //
+ // fetchOrder (private)
+ //
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // }
+ //
// a workaround for their bug in date format, hours are not 0-padded
- const parts = trade['transaction_date'].split (' ');
- const transaction_date = parts[0];
- let transaction_time = parts[1];
- if (transaction_time.length < 8) {
- transaction_time = '0' + transaction_time;
+ let timestamp = undefined;
+ const transactionDatetime = this.safeString (trade, 'transaction_date');
+ if (transactionDatetime !== undefined) {
+ const parts = transactionDatetime.split (' ');
+ const numParts = parts.length;
+ if (numParts > 1) {
+ const transactionDate = parts[0];
+ let transactionTime = parts[1];
+ if (transactionTime.length < 8) {
+ transactionTime = '0' + transactionTime;
+ }
+ timestamp = this.parse8601 (transactionDate + ' ' + transactionTime);
+ } else {
+ timestamp = this.safeIntegerProduct (trade, 'transaction_date', 0.001);
+ }
+ }
+ if (timestamp !== undefined) {
+ timestamp -= 9 * 3600000; // they report UTC + 9 hours, server in Korean timezone
}
- let timestamp = this.parse8601 (transaction_date + ' ' + transaction_time);
- timestamp -= 9 * 3600000; // they report UTC + 9 hours (server in Korean timezone)
const type = undefined;
let side = this.safeString (trade, 'type');
side = (side === 'ask') ? 'sell' : 'buy';
@@ -276,12 +394,24 @@ module.exports = class bithumb extends Exchange {
}
const price = this.safeFloat (trade, 'price');
const amount = this.safeFloat (trade, 'units_traded');
- let cost = undefined;
- if (amount !== undefined) {
- if (price !== undefined) {
- cost = price * amount;
+ let cost = this.safeFloat (trade, 'total');
+ if (cost === undefined) {
+ if (amount !== undefined) {
+ if (price !== undefined) {
+ cost = price * amount;
+ }
}
}
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'fee');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'fee_currency');
+ const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId);
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ };
+ }
return {
'id': id,
'info': trade,
@@ -295,7 +425,7 @@ module.exports = class bithumb extends Exchange {
'price': price,
'amount': amount,
'cost': cost,
- 'fee': undefined,
+ 'fee': fee,
};
}
@@ -309,57 +439,276 @@ module.exports = class bithumb extends Exchange {
request['count'] = limit; // default 20, max 100
}
const response = await this.publicGetTransactionHistoryCurrency (this.extend (request, params));
- return this.parseTrades (response['data'], market, since, limit);
+ //
+ // {
+ // "status":"0000",
+ // "data":[
+ // {
+ // "transaction_date":"2020-04-23 22:21:46",
+ // "type":"ask",
+ // "units_traded":"0.0125",
+ // "price":"8667000",
+ // "total":"108337"
+ // },
+ // ]
+ // }
+ //
+ const data = this.safeValue (response, 'data', []);
+ return this.parseTrades (data, market, since, limit);
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
- let request = undefined;
- let method = 'privatePostTrade';
+ const request = {
+ 'order_currency': market['id'],
+ 'Payment_currency': market['quote'],
+ 'units': amount,
+ };
+ let method = 'privatePostTradePlace';
if (type === 'limit') {
- request = {
- 'order_currency': market['id'],
- 'Payment_currency': market['quote'],
- 'units': amount,
- 'price': price,
- 'type': (side === 'buy') ? 'bid' : 'ask',
- };
- method += 'Place';
- } else if (type === 'market') {
- request = {
- 'currency': market['id'],
- 'units': amount,
- };
- method += 'Market' + this.capitalize (side);
+ request['price'] = price;
+ request['type'] = (side === 'buy') ? 'bid' : 'ask';
+ } else {
+ method = 'privatePostTradeMarket' + this.capitalize (side);
}
const response = await this[method] (this.extend (request, params));
const id = this.safeString (response, 'order_id');
+ if (id === undefined) {
+ throw new InvalidOrder (this.id + ' createOrder did not return an order id');
+ }
return {
'info': response,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
'id': id,
};
}
+ async fetchOrder (id, symbol = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'order_id': id,
+ 'count': 1,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
+ };
+ const response = await this.privatePostInfoOrderDetail (this.extend (request, params));
+ //
+ // {
+ // "status": "0000",
+ // "data": {
+ // "transaction_date": "1572497603668315",
+ // "type": "bid",
+ // "order_status": "Completed",
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_price": "8601000",
+ // "order_qty": "0.007",
+ // "cancel_date": "",
+ // "cancel_type": "",
+ // "contract": [
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // },
+ // ]
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data');
+ return this.parseOrder (this.extend (data, { 'order_id': id }), market);
+ }
+
+ parseOrderStatus (status) {
+ const statuses = {
+ 'Pending': 'open',
+ 'Completed': 'closed',
+ 'Cancel': 'canceled',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ parseOrder (order, market = undefined) {
+ //
+ // fetchOrder
+ //
+ // {
+ // "transaction_date": "1572497603668315",
+ // "type": "bid",
+ // "order_status": "Completed",
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_price": "8601000",
+ // "order_qty": "0.007",
+ // "cancel_date": "",
+ // "cancel_type": "",
+ // "contract": [
+ // {
+ // "transaction_date": "1572497603902030",
+ // "price": "8601000",
+ // "units": "0.005",
+ // "fee_currency": "KRW",
+ // "fee": "107.51",
+ // "total": "43005"
+ // },
+ // ]
+ // }
+ //
+ // fetchOpenOrders
+ //
+ // {
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_id": "C0101000007408440032",
+ // "order_date": "1571728739360570",
+ // "type": "bid",
+ // "units": "5.0",
+ // "units_remaining": "5.0",
+ // "price": "501000",
+ // }
+ //
+ const timestamp = this.safeIntegerProduct (order, 'order_date', 0.001);
+ const sideProperty = this.safeValue2 (order, 'type', 'side');
+ const side = (sideProperty === 'bid') ? 'buy' : 'sell';
+ const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
+ let price = this.safeFloat2 (order, 'order_price', 'price');
+ let type = 'limit';
+ if (price === 0) {
+ price = undefined;
+ type = 'market';
+ }
+ const amount = this.safeFloat2 (order, 'order_qty', 'units');
+ let remaining = this.safeFloat (order, 'units_remaining');
+ if (remaining === undefined) {
+ if (status === 'closed') {
+ remaining = 0;
+ } else {
+ remaining = amount;
+ }
+ }
+ let filled = undefined;
+ if ((amount !== undefined) && (remaining !== undefined)) {
+ filled = amount - remaining;
+ }
+ let symbol = undefined;
+ const baseId = this.safeString (order, 'order_currency');
+ const quoteId = this.safeString (order, 'payment_currency');
+ const base = this.safeCurrencyCode (baseId);
+ const quote = this.safeCurrencyCode (quoteId);
+ if ((base !== undefined) && (quote !== undefined)) {
+ symbol = base + '/' + quote;
+ }
+ if ((symbol === undefined) && (market !== undefined)) {
+ symbol = market['symbol'];
+ }
+ const rawTrades = this.safeValue (order, 'contract');
+ let trades = undefined;
+ const id = this.safeString (order, 'order_id');
+ if (rawTrades !== undefined) {
+ trades = this.parseTrades (rawTrades, market, undefined, undefined, {
+ 'side': side,
+ 'symbol': symbol,
+ 'order': id,
+ });
+ }
+ return {
+ 'info': order,
+ 'id': id,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
+ 'price': price,
+ 'amount': amount,
+ 'cost': undefined,
+ 'average': undefined,
+ 'filled': filled,
+ 'remaining': remaining,
+ 'status': status,
+ 'fee': undefined,
+ 'trades': trades,
+ };
+ }
+
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders requires a symbol argument');
+ }
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ if (limit === undefined) {
+ limit = 100;
+ }
+ const request = {
+ 'count': limit,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
+ };
+ if (since !== undefined) {
+ request['after'] = since;
+ }
+ const response = await this.privatePostInfoOrders (this.extend (request, params));
+ //
+ // {
+ // "status": "0000",
+ // "data": [
+ // {
+ // "order_currency": "BTC",
+ // "payment_currency": "KRW",
+ // "order_id": "C0101000007408440032",
+ // "order_date": "1571728739360570",
+ // "type": "bid",
+ // "units": "5.0",
+ // "units_remaining": "5.0",
+ // "price": "501000",
+ // }
+ // ]
+ // }
+ //
+ const data = this.safeValue (response, 'data', []);
+ return this.parseOrders (data, market, since, limit);
+ }
+
async cancelOrder (id, symbol = undefined, params = {}) {
const side_in_params = ('side' in params);
if (!side_in_params) {
- throw new ExchangeError (this.id + ' cancelOrder requires a `side` parameter (sell or buy) and a `currency` parameter');
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
- const currency = this.safeString (params, 'currency');
- if (currency === undefined) {
- throw new ExchangeError (this.id + ' cancelOrder requires a `currency` parameter (a currency id)');
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
+ const market = this.market (symbol);
const side = (params['side'] === 'buy') ? 'bid' : 'ask';
params = this.omit (params, [ 'side', 'currency' ]);
+ // https://github.com/ccxt/ccxt/issues/6771
const request = {
'order_id': id,
'type': side,
- 'currency': currency,
+ 'order_currency': market['base'],
+ 'payment_currency': market['quote'],
};
return await this.privatePostTradeCancel (this.extend (request, params));
}
+ cancelUnifiedOrder (order, params = {}) {
+ const request = {
+ 'side': order['side'],
+ };
+ return this.cancelOrder (order['id'], order['symbol'], this.extend (request, params));
+ }
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
this.checkAddress (address);
await this.loadMarkets ();
@@ -372,7 +721,7 @@ module.exports = class bithumb extends Exchange {
if (currency === 'XRP' || currency === 'XMR') {
const destination = this.safeString (params, 'destination');
if ((tag === undefined) && (destination === undefined)) {
- throw new ExchangeError (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
+ throw new ArgumentsRequired (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
} else if (tag !== undefined) {
request['destination'] = tag;
}
diff --git a/TaskServer/node_modules/ccxt/js/bitmart.js b/TaskServer/node_modules/ccxt/js/bitmart.js
index c9a3a9bb3..a25f8aeed 100644
--- a/TaskServer/node_modules/ccxt/js/bitmart.js
+++ b/TaskServer/node_modules/ccxt/js/bitmart.js
@@ -35,6 +35,7 @@ module.exports = class bitmart extends Exchange {
'fetchClosedOrders': true,
'fetchCanceledOrders': true,
'fetchOrder': true,
+ 'signIn': true,
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/61835713-a2662f80-ae85-11e9-9d00-6442919701fd.jpg',
@@ -42,6 +43,7 @@ module.exports = class bitmart extends Exchange {
'www': 'https://www.bitmart.com/',
'doc': 'https://github.com/bitmartexchange/bitmart-official-api-docs',
'referral': 'http://www.bitmart.com/?r=rQCFLh',
+ 'fees': 'https://www.bitmart.com/fee/en',
},
'requiredCredentials': {
'apiKey': true,
diff --git a/TaskServer/node_modules/ccxt/js/bitstamp.js b/TaskServer/node_modules/ccxt/js/bitstamp.js
index 124d385fc..74d767234 100644
--- a/TaskServer/node_modules/ccxt/js/bitstamp.js
+++ b/TaskServer/node_modules/ccxt/js/bitstamp.js
@@ -1134,11 +1134,19 @@ module.exports = class bitstamp extends Exchange {
body = this.urlencode (query);
contentType = 'application/x-www-form-urlencoded';
headers['Content-Type'] = contentType;
+ } else {
+ // sending an empty POST request will trigger
+ // an API0020 error returned by the exchange
+ // therefore for empty requests we send a dummy object
+ // https://github.com/ccxt/ccxt/issues/6846
+ body = this.urlencode ({ 'foo': 'bar' });
+ contentType = 'application/x-www-form-urlencoded';
+ headers['Content-Type'] = contentType;
}
}
const authBody = body ? body : '';
const auth = xAuth + method + url.replace ('https://', '') + contentType + xAuthNonce + xAuthTimestamp + xAuthVersion + authBody;
- const signature = this.encode (this.hmac (this.encode (auth), this.encode (this.secret)));
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret));
headers['X-Auth-Signature'] = signature;
}
}
diff --git a/TaskServer/node_modules/ccxt/js/bitz.js b/TaskServer/node_modules/ccxt/js/bitz.js
index 0bf24b0ee..50fa901e8 100644
--- a/TaskServer/node_modules/ccxt/js/bitz.js
+++ b/TaskServer/node_modules/ccxt/js/bitz.js
@@ -650,7 +650,7 @@ module.exports = class bitz extends Exchange {
}
} else {
if (since !== undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a limit argument if the since argument is specified');
}
}
const response = await this.marketGetKline (this.extend (request, params));
diff --git a/TaskServer/node_modules/ccxt/js/bleutrade.js b/TaskServer/node_modules/ccxt/js/bleutrade.js
index 3bfdc13e9..9bbd8a207 100644
--- a/TaskServer/node_modules/ccxt/js/bleutrade.js
+++ b/TaskServer/node_modules/ccxt/js/bleutrade.js
@@ -73,6 +73,9 @@ module.exports = class bleutrade extends Exchange {
],
},
'v3Private': {
+ 'get': [
+ 'statement',
+ ],
'post': [
'getbalance',
'getbalances',
@@ -189,8 +192,8 @@ module.exports = class bleutrade extends Exchange {
// MarketCurrencyLong: 'Litecoin',
// BaseCurrencyLong: 'Tether' }
const id = this.safeString (market, 'MarketName');
- const baseId = this.safeString (market, 'MarketCurrency');
- const quoteId = this.safeString (market, 'BaseCurrency');
+ const baseId = this.safeString (market, 'MarketAsset');
+ const quoteId = this.safeString (market, 'BaseAsset');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
const symbol = base + '/' + quote;
diff --git a/TaskServer/node_modules/ccxt/js/btctradeua.js b/TaskServer/node_modules/ccxt/js/btctradeua.js
index 8c056885c..553ec77f2 100644
--- a/TaskServer/node_modules/ccxt/js/btctradeua.js
+++ b/TaskServer/node_modules/ccxt/js/btctradeua.js
@@ -18,6 +18,7 @@ module.exports = class btctradeua extends Exchange {
'CORS': false,
'createMarketOrder': false,
'fetchOpenOrders': true,
+ 'signIn': true,
},
'urls': {
'referral': 'https://btc-trade.com.ua/registration/22689',
diff --git a/TaskServer/node_modules/ccxt/js/buda.js b/TaskServer/node_modules/ccxt/js/buda.js
index 3416ad8c4..e92a1617a 100644
--- a/TaskServer/node_modules/ccxt/js/buda.js
+++ b/TaskServer/node_modules/ccxt/js/buda.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied } = require ('./base/errors');
+const { AddressPending, AuthenticationError, ExchangeError, NotSupported, PermissionDenied, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -692,7 +692,7 @@ module.exports = class buda extends Exchange {
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
if (code === undefined) {
- throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
+ throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
}
const currency = this.currency (code);
const request = {
@@ -707,7 +707,7 @@ module.exports = class buda extends Exchange {
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
await this.loadMarkets ();
if (code === undefined) {
- throw new ExchangeError (this.id + ': fetchDeposits() requires a currency code argument');
+ throw new ArgumentsRequired (this.id + ': fetchDeposits() requires a currency code argument');
}
const currency = this.currency (code);
const request = {
diff --git a/TaskServer/node_modules/ccxt/js/bybit.js b/TaskServer/node_modules/ccxt/js/bybit.js
index a27c9eec5..5010ba98c 100644
--- a/TaskServer/node_modules/ccxt/js/bybit.js
+++ b/TaskServer/node_modules/ccxt/js/bybit.js
@@ -4,7 +4,7 @@
const Exchange = require ('./base/Exchange');
const { TICK_SIZE } = require ('./base/functions/number');
-const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce } = require ('./base/errors');
+const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce, NotSupported } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -48,7 +48,7 @@ module.exports = class bybit extends Exchange {
'30m': '30',
'1h': '60',
'2h': '120',
- '3h': '180',
+ '4h': '240',
'6h': '360',
'12h': '720',
'1d': 'D',
@@ -63,6 +63,7 @@ module.exports = class bybit extends Exchange {
'www': 'https://www.bybit.com/',
'doc': [
'https://bybit-exchange.github.io/docs/inverse/',
+ 'https://bybit-exchange.github.io/docs/linear/',
'https://github.com/bybit-exchange',
],
'fees': 'https://help.bybit.com/hc/en-us/articles/360039261154',
@@ -116,6 +117,41 @@ module.exports = class bybit extends Exchange {
'position/trading-stop',
],
},
+ 'publicLinear': {
+ 'get': [
+ 'kline',
+ 'recent-trading-records',
+ 'funding/prev-funding-rate',
+ 'mark-price-kline',
+ ],
+ },
+ 'privateLinear': {
+ 'get': [
+ 'order/list',
+ 'order/search',
+ 'stop-order/list',
+ 'stop-order/search',
+ 'position/list',
+ 'position/set-auto-add-margin',
+ 'position/set-leverage',
+ 'position/switch-isolated',
+ 'position/trading-stop',
+ 'position/add-margin',
+ 'trade/execution/list',
+ 'trade/closed-pnl/list',
+ 'risk-limit',
+ 'funding/prev-funding',
+ 'funding/predicted-funding',
+ ],
+ 'post': [
+ 'order/create',
+ 'order/cancel',
+ 'order/cancelAll',
+ 'stop-order/create',
+ 'stop-order/cancel',
+ 'stop-order/cancelAll',
+ ],
+ },
'position': {
'post': [
'change-position-margin',
@@ -227,6 +263,9 @@ module.exports = class bybit extends Exchange {
},
'precisionMode': TICK_SIZE,
'options': {
+ 'marketTypes': {
+ 'BTC/USDT': 'linear',
+ },
'code': 'BTC',
'fetchBalance': {
'code': 'BTC',
@@ -309,6 +348,8 @@ module.exports = class bybit extends Exchange {
// }
//
const markets = this.safeValue (response, 'result', []);
+ const options = this.safeValue (this.options, 'fetchMarkets', {});
+ const linearQuoteCurrencies = this.safeValue (options, 'linear', { 'USDT': true });
const result = [];
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
@@ -317,6 +358,8 @@ module.exports = class bybit extends Exchange {
const quoteId = this.safeString (market, 'quote_currency');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
+ const linear = (quote in linearQuoteCurrencies);
+ const inverse = !linear;
const symbol = base + '/' + quote;
const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {});
const priceFilter = this.safeValue (market, 'price_filter', {});
@@ -333,6 +376,12 @@ module.exports = class bybit extends Exchange {
'precision': precision,
'taker': this.safeFloat (market, 'taker_fee'),
'maker': this.safeFloat (market, 'maker_fee'),
+ 'type': 'future',
+ 'spot': false,
+ 'future': true,
+ 'option': false,
+ 'linear': linear,
+ 'inverse': inverse,
'limits': {
'amount': {
'min': this.safeFloat (lotSizeFilter, 'min_trading_qty'),
@@ -347,10 +396,6 @@ module.exports = class bybit extends Exchange {
'max': undefined,
},
},
- 'type': 'future',
- 'spot': false,
- 'future': true,
- 'option': false,
'info': market,
});
}
@@ -610,13 +655,25 @@ module.exports = class bybit extends Exchange {
// turnover: '162.32773718999994'
// },
//
+ // {
+ // "id":143536,
+ // "symbol":"BTCUSDT",
+ // "period":"15",
+ // "start_at":1587883500,
+ // "volume":1.035,
+ // "open":7540.5,
+ // "high":7541,
+ // "low":7540.5,
+ // "close":7541
+ // }
+ //
return [
- this.safeTimestamp (ohlcv, 'open_time'),
+ this.safeTimestamp2 (ohlcv, 'open_time', 'start_at'),
this.safeFloat (ohlcv, 'open'),
this.safeFloat (ohlcv, 'high'),
this.safeFloat (ohlcv, 'low'),
this.safeFloat (ohlcv, 'close'),
- this.safeFloat (ohlcv, 'turnover'),
+ this.safeFloat2 (ohlcv, 'turnover', 'volume'),
];
}
@@ -641,7 +698,13 @@ module.exports = class bybit extends Exchange {
if (limit !== undefined) {
request['limit'] = limit; // max 200, default 200
}
- const response = await this.publicGetKlineList (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'publicLinearGetKline' : 'publicGetKlineList';
+ const response = await this[method] (this.extend (request, params));
+ //
+ // inverse perpetual BTC/USD
+ //
// {
// ret_code: 0,
// ret_msg: 'OK',
@@ -662,6 +725,30 @@ module.exports = class bybit extends Exchange {
// ],
// time_now: '1583953082.397330'
// }
+ //
+ // linear perpetual BTC/USDT
+ //
+ // {
+ // "ret_code":0,
+ // "ret_msg":"OK",
+ // "ext_code":"",
+ // "ext_info":"",
+ // "result":[
+ // {
+ // "id":143536,
+ // "symbol":"BTCUSDT",
+ // "period":"15",
+ // "start_at":1587883500,
+ // "volume":1.035,
+ // "open":7540.5,
+ // "high":7541,
+ // "low":7540.5,
+ // "close":7541
+ // }
+ // ],
+ // "time_now":"1587884120.168077"
+ // }
+ //
const result = this.safeValue (response, 'result', {});
return this.parseOHLCVs (result, market, timeframe, since, limit);
}
@@ -688,6 +775,8 @@ module.exports = class bybit extends Exchange {
// "exec_id": "256e5ef8-abfe-5772-971b-f944e15e0d68",
// "exec_price": "8178.5",
// "exec_qty": 1,
+ // // the docs say the exec_time field is "abandoned" now
+ // // the user should use "trade_time_ms"
// "exec_time": "1571676941.70682",
// "exec_type": "Trade", //Exec Type Enum
// "exec_value": "0.00012227",
@@ -702,30 +791,35 @@ module.exports = class bybit extends Exchange {
// "order_type": "Market", //Order Type Enum
// "side": "Buy", //Side Enum
// "symbol": "BTCUSD", //Symbol Enum
- // "user_id": 1
+ // "user_id": 1,
+ // "trade_time_ms": 1577480599000
// }
//
const id = this.safeString2 (trade, 'id', 'exec_id');
let symbol = undefined;
let base = undefined;
const marketId = this.safeString (trade, 'symbol');
+ let amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
+ let cost = this.safeFloat (trade, 'exec_value');
+ const price = this.safeFloat2 (trade, 'price', 'exec_price');
if (marketId in this.markets_by_id) {
market = this.markets_by_id[marketId];
symbol = market['symbol'];
base = market['base'];
}
- if ((symbol === undefined) && (market !== undefined)) {
- symbol = market['symbol'];
- base = market['base'];
+ if (market !== undefined) {
+ if (symbol === undefined) {
+ symbol = market['symbol'];
+ base = market['base'];
+ }
+ // if private trade
+ if ('exec_fee' in trade) {
+ if (market['inverse']) {
+ amount = this.safeFloat (trade, 'exec_value');
+ cost = this.safeFloat (trade, 'exec_qty');
+ }
+ }
}
- let timestamp = this.parse8601 (this.safeString (trade, 'time'));
- if (timestamp === undefined) {
- timestamp = this.safeTimestamp (trade, 'exec_time');
- }
- const side = this.safeStringLower (trade, 'side');
- const price = this.safeFloat2 (trade, 'price', 'exec_price');
- const amount = this.safeFloat2 (trade, 'qty', 'exec_qty');
- let cost = this.safeFloat (trade, 'exec_value');
if (cost === undefined) {
if (amount !== undefined) {
if (price !== undefined) {
@@ -733,6 +827,11 @@ module.exports = class bybit extends Exchange {
}
}
}
+ let timestamp = this.parse8601 (this.safeString (trade, 'time'));
+ if (timestamp === undefined) {
+ timestamp = this.safeInteger (trade, 'trade_time_ms');
+ }
+ const side = this.safeStringLower (trade, 'side');
const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind');
const takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker';
const feeCost = this.safeFloat (trade, 'exec_fee');
@@ -771,7 +870,10 @@ module.exports = class bybit extends Exchange {
if (limit !== undefined) {
request['count'] = limit; // default 500, max 1000
}
- const response = await this.publicGetTradingRecords (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'publicLinearGetRecentTradingRecords' : 'publicGetTradingRecords';
+ const response = await this[method] (this.extend (request, params));
//
// {
// ret_code: 0,
@@ -885,8 +987,8 @@ module.exports = class bybit extends Exchange {
// "last_exec_time": 0,
// "last_exec_price": 0,
// "leaves_qty": 1,
- // "cum_exec_qty": 0,
- // "cum_exec_value": 0,
+ // "cum_exec_qty": 0, // in contracts, where 1 contract = 1 quote currency unit (USD for inverse contracts)
+ // "cum_exec_value": 0, // in contract's underlying currency (BTC for inverse contracts)
// "cum_exec_fee": 0,
// "reject_reason": "",
// "order_link_id": "",
@@ -894,18 +996,69 @@ module.exports = class bybit extends Exchange {
// "updated_at": "2019-11-30T11:03:43.455Z"
// }
//
+ // fetchOrder
+ //
+ // {
+ // "user_id" : 599946,
+ // "symbol" : "BTCUSD",
+ // "side" : "Buy",
+ // "order_type" : "Limit",
+ // "price" : "7948",
+ // "qty" : 10,
+ // "time_in_force" : "GoodTillCancel",
+ // "order_status" : "Filled",
+ // "ext_fields" : {
+ // "o_req_num" : -1600687220498,
+ // "xreq_type" : "x_create"
+ // },
+ // "last_exec_time" : "1588150113.968422",
+ // "last_exec_price" : "7948",
+ // "leaves_qty" : 0,
+ // "leaves_value" : "0",
+ // "cum_exec_qty" : 10,
+ // "cum_exec_value" : "0.00125817",
+ // "cum_exec_fee" : "-0.00000031",
+ // "reject_reason" : "",
+ // "cancel_type" : "",
+ // "order_link_id" : "",
+ // "created_at" : "2020-04-29T08:45:24.399146Z",
+ // "updated_at" : "2020-04-29T08:48:33.968422Z",
+ // "order_id" : "dd2504b9-0157-406a-99e1-efa522373944"
+ // }
+ //
+ const marketId = this.safeString (order, 'symbol');
+ let symbol = undefined;
+ let base = undefined;
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
const timestamp = this.parse8601 (this.safeString (order, 'created_at'));
const id = this.safeString (order, 'order_id');
const price = this.safeFloat (order, 'price');
const average = this.safeFloat (order, 'average_price');
- const amount = this.safeFloat (order, 'qty');
- let filled = this.safeFloat (order, 'cum_exec_qty');
- let remaining = this.safeFloat (order, 'leaves_qty');
+ let amount = undefined;
+ let cost = undefined;
+ let filled = undefined;
+ let remaining = undefined;
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ base = market['base'];
+ if (market['inverse']) {
+ cost = this.safeFloat (order, 'cum_exec_qty');
+ filled = this.safeFloat (order, 'cum_exec_value');
+ remaining = this.safeFloat (order, 'leaves_value');
+ amount = this.sum (filled, remaining);
+ } else {
+ amount = this.safeFloat (order, 'qty');
+ cost = this.safeFloat (order, 'cum_exec_value');
+ filled = this.safeFloat (order, 'cum_exec_qty');
+ remaining = this.safeFloat (order, 'leaves_qty');
+ }
+ }
let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time');
if (lastTradeTimestamp === 0) {
lastTradeTimestamp = undefined;
}
- let cost = this.safeFloat (order, 'cum_exec_value');
if ((filled === undefined) && (amount !== undefined) && (remaining !== undefined)) {
filled = amount - remaining;
}
@@ -920,22 +1073,6 @@ module.exports = class bybit extends Exchange {
}
}
const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
- const marketId = this.safeString (order, 'symbol');
- let symbol = undefined;
- let base = undefined;
- if (marketId in this.markets_by_id) {
- market = this.markets_by_id[marketId];
- symbol = market['symbol'];
- base = market['base'];
- }
- if (market !== undefined) {
- if (symbol === undefined) {
- symbol = market['symbol'];
- }
- if (base === undefined) {
- base = market['base'];
- }
- }
const side = this.safeStringLower (order, 'side');
let feeCost = this.safeFloat (order, 'cum_exec_fee');
let fee = undefined;
@@ -987,7 +1124,9 @@ module.exports = class bybit extends Exchange {
// conditional orders ---------------------------------------------
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
};
- let method = 'privateGetOrder';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearGetOrderSearch' : 'privateGetOrder';
const stopOrderId = this.safeString (params, 'stop_order_id');
if (stopOrderId === undefined) {
const orderLinkId = this.safeString (params, 'order_link_id');
@@ -995,7 +1134,7 @@ module.exports = class bybit extends Exchange {
request['order_id'] = id;
}
} else {
- method = 'privateGetStopOrder';
+ method = (marketType === 'linear') ? 'privateLinearGetStopOrderSearch' : 'privateGetStopOrder';
}
const response = await this[method] (this.extend (request, params));
//
@@ -1107,12 +1246,14 @@ module.exports = class bybit extends Exchange {
}
const stopPx = this.safeValue (params, 'stop_px');
const basePrice = this.safeValue (params, 'base_price');
- let method = 'privatePostOrderCreate';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearPostOrderCreate' : 'privatePostOrderCreate';
if (stopPx !== undefined) {
if (basePrice === undefined) {
throw new ArgumentsRequired (this.id + ' createOrder requires both the stop_px and base_price params for a conditional ' + type + ' order');
} else {
- method = 'openapiPostStopOrderCreate';
+ method = (marketType === 'linear') ? 'privateLinearPostStopOrderCreate' : 'openapiPostStopOrderCreate';
request['stop_px'] = this.priceToPrecision (symbol, stopPx);
request['base_price'] = this.priceToPrecision (symbol, basePrice);
params = this.omit (params, [ 'stop_px', 'base_price' ]);
@@ -1206,6 +1347,11 @@ module.exports = class bybit extends Exchange {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' editOrder requires an symbol argument');
}
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ if (marketType === 'linear') {
+ throw new NotSupported (this.id + ' does not support editOrder for ' + marketType + ' ' + symbol + ' market type');
+ }
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
@@ -1283,7 +1429,9 @@ module.exports = class bybit extends Exchange {
// conditional orders ---------------------------------------------
// 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
};
- let method = 'privatePostOrderCancel';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeValue (marketTypes, symbol);
+ let method = (marketType === 'linear') ? 'privateLinearPostOrderCancel' : 'privatePostOrderCancel';
const stopOrderId = this.safeString (params, 'stop_order_id');
if (stopOrderId === undefined) {
const orderLinkId = this.safeString (params, 'order_link_id');
@@ -1291,7 +1439,7 @@ module.exports = class bybit extends Exchange {
request['order_id'] = id;
}
} else {
- method = 'openapiPostStopOrderCancel';
+ method = (marketType === 'linear') ? 'privateLinearPostStopOrderCancel' : 'openapiPostStopOrderCancel';
}
const response = await this[method] (this.extend (request, params));
const result = this.safeValue (response, 'result', {});
@@ -1308,7 +1456,10 @@ module.exports = class bybit extends Exchange {
'symbol': market['id'],
};
const options = this.safeValue (this.options, 'cancelAllOrders');
- const method = this.safeString (options, 'method', 'privatePostOrderCancelAll');
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const defaultMethod = (marketType === 'linear') ? 'privateLinearPostOrderCancelAll' : 'privatePostOrderCancelAll';
+ const method = this.safeString (options, 'method', defaultMethod);
const response = await this[method] (this.extend (request, params));
const result = this.safeValue (response, 'result', []);
return this.parseOrders (result, market);
@@ -1337,7 +1488,9 @@ module.exports = class bybit extends Exchange {
request['limit'] = limit;
}
const options = this.safeValue (this.options, 'fetchOrders', {});
- let defaultMethod = 'openapiGetOrderList';
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ let defaultMethod = (marketType === 'linear') ? 'privateLinearGetOrderList' : 'openapiGetOrderList';
let query = params;
if (('stop_order_id' in params) || ('stop_order_status' in params)) {
let stopOrderStatus = this.safeValue (params, 'stopOrderStatus');
@@ -1348,7 +1501,7 @@ module.exports = class bybit extends Exchange {
request['stop_order_status'] = stopOrderStatus;
query = this.omit (params, 'stop_order_status');
}
- defaultMethod = 'openapiGetStopOrderList';
+ defaultMethod = (marketType === 'linear') ? 'privateLinearGetStopOrderList' : 'openapiGetStopOrderList';
}
const method = this.safeString (options, 'method', defaultMethod);
const response = await this[method] (this.extend (request, query));
@@ -1524,12 +1677,15 @@ module.exports = class bybit extends Exchange {
request['symbol'] = market['id'];
}
if (since !== undefined) {
- request['start_time'] = parseInt (since / 1000);
+ request['start_time'] = since;
}
if (limit !== undefined) {
request['limit'] = limit; // default 20, max 50
}
- const response = await this.privateGetExecutionList (this.extend (request, params));
+ const marketTypes = this.safeValue (this.options, 'marketTypes', {});
+ const marketType = this.safeString (marketTypes, symbol);
+ const method = (marketType === 'linear') ? 'privateLinearGetTradeExecutionList' : 'privateGetExecutionList';
+ const response = await this[method] (this.extend (request, params));
//
// {
// "ret_code": 0,
@@ -1864,6 +2020,11 @@ module.exports = class bybit extends Exchange {
if (Object.keys (params).length) {
request += '?' + this.rawencode (params);
}
+ } else if (api === 'publicLinear') {
+ request = '/public/linear/' + request;
+ if (Object.keys (params).length) {
+ request += '?' + this.rawencode (params);
+ }
} else {
this.checkRequiredCredentials ();
if (api === 'openapi') {
@@ -1871,14 +2032,16 @@ module.exports = class bybit extends Exchange {
} else if (api === 'private') {
// private v2
request = '/' + this.version + '/' + api + '/' + request;
+ } else if (api === 'privateLinear') {
+ request = '/private/linear/' + request;
} else {
// position, user
- request += '/' + api + '/' + request;
+ request = '/' + api + '/' + request;
}
const timestamp = this.nonce ();
const query = this.extend (params, {
'api_key': this.apiKey,
- 'recvWindow': this.options['recvWindow'],
+ 'recv_window': this.options['recvWindow'],
'timestamp': timestamp,
});
const auth = this.rawencode (this.keysort (query));
diff --git a/TaskServer/node_modules/ccxt/js/bytetrade.js b/TaskServer/node_modules/ccxt/js/bytetrade.js
index 3019af02f..b0d50b5cc 100644
--- a/TaskServer/node_modules/ccxt/js/bytetrade.js
+++ b/TaskServer/node_modules/ccxt/js/bytetrade.js
@@ -47,9 +47,15 @@ module.exports = class bytetrade extends Exchange {
'1M': '1M',
},
'urls': {
- 'test': 'https://api-v2-test.byte-trade.com',
+ 'test': {
+ 'market': 'https://api-v2-test.byte-trade.com',
+ 'public': 'https://api-v2-test.byte-trade.com',
+ },
'logo': 'https://user-images.githubusercontent.com/1294454/67288762-2f04a600-f4e6-11e9-9fd6-c60641919491.jpg',
- 'api': 'https://api-v2.byte-trade.com',
+ 'api': {
+ 'market': 'https://api-v2.bytetrade.com',
+ 'public': 'https://api-v2.bytetrade.com',
+ },
'www': 'https://www.byte-trade.com',
'doc': 'https://github.com/Bytetrade/bytetrade-official-api-docs/wiki',
},
@@ -1222,7 +1228,7 @@ module.exports = class bytetrade extends Exchange {
this.numberToLE (address.length, 1),
this.stringToBinary (this.encode (address)),
this.numberToLE (parseInt (coinId), 4),
- this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
+ this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
this.numberToLE (1, 1),
this.numberToLE (this.integerDivide (assetFee, eightBytes), 8),
@@ -1255,7 +1261,7 @@ module.exports = class bytetrade extends Exchange {
this.numberToLE (middleAddress.length, 1),
this.stringToBinary (this.encode (middleAddress)),
this.numberToLE (parseInt (coinId), 4),
- this.numberToLE (Math.floor (parseInt (parseFloat (this.integerDivide (amountChain, eightBytes)))), 8),
+ this.numberToLE (this.integerDivide (amountChain, eightBytes), 8),
this.numberToLE (this.integerModulo (amountChain, eightBytes), 8),
this.numberToLE (0, 1),
this.numberToLE (1, 1),
@@ -1358,7 +1364,7 @@ module.exports = class bytetrade extends Exchange {
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- let url = this.urls['api'];
+ let url = this.urls['api'][api];
url += '/' + path;
if (Object.keys (params).length) {
url += '?' + this.urlencode (params);
diff --git a/TaskServer/node_modules/ccxt/js/cex.js b/TaskServer/node_modules/ccxt/js/cex.js
index 24efe1a0e..dd8ab9391 100644
--- a/TaskServer/node_modules/ccxt/js/cex.js
+++ b/TaskServer/node_modules/ccxt/js/cex.js
@@ -564,9 +564,45 @@ module.exports = class cex extends Exchange {
request['order_type'] = type;
}
const response = await this.privatePostPlaceOrderPair (this.extend (request, params));
+ //
+ // {
+ // "id": "12978363524",
+ // "time": 1586610022259,
+ // "type": "buy",
+ // "price": "0.033934",
+ // "amount": "0.10722802",
+ // "pending": "0.10722802",
+ // "complete": false
+ // }
+ //
+ const placedAmount = this.safeFloat (response, 'amount');
+ const remaining = this.safeFloat (response, 'pending');
+ const timestamp = this.safeValue (response, 'time');
+ const complete = this.safeValue (response, 'complete');
+ const status = complete ? 'closed' : 'open';
+ let filled = undefined;
+ if ((placedAmount !== undefined) && (remaining !== undefined)) {
+ filled = Math.max (placedAmount - remaining, 0);
+ }
return {
+ 'id': this.safeString (response, 'id'),
'info': response,
- 'id': response['id'],
+ 'clientOrderId': undefined,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'type': type,
+ 'side': this.safeString (response, 'type'),
+ 'symbol': symbol,
+ 'status': status,
+ 'price': this.safeFloat (response, 'price'),
+ 'amount': placedAmount,
+ 'cost': undefined,
+ 'average': undefined,
+ 'remaining': remaining,
+ 'filled': filled,
+ 'fee': undefined,
+ 'trades': undefined,
};
}
diff --git a/TaskServer/node_modules/ccxt/js/coinmate.js b/TaskServer/node_modules/ccxt/js/coinmate.js
index 0046f4303..6e5196f01 100644
--- a/TaskServer/node_modules/ccxt/js/coinmate.js
+++ b/TaskServer/node_modules/ccxt/js/coinmate.js
@@ -561,6 +561,7 @@ module.exports = class coinmate extends Exchange {
const statuses = {
'FILLED': 'closed',
'CANCELLED': 'canceled',
+ 'PARTIALLY_FILLED': 'open',
'OPEN': 'open',
};
return this.safeString (statuses, status, status);
@@ -623,12 +624,15 @@ module.exports = class coinmate extends Exchange {
const price = this.safeFloat (order, 'price');
const amount = this.safeFloat2 (order, 'originalAmount', 'amount');
const remaining = this.safeFloat (order, 'remainingAmount', amount);
- const status = this.parseOrderStatus (this.safeString (order, 'status'));
+ let status = this.parseOrderStatus (this.safeString (order, 'status'));
const type = this.parseOrderType (this.safeString (order, 'orderTradeType'));
let filled = undefined;
let cost = undefined;
if ((amount !== undefined) && (remaining !== undefined)) {
- filled = amount - remaining;
+ filled = Math.min (amount - remaining, 0);
+ if (remaining === 0) {
+ status = 'closed';
+ }
if (price !== undefined) {
cost = filled * price;
}
diff --git a/TaskServer/node_modules/ccxt/js/crex24.js b/TaskServer/node_modules/ccxt/js/crex24.js
index cb448a0ff..c99799c7e 100644
--- a/TaskServer/node_modules/ccxt/js/crex24.js
+++ b/TaskServer/node_modules/ccxt/js/crex24.js
@@ -129,7 +129,6 @@ module.exports = class crex24 extends Exchange {
'fetchClosedOrdersMethod': 'tradingGetOrderHistory', // or 'tradingGetActiveOrders'
'fetchTickersMethod': 'publicGetTicker24hr',
'defaultTimeInForce': 'GTC', // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
- 'defaultLimitOrderType': 'limit', // or 'limit_maker'
'hasAlreadyAuthenticatedSuccessfully': false,
'warnOnFetchOpenOrdersWithoutSymbol': true,
'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision
diff --git a/TaskServer/node_modules/ccxt/js/deribit.js b/TaskServer/node_modules/ccxt/js/deribit.js
index 04f0380a8..6f4827691 100644
--- a/TaskServer/node_modules/ccxt/js/deribit.js
+++ b/TaskServer/node_modules/ccxt/js/deribit.js
@@ -525,11 +525,13 @@ module.exports = class deribit extends Exchange {
'info': response,
};
const balance = this.safeValue (response, 'result', {});
+ const currencyId = this.safeString (balance, 'currency');
+ const currencyCode = this.safeCurrencyCode (currencyId);
const account = this.account ();
account['free'] = this.safeFloat (balance, 'availableFunds');
account['used'] = this.safeFloat (balance, 'maintenanceMargin');
account['total'] = this.safeFloat (balance, 'equity');
- result[code] = account;
+ result[currencyCode] = account;
return this.parseBalance (result);
}
@@ -883,7 +885,7 @@ module.exports = class deribit extends Exchange {
// M = maker, T = taker, MT = both
takerOrMaker = (liquidity === 'M') ? 'maker' : 'taker';
}
- const feeCost = this.safeFloat (trade, 'feeCost');
+ const feeCost = this.safeFloat (trade, 'fee');
let fee = undefined;
if (feeCost !== undefined) {
const feeCurrencyId = this.safeString (trade, 'fee_currency');
diff --git a/TaskServer/node_modules/ccxt/js/exmo.js b/TaskServer/node_modules/ccxt/js/exmo.js
index dcf0f2036..6cc36522d 100644
--- a/TaskServer/node_modules/ccxt/js/exmo.js
+++ b/TaskServer/node_modules/ccxt/js/exmo.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded } = require ('./base/errors');
+const { ArgumentsRequired, ExchangeError, OrderNotFound, AuthenticationError, InsufficientFunds, InvalidOrder, InvalidNonce, NotSupported, OnMaintenance, RateLimitExceeded, BadRequest, PermissionDenied } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -14,7 +14,7 @@ module.exports = class exmo extends Exchange {
'name': 'EXMO',
'countries': [ 'ES', 'RU' ], // Spain, Russia
'rateLimit': 350, // once every 350 ms ≈ 180 requests per minute ≈ 3 requests per second
- 'version': 'v1',
+ 'version': 'v1.1',
'has': {
'CORS': false,
'fetchClosedOrders': 'emulated',
@@ -32,6 +32,21 @@ module.exports = class exmo extends Exchange {
'fetchFundingFees': true,
'fetchCurrencies': true,
'fetchTransactions': true,
+ 'fetchOHLCV': true,
+ },
+ 'timeframes': {
+ '1m': '1',
+ '5m': '5',
+ '15m': '15',
+ '30m': '30',
+ '45m': '45',
+ '1h': '60',
+ '2h': '120',
+ '3h': '180',
+ '4h': '240',
+ '1d': 'D',
+ '1w': 'W',
+ '1M': 'M',
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/27766491-1b0ea956-5eda-11e7-9225-40d67b481b8d.jpg',
@@ -62,6 +77,7 @@ module.exports = class exmo extends Exchange {
'pair_settings',
'ticker',
'trades',
+ 'candles_history',
],
},
'private': {
@@ -69,6 +85,8 @@ module.exports = class exmo extends Exchange {
'user_info',
'order_create',
'order_cancel',
+ 'stop_market_order_create',
+ 'stop_market_order_cancel',
'user_open_orders',
'user_trades',
'user_cancelled_orders',
@@ -103,86 +121,90 @@ module.exports = class exmo extends Exchange {
'error': '',
'data': {
'limits': [
- { 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'ALGO/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'ALGO/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '50' },
+ { 'pair': 'ATOM/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '50000000' },
+ { 'pair': 'ATOM/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'BTC/USD', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
- { 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
- { 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
- { 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
- { 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
- { 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
- { 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
- { 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
- { 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
- { 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
- { 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'BTC/RUB', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '2000000', 'min_a': '10', 'max_a': '50000000' },
{ 'pair': 'BTC/EUR', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
{ 'pair': 'BTC/UAH', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '15000000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'BTC/GBP', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '30000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ETH/GBP', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'XRP/GBP', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'USDT/GBP', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'BTC/PLN', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '20000000', 'min_a': '50', 'max_a': '2000000' },
{ 'pair': 'BTC/TRY', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1', 'max_p': '800000', 'min_a': '40', 'max_a': '6000000' },
+ { 'pair': 'BTC/KZT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '1000', 'max_p': '12000000', 'min_a': '1000', 'max_a': '100000000' },
{ 'pair': 'BTC/USDT', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.01', 'max_p': '30000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/BTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ETH/USD', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/RUB', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '100000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
+ { 'pair': 'XRP/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'XRP/USD', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/RUB', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '50000000' },
{ 'pair': 'ADA/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ADA/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.001', 'max_a': '5000' },
{ 'pair': 'ADA/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
- { 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
- { 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '10000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'ALGO/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ALGO/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'ALGO/EUR', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'ATOM/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'ATOM/EUR', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'BCH/USD', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '30000', 'min_a': '0.0001', 'max_a': '500000' },
+ { 'pair': 'BCH/RUB', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '2000000', 'min_a': '0.0001', 'max_a': '50000000' },
+ { 'pair': 'BCH/EUR', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'BCH/UAH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.1', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'BCH/BTC', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '5', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'BCH/ETH', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.0000001', 'max_p': '200', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'BCH/USDT', 'min_q': '0.003', 'max_q': '5000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'BTCZ/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'BTG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'BTG/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'BTG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.01', 'max_a': '5000' },
+ { 'pair': 'BTT/RUB', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'BTT/UAH', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'BTT/BTC', 'min_q': '1', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'CRON/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'CRON/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
+ { 'pair': 'CRON/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'CRON/EXM', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'DAI/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'DAI/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '0.5', 'max_a': '30000000' },
{ 'pair': 'DAI/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
{ 'pair': 'DAI/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'DASH/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'DASH/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
+ { 'pair': 'DASH/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '200000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'DASH/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'DASH/USDT', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.01', 'max_p': '5000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'DCR/RUB', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '3000000' },
{ 'pair': 'DCR/UAH', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.25', 'max_a': '1000000' },
{ 'pair': 'DCR/BTC', 'min_q': '0.01', 'max_q': '50000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '1000000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
- { 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'DOGE/USD', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'DOGE/BTC', 'min_q': '100', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'DXT/USD', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'DXT/BTC', 'min_q': '100', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'EOS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'EOS/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'EOS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETC/USD', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'ETC/RUB', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '0.01', 'max_a': '50000000' },
+ { 'pair': 'ETC/BTC', 'min_q': '0.2', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '0.5', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ETH/EUR', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/UAH', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '1000000', 'min_a': '90', 'max_a': '15000000' },
{ 'pair': 'ETH/PLN', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '2000000' },
{ 'pair': 'ETH/TRY', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.1', 'max_p': '80000', 'min_a': '10', 'max_a': '6000000' },
+ { 'pair': 'ETH/KZT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '4', 'max_p': '40000000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/USDT', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'ETH/LTC', 'min_q': '0.001', 'max_q': '5000', 'min_p': '0.00000001', 'max_p': '100000', 'min_a': '0.05', 'max_a': '100000' },
- { 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
- { 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
- { 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETZ/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '10' },
+ { 'pair': 'ETZ/ETH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ETZ/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '1000' },
+ { 'pair': 'EXM/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'EXM/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
+ { 'pair': 'GAS/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'GAS/BTC', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'GNT/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'GNT/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
{ 'pair': 'GUSD/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
@@ -197,84 +219,94 @@ module.exports = class exmo extends Exchange {
{ 'pair': 'KICK/USDT', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '100000' },
{ 'pair': 'KICK/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
{ 'pair': 'KICK/ETH', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '5000' },
- { 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
- { 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
- { 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
- { 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
- { 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
- { 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'LSK/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.1', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'LSK/RUB', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '50000000' },
+ { 'pair': 'LSK/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.0015', 'max_a': '100' },
+ { 'pair': 'LTC/USD', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'LTC/RUB', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '150', 'max_a': '50000000' },
+ { 'pair': 'LTC/EUR', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '3', 'max_a': '500000' },
+ { 'pair': 'LTC/UAH', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.01', 'max_p': '300000', 'min_a': '5', 'max_a': '18000000' },
+ { 'pair': 'LTC/BTC', 'min_q': '0.05', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'MKR/BTC', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '100', 'min_a': '0.000001', 'max_a': '100' },
{ 'pair': 'MKR/DAI', 'min_q': '0.0001', 'max_q': '1000', 'min_p': '0.5', 'max_p': '500000', 'min_a': '0.005', 'max_a': '500000' },
- { 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
- { 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
+ { 'pair': 'MNC/USD', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'MNC/BTC', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '100' },
+ { 'pair': 'MNC/ETH', 'min_q': '10', 'max_q': '500000000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '1000' },
{ 'pair': 'MNX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
{ 'pair': 'MNX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'MNX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
- { 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
- { 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
- { 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
- { 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
- { 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
- { 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
+ { 'pair': 'NEO/USD', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.01', 'max_p': '50000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'NEO/RUB', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1500000', 'min_a': '50', 'max_a': '50000000' },
+ { 'pair': 'NEO/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'OMG/USD', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'OMG/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'OMG/ETH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
+ { 'pair': 'ONG/EXM', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '15000000' },
+ { 'pair': 'ONG/BTC', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
+ { 'pair': 'ONG/RUB', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '250000' },
+ { 'pair': 'ONG/UAH', 'min_q': '1', 'max_q': '1000000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '50', 'max_a': '6000000' },
+ { 'pair': 'ONT/EXM', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '15000000' },
+ { 'pair': 'ONT/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
+ { 'pair': 'ONT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '100', 'max_a': '6000000' },
+ { 'pair': 'ONT/UAH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '100000', 'min_a': '200', 'max_a': '250000' },
+ { 'pair': 'PTI/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '600000', 'min_a': '10', 'max_a': '600000' },
+ { 'pair': 'PTI/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.000001', 'max_a': '10' },
+ { 'pair': 'PTI/EOS', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0000001', 'max_p': '5000', 'min_a': '0.01', 'max_a': '20000' },
+ { 'pair': 'PTI/USDT', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '10000', 'min_a': '0.01', 'max_a': '100000' },
+ { 'pair': 'QTUM/USD', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '10000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'QTUM/BTC', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'QTUM/ETH', 'min_q': '0.1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
{ 'pair': 'ROOBEE/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
- { 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
- { 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'SMART/USD', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'SMART/RUB', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.0001', 'max_p': '100000', 'min_a': '10', 'max_a': '50000000' },
+ { 'pair': 'SMART/EUR', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.000001', 'max_p': '1000', 'min_a': '1', 'max_a': '500000' },
+ { 'pair': 'SMART/BTC', 'min_q': '10', 'max_q': '100000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '100' },
+ { 'pair': 'TRX/USD', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'TRX/EUR', 'min_q': '0.01', 'max_q': '50000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'TRX/RUB', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'TRX/UAH', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.000001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'TRX/BTC', 'min_q': '1', 'max_q': '50000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'USDC/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'USDC/BTC', 'min_q': '1', 'max_q': '500000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
{ 'pair': 'USDC/ETH', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '1000' },
{ 'pair': 'USDC/USDT', 'min_q': '1', 'max_q': '500000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '3', 'max_a': '500000' },
{ 'pair': 'USDT/USD', 'min_q': '1', 'max_q': '500000', 'min_p': '0.5', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'USDT/RUB', 'min_q': '1', 'max_q': '500000', 'min_p': '0.01', 'max_p': '1000', 'min_a': '10', 'max_a': '50000000' },
- { 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '100000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '100000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
+ { 'pair': 'USDT/EUR', 'min_q': '0.01', 'max_q': '500000', 'min_p': '0.1', 'max_p': '10', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'USDT/UAH', 'min_q': '0.01', 'max_q': '500000', 'min_p': '1', 'max_p': '3000', 'min_a': '2', 'max_a': '15000000' },
+ { 'pair': 'USDT/KZT', 'min_q': '1', 'max_q': '500000', 'min_p': '200', 'max_p': '4000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'VLX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '0.1', 'min_a': '0.00001', 'max_a': '100' },
- { 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
- { 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
- { 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
- { 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
- { 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
- { 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '5000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
- { 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
- { 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
- { 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '200000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
- { 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '200000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
- { 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
- { 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
- { 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
- { 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
- { 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '100000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
- { 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
+ { 'pair': 'WAVES/USD', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.001', 'max_p': '3500', 'min_a': '0.5', 'max_a': '500000' },
+ { 'pair': 'WAVES/RUB', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.01', 'max_p': '10000', 'min_a': '1', 'max_a': '50000000' },
+ { 'pair': 'WAVES/BTC', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.000001', 'max_p': '1', 'min_a': '0.0001', 'max_a': '100' },
+ { 'pair': 'WAVES/ETH', 'min_q': '0.5', 'max_q': '500000', 'min_p': '0.00001', 'max_p': '30', 'min_a': '0.0035', 'max_a': '3500' },
+ { 'pair': 'XEM/USD', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XEM/EUR', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XEM/UAH', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.0001', 'max_p': '30000', 'min_a': '10', 'max_a': '15000000' },
+ { 'pair': 'XEM/BTC', 'min_q': '10', 'max_q': '10000000', 'min_p': '0.0000001', 'max_p': '1', 'min_a': '0.00015', 'max_a': '100' },
+ { 'pair': 'XLM/USD', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '500000' },
+ { 'pair': 'XLM/RUB', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'XLM/TRY', 'min_q': '0.01', 'max_q': '5000000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '6000000' },
+ { 'pair': 'XLM/BTC', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'XMR/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XMR/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '600000', 'min_a': '10', 'max_a': '16000000' },
+ { 'pair': 'XMR/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'XMR/UAH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '300000', 'min_a': '5', 'max_a': '16000000' },
+ { 'pair': 'XMR/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.0001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'XMR/ETH', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00000001', 'max_p': '100', 'min_a': '0.001', 'max_a': '5000' },
+ { 'pair': 'XRP/EUR', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/TRY', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '6000000' },
+ { 'pair': 'XRP/UAH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.01', 'max_a': '15000000' },
+ { 'pair': 'XRP/USDT', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.001', 'max_p': '1000', 'min_a': '0.001', 'max_a': '500000' },
+ { 'pair': 'XRP/ETH', 'min_q': '1', 'max_q': '5000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.00001', 'max_a': '5000' },
{ 'pair': 'XTZ/USD', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '100000' },
{ 'pair': 'XTZ/RUB', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00001', 'max_p': '100000', 'min_a': '0.5', 'max_a': '500000' },
{ 'pair': 'XTZ/BTC', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.00001', 'max_a': '10' },
{ 'pair': 'XTZ/ETH', 'min_q': '0.1', 'max_q': '100000', 'min_p': '0.0000001', 'max_p': '10', 'min_a': '0.0001', 'max_a': '1000' },
- { 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
- { 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
- { 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '1000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
+ { 'pair': 'ZEC/USD', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'ZEC/RUB', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '100000', 'min_a': '0.1', 'max_a': '50000000' },
+ { 'pair': 'ZEC/EUR', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.001', 'max_p': '5000', 'min_a': '0.1', 'max_a': '500000' },
+ { 'pair': 'ZEC/BTC', 'min_q': '0.01', 'max_q': '10000', 'min_p': '0.00001', 'max_p': '10', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ZRX/USD', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00001', 'max_p': '1000', 'min_a': '0.1', 'max_a': '500000' },
{ 'pair': 'ZRX/BTC', 'min_q': '1', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '1', 'min_a': '0.001', 'max_a': '100' },
{ 'pair': 'ZRX/ETH', 'min_q': '0.01', 'max_q': '10000000', 'min_p': '0.00000001', 'max_p': '10', 'min_a': '0.01', 'max_a': '5000' },
@@ -337,6 +369,8 @@ module.exports = class exmo extends Exchange {
{ 'prov': 'CRON', 'dep': '0%', 'wd': '5 CRON' },
{ 'prov': 'ONT', 'dep': '0%', 'wd': '1 ONT' },
{ 'prov': 'ONG', 'dep': '0%', 'wd': '5 ONG' },
+ { 'prov': 'ALGO', 'dep': '0%', 'wd': '0.01 ALGO' },
+ { 'prov': 'ATOM', 'dep': '0%', 'wd': '' },
],
},
{
@@ -345,9 +379,10 @@ module.exports = class exmo extends Exchange {
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Payeer', 'dep': '3.95%', 'wd': '-' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.99%' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 USD', 'wd': '-' },
{ 'prov': 'Visa', 'dep': '3.45%', 'wd': '-' },
+ { 'prov': 'Frick Bank', 'dep': '0 USD', 'wd': '-' },
],
},
{
@@ -355,22 +390,24 @@ module.exports = class exmo extends Exchange {
'title': 'EUR',
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
+ { 'prov': 'Visa/MasterCard', 'dep': '4.5% + 0.5 EUR', 'wd': '-' },
{ 'prov': 'Visa', 'dep': '2.95%', 'wd': '-' },
- { 'prov': 'SEPA', 'dep': '10 EUR', 'wd': '50 EUR' },
+ { 'prov': 'Frick Internal Transfer', 'dep': '0 EUR', 'wd': '-' },
+ { 'prov': 'SEPA Frick Bank', 'dep': '0 EUR', 'wd': '-' },
+ { 'prov': 'WIRE Frick Bank', 'dep': '0%', 'wd': '-' },
+ { 'prov': 'SEPA Weg Ag', 'dep': '-', 'wd': '1 EUR' },
],
},
{
'group': 'rub',
'title': 'RUB',
'items': [
- { 'prov': 'Payeer', 'dep': '2.49%', 'wd': '-' },
+ { 'prov': 'Payeer', 'dep': '2.49%', 'wd': '3.99%' },
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Qiwi', 'dep': '0.99%', 'wd': '2%' },
- { 'prov': 'Yandex Money', 'dep': '1.95%', 'wd': '-' },
- { 'prov': 'Enfins', 'dep': '0%', 'wd': '1.49%' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '2.49%' },
- { 'prov': 'Visa/MasterCard', 'dep': '1.99%', 'wd': '4.49% + 60 RUB' },
+ { 'prov': 'Qiwi', 'dep': '1.49%', 'wd': '2.49%' },
+ { 'prov': 'Yandex Money', 'dep': '1.49%', 'wd': '-' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '3.49%' },
+ { 'prov': 'Visa/MasterCard', 'dep': '2.99%', 'wd': '3.99% + 60 RUB' },
],
},
{
@@ -378,7 +415,6 @@ module.exports = class exmo extends Exchange {
'title': 'PLN',
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
- { 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 1 PLN', 'wd': '-' },
],
},
{
@@ -388,6 +424,7 @@ module.exports = class exmo extends Exchange {
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Visa', 'dep': '3.05%', 'wd': '-' },
{ 'prov': 'Visa/MasterCard (Simplex)', 'dep': '4.5% + 2 TRY', 'wd': '-' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
],
},
{
@@ -396,17 +433,18 @@ module.exports = class exmo extends Exchange {
'items': [
{ 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Terminal', 'dep': '2.6%', 'wd': '-' },
- { 'prov': 'Enfins', 'dep': '0%', 'wd': '1.95%' },
- { 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '2.99%' },
+ { 'prov': 'Visa/MasterCard', 'dep': '1% + 5 UAH', 'wd': '-' },
+ { 'prov': 'Visa/MasterCard EasyTransfer', 'dep': '-', 'wd': '2.99%' },
],
},
{
'group': 'kzt',
'title': 'KZT',
'items': [
+ { 'prov': 'EX-CODE', 'dep': '', 'wd': '0.2%' },
{ 'prov': 'Visa/MasterCard RoyalPay', 'dep': '-', 'wd': '2.99% + 450 KZT' },
{ 'prov': 'Visa/MasterCard', 'dep': '3.5%', 'wd': '-' },
- { 'prov': 'AdvCash', 'dep': '0%', 'wd': '1.49%' },
+ { 'prov': 'AdvCash', 'dep': '0%', 'wd': '-' },
],
},
],
@@ -420,6 +458,7 @@ module.exports = class exmo extends Exchange {
'40015': ExchangeError, // API function do not exist
'40016': OnMaintenance, // {"result":false,"error":"Error 40016: Maintenance work in progress"}
'40017': AuthenticationError, // Wrong API Key
+ '40032': PermissionDenied, // {"result":false,"error":"Error 40032: Access is denied for this API key"}
'40034': RateLimitExceeded, // {"result":false,"error":"Error 40034: Access is denied, rate limit is exceeded"}
'50052': InsufficientFunds,
'50054': InsufficientFunds,
@@ -429,6 +468,8 @@ module.exports = class exmo extends Exchange {
'50321': InvalidOrder, // Price by order is more than permissible maximum for this pair
},
'broad': {
+ 'range period is too long': BadRequest,
+ 'invalid syntax': BadRequest,
'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}
},
},
@@ -590,8 +631,21 @@ module.exports = class exmo extends Exchange {
}
async fetchMarkets (params = {}) {
- const fees = await this.fetchTradingFees ();
const response = await this.publicGetPairSettings (params);
+ //
+ // {
+ // "EXM_ETH": {
+ // "min_quantity": "1",
+ // "max_quantity": "1000",
+ // "min_price": "1",
+ // "max_price": "1000",
+ // "max_amount": "1000",
+ // "min_amount": "1",
+ // "commission_taker_percent": "0.2",
+ // "commission_maker_percent": "0.2"
+ // },
+ // }
+ //
const keys = Object.keys (response);
const result = [];
for (let i = 0; i < keys.length; i++) {
@@ -601,6 +655,8 @@ module.exports = class exmo extends Exchange {
const [ baseId, quoteId ] = symbol.split ('/');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
+ const taker = this.safeFloat (market, 'commission_taker_percent');
+ const maker = this.safeFloat (market, 'commission_maker_percent');
result.push ({
'id': id,
'symbol': symbol,
@@ -609,8 +665,8 @@ module.exports = class exmo extends Exchange {
'baseId': baseId,
'quoteId': quoteId,
'active': true,
- 'taker': fees['taker'],
- 'maker': fees['maker'],
+ 'taker': taker / 100,
+ 'maker': maker / 100,
'limits': {
'amount': {
'min': this.safeFloat (market, 'min_quantity'),
@@ -635,6 +691,74 @@ module.exports = class exmo extends Exchange {
return result;
}
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ 'resolution': this.timeframes[timeframe],
+ };
+ const options = this.safeValue (this.options, 'fetchOHLCV');
+ const maxLimit = this.safeInteger (options, 'maxLimit', 3000);
+ const duration = this.parseTimeframe (timeframe);
+ const now = this.milliseconds ();
+ if (since === undefined) {
+ if (limit === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument or a limit argument');
+ } else {
+ if (limit > maxLimit) {
+ throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
+ }
+ request['from'] = parseInt (now / 1000) - limit * duration - 1;
+ request['to'] = parseInt (now / 1000);
+ }
+ } else {
+ request['from'] = parseInt (since / 1000) - 1;
+ if (limit === undefined) {
+ request['to'] = parseInt (now / 1000);
+ } else {
+ if (limit > maxLimit) {
+ throw new BadRequest (this.id + ' fetchOHLCV will serve ' + maxLimit.toString () + ' candles at most');
+ }
+ const to = this.sum (since, limit * duration * 1000);
+ request['to'] = parseInt (to / 1000);
+ }
+ }
+ const response = await this.publicGetCandlesHistory (this.extend (request, params));
+ //
+ // {
+ // "candles":[
+ // {"t":1584057600000,"o":0.02235144,"c":0.02400233,"h":0.025171,"l":0.02221,"v":5988.34031761},
+ // {"t":1584144000000,"o":0.0240373,"c":0.02367413,"h":0.024399,"l":0.0235,"v":2027.82522329},
+ // {"t":1584230400000,"o":0.02363458,"c":0.02319242,"h":0.0237948,"l":0.02223196,"v":1707.96944997},
+ // ]
+ // }
+ //
+ const candles = this.safeValue (response, 'candles', []);
+ return this.parseOHLCVs (candles, market, timeframe, since, limit);
+ }
+
+ parseOHLCV (ohlcv, market = undefined, timeframe = '5m', since = undefined, limit = undefined) {
+ //
+ // {
+ // "t":1584057600000,
+ // "o":0.02235144,
+ // "c":0.02400233,
+ // "h":0.025171,
+ // "l":0.02221,
+ // "v":5988.34031761
+ // }
+ //
+ return [
+ this.safeInteger (ohlcv, 't'),
+ this.safeFloat (ohlcv, 'o'),
+ this.safeFloat (ohlcv, 'h'),
+ this.safeFloat (ohlcv, 'l'),
+ this.safeFloat (ohlcv, 'c'),
+ this.safeFloat (ohlcv, 'v'),
+ ];
+ }
+
async fetchBalance (params = {}) {
await this.loadMarkets ();
const response = await this.privatePostUserInfo (params);
@@ -758,8 +882,36 @@ module.exports = class exmo extends Exchange {
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "trade_id":165087520,
+ // "date":1587470005,
+ // "type":"buy",
+ // "quantity":"1.004",
+ // "price":"0.02491461",
+ // "amount":"0.02501426"
+ // },
+ //
+ // fetchMyTrades, fetchOrderTrades
+ //
+ // {
+ // "trade_id": 3,
+ // "date": 1435488248,
+ // "type": "buy",
+ // "pair": "BTC_USD",
+ // "order_id": 12345,
+ // "quantity": 1,
+ // "price": 100,
+ // "amount": 100,
+ // "exec_type": "taker",
+ // "commission_amount": "0.02",
+ // "commission_currency": "BTC",
+ // "commission_percent": "0.2"
+ // }
+ //
const timestamp = this.safeTimestamp (trade, 'date');
- let fee = undefined;
let symbol = undefined;
const id = this.safeString (trade, 'trade_id');
const orderId = this.safeString (trade, 'order_id');
@@ -768,24 +920,35 @@ module.exports = class exmo extends Exchange {
const cost = this.safeFloat (trade, 'amount');
const side = this.safeString (trade, 'type');
const type = undefined;
- if (market !== undefined) {
+ const marketId = this.safeString (trade, 'pair');
+ 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 ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
- if (market['taker'] !== market['maker']) {
- throw new ExchangeError (this.id + ' parseTrade can not deduce proper fee costs, taker and maker fees now differ');
- }
- if ((side === 'buy') && (amount !== undefined)) {
- fee = {
- 'currency': market['base'],
- 'cost': amount * market['taker'],
- 'rate': market['taker'],
- };
- } else if ((side === 'sell') && (cost !== undefined)) {
- fee = {
- 'currency': market['quote'],
- 'cost': cost * market['taker'],
- 'rate': market['taker'],
- };
+ }
+ const takerOrMaker = this.safeString (trade, 'exec_type');
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'commission_amount');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'commission_currency');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ let feeRate = this.safeFloat (trade, 'commission_percent');
+ if (feeRate !== undefined) {
+ feeRate /= 1000;
}
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ 'rate': feeRate,
+ };
}
return {
'id': id,
@@ -796,7 +959,7 @@ module.exports = class exmo extends Exchange {
'order': orderId,
'type': type,
'side': side,
- 'takerOrMaker': undefined,
+ 'takerOrMaker': takerOrMaker,
'price': price,
'amount': amount,
'cost': cost,
@@ -811,6 +974,28 @@ module.exports = class exmo extends Exchange {
'pair': market['id'],
};
const response = await this.publicGetTrades (this.extend (request, params));
+ //
+ // {
+ // "ETH_BTC":[
+ // {
+ // "trade_id":165087520,
+ // "date":1587470005,
+ // "type":"buy",
+ // "quantity":"1.004",
+ // "price":"0.02491461",
+ // "amount":"0.02501426"
+ // },
+ // {
+ // "trade_id":165087369,
+ // "date":1587469938,
+ // "type":"buy",
+ // "quantity":"0.94",
+ // "price":"0.02492348",
+ // "amount":"0.02342807"
+ // }
+ // ]
+ // }
+ //
const data = this.safeValue (response, market['id'], []);
return this.parseTrades (data, market, since, limit);
}
@@ -968,6 +1153,31 @@ module.exports = class exmo extends Exchange {
'order_id': id.toString (),
};
const response = await this.privatePostOrderTrades (this.extend (request, params));
+ //
+ // {
+ // "type": "buy",
+ // "in_currency": "BTC",
+ // "in_amount": "1",
+ // "out_currency": "USD",
+ // "out_amount": "100",
+ // "trades": [
+ // {
+ // "trade_id": 3,
+ // "date": 1435488248,
+ // "type": "buy",
+ // "pair": "BTC_USD",
+ // "order_id": 12345,
+ // "quantity": 1,
+ // "price": 100,
+ // "amount": 100,
+ // "exec_type": "taker",
+ // "commission_amount": "0.02",
+ // "commission_currency": "BTC",
+ // "commission_percent": "0.2"
+ // }
+ // ]
+ // }
+ //
const trades = this.safeValue (response, 'trades');
return this.parseTrades (trades, market, since, limit);
}
@@ -1415,9 +1625,10 @@ module.exports = class exmo extends Exchange {
if (response === undefined) {
return; // fallback to default error handler
}
- if ('result' in response) {
+ if (('result' in response) || ('errmsg' in response)) {
//
// {"result":false,"error":"Error 50052: Insufficient funds"}
+ // {"s":"error","errmsg":"strconv.ParseInt: parsing \"\": invalid syntax"}
//
let success = this.safeValue (response, 'result', false);
if (typeof success === 'string') {
@@ -1429,7 +1640,7 @@ module.exports = class exmo extends Exchange {
}
if (!success) {
let code = undefined;
- const message = this.safeString (response, 'error');
+ const message = this.safeString2 (response, 'error', 'errmsg');
const errorParts = message.split (':');
const numParts = errorParts.length;
if (numParts > 1) {
diff --git a/TaskServer/node_modules/ccxt/js/ftx.js b/TaskServer/node_modules/ccxt/js/ftx.js
index 8237d20e1..bdfa52251 100644
--- a/TaskServer/node_modules/ccxt/js/ftx.js
+++ b/TaskServer/node_modules/ccxt/js/ftx.js
@@ -580,6 +580,7 @@ module.exports = class ftx extends Exchange {
// {
// "fee": 20.1374935,
// "feeRate": 0.0005,
+ // "feeCurrency": "USD",
// "future": "EOS-0329",
// "id": 11215,
// "liquidity": "taker",
@@ -626,8 +627,11 @@ module.exports = class ftx extends Exchange {
let fee = undefined;
const feeCost = this.safeFloat (trade, 'fee');
if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'feeCurrency');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
fee = {
'cost': feeCost,
+ 'currency': feeCurrencyCode,
'rate': this.safeFloat (trade, 'feeRate'),
};
}
diff --git a/TaskServer/node_modules/ccxt/js/gateio.js b/TaskServer/node_modules/ccxt/js/gateio.js
index dd9389e9e..6a651080c 100644
--- a/TaskServer/node_modules/ccxt/js/gateio.js
+++ b/TaskServer/node_modules/ccxt/js/gateio.js
@@ -164,6 +164,26 @@ module.exports = class gateio extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetMarketinfo (params);
+ //
+ // {
+ // "result":"true",
+ // "pairs":[
+ // {
+ // "usdt_cnyx":{
+ // "decimal_places":3,
+ // "amount_decimal_places":3,
+ // "min_amount":1,
+ // "min_amount_a":1,
+ // "min_amount_b":3,
+ // "fee":0.02,
+ // "trade_disabled":0,
+ // "buy_disabled":0,
+ // "sell_disabled":0
+ // }
+ // },
+ // ]
+ // }
+ //
const markets = this.safeValue (response, 'pairs');
if (!markets) {
throw new ExchangeError (this.id + ' fetchMarkets got an unrecognized response');
@@ -190,14 +210,14 @@ module.exports = class gateio extends Exchange {
const symbol = base + '/' + quote;
const precision = {
'amount': 8,
- 'price': details['decimal_places'],
+ 'price': this.safeInteger (details, 'decimal_places'),
};
const amountLimits = {
- 'min': details['min_amount'],
+ 'min': this.safeFloat (details, 'min_amount'),
'max': undefined,
};
const priceLimits = {
- 'min': Math.pow (10, -details['decimal_places']),
+ 'min': Math.pow (10, -precision['price']),
'max': undefined,
};
const defaultCost = amountLimits['min'] * priceLimits['min'];
@@ -211,9 +231,13 @@ module.exports = class gateio extends Exchange {
'price': priceLimits,
'cost': costLimits,
};
- const active = true;
+ const disabled = this.safeValue (details, 'trade_disabled');
+ const active = !disabled;
+ const uppercaseId = id.toUpperCase ();
+ const fee = this.safeFloat (details, 'fee');
result.push ({
'id': id,
+ 'uppercaseId': uppercaseId,
'symbol': symbol,
'base': base,
'quote': quote,
@@ -221,8 +245,8 @@ module.exports = class gateio extends Exchange {
'quoteId': quoteId,
'info': market,
'active': active,
- 'maker': details['fee'] / 100,
- 'taker': details['fee'] / 100,
+ 'maker': fee / 100,
+ 'taker': fee / 100,
'precision': precision,
'limits': limits,
});
@@ -484,22 +508,64 @@ module.exports = class gateio extends Exchange {
parseOrder (order, market = undefined) {
//
- // {'amount': '0.00000000',
- // 'currencyPair': 'xlm_usdt',
- // 'fee': '0.0113766632239302 USDT',
- // 'feeCurrency': 'USDT',
- // 'feePercentage': 0.18,
- // 'feeValue': '0.0113766632239302',
- // 'filledAmount': '30.14004987',
- // 'filledRate': 0.2097,
- // 'initialAmount': '30.14004987',
- // 'initialRate': '0.2097',
- // 'left': 0,
- // 'orderNumber': '998307286',
- // 'rate': '0.2097',
- // 'status': 'closed',
- // 'timestamp': 1531158583,
- // 'type': 'sell'},
+ // createOrder
+ //
+ // {
+ // "fee": "0 ZEC",
+ // "code": 0,
+ // "rate": "0.0055",
+ // "side": 2,
+ // "type": "buy",
+ // "ctime": 1586460839.138,
+ // "market": "ZEC_BTC",
+ // "result": "true",
+ // "status": "open",
+ // "iceberg": "0",
+ // "message": "Success",
+ // "feeValue": "0",
+ // "filledRate": "0.005500000",
+ // "leftAmount": "0.60607456",
+ // "feeCurrency": "ZEC",
+ // "orderNumber": 10755887009,
+ // "filledAmount": "0",
+ // "feePercentage": 0.002,
+ // "initialAmount": "0.60607456"
+ // }
+ //
+ // {
+ // 'amount': '0.00000000',
+ // 'currencyPair': 'xlm_usdt',
+ // 'fee': '0.0113766632239302 USDT',
+ // 'feeCurrency': 'USDT',
+ // 'feePercentage': 0.18,
+ // 'feeValue': '0.0113766632239302',
+ // 'filledAmount': '30.14004987',
+ // 'filledRate': 0.2097,
+ // 'initialAmount': '30.14004987',
+ // 'initialRate': '0.2097',
+ // 'left': 0,
+ // 'orderNumber': '998307286',
+ // 'rate': '0.2097',
+ // 'status': 'closed',
+ // 'timestamp': 1531158583,
+ // 'type': 'sell'
+ // }
+ //
+ // {
+ // "orderNumber": 10802237760,
+ // "orderType": 1,
+ // "type": "buy",
+ // "rate": "0.54250000",
+ // "amount": "45.55638518",
+ // "total": "24.71433896",
+ // "initialRate": "0.54250000",
+ // "initialAmount": "45.55638518",
+ // "filledRate": "0.54250000",
+ // "filledAmount": "0",
+ // "currencyPair": "nano_usdt",
+ // "timestamp": 1586556143,
+ // "status": "open"
+ // }
//
const id = this.safeString2 (order, 'orderNumber', 'id');
let symbol = undefined;
@@ -520,12 +586,15 @@ module.exports = class gateio extends Exchange {
} else if (side === '2') {
side = 'buy';
}
- const price = this.safeFloat2 (order, 'initialRate', 'price');
+ const price = this.safeFloat2 (order, 'initialRate', 'rate');
const average = this.safeFloat (order, 'filledRate');
const amount = this.safeFloat2 (order, 'initialAmount', 'amount');
const filled = this.safeFloat (order, 'filledAmount');
// In the order status response, this field has a different name.
- const remaining = this.safeFloat2 (order, 'leftAmount', 'left');
+ let remaining = this.safeFloat2 (order, 'leftAmount', 'left');
+ if (remaining === undefined) {
+ remaining = amount - filled;
+ }
const feeCost = this.safeFloat (order, 'feeValue');
const feeCurrencyId = this.safeString (order, 'feeCurrency');
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
@@ -651,7 +720,7 @@ module.exports = class gateio extends Exchange {
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
- throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol param');
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
diff --git a/TaskServer/node_modules/ccxt/js/gemini.js b/TaskServer/node_modules/ccxt/js/gemini.js
index a4f58b2ca..6e07ab638 100644
--- a/TaskServer/node_modules/ccxt/js/gemini.js
+++ b/TaskServer/node_modules/ccxt/js/gemini.js
@@ -180,8 +180,7 @@ module.exports = class gemini extends Exchange {
if (numTables < 2) {
throw new NotSupported (error);
}
- // tables[1] = tables[1].replace ("\n", ''); // eslint-disable-line quotes
- const rows = tables[1].split ("\n"); // eslint-disable-line quotes
+ const rows = tables[1].split ("\n \n"); // eslint-disable-line quotes
const numRows = rows.length;
if (numRows < 2) {
throw new NotSupported (error);
@@ -192,66 +191,73 @@ module.exports = class gemini extends Exchange {
const row = rows[i];
const cells = row.split ("\n"); // eslint-disable-line quotes
const numCells = cells.length;
- if (numCells < 7) {
+ if (numCells < 9) {
throw new NotSupported (error);
}
- //
// [
- // 'btcusd',
- // ' | USD', // quote
- // ' | BTC', // base
- // ' | 0.00001 BTC (1e-5)', // min amount
- // ' | 0.00000001 BTC (1e-8)', // amount min tick size
- // ' | 0.01 USD', // price min tick size
- // ' | \n'
+ // 'BTC', // currency
+ // ' | 0.00001 BTC (1e-5)', // min order size
+ // ' | 0.00000001 BTC (1e-8)', // tick size
+ // ' | 0.01 USD', // usd price increment
+ // ' | N/A', // btc price increment
+ // ' | 0.0001 ETH (1e-4)', // eth price increment
+ // ' | 0.0001 BCH (1e-4)', // bch price increment
+ // ' | 0.001 LTC (1e-3)', // ltc price increment
+ // ''
// ]
//
- let id = cells[0].replace (' | ', '');
- id = id.replace ('', '');
- id = id.replace ('', '');
- let baseId = cells[2].replace (' | ', '');
- let quoteId = cells[1].replace (' | ', '');
- const minAmountAsString = cells[3].replace (' | ', '');
- const amountTickSizeAsString = cells[4].replace (' | ', '');
- const priceTickSizeAsString = cells[5].replace (' | ', '');
- const minAmount = minAmountAsString.split (' ');
- const amountPrecision = amountTickSizeAsString.split (' ');
- const pricePrecision = priceTickSizeAsString.split (' ');
- baseId = baseId.toLowerCase ();
- quoteId = quoteId.toLowerCase ();
+ const uppercaseBaseId = cells[0].replace (' | ', '');
+ const baseId = uppercaseBaseId.toLowerCase ();
const base = this.safeCurrencyCode (baseId);
- const quote = this.safeCurrencyCode (quoteId);
- const symbol = base + '/' + quote;
- const precision = {
- 'amount': this.precisionFromString (amountPrecision[0]),
- 'price': this.precisionFromString (pricePrecision[0]),
- };
- const active = undefined;
- result.push ({
- 'id': id,
- 'info': row,
- 'symbol': symbol,
- 'base': base,
- 'quote': quote,
- 'baseId': baseId,
- 'quoteId': quoteId,
- 'active': active,
- 'precision': precision,
- 'limits': {
- 'amount': {
- 'min': parseFloat (minAmount[0]),
- 'max': undefined,
+ const quoteIds = [ 'usd', 'btc', 'eth', 'bch', 'ltc' ];
+ const minAmountString = cells[1].replace (' | ', '');
+ const minAmountParts = minAmountString.split (' ');
+ const minAmount = this.safeFloat (minAmountParts, 0);
+ const amountPrecisionString = cells[2].replace (' | ', '');
+ const amountPrecisionParts = amountPrecisionString.split (' ');
+ const amountPrecision = this.precisionFromString (amountPrecisionParts[0]);
+ for (let j = 0; j < quoteIds.length; j++) {
+ const quoteId = quoteIds[j];
+ const quote = this.safeCurrencyCode (quoteId);
+ const pricePrecisionIndex = this.sum (3, j);
+ const pricePrecisionString = cells[pricePrecisionIndex].replace (' | ', '');
+ if (pricePrecisionString === 'N/A') {
+ continue;
+ }
+ const pricePrecisionParts = pricePrecisionString.split (' ');
+ const pricePrecision = this.precisionFromString (pricePrecisionParts[0]);
+ const symbol = base + '/' + quote;
+ const id = baseId + quoteId;
+ const active = undefined;
+ result.push ({
+ 'id': id,
+ 'info': row,
+ 'symbol': symbol,
+ 'base': base,
+ 'quote': quote,
+ 'baseId': baseId,
+ 'quoteId': quoteId,
+ 'active': active,
+ 'precision': {
+ 'amount': amountPrecision,
+ 'price': pricePrecision,
},
- 'price': {
- 'min': undefined,
- 'max': undefined,
+ 'limits': {
+ 'amount': {
+ 'min': minAmount,
+ 'max': undefined,
+ },
+ 'price': {
+ 'min': undefined,
+ 'max': undefined,
+ },
+ 'cost': {
+ 'min': undefined,
+ 'max': undefined,
+ },
},
- 'cost': {
- 'min': undefined,
- 'max': undefined,
- },
- },
- });
+ });
+ }
}
return result;
}
diff --git a/TaskServer/node_modules/ccxt/js/hbtc.js b/TaskServer/node_modules/ccxt/js/hbtc.js
new file mode 100644
index 000000000..317dc9d90
--- /dev/null
+++ b/TaskServer/node_modules/ccxt/js/hbtc.js
@@ -0,0 +1,2019 @@
+'use strict';
+
+// ---------------------------------------------------------------------------
+
+const Exchange = require ('./base/Exchange');
+const { AuthenticationError, ExchangeError, OrderNotFound, ArgumentsRequired, BadSymbol, BadRequest, NullResponse, InvalidOrder, BadResponse, NotSupported, ExchangeNotAvailable, RequestTimeout, RateLimitExceeded, PermissionDenied, InsufficientFunds, InvalidAddress } = require ('./base/errors');
+const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
+
+// ---------------------------------------------------------------------------
+
+module.exports = class hbtc extends Exchange {
+ describe () {
+ return this.deepExtend (super.describe (), {
+ 'id': 'hbtc',
+ 'name': 'HBTC',
+ 'countries': [ 'CN' ],
+ 'rateLimit': 2000,
+ 'version': 'v1',
+ 'has': {
+ 'CORS': false,
+ 'fetchTime': true,
+ 'fetchBidAsk': true,
+ 'fetchBidsAsks': true,
+ 'fetchTickers': true,
+ 'fetchTicker': true,
+ 'fetchDepositAddress': false,
+ 'fetchOHLCV': true,
+ 'fetchOrder': true,
+ 'fetchOrders': false,
+ 'fetchOpenOrders': true,
+ 'fetchClosedOrders': true,
+ 'fetchTradingLimits': true,
+ 'fetchMarkets': true,
+ 'fetchMyTrades': true,
+ 'withdraw': true,
+ 'fetchCurrencies': false,
+ 'fetchDeposits': true,
+ 'fetchWithdrawals': true,
+ 'fetchAccounts': true,
+ 'fetchLedger': true,
+ },
+ 'timeframes': {
+ '1m': '1m',
+ '3m': '3m',
+ '5m': '5m',
+ '15m': '15m',
+ '30m': '30m',
+ '1h': '1h',
+ '2h': '2h',
+ '4h': '4h',
+ '6h': '6h',
+ '8h': '8h',
+ '12h': '12h',
+ '1d': '1d',
+ '3d': '3d',
+ '1w': '1w',
+ '1M': '1M',
+ },
+ 'urls': {
+ 'logo': 'https://user-images.githubusercontent.com/51840849/80134449-70663300-85a7-11ea-8942-e204cdeaab5d.jpg', // 交易所LOGO
+ 'api': {
+ 'quote': 'https://api.hbtc.com/openapi/quote', // 市场API数据端点
+ 'contract': 'https://api.hbtc.com/openapi/contract', // 合约API数据端点
+ 'option': 'https://api.hbtc.com/openapi/option', // 合约API数据端点
+ 'public': 'https://api.hbtc.com/openapi', // 公共API数据端点
+ 'private': 'https://api.hbtc.com/openapi', // 私有API数据端点
+ 'zendesk': 'https://hbtc.zendesk.com/hc/en-us',
+ },
+ 'www': 'https://www.hbtc.com', // 公司主页
+ 'referral': 'https://www.hbtc.com/register/O2S8NS', // 邀请链接
+ 'doc': 'https://github.com/bhexopen/BHEX-OpenApi/tree/master/doc', // openapi文档地址
+ 'fees': 'https://hbtc.zendesk.com/hc/zh-cn/articles/360009274694', // 费率介绍
+ },
+ 'api': {
+ 'public': {
+ 'get': [
+ 'ping',
+ 'time',
+ 'brokerInfo', // 查询当前broker交易规则和symbol信息
+ 'getOptions',
+ ],
+ },
+ 'quote': {
+ 'get': [
+ 'depth', // 获取深度
+ 'depth/merged',
+ 'trades', // 获取当前最新成交
+ 'klines', // 获取K线数据
+ 'ticker/24hr', // 获取24小时价格变化数据
+ 'ticker/price',
+ 'ticker/bookTicker',
+ 'contract/index', // 获取合约标的指数价格
+ 'contract/depth', // 获取合约深度
+ 'contract/depth/merged',
+ 'contract/trades', // 获取合约最近成交,
+ 'contract/klines', // 获取合约的K线数据
+ 'contract/ticker/24hr',
+ 'option/index',
+ 'option/depth',
+ 'option/depth/merged',
+ 'option/trades',
+ 'option/klines',
+ 'option/ticker/24hr',
+ ],
+ },
+ 'contract': {
+ 'get': [
+ // public
+ 'insurance',
+ 'fundingRate', // 获取资金费率信息
+ // private
+ 'openOrders', // 查询合约当前委托
+ 'historyOrders', // 查询合约历史委托
+ 'getOrder', // 查询合约订单详情
+ 'myTrades', // 查询合约历史成交
+ 'positions', // 查询合约当前持仓
+ 'account', // 查询合约账户信息
+ ],
+ 'post': [
+ 'order', // 创建合约订单
+ 'modifyMargin', // 修改保证金
+ ],
+ 'delete': [
+ 'order/cancel', // 取消合约订单
+ 'order/batchCancel',
+ ],
+ },
+ 'option': {
+ 'get': [
+ 'openOrders',
+ 'positions',
+ 'historyOrders',
+ // 'getOrder',
+ 'myTrades',
+ 'settlements',
+ 'account',
+ ],
+ 'post': [
+ 'order',
+ ],
+ 'delete': [
+ 'order/cancel',
+ ],
+ },
+ 'private': {
+ 'get': [
+ 'order', // 查询订单
+ 'openOrders', // 查询当前委托
+ 'historyOrders', // 查询历史委托
+ 'account', // 获取当前账户信息
+ 'myTrades', // 查询历史成交
+ 'depositOrders',
+ 'withdrawalOrders',
+ 'withdraw/detail',
+ 'balance_flow',
+ ],
+ 'post': [
+ 'order', // 创建新订单
+ 'order/test',
+ 'userDataStream',
+ 'subAccount/query',
+ 'transfer',
+ 'user/transfer',
+ 'withdraw',
+ ],
+ 'put': [
+ 'userDataStream',
+ ],
+ 'delete': [
+ 'order', // 取消订单
+ 'userDataStream',
+ ],
+ },
+ },
+ 'precisionMode': TICK_SIZE,
+ 'fees': {
+ 'trading': {
+ 'tierBased': false,
+ 'percentage': true,
+ 'maker': 0.002, // MAKER费率
+ 'taker': 0.002, // TAKER费率
+ },
+ },
+ 'exceptions': {
+ 'exact': {
+ // general server or network errors
+ '-1000': ExchangeError, // An unknown error occured while processing the request
+ '-1001': ExchangeError, // Internal error, unable to process your request. Please try again
+ '-1002': AuthenticationError, // You are not authorized to execute this request. Request need API Key included in. We suggest that API Key be included in any request
+ '-1003': RateLimitExceeded, // Too many requests, please use the websocket for live updates
+ '-1004': BadRequest,
+ '-1005': PermissionDenied,
+ '-1006': BadResponse, // An unexpected response was received from the message bus. Execution status unknown. OPEN API server find some exception in execute request.Please report to Customer service
+ '-1007': RequestTimeout, // Timeout waiting for response from backend server. Send status unknown, execution status unknown
+ '-1014': InvalidOrder, // Unsupported order combination
+ '-1015': RateLimitExceeded, // Reach the rate limit.Please slow down your request speed
+ '-1016': ExchangeNotAvailable, // This service is no longer available
+ '-1020': NotSupported, // This operation is not supported
+ '-1021': BadRequest, // Timestamp for this request is outside of the recvWindow
+ '-1022': AuthenticationError, // Signature for this request is not valid
+ // request issues
+ '-1100': BadRequest, // Illegal characters found in a parameter
+ '-1101': BadRequest, // Too many parameters sent for this endpoint
+ '-1102': BadRequest, // A mandatory parameter was not sent, was empty/null, or malformed
+ '-1103': BadRequest, // An unknown parameter was sent
+ '-1104': BadRequest, // Not all sent parameters were read
+ '-1105': BadRequest, // A parameter was empty
+ '-1106': BadRequest, // A parameter was sent when not required
+ '-1111': BadRequest, // Precision is over the maximum defined for this asset
+ '-1112': NullResponse, // No orders on book for symbol
+ '-1114': InvalidOrder, // TimeInForce parameter sent when not required
+ '-1115': InvalidOrder, // Invalid timeInForce
+ '-1116': InvalidOrder, // Invalid orderType
+ '-1117': InvalidOrder, // Invalid side
+ '-1118': InvalidOrder, // New client order ID was empty
+ '-1119': InvalidOrder, // Original client order ID was empty
+ '-1120': BadRequest, // Invalid interval
+ '-1121': BadSymbol, // Invalid symbol
+ '-1125': AuthenticationError, // This listenKey does not exist
+ '-1127': BadRequest, // Lookup interval is too big
+ '-1128': BadRequest, // Combination of optional parameters invalid
+ '-1130': BadRequest, // Invalid data sent for a parameter
+ '-1131': InsufficientFunds,
+ '-1132': InvalidOrder, // Order price too high
+ '-1133': InvalidOrder, // Order price lower than the minimum,please check general broker info
+ '-1134': InvalidOrder, // Order price decimal too long,please check general broker info
+ '-1135': InvalidOrder, // Order quantity too large
+ '-1136': InvalidOrder, // Order quantity lower than the minimum
+ '-1137': InvalidOrder, // Order quantity decimal too long
+ '-1138': InvalidOrder, // Order price exceeds permissible range
+ '-1139': InvalidOrder, // Order has been filled
+ '-1140': InvalidOrder, // Transaction amount lower than the minimum
+ '-1141': InvalidOrder, // Duplicate clientOrderId
+ '-1142': InvalidOrder, // Order has been canceled
+ '-1143': OrderNotFound, // Cannot be found on order book
+ '-1144': InvalidOrder, // Order has been locked
+ '-1145': InvalidOrder, // This order type does not support cancellation
+ '-1146': RequestTimeout, // Order creation timeout
+ '-1147': RequestTimeout, // Order cancellation timeout
+ '-1149': InvalidOrder, // Create order failed
+ '-1187': InvalidAddress, // Withdrawal address not in whitelist
+ '-2010': InvalidOrder, // NEW_ORDER_REJECTED
+ '-2011': InvalidOrder, // CANCEL_REJECTED
+ '-2013': OrderNotFound, // Order does not exist
+ '-2014': AuthenticationError, // API-key format invalid
+ '-2015': AuthenticationError, // Invalid API-key, IP, or permissions for action
+ '-2016': ExchangeError, // No trading window could be found for the symbol. Try ticker/24hrs instead
+ },
+ },
+ // exchange-specific options
+ 'options': {
+ 'fetchTickers': {
+ 'method': 'quoteGetTicker24hr',
+ },
+ },
+ });
+ }
+
+ async fetchTime (params = {}) {
+ const response = await this.publicGetTime (params);
+ //
+ // {
+ // "serverTime": 1527777538000
+ // }
+ //
+ return this.safeInteger (response, 'serverTime');
+ }
+
+ parseMarket (market, type = 'spot') {
+ const filters = this.safeValue (market, 'filters', []);
+ const id = this.safeString (market, 'symbol');
+ let baseId = this.safeString (market, 'baseAsset');
+ const quoteId = this.safeString (market, 'quoteAsset');
+ let base = this.safeCurrencyCode (baseId);
+ const quote = this.safeCurrencyCode (quoteId);
+ let symbol = base + '/' + quote;
+ let spot = true;
+ let future = false;
+ let option = false;
+ let inverse = false;
+ if (type === 'future') {
+ symbol = id;
+ spot = false;
+ future = true;
+ inverse = this.safeValue (market, 'inverse', false);
+ baseId = this.safeString (market, 'underlying');
+ base = this.safeCurrencyCode (baseId);
+ } else if (type === 'option') {
+ symbol = id;
+ spot = false;
+ option = true;
+ }
+ let amountMin = undefined;
+ let amountMax = undefined;
+ let priceMin = undefined;
+ let priceMax = undefined;
+ let costMin = undefined;
+ for (let j = 0; j < filters.length; j++) {
+ const filter = filters[j];
+ const filterType = this.safeString (filter, 'filterType');
+ if (filterType === 'LOT_SIZE') {
+ amountMin = this.safeFloat (filter, 'minQty');
+ amountMax = this.safeFloat (filter, 'maxQty');
+ }
+ if (filterType === 'PRICE_FILTER') {
+ priceMin = this.safeFloat (filter, 'minPrice');
+ priceMax = this.safeFloat (filter, 'maxPrice');
+ }
+ if (filterType === 'MIN_NOTIONAL') {
+ costMin = this.safeFloat (filter, 'minNotional');
+ }
+ }
+ if ((costMin === undefined) && (amountMin !== undefined) && (priceMin !== undefined)) {
+ costMin = amountMin * priceMin;
+ }
+ const precision = {
+ 'price': this.safeFloat2 (market, 'quotePrecision', 'quoteAssetPrecision'),
+ 'amount': this.safeFloat (market, 'baseAssetPrecision'),
+ };
+ const limits = {
+ 'amount': {
+ 'min': amountMin,
+ 'max': amountMax,
+ },
+ 'price': {
+ 'min': priceMin,
+ 'max': priceMax,
+ },
+ 'cost': {
+ 'min': costMin,
+ 'max': undefined,
+ },
+ };
+ return {
+ 'id': id,
+ 'symbol': symbol,
+ 'base': base,
+ 'quote': quote,
+ 'baseId': baseId,
+ 'quoteId': quoteId,
+ 'active': true,
+ 'type': type,
+ 'spot': spot,
+ 'future': future,
+ 'option': option,
+ 'inverse': inverse,
+ 'precision': precision,
+ 'limits': limits,
+ 'info': market,
+ };
+ }
+
+ async fetchMarkets (params = {}) {
+ const response = await this.publicGetBrokerInfo (params);
+ //
+ // {
+ // "timezone":"UTC",
+ // "serverTime":"1588015885118",
+ // "brokerFilters":[],
+ // "symbols":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.01","maxPrice":"100000.00000000","tickSize":"0.01","filterType":"PRICE_FILTER"},
+ // {"minQty":"0.0005","maxQty":"100000.00000000","stepSize":"0.000001","filterType":"LOT_SIZE"},
+ // {"minNotional":"5","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTCUSDT",
+ // "symbolName":"BTCUSDT",
+ // "status":"TRADING",
+ // "baseAsset":"BTC",
+ // "baseAssetPrecision":"0.000001",
+ // "quoteAsset":"USDT",
+ // "quotePrecision":"0.01",
+ // "icebergAllowed":false
+ // },
+ // ],
+ // "options":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.01","maxPrice":"100000.00000000","tickSize":"0.01","filterType":"PRICE_FILTER"},
+ // {"minQty":"0.01","maxQty":"100000.00000000","stepSize":"0.001","filterType":"LOT_SIZE"},
+ // {"minNotional":"1","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC0501CS8500",
+ // "symbolName":"BTC0501CS8500",
+ // "status":"TRADING",
+ // "baseAsset":"BTC0501CS8500",
+ // "baseAssetPrecision":"0.001",
+ // "quoteAsset":"BUSDT",
+ // "quotePrecision":"0.01",
+ // "icebergAllowed":false
+ // },
+ // ],
+ // "contracts":[
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-PERP-REV",
+ // "symbolName":"BTC-PERP-REV",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-PERP-REV",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"USDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":true,
+ // "index":"BTCUSDT",
+ // "marginToken":"TBTC",
+ // "marginPrecision":"0.00000001",
+ // "contractMultiplier":"1.0",
+ // "underlying":"TBTC",
+ // "riskLimits":[
+ // {"riskLimitId":"200000001","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"200000002","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"200000003","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"200000004","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-SWAP",
+ // "symbolName":"BTC-SWAP",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-SWAP",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"USDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":true,
+ // "index":"BTCUSDT",
+ // "marginToken":"BTC",
+ // "marginPrecision":"0.00000001",
+ // "contractMultiplier":"1.0",
+ // "underlying":"BTC",
+ // "riskLimits":[
+ // {"riskLimitId":"500000001","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"500000002","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"500000003","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"500000004","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // {
+ // "filters":[
+ // {"minPrice":"0.1","maxPrice":"100000.00000000","tickSize":"0.1","filterType":"PRICE_FILTER"},
+ // {"minQty":"1","maxQty":"100000.00000000","stepSize":"1","filterType":"LOT_SIZE"},
+ // {"minNotional":"0.000000001","filterType":"MIN_NOTIONAL"}
+ // ],
+ // "exchangeId":"301",
+ // "symbol":"BTC-PERP-BUSDT",
+ // "symbolName":"BTC-PERP-BUSDT",
+ // "status":"TRADING",
+ // "baseAsset":"BTC-PERP-BUSDT",
+ // "baseAssetPrecision":"1",
+ // "quoteAsset":"BUSDT",
+ // "quoteAssetPrecision":"0.1",
+ // "icebergAllowed":false,
+ // "inverse":false,
+ // "index":"BTCUSDT",
+ // "marginToken":"BUSDT",
+ // "marginPrecision":"0.0001",
+ // "contractMultiplier":"0.0001",
+ // "underlying":"TBTC",
+ // "riskLimits":[
+ // {"riskLimitId":"600000132","quantity":"1000000.0","initialMargin":"0.01","maintMargin":"0.005"},
+ // {"riskLimitId":"600000133","quantity":"2000000.0","initialMargin":"0.02","maintMargin":"0.01"},
+ // {"riskLimitId":"600000134","quantity":"3000000.0","initialMargin":"0.03","maintMargin":"0.015"},
+ // {"riskLimitId":"600000135","quantity":"4000000.0","initialMargin":"0.04","maintMargin":"0.02"}
+ // ]
+ // },
+ // ]
+ // }
+ //
+ const result = [];
+ const symbols = this.safeValue (response, 'symbols', []);
+ for (let i = 0; i < symbols.length; i++) {
+ const market = this.parseMarket (symbols[i], 'spot');
+ result.push (market);
+ }
+ const options = this.safeValue (response, 'options', []);
+ for (let i = 0; i < options.length; i++) {
+ const market = this.parseMarket (options[i], 'option');
+ result.push (market);
+ }
+ const contracts = this.safeValue (response, 'contracts', []);
+ for (let i = 0; i < contracts.length; i++) {
+ const market = this.parseMarket (contracts[i], 'future');
+ result.push (market);
+ }
+ return result;
+ }
+
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 40, max 40
+ }
+ const response = await this.quoteGetDepth (this.extend (request, params));
+ //
+ // {
+ // "time":1588068913453,
+ // "bids":[
+ // ["0.025278","0.0202"],
+ // ["0.025277","16.1132"],
+ // ["0.025276","7.9056"],
+ // ]
+ // "asks":[
+ // ["0.025302","5.9999"],
+ // ["0.025303","34.9151"],
+ // ["0.025304","92.391"],
+ // ]
+ // }
+ //
+ const timestamp = this.safeInteger (response, 'time');
+ return this.parseOrderBook (response, timestamp);
+ }
+
+ async fetchTicker (symbol, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const response = await this.quoteGetTicker24hr (this.extend (request, params));
+ //
+ // {
+ // "time":1588069860794,
+ // "symbol":"BNB0501PS16",
+ // "bestBidPrice":"0.2129",
+ // "bestAskPrice":"0.3163",
+ // "volume":"33547",
+ // "quoteVolume":"10801.987",
+ // "lastPrice":"0.2625",
+ // "highPrice":"0.3918",
+ // "lowPrice":"0.2625",
+ // "openPrice":"0.362",
+ // }
+ //
+ return this.parseTicker (response, market);
+ }
+
+ parseTickers (rawTickers, symbols = undefined) {
+ const tickers = [];
+ for (let i = 0; i < rawTickers.length; i++) {
+ tickers.push (this.parseTicker (rawTickers[i]));
+ }
+ return this.filterByArray (tickers, 'symbol', symbols);
+ }
+
+ async fetchBidAsk (symbol, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ const response = await this.quoteGetTickerBookTicker (this.extend (request, params));
+ //
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // }
+ //
+ return this.parseTicker (response, market);
+ }
+
+ async fetchBidsAsks (symbols = undefined, params = {}) {
+ await this.loadMarkets ();
+ const response = await this.quoteGetTickerBookTicker (params);
+ //
+ // [
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // },
+ // {
+ // "symbol": "ETHBTC",
+ // "bidPrice": "0.07946700",
+ // "bidQty": "9.00000000",
+ // "askPrice": "100000.00000000",
+ // "askQty": "1000.00000000"
+ // },
+ // ]
+ //
+ return this.parseTickers (response, symbols);
+ }
+
+ async fetchTickers (symbols = undefined, params = {}) {
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchTickers', {});
+ const defaultMethod = this.safeString (options, 'method', 'quoteGetTicker24hr');
+ const defaultType = this.safeString (options, 'type', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ let method = defaultMethod;
+ if (type === 'future') {
+ method = 'quoteGetContractTicker24hr';
+ } else if (type === 'option') {
+ method = 'quoteGetOptionTicker24hr';
+ }
+ const response = await this[method] (query);
+ //
+ // [
+ // {
+ // "time": 1538725500422,
+ // "symbol": "ETHBTC",
+ // "lastPrice": "4.00000200",
+ // "openPrice": "99.00000000",
+ // "highPrice": "100.00000000",
+ // "lowPrice": "0.10000000",
+ // "volume": "8913.30000000"
+ // },
+ // ]
+ //
+ return this.parseTickers (response, symbols);
+ }
+
+ async fetchBalance (params = {}) {
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchBalance', {});
+ const defaultType = this.safeString (options, 'type', 'spot');
+ const type = this.safeString (params, 'type', defaultType);
+ const query = this.omit (params, 'type');
+ let method = 'privateGetAccount';
+ if (type === 'future') {
+ method = 'contractGetAccount';
+ } else if (type === 'option') {
+ method = 'optionGetAccount';
+ }
+ const response = await this[method] (query);
+ //
+ // spot
+ //
+ // {
+ // 'balances': [
+ // {
+ // 'asset': 'ALGO',
+ // 'free': '0',
+ // 'locked': '0'
+ // },
+ // {
+ // 'asset': 'BHT',
+ // 'free': '0',
+ // 'locked': '0'
+ // }
+ // ]
+ // }
+ //
+ // contract
+ //
+ // {
+ // "BUSDT":{
+ // "total":"1000",
+ // "availableMargin":"1000",
+ // "positionMargin":"0",
+ // "orderMargin":"0",
+ // "tokenId":"BUSDT"
+ // },
+ // "TBTC":{
+ // "total":"0.5",
+ // "availableMargin":"0.5",
+ // "positionMargin":"0",
+ // "orderMargin":"0",
+ // "tokenId":"TBTC"
+ // }
+ // }
+ //
+ // option
+ //
+ // {
+ // "optionAsset":"",
+ // "balances":[
+ // {
+ // "tokenName":"USDT",
+ // "free":"0.0",
+ // "locked":"0.0",
+ // "margin":"0.0"
+ // },
+ // {
+ // "tokenName":"BUSDT",
+ // "free":"0.0",
+ // "locked":"0.0",
+ // "margin":"0.0"
+ // }
+ // ]
+ // }
+ //
+ const balances = this.safeValue (response, 'balances');
+ const result = { 'info': response };
+ if (balances !== undefined) {
+ for (let i = 0; i < balances.length; i++) {
+ const balance = balances[i];
+ const currencyId = this.safeString2 (balance, 'asset', 'tokenName');
+ const code = this.safeCurrencyCode (currencyId);
+ const account = this.account ();
+ account['free'] = this.safeFloat (balance, 'free');
+ account['used'] = this.safeFloat (balance, 'locked');
+ result[code] = account;
+ }
+ } else {
+ const currencyIds = Object.keys (response);
+ for (let i = 0; i < currencyIds.length; i++) {
+ const currencyId = currencyIds[i];
+ const code = this.safeCurrencyCode (currencyId);
+ const balance = response[currencyId];
+ const account = this.account ();
+ account['free'] = this.safeFloat (balance, 'availableMargin');
+ account['total'] = this.safeFloat (balance, 'total');
+ result[code] = account;
+ }
+ }
+ return this.parseBalance (result);
+ }
+
+ async fetchTrades (symbol, since = undefined, limit = 50, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ };
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ const response = await this.quoteGetTrades (this.extend (request, params));
+ //
+ // [
+ // {"price":"0.025344","time":1588084082060,"qty":"1","isBuyerMaker":false},
+ // {"price":"0.02535","time":1588084086021,"qty":"0.553","isBuyerMaker":true},
+ // {"price":"0.025348","time":1588084097037,"qty":"1","isBuyerMaker":false},
+ // ]
+ //
+ return this.parseTrades (response, market, since, limit);
+ }
+
+ parseOHLCV (ohlcv, market = undefined, timeframe = '1m', since = undefined, limit = undefined) {
+ //
+ // [
+ // 1587906000000, // open time
+ // "0.1761", // open
+ // "0.1761", // high
+ // "0.1761", // low
+ // "0.1761", // close
+ // "0", // base volume
+ // 0, // close time
+ // "0", // quote volume
+ // 0, // number of trades
+ // "0", // taker buy base asset volume
+ // "0" // taker buy quote asset volume
+ // ]
+ //
+ return [
+ this.safeInteger (ohlcv, 0),
+ this.safeFloat (ohlcv, 1),
+ this.safeFloat (ohlcv, 2),
+ this.safeFloat (ohlcv, 3),
+ this.safeFloat (ohlcv, 4),
+ this.safeFloat (ohlcv, 5),
+ ];
+ }
+
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const request = {
+ 'symbol': market['id'],
+ 'interval': this.timeframes[timeframe],
+ };
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 500
+ }
+ const response = await this.quoteGetKlines (this.extend (request, params));
+ //
+ // [
+ // [1587906000000,"0.1761","0.1761","0.1761","0.1761","0",0,"0",0,"0","0"],
+ // [1587906180000,"0.1761","0.1761","0.1761","0.1761","0",0,"0",0,"0","0"],
+ // [1587906360000,"0.1761","0.1848","0.1761","0.1848","53",0,"9.7944",1,"0","0"],
+ // ]
+ //
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
+ }
+
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if only fromId is set,it will get orders < that fromId in descending order
+ // if only toId is set, it will get orders > that toId in ascending order
+ // if fromId is set and toId is set, it will get orders < that fromId and > that toId in descending order
+ // if fromId is not set and toId it not set, most recent order are returned in descending order
+ // 'fromId': '43287482374',
+ // 'toId': '43287482374',
+ // 'endTime': this.milliseconds (), // optional, spot only
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchMyTrades', {});
+ const fetchMyTradesType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchMyTradesType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ // spot default 500, max 1000
+ // futures and options default 20, max 1000
+ request['limit'] = limit;
+ }
+ let method = 'privateGetMyTrades';
+ if (type === 'future') {
+ method = 'contractGetMyTrades';
+ } else {
+ if (type === 'option') {
+ method = 'optionGetMyTrades';
+ } else {
+ if (symbol === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a `symbol` argument for ' + type + ' markets');
+ }
+ const market = this.market (symbol);
+ request['symbol'] = market['id'];
+ // spot only?
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ }
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // "id":"616384027512920576",
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616384027202542080",
+ // "matchOrderId":"605124954767266560",
+ // "price":"6826.06",
+ // "qty":"0.1",
+ // "commission":"0.682606",
+ // "commissionAsset":"BUSDT",
+ // "time":"1588214701982",
+ // "isBuyer":false,
+ // "isMaker":false,
+ // "fee":{
+ // "feeTokenId":"BUSDT",
+ // "feeTokenName":"BUSDT",
+ // "fee":"0.682606"
+ // }
+ // }
+ // ]
+ //
+ return this.parseTrades (response, market, since, limit);
+ }
+
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
+ await this.loadMarkets ();
+ const market = this.market (symbol);
+ const orderSide = side.toUpperCase ();
+ const orderType = type.toUpperCase ();
+ const request = {
+ 'symbol': market['id'],
+ // BUY or SELL for spot and options
+ 'side': orderSide,
+ // GTC, FOK, IOC for spot and options
+ // GTC, FOK, IOC, LIMIT_MAKER for futures
+ // 'timeInForce': 'GTC',
+ };
+ let query = params;
+ let method = 'privatePostOrder';
+ if (market['type'] === 'future') {
+ if ((orderSide !== 'BUY_OPEN') && (orderSide !== 'SELL_OPEN') && (orderSide !== 'BUY_CLOSE') && (orderSide !== 'SELL_CLOSE')) {
+ throw new NotSupported (this.id + ' createOrder() does not support order side ' + side + ' for ' + market['type'] + ' markets, only BUY_OPEN, SELL_OPEN, BUY_CLOSE and SELL_CLOSE are supported');
+ }
+ if ((orderType !== 'LIMIT') && (orderType !== 'STOP')) {
+ throw new NotSupported (this.id + ' createOrder() does not support order type ' + type + ' for ' + market['type'] + ' markets, only LIMIT and STOP are supported');
+ }
+ const clientOrderId = this.safeValue (params, 'clientOrderId');
+ if (clientOrderId === undefined) {
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a clientOrderId parameter for ' + market['type'] + ' markets, supply clientOrderId in the params argument');
+ }
+ const leverage = this.safeValue (params, 'leverage');
+ if (leverage === undefined && (orderSide === 'BUY_OPEN' || orderSide === 'SELL_OPEN')) {
+ throw new NotSupported (this.id + ' createOrder() requires a leverage parameter for ' + market['type'] + ' markets if orderSide is BUY_OPEN or SELL_OPEN');
+ }
+ method = 'contractPostOrder';
+ const priceType = this.safeString (params, 'priceType');
+ if (priceType === undefined) {
+ request['price'] = this.priceToPrecision (symbol, price);
+ } else {
+ request['priceType'] = priceType;
+ if (priceType === 'INPUT') {
+ request['price'] = this.priceToPrecision (symbol, price);
+ }
+ }
+ request['orderType'] = type.toUpperCase (); // LIMIT, STOP
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ // request['leverage'] = 1; // not required for closing orders
+ request['leverage'] = leverage;
+ request['clientOrderId'] = clientOrderId;
+ // optional
+ // request['priceType'] = 'INPUT', // INPUT, OPPONENT, QUEUE, OVER, MARKET
+ // request['triggerPrice'] = 123.45;
+ } else {
+ if (market['type'] === 'option') {
+ method = 'optionPostOrder';
+ }
+ const newClientOrderId = this.safeValue2 (params, 'clientOrderId', 'newClientOrderId');
+ if (newClientOrderId !== undefined) {
+ request['newClientOrderId'] = newClientOrderId;
+ }
+ request['type'] = orderType;
+ if (type === 'limit') {
+ request['price'] = this.priceToPrecision (symbol, price);
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ } else if (type === 'market') {
+ // for market buy it requires the amount of quote currency to spend
+ if (side === 'buy') {
+ const createMarketBuyOrderRequiresPrice = this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true);
+ if (createMarketBuyOrderRequiresPrice) {
+ if (price !== undefined) {
+ amount = amount * price;
+ } else {
+ throw new InvalidOrder (this.id + " createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false and supply the total cost value in the 'amount' argument (the exchange-specific behaviour)");
+ }
+ }
+ const precision = market['precision']['price'];
+ request['quantity'] = this.decimalToPrecision (amount, TRUNCATE, precision, this.precisionMode);
+ } else {
+ request['quantity'] = this.amountToPrecision (symbol, amount);
+ }
+ }
+ }
+ query = this.omit (query, [ 'clientOrderId', 'newClientOrderId' ]);
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // {
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616376654496877056",
+ // "clientOrderId":"158821382304516955",
+ // "transactTime":"1588213823080",
+ // "price":"0",
+ // "origQty":"1000",
+ // "executedQty":"0",
+ // "status":"NEW",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"BUY"
+ // }
+ //
+ // contract
+ //
+ // {
+ // 'time': '1570759718825',
+ // 'updateTime': '0',
+ // 'orderId': '469961015902208000',
+ // 'clientOrderId': '6423344174',
+ // 'symbol': 'BTC-PERP-REV',
+ // 'price': '8200',
+ // 'leverage': '12.08',
+ // 'origQty': '5',
+ // 'executedQty': '0',
+ // 'avgPrice': '0',
+ // 'marginLocked': '0.00005047',
+ // 'orderType': 'LIMIT',
+ // 'side': 'BUY_OPEN',
+ // 'fees': [],
+ // 'timeInForce': 'GTC',
+ // 'status': 'NEW',
+ // 'priceType': 'INPUT'
+ // }
+ //
+ return this.parseOrder (response, market);
+ }
+
+ async cancelOrder (id, symbol = undefined, params = {}) {
+ await this.loadMarkets ();
+ const clientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
+ const request = {};
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'cancelOrder', {});
+ const cancelOrderType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', cancelOrderType);
+ let query = this.omit (params, 'type');
+ if (clientOrderId !== undefined) {
+ request['origClientOrderId'] = clientOrderId;
+ query = this.omit (query, [ 'origClientOrderId', 'clientOrderId' ]);
+ } else {
+ request['orderId'] = id;
+ }
+ let method = 'privateDeleteOrder';
+ const orderType = this.safeString (query, 'orderType');
+ if (orderType !== undefined) {
+ type = 'future';
+ }
+ if (type === 'future') {
+ method = 'contractDeleteOrderCancel';
+ if (orderType === undefined) {
+ throw new ArgumentsRequired (this.id + " cancelOrder() requires an orderType parameter, pass the { 'orderType': 'LIMIT' } or { 'orderType': 'STOP' } in params argument");
+ }
+ request['orderType'] = orderType;
+ } else {
+ if (type === 'option') {
+ method = 'optionDeleteOrderCancel';
+ }
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // {
+ // 'exchangeId': '301',
+ // 'symbol': 'BHTUSDT',
+ // 'clientOrderId': '0',
+ // 'orderId': '499890200602846976',
+ // 'status': 'CANCELED'
+ // }
+ //
+ // futures
+ //
+ // {
+ // "time":"1588353669383",
+ // "updateTime":"0",
+ // "orderId":"617549770304599296",
+ // "clientOrderId":"test-001",
+ // "symbol":"BTC-PERP-REV",
+ // "price":"10000",
+ // "leverage":"1",
+ // "origQty":"100",
+ // "executedQty":"0",
+ // "avgPrice":"0",
+ // "marginLocked":"0",
+ // "orderType":"LIMIT",
+ // "side":"SELL_OPEN",
+ // "fees":[],
+ // "timeInForce":"GTC",
+ // "status":"CANCELED",
+ // "priceType":"INPUT",
+ // }
+ //
+ return this.parseOrder (response);
+ }
+
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if orderId is set, it will get orders < that orderId otherwise most recent orders are returned
+ // 'orderId': '43287482374',
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchOpenOrders', {});
+ const fetchOpenOrdersType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchOpenOrdersType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ let method = 'privateGetOpenOrders';
+ if (type === 'future') {
+ method = 'contractGetOpenOrders';
+ } else if (type === 'option') {
+ method = 'optionGetOpenOrders';
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // 'orderId': '499902955766523648',
+ // 'clientOrderId': '157432907618453',
+ // 'exchangeId': '301',
+ // 'symbol': 'BHTUSDT',
+ // 'price': '0.01',
+ // 'origQty': '50',
+ // 'executedQty': '0',
+ // 'cummulativeQuoteQty': '0',
+ // 'avgPrice': '0',
+ // 'status': 'NEW',
+ // 'timeInForce': 'GTC',
+ // 'type': 'LIMIT',
+ // 'side': 'BUY',
+ // 'stopPrice': '0.0',
+ // 'icebergQty': '0.0',
+ // 'time': '1574329076202',
+ // 'updateTime': '0',
+ // 'isWorking': true
+ // }
+ // ]
+ //
+ // futures
+ //
+ // [
+ // {
+ // "time":"1588353669383",
+ // "updateTime":"0",
+ // "orderId":"617549770304599296",
+ // "clientOrderId":"test-001",
+ // "symbol":"BTC-PERP-REV",
+ // "price":"10000",
+ // "leverage":"1",
+ // "origQty":"100",
+ // "executedQty":"0",
+ // "avgPrice":"0",
+ // "marginLocked":"0.01",
+ // "orderType":"LIMIT",
+ // "side":"SELL_OPEN",
+ // "fees":[],
+ // "timeInForce":"GTC",
+ // "status":"NEW",
+ // "priceType":"INPUT"
+ // }
+ // ]
+ //
+ return this.parseOrders (response, market, since, limit);
+ }
+
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let market = undefined;
+ const request = {
+ // if orderId is set, it will get orders < that orderId otherwise most recent orders are returned
+ // 'orderId': '43287482374',
+ // 'endTime': this.milliseconds (), // optional
+ };
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchClosedOrders', {});
+ const fetchClosedOrdersType = this.safeString (options, 'type', defaultType);
+ let type = this.safeString (params, 'type', fetchClosedOrdersType);
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['symbol'] = market['id'];
+ type = market['type'];
+ }
+ const query = this.omit (params, 'type');
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ let method = 'privateGetHistoryOrders';
+ if (type === 'future') {
+ method = 'contractGetHistoryOrders';
+ } else if (type === 'option') {
+ method = 'optionGetHistoryOrders';
+ }
+ const response = await this[method] (this.extend (request, query));
+ //
+ // spot
+ //
+ // [
+ // {
+ // "orderId":"616384027202542080",
+ // "clientOrderId":"158821470194414688",
+ // "exchangeId":"301",
+ // "symbol":"TBTCBUSDT",
+ // "price":"0",
+ // "origQty":"0.1",
+ // "executedQty":"0.1",
+ // "cummulativeQuoteQty":"682.606",
+ // "avgPrice":"6826.06",
+ // "status":"FILLED",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"SELL",
+ // "stopPrice":"0.0",
+ // "icebergQty":"0.0",
+ // "time":"1588214701974",
+ // "updateTime":"0",
+ // "isWorking":true
+ // }
+ // ]
+ //
+ return this.parseOrders (response, market, since, limit);
+ }
+
+ async fetchOrder (id, symbol = undefined, params = {}) {
+ await this.loadMarkets ();
+ const clientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
+ const request = {};
+ const defaultType = this.safeString (this.options, 'type', 'spot');
+ const options = this.safeValue (this.options, 'fetchOrder', {});
+ const fetchOrderType = this.safeString (options, 'type', defaultType);
+ const type = this.safeString (params, 'type', fetchOrderType);
+ let query = this.omit (params, 'type');
+ if (clientOrderId !== undefined) {
+ request['origClientOrderId'] = clientOrderId;
+ query = this.omit (query, [ 'origClientOrderId', 'clientOrderId' ]);
+ } else {
+ request['orderId'] = id;
+ }
+ let method = 'privateGetOrder';
+ if (type === 'future') {
+ method = 'contractGetGetOrder';
+ } else if (type === 'option') {
+ method = 'optionGetGetOrder';
+ }
+ const response = await this[method] (this.extend (request, query));
+ return this.parseOrder (response);
+ }
+
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let currency = undefined;
+ const request = {
+ // 'fromId': 'string', // if fromId is set, it will get deposits > that fromId, otherwise most recent deposits are returned
+ };
+ if (code !== undefined) {
+ currency = this.currency (code);
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit;
+ }
+ const response = await this.privateGetDepositOrders (this.extend (request, params));
+ //
+ // [
+ // {
+ // 'time': '1565769575929',
+ // 'orderId': '428100569859739648',
+ // 'token': 'USDT',
+ // 'address': '',
+ // 'addressTag': '',
+ // 'fromAddress': '',
+ // 'fromAddressTag': '',
+ // 'quantity': '1100',
+ // },
+ // ]
+ //
+ return this.parseTransactions (response, currency, since, limit);
+ }
+
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ let currency = undefined;
+ const request = {
+ // 'fromId': 'string', // if fromId is set, it will get deposits > that fromId, otherwise most recent deposits are returned
+ };
+ if (code !== undefined) {
+ currency = this.currency (code);
+ request['token'] = currency['id'];
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 1000
+ }
+ const response = await this.privateGetWithdrawalOrders (this.extend (request, params));
+ //
+ // [
+ // {
+ // "time":"1536232111669",
+ // "orderId":"90161227158286336",
+ // "accountId":"517256161325920",
+ // "tokenId":"BHC",
+ // "tokenName":"BHC",
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
+ // "addressExt":"address tag",
+ // "quantity":"14", // Withdrawal qty
+ // "arriveQuantity":"14", // Arrived qty
+ // "statusCode":"PROCESSING_STATUS",
+ // "status":3,
+ // "txid":"",
+ // "txidUrl":"",
+ // "walletHandleTime":"1536232111669",
+ // "feeTokenId":"BHC",
+ // "feeTokenName":"BHC",
+ // "fee":"0.1",
+ // "requiredConfirmNum":0, // Required confirmations
+ // "confirmNum":0, // Confirmations
+ // "kernelId":"", // BEAM and GRIN only
+ // "isInternalTransfer": false // True if this transfer is internal
+ // }
+ // ]
+ //
+ return this.parseTransactions (response, currency, since, limit);
+ }
+
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
+ this.checkAddress (address);
+ await this.loadMarkets ();
+ const currency = this.currency (code);
+ const clientOrderId = this.safeString (params, 'clientOrderId', this.uuid ());
+ const request = {
+ 'clientOrderId': clientOrderId,
+ 'tokenId': currency['id'],
+ 'address': address, // the withdrawal address must be in current tag list in your PC/APP client
+ 'withdrawQuantity': amount,
+ // 'chainType': 'OMNI', // OMNI, ERC20, TRC20
+ };
+ if (tag !== undefined) {
+ request['addressExt'] = tag;
+ }
+ const response = await this.privatePostWithdraw (this.extend (request, params));
+ //
+ // {
+ // "status": 0,
+ // "success": true,
+ // "needBrokerAudit": false, // Whether this request needs broker auit
+ // "orderId": "423885103582776064" // Id for successful withdrawal
+ // }
+ //
+ return {
+ 'info': response,
+ 'id': this.safeString (response, 'orderId'),
+ };
+ }
+
+ async fetchAccounts (params = {}) {
+ const response = await this.privatePostSubAccountQuery (params);
+ //
+ // [
+ // {
+ // "accountId": "122216245228131",
+ // "accountName": "createSubAccountByCurl", // sub-account name
+ // "accountType": 1, // 1 token trading, 2 options, 3 futures
+ // "accountIndex": 1, // 0 main account, 1 sub-account
+ // },
+ // ]
+ //
+ const result = [];
+ for (let i = 0; i < response.length; i++) {
+ const account = response[i];
+ const accountId = this.safeString (account, 'accountId');
+ const accountType = this.safeString (account, 'accountType');
+ let type = accountType;
+ if (accountType === '1') {
+ type = 'spot';
+ } else if (accountType === '2') {
+ type = 'option';
+ } else if (accountType === '3') {
+ type = 'future';
+ }
+ result.push ({
+ 'id': accountId,
+ 'type': type,
+ 'currency': undefined,
+ 'info': account,
+ });
+ }
+ return result;
+ }
+
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
+ await this.loadMarkets ();
+ const request = {
+ 'accountType': 1, // spot 1, options 2, futures 3
+ 'accountIndex': 0, // main 0, sub-account 1
+ 'fromFlowId': '', // flowId to start from
+ 'endFlowId': '', // flowId to end with
+ 'endTime': 1588450533040,
+ };
+ let currency = undefined;
+ if (code !== undefined) {
+ currency = this.currency (code);
+ request['tokenId'] = currency['id'];
+ }
+ if (since !== undefined) {
+ request['startTime'] = since;
+ }
+ if (limit !== undefined) {
+ request['limit'] = limit; // default 500, max 500
+ }
+ const response = await this.privateGetBalanceFlow (this.extend (request, params));
+ //
+ // [
+ // {
+ // "id": "539870570957903104",
+ // "accountId": "122216245228131",
+ // "tokenId": "BTC",
+ // "tokenName": "BTC",
+ // "flowTypeValue": 51,
+ // "flowType": "USER_ACCOUNT_TRANSFER",
+ // "flowName": "Transfer",
+ // "change": "-12.5",
+ // "total": "379.624059937852365", // after change
+ // "created": "1579093587214"
+ // },
+ // {
+ // "id": "536072393645448960",
+ // "accountId": "122216245228131",
+ // "tokenId": "USDT",
+ // "tokenName": "USDT",
+ // "flowTypeValue": 7,
+ // "flowType": "AIRDROP",
+ // "flowName": "Airdrop",
+ // "change": "-2000",
+ // "total": "918662.0917630848",
+ // "created": "1578640809195"
+ // }
+ // ]
+ //
+ return this.parseLedger (response, currency, since, limit);
+ }
+
+ parseLedgerEntry (item, currency = undefined) {
+ //
+ // {
+ // "id": "539870570957903104",
+ // "accountId": "122216245228131",
+ // "tokenId": "BTC",
+ // "tokenName": "BTC",
+ // "flowTypeValue": 51,
+ // "flowType": "USER_ACCOUNT_TRANSFER",
+ // "flowName": "Transfer",
+ // "change": "-12.5",
+ // "total": "379.624059937852365", // after change
+ // "created": "1579093587214"
+ // }
+ //
+ // {
+ // "id": "536072393645448960",
+ // "accountId": "122216245228131",
+ // "tokenId": "USDT",
+ // "tokenName": "USDT",
+ // "flowTypeValue": 7,
+ // "flowType": "AIRDROP",
+ // "flowName": "Airdrop",
+ // "change": "-2000",
+ // "total": "918662.0917630848",
+ // "created": "1578640809195"
+ // }
+ //
+ const currencyId = this.safeString (item, 'tokenId');
+ const code = this.safeCurrencyCode (currencyId, currency);
+ const amount = this.safeFloat (item, 'change');
+ const after = this.safeFloat (item, 'total');
+ const direction = (amount < 0) ? 'out' : 'in';
+ let before = undefined;
+ if (after !== undefined && amount !== undefined) {
+ const difference = (direction === 'out') ? amount : -amount;
+ before = this.sum (after, difference);
+ }
+ const timestamp = this.safeInteger (item, 'created');
+ const type = this.parseLedgerEntryType (this.safeString (item, 'flowType'));
+ const id = this.safeString (item, 'id');
+ const account = this.safeString (item, 'accountId');
+ return {
+ 'id': id,
+ 'currency': code,
+ 'account': account,
+ 'referenceAccount': undefined,
+ 'referenceId': undefined,
+ 'status': undefined,
+ 'amount': amount,
+ 'before': before,
+ 'after': after,
+ 'fee': undefined,
+ 'direction': direction,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'type': type,
+ 'info': item,
+ };
+ }
+
+ parseLedgerEntryType (type) {
+ const types = {
+ 'TRADE': 'trade',
+ 'FEE': 'fee',
+ 'TRANSFER': 'transfer',
+ 'DEPOSIT': 'transaction',
+ 'MAKER_REWARD': 'rebate',
+ 'PNL': 'pnl',
+ 'SETTLEMENT': 'settlement',
+ 'LIQUIDATION': 'liquidation',
+ 'FUNDING_SETTLEMENT': 'settlement',
+ 'USER_ACCOUNT_TRANSFER': 'transfer',
+ 'OTC_BUY_COIN': 'trade',
+ 'OTC_SELL_COIN': 'trade',
+ 'OTC_FEE': 'fee',
+ 'OTC_TRADE': 'trade',
+ 'ACTIVITY_AWARD': 'referral',
+ 'INVITATION_REFERRAL_BONUS': 'referral',
+ 'REGISTER_BONUS': 'referral',
+ 'AIRDROP': 'airdrop',
+ 'MINE_REWARD': 'reward',
+ };
+ return this.safeString (types, type, type);
+ }
+
+ parseTransactionStatus (status) {
+ const statuses = {
+ 'BROKER_AUDITING_STATUS': 'pending',
+ 'BROKER_REJECT_STATUS': 'failed',
+ 'AUDITING_STATUS': 'pending',
+ 'AUDIT_REJECT_STATUS': 'failed',
+ 'PROCESSING_STATUS': 'pending',
+ 'WITHDRAWAL_SUCCESS_STATUS': 'ok',
+ 'WITHDRAWAL_FAILURE_STATUS': 'failed',
+ 'BLOCK_MINING_STATUS': 'ok',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ parseTransaction (transaction, currency = undefined) {
+ //
+ // fetchDeposits
+ //
+ // {
+ // 'time': '1565769575929',
+ // 'orderId': '428100569859739648',
+ // 'token': 'USDT',
+ // 'address': '',
+ // 'addressTag': '',
+ // 'fromAddress': '',
+ // 'fromAddressTag': '',
+ // 'quantity': '1100',
+ // }
+ //
+ // fetchWithdrawals
+ //
+ // {
+ // "time":"1536232111669",
+ // "orderId":"90161227158286336",
+ // "accountId":"517256161325920",
+ // "tokenId":"BHC",
+ // "tokenName":"BHC",
+ // "address":"0x815bF1c3cc0f49b8FC66B21A7e48fCb476051209",
+ // "addressExt":"address tag",
+ // "quantity":"14", // Withdrawal qty
+ // "arriveQuantity":"14", // Arrived qty
+ // "statusCode":"PROCESSING_STATUS",
+ // "status":3,
+ // "txid":"",
+ // "txidUrl":"",
+ // "walletHandleTime":"1536232111669",
+ // "feeTokenId":"BHC",
+ // "feeTokenName":"BHC",
+ // "fee":"0.1",
+ // "requiredConfirmNum":0, // Required confirmations
+ // "confirmNum":0, // Confirmations
+ // "kernelId":"", // BEAM and GRIN only
+ // "isInternalTransfer": false // True if this transfer is internal
+ // }
+ //
+ const id = this.safeString (transaction, 'orderId');
+ const address = this.safeString (transaction, 'address');
+ let tag = this.safeString2 (transaction, 'addressExt', 'addressTag');
+ if (tag !== undefined) {
+ if (tag.length < 1) {
+ tag = undefined;
+ }
+ }
+ const addressFrom = this.safeString (transaction, 'fromAddress');
+ let tagFrom = this.safeString (transaction, 'fromAddressTag');
+ if (tagFrom !== undefined) {
+ if (tagFrom.length < 1) {
+ tagFrom = undefined;
+ }
+ }
+ const currencyId = this.safeString (transaction, 'tokenId');
+ const code = this.safeCurrencyCode (currencyId, currency);
+ const timestamp = this.safeInteger (transaction, 'time');
+ let txid = this.safeString (transaction, 'txid');
+ if (txid === '') {
+ txid = undefined;
+ }
+ let type = undefined;
+ let status = this.parseTransactionStatus (this.safeString (transaction, 'statusCode'));
+ if (status === undefined) {
+ type = 'deposit';
+ status = 'ok';
+ } else {
+ type = 'withdrawal';
+ }
+ const amount = this.safeFloat (transaction, 'quantity');
+ const feeCost = this.safeFloat (transaction, 'fee');
+ let fee = undefined;
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (transaction, 'feeTokenId');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ fee = {
+ 'currency': feeCurrencyCode,
+ 'cost': feeCost,
+ };
+ }
+ return {
+ 'info': transaction,
+ 'id': id,
+ 'txid': txid,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'addressFrom': addressFrom,
+ 'address': address,
+ 'addressTo': address,
+ 'tagFrom': tagFrom,
+ 'tag': tag,
+ 'tagTo': tag,
+ 'type': type,
+ 'amount': amount,
+ 'currency': code,
+ 'status': status,
+ 'updated': undefined,
+ 'fee': fee,
+ };
+ }
+
+ parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker, fetchTickers
+ //
+ // {
+ // "time":1588069860794,
+ // "symbol":"BNB0501PS16",
+ // "bestBidPrice":"0.2129",
+ // "bestAskPrice":"0.3163",
+ // "volume":"33547",
+ // "quoteVolume":"10801.987",
+ // "lastPrice":"0.2625",
+ // "highPrice":"0.3918",
+ // "lowPrice":"0.2625",
+ // "openPrice":"0.362",
+ // }
+ //
+ // fetchBidAsk, fetchBidAsks
+ //
+ // {
+ // "symbol": "LTCBTC",
+ // "bidPrice": "4.00000000",
+ // "bidQty": "431.00000000",
+ // "askPrice": "4.00000200",
+ // "askQty": "9.00000000"
+ // }
+ //
+ let symbol = undefined;
+ const marketId = this.safeString (ticker, 'symbol');
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ const timestamp = this.safeInteger (ticker, 'time');
+ const open = this.safeFloat (ticker, 'openPrice');
+ const close = this.safeFloat (ticker, 'lastPrice');
+ let change = undefined;
+ let percentage = undefined;
+ let average = undefined;
+ if ((open !== undefined) && (close !== undefined)) {
+ change = close - open;
+ average = this.sum (open, close) / 2;
+ if ((close !== undefined) && (close > 0)) {
+ percentage = (change / open) * 100;
+ }
+ }
+ const quoteVolume = this.safeFloat (ticker, 'quoteVolume');
+ const baseVolume = this.safeFloat (ticker, 'volume');
+ let vwap = undefined;
+ if (baseVolume !== undefined && quoteVolume !== undefined && baseVolume > 0) {
+ vwap = quoteVolume / baseVolume;
+ }
+ return {
+ 'symbol': symbol,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'high': this.safeFloat (ticker, 'highPrice'),
+ 'low': this.safeFloat (ticker, 'lowPrice'),
+ 'bid': this.safeFloat2 (ticker, 'bestBidPrice', 'bidPrice'),
+ 'bidVolume': this.safeFloat (ticker, 'bidQty'),
+ 'ask': this.safeFloat2 (ticker, 'bestAskPrice', 'askPrice'),
+ 'askVolume': this.safeFloat (ticker, 'askQty'),
+ 'vwap': vwap,
+ 'open': open,
+ 'close': close,
+ 'last': close,
+ 'previousClose': undefined,
+ 'change': change,
+ 'percentage': percentage,
+ 'average': average,
+ 'baseVolume': baseVolume,
+ 'quoteVolume': quoteVolume,
+ 'info': ticker,
+ };
+ }
+
+ parseTrade (trade, market) {
+ //
+ // fetchTrades (public)
+ //
+ // {
+ // "price":"0.025344",
+ // "time":1588084082060,
+ // "qty":"1",
+ // "isBuyerMaker":false
+ // }
+ //
+ // fetchMyTrades (private)
+ //
+ // spot
+ //
+ // {
+ // "id":"616384027512920576",
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616384027202542080",
+ // "matchOrderId":"605124954767266560",
+ // "price":"6826.06",
+ // "qty":"0.1",
+ // "commission":"0.682606",
+ // "commissionAsset":"BUSDT",
+ // "time":"1588214701982",
+ // "isBuyer":false,
+ // "isMaker":false,
+ // "fee":{
+ // "feeTokenId":"BUSDT",
+ // "feeTokenName":"BUSDT",
+ // "fee":"0.682606"
+ // }
+ // }
+ //
+ const id = this.safeString (trade, 'id');
+ const timestamp = this.safeFloat (trade, 'time');
+ const type = undefined;
+ const orderId = this.safeString (trade, 'orderId');
+ const price = this.safeFloat (trade, 'price');
+ const amount = this.safeFloat (trade, 'qty');
+ let cost = undefined;
+ if (price !== undefined) {
+ if (amount !== undefined) {
+ cost = price * amount;
+ }
+ }
+ let side = undefined;
+ let takerOrMaker = undefined;
+ if ('isBuyerMaker' in trade) {
+ side = trade['isBuyerMaker'] ? 'sell' : 'buy';
+ } else {
+ const isMaker = this.safeValue (trade, 'isMaker');
+ if (isMaker !== undefined) {
+ takerOrMaker = isMaker ? 'maker' : 'taker';
+ }
+ const isBuyer = this.safeValue (trade, 'isBuyer');
+ side = isBuyer ? 'buy' : 'sell';
+ }
+ let fee = undefined;
+ const feeCost = this.safeFloat (trade, 'commission');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (trade, 'commissionAsset');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ fee = {
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ };
+ }
+ let symbol = undefined;
+ if ((symbol === undefined) && (market !== undefined)) {
+ symbol = market['symbol'];
+ }
+ return {
+ 'id': id,
+ 'info': trade,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'symbol': symbol,
+ 'type': type,
+ 'order': orderId,
+ 'side': side,
+ 'takerOrMaker': takerOrMaker,
+ 'price': price,
+ 'amount': amount,
+ 'cost': cost,
+ 'fee': fee,
+ };
+ }
+
+ parseOrder (order, market = undefined) {
+ //
+ // createOrder
+ //
+ // {
+ // "symbol":"TBTCBUSDT",
+ // "orderId":"616376654496877056",
+ // "clientOrderId":"158821382304516955",
+ // "transactTime":"1588213823080",
+ // "price":"0",
+ // "origQty":"1000",
+ // "executedQty":"0",
+ // "status":"NEW",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"BUY"
+ // }
+ //
+ // fetchOrder, fetchOpenOrders, fetchClosedOrders
+ //
+ // spot
+ //
+ // {
+ // "orderId":"616384027202542080",
+ // "clientOrderId":"158821470194414688",
+ // "exchangeId":"301",
+ // "symbol":"TBTCBUSDT",
+ // "price":"0",
+ // "origQty":"0.1",
+ // "executedQty":"0.1",
+ // "cummulativeQuoteQty":"682.606",
+ // "avgPrice":"6826.06",
+ // "status":"FILLED",
+ // "timeInForce":"GTC",
+ // "type":"MARKET",
+ // "side":"SELL",
+ // "stopPrice":"0.0",
+ // "icebergQty":"0.0",
+ // "time":"1588214701974",
+ // "updateTime":"0",
+ // "isWorking":true
+ // }
+ //
+ // future
+ //
+ // {
+ // time: "1588353669383",
+ // updateTime: "0",
+ // orderId: "617549770304599296",
+ // clientOrderId: "test-001",
+ // symbol: "BTC-PERP-REV",
+ // price: "10000",
+ // leverage: "1",
+ // origQty: "100",
+ // executedQty: "0",
+ // avgPrice: "0",
+ // marginLocked: "0",
+ // orderType: "LIMIT",
+ // side: "SELL_OPEN",
+ // fees: [],
+ // timeInForce: "GTC",
+ // status: "CANCELED",
+ // priceType: "INPUT"
+ // }
+ //
+ //
+ const id = this.safeString (order, 'orderId');
+ const clientOrderId = this.safeString (order, 'clientOrderId');
+ let timestamp = this.safeInteger (order, 'time');
+ if (timestamp === undefined) {
+ timestamp = this.safeInteger (order, 'transactTime');
+ }
+ let symbol = undefined;
+ if (market === undefined) {
+ let marketId = this.safeString (order, 'symbol');
+ if (marketId !== undefined) {
+ marketId = marketId.toUpperCase ();
+ if (marketId in this.markets_by_id) {
+ market = this.markets_by_id[marketId];
+ }
+ }
+ }
+ let type = this.safeStringLower (order, 'type');
+ const side = this.safeStringLower (order, 'side');
+ let price = this.safeFloat (order, 'price');
+ let average = this.safeFloat (order, 'avgPrice');
+ let amount = undefined;
+ let cost = this.safeFloat (order, 'cummulativeQuoteQty');
+ let filled = undefined;
+ let remaining = undefined;
+ if (type === undefined) {
+ type = this.safeStringLower (order, 'orderType');
+ if ((market !== undefined) && market['inverse']) {
+ cost = this.safeFloat (order, 'executedQty');
+ amount = undefined;
+ }
+ if (cost === 0.0) {
+ filled = 0;
+ }
+ } else {
+ amount = this.safeFloat (order, 'origQty');
+ if (type === 'market') {
+ price = undefined;
+ if (side === 'buy') {
+ amount = undefined;
+ }
+ }
+ filled = this.safeFloat (order, 'executedQty');
+ if (filled !== undefined) {
+ if (amount !== undefined) {
+ remaining = amount - filled;
+ }
+ }
+ }
+ if (average === 0.0) {
+ average = undefined;
+ }
+ const status = this.parseOrderStatus (this.safeString (order, 'status'));
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ const result = {
+ 'info': order,
+ 'id': id,
+ 'clientOrderId': clientOrderId,
+ 'timestamp': timestamp,
+ 'datetime': this.iso8601 (timestamp),
+ 'lastTradeTimestamp': undefined,
+ 'symbol': symbol,
+ 'type': type,
+ 'side': side,
+ 'price': price,
+ 'average': average,
+ 'cost': cost,
+ 'amount': amount,
+ 'filled': filled,
+ 'remaining': remaining,
+ 'status': status,
+ 'trades': undefined,
+ 'fee': undefined,
+ 'fees': undefined,
+ };
+ const fees = this.safeValue (order, 'fees', []);
+ const numFees = fees.length;
+ if (numFees > 0) {
+ result['fees'] = [];
+ for (let i = 0; i < fees.length; i++) {
+ const feeCost = this.safeFloat (fees[i], 'fee');
+ if (feeCost !== undefined) {
+ const feeCurrencyId = this.safeString (fees[i], 'feeToken');
+ const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
+ result['fees'].push ({
+ 'cost': feeCost,
+ 'currency': feeCurrencyCode,
+ });
+ }
+ }
+ }
+ return result;
+ }
+
+ parseOrderStatus (status) {
+ const statuses = {
+ 'NEW': 'open',
+ 'CANCELED': 'canceled',
+ 'FILLED': 'closed',
+ 'PENDING_CANCEL': 'canceled',
+ };
+ return this.safeString (statuses, status, status);
+ }
+
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
+ let url = this.urls['api'][api] + '/' + this.version + '/' + this.implodeParams (path, params);
+ const query = this.omit (params, this.extractParams (path));
+ const isPublicContract = (api === 'contract') && ((path === 'insurance') || (path === 'fundingRate'));
+ if ((api === 'public') || (api === 'quote') || isPublicContract) {
+ if (Object.keys (params).length) {
+ url += '?' + this.urlencode (params);
+ }
+ } else {
+ const timestamp = this.milliseconds ();
+ this.checkRequiredCredentials ();
+ const request = this.extend ({
+ 'timestamp': timestamp,
+ }, query);
+ // 准备待签名数据
+ const auth = this.urlencode (request);
+ const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256');
+ request['signature'] = signature;
+ headers = {
+ 'X-BH-APIKEY': this.apiKey,
+ };
+ if (method === 'POST') {
+ body = this.urlencode (request);
+ headers = this.extend ({
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ }, headers);
+ } else {
+ url += '?' + this.urlencode (request);
+ }
+ }
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
+ }
+
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
+ if (response === undefined) {
+ return; // fallback to default error handler
+ }
+ if ('code' in response) {
+ const code = this.safeString (response, 'code');
+ if (code !== '0') {
+ const feedback = this.id + ' ' + body;
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
+ throw new ExchangeError (feedback);
+ }
+ }
+ }
+};
diff --git a/TaskServer/node_modules/ccxt/js/hitbtc.js b/TaskServer/node_modules/ccxt/js/hitbtc.js
index 6cc535b07..14b6e46a0 100644
--- a/TaskServer/node_modules/ccxt/js/hitbtc.js
+++ b/TaskServer/node_modules/ccxt/js/hitbtc.js
@@ -730,14 +730,13 @@ module.exports = class hitbtc extends Exchange {
}
parseOHLCV (ohlcv, market = undefined, timeframe = '1d', since = undefined, limit = undefined) {
- const timestamp = this.parse8601 (ohlcv['timestamp']);
return [
- timestamp,
- parseFloat (ohlcv['open']),
- parseFloat (ohlcv['max']),
- parseFloat (ohlcv['min']),
- parseFloat (ohlcv['close']),
- parseFloat (ohlcv['volume']),
+ this.parse8601 (this.safeString (ohlcv, 'timestamp')),
+ this.safeFloat (ohlcv, 'open'),
+ this.safeFloat (ohlcv, 'max'),
+ this.safeFloat (ohlcv, 'min'),
+ this.safeFloat (ohlcv, 'close'),
+ this.safeFloat (ohlcv, 'volume'),
];
}
diff --git a/TaskServer/node_modules/ccxt/js/hitbtc2.js b/TaskServer/node_modules/ccxt/js/hitbtc2.js
deleted file mode 100644
index 145d70a92..000000000
--- a/TaskServer/node_modules/ccxt/js/hitbtc2.js
+++ /dev/null
@@ -1,17 +0,0 @@
-'use strict';
-
-// ---------------------------------------------------------------------------
-
-const hitbtc = require ('./hitbtc');
-
-// ---------------------------------------------------------------------------
-
-module.exports = class hitbtc2 extends hitbtc {
- describe () {
- // this is a temporary stub for backward compatibility
- // https://github.com/ccxt/ccxt/issues/6678
- return this.deepExtend (super.describe (), {
- 'id': 'hitbtc2',
- });
- }
-};
diff --git a/TaskServer/node_modules/ccxt/js/huobipro.js b/TaskServer/node_modules/ccxt/js/huobipro.js
index b3b298c49..497cdf9bf 100644
--- a/TaskServer/node_modules/ccxt/js/huobipro.js
+++ b/TaskServer/node_modules/ccxt/js/huobipro.js
@@ -163,12 +163,14 @@ module.exports = class huobipro extends Exchange {
'exceptions': {
'exact': {
// err-code
+ 'bad-request': BadRequest,
'api-not-support-temp-addr': PermissionDenied, // {"status":"error","err-code":"api-not-support-temp-addr","err-msg":"API withdrawal does not support temporary addresses","data":null}
'timeout': RequestTimeout, // {"ts":1571653730865,"status":"error","err-code":"timeout","err-msg":"Request Timeout"}
'gateway-internal-error': ExchangeNotAvailable, // {"status":"error","err-code":"gateway-internal-error","err-msg":"Failed to load data. Try again later.","data":null}
'account-frozen-balance-insufficient-error': InsufficientFunds, // {"status":"error","err-code":"account-frozen-balance-insufficient-error","err-msg":"trade account balance is not enough, left: `0.0027`","data":null}
'invalid-amount': InvalidOrder, // eg "Paramemter `amount` is invalid."
'order-limitorder-amount-min-error': InvalidOrder, // limit order amount error, min: `0.001`
+ 'order-limitorder-amount-max-error': InvalidOrder, // market order amount error, max: `1000000`
'order-marketorder-amount-min-error': InvalidOrder, // market order amount error, min: `0.01`
'order-limitorder-price-min-error': InvalidOrder, // limit order price error
'order-limitorder-price-max-error': InvalidOrder, // limit order price error
@@ -331,6 +333,8 @@ module.exports = class huobipro extends Exchange {
}
parseTicker (ticker, market = undefined) {
+ //
+ // fetchTicker
//
// {
// "amount": 26228.672978342216,
@@ -346,25 +350,47 @@ module.exports = class huobipro extends Exchange {
// "bid": [ 9146.86, 0.080758 ],
// }
//
+ // fetchTickers
+ // {
+ // symbol: "bhdht",
+ // open: 2.3938,
+ // high: 2.4151,
+ // low: 2.3323,
+ // close: 2.3909,
+ // amount: 628.992,
+ // vol: 1493.71841095,
+ // count: 2088,
+ // bid: 2.3643,
+ // bidSize: 0.7136,
+ // ask: 2.4061,
+ // askSize: 0.4156
+ // }
+ //
let symbol = undefined;
if (market !== undefined) {
symbol = market['symbol'];
}
const timestamp = this.safeInteger (ticker, 'ts');
let bid = undefined;
- let ask = undefined;
let bidVolume = undefined;
+ let ask = undefined;
let askVolume = undefined;
if ('bid' in ticker) {
if (Array.isArray (ticker['bid'])) {
bid = this.safeFloat (ticker['bid'], 0);
bidVolume = this.safeFloat (ticker['bid'], 1);
+ } else {
+ bid = this.safeFloat (ticker, 'bid');
+ bidVolume = this.safeValue (ticker, 'bidSize');
}
}
if ('ask' in ticker) {
if (Array.isArray (ticker['ask'])) {
ask = this.safeFloat (ticker['ask'], 0);
askVolume = this.safeFloat (ticker['ask'], 1);
+ } else {
+ ask = this.safeFloat (ticker, 'ask');
+ askVolume = this.safeValue (ticker, 'askSize');
}
}
const open = this.safeFloat (ticker, 'open');
diff --git a/TaskServer/node_modules/ccxt/js/ice3x.js b/TaskServer/node_modules/ccxt/js/ice3x.js
index 1f660df72..73230a5b1 100644
--- a/TaskServer/node_modules/ccxt/js/ice3x.js
+++ b/TaskServer/node_modules/ccxt/js/ice3x.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, AuthenticationError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -221,7 +221,7 @@ module.exports = class ice3x extends Exchange {
const type = this.safeString (params, 'type');
if ((type !== 'ask') && (type !== 'bid')) {
// eslint-disable-next-line quotes
- throw new ExchangeError (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
+ throw new ArgumentsRequired (this.id + " fetchOrderBook requires an exchange-specific extra 'type' param ('bid' or 'ask') when used with a limit");
} else {
request['items_per_page'] = limit;
}
diff --git a/TaskServer/node_modules/ccxt/js/indodax.js b/TaskServer/node_modules/ccxt/js/indodax.js
index 83f7b4e2c..42ee4051e 100644
--- a/TaskServer/node_modules/ccxt/js/indodax.js
+++ b/TaskServer/node_modules/ccxt/js/indodax.js
@@ -362,7 +362,7 @@ module.exports = class indodax extends Exchange {
async fetchOrder (id, symbol = undefined, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + ' fetchOrder requires a symbol');
+ throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -409,7 +409,7 @@ module.exports = class indodax extends Exchange {
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + ' fetchOrders requires a symbol');
+ throw new ArgumentsRequired (this.id + ' fetchOrders requires a symbol argument');
}
await this.loadMarkets ();
const request = {};
@@ -458,7 +458,7 @@ module.exports = class indodax extends Exchange {
}
const side = this.safeValue (params, 'side');
if (side === undefined) {
- throw new ExchangeError (this.id + ' cancelOrder requires an extra "side" param');
+ throw new ArgumentsRequired (this.id + ' cancelOrder requires an extra "side" param');
}
await this.loadMarkets ();
const market = this.market (symbol);
diff --git a/TaskServer/node_modules/ccxt/js/itbit.js b/TaskServer/node_modules/ccxt/js/itbit.js
index f146ae46c..dacb3199f 100644
--- a/TaskServer/node_modules/ccxt/js/itbit.js
+++ b/TaskServer/node_modules/ccxt/js/itbit.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, AuthenticationError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -254,7 +254,7 @@ module.exports = class itbit extends Exchange {
await this.loadMarkets ();
const walletId = this.safeString (params, 'walletId');
if (walletId === undefined) {
- throw new ExchangeError (this.id + ' fetchMyTrades requires a walletId parameter');
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a walletId parameter');
}
const request = {
'walletId': walletId,
diff --git a/TaskServer/node_modules/ccxt/js/kraken.js b/TaskServer/node_modules/ccxt/js/kraken.js
index 7063d9d37..20c36d198 100644
--- a/TaskServer/node_modules/ccxt/js/kraken.js
+++ b/TaskServer/node_modules/ccxt/js/kraken.js
@@ -36,6 +36,7 @@ module.exports = class kraken extends Exchange {
'withdraw': true,
'fetchLedgerEntry': true,
'fetchLedger': true,
+ 'fetchOrderTrades': 'emulated',
},
'marketsByAltname': {},
'timeframes': {
@@ -54,7 +55,7 @@ module.exports = class kraken extends Exchange {
'api': {
'public': 'https://api.kraken.com',
'private': 'https://api.kraken.com',
- 'zendesk': 'https://support.kraken.com/hc/en-us/articles',
+ 'zendesk': 'https://kraken.zendesk.com/api/v2/help_center/en-us/articles', // use the public zendesk api to receive article bodies and bypass new anti-spam protections
},
'www': 'https://www.kraken.com',
'doc': 'https://www.kraken.com/features/api',
@@ -149,9 +150,9 @@ module.exports = class kraken extends Exchange {
'get': [
// we should really refrain from putting fixed fee numbers and stop hardcoding
// we will be using their web APIs to scrape all numbers from these articles
- '205893708-What-is-the-minimum-order-size-',
- '201396777-What-are-the-deposit-fees-',
- '201893608-What-are-the-withdrawal-fees-',
+ '205893708', // -What-is-the-minimum-order-size-
+ '360000292886', // -What-are-the-deposit-fees-
+ '201893608', // -What-are-the-withdrawal-fees-
],
},
'public': {
@@ -234,12 +235,14 @@ module.exports = class kraken extends Exchange {
return this.decimalToPrecision (fee, TRUNCATE, this.markets[symbol]['precision']['amount'], DECIMAL_PLACES);
}
- async fetchMinOrderAmounts () {
- const html = await this.zendeskGet205893708WhatIsTheMinimumOrderSize ();
+ async fetchMinOrderAmounts (params = {}) {
+ const response = await this.zendeskGet205893708 (params);
+ const article = this.safeValue (response, 'article');
+ const html = this.safeString (article, 'body');
const parts = html.split (' | ');
const numParts = parts.length;
if (numParts < 3) {
- throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://support.kraken.com/hc/en-us/articles/205893708-What-is-the-minimum-order-size-');
+ throw new NotSupported (this.id + ' fetchMinOrderAmounts HTML page markup has changed: https://kraken.zendesk.com/api/v2/help_center/en-us/articles/205893708');
}
const result = {};
// skip the part before the header and the header itself
@@ -262,6 +265,52 @@ module.exports = class kraken extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetAssetPairs (params);
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "ADAETH":{
+ // "altname":"ADAETH",
+ // "wsname":"ADA\/ETH",
+ // "aclass_base":"currency",
+ // "base":"ADA",
+ // "aclass_quote":"currency",
+ // "quote":"XETH",
+ // "lot":"unit",
+ // "pair_decimals":7,
+ // "lot_decimals":8,
+ // "lot_multiplier":1,
+ // "leverage_buy":[],
+ // "leverage_sell":[],
+ // "fees":[
+ // [0,0.26],
+ // [50000,0.24],
+ // [100000,0.22],
+ // [250000,0.2],
+ // [500000,0.18],
+ // [1000000,0.16],
+ // [2500000,0.14],
+ // [5000000,0.12],
+ // [10000000,0.1]
+ // ],
+ // "fees_maker":[
+ // [0,0.16],
+ // [50000,0.14],
+ // [100000,0.12],
+ // [250000,0.1],
+ // [500000,0.08],
+ // [1000000,0.06],
+ // [2500000,0.04],
+ // [5000000,0.02],
+ // [10000000,0]
+ // ],
+ // "fee_volume_currency":"ZUSD",
+ // "margin_call":80,
+ // "margin_stop":40
+ // },
+ // }
+ // }
+ //
const fetchMinOrderAmounts = this.safeValue (this.options, 'fetchMinOrderAmounts', false);
let limits = {};
if (fetchMinOrderAmounts) {
@@ -441,6 +490,13 @@ module.exports = class kraken extends Exchange {
};
}
+ parseBidAsk (bidask, priceKey = 0, amountKey = 1) {
+ const price = this.safeFloat (bidask, priceKey);
+ const amount = this.safeFloat (bidask, amountKey);
+ const timestamp = this.safeInteger (bidask, 2);
+ return [ price, amount, timestamp ];
+ }
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
@@ -454,7 +510,27 @@ module.exports = class kraken extends Exchange {
request['count'] = limit; // 100
}
const response = await this.publicGetDepth (this.extend (request, params));
- const orderbook = response['result'][market['id']];
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "XETHXXBT":{
+ // "asks":[
+ // ["0.023480","4.000",1586321307],
+ // ["0.023490","50.095",1586321306],
+ // ["0.023500","28.535",1586321302],
+ // ],
+ // "bids":[
+ // ["0.023470","59.580",1586321307],
+ // ["0.023460","20.000",1586321301],
+ // ["0.023440","67.832",1586321306],
+ // ]
+ // }
+ // }
+ // }
+ //
+ const result = this.safeValue (response, 'result', {});
+ const orderbook = this.safeValue (result, market['id']);
return this.parseOrderBook (orderbook);
}
@@ -708,26 +784,46 @@ module.exports = class kraken extends Exchange {
}
parseTrade (trade, market = undefined) {
+ //
+ // fetchTrades (public)
+ //
+ // [
+ // "0.032310", // price
+ // "4.28169434", // amount
+ // 1541390792.763, // timestamp
+ // "s", // sell or buy
+ // "l", // limit or market
+ // ""
+ // ]
+ //
+ // fetchOrderTrades (private)
+ //
+ // {
+ // id: 'TIMIRG-WUNNE-RRJ6GT', // injected from outside
+ // ordertxid: 'OQRPN2-LRHFY-HIFA7D',
+ // postxid: 'TKH2SE-M7IF5-CFI7LT',
+ // pair: 'USDCUSDT',
+ // time: 1586340086.457,
+ // type: 'sell',
+ // ordertype: 'market',
+ // price: '0.99860000',
+ // cost: '22.16892001',
+ // fee: '0.04433784',
+ // vol: '22.20000000',
+ // margin: '0.00000000',
+ // misc: ''
+ // }
+ //
let timestamp = undefined;
let side = undefined;
let type = undefined;
let price = undefined;
let amount = undefined;
+ let cost = undefined;
let id = undefined;
let order = undefined;
let fee = undefined;
- const marketId = this.safeString (trade, 'pair');
- const foundMarket = this.findMarketByAltnameOrId (marketId);
let symbol = undefined;
- if (foundMarket !== undefined) {
- market = foundMarket;
- } else if (marketId !== undefined) {
- // delisted market ids go here
- market = this.getDelistedMarketById (marketId);
- }
- if (market !== undefined) {
- symbol = market['symbol'];
- }
if (Array.isArray (trade)) {
timestamp = this.safeTimestamp (trade, 2);
side = (trade[3] === 's') ? 'sell' : 'buy';
@@ -738,17 +834,27 @@ module.exports = class kraken extends Exchange {
if (tradeLength > 6) {
id = this.safeString (trade, 6); // artificially added as per #1794
}
+ } else if (typeof trade === 'string') {
+ id = trade;
} else if ('ordertxid' in trade) {
+ const marketId = this.safeString (trade, 'pair');
+ const foundMarket = this.findMarketByAltnameOrId (marketId);
+ if (foundMarket !== undefined) {
+ market = foundMarket;
+ } else if (marketId !== undefined) {
+ // delisted market ids go here
+ market = this.getDelistedMarketById (marketId);
+ }
order = trade['ordertxid'];
id = this.safeString2 (trade, 'id', 'postxid');
timestamp = this.safeTimestamp (trade, 'time');
- side = trade['type'];
- type = trade['ordertype'];
+ side = this.safeString (trade, 'type');
+ type = this.safeString (trade, 'ordertype');
price = this.safeFloat (trade, 'price');
amount = this.safeFloat (trade, 'vol');
if ('fee' in trade) {
let currency = undefined;
- if (market) {
+ if (market !== undefined) {
currency = market['quote'];
}
fee = {
@@ -757,6 +863,14 @@ module.exports = class kraken extends Exchange {
};
}
}
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
+ if (price !== undefined) {
+ if (amount !== undefined) {
+ cost = price * amount;
+ }
+ }
return {
'id': id,
'order': order,
@@ -769,7 +883,7 @@ module.exports = class kraken extends Exchange {
'takerOrMaker': undefined,
'price': price,
'amount': amount,
- 'cost': price * amount,
+ 'cost': cost,
'fee': fee,
};
}
@@ -986,6 +1100,11 @@ module.exports = class kraken extends Exchange {
const status = this.parseOrderStatus (this.safeString (order, 'status'));
const id = this.safeString (order, 'id');
const clientOrderId = this.safeString (order, 'userref');
+ const rawTrades = this.safeValue (order, 'trades');
+ let trades = undefined;
+ if (rawTrades !== undefined) {
+ trades = this.parseTrades (rawTrades, market, undefined, undefined, { 'order': id });
+ }
return {
'id': id,
'clientOrderId': clientOrderId,
@@ -1004,8 +1123,7 @@ module.exports = class kraken extends Exchange {
'average': average,
'remaining': remaining,
'fee': fee,
- // 'trades': this.parseTrades (order['trades'], market),
- 'trades': undefined,
+ 'trades': trades,
};
}
@@ -1026,16 +1144,129 @@ module.exports = class kraken extends Exchange {
async fetchOrder (id, symbol = undefined, params = {}) {
await this.loadMarkets ();
- const response = await this.privatePostQueryOrders (this.extend ({
+ const clientOrderId = this.safeValue2 (params, 'userref', 'clientOrderId');
+ const request = {
'trades': true, // whether or not to include trades in output (optional, default false)
- 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
+ // 'txid': id, // do not comma separate a list of ids - use fetchOrdersByIds instead
// 'userref': 'optional', // restrict results to given user reference id (optional)
- }, params));
- const orders = response['result'];
+ };
+ let query = params;
+ if (clientOrderId !== undefined) {
+ request['userref'] = clientOrderId;
+ query = this.omit (params, [ 'userref', 'clientOrderId' ]);
+ } else {
+ request['txid'] = id;
+ }
+ const response = await this.privatePostQueryOrders (this.extend (request, query));
+ //
+ // {
+ // "error":[],
+ // "result":{
+ // "OTLAS3-RRHUF-NDWH5A":{
+ // "refid":null,
+ // "userref":null,
+ // "status":"closed",
+ // "reason":null,
+ // "opentm":1586822919.3342,
+ // "closetm":1586822919.365,
+ // "starttm":0,
+ // "expiretm":0,
+ // "descr":{
+ // "pair":"XBTUSDT",
+ // "type":"sell",
+ // "ordertype":"market",
+ // "price":"0",
+ // "price2":"0",
+ // "leverage":"none",
+ // "order":"sell 0.21804000 XBTUSDT @ market",
+ // "close":""
+ // },
+ // "vol":"0.21804000",
+ // "vol_exec":"0.21804000",
+ // "cost":"1493.9",
+ // "fee":"3.8",
+ // "price":"6851.5",
+ // "stopprice":"0.00000",
+ // "limitprice":"0.00000",
+ // "misc":"",
+ // "oflags":"fciq",
+ // "trades":["TT5UC3-GOIRW-6AZZ6R"]
+ // }
+ // }
+ // }
+ //
+ const orders = this.safeValue (response, 'result', []);
const order = this.parseOrder (this.extend ({ 'id': id }, orders[id]));
return this.extend ({ 'info': response }, order);
}
+ async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
+ const orderTrades = this.safeValue (params, 'trades');
+ const tradeIds = [];
+ if (orderTrades === undefined) {
+ throw new ArgumentsRequired (this.id + " fetchOrderTrades requires a unified order structure in the params argument or a 'trades' param (an array of trade id strings)");
+ } else {
+ for (let i = 0; i < orderTrades.length; i++) {
+ const orderTrade = orderTrades[i];
+ if (typeof orderTrade === 'string') {
+ tradeIds.push (orderTrade);
+ } else {
+ tradeIds.push (orderTrade['id']);
+ }
+ }
+ }
+ await this.loadMarkets ();
+ const options = this.safeValue (this.options, 'fetchOrderTrades', {});
+ const batchSize = this.safeInteger (options, 'batchSize', 20);
+ let numBatches = parseInt (tradeIds / batchSize);
+ numBatches = this.sum (numBatches, 1);
+ const numTradeIds = tradeIds.length;
+ let result = [];
+ for (let j = 0; j < numBatches; j++) {
+ const requestIds = [];
+ for (let k = 0; k < batchSize; k++) {
+ const index = this.sum (j * batchSize, k);
+ if (index < numTradeIds) {
+ requestIds.push (tradeIds[index]);
+ }
+ }
+ const request = {
+ 'txid': requestIds.join (','),
+ };
+ const response = await this.privatePostQueryTrades (request);
+ //
+ // {
+ // error: [],
+ // result: {
+ // 'TIMIRG-WUNNE-RRJ6GT': {
+ // ordertxid: 'OQRPN2-LRHFY-HIFA7D',
+ // postxid: 'TKH2SE-M7IF5-CFI7LT',
+ // pair: 'USDCUSDT',
+ // time: 1586340086.457,
+ // type: 'sell',
+ // ordertype: 'market',
+ // price: '0.99860000',
+ // cost: '22.16892001',
+ // fee: '0.04433784',
+ // vol: '22.20000000',
+ // margin: '0.00000000',
+ // misc: ''
+ // }
+ // }
+ // }
+ //
+ const rawTrades = this.safeValue (response, 'result');
+ const ids = Object.keys (rawTrades);
+ for (let i = 0; i < ids.length; i++) {
+ rawTrades[ids[i]]['id'] = ids[i];
+ }
+ const trades = this.parseTrades (rawTrades, undefined, since, limit);
+ const tradesFilteredBySymbol = this.filterBySymbol (trades, symbol);
+ result = this.arrayConcat (result, tradesFilteredBySymbol);
+ }
+ return result;
+ }
+
async fetchOrdersByIds (ids, symbol = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.privatePostQueryOrders (this.extend ({
@@ -1248,11 +1479,11 @@ module.exports = class kraken extends Exchange {
}
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
// https://www.kraken.com/en-us/help/api#deposit-status
if (code === undefined) {
throw new ArgumentsRequired (this.id + ' fetchDeposits requires a currency code argument');
}
+ await this.loadMarkets ();
const currency = this.currency (code);
const request = {
'asset': currency['id'],
@@ -1275,11 +1506,11 @@ module.exports = class kraken extends Exchange {
}
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
- await this.loadMarkets ();
// https://www.kraken.com/en-us/help/api#withdraw-status
if (code === undefined) {
throw new ArgumentsRequired (this.id + ' fetchWithdrawals requires a currency code argument');
}
+ await this.loadMarkets ();
const currency = this.currency (code);
const request = {
'asset': currency['id'],
@@ -1328,7 +1559,7 @@ module.exports = class kraken extends Exchange {
}
method = this.options['depositMethods'][code][0]['method'];
} else {
- throw new ExchangeError (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
+ throw new ArgumentsRequired (this.id + ' fetchDepositAddress() requires an extra `method` parameter. Use fetchDepositMethods ("' + code + '") to get a list of available deposit methods or enable the exchange property .options["cacheDepositMethodsOnFetchDepositAddress"] = true');
}
}
const request = {
diff --git a/TaskServer/node_modules/ccxt/js/kucoin.js b/TaskServer/node_modules/ccxt/js/kucoin.js
index 3afaaba98..025d0dc1e 100644
--- a/TaskServer/node_modules/ccxt/js/kucoin.js
+++ b/TaskServer/node_modules/ccxt/js/kucoin.js
@@ -69,7 +69,9 @@ module.exports = class kucoin extends Exchange {
'public': {
'get': [
'timestamp',
+ 'status',
'symbols',
+ 'markets',
'market/allTickers',
'market/orderbook/level{level}',
'market/orderbook/level2',
@@ -81,6 +83,9 @@ module.exports = class kucoin extends Exchange {
'market/stats',
'currencies',
'currencies/{currency}',
+ 'prices',
+ 'mark-price/{symbol}/current',
+ 'margin/config',
],
'post': [
'bullet-public',
@@ -92,6 +97,10 @@ module.exports = class kucoin extends Exchange {
'accounts/{accountId}',
'accounts/{accountId}/ledgers',
'accounts/{accountId}/holds',
+ 'accounts/transferable',
+ 'sub/user',
+ 'sub-accounts',
+ 'sub-accounts/{subUserId}',
'deposit-addresses',
'deposits',
'hist-deposits',
@@ -101,8 +110,20 @@ module.exports = class kucoin extends Exchange {
'withdrawals/quotas',
'orders',
'orders/{orderId}',
+ 'limit/orders',
'fills',
'limit/fills',
+ 'margin/account',
+ 'margin/borrow',
+ 'margin/borrow/outstanding',
+ 'margin/borrow/borrow/repaid',
+ 'margin/lend/active',
+ 'margin/lend/done',
+ 'margin/lend/trade/unsettled',
+ 'margin/lend/trade/settled',
+ 'margin/lend/assets',
+ 'margin/market',
+ 'margin/margin/trade/last',
],
'post': [
'accounts',
@@ -111,11 +132,19 @@ module.exports = class kucoin extends Exchange {
'deposit-addresses',
'withdrawals',
'orders',
+ 'orders/multi',
+ 'margin/borrow',
+ 'margin/repay/all',
+ 'margin/repay/single',
+ 'margin/lend',
+ 'margin/toggle-auto-lend',
'bullet-private',
],
'delete': [
'withdrawals/{withdrawalId}',
+ 'orders',
'orders/{orderId}',
+ 'margin/lend/{orderId}',
],
},
},
@@ -247,18 +276,20 @@ module.exports = class kucoin extends Exchange {
async fetchMarkets (params = {}) {
const response = await this.publicGetSymbols (params);
//
- // { quoteCurrency: 'BTC',
- // symbol: 'KCS-BTC',
- // quoteMaxSize: '9999999',
- // quoteIncrement: '0.000001',
- // baseMinSize: '0.01',
- // quoteMinSize: '0.00001',
- // enableTrading: true,
- // priceIncrement: '0.00000001',
- // name: 'KCS-BTC',
- // baseIncrement: '0.01',
- // baseMaxSize: '9999999',
- // baseCurrency: 'KCS' }
+ // {
+ // quoteCurrency: 'BTC',
+ // symbol: 'KCS-BTC',
+ // quoteMaxSize: '9999999',
+ // quoteIncrement: '0.000001',
+ // baseMinSize: '0.01',
+ // quoteMinSize: '0.00001',
+ // enableTrading: true,
+ // priceIncrement: '0.00000001',
+ // name: 'KCS-BTC',
+ // baseIncrement: '0.01',
+ // baseMaxSize: '9999999',
+ // baseCurrency: 'KCS'
+ // }
//
const data = response['data'];
const result = [];
@@ -344,20 +375,27 @@ module.exports = class kucoin extends Exchange {
async fetchAccounts (params = {}) {
const response = await this.privateGetAccounts (params);
//
- // { code: "200000",
- // data: [ { balance: "0.00009788",
+ // {
+ // code: "200000",
+ // data: [
+ // {
+ // balance: "0.00009788",
// available: "0.00009788",
- // holds: "0",
- // currency: "BTC",
- // id: "5c6a4fd399a1d81c4f9cc4d0",
- // type: "trade" },
- // ...,
- // { balance: "0.00000001",
+ // holds: "0",
+ // currency: "BTC",
+ // id: "5c6a4fd399a1d81c4f9cc4d0",
+ // type: "trade"
+ // },
+ // {
+ // balance: "0.00000001",
// available: "0.00000001",
- // holds: "0",
- // currency: "ETH",
- // id: "5c6a49ec99a1d819392e8e9f",
- // type: "trade" } ] }
+ // holds: "0",
+ // currency: "ETH",
+ // id: "5c6a49ec99a1d819392e8e9f",
+ // type: "trade"
+ // }
+ // ]
+ // }
//
const data = this.safeValue (response, 'data');
const result = [];
@@ -641,30 +679,72 @@ module.exports = class kucoin extends Exchange {
};
}
+ async fetchL3OrderBook (symbol, limit = undefined, params = {}) {
+ return await this.fetchOrderBook (symbol, limit, { 'level': 3 });
+ }
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
- let level = '2';
- if (limit !== undefined) {
- if ((limit !== 20) && (limit !== 100)) {
- throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
+ const level = this.safeInteger (params, 'level', 2);
+ let levelLimit = level.toString ();
+ if (level === '2') {
+ if (limit !== undefined) {
+ if ((limit !== 20) && (limit !== 100)) {
+ throw new ExchangeError (this.id + ' fetchOrderBook limit argument must be undefined, 20 or 100');
+ }
+ levelLimit += '_' + limit.toString ();
}
- level += '_' + limit.toString ();
}
await this.loadMarkets ();
const marketId = this.marketId (symbol);
- const request = this.extend ({ 'symbol': marketId, 'level': level }, params);
- const response = await this.publicGetMarketOrderbookLevelLevel (request);
+ const request = { 'symbol': marketId, 'level': levelLimit };
+ const response = await this.publicGetMarketOrderbookLevelLevel (this.extend (request, params));
//
- // { sequence: '1547731421688',
- // asks: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ],
- // bids: [ [ '5c419328ef83c75456bd615c', '0.9', '0.09' ], ... ], }
+ // 'market/orderbook/level2'
+ // 'market/orderbook/level2_20'
+ // 'market/orderbook/level2_100'
//
- const data = response['data'];
+ // {
+ // "code":"200000",
+ // "data":{
+ // "sequence":"1583235112106",
+ // "asks":[
+ // // ...
+ // ["0.023197","12.5067468"],
+ // ["0.023194","1.8"],
+ // ["0.023191","8.1069672"]
+ // ],
+ // "bids":[
+ // ["0.02319","1.6000002"],
+ // ["0.023189","2.2842325"],
+ // ],
+ // "time":1586584067274
+ // }
+ // }
+ //
+ // 'market/orderbook/level3'
+ //
+ // {
+ // "code":"200000",
+ // "data":{
+ // "sequence":"1583731857120",
+ // "asks":[
+ // // id, price, size, timestamp in nanoseconds
+ // ["5e915f8acd26670009675300","6925.7","0.2","1586585482194286069"],
+ // ["5e915f8ace35a200090bba48","6925.7","0.001","1586585482229569826"],
+ // ["5e915f8a8857740009ca7d33","6926","0.00001819","1586585482149148621"],
+ // ],
+ // "bids":[
+ // ["5e915f8acca406000ac88194","6925.6","0.05","1586585482384384842"],
+ // ["5e915f93cd26670009676075","6925.6","0.08","1586585491334914600"],
+ // ["5e915f906aa6e200099b49f6","6925.4","0.2","1586585488941126340"],
+ // ],
+ // "time":1586585492487
+ // }
+ // }
+ //
+ const data = this.safeValue (response, 'data', {});
const timestamp = this.safeInteger (data, 'time');
- // level can be a string such as 2_20 or 2_100
- const levelString = this.safeString (request, 'level');
- const levelParts = levelString.split ('_');
- const offset = parseInt (levelParts[0]);
- const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', offset - 2, offset - 1);
+ const orderbook = this.parseOrderBook (data, timestamp, 'bids', 'asks', level - 2, level - 1);
orderbook['nonce'] = this.safeInteger (data, 'sequence');
return orderbook;
}
@@ -715,7 +795,7 @@ module.exports = class kucoin extends Exchange {
'datetime': this.iso8601 (timestamp),
'fee': undefined,
'status': 'open',
- 'clientOid': clientOid,
+ 'clientOrderId': clientOid,
'info': data,
};
if (!this.safeValue (params, 'quoteAmount')) {
diff --git a/TaskServer/node_modules/ccxt/js/kuna.js b/TaskServer/node_modules/ccxt/js/kuna.js
index 08651fad2..d688a838c 100644
--- a/TaskServer/node_modules/ccxt/js/kuna.js
+++ b/TaskServer/node_modules/ccxt/js/kuna.js
@@ -18,11 +18,12 @@ module.exports = class kuna extends acx {
'has': {
'CORS': false,
'fetchTickers': true,
- 'fetchOHLCV': false,
+ 'fetchOHLCV': 'emulated',
'fetchOpenOrders': true,
'fetchMyTrades': true,
'withdraw': false,
},
+ 'timeframes': undefined,
'urls': {
'referral': 'https://kuna.io?r=kunaid-gvfihe8az7o4',
'logo': 'https://user-images.githubusercontent.com/1294454/31697638-912824fa-b3c1-11e7-8c36-cf9606eb94ac.jpg',
@@ -191,4 +192,23 @@ module.exports = class kuna extends acx {
const response = await this.privateGetTradesMy (this.extend (request, params));
return this.parseTrades (response, market, since, limit);
}
+
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limits = undefined, params = {}) {
+ await this.loadMarkets ();
+ const trades = await this.fetchTrades (symbol, since, limits, params);
+ const ohlcvc = this.buildOHLCVC (trades, timeframe, since, limits);
+ const result = [];
+ for (let i = 0; i < ohlcvc.length; i++) {
+ const ohlcv = ohlcvc[i];
+ result.push ([
+ ohlcv[0],
+ ohlcv[1],
+ ohlcv[2],
+ ohlcv[3],
+ ohlcv[4],
+ ohlcv[5],
+ ]);
+ }
+ return result;
+ }
};
diff --git a/TaskServer/node_modules/ccxt/js/lakebtc.js b/TaskServer/node_modules/ccxt/js/lakebtc.js
index 396bf0b69..4f62ae834 100644
--- a/TaskServer/node_modules/ccxt/js/lakebtc.js
+++ b/TaskServer/node_modules/ccxt/js/lakebtc.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError } = require ('./base/errors');
+const { ExchangeError, AuthenticationError, BadSymbol, InvalidOrder, InsufficientFunds } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -14,6 +14,7 @@ module.exports = class lakebtc extends Exchange {
'name': 'LakeBTC',
'countries': [ 'US' ],
'version': 'api_v2',
+ 'rateLimit': 1000,
'has': {
'CORS': true,
'createMarketOrder': false,
@@ -55,6 +56,14 @@ module.exports = class lakebtc extends Exchange {
'taker': 0.2 / 100,
},
},
+ 'exceptions': {
+ 'broad': {
+ 'Signature': AuthenticationError,
+ 'invalid symbol': BadSymbol,
+ 'Volume doit': InvalidOrder,
+ 'insufficient_balance': InsufficientFunds,
+ },
+ },
});
}
@@ -248,40 +257,68 @@ module.exports = class lakebtc extends Exchange {
} else {
this.checkRequiredCredentials ();
const nonce = this.nonce ();
+ const nonceAsString = nonce.toString ();
+ const requestId = this.seconds ();
let queryParams = '';
if ('params' in params) {
const paramsList = params['params'];
- queryParams = paramsList.join (',');
+ const stringParams = [];
+ for (let i = 0; i < paramsList.length; i++) {
+ let param = paramsList[i];
+ if (typeof paramsList !== 'string') {
+ param = param.toString ();
+ }
+ stringParams.push (param);
+ }
+ queryParams = stringParams.join (',');
+ body = {
+ 'method': path,
+ 'params': params['params'],
+ 'id': requestId,
+ };
+ } else {
+ body = {
+ 'method': path,
+ 'params': '',
+ 'id': requestId,
+ };
}
- const query = this.urlencode ({
- 'tonce': nonce,
- 'accesskey': this.apiKey,
- 'requestmethod': method.toLowerCase (),
- 'id': nonce,
- 'method': path,
- 'params': queryParams,
- });
- body = this.json ({
- 'method': path,
- 'params': queryParams,
- 'id': nonce,
- });
+ body = this.json (body);
+ let query = [
+ 'tonce=' + nonceAsString,
+ 'accesskey=' + this.apiKey,
+ 'requestmethod=' + method.toLowerCase (),
+ 'id=' + requestId.toString (),
+ 'method=' + path,
+ 'params=' + queryParams,
+ ];
+ query = query.join ('&');
const signature = this.hmac (this.encode (query), this.encode (this.secret), 'sha1');
const auth = this.encode (this.apiKey + ':' + signature);
+ const signature64 = this.decode (this.stringToBase64 (auth));
headers = {
- 'Json-Rpc-Tonce': nonce.toString (),
- 'Authorization': 'Basic ' + this.decode (this.stringToBase64 (auth)),
+ 'Json-Rpc-Tonce': nonceAsString,
+ 'Authorization': 'Basic ' + signature64,
'Content-Type': 'application/json',
};
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
- async request (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
- const response = await this.fetch2 (path, api, method, params, headers, body);
- if ('error' in response) {
- throw new ExchangeError (this.id + ' ' + this.json (response));
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
+ if (response === undefined) {
+ return; // fallback to the default error handler
+ }
+ //
+ // {"error":"Failed to submit order: invalid symbol"}
+ // {"error":"Failed to submit order: La validation a échoué : Volume doit être supérieur ou égal à 1.0"}
+ // {"error":"Failed to submit order: insufficient_balance"}
+ //
+ const feedback = this.id + ' ' + body;
+ const error = this.safeString (response, 'error');
+ if (error !== undefined) {
+ this.throwBroadlyMatchedException (this.exceptions['broad'], error, feedback);
+ throw new ExchangeError (feedback); // unknown message
}
- return response;
}
};
diff --git a/TaskServer/node_modules/ccxt/js/lbank.js b/TaskServer/node_modules/ccxt/js/lbank.js
index de0464dab..41df417f7 100644
--- a/TaskServer/node_modules/ccxt/js/lbank.js
+++ b/TaskServer/node_modules/ccxt/js/lbank.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder } = require ('./base/errors');
+const { ExchangeError, DDoSProtection, AuthenticationError, InvalidOrder, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -339,10 +339,10 @@ module.exports = class lbank extends Exchange {
await this.loadMarkets ();
const market = this.market (symbol);
if (since === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a `since` argument');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `since` argument');
}
if (limit === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a `limit` argument');
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a `limit` argument');
}
const request = {
'symbol': market['id'],
diff --git a/TaskServer/node_modules/ccxt/js/liquid.js b/TaskServer/node_modules/ccxt/js/liquid.js
index cd1337126..83e930a23 100644
--- a/TaskServer/node_modules/ccxt/js/liquid.js
+++ b/TaskServer/node_modules/ccxt/js/liquid.js
@@ -177,7 +177,7 @@ module.exports = class liquid extends Exchange {
}
async fetchMarkets (params = {}) {
- const markets = await this.publicGetProducts ();
+ const spot = await this.publicGetProducts (params);
//
// [
// {
@@ -208,20 +208,69 @@ module.exports = class liquid extends Exchange {
// },
// ]
//
+ const perpetual = await this.publicGetProducts ({ 'perpetual': '1' });
+ //
+ // [
+ // {
+ // "id": "603",
+ // "product_type": "Perpetual",
+ // "code": "CASH",
+ // "name": null,
+ // "market_ask": "1143900",
+ // "market_bid": "1143250",
+ // "currency": "JPY",
+ // "currency_pair_code": "P-BTCJPY",
+ // "pusher_channel": "product_cash_p-btcjpy_603",
+ // "taker_fee": "0.0",
+ // "maker_fee": "0.0",
+ // "low_market_bid": "1124450.0",
+ // "high_market_ask": "1151750.0",
+ // "volume_24h": "0.1756",
+ // "last_price_24h": "1129850.0",
+ // "last_traded_price": "1144700.0",
+ // "last_traded_quantity": "0.014",
+ // "quoted_currency": "JPY",
+ // "base_currency": "P-BTC",
+ // "tick_size": "50.0",
+ // "perpetual_enabled": true,
+ // "index_price": "1142636.03935",
+ // "mark_price": "1143522.18417",
+ // "funding_rate": "0.00033",
+ // "fair_price": "1143609.31009",
+ // "timestamp": "1581558659.195353100",
+ // },
+ // ]
+ //
const currencies = await this.fetchCurrencies ();
const currenciesByCode = this.indexBy (currencies, 'code');
const result = [];
+ const markets = this.arrayConcat (spot, perpetual);
for (let i = 0; i < markets.length; i++) {
const market = markets[i];
- const id = market['id'].toString ();
- const baseId = market['base_currency'];
- const quoteId = market['quoted_currency'];
+ const id = this.safeString (market, 'id');
+ const baseId = this.safeString (market, 'base_currency');
+ const quoteId = this.safeString (market, 'quoted_currency');
+ const productType = this.safeString (market, 'product_type');
+ let type = 'spot';
+ let spot = true;
+ let swap = false;
+ if (productType === 'Perpetual') {
+ spot = false;
+ swap = true;
+ type = 'swap';
+ }
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
- const symbol = base + '/' + quote;
+ let symbol = undefined;
+ if (swap) {
+ symbol = this.safeString (market, 'currency_pair_code');
+ } else {
+ symbol = base + '/' + quote;
+ }
const maker = this.safeFloat (market, 'maker_fee');
const taker = this.safeFloat (market, 'taker_fee');
- const active = !market['disabled'];
+ const disabled = this.safeValue (market, 'disabled', false);
+ const active = !disabled;
const baseCurrency = this.safeValue (currenciesByCode, base);
const quoteCurrency = this.safeValue (currenciesByCode, quote);
const precision = {
@@ -265,6 +314,9 @@ module.exports = class liquid extends Exchange {
'quote': quote,
'baseId': baseId,
'quoteId': quoteId,
+ 'type': type,
+ 'spot': spot,
+ 'swap': swap,
'maker': maker,
'taker': taker,
'limits': limits,
@@ -393,7 +445,7 @@ module.exports = class liquid extends Exchange {
return this.parseTicker (response, market);
}
- parseTrade (trade, market) {
+ parseTrade (trade, market = undefined) {
// { id: 12345,
// quantity: "6.789",
// price: "98765.4321",
@@ -420,13 +472,17 @@ module.exports = class liquid extends Exchange {
}
}
const id = this.safeString (trade, 'id');
+ let symbol = undefined;
+ if (market !== undefined) {
+ symbol = market['symbol'];
+ }
return {
'info': trade,
'id': id,
'order': orderId,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
- 'symbol': market['symbol'],
+ 'symbol': symbol,
'type': undefined,
'side': side,
'takerOrMaker': takerOrMaker,
diff --git a/TaskServer/node_modules/ccxt/js/livecoin.js b/TaskServer/node_modules/ccxt/js/livecoin.js
index 9f8395531..eee90a7e2 100644
--- a/TaskServer/node_modules/ccxt/js/livecoin.js
+++ b/TaskServer/node_modules/ccxt/js/livecoin.js
@@ -439,7 +439,18 @@ module.exports = class livecoin extends Exchange {
}
}
let symbol = undefined;
- if (market !== undefined) {
+ const marketId = this.safeString (trade, 'symbol');
+ 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 ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
}
return {
@@ -460,16 +471,17 @@ module.exports = class livecoin extends Exchange {
}
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
- if (symbol === undefined) {
- throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument');
- }
await this.loadMarkets ();
- const market = this.market (symbol);
const request = {
- 'currencyPair': market['id'],
- // orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
+ // 'currencyPair': market['id'],
+ // 'orderDesc': 'true', // or 'false', if true then new orders will be first, otherwise old orders will be first.
// 'offset': 0, // page offset, position of the first item on the page
};
+ let market = undefined;
+ if (symbol !== undefined) {
+ market = this.market (symbol);
+ request['currencyPair'] = market['id'];
+ }
if (limit !== undefined) {
request['limit'] = limit;
}
diff --git a/TaskServer/node_modules/ccxt/js/mercado.js b/TaskServer/node_modules/ccxt/js/mercado.js
index 661b51b66..6be269e14 100644
--- a/TaskServer/node_modules/ccxt/js/mercado.js
+++ b/TaskServer/node_modules/ccxt/js/mercado.js
@@ -399,17 +399,17 @@ module.exports = class mercado extends Exchange {
if (code === 'BRL') {
const account_ref = ('account_ref' in params);
if (!account_ref) {
- throw new ExchangeError (this.id + ' requires account_ref parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires account_ref parameter to withdraw ' + code);
}
} else if (code !== 'LTC') {
const tx_fee = ('tx_fee' in params);
if (!tx_fee) {
- throw new ExchangeError (this.id + ' requires tx_fee parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires tx_fee parameter to withdraw ' + code);
}
if (code === 'XRP') {
if (tag === undefined) {
if (!('destination_tag' in params)) {
- throw new ExchangeError (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
+ throw new ArgumentsRequired (this.id + ' requires a tag argument or destination_tag parameter to withdraw ' + code);
}
} else {
request['destination_tag'] = tag;
diff --git a/TaskServer/node_modules/ccxt/js/okex.js b/TaskServer/node_modules/ccxt/js/okex.js
index d7e5c73cd..c05baf41b 100644
--- a/TaskServer/node_modules/ccxt/js/okex.js
+++ b/TaskServer/node_modules/ccxt/js/okex.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, OnMaintenance, ArgumentsRequired, BadRequest, AccountSuspended, InvalidAddress, PermissionDenied, DDoSProtection, InsufficientFunds, InvalidNonce, CancelPending, InvalidOrder, OrderNotFound, AuthenticationError, RequestTimeout, NotSupported, BadSymbol } = require ('./base/errors');
const { TICK_SIZE, TRUNCATE } = require ('./base/functions/number');
// ---------------------------------------------------------------------------
@@ -61,6 +61,9 @@ module.exports = class okex extends Exchange {
'doc': 'https://www.okex.com/docs/en/',
'fees': 'https://www.okex.com/pages/products/fees.html',
'referral': 'https://www.okex.com/join/1888677',
+ 'test': {
+ 'rest': 'https://testnet.okex.com',
+ },
},
'api': {
'general': {
@@ -348,8 +351,9 @@ module.exports = class okex extends Exchange {
'30034': ExchangeError, // { "code": 30034, "message": "exchange ID does not exist" }
'30035': ExchangeError, // { "code": 30035, "message": "trading is not supported in this website" }
'30036': ExchangeError, // { "code": 30036, "message": "no relevant data" }
- '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
'30037': ExchangeNotAvailable, // { "code": 30037, "message": "endpoint is offline or unavailable" }
+ // '30038': AuthenticationError, // { "code": 30038, "message": "user does not exist" }
+ '30038': OnMaintenance, // {"client_oid":"","code":"30038","error_code":"30038","error_message":"Matching engine is being upgraded. Please try in about 1 minute.","message":"Matching engine is being upgraded. Please try in about 1 minute.","order_id":"-1","result":false}
// futures
'32001': AccountSuspended, // { "code": 32001, "message": "futures account suspended" }
'32002': PermissionDenied, // { "code": 32002, "message": "futures account does not exist" }
@@ -792,14 +796,6 @@ module.exports = class okex extends Exchange {
'price': this.safeFloat (market, 'tick_size'),
};
const minAmount = this.safeFloat2 (market, 'min_size', 'base_min_size');
- let minPrice = this.safeFloat (market, 'tick_size');
- if (precision['price'] !== undefined) {
- minPrice = Math.pow (10, -precision['price']);
- }
- let minCost = undefined;
- if (minAmount !== undefined && minPrice !== undefined) {
- minCost = minAmount * minPrice;
- }
const active = true;
const fees = this.safeValue2 (this.fees, marketType, 'trading', {});
return this.extend (fees, {
@@ -823,11 +819,11 @@ module.exports = class okex extends Exchange {
'max': undefined,
},
'price': {
- 'min': minPrice,
+ 'min': precision['price'],
'max': undefined,
},
'cost': {
- 'min': minCost,
+ 'min': precision['price'],
'max': undefined,
},
},
@@ -1360,8 +1356,18 @@ module.exports = class okex extends Exchange {
'instrument_id': market['id'],
'granularity': this.timeframes[timeframe],
};
+ const duration = this.parseTimeframe (timeframe);
if (since !== undefined) {
+ if (limit !== undefined) {
+ request['end'] = this.iso8601 (this.sum (since, limit * duration * 1000));
+ }
request['start'] = this.iso8601 (since);
+ } else {
+ const now = this.milliseconds ();
+ if (limit !== undefined) {
+ request['start'] = this.iso8601 (now - limit * duration * 1000);
+ request['end'] = this.iso8601 (now);
+ }
}
const response = await this[method] (this.extend (request, params));
//
@@ -1841,28 +1847,7 @@ module.exports = class okex extends Exchange {
// "result":true
// }
//
- const timestamp = this.milliseconds ();
- const id = this.safeString (response, 'order_id');
- return {
- 'info': response,
- 'id': id,
- 'timestamp': timestamp,
- 'datetime': this.iso8601 (timestamp),
- 'lastTradeTimestamp': undefined,
- 'status': undefined,
- 'symbol': symbol,
- 'type': type,
- 'side': side,
- 'price': price,
- 'amount': amount,
- 'filled': undefined,
- 'remaining': undefined,
- 'cost': undefined,
- 'trades': undefined,
- 'fee': undefined,
- 'clientOrderId': undefined,
- 'average': undefined,
- };
+ return this.parseOrder (response, market);
}
async cancelOrder (id, symbol = undefined, params = {}) {
@@ -2302,9 +2287,11 @@ module.exports = class okex extends Exchange {
}
parseDepositAddresses (addresses) {
- const result = [];
+ const result = {};
for (let i = 0; i < addresses.length; i++) {
- result.push (this.parseDepositAddress (addresses[i]));
+ const address = this.parseDepositAddress (addresses[i]);
+ const code = address['currency'];
+ result[code] = address;
}
return result;
}
@@ -2350,11 +2337,11 @@ module.exports = class okex extends Exchange {
// ]
//
const addresses = this.parseDepositAddresses (response);
- const numAddresses = addresses.length;
- if (numAddresses < 1) {
+ const address = this.safeValue (addresses, code);
+ if (address === undefined) {
throw new InvalidAddress (this.id + ' fetchDepositAddress cannot return nonexistent addresses, you should create withdrawal addresses with the exchange website first');
}
- return addresses[0];
+ return address;
}
async withdraw (code, amount, address, tag = undefined, params = {}) {
@@ -2366,7 +2353,7 @@ module.exports = class okex extends Exchange {
}
const fee = this.safeString (params, 'fee');
if (fee === undefined) {
- throw new ExchangeError (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
+ throw new ArgumentsRequired (this.id + " withdraw() requires a `fee` string parameter, network transaction fee must be ≥ 0. Withdrawals to OKCoin or OKEx are fee-free, please set '0'. Withdrawing to external digital asset address requires network transaction fee.");
}
const request = {
'currency': currency['id'],
diff --git a/TaskServer/node_modules/ccxt/js/paymium.js b/TaskServer/node_modules/ccxt/js/paymium.js
index 16e50e717..b46b2c369 100644
--- a/TaskServer/node_modules/ccxt/js/paymium.js
+++ b/TaskServer/node_modules/ccxt/js/paymium.js
@@ -27,6 +27,7 @@ module.exports = class paymium extends Exchange {
'https://github.com/Paymium/api-documentation',
'https://www.paymium.com/page/developers',
],
+ 'referral': 'https://www.paymium.com/page/sign-up?referral=eDAzPoRQFMvaAB8sf-qj',
},
'api': {
'public': {
@@ -41,12 +42,12 @@ module.exports = class paymium extends Exchange {
},
'private': {
'get': [
- 'merchant/get_payment/{UUID}',
+ 'merchant/get_payment/{uuid}',
'user',
'user/addresses',
'user/addresses/{btc_address}',
'user/orders',
- 'user/orders/{UUID}',
+ 'user/orders/{uuid}',
'user/price_alerts',
],
'post': [
@@ -57,7 +58,7 @@ module.exports = class paymium extends Exchange {
'merchant/create_payment',
],
'delete': [
- 'user/orders/{UUID}/cancel',
+ 'user/orders/{uuid}/cancel',
'user/price_alerts/{id}',
],
},
@@ -204,9 +205,9 @@ module.exports = class paymium extends Exchange {
async cancelOrder (id, symbol = undefined, params = {}) {
const request = {
- 'UUID': id,
+ 'uuid': id,
};
- return await this.privateDeleteUserOrdersUUIDCancel (this.extend (request, params));
+ return await this.privateDeleteUserOrdersUuidCancel (this.extend (request, params));
}
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
@@ -220,18 +221,24 @@ module.exports = class paymium extends Exchange {
this.checkRequiredCredentials ();
const nonce = this.nonce ().toString ();
let auth = nonce + url;
+ headers = {
+ 'Api-Key': this.apiKey,
+ 'Api-Nonce': nonce,
+ };
if (method === 'POST') {
if (Object.keys (query).length) {
body = this.json (query);
auth += body;
+ headers['Content-Type'] = 'application/json';
+ }
+ } else {
+ if (Object.keys (query).length) {
+ const queryString = this.urlencode (query);
+ auth += queryString;
+ url += '?' + queryString;
}
}
- headers = {
- 'Api-Key': this.apiKey,
- 'Api-Signature': this.hmac (this.encode (auth), this.encode (this.secret)),
- 'Api-Nonce': nonce,
- 'Content-Type': 'application/json',
- };
+ headers['Api-Signature'] = this.hmac (this.encode (auth), this.encode (this.secret));
}
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
}
diff --git a/TaskServer/node_modules/ccxt/js/poloniex.js b/TaskServer/node_modules/ccxt/js/poloniex.js
index fc389cd5e..ca6b4e842 100644
--- a/TaskServer/node_modules/ccxt/js/poloniex.js
+++ b/TaskServer/node_modules/ccxt/js/poloniex.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce } = require ('./base/errors');
+const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, DDoSProtection, InsufficientFunds, OrderNotFound, OrderNotCached, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -170,6 +170,7 @@ module.exports = class poloniex extends Exchange {
'Permission denied': PermissionDenied,
'Connection timed out. Please try again.': RequestTimeout,
'Internal error. Please try again.': ExchangeNotAvailable,
+ 'Currently in maintenance mode.': OnMaintenance,
'Order not found, or you are not the person who placed it.': OrderNotFound,
'Invalid API key/secret pair.': AuthenticationError,
'Please do not make more than 8 API calls per second.': DDoSProtection,
diff --git a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOHLCV.js b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOHLCV.js
index a526fd72f..0ce38e977 100644
--- a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOHLCV.js
+++ b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOHLCV.js
@@ -17,7 +17,6 @@ module.exports = async (exchange, symbol) => {
'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',
- 'mandala',
]
if (skippedExchanges.includes (exchange.id)) {
diff --git a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrderBooks.js b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrderBooks.js
index 718df81b3..871efde2c 100644
--- a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrderBooks.js
+++ b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrderBooks.js
@@ -13,7 +13,7 @@ const log = require ('ololog')
module.exports = async (exchange) => {
- const randomSymbols = exchange.symbols.sort (() => 0.5 - Math.random ()).slice (0, 2)
+ const randomSymbols = exchange.symbols.slice ().sort (() => 0.5 - Math.random ()).slice (0, 2)
const customExchangeParams = ([
'yobit',
'tidex',
diff --git a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrders.js b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrders.js
index aba8a1696..dd157c41f 100644
--- a/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrders.js
+++ b/TaskServer/node_modules/ccxt/js/test/Exchange/test.fetchOrders.js
@@ -14,7 +14,6 @@ const log = require ('ololog')
module.exports = async (exchange, symbol) => {
const skippedExchanges = [
- 'mandala',
'rightbtc',
]
diff --git a/TaskServer/node_modules/ccxt/js/test/Exchange/test.ticker.js b/TaskServer/node_modules/ccxt/js/test/Exchange/test.ticker.js
index 9601714f6..960794026 100644
--- a/TaskServer/node_modules/ccxt/js/test/Exchange/test.ticker.js
+++ b/TaskServer/node_modules/ccxt/js/test/Exchange/test.ticker.js
@@ -76,7 +76,6 @@ module.exports = (exchange, ticker, method, symbol) => {
'xbtce',
'coss',
'idex',
- 'mandala',
'mercado',
'okex',
'southxchange', // https://user-images.githubusercontent.com/1294454/59953532-314bea80-9489-11e9-85b3-2a711ca49aa7.png
diff --git a/TaskServer/node_modules/ccxt/js/test/base/functions/test.number.js b/TaskServer/node_modules/ccxt/js/test/base/functions/test.number.js
index e4b9a6b00..1d5adce06 100644
--- a/TaskServer/node_modules/ccxt/js/test/base/functions/test.number.js
+++ b/TaskServer/node_modules/ccxt/js/test/base/functions/test.number.js
@@ -25,6 +25,8 @@ assert (toWei ('0.001', 18) === '1000000000000000');
assert (toWei (0.1, 18) === '100000000000000000');
assert (toWei (0.01, 18) === '10000000000000000');
assert (toWei (0.001, 18) === '1000000000000000');
+assert (toWei ('0.3323340739', 18) === '332334073900000000');
+assert (toWei (0.3323340739, 18) === '332334073900000000');
// let us test that we get the inverse for all these test
assert (fromWei ('1000000000000000000', 18) === 1.0);
@@ -43,6 +45,8 @@ assert (fromWei ('1000000000000000', 18) === 0.001);
assert (fromWei (100000000000000000, 18) === 0.1);
assert (fromWei (10000000000000000, 18) === 0.01);
assert (fromWei (1000000000000000, 18) === 0.001);
+assert (fromWei ('332334073900000000', 18) === 0.3323340739);
+assert (fromWei (332334073900000000, 18) === 0.3323340739);
// ----------------------------------------------------------------------------
// numberToString
@@ -58,6 +62,7 @@ assert (numberToString (7.9e27) === '7900000000000000000000000000');
assert (numberToString (-12.345) === '-12.345');
assert (numberToString (12.345) === '12.345');
assert (numberToString (0) === '0');
+assert (numberToString (7.35946e21) === '7359460000000000000000');
// the following line breaks the test
// see https://github.com/ccxt/ccxt/issues/5744
// assert (numberToString (0.00000001) === '0.00000001');
diff --git a/TaskServer/node_modules/ccxt/js/test/test.js b/TaskServer/node_modules/ccxt/js/test/test.js
index 665e1a228..322deed58 100644
--- a/TaskServer/node_modules/ccxt/js/test/test.js
+++ b/TaskServer/node_modules/ccxt/js/test/test.js
@@ -370,9 +370,12 @@ let tryAllProxies = async function (exchange, proxies) {
;(async function test () {
if (exchangeSymbol) {
+
await loadExchange (exchange)
await testSymbol (exchange, exchangeSymbol)
+
} else {
+
await tryAllProxies (exchange, proxies)
}
diff --git a/TaskServer/node_modules/ccxt/js/theocean.js b/TaskServer/node_modules/ccxt/js/theocean.js
index 2fd3e1bd6..502aaedd5 100644
--- a/TaskServer/node_modules/ccxt/js/theocean.js
+++ b/TaskServer/node_modules/ccxt/js/theocean.js
@@ -180,6 +180,9 @@ module.exports = class theocean extends Exchange {
}
async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
+ if (since === undefined) {
+ throw new ArgumentsRequired (this.id + ' fetchOHLCV requires a since argument');
+ }
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
@@ -187,9 +190,6 @@ module.exports = class theocean extends Exchange {
'quoteTokenAddress': market['quoteId'],
'interval': this.timeframes[timeframe],
};
- if (since === undefined) {
- throw new ExchangeError (this.id + ' fetchOHLCV requires a since argument');
- }
since = parseInt (since);
request['startTime'] = since;
const response = await this.publicGetCandlesticks (this.extend (request, params));
diff --git a/TaskServer/node_modules/ccxt/js/tidebit.js b/TaskServer/node_modules/ccxt/js/tidebit.js
index 5d0f63e6b..7f3fe2605 100644
--- a/TaskServer/node_modules/ccxt/js/tidebit.js
+++ b/TaskServer/node_modules/ccxt/js/tidebit.js
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
-const { ExchangeError, InsufficientFunds, OrderNotFound } = require ('./base/errors');
+const { ExchangeError, InsufficientFunds, OrderNotFound, ArgumentsRequired } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -460,7 +460,7 @@ module.exports = class tidebit extends Exchange {
const currency = this.currency (code);
const id = this.safeString (params, 'id');
if (id === undefined) {
- throw new ExchangeError (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
+ throw new ArgumentsRequired (this.id + ' withdraw() requires an extra `id` param (withdraw account id according to withdraws/bind_account_list endpoint');
}
const request = {
'id': id,
diff --git a/TaskServer/node_modules/ccxt/js/timex.js b/TaskServer/node_modules/ccxt/js/timex.js
index 1c381f7cb..d772f12c3 100644
--- a/TaskServer/node_modules/ccxt/js/timex.js
+++ b/TaskServer/node_modules/ccxt/js/timex.js
@@ -42,6 +42,7 @@ module.exports = class timex extends Exchange {
'api': 'https://plasma-relay-backend.timex.io',
'www': 'https://timex.io',
'doc': 'https://docs.timex.io',
+ 'referral': 'https://timex.io/?refcode=1x27vNkTbP1uwkCck',
},
'api': {
'custody': {
@@ -892,7 +893,21 @@ module.exports = class timex extends Exchange {
// "active": true,
// "withdrawalFee": "50000000000000000",
// "purchaseCommissions": []
- // },
+ // }
+ //
+ // https://github.com/ccxt/ccxt/issues/6878
+ //
+ // {
+ // "symbol":"XRP",
+ // "name":"Ripple",
+ // "address":"0x0dc8882914f3ddeebf4cec6dc20edb99df3def6c",
+ // "decimals":6,
+ // "tradeDecimals":16,
+ // "depositEnabled":true,
+ // "withdrawalEnabled":true,
+ // "transferEnabled":true,
+ // "active":true
+ // }
//
const id = this.safeString (currency, 'symbol');
const code = this.safeCurrencyCode (id);
@@ -901,20 +916,22 @@ module.exports = class timex extends Exchange {
const active = this.safeValue (currency, 'active');
// const fee = this.safeFloat (currency, 'withdrawalFee');
const feeString = this.safeString (currency, 'withdrawalFee');
- const feeStringLen = feeString.length;
const tradeDecimals = this.safeInteger (currency, 'tradeDecimals');
let fee = undefined;
- const dotIndex = feeStringLen - tradeDecimals;
- if (dotIndex > 0) {
- const whole = feeString.slice (0, dotIndex);
- const fraction = feeString.slice (-dotIndex);
- fee = parseFloat (whole + '.' + fraction);
- } else {
- let fraction = '.';
- for (let i = 0; i < -dotIndex; i++) {
- fraction += '0';
+ if ((feeString !== undefined) && (tradeDecimals !== undefined)) {
+ const feeStringLen = feeString.length;
+ const dotIndex = feeStringLen - tradeDecimals;
+ if (dotIndex > 0) {
+ const whole = feeString.slice (0, dotIndex);
+ const fraction = feeString.slice (-dotIndex);
+ fee = parseFloat (whole + '.' + fraction);
+ } else {
+ let fraction = '.';
+ for (let i = 0; i < -dotIndex; i++) {
+ fraction += '0';
+ }
+ fee = parseFloat (fraction + feeString);
}
- fee = parseFloat (fraction + feeString);
}
return {
'id': code,
@@ -1105,7 +1122,7 @@ module.exports = class timex extends Exchange {
this.safeFloat (ohlcv, 'high'),
this.safeFloat (ohlcv, 'low'),
this.safeFloat (ohlcv, 'close'),
- this.safeFloat (ohlcv, 'volumeQuote'),
+ this.safeFloat (ohlcv, 'volume'),
];
}
diff --git a/TaskServer/node_modules/ccxt/js/upbit.js b/TaskServer/node_modules/ccxt/js/upbit.js
index e34f8e651..8018766c0 100644
--- a/TaskServer/node_modules/ccxt/js/upbit.js
+++ b/TaskServer/node_modules/ccxt/js/upbit.js
@@ -1324,9 +1324,11 @@ module.exports = class upbit extends Exchange {
}
parseDepositAddresses (addresses) {
- const result = [];
+ const result = {};
for (let i = 0; i < addresses.length; i++) {
- result.push (this.parseDepositAddress (addresses[i]));
+ const address = this.parseDepositAddress (addresses[i]);
+ const code = address['currency'];
+ result[code] = address;
}
return result;
}
diff --git a/TaskServer/node_modules/ccxt/js/yobit.js b/TaskServer/node_modules/ccxt/js/yobit.js
index 58e452423..58bc08f89 100644
--- a/TaskServer/node_modules/ccxt/js/yobit.js
+++ b/TaskServer/node_modules/ccxt/js/yobit.js
@@ -167,11 +167,12 @@ module.exports = class yobit extends Exchange {
'api key dont have trade permission': AuthenticationError,
'invalid parameter': InvalidOrder,
'invalid order': InvalidOrder,
+ 'The given order has already been cancelled': InvalidOrder,
'Requests too often': DDoSProtection,
'not available': ExchangeNotAvailable,
'data unavailable': ExchangeNotAvailable,
'external service unavailable': ExchangeNotAvailable,
- 'Total transaction amount': ExchangeError, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
+ 'Total transaction amount': InvalidOrder, // { "success": 0, "error": "Total transaction amount is less than minimal total: 0.00010000"}
'Insufficient funds': InsufficientFunds,
'invalid key': AuthenticationError,
'invalid nonce': InvalidNonce, // {"success":0,"error":"invalid nonce (has already been used)"}'
diff --git a/TaskServer/node_modules/ccxt/js/zb.js b/TaskServer/node_modules/ccxt/js/zb.js
index f4807b607..f3cc69084 100644
--- a/TaskServer/node_modules/ccxt/js/zb.js
+++ b/TaskServer/node_modules/ccxt/js/zb.js
@@ -453,7 +453,7 @@ module.exports = class zb extends Exchange {
async fetchOrders (symbol = undefined, since = undefined, limit = 50, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + 'fetchOrders requires a symbol parameter');
+ throw new ArgumentsRequired (this.id + 'fetchOrders requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
@@ -481,7 +481,7 @@ module.exports = class zb extends Exchange {
async fetchOpenOrders (symbol = undefined, since = undefined, limit = 10, params = {}) {
if (symbol === undefined) {
- throw new ExchangeError (this.id + 'fetchOpenOrders requires a symbol parameter');
+ throw new ArgumentsRequired (this.id + 'fetchOpenOrders requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
diff --git a/TaskServer/node_modules/ccxt/package.json b/TaskServer/node_modules/ccxt/package.json
index 953f8eb8b..01c9960d1 100644
--- a/TaskServer/node_modules/ccxt/package.json
+++ b/TaskServer/node_modules/ccxt/package.json
@@ -1,27 +1,26 @@
{
- "_from": "ccxt@1.25.80",
- "_id": "ccxt@1.25.80",
+ "_from": "ccxt@^1.25.80",
+ "_id": "ccxt@1.27.45",
"_inBundle": false,
- "_integrity": "sha512-AUWagxMa8PMexRabbktWezlmVacj6L2Ep4844ebIXUOyME2Ommg7O/9/pq0F2Ne1IHcJnNJzHrMYQvkh2gBtlw==",
+ "_integrity": "sha512-4ADlbcIWDzIWjtLvsrtux5jMFj7pU4kVuiqtI2Btq6NEhQ4r/4+LirXdEFlCF6/wIU3XSHabxMd/8nu8HC1KJw==",
"_location": "/ccxt",
"_phantomChildren": {},
"_requested": {
- "type": "version",
+ "type": "range",
"registry": true,
- "raw": "ccxt@1.25.80",
+ "raw": "ccxt@^1.25.80",
"name": "ccxt",
"escapedName": "ccxt",
- "rawSpec": "1.25.80",
+ "rawSpec": "^1.25.80",
"saveSpec": null,
- "fetchSpec": "1.25.80"
+ "fetchSpec": "^1.25.80"
},
"_requiredBy": [
- "#USER",
"/"
],
- "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.25.80.tgz",
- "_shasum": "aee14637402aecc53d8a7d78af78bb7d730c84d5",
- "_spec": "ccxt@1.25.80",
+ "_resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.27.45.tgz",
+ "_shasum": "d4470a16dbff881da7fcccd38b0efa277f5a9c37",
+ "_spec": "ccxt@^1.25.80",
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer",
"author": {
"name": "Igor Kroitor",
@@ -447,8 +446,6 @@
"Binance Jersey",
"bequant.io",
"Bequant",
- "mandalaex.com",
- "Mandala",
"dx.exchange",
"DX.Exchange",
"oceanex.pro.com",
@@ -491,7 +488,9 @@
"Bybit",
"aofex.com",
"AOFEX",
- "byte-trade.com"
+ "byte-trade.com",
+ "hbtc.com",
+ "HBTC"
],
"license": "MIT",
"main": "./ccxt.js",
@@ -539,5 +538,5 @@
},
"types": "./ccxt.d.ts",
"unpkg": "dist/ccxt.browser.js",
- "version": "1.25.80"
+ "version": "1.27.45"
}
diff --git a/TaskServer/node_modules/dotenv/package.json b/TaskServer/node_modules/dotenv/package.json
index 40e1c3ed6..eeecadeb1 100644
--- a/TaskServer/node_modules/dotenv/package.json
+++ b/TaskServer/node_modules/dotenv/package.json
@@ -1,27 +1,26 @@
{
- "_from": "dotenv@8.2.0",
+ "_from": "dotenv@^8.2.0",
"_id": "dotenv@8.2.0",
"_inBundle": false,
"_integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"_location": "/dotenv",
"_phantomChildren": {},
"_requested": {
- "type": "version",
+ "type": "range",
"registry": true,
- "raw": "dotenv@8.2.0",
+ "raw": "dotenv@^8.2.0",
"name": "dotenv",
"escapedName": "dotenv",
- "rawSpec": "8.2.0",
+ "rawSpec": "^8.2.0",
"saveSpec": null,
- "fetchSpec": "8.2.0"
+ "fetchSpec": "^8.2.0"
},
"_requiredBy": [
- "#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"_shasum": "97e619259ada750eea3e4ea3e26bceea5424b16a",
- "_spec": "dotenv@8.2.0",
+ "_spec": "dotenv@^8.2.0",
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer",
"bugs": {
"url": "https://github.com/motdotla/dotenv/issues"
diff --git a/TaskServer/node_modules/telegraf/context.js b/TaskServer/node_modules/telegraf/context.js
index 9302d21b8..02f421079 100644
--- a/TaskServer/node_modules/telegraf/context.js
+++ b/TaskServer/node_modules/telegraf/context.js
@@ -330,6 +330,11 @@ class TelegrafContext {
return this.telegram.kickChatMember(this.chat.id, ...args)
}
+ unbanChatMember (...args) {
+ this.assert(this.chat, 'unbanChatMember')
+ return this.telegram.unbanChatMember(this.chat.id, ...args)
+ }
+
restrictChatMember (...args) {
this.assert(this.chat, 'restrictChatMember')
return this.telegram.restrictChatMember(this.chat.id, ...args)
diff --git a/TaskServer/node_modules/telegraf/markup.js b/TaskServer/node_modules/telegraf/markup.js
index 192d31fb9..ca0683c0c 100644
--- a/TaskServer/node_modules/telegraf/markup.js
+++ b/TaskServer/node_modules/telegraf/markup.js
@@ -164,15 +164,91 @@ class Markup {
}
static formatHTML (text = '', entities = []) {
- const chars = ['', ...text.split(''), ''].map(escapeHTMLChar)
- entities.forEach(entity => {
- const tag = getHTMLTag(entity)
- const openPos = entity.offset
- const closePos = entity.offset + entity.length + 1
- chars[openPos] += tag.open
- chars[closePos] = tag.close + chars[closePos]
- })
- return chars.join('')
+ const chars = [...text]
+ const available = [...entities]
+ const opened = []
+ const result = []
+ for (let offset = 0; offset < chars.length; offset++) {
+ while (true) {
+ const index = available.findIndex((entity) => entity.offset === offset)
+ if (index === -1) {
+ break
+ }
+ const entity = available[index]
+ switch (entity.type) {
+ case 'bold':
+ result.push('')
+ break
+ case 'italic':
+ result.push('')
+ break
+ case 'code':
+ result.push('')
+ break
+ case 'pre':
+ if (entity.language) {
+ result.push(``)
+ } else {
+ result.push('')
+ }
+ break
+ case 'strikethrough':
+ result.push('')
+ break
+ case 'underline':
+ result.push('')
+ break
+ case 'text_mention':
+ result.push(``)
+ break
+ case 'text_link':
+ result.push(``)
+ break
+ }
+ opened.unshift(entity)
+ available.splice(index, 1)
+ }
+
+ result.push(chars[offset])
+
+ while (true) {
+ const index = opened.findIndex((entity) => entity.offset + entity.length - 1 === offset)
+ if (index === -1) {
+ break
+ }
+ const entity = opened[index]
+ switch (entity.type) {
+ case 'bold':
+ result.push('
')
+ break
+ case 'italic':
+ result.push('')
+ break
+ case 'code':
+ result.push('')
+ break
+ case 'pre':
+ if (entity.language) {
+ result.push('')
+ } else {
+ result.push('')
+ }
+ break
+ case 'strikethrough':
+ result.push('')
+ break
+ case 'underline':
+ result.push('')
+ break
+ case 'text_mention':
+ case 'text_link':
+ result.push('')
+ break
+ }
+ opened.splice(index, 1)
+ }
+ }
+ return result.join('')
}
}
@@ -203,40 +279,4 @@ function buildKeyboard (buttons, options) {
return result
}
-function escapeHTMLChar (c) {
- switch (c) {
- case '&': return '&'
- case '"': return '"'
- case '\'': return '''
- case '<': return '<'
- default : return c
- }
-}
-
-function tag (name, params) {
- return {
- open: params
- ? `<${name} ${Object.entries(params).map(([key, value]) => `${key}="${value.replace(/[<&"]/g, escapeHTMLChar)}"`).join(' ')}>`
- : `<${name}>`,
- close: `${name}>`
- }
-}
-
-const HTMLTags = new Map([
- ['bold', tag('b')],
- ['italic', tag('i')],
- ['code', tag('code')],
- ['pre', tag('pre')],
- ['strikethrough', tag('s')],
- ['underline', tag('u')],
- ['text_link', ({ url }) => tag('a', { href: url })],
- ['text_mention', ({ user }) => tag('a', { href: `tg://user?id=${user.id}` })]
-])
-
-function getHTMLTag (entity) {
- const tag = HTMLTags.get(entity.type || 'unknown')
- if (!tag) return { open: '', close: '' }
- return typeof tag === 'function' ? tag(entity) : tag
-}
-
module.exports = Markup
diff --git a/TaskServer/node_modules/telegraf/package.json b/TaskServer/node_modules/telegraf/package.json
index 040c02569..ee36d765c 100644
--- a/TaskServer/node_modules/telegraf/package.json
+++ b/TaskServer/node_modules/telegraf/package.json
@@ -1,34 +1,33 @@
{
- "_from": "telegraf@3.37.0",
- "_id": "telegraf@3.37.0",
+ "_from": "telegraf@^3.37.0",
+ "_id": "telegraf@3.38.0",
"_inBundle": false,
- "_integrity": "sha512-V3448qwfOolBqkIc87yxjW4zMvR2P6AIF24pPTlX9WhZPwA1TF/x3nQhnWPRLtGh2SJuvDcr83iTkXPXT7Opnw==",
+ "_integrity": "sha512-va4VlrKWp64JrowFoZX/NPzzA6q38kvaIukVXOWFO1V+jR1G8+hCfgJy4TX8Z3rwLJzwaBEet1QhikHDRZWl3A==",
"_location": "/telegraf",
"_phantomChildren": {},
"_requested": {
- "type": "version",
+ "type": "range",
"registry": true,
- "raw": "telegraf@3.37.0",
+ "raw": "telegraf@^3.37.0",
"name": "telegraf",
"escapedName": "telegraf",
- "rawSpec": "3.37.0",
+ "rawSpec": "^3.37.0",
"saveSpec": null,
- "fetchSpec": "3.37.0"
+ "fetchSpec": "^3.37.0"
},
"_requiredBy": [
- "#USER",
"/"
],
- "_resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.37.0.tgz",
- "_shasum": "f88ae3d4bddac6f479137d4c867489acf3f57b66",
- "_spec": "telegraf@3.37.0",
+ "_resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.38.0.tgz",
+ "_shasum": "745b447547a8e6cdb626055e4d616058aaae0759",
+ "_spec": "telegraf@^3.37.0",
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer",
"author": {
"name": "Vitaly Domnikov",
"email": "oss@vitaly.codes"
},
"bin": {
- "telegraf": "bin/telegraf"
+ "telegraf": "./bin/telegraf"
},
"bugs": {
"url": "https://github.com/telegraf/telegraf/issues"
@@ -55,6 +54,7 @@
"eslint-plugin-promise": "^4.0.0",
"eslint-plugin-standard": "^4.0.0",
"husky": "^4.2.0",
+ "prettier": "^2.0.5",
"typescript": "^3.0.1"
},
"engines": {
@@ -91,5 +91,5 @@
},
"type": "commonjs",
"types": "./typings/index.d.ts",
- "version": "3.37.0"
+ "version": "3.38.0"
}
diff --git a/TaskServer/node_modules/telegraf/telegraf.js b/TaskServer/node_modules/telegraf/telegraf.js
index 15c3b0fb6..23e228eea 100644
--- a/TaskServer/node_modules/telegraf/telegraf.js
+++ b/TaskServer/node_modules/telegraf/telegraf.js
@@ -213,6 +213,7 @@ module.exports = Object.assign(Telegraf, {
Extra,
Markup,
Router,
+ Telegraf,
Telegram,
Stage,
BaseScene,
diff --git a/TaskServer/node_modules/ws/lib/buffer-util.js b/TaskServer/node_modules/ws/lib/buffer-util.js
index 3648638b0..6fd84c311 100644
--- a/TaskServer/node_modules/ws/lib/buffer-util.js
+++ b/TaskServer/node_modules/ws/lib/buffer-util.js
@@ -92,7 +92,7 @@ function toBuffer(data) {
if (data instanceof ArrayBuffer) {
buf = Buffer.from(data);
} else if (ArrayBuffer.isView(data)) {
- buf = viewToBuffer(data);
+ buf = Buffer.from(data.buffer, data.byteOffset, data.byteLength);
} else {
buf = Buffer.from(data);
toBuffer.readOnly = false;
@@ -101,23 +101,6 @@ function toBuffer(data) {
return buf;
}
-/**
- * Converts an `ArrayBuffer` view into a buffer.
- *
- * @param {(DataView|TypedArray)} view The view to convert
- * @return {Buffer} Converted view
- * @private
- */
-function viewToBuffer(view) {
- const buf = Buffer.from(view.buffer);
-
- if (view.byteLength !== view.buffer.byteLength) {
- return buf.slice(view.byteOffset, view.byteOffset + view.byteLength);
- }
-
- return buf;
-}
-
try {
const bufferUtil = require('bufferutil');
const bu = bufferUtil.BufferUtil || bufferUtil;
diff --git a/TaskServer/node_modules/ws/lib/event-target.js b/TaskServer/node_modules/ws/lib/event-target.js
index c060d63a8..d38e1f2d7 100644
--- a/TaskServer/node_modules/ws/lib/event-target.js
+++ b/TaskServer/node_modules/ws/lib/event-target.js
@@ -109,11 +109,16 @@ const EventTarget = {
/**
* Register an event listener.
*
- * @param {String} method A string representing the event type to listen for
+ * @param {String} type A string representing the event type to listen for
* @param {Function} listener The listener to add
+ * @param {Object} options An options object specifies characteristics about
+ * the event listener
+ * @param {Boolean} options.once A `Boolean`` indicating that the listener
+ * should be invoked at most once after being added. If `true`, the
+ * listener would be automatically removed when invoked.
* @public
*/
- addEventListener(method, listener) {
+ addEventListener(type, listener, options) {
if (typeof listener !== 'function') return;
function onMessage(data) {
@@ -132,36 +137,38 @@ const EventTarget = {
listener.call(this, new OpenEvent(this));
}
- if (method === 'message') {
+ const method = options && options.once ? 'once' : 'on';
+
+ if (type === 'message') {
onMessage._listener = listener;
- this.on(method, onMessage);
- } else if (method === 'close') {
+ this[method](type, onMessage);
+ } else if (type === 'close') {
onClose._listener = listener;
- this.on(method, onClose);
- } else if (method === 'error') {
+ this[method](type, onClose);
+ } else if (type === 'error') {
onError._listener = listener;
- this.on(method, onError);
- } else if (method === 'open') {
+ this[method](type, onError);
+ } else if (type === 'open') {
onOpen._listener = listener;
- this.on(method, onOpen);
+ this[method](type, onOpen);
} else {
- this.on(method, listener);
+ this[method](type, listener);
}
},
/**
* Remove an event listener.
*
- * @param {String} method A string representing the event type to remove
+ * @param {String} type A string representing the event type to remove
* @param {Function} listener The listener to remove
* @public
*/
- removeEventListener(method, listener) {
- const listeners = this.listeners(method);
+ removeEventListener(type, listener) {
+ const listeners = this.listeners(type);
for (let i = 0; i < listeners.length; i++) {
if (listeners[i] === listener || listeners[i]._listener === listener) {
- this.removeListener(method, listeners[i]);
+ this.removeListener(type, listeners[i]);
}
}
}
diff --git a/TaskServer/node_modules/ws/lib/stream.js b/TaskServer/node_modules/ws/lib/stream.js
index c6811afb1..f8d410eba 100644
--- a/TaskServer/node_modules/ws/lib/stream.js
+++ b/TaskServer/node_modules/ws/lib/stream.js
@@ -125,8 +125,8 @@ function createWebSocketStream(ws, options) {
if (ws._socket === null) return;
if (ws._socket._writableState.finished) {
- if (duplex._readableState.endEmitted) duplex.destroy();
callback();
+ if (duplex._readableState.endEmitted) duplex.destroy();
} else {
ws._socket.once('finish', function finish() {
// `duplex` is not destroyed here because the `'end'` event will be
diff --git a/TaskServer/node_modules/ws/lib/websocket-server.js b/TaskServer/node_modules/ws/lib/websocket-server.js
index 057a12be5..0d3f39592 100644
--- a/TaskServer/node_modules/ws/lib/websocket-server.js
+++ b/TaskServer/node_modules/ws/lib/websocket-server.js
@@ -7,10 +7,9 @@ const { createServer, STATUS_CODES } = require('http');
const PerMessageDeflate = require('./permessage-deflate');
const WebSocket = require('./websocket');
const { format, parse } = require('./extension');
-const { GUID } = require('./constants');
+const { GUID, kWebSocket } = require('./constants');
const keyRegex = /^[+/0-9A-Za-z]{22}==$/;
-const kUsedByWebSocketServer = Symbol('kUsedByWebSocketServer');
/**
* Class representing a WebSocket server.
@@ -79,13 +78,6 @@ class WebSocketServer extends EventEmitter {
callback
);
} else if (options.server) {
- if (options.server[kUsedByWebSocketServer]) {
- throw new Error(
- 'The HTTP/S server is already being used by another WebSocket server'
- );
- }
-
- options.server[kUsedByWebSocketServer] = true;
this._server = options.server;
}
@@ -153,8 +145,6 @@ class WebSocketServer extends EventEmitter {
server.close(() => this.emit('close'));
return;
}
-
- delete server[kUsedByWebSocketServer];
}
process.nextTick(emitClose, this);
@@ -264,6 +254,7 @@ class WebSocketServer extends EventEmitter {
* @param {net.Socket} socket The network socket between the server and client
* @param {Buffer} head The first packet of the upgraded stream
* @param {Function} cb Callback
+ * @throws {Error} If called more than once with the same socket
* @private
*/
completeUpgrade(key, extensions, req, socket, head, cb) {
@@ -272,6 +263,13 @@ class WebSocketServer extends EventEmitter {
//
if (!socket.readable || !socket.writable) return socket.destroy();
+ if (socket[kWebSocket]) {
+ throw new Error(
+ 'server.handleUpgrade() was called more than once with the same ' +
+ 'socket, possibly due to a misconfiguration'
+ );
+ }
+
const digest = createHash('sha1')
.update(key + GUID)
.digest('base64');
@@ -386,7 +384,7 @@ function abortHandshake(socket, code, message, headers) {
message = message || STATUS_CODES[code];
headers = {
Connection: 'close',
- 'Content-type': 'text/html',
+ 'Content-Type': 'text/html',
'Content-Length': Buffer.byteLength(message),
...headers
};
diff --git a/TaskServer/node_modules/ws/lib/websocket.js b/TaskServer/node_modules/ws/lib/websocket.js
index ca72ad76d..3e8e4afd7 100644
--- a/TaskServer/node_modules/ws/lib/websocket.js
+++ b/TaskServer/node_modules/ws/lib/websocket.js
@@ -456,7 +456,6 @@ function initAsClient(websocket, address, protocols, options) {
protocol: undefined,
timeout: undefined,
method: undefined,
- auth: undefined,
host: undefined,
path: undefined,
port: undefined
diff --git a/TaskServer/node_modules/ws/package.json b/TaskServer/node_modules/ws/package.json
index a6a75bdf9..df2515568 100644
--- a/TaskServer/node_modules/ws/package.json
+++ b/TaskServer/node_modules/ws/package.json
@@ -1,52 +1,38 @@
{
- "_args": [
- [
- "ws@^7.1.2",
- "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer"
- ]
- ],
- "_from": "ws@>=7.1.2-0 <8.0.0-0",
- "_hasShrinkwrap": false,
- "_id": "ws@7.2.3",
- "_inCache": true,
+ "_from": "ws@^7.1.2",
+ "_id": "ws@7.3.0",
+ "_inBundle": false,
+ "_integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==",
"_location": "/ws",
- "_nodeVersion": "13.10.1",
- "_npmOperationalInternal": {
- "host": "s3://npm-registry-packages",
- "tmp": "tmp/ws_7.2.3_1583774852485_0.5683086237203219"
- },
- "_npmUser": {
- "email": "luigipinca@gmail.com",
- "name": "lpinca"
- },
- "_npmVersion": "6.13.7",
"_phantomChildren": {},
"_requested": {
- "name": "ws",
+ "type": "range",
+ "registry": true,
"raw": "ws@^7.1.2",
+ "name": "ws",
+ "escapedName": "ws",
"rawSpec": "^7.1.2",
- "scope": null,
- "spec": ">=7.1.2-0 <8.0.0-0",
- "type": "range"
+ "saveSpec": null,
+ "fetchSpec": "^7.1.2"
},
"_requiredBy": [
"/"
],
- "_resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
- "_shasum": "a5411e1fb04d5ed0efee76d26d5c46d830c39b46",
- "_shrinkwrap": null,
+ "_resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
+ "_shasum": "4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd",
"_spec": "ws@^7.1.2",
"_where": "C:\\Users\\Luis\\source\\repos\\AAMasters\\TaskServer",
"author": {
- "email": "einaros@gmail.com",
"name": "Einar Otto Stangvik",
+ "email": "einaros@gmail.com",
"url": "http://2x.io"
},
"browser": "browser.js",
"bugs": {
"url": "https://github.com/websockets/ws/issues"
},
- "dependencies": {},
+ "bundleDependencies": false,
+ "deprecated": false,
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
"devDependencies": {
"benchmark": "^2.1.4",
@@ -60,19 +46,14 @@
"prettier": "^1.17.0",
"utf-8-validate": "^5.0.2"
},
- "directories": {},
- "dist": {
- "fileCount": 17,
- "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ==",
- "npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeZnyFCRA9TVsSAnZWagAAUvwP/jAz5ASUvvHJjDMOS+r/\npDkuV2MoMwz6ccV+qfbVRWUKq9DqnK7bZBApyNlzV2I+APDqLOVU+2BazNKh\nqoTcVHYcBYe5oBIYUvEeSK2qyBCNJUcz2f79lVxWagdcax5nl5tOcW3B8v4X\n9T2hSvSuDNz8vg0uhCnLboZ+F4SPXd3lHwwfcZFkNSjTcRog4W4QNQTEaPbi\noqPawUw/NXDJMFILS2m/rerFnEyrDl4VpoAS9GyitCE31g22N03bCbsmaUMo\nHmFmefATEhmtIExXMDW9JGLL9FtTwVEIAJEfAWqjLt3JeAuWHvYKKd7rU/y1\nwPUQJxwGM1HDYaxbDLXRBVYkOja3YHB5txB8d2lHLt98c5DQ/lZCz1XQIRao\nPv48dpOX2Qg69IpMzSHktoRUJpt+0KkLWUhb7XGVY79kCgqt6ZqYxBs7coae\nOeReUBaKc+yuM3k45sHxyqiKCsw/qejgzScPnmU/BaC32vEdjqpysRNDtfZj\nNmizo+cLoiO8stLVCHGBwpIxegM8aGj3/C8emNEsSFi4rXT6LGHaWvNfv3FR\nVY2/4QZFL/ddUQ3yAOKF4znsHBY2qfbpPJVnW7IyxZ2h39HX3PpITCcYDPzu\nj4LV/wXFESBSre9RANqfPfkJC+A3k0V8eAB0bYQJKImeUAiqkOkYMyrX+2Ea\nHUeL\r\n=aUaH\r\n-----END PGP SIGNATURE-----\r\n",
- "shasum": "a5411e1fb04d5ed0efee76d26d5c46d830c39b46",
- "tarball": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
- "unpackedSize": 109814
- },
"engines": {
"node": ">=8.3.0"
},
- "gitHead": "5fcdc42ef76d2d0ab920aa37631468e6f1066bcd",
+ "files": [
+ "browser.js",
+ "index.js",
+ "lib/*.js"
+ ],
"greenkeeper": {
"commitMessages": {
"dependencyUpdate": "[pkg] Update ${dependency} to version ${version}",
@@ -80,7 +61,6 @@
}
},
"homepage": "https://github.com/websockets/ws",
- "installable": true,
"keywords": [
"HyBi",
"Push",
@@ -91,26 +71,7 @@
],
"license": "MIT",
"main": "index.js",
- "maintainers": [
- {
- "email": "npm@3rd-Eden.com",
- "name": "3rdeden"
- },
- {
- "email": "einaros@gmail.com",
- "name": "einaros"
- },
- {
- "email": "luigipinca@gmail.com",
- "name": "lpinca"
- },
- {
- "email": "npm@3rd-Eden.com",
- "name": "v1"
- }
- ],
"name": "ws",
- "optionalDependencies": {},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
@@ -132,5 +93,5 @@
"lint": "eslint --ignore-path .gitignore . && prettier --check --ignore-path .gitignore \"**/*.{json,md,yaml,yml}\"",
"test": "npm run lint && nyc --reporter=html --reporter=text mocha --throw-deprecation test/*.test.js"
},
- "version": "7.2.3"
+ "version": "7.3.0"
}
diff --git a/TaskServer/package-lock.json b/TaskServer/package-lock.json
index 9da031d46..fc670f1b4 100644
--- a/TaskServer/package-lock.json
+++ b/TaskServer/package-lock.json
@@ -5,9 +5,9 @@
"requires": true,
"dependencies": {
"ccxt": {
- "version": "1.25.80",
- "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.25.80.tgz",
- "integrity": "sha512-AUWagxMa8PMexRabbktWezlmVacj6L2Ep4844ebIXUOyME2Ommg7O/9/pq0F2Ne1IHcJnNJzHrMYQvkh2gBtlw=="
+ "version": "1.27.45",
+ "resolved": "https://registry.npmjs.org/ccxt/-/ccxt-1.27.45.tgz",
+ "integrity": "sha512-4ADlbcIWDzIWjtLvsrtux5jMFj7pU4kVuiqtI2Btq6NEhQ4r/4+LirXdEFlCF6/wIU3XSHabxMd/8nu8HC1KJw=="
},
"debug": {
"version": "4.1.1",
@@ -48,9 +48,9 @@
"integrity": "sha512-jLYV0DORrzY3xaz/S9ydJL6Iz7essZeAfnAavsJ+zsJGZ1MOnsS52yRjU3uF3pJa/lla7+wisp//fxOwOH8SKQ=="
},
"telegraf": {
- "version": "3.37.0",
- "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.37.0.tgz",
- "integrity": "sha512-V3448qwfOolBqkIc87yxjW4zMvR2P6AIF24pPTlX9WhZPwA1TF/x3nQhnWPRLtGh2SJuvDcr83iTkXPXT7Opnw==",
+ "version": "3.38.0",
+ "resolved": "https://registry.npmjs.org/telegraf/-/telegraf-3.38.0.tgz",
+ "integrity": "sha512-va4VlrKWp64JrowFoZX/NPzzA6q38kvaIukVXOWFO1V+jR1G8+hCfgJy4TX8Z3rwLJzwaBEet1QhikHDRZWl3A==",
"requires": {
"debug": "4.1.1",
"minimist": "1.2.5",
@@ -66,9 +66,9 @@
"integrity": "sha512-njVv1EAhIZnmQVLocZEADYUyqA1WIXuVcDYlsp+mXua/XB0pxx+PKtMSPeZ/EE4wPWTw9h/hA9ASTT6yQelkiw=="
},
"ws": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.3.tgz",
- "integrity": "sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ=="
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz",
+ "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w=="
}
}
}
| |