From 15945ef1b017dcbbc59aab2eb83e110855fd935a Mon Sep 17 00:00:00 2001 From: adamant-al Date: Wed, 22 Feb 2023 13:17:39 +0400 Subject: [PATCH 1/5] chore: update p2b api --- helpers/utils.js | 6 ++---- package.json | 2 +- trade/api/p2pb2b_api.js | 24 +++++++++++++----------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/helpers/utils.js b/helpers/utils.js index e5f3e844..dc1c6c55 100644 --- a/helpers/utils.js +++ b/helpers/utils.js @@ -1562,16 +1562,14 @@ module.exports = { /** * Inclines a number * @param {Number} number Number to incline - * @return {String} 1-st, 2-d, 3-d, 4-th, 10-th, 20-th, 21-st, 22-d, 23-d, 30-th + * @return {String} 0th, 1st, 2d, 3d, 4th, 10th, 20th, 21st, 22d, 23d, 30th */ inclineNumber(number) { if (!this.isPositiveOrZeroInteger(number)) { return number; } - if (number === 0) { - return `zero-index`; - } else if (number % 10 === 1 && number !== 11) { + if (number % 10 === 1 && number !== 11) { return `${number}st`; } else if ([2, 3].includes(number % 10) && ![12, 13].includes(number)) { return `${number}d`; diff --git a/package.json b/package.json index 49e142ed..ff228127 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adamant-tradebot", - "version": "5.2.0", + "version": "5.2.1", "description": "ADAMANT Trading and Market Making bot", "main": "index.js", "scripts": { diff --git a/trade/api/p2pb2b_api.js b/trade/api/p2pb2b_api.js index 14d1dd54..41aea2b6 100644 --- a/trade/api/p2pb2b_api.js +++ b/trade/api/p2pb2b_api.js @@ -35,23 +35,25 @@ module.exports = function() { * @param {String} url */ const handleResponse = (responseOrError, resolve, reject, bodyString, queryString, url) => { - try { - const httpCode = responseOrError?.status || responseOrError?.response?.status; - const httpMessage = responseOrError?.statusText || responseOrError?.response?.statusText; + const httpCode = responseOrError?.status || responseOrError?.response?.status; + const httpMessage = responseOrError?.statusText || responseOrError?.response?.statusText; - const p2bData = responseOrError?.data || responseOrError?.response?.data; - const p2bStatus = p2bData?.success; - const p2bErrorCode = p2bData?.errorCode || p2bData?.status; - const p2bErrorMessage = utils.trimAny(p2bData?.message || p2bData?.errors?.message?.[0], '. '); - const p2bErrorInfo = p2bErrorCode ? `[${p2bErrorCode}] ${utils.trimAny(p2bErrorMessage, ' .')}` : `[No error code]`; + const p2bData = responseOrError?.data || responseOrError?.response?.data; + const p2bStatus = p2bData?.success; + const p2bErrorCode = p2bData?.errorCode || p2bData?.status; + const p2bErrorMessage = utils.trimAny(p2bData?.message || p2bData?.errors?.message?.[0], '. '); + const p2bErrorInfo = p2bErrorCode ? `[${p2bErrorCode}] ${utils.trimAny(p2bErrorMessage, ' .')}` : `[No error code]`; - const errorMessage = httpCode ? `${httpCode} ${httpMessage}, ${p2bErrorInfo}` : String(responseOrError); - const reqParameters = queryString || bodyString || '{ No parameters }'; + const errorMessage = httpCode ? `${httpCode} ${httpMessage}, ${p2bErrorInfo}` : String(responseOrError); + const reqParameters = queryString || bodyString || '{ No parameters }'; + try { if (p2bStatus) { resolve(p2bData); } else if (p2bErrorCode) { - p2bData.p2bErrorInfo = p2bErrorInfo; + if (p2bData) { + p2bData.p2bErrorInfo = p2bErrorInfo; + } if (notValidStatuses.includes(httpCode)) { log.log(`P2PB2B request to ${url} with data ${reqParameters} failed: ${errorMessage}. Rejecting…`); From 96878fbcfa441eda4e495f1a2d26de7e650a786d Mon Sep 17 00:00:00 2001 From: adamant-al Date: Thu, 23 Feb 2023 12:00:25 +0400 Subject: [PATCH 2/5] fix: updateOrders() --- package.json | 2 +- trade/orderUtils.js | 8 +++++--- trade/trader_p2pb2b.js | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ff228127..e5081301 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adamant-tradebot", - "version": "5.2.1", + "version": "5.2.2", "description": "ADAMANT Trading and Market Making bot", "main": "index.js", "scripts": { diff --git a/trade/orderUtils.js b/trade/orderUtils.js index 01b449e3..bf30f15c 100644 --- a/trade/orderUtils.js +++ b/trade/orderUtils.js @@ -336,11 +336,13 @@ module.exports = { } // for (const dbOrder of dbOrders) } else { // if exchangeOrders - log.warn(`orderUtils: Unable to get exchangeOrders${onWhichAccount} in updateOrders(), leaving dbOrders as is.`); - updatedOrders = dbOrders; + log.warn(`orderUtils: Unable to get exchangeOrders${onWhichAccount} in updateOrders(), leaving ${samePurpose}dbOrders as is.`); + return dbOrders; } } catch (e) { - log.error(`Error in updateOrders(${paramString}) of ${utils.getModuleName(module.id)} module: ` + e); + log.error(`Error in updateOrders(${paramString}) of ${utils.getModuleName(module.id)} module: ${e}`); + log.warn(`orderUtils: Because of error in updateOrders(), returning ${samePurpose}dbOrders before processing finished. It may be partly modified.`); + return dbOrders; } const orderCountAll = updatedOrders.length; diff --git a/trade/trader_p2pb2b.js b/trade/trader_p2pb2b.js index 18ac0977..c292f69d 100644 --- a/trade/trader_p2pb2b.js +++ b/trade/trader_p2pb2b.js @@ -151,7 +151,7 @@ module.exports = (apiKey, secretKey, pwd, log, publicOnly = false) => { try { data = await P2PB2BClient.getOrders(pair_.pair, offset, limit); - } catch (e) { + } catch (err) { log.warn(`API request getOpenOrdersPage(${paramString}) of ${utils.getModuleName(module.id)} module failed. ${err}`); return undefined; } From cf0fc83cb9558c8d97b5e082579a8726f45ae4b6 Mon Sep 17 00:00:00 2001 From: adamant-al Date: Sat, 25 Feb 2023 17:15:03 +0400 Subject: [PATCH 3/5] feat: additional info in balances --- helpers/utils.js | 103 +++++++++++++++++++++++++++++++++------- modules/commandTxs.js | 42 +++++++++++----- modules/configReader.js | 2 + package-lock.json | 11 ++--- package.json | 1 + 5 files changed, 124 insertions(+), 35 deletions(-) diff --git a/helpers/utils.js b/helpers/utils.js index dc1c6c55..eff80ca7 100644 --- a/helpers/utils.js +++ b/helpers/utils.js @@ -3,14 +3,19 @@ const log = require('./log'); const tradeParams = require('../trade/settings/tradeParams_' + config.exchange); const fs = require('fs'); const { SAT, EPOCH, MINUTE, LIQUIDITY_SS_MAX_SPREAD_PERCENT } = require('./const'); +const equal = require('fast-deep-equal'); const AVERAGE_SPREAD_DEVIATION = 0.15; module.exports = { - saveConfig(isWebApi = false) { - const toSave = 'module.exports = ' + JSON.stringify(tradeParams, null, 2).replace(/"/g, '\'').replace(/\n\}/g, ',\n};\n'); - fs.writeFileSync('./trade/settings/tradeParams_' + config.exchange + '.js', toSave); + let oldConfig; + eval(fs.readFileSync(config.fileWithPath).toString().replace('module.exports', 'oldConfig')); + if (!equal(tradeParams, oldConfig)) { + const toSave = 'module.exports = ' + JSON.stringify(tradeParams, null, 2).replace(/"/g, '\'').replace(/\n\}/g, ',\n};\n'); + fs.writeFileSync(config.fileWithPath, toSave); + log.log(`Config is updated and saved: ${config.file}`); + } }, /** @@ -125,6 +130,25 @@ module.exports = { } catch (e) { } }, + /** + * Rounds up to precision + * roundUp(6, 10) -> 10 + * roundUp(30, 10) -> 30 + * roundUp(31, 10) -> 30 + * roundUp(36, 10) -> 40 + * roundUp(561, 100) -> 600 + * roundUp(66, 5) -> 65 + * roundUp(1, 10) -> 1 + * roundUp(7, 10) -> 1 + * @param {Number} value Value to round up + * @param {Number} precision 5, 10, 100, etc. + * @return {Number} Rounded value + */ + roundUp(value, precision) { + if (!this.isNumber(value) || !this.isInteger(precision) || precision < 1 || value < precision) return value; + return Math.round(value / precision) * precision; + }, + /** * Returns integer random of (min-max) * @param {number} min Minimum is inclusive @@ -1211,14 +1235,33 @@ module.exports = { /** * Returns decimals for precision - * @param precision e.g. 0.00001 + * 0.00001 -> 5 + * 1000 -> 0 + * 1 -> 0 + * 0 -> undefined + * @param {Number|String} precision e.g. 0.00001 * @returns {number} returns 5 */ getDecimalsFromPrecision(precision) { if (!precision) return; + if (precision > 1) return 0; return Math.round(Math.abs(Math.log10(+precision))); }, + /** + * Returns decimals for precision for number greater than 1 + * 0.00001 -> 5 + * 1000 -> -3 + * 1 -> 0 + * 0 -> undefined + * @param {Number|String} precision e.g. 0.00001 + * @returns {number} returns 5 + */ + getDecimalsFromPrecisionForBigNumbers(precision) { + if (!precision) return; + return Math.round(-Math.log10(+precision)); + }, + /** * Checks if order price is out of order book custom percent (as mm_liquiditySpreadPercent) spread * @param order Object of ordersDb @@ -1397,28 +1440,42 @@ module.exports = { /** * Creates a difference string for current and previous balances * @param {Array of Object} a Current balances - * @param {Array of Object} b Previous balances + * @param {Object} b Previous balances with timestamp * @return {String} Difference string */ differenceInBalancesString(a, b, marketInfo) { let output = ''; - const diff = this.differenceInBalances(a, b); + const diff = this.differenceInBalances(a, b?.balances); + const timeDiffString = b?.timestamp ? ' in ' + this.timestampInDaysHoursMins(Date.now() - b.timestamp) : ''; if (diff) { if (diff[0]) { - output += '\nChanges:\n'; - let delta; let deltaUSD = 0; let deltaBTC = 0; let deltaCoin1 = 0; let deltaCoin2 = 0; - let sign; let signUSD = ''; let signBTC = ''; let signCoin1 = ''; let signCoin2 = ''; + output += `\nChanges${timeDiffString}:\n`; + + let delta; let deltaTotalUSD = 0; let deltaTotalBTC = 0; + let deltaCoin1 = 0; let deltaCoin2 = 0; let deltaTotalNonCoin1USD = 0; let deltaTotalNonCoin1BTC = 0; + let sign; let signTotalUSD = ''; let signTotalBTC = ''; + let signCoin1 = ''; let signCoin2 = ''; let signTotalNonCoin1USD = ''; let signTotalNonCoin1BTC = ''; diff.forEach((crypto) => { delta = Math.abs(crypto.now - crypto.prev); sign = crypto.now > crypto.prev ? '+' : '−'; if (crypto.code === 'totalUSD') { - deltaUSD = delta; - signUSD = sign; + deltaTotalUSD = delta; + signTotalUSD = sign; return; } if (crypto.code === 'totalBTC') { - deltaBTC = delta; - signBTC = sign; + deltaTotalBTC = delta; + signTotalBTC = sign; + return; + } + if (crypto.code === 'totalNonCoin1USD') { + deltaTotalNonCoin1USD = delta; + signTotalNonCoin1USD = sign; + return; + } + if (crypto.code === 'totalNonCoin1BTC') { + deltaTotalNonCoin1BTC = delta; + signTotalNonCoin1BTC = sign; return; } if (crypto.code === config.coin1) { @@ -1432,13 +1489,25 @@ module.exports = { output += `_${crypto.code}_: ${sign}${this.formatNumber(+(delta).toFixed(8), true)}`; output += '\n'; }); - output += `Total holdings ${signUSD}${this.formatNumber(+deltaUSD.toFixed(2), true)} _USD_ or ${signBTC}${this.formatNumber(deltaBTC.toFixed(8), true)} _BTC_`; - if (deltaCoin1 && deltaCoin2 && (signCoin1 !== signCoin2)) { - const price = deltaCoin2 / deltaCoin1; + + if (Math.abs(deltaTotalUSD)> 0.01 || Math.abs(deltaTotalBTC > 0.00000009)) { + output += `Total holdings ${signTotalUSD}${this.formatNumber(+deltaTotalUSD.toFixed(2), true)} _USD_ or ${signTotalBTC}${this.formatNumber(deltaTotalBTC.toFixed(8), true)} _BTC_`; + } else { + output += `Total holdings ~ No changes`; + } + + if (Math.abs(deltaTotalNonCoin1USD) > 0.01 || Math.abs(deltaTotalNonCoin1BTC) > 0.00000009) { + output += `\nTotal holdings (non-${config.coin1}) ${signTotalNonCoin1USD}${this.formatNumber(+deltaTotalNonCoin1USD.toFixed(2), true)} _USD_ or ${signTotalNonCoin1BTC}${this.formatNumber(deltaTotalNonCoin1BTC.toFixed(8), true)} _BTC_`; + } else { + output += `\nTotal holdings (non-${config.coin1}) ~ No changes`; + } + + if (deltaCoin1 && deltaTotalNonCoin1USD && (signCoin1 !== signTotalNonCoin1USD)) { + const price = deltaTotalNonCoin1USD / deltaCoin1; output += `\n[Can be wrong] ${signCoin1 === '+' ? 'I\'ve bought' : 'I\'ve sold'} ${this.formatNumber(+deltaCoin1.toFixed(marketInfo.coin1Decimals), true)} _${config.coin1}_ at ${this.formatNumber(price.toFixed(marketInfo.coin2Decimals), true)} _${config.coin2}_ price.`; } } else { - output += '\nNo changes.\n'; + output += `\nNo changes${timeDiffString}.\n`; } } return output; diff --git a/modules/commandTxs.js b/modules/commandTxs.js index 7388fd97..e822b1a6 100644 --- a/modules/commandTxs.js +++ b/modules/commandTxs.js @@ -1044,6 +1044,8 @@ async function fill(params) { }; } + const onWhichAccount = traderapi.isSecondAccount ? ' on second account' : ''; + const balances = await traderapi.getBalances(false); let balance; let isBalanceEnough = true; @@ -2075,13 +2077,14 @@ async function calc(params, tx, isWebApi = false) { function balancesString(balances, caption, params) { let output = ''; let totalBTC = 0; let totalUSD = 0; + let totalNonCoin1BTC = 0; let totalNonCoin1USD = 0; const unknownCryptos = []; if (balances.length === 0) { output = `All empty.`; } else { output = caption; - balances = balances.filter((crypto) => !['totalBTC', 'totalUSD'].includes(crypto.code)); + balances = balances.filter((crypto) => !['totalBTC', 'totalUSD', 'totalNonCoin1BTC', 'totalNonCoin1USD'].includes(crypto.code)); balances.forEach((crypto) => { const accountTypeString = params?.[0] ? `[${crypto.accountType}] ` : ''; output += `${accountTypeString}${utils.formatNumber(+(crypto.total).toFixed(8), true)} _${crypto.code}_`; @@ -2098,25 +2101,30 @@ function balancesString(balances, caption, params) { const skipUnknownCryptos = ['BTXCRD']; if (utils.isPositiveOrZeroNumber(crypto.usd)) { totalUSD += crypto.usd; + if (crypto.code !== config.coin1) totalNonCoin1USD += crypto.usd; } else { value = exchangerUtils.convertCryptos(crypto.code, 'USD', crypto.total).outAmount; if (utils.isPositiveOrZeroNumber(value)) { totalUSD += value; + if (crypto.code !== config.coin1) totalNonCoin1USD += value; } else if (!skipUnknownCryptos.includes(crypto.code)) { unknownCryptos.push(crypto.code); } } if (utils.isPositiveOrZeroNumber(crypto.btc)) { totalBTC += crypto.btc; + if (crypto.code !== config.coin1) totalNonCoin1BTC += crypto.btc; } else { value = exchangerUtils.convertCryptos(crypto.code, 'BTC', crypto.total).outAmount; if (utils.isPositiveOrZeroNumber(value)) { totalBTC += value; + if (crypto.code !== config.coin1) totalNonCoin1BTC += value; } } }); output += `Total holdings ~ ${utils.formatNumber(+totalUSD.toFixed(2), true)} _USD_ or ${utils.formatNumber(totalBTC.toFixed(8), true)} _BTC_`; + output += `\nTotal holdings (non-${config.coin1}) ~ ${utils.formatNumber(+totalNonCoin1USD.toFixed(2), true)} _USD_ or ${utils.formatNumber(totalNonCoin1BTC.toFixed(8), true)} _BTC_`; if (unknownCryptos.length) { output += `. Note: I didn't count unknown cryptos ${unknownCryptos.join(', ')}.`; } @@ -2130,6 +2138,14 @@ function balancesString(balances, caption, params) { code: 'totalBTC', total: totalBTC, }); + balances.push({ + code: 'totalNonCoin1USD', + total: totalNonCoin1USD, + }); + balances.push({ + code: 'totalNonCoin1BTC', + total: totalNonCoin1BTC, + }); } return { output, balances }; @@ -2138,33 +2154,34 @@ function balancesString(balances, caption, params) { /** * Create balance info string for an account, including balance difference from previous request * @param {Number} accountNo 0 for first account, 1 for second one - * @param {Object} tx Income ADM transaction + * @param {Object} tx [deprecated] Income ADM transaction to get senderId + * @param {String} userId senderId or userId for web * @param {Boolean} isWebApi If true, info messages will be different * @param {Array} params First parameter: account type, like main, trade, margin, or 'full'. * Note: Balance difference only for 'trade' account * @return {String} */ -async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params) { +async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params, userId) { let output = ''; try { - let balances = await traderapi.getBalances(); - const caption = `${config.exchangeName} balances:\n`; - const balancesObject = balancesString(balances, caption); + const accountTypeString = params?.[0] ? ` _${params?.[0]}_ account` : ''; + const caption = `${config.exchangeName}${accountTypeString} balances:\n`; + const balancesObject = balancesString(balances, caption, params); output = balancesObject.output; balances = balancesObject.balances; if (!isWebApi && !params?.[0]) { output += utils.differenceInBalancesString( balances, - previousBalances[accountNo][tx.senderId], + previousBalances[accountNo][userId], orderUtils.parseMarket(config.pair), ); - previousBalances[accountNo][tx.senderId] = balances; + previousBalances[accountNo][userId] = { timestamp: Date.now(), balances: balances }; } } catch (e) { log.error(`Error in getBalancesInfo() of ${utils.getModuleName(module.id)} module: ` + e); @@ -2179,11 +2196,12 @@ async function getBalancesInfo(accountNo = 0, tx, isWebApi = false, params) { * If undefined, will show balances for 'trade' account. If 'full', for all account types. * Exchange should support features().accountTypes * Note: Both account balances in case of two-keys trading will show only for 'trade' - * @param {Object} tx Income ADM transaction + * @param {Object} tx Income ADM transaction for in-chat command + * @param {Object} user User info for web * @param {Boolean} isWebApi If true, info messages will be different * @return {String} */ -async function balances(params, tx, isWebApi = false) { +async function balances(params, tx, user, isWebApi = false) { let output = ''; try { @@ -2195,7 +2213,8 @@ async function balances(params, tx, isWebApi = false) { } } - const account0Balances = await getBalancesInfo(0, tx, isWebApi); + const userId = isWebApi ? user.login : tx.senderId; + const account0Balances = await getBalancesInfo(0, tx, isWebApi, params, userId); const account1Balances = undefined; output = account1Balances ? account0Balances + '\n\n' + account1Balances : account0Balances; @@ -2208,7 +2227,6 @@ async function balances(params, tx, isWebApi = false) { msgSendBack: output, notifyType: 'log', }; - } function version() { diff --git a/modules/configReader.js b/modules/configReader.js index 7d74fd0a..59544453 100644 --- a/modules/configReader.js +++ b/modules/configReader.js @@ -147,6 +147,8 @@ try { config.supported_exchanges = config.exchanges.join(', '); config.exchangeName = config.exchange; config.exchange = config.exchangeName.toLowerCase(); + config.file = 'tradeParams_' + config.exchange + '.js'; + config.fileWithPath = './trade/settings/' + config.file; config.pair = config.pair.toUpperCase(); config.coin1 = config.pair.split('/')[0].trim(); config.coin2 = config.pair.split('/')[1].trim(); diff --git a/package-lock.json b/package-lock.json index c72314a7..311e7695 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { "name": "adamant-tradebot", - "version": "5.1.0", + "version": "5.2.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "adamant-tradebot", - "version": "5.1.0", + "version": "5.2.2", "license": "GPL-3.0", "dependencies": { "adamant-api": "^1.8.0", "axios": "^1.3.3", "express": "^4.18.2", + "fast-deep-equal": "^3.1.3", "form-data": "^4.0.0", "jsonminify": "^0.4.2", "mongodb": "^4.14.0" @@ -5988,8 +5989,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", @@ -15488,8 +15488,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-json-stable-stringify": { "version": "2.1.0", diff --git a/package.json b/package.json index e5081301..556db89e 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "adamant-api": "^1.8.0", "axios": "^1.3.3", "express": "^4.18.2", + "fast-deep-equal": "^3.1.3", "form-data": "^4.0.0", "jsonminify": "^0.4.2", "mongodb": "^4.14.0" From 9a1ba9cf5bb04ad302d107c87ace8856907d2633 Mon Sep 17 00:00:00 2001 From: adamant-al Date: Sat, 25 Feb 2023 17:16:56 +0400 Subject: [PATCH 4/5] chore: update dependencies --- package-lock.json | 208 +++++++++++++++++++++++----------------------- package.json | 8 +- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/package-lock.json b/package-lock.json index 311e7695..8a17ee70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "adamant-tradebot", - "version": "5.2.2", + "version": "5.3.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "adamant-tradebot", - "version": "5.2.2", + "version": "5.3.0", "license": "GPL-3.0", "dependencies": { "adamant-api": "^1.8.0", - "axios": "^1.3.3", + "axios": "^1.3.4", "express": "^4.18.2", "fast-deep-equal": "^3.1.3", "form-data": "^4.0.0", @@ -18,9 +18,9 @@ "mongodb": "^4.14.0" }, "devDependencies": { - "@babel/core": "^7.20.12", + "@babel/core": "^7.21.0", "@babel/eslint-parser": "^7.19.1", - "@babel/plugin-transform-runtime": "^7.19.6", + "@babel/plugin-transform-runtime": "^7.21.0", "@babel/preset-env": "^7.20.2", "axios-mock-adapter": "^1.21.2", "eslint": "^8.34.0", @@ -1130,21 +1130,21 @@ } }, "node_modules/@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.1.0", + "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.0", "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.0", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.0", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1178,13 +1178,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", "dev": true, "dependencies": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -1326,13 +1327,13 @@ } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -1375,9 +1376,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.18.9", @@ -1386,8 +1387,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" }, "engines": { "node": ">=6.9.0" @@ -1528,14 +1529,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz", - "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, "dependencies": { "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.13", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -1556,9 +1557,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", - "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -2495,13 +2496,13 @@ } }, "node_modules/@babel/plugin-transform-runtime": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", - "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz", + "integrity": "sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==", "dev": true, "dependencies": { "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "babel-plugin-polyfill-corejs2": "^0.3.3", "babel-plugin-polyfill-corejs3": "^0.6.0", "babel-plugin-polyfill-regenerator": "^0.4.1", @@ -2759,19 +2760,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", - "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", "dev": true, "dependencies": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.1", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.13", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2780,9 +2781,9 @@ } }, "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.19.4", @@ -4116,9 +4117,9 @@ } }, "node_modules/axios": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz", - "integrity": "sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -11841,21 +11842,21 @@ "dev": true }, "@babel/core": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.12.tgz", - "integrity": "sha512-XsMfHovsUYHFMdrIHkZphTN/2Hzzi78R08NuHfDBehym2VsPDL6Zn/JAD/JQdnRvbSsbQc4mVaU1m6JgtTEElg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", + "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", "dev": true, "requires": { - "@ampproject/remapping": "^2.1.0", + "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.0", "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helpers": "^7.20.7", - "@babel/parser": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.0", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.0", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.12", - "@babel/types": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -11875,13 +11876,14 @@ } }, "@babel/generator": { - "version": "7.20.14", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", - "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", + "version": "7.21.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", + "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", "dev": true, "requires": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "dependencies": { @@ -11986,13 +11988,13 @@ } }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "dev": true, "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" } }, "@babel/helper-hoist-variables": { @@ -12023,9 +12025,9 @@ } }, "@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.18.9", @@ -12034,8 +12036,8 @@ "@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" } }, "@babel/helper-optimise-call-expression": { @@ -12137,14 +12139,14 @@ } }, "@babel/helpers": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.13.tgz", - "integrity": "sha512-nzJ0DWCL3gB5RCXbUO3KIMMsBY2Eqbx8mBpKGE/02PgyRQFcPQLbkQ1vyy596mZLaP+dAfD+R4ckASzNVmW3jg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "dev": true, "requires": { "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.13", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" } }, "@babel/highlight": { @@ -12159,9 +12161,9 @@ } }, "@babel/parser": { - "version": "7.20.15", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", - "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", "dev": true }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { @@ -12765,13 +12767,13 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.19.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz", - "integrity": "sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.0.tgz", + "integrity": "sha512-ReY6pxwSzEU0b3r2/T/VhqMKg/AkceBT19X0UptA3/tYi5Pe2eXgEUH+NNMC5nok6c6XQz5tyVTUpuezRfSMSg==", "dev": true, "requires": { "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "babel-plugin-polyfill-corejs2": "^0.3.3", "babel-plugin-polyfill-corejs3": "^0.6.0", "babel-plugin-polyfill-regenerator": "^0.4.1", @@ -12966,27 +12968,27 @@ } }, "@babel/traverse": { - "version": "7.20.13", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", - "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", + "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", "dev": true, "requires": { "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", + "@babel/generator": "^7.21.1", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.13", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.2", + "@babel/types": "^7.21.2", "debug": "^4.1.0", "globals": "^11.1.0" } }, "@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", + "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", "dev": true, "requires": { "@babel/helper-string-parser": "^7.19.4", @@ -14035,9 +14037,9 @@ "dev": true }, "axios": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.3.tgz", - "integrity": "sha512-eYq77dYIFS77AQlhzEL937yUBSepBfPIe8FcgEDN35vMNZKMrs81pgnyrQpwfy4NF4b4XWX1Zgx7yX+25w8QJA==", + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", + "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", diff --git a/package.json b/package.json index 556db89e..6dffd127 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "adamant-tradebot", - "version": "5.2.2", + "version": "5.3.0", "description": "ADAMANT Trading and Market Making bot", "main": "index.js", "scripts": { @@ -45,7 +45,7 @@ "license": "GPL-3.0", "dependencies": { "adamant-api": "^1.8.0", - "axios": "^1.3.3", + "axios": "^1.3.4", "express": "^4.18.2", "fast-deep-equal": "^3.1.3", "form-data": "^4.0.0", @@ -53,9 +53,9 @@ "mongodb": "^4.14.0" }, "devDependencies": { - "@babel/core": "^7.20.12", + "@babel/core": "^7.21.0", "@babel/eslint-parser": "^7.19.1", - "@babel/plugin-transform-runtime": "^7.19.6", + "@babel/plugin-transform-runtime": "^7.21.0", "@babel/preset-env": "^7.20.2", "axios-mock-adapter": "^1.21.2", "eslint": "^8.34.0", From cfbf0815a902b617a60b260d2ef952e81cc7d913 Mon Sep 17 00:00:00 2001 From: adamant-al Date: Sat, 25 Feb 2023 17:39:30 +0400 Subject: [PATCH 5/5] chore: remove Coindeal support --- config.default.jsonc | 1 - trade/api/coindeal_api.js | 291 ----------------- trade/settings/tradeParams_coindeal.js | 26 -- trade/trader_coindeal.js | 432 ------------------------- 4 files changed, 750 deletions(-) delete mode 100644 trade/api/coindeal_api.js delete mode 100644 trade/settings/tradeParams_coindeal.js delete mode 100644 trade/trader_coindeal.js diff --git a/config.default.jsonc b/config.default.jsonc index 1d295cc3..8d29b138 100644 --- a/config.default.jsonc +++ b/config.default.jsonc @@ -43,7 +43,6 @@ /** List of supported exchanges **/ "exchanges": [ - "CoinDeal", "Resfinex", "P2PB2B" ], diff --git a/trade/api/coindeal_api.js b/trade/api/coindeal_api.js deleted file mode 100644 index ae4a99fd..00000000 --- a/trade/api/coindeal_api.js +++ /dev/null @@ -1,291 +0,0 @@ -const axios = require('axios'); -const FormData = require('form-data'); - -module.exports = function() { - const DEFAULT_HEADERS = { - 'Accept': 'application/json', - }; - - let WEB_BASE = ''; // API server like https://apigateway.coindeal.com - let config = { - 'apiKey': '', - 'secret_key': '', - 'tradePwd': '', - }; - let log = {}; - - function protectedRequest(path, data, type = 'get') { - let url = `${WEB_BASE}${path}`; - const params = []; - for (const key in data) { - const v = data[key]; - params.push(key + '=' + v); - } - const paramsString = params.join('&'); - if (paramsString && type !== 'post') { - url = url + '?' + paramsString; - } - let headersWithSign = Object.assign({ 'Authorization': setSign() }, DEFAULT_HEADERS); - - return new Promise((resolve, reject) => { - try { - - let httpOptions; - - if (type === 'get' || type === 'delete') { - - httpOptions = { - url: url, - method: type, - timeout: 10000, - headers: headersWithSign, - }; - - axios(httpOptions) - .then(function(response) { - const data = response.data; - resolve(data); - }) - .catch(function(error) { - // We can get 4xx with data - if (error.response && typeof error.response.data === 'object' && Object.keys(error.response.data).length !== 0) { - log.log(`${type.toUpperCase()}-request to ${url} with data ${JSON.stringify(data)} failed. ${error}. Reply data: ${JSON.stringify(error.response.data)}.`); - resolve(error.response.data); - } else if ( - type === 'delete' && - error.response && - error.response.status === 404 && - typeof error.response.data === 'string' && - error.response.data.includes('') && - error.response.data.includes('404 Not Found') - ) { - log.log(`${type.toUpperCase()}-request to ${url} with data ${JSON.stringify(data)} failed. ${error}. We assume that user doesn't have this order (but this may be a temporary server error, can't be sure).`); - if (error.response.status < 500) { - resolve(error.response.data); - } else { - reject(error.response.data); - } - } else { - log.log(`${type.toUpperCase()}-request to ${url} with data ${JSON.stringify(data)} failed. ${error}.`); - reject(error); - } - }); - } else { // post - const form = new FormData(); - Object.keys(data).forEach((key) => { - form.append(key, data[key]); - }); - - headersWithSign = Object.assign(headersWithSign, form.getHeaders()); - httpOptions = { - timeout: 10000, - headers: headersWithSign, - }; - - axios.post(url, form, httpOptions) - .then(function(response) { - const data = response.data; - resolve(data); - }) - .catch(function(error) { - // We can get 4xx with data - if (error.response && typeof error.response.data === 'object' && Object.keys(error.response.data).length !== 0) { - log.log(`${type.toUpperCase()}-request to ${url} with data ${JSON.stringify(data)} failed. ${error}. Reply data: ${JSON.stringify(error.response.data)}.`); - if (error.response.status < 500) { - resolve(error.response.data); - } else { - reject(error.response.data); - } - } else { - log.log(`${type.toUpperCase()}-request to ${url} with data ${JSON.stringify(data)} failed. ${error}.`); - reject(error); - } - }); - } - } catch (err) { - log.log(`Processing of ${type}-request to ${url} with data ${JSON.stringify(data)} failed. ${err}.`); - reject(null); - } - }); - } - - function publicRequest(url, data, type = 'get') { - return new Promise((resolve, reject) => { - try { - const httpOptions = { - url: url, - method: type, - timeout: 10000, - }; - axios(httpOptions) - .then(function(response) { - const data = response.data; - resolve(data); - }) - .catch(function(error) { - // We can get 4xx with data - if (error.response && typeof error.response.data === 'object' && Object.keys(error.response.data).length !== 0) { - log.log(`${type.toUpperCase()}-request to ${url} failed. ${error}. Reply data: ${JSON.stringify(error.response.data)}.`); - if (error.response.status < 500) { - resolve(error.response.data); - } else { - reject(error.response.data); - } - } else { - log.log(`${type.toUpperCase()}-request to ${url} failed. ${error}.`); - reject(error); - } - }); - - } catch (err) { - log.log(`Processing of ${type}-request to ${url} failed. ${err}.`); - reject(null); - } - }); - } - - function setSign() { - signString = 'Basic '; - signString += Buffer.from(config.apiKey + ':' + config.secret_key).toString('base64'); - return signString; - } - - const EXCHANGE_API = { - - setConfig: function(apiServer, apiKey, secretKey, tradePwd, logger, publicOnly = false) { - - if (apiServer) { - WEB_BASE = apiServer; - } - - if (logger) { - log = logger; - } - - if (!publicOnly) { - config = { - 'apiKey': apiKey, - 'secret_key': secretKey, - 'tradePwd': tradePwd || '', - }; - } - - }, - - /** - * ------------------------------------------------------------------ - * (Get user balances) - * ------------------------------------------------------------------ - */ - getUserAssets: function() { - return protectedRequest('/api/v1/trading/balance'); - }, - /** - * ------------------------------------------------------------------ - * (Get user open orders) - * ------------------------------------------------------------------ - */ - getUserNowEntrustSheet: function(coinFrom, coinTo) { - const data = {}; - data.symbol = coinFrom + coinTo; - // no limit/size parameter according to docs - // https://apigateway.coindeal.com/api/doc#operation/v1getOrder - return protectedRequest('/api/v1/order', data); - }, - /** - * ------------------------------------------------------------------ - * (Place a Limit order) - * @param symbol string "ADMBTC" - * @param amount float - * @param price float - * @param side string buy, sell - * ------------------------------------------------------------------ - */ - addEntrustSheet: function(symbol, amount, price, side) { - const data = {}; - data.symbol = symbol; - data.price = price; - data.quantity = amount; - data.side = side; - data.type = 'limit'; - return protectedRequest('/api/v1/order', data, 'post'); - }, - /** - * ------------------------------------------------------------------ - * (Cancel the order) - * @param entrustSheetId string - * ------------------------------------------------------------------ - */ - cancelEntrustSheet: function(entrustSheetId) { - const data = {}; - return protectedRequest(`/api/v1/order/${entrustSheetId}`, data, 'delete'); - }, - - /** - * ------------------------------------------------------------------ - * (Get the price data) - * @param symbol ADMBTC - * ------------------------------------------------------------------ - */ - orderBook: function(symbol, size) { - const data = {}; - // default limit/size is 100; - // no limit according to docs; 0 - full orderbook otherwise number of levels - // https://apigateway.coindeal.com/api/doc#operation/v1getPublicOrderbookCurrencyPair - if (size) { - data.limit = size; - } else { - data.limit = 0; - } - return publicRequest(`${WEB_BASE}/api/v1/public/orderbook/${symbol}`, data); - }, - - /** - * Get trades history - * @param pair Trading pair, like BTCUSDT - * @param {Number} limit Default: 100. — It is wrong, tested: max limit = 20 - * @param {String} sort Enum: "DESC", "ASC". Default: "DESC" - * @param {String} by Enum: "timestamp", "id". Default: "timestamp". Filter field: timestamp in milliseconds or id - * @param {String} from If filtered by timestamp, then timestamp in millisecond otherwise trade id. Example: from=1572356518965 - * @param {String} till If filtered by timestamp, then timestamp in millisecond otherwise trade id. Example: from=1572356518965 - * @param {Number} offset Example: offset=10 - * @return {Array of Object} Last trades - */ - getTradesHistory: function(symbol, limit, sort, by, from, till, offset) { - const data = {}; - data.symbol = symbol; - if (limit) data.limit = limit; - if (sort) data.sort = sort; - if (by) data.by = by; - if (from) data.from = from; - if (till) data.till = till; - if (offset) data.offset = offset; - return protectedRequest(`/api/v2/history/trades`, data, 'get'); - }, - - /** - * ------------------------------------------------------------------ - * (Get the deposit address) - * @param symbol ADM - * ------------------------------------------------------------------ - */ - getDepositAddress: function(symbol) { - const data = {}; - return protectedRequest(`/api/v1/deposits/${symbol}/addresses`, data); - }, - - /** - * ------------------------------------------------------------------ - * (Get stats) - * @param symbol eth_btc - * ------------------------------------------------------------------ - */ - stats: function(symbol) { - return publicRequest(`https://coinmarketcap.coindeal.com/api/v1/ticker`); - }, - - - }; - - return EXCHANGE_API; -}; diff --git a/trade/settings/tradeParams_coindeal.js b/trade/settings/tradeParams_coindeal.js deleted file mode 100644 index fe1cb32f..00000000 --- a/trade/settings/tradeParams_coindeal.js +++ /dev/null @@ -1,26 +0,0 @@ -module.exports = { - 'mm_buyPercent': 0.67, - 'mm_minInterval': 60000, - 'mm_maxInterval': 360000, - 'mm_isActive': false, - 'mm_minAmount': 0.1, - 'mm_maxAmount': 202, - 'mm_Policy': 'optimal', - 'mm_isOrderBookActive': true, - 'mm_orderBookHeight': 10, - 'mm_orderBookOrdersCount': 10, - 'mm_orderBookMaxOrderPercent': 50, - 'mm_isLiquidityActive': false, - 'mm_liquiditySellAmount': 100, - 'mm_liquidityBuyQuoteAmount': 50, - 'mm_liquiditySpreadPercent': 2, - 'mm_liquidityTrend': 'middle', - 'mm_isPriceWatcherActive': false, - 'mm_priceWatcherLowPriceInSourceCoin': 0, - 'mm_priceWatcherMidPriceInSourceCoin': 0, - 'mm_priceWatcherHighPriceInSourceCoin': 0, - 'mm_priceWatcherDeviationPercent': 0, - 'mm_priceWatcherSource': '#', - 'mm_priceWatcherSourcePolicy': 'smart', - 'mm_priceWatcherAction': 'fill', -}; diff --git a/trade/trader_coindeal.js b/trade/trader_coindeal.js deleted file mode 100644 index 0bc544e6..00000000 --- a/trade/trader_coindeal.js +++ /dev/null @@ -1,432 +0,0 @@ -const Coindeal = require('./api/coindeal_api'); -const utils = require('../helpers/utils'); - -// API endpoints: -// https://apigateway.coindeal.com - -const apiServer = 'https://apigateway.coindeal.com'; -const exchangeName = 'CoinDeal'; - -module.exports = (apiKey, secretKey, pwd, log, publicOnly = false) => { - const CoindealClient = Coindeal(); - - CoindealClient.setConfig(apiServer, apiKey, secretKey, pwd, log, publicOnly); - - // CoinDeal API doesn't provide market info - const defaultMarketInfo = { - coin1Decimals: 8, - coin2Decimals: 8, - }; - - return { - get markets() { - return {}; - }, - marketInfo(pair) { - pair = pair.toUpperCase().trim(); - const [coin1, coin2] = pair.split('/'); - return { - ...defaultMarketInfo, - pairPlain: pair, - coin1, - coin2, - }; - }, - features() { - return { - getMarkets: false, - placeMarketOrder: false, - getDepositAddress: true, - getDepositAddressLimit: 'Only created on website', - createDepositAddressWithWebsiteOnly: true, - getFundHistory: false, - getFundHistoryImplemented: false, - allowAmountForMarketBuy: false, - amountForMarketOrderNecessary: false, - }; - }, - - getBalances(nonzero = true) { - return new Promise((resolve, reject) => { - CoindealClient.getUserAssets().then(function(data) { - try { - let assets = data; - if (!assets) { - assets = []; - } - let result = []; - assets.forEach((crypto) => { - result.push({ - code: crypto.symbol, - free: +crypto.available, - freezed: +crypto.reserved, - total: +crypto.available + +crypto.reserved, - btc: +crypto.estimatedBalanceBtc, - usd: +crypto.estimatedBalanceUsd, - pending: +crypto.pending, - }); - }); - if (nonzero) { - result = result.filter((crypto) => crypto.free || crypto.freezed); - } - resolve(result); - } catch (e) { - resolve(false); - log.warn('Error while processing getBalances() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getBalances(nonzero: ${nonzero}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - getOpenOrders(pair) { - pair_ = formatPairName(pair); - return new Promise((resolve, reject) => { - CoindealClient.getUserNowEntrustSheet(pair_.coin1, pair_.coin2).then(function(data) { - try { - let openOrders = data; - if (!openOrders) { - openOrders = []; - } - - const result = []; - openOrders.forEach((order) => { - let orderStatus; - switch (order.status) { - case 'new': - orderStatus = 'new'; - break; - case 'canceled': - orderStatus = 'closed'; - break; - case 'filled': - orderStatus = 'filled'; - break; - case 'partiallyFilled': - orderStatus = 'part_filled'; - break; - case 'suspended': - break; - case 'expired': - break; - default: - break; - } - result.push({ - orderId: order.id?.toString(), - symbol: order.symbol, - price: +order.price, - side: order.side, // sell or buy - type: order.type, // limit or market, etc. - timestamp: order.createdAt, - amount: +order.cumQuantity, - amountExecuted: +order.cumQuantity - +order.quantity, - amountLeft: +order.quantity, - status: orderStatus, - uid: order.clientOrderId.toString(), - // coin2Amount: order.total, - coinFrom: order.baseCurrency, - coinTo: order.quoteCurrency, - }); - }); - - resolve(result); - - } catch (e) { - resolve(false); - log.warn('Error while processing getOpenOrders() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getOpenOrders(pair: ${pair}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - cancelOrder(orderId) { - /* - Watch this: sometimes cancelled orders on Coindeal switched to "CANCELLING" state - Balances stay frozen. To fix them, you need to contact Coindeal support. - */ - return new Promise((resolve, reject) => { - CoindealClient.cancelEntrustSheet(orderId).then(function(data) { - try { - if (data.id) { - log.log(`Cancelling order ${orderId}…`); - resolve(true); - } else { - log.log(`Order ${orderId} not found. Unable to cancel it.`); - resolve(false); - } - } catch (e) { - if (e instanceof SyntaxError) { - /* - Watch this: Sometimes you'll get

The server returned a "404 Not Found".

instead of JSON. - This means this order does not exist. - */ - resolve(false); - log.warn(`Error while processing cancelOrder() request: ${e}. It seems the order ${orderId} does not exist.`); - } else { - resolve(false); - log.warn(`Error while processing cancelOrder() request: ${e}. Data object I've got: ${data}.`); - } - }; - }).catch((err) => { - log.warn(`API request cancelOrder(orderId: ${orderId}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - getRates(pair) { - pair_ = formatPairName(pair); - return new Promise((resolve, reject) => { - CoindealClient.stats().then(function(data2) { - data2 = data2[pair_.coin1 + '_' + pair_.coin2]; - try { - if (data2) { - resolve({ - volume: +data2.baseVolume, - volumeInCoin2: +data2.quoteVolume, - high: +data2.high24hr, - low: +data2.low24hr, - ask: +data2.lowestAsk, - bid: +data2.highestBid, - }); - } else { - resolve(false); - } - } catch (e) { - resolve(false); - log.warn('Error while processing getRates() stats() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getRates(pair: ${pair}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - - placeOrder(orderType, pair, price, coin1Amount, limit = 1, coin2Amount) { - - const pair_ = formatPairName(pair); - let output = ''; - let message; - const order = {}; - - const type = (orderType === 'sell') ? 'sell' : 'buy'; - - if (!this.marketInfo(pair)) { - log.warn(`Unable to place an order on ${exchangeName} exchange. I don't have info about market ${pair}.`); - return undefined; - } - - if (coin1Amount) { - coin1Amount = (+coin1Amount).toFixed(this.marketInfo(pair).coin1Decimals); - } - if (coin2Amount) { - coin2Amount = (+coin2Amount).toFixed(this.marketInfo(pair).coin2Decimals); - } - if (price) { - price = (+price).toFixed(this.marketInfo(pair).coin2Decimals); - } - - if (limit) { // Limit order - output = `${orderType} ${coin1Amount} ${pair_.coin1.toUpperCase()} at ${price} ${pair_.coin2.toUpperCase()}.`; - - return new Promise((resolve, reject) => { - CoindealClient.addEntrustSheet(pair_.pair, coin1Amount, price, type).then(function(data) { - try { - const result = data; - if (result && result.id) { - message = `Order placed to ${output} Order Id: ${result.id.toString()}.`; - log.info(message); - order.orderId = result.id.toString(); - order.message = message; - resolve(order); - } else { - message = `Unable to place order to ${output} Check parameters and balances. Description: ${result.message}`; - if (result.errors && result.errors.errors) { - message += `: ${result.errors.errors.join(', ')}`; - } - log.warn(message); - order.orderId = false; - order.message = message; - resolve(order); - } - } catch (e) { - message = 'Error while processing placeOrder() request: ' + e; - log.warn(message); - order.orderId = false; - order.message = message; - resolve(order); - }; - }).catch((err) => { - log.warn(`API request CoindealClient.addEntrustSheet-limit(pair: ${pair_.pair}, coin1Amount: ${coin1Amount}, price: ${price}, type: ${type}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - - } else { // Market order - let size = 0; - if (orderType === 'sell') { - if (coin1Amount) { - size = coin1Amount; - output = `${orderType} ${coin1Amount} ${pair_.coin1.toUpperCase()} at Market Price on ${pair} market.`; - } else { - message = `Unable to place order to ${orderType} ${pair_.coin1.toUpperCase()} at Market Price on ${pair} market. Set ${pair_.coin1.toUpperCase()} amount.`; - log.warn(message); - order.orderId = false; - order.message = message; - return order; - } - } else { // buy - if (coin2Amount) { - output = `${orderType} ${pair_.coin1} for ${coin2Amount} ${pair_.coin2.toUpperCase()} at Market Price on ${pair} market.`; - } else { - message = `Unable to place order to ${orderType} ${pair_.coin1.toUpperCase()} for ${pair_.coin2.toUpperCase()} at Market Price on ${pair} market. Set ${pair_.coin2.toUpperCase()} amount.`; - log.warn(message); - order.orderId = false; - order.message = message; - return order; - } - } - - message = `Unable to place order to ${output} CoinDeal doesn't support Market orders yet.`; - log.warn(message); - order.orderId = false; - order.message = message; - return order; - - } - }, - getOrderBook(pair) { - const pair_ = formatPairName(pair); - return new Promise((resolve, reject) => { - CoindealClient.orderBook(pair_.pair).then(function(data) { - try { - let book = data; - if (!book) { - book = []; - } - const result = { - bids: new Array(), - asks: new Array(), - }; - book.ask.forEach((crypto) => { - result.asks.push({ - amount: +crypto.amount, - price: +crypto.price, - count: 1, - type: 'ask-sell-right', - }); - }); - result.asks.sort(function(a, b) { - return parseFloat(a.price) - parseFloat(b.price); - }); - book.bid.forEach((crypto) => { - result.bids.push({ - amount: +crypto.amount, - price: +crypto.price, - count: 1, - type: 'bid-buy-left', - }); - }); - result.bids.sort(function(a, b) { - return parseFloat(b.price) - parseFloat(a.price); - }); - resolve(result); - } catch (e) { - resolve(false); - log.warn('Error while processing orderBook() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getOrderBook(pair: ${pair}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - - getTradesHistory(pair, limit, sort, by, from, till, offset) { - const pair_ = formatPairName(pair); - return new Promise((resolve, reject) => { - CoindealClient.getTradesHistory(pair_.pair, limit, sort, by, from, till, offset).then(function(data) { - try { - let trades = data; - if (!trades) { - trades = []; - } - - const result = []; - trades.forEach((trade) => { - - result.push({ - coin1Amount: +trade.quantity, // amount in coin1 - price: +trade.price, // trade price - coin2Amount: +trade.quantity * +trade.price, // quote in coin2 - // trade.timestamp is like '2021-04-21 22:41:28' (ISO) - dateOri: trade.timestamp, - date: new Date(trade.timestamp + '+0000').getTime(), // must be as utils.unixTimeStampMs(): 1641121688194 - 1 641 121 688 194 - type: trade.side?.toLowerCase(), // 'buy' or 'sell' - tradeId: trade.id?.toString(), - // Additionally CoinDeal provides: clientOrderId, orderId, symbol, fee - }); - }); - - // We need ascending sort order - result.sort(function(a, b) { - return parseFloat(a.date) - parseFloat(b.date); - }); - resolve(result); - - } catch (e) { - resolve(false); - log.warn('Error while processing getTradesHistory() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getTradesHistory(pair: ${pair}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - - getDepositAddress(coin) { - return new Promise((resolve) => { - CoindealClient.getDepositAddress(coin).then(function(data) { - try { - if (data?.items?.length) { - resolve(data.items.map(({ address }) => ({ network: null, address }))); - } else { - resolve(false); - } - } catch (e) { - resolve(false); - log.warn('Error while processing getDepositAddress() request: ' + e); - }; - }).catch((err) => { - log.warn(`API request getDepositAddress(coin: ${coin}) of ${utils.getModuleName(module.id)} module failed. ${err}`); - resolve(undefined); - }); - }); - }, - }; -}; - -function formatPairName(pair) { - let pair_; let coin1; let coin2; - if (pair.indexOf('-') > -1) { - pair_ = pair.replace('-', '').toUpperCase(); - [coin1, coin2] = pair.split('-'); - } else if (pair.indexOf('_') > -1) { - pair_ = pair.replace('_', '').toUpperCase(); - [coin1, coin2] = pair.split('_'); - } else { - pair_ = pair.replace('/', '').toUpperCase(); - [coin1, coin2] = pair.split('/'); - } - - return { - pair: pair_, - coin1: coin1.toUpperCase(), - coin2: coin2.toUpperCase(), - }; -}