7 changed files with 1006 additions and 214 deletions
@ -0,0 +1,382 @@ |
|||||
|
var LRU = require("lru-cache"); |
||||
|
|
||||
|
var utils = require("../utils.js"); |
||||
|
var config = require("../config.js"); |
||||
|
var coins = require("../coins.js"); |
||||
|
|
||||
|
// choose one of the below: RPC to a node, or mock data while testing
|
||||
|
var rpcApi = require("./rpcApi.js"); |
||||
|
//var rpcApi = require("./mockApi.js");
|
||||
|
|
||||
|
var miscCache = LRU(50); |
||||
|
var blockCache = LRU(50); |
||||
|
var txCache = LRU(200); |
||||
|
|
||||
|
|
||||
|
|
||||
|
function getGenesisBlockHash() { |
||||
|
return coins[config.coin].genesisBlockHash; |
||||
|
} |
||||
|
|
||||
|
function getGenesisCoinbaseTransactionId() { |
||||
|
return coins[config.coin].genesisCoinbaseTransactionId; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
function tryCacheThenRpcApi(cache, cacheKey, cacheMaxAge, rpcApiFunction) { |
||||
|
console.log("tryCache: " + cacheKey + ", " + cacheMaxAge); |
||||
|
|
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var result = cache.get(cacheKey); |
||||
|
if (result) { |
||||
|
resolve(result); |
||||
|
|
||||
|
} else { |
||||
|
rpcApiFunction().then(function(result) { |
||||
|
if (result) { |
||||
|
cache.set(cacheKey, result, cacheMaxAge); |
||||
|
|
||||
|
resolve(result); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
function getBlockchainInfo() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getBlockchainInfo", 10000, rpcApi.getBlockchainInfo); |
||||
|
} |
||||
|
|
||||
|
function getNetworkInfo() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getNetworkInfo", 10000, rpcApi.getNetworkInfo); |
||||
|
} |
||||
|
|
||||
|
function getNetTotals() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getNetTotals", 10000, rpcApi.getNetTotals); |
||||
|
} |
||||
|
|
||||
|
function getMempoolInfo() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getMempoolInfo", 1000, rpcApi.getMempoolInfo); |
||||
|
} |
||||
|
|
||||
|
function getUptimeSeconds() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getUptimeSeconds", 1000, rpcApi.getUptimeSeconds); |
||||
|
} |
||||
|
|
||||
|
function getMempoolStats() { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
tryCacheThenRpcApi(miscCache, "getRawMempool", 5000, rpcApi.getRawMempool).then(function(result) { |
||||
|
var maxFee = 0; |
||||
|
var maxFeePerByte = 0; |
||||
|
for (var txid in result) { |
||||
|
var txMempoolInfo = result[txid]; |
||||
|
var fee = txMempoolInfo.modifiedfee; |
||||
|
var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; |
||||
|
|
||||
|
if (fee > maxFee) { |
||||
|
maxFee = txMempoolInfo.modifiedfee; |
||||
|
} |
||||
|
|
||||
|
if (feePerByte > maxFeePerByte) { |
||||
|
maxFeePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var satoshiPerByteBucketMaxima = coins[config.coin].feeSatoshiPerByteBucketMaxima; |
||||
|
var bucketCount = satoshiPerByteBucketMaxima.length + 1; |
||||
|
|
||||
|
var satoshiPerByteBuckets = []; |
||||
|
var satoshiPerByteBucketLabels = []; |
||||
|
|
||||
|
satoshiPerByteBucketLabels[0] = ("[0 - " + satoshiPerByteBucketMaxima[0] + ")"); |
||||
|
for (var i = 0; i < bucketCount; i++) { |
||||
|
satoshiPerByteBuckets[i] = {"count":0, "totalFees":0, "totalBytes":0}; |
||||
|
|
||||
|
if (i > 0 && i < bucketCount - 1) { |
||||
|
satoshiPerByteBucketLabels[i] = ("[" + satoshiPerByteBucketMaxima[i - 1] + " - " + satoshiPerByteBucketMaxima[i] + ")"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
satoshiPerByteBucketLabels[bucketCount - 1] = (satoshiPerByteBucketMaxima[satoshiPerByteBucketMaxima.length - 1] + "+"); |
||||
|
|
||||
|
var summary = { |
||||
|
"count":0, |
||||
|
"totalFees":0, |
||||
|
"totalBytes":0, |
||||
|
"satoshiPerByteBuckets":satoshiPerByteBuckets, |
||||
|
"satoshiPerByteBucketLabels":satoshiPerByteBucketLabels |
||||
|
}; |
||||
|
|
||||
|
for (var txid in result) { |
||||
|
var txMempoolInfo = result[txid]; |
||||
|
var fee = txMempoolInfo.modifiedfee; |
||||
|
var feePerByte = txMempoolInfo.modifiedfee / txMempoolInfo.size; |
||||
|
var satoshiPerByte = feePerByte * 100000000; |
||||
|
|
||||
|
var addedToBucket = false; |
||||
|
for (var i = 0; i < satoshiPerByteBucketMaxima.length; i++) { |
||||
|
if (satoshiPerByteBucketMaxima[i] > satoshiPerByte) { |
||||
|
satoshiPerByteBuckets[i]["count"]++; |
||||
|
satoshiPerByteBuckets[i]["totalFees"] += fee; |
||||
|
satoshiPerByteBuckets[i]["totalBytes"] += txMempoolInfo.size; |
||||
|
|
||||
|
addedToBucket = true; |
||||
|
|
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (!addedToBucket) { |
||||
|
satoshiPerByteBuckets[bucketCount - 1]["count"]++; |
||||
|
satoshiPerByteBuckets[bucketCount - 1]["totalFees"] += fee; |
||||
|
satoshiPerByteBuckets[bucketCount - 1]["totalBytes"] += txMempoolInfo.size; |
||||
|
} |
||||
|
|
||||
|
summary["count"]++; |
||||
|
summary["totalFees"] += txMempoolInfo.modifiedfee; |
||||
|
summary["totalBytes"] += txMempoolInfo.size; |
||||
|
} |
||||
|
|
||||
|
summary["averageFee"] = summary["totalFees"] / summary["count"]; |
||||
|
summary["averageFeePerByte"] = summary["totalFees"] / summary["totalBytes"]; |
||||
|
|
||||
|
summary["satoshiPerByteBucketMaxima"] = satoshiPerByteBucketMaxima; |
||||
|
summary["satoshiPerByteBucketCounts"] = []; |
||||
|
summary["satoshiPerByteBucketTotalFees"] = []; |
||||
|
|
||||
|
for (var i = 0; i < bucketCount; i++) { |
||||
|
summary["satoshiPerByteBucketCounts"].push(summary["satoshiPerByteBuckets"][i]["count"]); |
||||
|
summary["satoshiPerByteBucketTotalFees"].push(summary["satoshiPerByteBuckets"][i]["totalFees"]); |
||||
|
} |
||||
|
|
||||
|
resolve(summary); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlockByHeight(blockHeight) { |
||||
|
return tryCacheThenRpcApi(blockCache, "getBlockByHeight-" + blockHeight, 3600000, function() { |
||||
|
return rpcApi.getBlockByHeight(blockHeight); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlocksByHeight(blockHeights) { |
||||
|
var blockHeightsNotInCache = []; |
||||
|
var blocksByIndex = {}; |
||||
|
|
||||
|
for (var i = 0; i < blockHeights.length; i++) { |
||||
|
var blockI = blockCache.get("getBlockByHeight-" + blockHeights[i]); |
||||
|
if (blockI == null) { |
||||
|
blockHeightsNotInCache.push(blockHeights[i]); |
||||
|
|
||||
|
} else { |
||||
|
blocksByIndex[i] = blockI; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var combinedBlocks = []; |
||||
|
if (blockHeightsNotInCache.length > 0) { |
||||
|
rpcApi.getBlocksByHeight(blockHeightsNotInCache).then(function(queriedBlocks) { |
||||
|
console.log("qbs: " + queriedBlocks); |
||||
|
var queriedBlocksCurrentIndex = 0; |
||||
|
for (var i = 0; i < blockHeights.length; i++) { |
||||
|
if (blocksByIndex.hasOwnProperty(i)) { |
||||
|
combinedBlocks.push(blocksByIndex[i]); |
||||
|
|
||||
|
} else { |
||||
|
var queriedBlock = queriedBlocks[queriedBlocksCurrentIndex]; |
||||
|
console.log("queriedBlock: " + queriedBlock); |
||||
|
|
||||
|
combinedBlocks.push(queriedBlock); |
||||
|
|
||||
|
blockCache.set("getBlockByHeight-" + queriedBlock.height, queriedBlock, 3600000); |
||||
|
|
||||
|
queriedBlocksCurrentIndex++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolve(combinedBlocks); |
||||
|
}).catch(function(err) { |
||||
|
console.log("Error 39g2rfyewgf: " + err); |
||||
|
}); |
||||
|
} else { |
||||
|
for (var i = 0; i < blockHeights.length; i++) { |
||||
|
combinedBlocks.push(blocksByIndex[i]); |
||||
|
} |
||||
|
|
||||
|
resolve(combinedBlocks); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlockByHash(blockHash) { |
||||
|
return tryCacheThenRpcApi(blockCache, "getBlockByHash-" + blockHash, 3600000, function() { |
||||
|
return rpcApi.getBlockByHash(blockHash); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlocksByHash(blockHashes) { |
||||
|
var blockHashesNotInCache = []; |
||||
|
var blocksByIndex = {}; |
||||
|
|
||||
|
for (var i = 0; i < blockHashes.length; i++) { |
||||
|
var blockI = blockCache.get("getBlockByHash-" + blockHashes[i]); |
||||
|
if (blockI == null) { |
||||
|
blockHashesNotInCache.push(blockHashes[i]); |
||||
|
|
||||
|
} else { |
||||
|
blocksByIndex[i] = blockI; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var combinedBlocks = []; |
||||
|
if (blockHashesNotInCache.length > 0) { |
||||
|
rpcApi.getBlocksByHash(blockHashesNotInCache).then(function(queriedBlocks) { |
||||
|
var queriedBlocksCurrentIndex = 0; |
||||
|
for (var i = 0; i < blockHashes.length; i++) { |
||||
|
if (blocksByIndex.hasOwnProperty(i)) { |
||||
|
combinedBlocks.push(blocksByIndex[i]); |
||||
|
|
||||
|
} else { |
||||
|
var queriedBlock = queriedBlocks[queriedBlocksCurrentIndex]; |
||||
|
|
||||
|
combinedBlocks.push(queriedBlock); |
||||
|
|
||||
|
blockCache.set("getBlockByHash-" + queriedBlock.hash, queriedBlock, 3600000); |
||||
|
|
||||
|
queriedBlocksCurrentIndex++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolve(combinedBlocks); |
||||
|
}); |
||||
|
} else { |
||||
|
for (var i = 0; i < blockHeights.length; i++) { |
||||
|
combinedBlocks.push(blocksByIndex[i]); |
||||
|
} |
||||
|
|
||||
|
resolve(combinedBlocks); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getRawTransaction(txid) { |
||||
|
return tryCacheThenRpcApi(txCache, "getRawTransaction-" + txid, 3600000, function() { |
||||
|
return rpcApi.getRawTransaction(txid); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getAddress(address) { |
||||
|
return tryCacheThenRpcApi(miscCache, "getAddress-" + address, 3600000, function() { |
||||
|
return rpcApi.getAddress(address); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getRawTransactions(txids) { |
||||
|
var txidsNotInCache = []; |
||||
|
var txsByIndex = {}; |
||||
|
|
||||
|
for (var i = 0; i < txids.length; i++) { |
||||
|
var txI = txCache.get("getRawTransaction-" + txids[i]); |
||||
|
if (txI == null) { |
||||
|
txidsNotInCache.push(txids[i]); |
||||
|
|
||||
|
} else { |
||||
|
txsByIndex[i] = txI; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var combinedTxs = []; |
||||
|
if (txidsNotInCache.length > 0) { |
||||
|
rpcApi.getRawTransactions(txidsNotInCache).then(function(queriedTxs) { |
||||
|
var queriedTxsCurrentIndex = 0; |
||||
|
for (var i = 0; i < txids.length; i++) { |
||||
|
if (txsByIndex.hasOwnProperty(i)) { |
||||
|
combinedTxs.push(txsByIndex[i]); |
||||
|
|
||||
|
} else { |
||||
|
var queriedTx = queriedTxs[queriedTxsCurrentIndex]; |
||||
|
|
||||
|
combinedTxs.push(queriedTx); |
||||
|
|
||||
|
txCache.set("getRawTransaction-" + queriedTx.txid, queriedTx, 3600000); |
||||
|
|
||||
|
queriedTxsCurrentIndex++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolve(combinedTxs); |
||||
|
}); |
||||
|
} else { |
||||
|
for (var i = 0; i < txids.length; i++) { |
||||
|
combinedTxs.push(txsByIndex[i]); |
||||
|
} |
||||
|
|
||||
|
resolve(combinedTxs); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getMinerFromCoinbaseTx(tx) { |
||||
|
if (global.miningPoolsConfig) { |
||||
|
for (var coinbaseTag in global.miningPoolsConfig.coinbase_tags) { |
||||
|
if (global.miningPoolsConfig.coinbase_tags.hasOwnProperty(coinbaseTag)) { |
||||
|
if (utils.hex2ascii(tx.vin[0].coinbase).indexOf(coinbaseTag) != -1) { |
||||
|
return global.miningPoolsConfig.coinbase_tags[coinbaseTag]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
for (var payoutAddress in global.miningPoolsConfig.payout_addresses) { |
||||
|
if (global.miningPoolsConfig.payout_addresses.hasOwnProperty(payoutAddress)) { |
||||
|
return global.miningPoolsConfig.payout_addresses[payoutAddress]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
function getBlockByHashWithTransactions(blockHash, txLimit, txOffset) { |
||||
|
return tryCacheThenRpcApi(miscCache, "getBlockByHashWithTransactions-" + blockHash + "-" + txLimit + "-" + txOffset, 3600000, function() { |
||||
|
return rpcApi.getBlockByHashWithTransactions(blockHash, txLimit, txOffset); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getHelp() { |
||||
|
return tryCacheThenRpcApi(miscCache, "getHelp", 3600000, function() { |
||||
|
return rpcApi.getHelp(); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getRpcMethodHelp(methodName) { |
||||
|
return tryCacheThenRpcApi(miscCache, "getHelp-" + methodName, 3600000, function() { |
||||
|
return rpcApi.getRpcMethodHelp(methodName); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
module.exports = { |
||||
|
getGenesisBlockHash: getGenesisBlockHash, |
||||
|
getGenesisCoinbaseTransactionId: getGenesisCoinbaseTransactionId, |
||||
|
getBlockchainInfo: getBlockchainInfo, |
||||
|
getNetworkInfo: getNetworkInfo, |
||||
|
getNetTotals: getNetTotals, |
||||
|
getMempoolInfo: getMempoolInfo, |
||||
|
getBlockByHeight: getBlockByHeight, |
||||
|
getBlocksByHeight: getBlocksByHeight, |
||||
|
getBlockByHash: getBlockByHash, |
||||
|
getBlockByHashWithTransactions: getBlockByHashWithTransactions, |
||||
|
getRawTransaction: getRawTransaction, |
||||
|
getRawTransactions: getRawTransactions, |
||||
|
getMempoolStats: getMempoolStats, |
||||
|
getUptimeSeconds: getUptimeSeconds, |
||||
|
getHelp: getHelp, |
||||
|
getRpcMethodHelp: getRpcMethodHelp, |
||||
|
getAddress: getAddress |
||||
|
}; |
@ -0,0 +1,507 @@ |
|||||
|
var utils = require("../utils.js"); |
||||
|
var config = require("../config.js"); |
||||
|
var coins = require("../coins.js"); |
||||
|
|
||||
|
var SHA256 = require("crypto-js/sha256"); |
||||
|
var earliestBlockTime = 1231006505; |
||||
|
var avgBlockTime = 200000; |
||||
|
var currentBlockHeight = 1234567; |
||||
|
|
||||
|
|
||||
|
function getBlockchainInfo() { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
resolve({ |
||||
|
blocks: currentBlockHeight |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getNetworkInfo() { |
||||
|
return getRpcData("getnetworkinfo"); |
||||
|
} |
||||
|
|
||||
|
function getNetTotals() { |
||||
|
return getRpcData("getnettotals"); |
||||
|
} |
||||
|
|
||||
|
function getMempoolInfo() { |
||||
|
return getRpcData("getmempoolinfo"); |
||||
|
} |
||||
|
|
||||
|
function getUptimeSeconds() { |
||||
|
return getRpcData("uptime"); |
||||
|
} |
||||
|
|
||||
|
function getRawMempool() { |
||||
|
return getRpcDataWithParams("getrawmempool", true); |
||||
|
} |
||||
|
|
||||
|
function getBlockByHeight(blockHeight) { |
||||
|
var txCount = utils.seededRandomIntBetween(blockHeight, 1, 20); |
||||
|
var txids = []; |
||||
|
for (var i = 0; i < txCount; i++) { |
||||
|
txids.push(SHA256("" + blockHeight + "_" + i)); |
||||
|
} |
||||
|
|
||||
|
return new Promise(function(resolve, reject) { |
||||
|
resolve({ |
||||
|
"hash": SHA256("" + blockHeight), |
||||
|
"confirmations": currentBlockHeight - blockHeight, |
||||
|
"strippedsize": 56098, |
||||
|
"size": 65384, |
||||
|
"weight": 233678, |
||||
|
"height": blockHeight, |
||||
|
"version": 536870912, |
||||
|
"versionHex": "20000000", |
||||
|
"merkleroot": "567a3d773b07372179ad651edc02776f851020af69b7375a68ad89557dcbff5b", |
||||
|
"tx": txids, |
||||
|
"time": 1529848136, |
||||
|
"mediantime": 1529846560, |
||||
|
"nonce": 3615953854, |
||||
|
"bits": "17376f56", |
||||
|
"difficulty": "5077499034879.017", |
||||
|
"chainwork": SHA256("xyz" + blockHeight), |
||||
|
"previousblockhash": SHA256("" + (blockHeight - 1)), |
||||
|
"nextblockhash": SHA256("" + (blockHeight + 1)) |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlocksByHeight(blockHeights) { |
||||
|
console.log("mock.getBlocksByHeight: " + blockHeights); |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var blocks = []; |
||||
|
for (var i = 0; i < blockHeights.length; i++) { |
||||
|
getBlockByHeight(blockHeights[i]).then(function(result) { |
||||
|
blocks.push(result); |
||||
|
}); |
||||
|
/*blocks.push({ |
||||
|
"hash": "000000000000000000001542470d8261b9e5a2c3c2be2e2ab292d1a4c8250b12", |
||||
|
"confirmations": 3, |
||||
|
"strippedsize": 56098, |
||||
|
"size": 65384, |
||||
|
"weight": 233678, |
||||
|
"height": blockHeights[i], |
||||
|
"version": 536870912, |
||||
|
"versionHex": "20000000", |
||||
|
"merkleroot": "567a3d773b07372179ad651edc02776f851020af69b7375a68ad89557dcbff5b", |
||||
|
"tx": [ |
||||
|
"a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
"e999b2b8f1ee1e0b1adcc138d96d16e4fb65f2b422fc08d59a3b306b6a5c73d6", |
||||
|
"328ae013c7870ab29ffd93e1a1c01db6205229f261a91a04e73539c99861923f", |
||||
|
"b0604a447db9a0170a10a8d6cd2d68258783ae3061e5bfe5e26bcb6e76728c08", |
||||
|
], |
||||
|
"time": 1529848136, |
||||
|
"mediantime": 1529846560, |
||||
|
"nonce": 3615953854, |
||||
|
"bits": "17376f56", |
||||
|
"difficulty": "5077499034879.017", |
||||
|
"chainwork": "00000000000000000000000000000000000000000226420affb91a60111258b4", |
||||
|
"previousblockhash": "0000000000000000003147c5229962ca4e38714fc5aee8cf38670cf1a4ef297b", |
||||
|
"nextblockhash": "0000000000000000003382a0eef5b127c5d5ea270c85d9db3f3c605d32287cc5" |
||||
|
});*/ |
||||
|
} |
||||
|
|
||||
|
resolve(blocks); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlockByHash(blockHash) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
resolve({ |
||||
|
"hash": blockHash, |
||||
|
"confirmations": 3, |
||||
|
"strippedsize": 56098, |
||||
|
"size": 65384, |
||||
|
"weight": 233678, |
||||
|
"height": 123456, |
||||
|
"version": 536870912, |
||||
|
"versionHex": "20000000", |
||||
|
"merkleroot": "567a3d773b07372179ad651edc02776f851020af69b7375a68ad89557dcbff5b", |
||||
|
"tx": [ |
||||
|
"a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
"e999b2b8f1ee1e0b1adcc138d96d16e4fb65f2b422fc08d59a3b306b6a5c73d6", |
||||
|
"328ae013c7870ab29ffd93e1a1c01db6205229f261a91a04e73539c99861923f", |
||||
|
"b0604a447db9a0170a10a8d6cd2d68258783ae3061e5bfe5e26bcb6e76728c08", |
||||
|
], |
||||
|
"time": 1529848136, |
||||
|
"mediantime": 1529846560, |
||||
|
"nonce": 3615953854, |
||||
|
"bits": "17376f56", |
||||
|
"difficulty": "5077499034879.017", |
||||
|
"chainwork": "00000000000000000000000000000000000000000226420affb91a60111258b4", |
||||
|
"previousblockhash": "0000000000000000003147c5229962ca4e38714fc5aee8cf38670cf1a4ef297b", |
||||
|
"nextblockhash": "0000000000000000003382a0eef5b127c5d5ea270c85d9db3f3c605d32287cc5" |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getBlocksByHash(blockHashes) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var blocks = []; |
||||
|
for (var i = 0; i < blockHashes.length; i++) { |
||||
|
blocks.push({ |
||||
|
"hash": blockHashes[i], |
||||
|
"confirmations": 3, |
||||
|
"strippedsize": 56098, |
||||
|
"size": 65384, |
||||
|
"weight": 233678, |
||||
|
"height": 123456, |
||||
|
"version": 536870912, |
||||
|
"versionHex": "20000000", |
||||
|
"merkleroot": "567a3d773b07372179ad651edc02776f851020af69b7375a68ad89557dcbff5b", |
||||
|
"tx": [ |
||||
|
"a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
"e999b2b8f1ee1e0b1adcc138d96d16e4fb65f2b422fc08d59a3b306b6a5c73d6", |
||||
|
"328ae013c7870ab29ffd93e1a1c01db6205229f261a91a04e73539c99861923f", |
||||
|
"b0604a447db9a0170a10a8d6cd2d68258783ae3061e5bfe5e26bcb6e76728c08", |
||||
|
], |
||||
|
"time": 1529848136, |
||||
|
"mediantime": 1529846560, |
||||
|
"nonce": 3615953854, |
||||
|
"bits": "17376f56", |
||||
|
"difficulty": "5077499034879.017", |
||||
|
"chainwork": "00000000000000000000000000000000000000000226420affb91a60111258b4", |
||||
|
"previousblockhash": "0000000000000000003147c5229962ca4e38714fc5aee8cf38670cf1a4ef297b", |
||||
|
"nextblockhash": "0000000000000000003382a0eef5b127c5d5ea270c85d9db3f3c605d32287cc5" |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
resolve(blocks); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getRawTransaction(txid) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
resolve({ |
||||
|
"txid": txid, |
||||
|
"hash": txid, |
||||
|
"version": 1, |
||||
|
"size": 237, |
||||
|
"vsize": 210, |
||||
|
"locktime": 0, |
||||
|
"vin": [ |
||||
|
{ |
||||
|
"coinbase": "03851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f", |
||||
|
"sequence": 0 |
||||
|
} |
||||
|
], |
||||
|
"vout": [ |
||||
|
{ |
||||
|
"value": 12.51946416, |
||||
|
"n": 0, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_DUP OP_HASH160 7c154ed1dc59609e3d26abb2df2ea3d587cd8c41 OP_EQUALVERIFY OP_CHECKSIG", |
||||
|
"hex": "76a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac", |
||||
|
"reqSigs": 1, |
||||
|
"type": "pubkeyhash", |
||||
|
"addresses": [ |
||||
|
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE" |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"value": 0, |
||||
|
"n": 1, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_RETURN aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"hex": "6a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"type": "nulldata" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4503851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f0000000002b02f9f4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac0000000000000000266a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b9862810120000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
|
"blockhash": "000000000000000000001542470d8261b9e5a2c3c2be2e2ab292d1a4c8250b12", |
||||
|
"confirmations": 3, |
||||
|
"time": 1529848136, |
||||
|
"blocktime": 1529848136 |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getAddress(address) { |
||||
|
return getRpcDataWithParams("validateaddress", address); |
||||
|
} |
||||
|
|
||||
|
function getRawTransactions(txids) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
var txs = []; |
||||
|
for (var i = 0; i < txids.length; i++) { |
||||
|
txs.push({ |
||||
|
"txid": txid, |
||||
|
"hash": txid, |
||||
|
"version": 1, |
||||
|
"size": 237, |
||||
|
"vsize": 210, |
||||
|
"locktime": 0, |
||||
|
"vin": [ |
||||
|
{ |
||||
|
"coinbase": "03851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f", |
||||
|
"sequence": 0 |
||||
|
} |
||||
|
], |
||||
|
"vout": [ |
||||
|
{ |
||||
|
"value": 12.51946416, |
||||
|
"n": 0, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_DUP OP_HASH160 7c154ed1dc59609e3d26abb2df2ea3d587cd8c41 OP_EQUALVERIFY OP_CHECKSIG", |
||||
|
"hex": "76a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac", |
||||
|
"reqSigs": 1, |
||||
|
"type": "pubkeyhash", |
||||
|
"addresses": [ |
||||
|
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE" |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"value": 0, |
||||
|
"n": 1, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_RETURN aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"hex": "6a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"type": "nulldata" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4503851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f0000000002b02f9f4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac0000000000000000266a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b9862810120000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
|
"blockhash": "000000000000000000001542470d8261b9e5a2c3c2be2e2ab292d1a4c8250b12", |
||||
|
"confirmations": 3, |
||||
|
"time": 1529848136, |
||||
|
"blocktime": 1529848136 |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
resolve(txs); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getMinerFromCoinbaseTx(tx) { |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
function getBlockByHashWithTransactions(blockHash, txLimit, txOffset) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
resolve({ |
||||
|
getblock:{ |
||||
|
"hash": blockHash, |
||||
|
"confirmations": 3, |
||||
|
"strippedsize": 56098, |
||||
|
"size": 65384, |
||||
|
"weight": 233678, |
||||
|
"height": 123456, |
||||
|
"version": 536870912, |
||||
|
"versionHex": "20000000", |
||||
|
"merkleroot": "567a3d773b07372179ad651edc02776f851020af69b7375a68ad89557dcbff5b", |
||||
|
"tx": [ |
||||
|
"a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
], |
||||
|
"time": 1529848136, |
||||
|
"mediantime": 1529846560, |
||||
|
"nonce": 3615953854, |
||||
|
"bits": "17376f56", |
||||
|
"difficulty": "5077499034879.017", |
||||
|
"chainwork": "00000000000000000000000000000000000000000226420affb91a60111258b4", |
||||
|
"previousblockhash": "0000000000000000003147c5229962ca4e38714fc5aee8cf38670cf1a4ef297b", |
||||
|
"nextblockhash": "0000000000000000003382a0eef5b127c5d5ea270c85d9db3f3c605d32287cc5" |
||||
|
}, |
||||
|
transactions: [ |
||||
|
{ |
||||
|
"txid": "a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"hash": "a97a04ebcaaca0ec80a6b2f295171eb8b082b4bc5446cd085444c304dca6f014", |
||||
|
"version": 1, |
||||
|
"size": 237, |
||||
|
"vsize": 210, |
||||
|
"locktime": 0, |
||||
|
"vin": [ |
||||
|
{ |
||||
|
"coinbase": "03851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f", |
||||
|
"sequence": 0 |
||||
|
} |
||||
|
], |
||||
|
"vout": [ |
||||
|
{ |
||||
|
"value": 12.51946416, |
||||
|
"n": 0, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_DUP OP_HASH160 7c154ed1dc59609e3d26abb2df2ea3d587cd8c41 OP_EQUALVERIFY OP_CHECKSIG", |
||||
|
"hex": "76a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac", |
||||
|
"reqSigs": 1, |
||||
|
"type": "pubkeyhash", |
||||
|
"addresses": [ |
||||
|
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE" |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"value": 0, |
||||
|
"n": 1, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_RETURN aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"hex": "6a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"type": "nulldata" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4503851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f0000000002b02f9f4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac0000000000000000266a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b9862810120000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
|
"blockhash": "000000000000000000001542470d8261b9e5a2c3c2be2e2ab292d1a4c8250b12", |
||||
|
"confirmations": 3, |
||||
|
"time": 1529848136, |
||||
|
"blocktime": 1529848136 |
||||
|
}, |
||||
|
{ |
||||
|
"txid": "223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
"hash": "223fdd9cae01f3253adc0f0133cc8e6bebdb6f1481dfa0cd9cbfebff656f32f8", |
||||
|
"version": 1, |
||||
|
"size": 237, |
||||
|
"vsize": 210, |
||||
|
"locktime": 0, |
||||
|
"vin": [ |
||||
|
{ |
||||
|
"coinbase": "03851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f", |
||||
|
"sequence": 0 |
||||
|
} |
||||
|
], |
||||
|
"vout": [ |
||||
|
{ |
||||
|
"value": 12.51946416, |
||||
|
"n": 0, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_DUP OP_HASH160 7c154ed1dc59609e3d26abb2df2ea3d587cd8c41 OP_EQUALVERIFY OP_CHECKSIG", |
||||
|
"hex": "76a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac", |
||||
|
"reqSigs": 1, |
||||
|
"type": "pubkeyhash", |
||||
|
"addresses": [ |
||||
|
"1CK6KHY6MHgYvmRQ4PAafKYDrg1ejbH1cE" |
||||
|
] |
||||
|
} |
||||
|
}, |
||||
|
{ |
||||
|
"value": 0, |
||||
|
"n": 1, |
||||
|
"scriptPubKey": { |
||||
|
"asm": "OP_RETURN aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"hex": "6a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b986281", |
||||
|
"type": "nulldata" |
||||
|
} |
||||
|
} |
||||
|
], |
||||
|
"hex": "010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff4503851208fabe6d6d7bf60491521f081d77fa018fb41a167dd447bf20e7d2487426c3cee65332cdb50100000000000000266508019fcf7fcb7b01002ffd0c2f736c7573682f0000000002b02f9f4a000000001976a9147c154ed1dc59609e3d26abb2df2ea3d587cd8c4188ac0000000000000000266a24aa21a9ed2b367f88dbcc39b83e89703d5425a9b51fa3d2d921b8f39a42bc54492b9862810120000000000000000000000000000000000000000000000000000000000000000000000000", |
||||
|
"blockhash": "000000000000000000001542470d8261b9e5a2c3c2be2e2ab292d1a4c8250b12", |
||||
|
"confirmations": 3, |
||||
|
"time": 1529848136, |
||||
|
"blocktime": 1529848136 |
||||
|
} |
||||
|
], |
||||
|
txInputsByTransaction: {} |
||||
|
}); |
||||
|
/*client.command('getblock', blockHash, function(errGetblock, resultGetblock, resHeadersGetblock) { |
||||
|
if (errGetblock) { |
||||
|
console.log("Error 3017hfwe0f: " + errGetblock); |
||||
|
|
||||
|
reject(errGetblock); |
||||
|
|
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
var txids = []; |
||||
|
|
||||
|
// make sure we have the coinbase transaction since it can indicate
|
||||
|
// "block" info that we might want to display (miner)
|
||||
|
if (txOffset > 0) { |
||||
|
txids.push(resultGetblock.tx[0]); |
||||
|
} |
||||
|
|
||||
|
for (var i = txOffset; i < Math.min(txOffset + txLimit, resultGetblock.tx.length); i++) { |
||||
|
txids.push(resultGetblock.tx[i]); |
||||
|
} |
||||
|
|
||||
|
var maxInputsTracked = 10; |
||||
|
getRawTransactions(txids).then(function(transactions) { |
||||
|
var txInputsByTransaction = {}; |
||||
|
|
||||
|
// even if we're on "page 2" of transactions we pull the coinbase
|
||||
|
// tx first so that we can store it
|
||||
|
resultGetblock.coinbaseTx = transactions[0]; |
||||
|
resultGetblock.miner = getMinerFromCoinbaseTx(transactions[0]); |
||||
|
|
||||
|
// if we're on page 2, we don't really want it anymore...
|
||||
|
if (txOffset > 0) { |
||||
|
transactions.shift(); |
||||
|
} |
||||
|
|
||||
|
var vinTxids = []; |
||||
|
var promises = []; |
||||
|
for (var i = 0; i < transactions.length; i++) { |
||||
|
var transaction = transactions[i]; |
||||
|
|
||||
|
if (transaction) { |
||||
|
//console.log("xyz: " + JSON.stringify(transaction.vin));
|
||||
|
|
||||
|
for (var j = 0; j < Math.min(maxInputsTracked, transaction.vin.length); j++) { |
||||
|
if (transaction.vin[j].txid) { |
||||
|
vinTxids.push(transaction.vin[j].txid); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
getRawTransactions(vinTxids).then(function(vinTransactions) { |
||||
|
var vinTxById = {}; |
||||
|
|
||||
|
vinTransactions.forEach(function(tx) { |
||||
|
vinTxById[tx.txid] = tx; |
||||
|
}); |
||||
|
|
||||
|
transactions.forEach(function(tx) { |
||||
|
txInputsByTransaction[tx.txid] = []; |
||||
|
|
||||
|
for (var i = 0; i < Math.min(maxInputsTracked, tx.vin.length); i++) { |
||||
|
if (vinTxById[tx.vin[i].txid]) { |
||||
|
txInputsByTransaction[tx.txid].push(vinTxById[tx.vin[i].txid]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
resolve({ getblock:resultGetblock, transactions:transactions, txInputsByTransaction:txInputsByTransaction }); |
||||
|
}); |
||||
|
}); |
||||
|
}); |
||||
|
});*/ |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getHelp() { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
reject("Not implemented"); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
function getRpcMethodHelp(methodName) { |
||||
|
return new Promise(function(resolve, reject) { |
||||
|
reject("Not implemented"); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
module.exports = { |
||||
|
getBlockchainInfo: getBlockchainInfo, |
||||
|
getNetworkInfo: getNetworkInfo, |
||||
|
getNetTotals: getNetTotals, |
||||
|
getMempoolInfo: getMempoolInfo, |
||||
|
getBlockByHeight: getBlockByHeight, |
||||
|
getBlocksByHeight: getBlocksByHeight, |
||||
|
getBlockByHash: getBlockByHash, |
||||
|
getBlockByHashWithTransactions: getBlockByHashWithTransactions, |
||||
|
getRawTransaction: getRawTransaction, |
||||
|
getRawTransactions: getRawTransactions, |
||||
|
getRawMempool: getRawMempool, |
||||
|
getUptimeSeconds: getUptimeSeconds, |
||||
|
getHelp: getHelp, |
||||
|
getRpcMethodHelp: getRpcMethodHelp, |
||||
|
getAddress: getAddress |
||||
|
}; |
Loading…
Reference in new issue