var debug = require('debug')('btcexp:rpcApi'); var async = require("async"); var utils = require("../utils.js"); var config = require("../config.js"); var coins = require("../coins.js"); var rpcQueue = async.queue(function(task, callback) { task.rpcCall(); if (callback != null) { callback(); } }, config.rpcConcurrency); function getBlockchainInfo() { return getRpcData("getblockchaininfo"); } function getNetworkInfo() { return getRpcData("getnetworkinfo"); } function getNetTotals() { return getRpcData("getnettotals"); } function getMempoolInfo() { return getRpcData("getmempoolinfo"); } function getMiningInfo() { return getRpcData("getmininginfo"); } function getUptimeSeconds() { return getRpcData("uptime"); } function getPeerInfo() { return getRpcData("getpeerinfo"); } function getRawMempool() { return getRpcDataWithParams({method:"getrawmempool", parameters:[true]}); } function getChainTxStats(blockCount) { return getRpcDataWithParams({method:"getchaintxstats", parameters:[blockCount]}); } function getBlockByHeight(blockHeight) { return new Promise(function(resolve, reject) { getRpcDataWithParams({method:"getblockhash", parameters:[blockHeight]}).then(function(blockhash) { getBlockByHash(blockhash).then(function(block) { resolve(block); }).catch(function(err) { reject(err); }); }).catch(function(err) { reject(err); }); }); } function getBlockByHash(blockHash) { debug("getBlockByHash: %s", blockHash); return new Promise(function(resolve, reject) { getRpcDataWithParams({method:"getblock", parameters:[blockHash]}).then(function(block) { getRawTransaction(block.tx[0]).then(function(tx) { block.coinbaseTx = tx; block.totalFees = utils.getBlockTotalFeesFromCoinbaseTxAndBlockHeight(tx, block.height); block.miner = utils.getMinerFromCoinbaseTx(tx); resolve(block); }).catch(function(err) { reject(err); }); }).catch(function(err) { reject(err); }); }); } function getAddress(address) { return getRpcDataWithParams({method:"validateaddress", parameters:[address]}); } function getRawTransaction(txid) { debug("getRawTransaction: %s", txid); return new Promise(function(resolve, reject) { if (coins[config.coin].genesisCoinbaseTransactionId && txid == coins[config.coin].genesisCoinbaseTransactionId) { // copy the "confirmations" field from genesis block to the genesis-coinbase tx promises.push(new Promise(function(resolve2, reject2) { getBlockchainInfo().then(function(blockchainInfoResult) { var result = coins[config.coin].genesisCoinbaseTransaction; result.confirmations = blockchainInfoResult.blocks; resolve([result]); }).catch(function(err) { reject(err); }); })); } else { getRpcDataWithParams({method:"getrawtransaction", parameters:[txid, 1]}).then(function(result) { resolve(result); }).catch(function(err) { reject(err); }); } }); } function getHelp() { return new Promise(function(resolve, reject) { client.command('help', function(err, result, resHeaders) { if (err) { console.log("Error 32907th429ghf: " + err); reject(err); return; } var lines = result.split("\n"); var sections = []; lines.forEach(function(line) { if (line.startsWith("==")) { var sectionName = line.substring(2); sectionName = sectionName.substring(0, sectionName.length - 2).trim(); sections.push({name:sectionName, methods:[]}); } else if (line.trim().length > 0) { var methodName = line.trim(); if (methodName.includes(" ")) { methodName = methodName.substring(0, methodName.indexOf(" ")); } sections[sections.length - 1].methods.push({name:methodName, content:line.trim()}); } }); resolve(sections); }).catch(function(err) { reject(err); }); }); } function getRpcMethodHelp(methodName) { return new Promise(function(resolve, reject) { client.command('help', methodName, function(err, result, resHeaders) { if (err) { console.log("Error 237hwerf07wehg: " + err); reject(err); return; } var output = {}; output.string = result; var str = result; var lines = str.split("\n"); var argumentLines = []; var catchArgs = false; lines.forEach(function(line) { if (line.trim().length == 0) { catchArgs = false; } if (catchArgs) { argumentLines.push(line); } if (line.trim() == "Arguments:" || line.trim() == "Arguments") { catchArgs = true; } }); var args = []; var argX = null; // looking for line starting with "N. " where N is an integer (1-2 digits) argumentLines.forEach(function(line) { var regex = /^([0-9]+)\.\s*"?(\w+)"?\s*\(([^,)]*),?\s*([^,)]*),?\s*([^,)]*),?\s*([^,)]*)?\s*\)\s*(.+)?$/; var match = regex.exec(line); if (match) { argX = {}; argX.name = match[2]; argX.detailsLines = []; argX.properties = []; if (match[3]) { argX.properties.push(match[3]); } if (match[4]) { argX.properties.push(match[4]); } if (match[5]) { argX.properties.push(match[5]); } if (match[6]) { argX.properties.push(match[6]); } if (match[7]) { argX.description = match[7]; } args.push(argX); } if (!match && argX) { argX.detailsLines.push(line); } }); output.args = args; resolve(output); }).catch(function(err) { reject(err); }); }); } function getRpcData(cmd) { return new Promise(function(resolve, reject) { debug(`RPC: ${cmd}`); rpcCall = function() { client.command(cmd, function(err, result, resHeaders) { if (err) { console.log(`Error for RPC command '${cmd}': ${err}`); reject(err); } else { resolve(result); } }).catch(function(err) { reject(err); }); }; rpcQueue.push({rpcCall:rpcCall}); }); } function getRpcDataWithParams(request) { return new Promise(function(resolve, reject) { debug(`RPC: ${request}`); rpcCall = function() { client.command([request], function(err, result, resHeaders) { if (err != null) { console.log(`Error for RPC command ${JSON.stringify(request)}: ${err}, headers=${resHeaders}`); reject(err); return; } resolve(result[0]); }); }; rpcQueue.push({rpcCall:rpcCall}); }); } module.exports = { getBlockchainInfo: getBlockchainInfo, getNetworkInfo: getNetworkInfo, getNetTotals: getNetTotals, getMempoolInfo: getMempoolInfo, getMiningInfo: getMiningInfo, getBlockByHeight: getBlockByHeight, getBlockByHash: getBlockByHash, getRawTransaction: getRawTransaction, getRawMempool: getRawMempool, getUptimeSeconds: getUptimeSeconds, getHelp: getHelp, getRpcMethodHelp: getRpcMethodHelp, getAddress: getAddress, getPeerInfo: getPeerInfo, getChainTxStats: getChainTxStats };