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