You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
328 lines
6.9 KiB
328 lines
6.9 KiB
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 activeQueueTasks = 0;
|
|
|
|
var rpcQueue = async.queue(function(task, callback) {
|
|
activeQueueTasks++;
|
|
//console.log("activeQueueTasks: " + activeQueueTasks);
|
|
|
|
task.rpcCall(function() {
|
|
callback();
|
|
|
|
activeQueueTasks--;
|
|
//console.log("activeQueueTasks: " + activeQueueTasks);
|
|
});
|
|
|
|
}, 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(callback) {
|
|
client.command(cmd, function(err, result, resHeaders) {
|
|
if (err) {
|
|
console.log(`Error for RPC command '${cmd}': ${err}`);
|
|
|
|
reject(err);
|
|
|
|
callback();
|
|
|
|
return;
|
|
}
|
|
|
|
resolve(result);
|
|
|
|
callback();
|
|
});
|
|
};
|
|
|
|
rpcQueue.push({rpcCall:rpcCall});
|
|
});
|
|
}
|
|
|
|
function getRpcDataWithParams(request) {
|
|
return new Promise(function(resolve, reject) {
|
|
debug(`RPC: ${request}`);
|
|
|
|
rpcCall = function(callback) {
|
|
client.command([request], function(err, result, resHeaders) {
|
|
if (err != null) {
|
|
console.log(`Error for RPC command ${JSON.stringify(request)}: ${err}, headers=${resHeaders}`);
|
|
|
|
reject(err);
|
|
|
|
callback();
|
|
|
|
return;
|
|
}
|
|
|
|
resolve(result[0]);
|
|
|
|
callback();
|
|
});
|
|
};
|
|
|
|
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
|
|
};
|