From d6bc66384c2935ae07e089bf87aba20fb2e4077f Mon Sep 17 00:00:00 2001 From: Dan Janosik Date: Sat, 27 Apr 2019 11:20:13 -0400 Subject: [PATCH] support for addressApi=blockchair.com thanks for suggestion @LiveBit_io --- .env-sample | 5 ++-- README.md | 2 +- app/api/addressApi.js | 13 +++++++- app/api/blockchairAddressApi.js | 53 +++++++++++++++++++++++++++++++++ bin/cli.js | 2 +- routes/baseActionsRouter.js | 9 ++++-- 6 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 app/api/blockchairAddressApi.js diff --git a/.env-sample b/.env-sample index 18e2647..9537fa9 100644 --- a/.env-sample +++ b/.env-sample @@ -15,10 +15,9 @@ #BTCEXP_BITCOIND_RPC_TIMEOUT=5000 # Select optional "address API" to display address tx lists and balances -# Options: electrumx, blockchain.com, blockcypher.com +# Options: electrumx, blockchain.com, blockchair.com, blockcypher.com # If electrumx set, the BTCEXP_ELECTRUMX_SERVERS variable must also be -# set. Neither blockchain.com or blockcypher.com support native-segwit bc1... -# addresses, but are convenient for users who don't run their own ElectrumX. +# set. BTCEXP_ADDRESS_API=(electrumx|blockchain.com|blockcypher.com) # Optional ElectrumX Servers. See BTCEXP_ADDRESS_API. This value is only diff --git a/README.md b/README.md index 18bff79..4616bc0 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Live demos are available at: * View transaction details, with navigation "backward" via spent transaction outputs * View JSON content used to generate most pages * Search by transaction ID, block hash/height, and address -* Optional transaction history for addresses by querying from ElectrumX, blockchain.com, or blockcypher.com +* Optional transaction history for addresses by querying from ElectrumX, blockchain.com, blockchair.com, or blockcypher.com * Mempool summary, with fee, size, and age breakdowns * RPC command browser and terminal * Currently supports BTC, LTC (support for any Bitcoin-RPC-protocol-compliant coin can be added easily) diff --git a/app/api/addressApi.js b/app/api/addressApi.js index 1ce2446..2476f05 100644 --- a/app/api/addressApi.js +++ b/app/api/addressApi.js @@ -6,10 +6,11 @@ var coinConfig = coins[config.coin]; var electrumAddressApi = require("./electrumAddressApi.js"); var blockchainAddressApi = require("./blockchainAddressApi.js"); +var blockchairAddressApi = require("./blockchairAddressApi.js"); var blockcypherAddressApi = require("./blockcypherAddressApi.js"); function getSupportedAddressApis() { - return ["blockchain.com", "blockcypher.com", "electrumx"]; + return ["blockchain.com", "blockchair.com", "blockcypher.com", "electrumx"]; } function getCurrentAddressApiFeatureSupport() { @@ -20,6 +21,13 @@ function getCurrentAddressApiFeatureSupport() { sortAsc: true }; + } else if (config.addressApi == "blockchair.com") { + return { + pageNumbers: true, + sortDesc: true, + sortAsc: false + }; + } else if (config.addressApi == "blockcypher.com") { return { pageNumbers: true, @@ -43,6 +51,9 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) { if (config.addressApi == "blockchain.com") { promises.push(blockchainAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset)); + } else if (config.addressApi == "blockchair.com") { + promises.push(blockchairAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset)); + } else if (config.addressApi == "blockcypher.com") { promises.push(blockcypherAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset)); diff --git a/app/api/blockchairAddressApi.js b/app/api/blockchairAddressApi.js new file mode 100644 index 0000000..6f5bec1 --- /dev/null +++ b/app/api/blockchairAddressApi.js @@ -0,0 +1,53 @@ +var request = require("request"); +var 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) { + var options = { + url: `https://api.blockchair.com/bitcoin/dashboards/address/${address}/?offset=${offset}`, + headers: { + 'User-Agent': 'request' + } + }; + + request(options, function(error, response, body) { + if (error == null && response && response.statusCode && response.statusCode == 200) { + var responseObj = JSON.parse(body); + responseObj = responseObj.data[address]; + + var result = {}; + + result.txids = []; + + // blockchair doesn't support offset for paging, so simulate up to the hard cap of 2,000 + for (var i = offset; i < Math.min(responseObj.transactions.length, limit); i++) { + var txid = responseObj.transactions[i]; + + 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}); + + } else { + var fullError = {error:error, response:response, body:body}; + + utils.logError("308dhew3w83", fullError); + + reject(fullError); + } + }); + }); +} + + +module.exports = { + getAddressDetails: getAddressDetails +}; \ No newline at end of file diff --git a/bin/cli.js b/bin/cli.js index f1010fe..ad610b2 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -17,7 +17,7 @@ const args = require('meow')(` -u, --bitcoind-user username for bitcoind rpc [default: none] -w, --bitcoind-pass password for bitcoind rpc [default: none] - --address-api