diff --git a/app.js b/app.js index 4c24391..b5a4438 100755 --- a/app.js +++ b/app.js @@ -83,7 +83,7 @@ const momentDurationFormat = require("moment-duration-format"); const coreApi = require("./app/api/coreApi.js"); const rpcApi = require("./app/api/rpcApi.js"); const coins = require("./app/coins.js"); -const request = require("request"); +const axios = require("axios"); const qrcode = require("qrcode"); const addressApi = require("./app/api/addressApi.js"); const electrumAddressApi = require("./app/api/electrumAddressApi.js"); @@ -93,7 +93,6 @@ const auth = require('./app/auth.js'); const sso = require('./app/sso.js'); const markdown = require("markdown-it")(); const v8 = require("v8"); -const axios = require("axios"); var compression = require("compression"); require("./app/currencies.js"); @@ -247,24 +246,21 @@ function loadMiningPoolConfigs() { }); } -function getSourcecodeProjectMetadata() { +async function getSourcecodeProjectMetadata() { var options = { url: "https://api.github.com/repos/janoside/btc-rpc-explorer", headers: { 'User-Agent': 'request' } }; + try { + const response = await axios(options); - request(options, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var responseBody = JSON.parse(body); + global.sourcecodeProjectMetadata = response.data; - global.sourcecodeProjectMetadata = responseBody; - - } else { - utils.logError("3208fh3ew7eghfg", {error:error, response:response, body:body}); + } catch (err) { + utils.logError("3208fh3ew7eghfg", err); } - }); } function loadChangelog() { diff --git a/app/api/blockchainAddressApi.js b/app/api/blockchainAddressApi.js index b704f0d..cf7354e 100644 --- a/app/api/blockchainAddressApi.js +++ b/app/api/blockchainAddressApi.js @@ -1,11 +1,11 @@ "use strict"; -const request = require("request"); +const axios = require("axios"); const utils = require("./../utils.js"); function getAddressDetails(address, scriptPubkey, sort, limit, offset) { - return new Promise(function(resolve, reject) { + return new Promise(async (resolve, reject) => { if (address.startsWith("bc1")) { reject({userText:"blockchain.com API does not support bc1 (native Segwit) addresses"}); @@ -14,49 +14,42 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) { if (sort == "asc") { // need to query the total number of tx first, then build paging info from that value - var options = { - url: `https://blockchain.info/rawaddr/${address}?limit=1`, - headers: { - 'User-Agent': 'request' + try { + const response = await axios.get( + `https://blockchain.info/rawaddr/${address}?limit=1`, + { headers: { 'User-Agent': 'axios' }}); + + var blockchainJson = response.data; + + var txCount = blockchainJson.n_tx; + var pageCount = parseInt(txCount / limit); + var lastPageSize = limit; + if (pageCount * limit < txCount) { + lastPageSize = txCount - pageCount * limit; } - }; - request(options, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var blockchainJson = JSON.parse(body); - - var txCount = blockchainJson.n_tx; - var pageCount = parseInt(txCount / limit); - var lastPageSize = limit; - if (pageCount * limit < txCount) { - lastPageSize = txCount - pageCount * limit; - } - - var dynamicOffset = txCount - limit - offset; - if (dynamicOffset < 0) { - limit += dynamicOffset; - dynamicOffset += limit; - } - - getAddressDetailsSortDesc(address, limit, dynamicOffset).then(function(result) { - result.txids.reverse(); - - resolve({addressDetails:result}); - - }).catch(function(err) { - utils.logError("2308hsghse", err); - - reject(err); - }); - - } else { - var fullError = {error:error, response:response, body:body}; - - utils.logError("we0f8hasd0fhas", fullError); - - reject(fullError); + var dynamicOffset = txCount - limit - offset; + if (dynamicOffset < 0) { + limit += dynamicOffset; + dynamicOffset += limit; } - }); + + getAddressDetailsSortDesc(address, limit, dynamicOffset).then(function(result) { + result.txids.reverse(); + + resolve({addressDetails:result}); + + }).catch(function(err) { + utils.logError("2308hsghse", err); + + reject(err); + }); + + } catch (err) { + utils.logError("we0f8hasd0fhas", err); + + reject(fullError); + } } else { getAddressDetailsSortDesc(address, limit, offset).then(function(result) { resolve({addressDetails:result}); @@ -71,44 +64,37 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) { } function getAddressDetailsSortDesc(address, limit, offset) { - return new Promise(function(resolve, reject) { - var options = { - url: `https://blockchain.info/rawaddr/${address}?limit=${limit}&offset=${offset}`, - headers: { - 'User-Agent': 'request' - } - }; + return new Promise(async (resolve, reject) => { + try { + const apiResponse = await axios.get( + `https://blockchain.info/rawaddr/${address}?limit=${limit}&offset=${offset}`, + { headers: { 'User-Agent': 'axios' }}); - request(options, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var blockchainJson = JSON.parse(body); + var blockchainJson = apiResponse.data; - var response = {}; + var response = {}; - response.txids = []; - response.blockHeightsByTxid = {}; - blockchainJson.txs.forEach(function(tx) { - response.txids.push(tx.hash); - response.blockHeightsByTxid[tx.hash] = tx.block_height; - }); + response.txids = []; + response.blockHeightsByTxid = {}; + blockchainJson.txs.forEach(function(tx) { + response.txids.push(tx.hash); + response.blockHeightsByTxid[tx.hash] = tx.block_height; + }); - response.txCount = blockchainJson.n_tx; - response.hash160 = blockchainJson.hash160; - response.totalReceivedSat = blockchainJson.total_received; - response.totalSentSat = blockchainJson.total_sent; - response.balanceSat = blockchainJson.final_balance; - response.source = "blockchain.com"; + response.txCount = blockchainJson.n_tx; + response.hash160 = blockchainJson.hash160; + response.totalReceivedSat = blockchainJson.total_received; + response.totalSentSat = blockchainJson.total_sent; + response.balanceSat = blockchainJson.final_balance; + response.source = "blockchain.com"; - resolve(response); + resolve(response); - } else { - var fullError = {error:error, response:response, body:body}; + } catch (err) { + utils.logError("32907shsghs", err); - utils.logError("32907shsghs", fullError); - - reject(fullError); - } - }); + reject(err); + } }); } diff --git a/app/api/blockchairAddressApi.js b/app/api/blockchairAddressApi.js index c686a92..3fde4a7 100644 --- a/app/api/blockchairAddressApi.js +++ b/app/api/blockchairAddressApi.js @@ -1,12 +1,12 @@ "use strict"; -const request = require("request"); +const axios = require("axios"); const utils = require("./../utils.js"); function getAddressDetails(address, scriptPubkey, sort, limit, offset) { // Note: blockchair api seems to not respect the limit parameter, always using 100 - return new Promise(function(resolve, reject) { + return new Promise(async (resolve, reject) => { var mainnetUrl = `https://api.blockchair.com/bitcoin/dashboards/address/${address}/?offset=${offset}`; var testnetUrl = `https://api.blockchair.com/bitcoin/testnet/dashboards/address/${address}/?offset=${offset}`; var url = (global.activeBlockchain == "main") ? mainnetUrl : ((global.activeBlockchain == "test") ? testnetUrl : mainnetUrl); @@ -18,38 +18,38 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) { } }; - request(options, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var responseObj = JSON.parse(body); - responseObj = responseObj.data[address]; + try { + const response = await axios.get( + url, + { headers: { "User-Agent": "axios" }}); - var result = {}; + var responseObj = response.data; + responseObj = responseObj.data[address]; - result.txids = []; + var result = {}; - // blockchair doesn't support offset for paging, so simulate up to the hard cap of 2,000 - for (var i = 0; i < Math.min(responseObj.transactions.length, limit); i++) { - var txid = responseObj.transactions[i]; + result.txids = []; - result.txids.push(txid); - } + // blockchair doesn't support offset for paging, so simulate up to the hard cap of 2,000 + for (var i = 0; i < Math.min(responseObj.transactions.length, limit); i++) { + var txid = responseObj.transactions[i]; - result.txCount = responseObj.address.transaction_count; - result.totalReceivedSat = responseObj.address.received; - result.totalSentSat = responseObj.address.spent; - result.balanceSat = responseObj.address.balance; - result.source = "blockchair.com"; - - resolve({addressDetails:result}); - - } else { - var fullError = {error:error, response:response, body:body}; - - utils.logError("308dhew3w83", fullError); - - reject(fullError); + result.txids.push(txid); } - }); + + result.txCount = responseObj.address.transaction_count; + result.totalReceivedSat = responseObj.address.received; + result.totalSentSat = responseObj.address.spent; + result.balanceSat = responseObj.address.balance; + result.source = "blockchair.com"; + + resolve({addressDetails:result}); + + } catch (err) { + utils.logError("308dhew3w83", err); + + reject(err); + } }); } diff --git a/app/api/blockcypherAddressApi.js b/app/api/blockcypherAddressApi.js index 0fbf92a..06fb5bc 100644 --- a/app/api/blockcypherAddressApi.js +++ b/app/api/blockcypherAddressApi.js @@ -1,11 +1,11 @@ "use strict"; -const request = require("request"); +const axios = require("axios"); const utils = require("./../utils.js"); function getAddressDetails(address, scriptPubkey, sort, limit, offset) { - return new Promise(function(resolve, reject) { + return new Promise(async (resolve, reject) => { if (address.startsWith("bc1")) { reject({userText:"blockcypher.com API does not support bc1 (native Segwit) addresses"}); @@ -24,39 +24,39 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) { } }; - request(options, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var blockcypherJson = JSON.parse(body); + try { + const apiResponse = await axios.get( + url, + { headers: { "User-Agent": "axios" }}); - var response = {}; + var blockcypherJson = apiResponse.data; - response.txids = []; - response.blockHeightsByTxid = {}; + var response = {}; - // blockcypher doesn't support offset for paging, so simulate up to the hard cap of 2,000 - for (var i = offset; i < Math.min(blockcypherJson.txrefs.length, limitOffset); i++) { - var tx = blockcypherJson.txrefs[i]; + response.txids = []; + response.blockHeightsByTxid = {}; - response.txids.push(tx.tx_hash); - response.blockHeightsByTxid[tx.tx_hash] = tx.block_height; - } + // blockcypher doesn't support offset for paging, so simulate up to the hard cap of 2,000 + for (var i = offset; i < Math.min(blockcypherJson.txrefs.length, limitOffset); i++) { + var tx = blockcypherJson.txrefs[i]; - response.txCount = blockcypherJson.n_tx; - response.totalReceivedSat = blockcypherJson.total_received; - response.totalSentSat = blockcypherJson.total_sent; - response.balanceSat = blockcypherJson.final_balance; - response.source = "blockcypher.com"; - - resolve({addressDetails:response}); - - } else { - var fullError = {error:error, response:response, body:body}; - - utils.logError("097wef0adsgadgs", fullError); - - reject(fullError); + response.txids.push(tx.tx_hash); + response.blockHeightsByTxid[tx.tx_hash] = tx.block_height; } - }); + + response.txCount = blockcypherJson.n_tx; + response.totalReceivedSat = blockcypherJson.total_received; + response.totalSentSat = blockcypherJson.total_sent; + response.balanceSat = blockcypherJson.final_balance; + response.source = "blockcypher.com"; + + resolve({addressDetails:response}); + + } catch (err) { + utils.logError("097wef0adsgadgs", err); + + reject(err); + } }); } diff --git a/app/utils.js b/app/utils.js index 1f8252d..2c1abc3 100644 --- a/app/utils.js +++ b/app/utils.js @@ -6,7 +6,7 @@ const debugErrorLog = debug("btcexp:error"); const debugErrorVerboseLog = debug("btcexp:errorVerbose"); const Decimal = require("decimal.js"); -const request = require("request"); +const axios = require("axios"); const qrcode = require("qrcode"); const bs58check = require("bs58check"); const bip32 = require('bip32'); @@ -585,30 +585,28 @@ function estimatedSupply(height) { return supply; } -function refreshExchangeRates() { +async function refreshExchangeRates() { if (!config.queryExchangeRates) { return; } if (coins[config.coin].exchangeRateData) { - request(coins[config.coin].exchangeRateData.jsonUrl, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var responseBody = JSON.parse(body); + try { + const response = await axios.get(coins[config.coin].exchangeRateData.jsonUrl); - var exchangeRates = coins[config.coin].exchangeRateData.responseBodySelectorFunction(responseBody); - if (exchangeRates != null) { - global.exchangeRates = exchangeRates; - global.exchangeRatesUpdateTime = new Date(); + var exchangeRates = coins[config.coin].exchangeRateData.responseBodySelectorFunction(response.data); + if (exchangeRates != null) { + global.exchangeRates = exchangeRates; + global.exchangeRatesUpdateTime = new Date(); - debugLog("Using exchange rates: " + JSON.stringify(global.exchangeRates) + " starting at " + global.exchangeRatesUpdateTime); + debugLog("Using exchange rates: " + JSON.stringify(global.exchangeRates) + " starting at " + global.exchangeRatesUpdateTime); - } else { - debugLog("Unable to get exchange rate data"); - } } else { - logError("39r7h2390fgewfgds", {error:error, response:response, body:body}); + debugLog("Unable to get exchange rate data"); } - }); + } catch (err) { + logError("39r7h2390fgewfgds", err); + } } if (coins[config.coin].goldExchangeRateData) { @@ -619,24 +617,22 @@ function refreshExchangeRates() { debugLog("Using DEBUG gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime); } else { - request(coins[config.coin].goldExchangeRateData.jsonUrl, function(error, response, body) { - if (error == null && response && response.statusCode && response.statusCode == 200) { - var responseBody = JSON.parse(body); + try { + const response = await axios.get(coins[config.coin].goldExchangeRateData.jsonUrl); - var exchangeRates = coins[config.coin].goldExchangeRateData.responseBodySelectorFunction(responseBody); - if (exchangeRates != null) { - global.goldExchangeRates = exchangeRates; - global.goldExchangeRatesUpdateTime = new Date(); + var exchangeRates = coins[config.coin].goldExchangeRateData.responseBodySelectorFunction(response.data); + if (exchangeRates != null) { + global.goldExchangeRates = exchangeRates; + global.goldExchangeRatesUpdateTime = new Date(); - debugLog("Using gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime); + debugLog("Using gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime); - } else { - debugLog("Unable to get gold exchange rate data"); - } } else { - logError("34082yt78yewewe", {error:error, response:response, body:body}); + debugLog("Unable to get gold exchange rate data"); } - }); + } catch (err) { + logError("34082yt78yewewe", err); + } } } } @@ -655,45 +651,39 @@ function geoLocateIpAddresses(ipAddresses, provider) { var promises = []; for (var i = 0; i < ipAddresses.length; i++) { var ipStr = ipAddresses[i]; - + promises.push(new Promise(function(resolve2, reject2) { - ipCache.get(ipStr).then(function(result) { + ipCache.get(ipStr).then(async function(result) { if (result.value == null) { var apiUrl = "http://api.ipstack.com/" + result.key + "?access_key=" + config.credentials.ipStackComApiAccessKey; - request(apiUrl, function(error, response, body) { - if (error) { - debugLog("Failed IP-geo-lookup: " + result.key); + try { + const response = await axios.get(apiUrl); - logError("39724gdge33a", error, {ip: result.key}); + var ip = response.data.ip; - // we failed to get what we wanted, but there's no meaningful recourse, - // so we log the failure and continue without objection - resolve2(); + ipDetails.detailsByIp[ip] = response.data; + + if (response.data.latitude && response.data.longitude) { + debugLog(`Successful IP-geo-lookup: ${ip} -> (${response.data.latitude}, ${response.data.longitude})`); } else { - if (response != null && response.statusCode == 200) { - var resBody = JSON.parse(response.body); - var ip = resBody.ip; + debugLog(`Unknown location for IP-geo-lookup: ${ip}`); + } - ipDetails.detailsByIp[ip] = resBody; + ipCache.set(ip, response.data, 1000 * 60 * 60 * 24 * 365); - if (resBody.latitude && resBody.longitude) { - debugLog(`Successful IP-geo-lookup: ${ip} -> (${resBody.latitude}, ${resBody.longitude})`); + resolve2(); - } else { - debugLog(`Unknown location for IP-geo-lookup: ${ip}`); - } + } catch (err) { + debugLog("Failed IP-geo-lookup: " + result.key); - ipCache.set(ip, resBody, 1000 * 60 * 60 * 24 * 365); + logError("39724gdge33a", error, {ip: result.key}); - } else { - debugLog("Unsuccessful IP-geo-lookup: " + result.key); - } - - resolve2(); - } - }); + // we failed to get what we wanted, but there's no meaningful recourse, + // so we log the failure and continue without objection + resolve2(); + } } else { ipDetails.detailsByIp[result.key] = result.value; diff --git a/bin/refresh-mining-pool-configs.js b/bin/refresh-mining-pool-configs.js index e92644a..4b5fc8f 100644 --- a/bin/refresh-mining-pool-configs.js +++ b/bin/refresh-mining-pool-configs.js @@ -2,94 +2,82 @@ "use strict"; -var os = require('os'); -var path = require('path'); -var dotenv = require("dotenv"); -var fs = require('fs'); -var request = require("request"); +const os = require("os"); +const path = require("path"); +const dotenv = require("dotenv"); +const fs = require("fs"); +const axios = require("axios"); -var utils = require("../app/utils.js"); -var coins = require("../app/coins.js"); +const utils = require("../app/utils.js"); +const coins = require("../app/coins.js"); async function refreshMiningPoolsForCoin(coinName) { - return new Promise(function(resolve, reject) { - console.log(`Refreshing mining pools for ${coinName}...`); + console.log(`Refreshing mining pools for ${coinName}...`); - if (coins[coinName].miningPoolsConfigUrls) { - var miningPoolsConfigDir = path.join(__dirname, "..", "public", "txt", "mining-pools-configs", coinName); - fs.readdir(miningPoolsConfigDir, function(err, files) { - if (err) { - reject(`Unable to delete existing files from '${miningPoolsConfigDir}'`); - - return; - } - - files.forEach(function(file) { - // delete existing file - fs.unlinkSync(path.join(miningPoolsConfigDir, file)); - }); - }); - - var miningPoolsConfigUrls = coins[coinName].miningPoolsConfigUrls; - - var promises = []; - - console.log(`${miningPoolsConfigUrls.length} mining pool config(s) found for ${coinName}`); - - for (var i = 0; i < miningPoolsConfigUrls.length; i++) { - promises.push(refreshMiningPoolConfig(coinName, i, miningPoolsConfigUrls[i])); + if (coins[coinName].miningPoolsConfigUrls) { + const miningPoolsConfigDir = path.join(__dirname, "..", "public", "txt", "mining-pools-configs", coinName); + + fs.readdir(miningPoolsConfigDir, (err, files) => { + if (err) { + throw new Error(`Unable to delete existing files from '${miningPoolsConfigDir}'`); } - Promise.all(promises).then(function() { - console.log(`Refreshed ${miningPoolsConfigUrls.length} mining pool config(s) for ${coinName}\n---------------------------------------------`); - - resolve(); - - }).catch(function(err) { - reject(err); + files.forEach(function(file) { + // delete existing file + fs.unlinkSync(path.join(miningPoolsConfigDir, file)); }); - } else { - console.log(`No mining pool URLs configured for ${coinName}`); + }); - reject(`No mining pool URLs configured for ${coinName}`); + const miningPoolsConfigUrls = coins[coinName].miningPoolsConfigUrls; + + const promises = []; + + console.log(`${miningPoolsConfigUrls.length} mining pool config(s) found for ${coinName}`); + + for (let i = 0; i < miningPoolsConfigUrls.length; i++) { + promises.push(refreshMiningPoolConfig(coinName, i, miningPoolsConfigUrls[i])); } - }); + + await Promise.all(promises); + + console.log(`Refreshed ${miningPoolsConfigUrls.length} mining pool config(s) for ${coinName}\n---------------------------------------------`); + + } else { + console.log(`No mining pool URLs configured for ${coinName}`); + + throw new Error(`No mining pool URLs configured for ${coinName}`); + } } async function refreshMiningPoolConfig(coinName, index, url) { - return new Promise(function(resolve, reject) { - request(url, function(error, response, body) { - if (!error && response && response.statusCode && response.statusCode == 200) { - var responseBody = JSON.parse(body); + try { + const response = await axios.get(url, { transformResponse: res => res }); - var filename = path.join(__dirname, "..", "public", "txt", "mining-pools-configs", coinName, index + ".json"); + const filename = path.join(__dirname, "..", "public", "txt", "mining-pools-configs", coinName, index + ".json"); - fs.writeFileSync(filename, body, function(err) { - console.log(`Error writing file '${filename}': ${err}`); - }); - - console.log(`Wrote '${coinName}/${index}.json' with contents of url: ${url}`); - - resolve(); - - } else { - console.log(`Error downloading mining pool config for ${coinName}: url=${url}`); - - reject(error); - } + fs.writeFileSync(filename, response.data, (err) => { + console.log(`Error writing file '${filename}': ${err}`); }); - }); + + console.log(`Wrote '${coinName}/${index}.json' with contents of url: ${url}`); + + } catch (err) { + console.log(`Error downloading mining pool config for ${coinName}: url=${url}`); + + throw err; + } } async function refreshAllMiningPoolConfigs() { - var outerPromises = []; + const outerPromises = []; - for (var i = 0; i < coins.coins.length; i++) { - var coinName = coins.coins[i]; + for (let i = 0; i < coins.coins.length; i++) { + const coinName = coins.coins[i]; await refreshMiningPoolsForCoin(coinName); } } -refreshAllMiningPoolConfigs(); - +refreshAllMiningPoolConfigs().then(() => { + process.exit(); +}); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2825145..e3569fe 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -42,7 +42,6 @@ "pug": "^3.0.2", "qrcode": "^1.4.4", "redis": "^3.0.2", - "request": "^2.88.2", "semver": "^7.3.5", "serve-favicon": "^2.5.0", "simple-git": "^2.39.0" diff --git a/package.json b/package.json index 7067fa2..ed18da9 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "pug": "^3.0.2", "qrcode": "^1.4.4", "redis": "^3.0.2", - "request": "^2.88.2", "semver": "^7.3.5", "serve-favicon": "^2.5.0", "simple-git": "^2.39.0"