Browse Source

support for addressApi=blockchair.com

thanks for suggestion @LiveBit_io
fix-133-memory-crash
Dan Janosik 6 years ago
parent
commit
d6bc66384c
No known key found for this signature in database GPG Key ID: C6F8CE9FFDB2CED2
  1. 5
      .env-sample
  2. 2
      README.md
  3. 13
      app/api/addressApi.js
  4. 53
      app/api/blockchairAddressApi.js
  5. 2
      bin/cli.js
  6. 7
      routes/baseActionsRouter.js

5
.env-sample

@ -15,10 +15,9 @@
#BTCEXP_BITCOIND_RPC_TIMEOUT=5000 #BTCEXP_BITCOIND_RPC_TIMEOUT=5000
# Select optional "address API" to display address tx lists and balances # 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 # If electrumx set, the BTCEXP_ELECTRUMX_SERVERS variable must also be
# set. Neither blockchain.com or blockcypher.com support native-segwit bc1... # set.
# addresses, but are convenient for users who don't run their own ElectrumX.
BTCEXP_ADDRESS_API=(electrumx|blockchain.com|blockcypher.com) BTCEXP_ADDRESS_API=(electrumx|blockchain.com|blockcypher.com)
# Optional ElectrumX Servers. See BTCEXP_ADDRESS_API. This value is only # Optional ElectrumX Servers. See BTCEXP_ADDRESS_API. This value is only

2
README.md

@ -21,7 +21,7 @@ Live demos are available at:
* View transaction details, with navigation "backward" via spent transaction outputs * View transaction details, with navigation "backward" via spent transaction outputs
* View JSON content used to generate most pages * View JSON content used to generate most pages
* Search by transaction ID, block hash/height, and address * 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 * Mempool summary, with fee, size, and age breakdowns
* RPC command browser and terminal * RPC command browser and terminal
* Currently supports BTC, LTC (support for any Bitcoin-RPC-protocol-compliant coin can be added easily) * Currently supports BTC, LTC (support for any Bitcoin-RPC-protocol-compliant coin can be added easily)

13
app/api/addressApi.js

@ -6,10 +6,11 @@ var coinConfig = coins[config.coin];
var electrumAddressApi = require("./electrumAddressApi.js"); var electrumAddressApi = require("./electrumAddressApi.js");
var blockchainAddressApi = require("./blockchainAddressApi.js"); var blockchainAddressApi = require("./blockchainAddressApi.js");
var blockchairAddressApi = require("./blockchairAddressApi.js");
var blockcypherAddressApi = require("./blockcypherAddressApi.js"); var blockcypherAddressApi = require("./blockcypherAddressApi.js");
function getSupportedAddressApis() { function getSupportedAddressApis() {
return ["blockchain.com", "blockcypher.com", "electrumx"]; return ["blockchain.com", "blockchair.com", "blockcypher.com", "electrumx"];
} }
function getCurrentAddressApiFeatureSupport() { function getCurrentAddressApiFeatureSupport() {
@ -20,6 +21,13 @@ function getCurrentAddressApiFeatureSupport() {
sortAsc: true sortAsc: true
}; };
} else if (config.addressApi == "blockchair.com") {
return {
pageNumbers: true,
sortDesc: true,
sortAsc: false
};
} else if (config.addressApi == "blockcypher.com") { } else if (config.addressApi == "blockcypher.com") {
return { return {
pageNumbers: true, pageNumbers: true,
@ -43,6 +51,9 @@ function getAddressDetails(address, scriptPubkey, sort, limit, offset) {
if (config.addressApi == "blockchain.com") { if (config.addressApi == "blockchain.com") {
promises.push(blockchainAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset)); 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") { } else if (config.addressApi == "blockcypher.com") {
promises.push(blockcypherAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset)); promises.push(blockcypherAddressApi.getAddressDetails(address, scriptPubkey, sort, limit, offset));

53
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
};

2
bin/cli.js

@ -17,7 +17,7 @@ const args = require('meow')(`
-u, --bitcoind-user <user> username for bitcoind rpc [default: none] -u, --bitcoind-user <user> username for bitcoind rpc [default: none]
-w, --bitcoind-pass <pass> password for bitcoind rpc [default: none] -w, --bitcoind-pass <pass> password for bitcoind rpc [default: none]
--address-api <option> api to use for address queries (options: electrumx, blockchain.com, blockcypher.com) [default: none] --address-api <option> api to use for address queries (options: electrumx, blockchain.com, blockchair.com, blockcypher.com) [default: none]
-E, --electrumx-servers <..> comma separated list of electrum servers to use for address queries; only used if --address-api=electrumx [default: none] -E, --electrumx-servers <..> comma separated list of electrum servers to use for address queries; only used if --address-api=electrumx [default: none]
--rpc-allowall allow all rpc commands [default: false] --rpc-allowall allow all rpc commands [default: false]

7
routes/baseActionsRouter.js

@ -664,14 +664,13 @@ router.get("/address/:address", function(req, res, next) {
if (addressDetails.txids) { if (addressDetails.txids) {
var txids = addressDetails.txids; var txids = addressDetails.txids;
var blockHeightsByTxid = addressDetails.blockHeightsByTxid; var blockHeightsByTxid = {};
res.locals.txids = txids; res.locals.txids = txids;
coreApi.getRawTransactionsWithInputs(txids).then(function(rawTxResult) { coreApi.getRawTransactionsWithInputs(txids).then(function(rawTxResult) {
res.locals.transactions = rawTxResult.transactions; res.locals.transactions = rawTxResult.transactions;
res.locals.txInputsByTransaction = rawTxResult.txInputsByTransaction; res.locals.txInputsByTransaction = rawTxResult.txInputsByTransaction;
res.locals.blockHeightsByTxid = blockHeightsByTxid;
var addrGainsByTx = {}; var addrGainsByTx = {};
var addrLossesByTx = {}; var addrLossesByTx = {};
@ -683,6 +682,8 @@ router.get("/address/:address", function(req, res, next) {
var tx = rawTxResult.transactions[i]; var tx = rawTxResult.transactions[i];
var txInputs = rawTxResult.txInputsByTransaction[tx.txid]; var txInputs = rawTxResult.txInputsByTransaction[tx.txid];
blockHeightsByTxid[tx.txid] = tx.height;
for (var j = 0; j < tx.vout.length; j++) { for (var j = 0; j < tx.vout.length; j++) {
if (tx.vout[j].value > 0 && tx.vout[j].scriptPubKey && tx.vout[j].scriptPubKey.addresses && tx.vout[j].scriptPubKey.addresses.includes(address)) { if (tx.vout[j].value > 0 && tx.vout[j].scriptPubKey && tx.vout[j].scriptPubKey.addresses && tx.vout[j].scriptPubKey.addresses.includes(address)) {
if (addrGainsByTx[tx.txid] == null) { if (addrGainsByTx[tx.txid] == null) {
@ -712,6 +713,8 @@ router.get("/address/:address", function(req, res, next) {
//debugLog("txInputs: " + JSON.stringify(txInputs)); //debugLog("txInputs: " + JSON.stringify(txInputs));
} }
res.locals.blockHeightsByTxid = blockHeightsByTxid;
resolve(); resolve();
}).catch(function(err) { }).catch(function(err) {

Loading…
Cancel
Save