Browse Source

/mining-summary tool

master
Dan Janosik 5 years ago
parent
commit
52d2aaee0f
No known key found for this signature in database GPG Key ID: C6F8CE9FFDB2CED2
  1. 5
      CHANGELOG.md
  2. 2
      app.js
  3. 4
      app/config.js
  4. 4877
      public/js/decimal.js
  5. 46
      routes/api.js
  6. 17
      routes/baseActionsRouter.js
  7. 280
      views/mining-summary.pug

5
CHANGELOG.md

@ -1,3 +1,8 @@
#### v1.2.0
##### 2020-02-23
* New tool `/mining-summary` for viewing summarized mining data from recent blocks
#### v1.1.9
##### 2020-02-23

2
app.js

@ -51,6 +51,7 @@ global.appVersion = package_json.version;
var crawlerBotUserAgentStrings = [ "Googlebot", "Bingbot", "Slurp", "DuckDuckBot", "Baiduspider", "YandexBot", "Sogou", "Exabot", "facebot", "ia_archiver" ];
var baseActionsRouter = require('./routes/baseActionsRouter');
var apiActionsRouter = require('./routes/api');
var app = express();
@ -428,6 +429,7 @@ app.use(csurf(), (req, res, next) => {
});
app.use('/', baseActionsRouter);
app.use('/api/', apiActionsRouter);
app.use(function(req, res, next) {
var time = Date.now() - req.startTime;

4
app/config.js

@ -177,7 +177,9 @@ module.exports = {
{name:"RPC Browser", url:"/rpc-browser", desc:"Browse the RPC functionality of this node. See docs and execute commands.", fontawesome:"fas fa-book"},
{name:"RPC Terminal", url:"/rpc-terminal", desc:"Directly execute RPCs against this node.", fontawesome:"fas fa-terminal"},
{name:(coins[currentCoin].name + " Fun"), url:"/fun", desc:"See fun/interesting historical blockchain data.", fontawesome:"fas fa-certificate"}
{name:(coins[currentCoin].name + " Fun"), url:"/fun", desc:"See fun/interesting historical blockchain data.", fontawesome:"fas fa-certificate"},
{name:"Mining Summary", url:"/mining-summary", desc:"Summary of recent data about miners.", fontawesome:"fas fa-chart-pie"},
],
donations:{

4877
public/js/decimal.js

File diff suppressed because it is too large

46
routes/api.js

@ -0,0 +1,46 @@
var debug = require("debug");
var debugLog = debug("btcexp:router");
var express = require('express');
var csurf = require('csurf');
var router = express.Router();
var util = require('util');
var moment = require('moment');
var bitcoinCore = require("bitcoin-core");
var qrcode = require('qrcode');
var bitcoinjs = require('bitcoinjs-lib');
var sha256 = require("crypto-js/sha256");
var hexEnc = require("crypto-js/enc-hex");
var Decimal = require("decimal.js");
var marked = require("marked");
var utils = require('./../app/utils.js');
var coins = require("./../app/coins.js");
var config = require("./../app/config.js");
var coreApi = require("./../app/api/coreApi.js");
var addressApi = require("./../app/api/addressApi.js");
const forceCsrf = csurf({ ignoreMethods: [] });
router.get("/blocks-by-height/:blockHeights", function(req, res, next) {
var blockHeightStrs = req.params.blockHeights.split(",");
var blockHeights = [];
for (var i = 0; i < blockHeightStrs.length; i++) {
blockHeights.push(parseInt(blockHeightStrs[i]));
}
coreApi.getBlocksByHeight(blockHeights).then(function(result) {
res.json(result);
next();
});
});
module.exports = router;

17
routes/baseActionsRouter.js

@ -338,6 +338,23 @@ router.get("/blocks", function(req, res, next) {
});
});
router.get("/mining-summary", function(req, res, next) {
coreApi.getBlockchainInfo().then(function(getblockchaininfo) {
res.locals.currentBlockHeight = getblockchaininfo.blocks;
res.render("mining-summary");
next();
}).catch(function(err) {
res.locals.userMessage = "Error: " + err;
res.render("mining-summary");
next();
});
});
router.get("/search", function(req, res, next) {
if (!req.body.query) {
req.session.userMessage = "Enter a block height, block hash, or transaction id.";

280
views/mining-summary.pug

@ -0,0 +1,280 @@
extends layout
block headContent
title Mining Summary
block content
h1.h3 Mining Summary
hr
div.mb-4(id="time-range-buttons")
h3.h5 Block Count
div.btn-group
a.btn.btn-primary.block-count-btn(href="javascript:void(0)", data-blockCount="144") 144
small.ml-2 (~1d)
a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="432") 432
small.ml-2 (~3d)
a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="1008") 1,008
small.ml-2 (~7d)
a.btn.btn-outline-primary.block-count-btn(href="javascript:void(0)", data-blockCount="4320") 4,320
small.ml-2 (~30d)
div#progress-wrapper
h4.h6 Loading blocks:
span(id="block-progress-text")
div.progress(id="progress-bar", style="height: 7px; margin-bottom: 200px;")
div.progress-bar(id="data-progress", role="progressbar", aria-valuenow="0", aria-valuemin="0" ,aria-valuemax="100")
div.table-responsive.mb-5(id="summary-table", style="display: none;")
table.table.table-striped.mb-0
thead
tr
th.data-header Miner
th.data-header.text-right Blocks
th.data-header.text-right Transactions
th.data-header.text-right Block Rewards
th.data-header.text-right Fees Collected
tbody(id="summary-table-body")
tr(id="miner-summary-prototype", style="display: none;")
td.data-cell.text-monospace.miner-name
td.data-cell.text-monospace.text-right
span.miner-block-count
small.text-muted.miner-block-percent.ml-2
td.data-cell.text-monospace.text-right
span.miner-tx-count
small.text-muted.miner-tx-percent.ml-2
td.data-cell.text-monospace.text-right
span.miner-subsidy
small.text-muted.miner-subsidy-percent.ml-2
//- var currencyValue = new Decimal(summary.totalSubsidiesCollected);
//include ./includes/value-display.pug
td.data-cell.text-monospace.text-right
span.miner-fees
small.text-muted.miner-fees-percent.ml-2
//- var currencyValue = new Decimal(summary.totalFeesCollected);
//include ./includes/value-display.pug
tr(id="miner-summary-totals", style="display: none;")
th.data-cell.text-monospace.miner-name Total
th.data-cell.text-monospace.text-right
span.miner-block-count
small.text-muted.miner-block-percent.ml-2 (100%)
th.data-cell.text-monospace.text-right
span.miner-tx-count
small.text-muted.miner-tx-percent.ml-2 (100%)
th.data-cell.text-monospace.text-right
span.miner-subsidy
//- var currencyValue = new Decimal(summary.totalSubsidiesCollected);
//include ./includes/value-display.pug
th.data-cell.text-monospace.text-right
span.miner-fees
//- var currencyValue = new Decimal(summary.totalFeesCollected);
//include ./includes/value-display.pug
if (false)
pre
code.json #{JSON.stringify(summariesByMiner, null, 4)}
block endOfBody
script(src='/js/decimal.js')
script.
var currentBlockHeight = !{currentBlockHeight};
$(document).ready(function() {
$("#time-range-buttons .block-count-btn").on("click", function() {
// highlight current selection
$("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary");
$(this).addClass("btn-primary").removeClass("btn-outline-primary");
var blockCount = parseInt($(this).attr("data-blockCount"));
$(".miner-summary-row").remove();
$("#data-progress").css("width", "0%");
$("#block-progress-text").text("");
$("#summary-table").hide();
$("#progress-wrapper").show();
getData(currentBlockHeight, blockCount, 15);
});
getData(currentBlockHeight, 144, 15);
});
function getData(blockStart, count, chunkSize) {
$("#time-range-buttons .block-count-btn").addClass("disabled");
var chunks = [];
var blockIndex = blockStart;
while (blockIndex > blockStart - count) {
var chunk = [];
for (var i = blockIndex; (i > (blockIndex - chunkSize) && i > (currentBlockHeight - count)); i--) {
chunk.push(i);
}
blockIndex -= chunkSize;
chunks.push(chunk);
}
//alert(JSON.stringify(chunks));
var results = [];
var statusCallback = function(chunkIndexDone, chunkCount) {
console.log("Done: " + Math.min(((chunkIndexDone + 1) * chunkSize), count) + " of " + count);
var wPercent = `${parseInt(100 * (chunkIndexDone + 1) / parseFloat(chunkCount))}%`;
$("#data-progress").css("width", wPercent);
$("#block-progress-text").text(`${Math.min(((chunkIndexDone + 1) * chunkSize), count).toLocaleString()} of ${count.toLocaleString()} (${wPercent})`);
};
var finishedCallback = function() {
$("#time-range-buttons .block-count-btn").removeClass("disabled");
console.log(JSON.stringify(results));
var summary = summarizeBlockData(results);
for (var i = 0; i < summary.minerNamesSortedByBlockCount.length; i++) {
var minerName = summary.minerNamesSortedByBlockCount[i];
var minerSummary = summary.summariesByMiner[minerName];
var row = $("#miner-summary-prototype").clone();
row.attr("id", null);
row.addClass("miner-summary-row");
row.find(".miner-name").text(minerName);
row.find(".miner-block-count").text(minerSummary.blockCount.toLocaleString());
row.find(".miner-block-percent").text(`(${new Decimal(minerSummary.blockCount).dividedBy(summary.overallSummary.blockCount).times(100).toDecimalPlaces(1)}%)`);
row.find(".miner-tx-count").text(minerSummary.transactionCount.toLocaleString());
row.find(".miner-tx-percent").text(`(${new Decimal(minerSummary.transactionCount).dividedBy(summary.overallSummary.transactionCount).times(100).toDecimalPlaces(1)}%)`);
row.find(".miner-subsidy").text(minerSummary.totalSubsidiesCollected.toLocaleString());
row.find(".miner-subsidy-percent").text(`(${new Decimal(minerSummary.totalSubsidiesCollected).dividedBy(summary.overallSummary.totalSubsidiesCollected).times(100).toDecimalPlaces(1)}%)`);
row.find(".miner-fees").text(minerSummary.totalFeesCollected.toLocaleString());
row.find(".miner-fees-percent").text(`(${new Decimal(minerSummary.totalFeesCollected).dividedBy(summary.overallSummary.totalFeesCollected).times(100).toDecimalPlaces(1)}%)`);
row.show();
$("#summary-table-body").append(row);
}
var totalsRow = $("#miner-summary-totals");
totalsRow.find(".miner-block-count").text(summary.overallSummary.blockCount.toLocaleString());
totalsRow.find(".miner-tx-count").text(summary.overallSummary.transactionCount.toLocaleString());
totalsRow.find(".miner-subsidy").text(summary.overallSummary.totalSubsidiesCollected.toLocaleString());
totalsRow.find(".miner-fees").text(summary.overallSummary.totalFeesCollected.toLocaleString());
var parent = totalsRow.parent();
parent.remove(totalsRow);
parent.append(totalsRow);
totalsRow.show();+
$("#summary-table").show();
$("#progress-wrapper").hide();
//$("#xyz").html(JSON.stringify(summary, null, 4));
};
getBlockData(results, chunks, 0, statusCallback, finishedCallback);
}
function getBlockData(results, chunks, chunkIndex, statusCallback, finishedCallback) {
if (chunkIndex > chunks.length - 1) {
finishedCallback();
return;
}
var url = `/api/blocks-by-height/${chunks[chunkIndex]}`;
//console.log(url);
$.ajax({
url: url
}).done(function(result) {
for (var i = 0; i < result.length; i++) {
results.push(result[i]);
}
statusCallback(chunkIndex, chunks.length);
getBlockData(results, chunks, chunkIndex + 1, statusCallback, finishedCallback);
});
}
function summarizeBlockData(blocks) {
var summariesByMiner = {};
var minerNamesSortedByBlockCount = [];
var overallSummary = {};
overallSummary.blockCount = 0;
overallSummary.transactionCount = 0;
overallSummary.totalSubsidiesCollected = new Decimal(0);
overallSummary.totalFeesCollected = new Decimal(0);
overallSummary.blockSizeTotal = 0;
for (var i = 0; i < blocks.length; i++) {
var block = blocks[i];
var miner = block.miner;
if (!miner) {
miner = {name:"Unknown"};
}
if (!summariesByMiner[miner.name]) {
minerNamesSortedByBlockCount.push(miner.name);
summariesByMiner[miner.name] = {};
summariesByMiner[miner.name].miner = miner;
summariesByMiner[miner.name].blockCount = 0;
summariesByMiner[miner.name].transactionCount = 0;
summariesByMiner[miner.name].totalSubsidiesCollected = new Decimal(0);
summariesByMiner[miner.name].totalFeesCollected = new Decimal(0);
summariesByMiner[miner.name].blockSizeTotal = 0;
if (blocks[0].weight) {
summariesByMiner[miner.name].blockWeightTotal = 0;
}
}
summariesByMiner[miner.name].blockCount++;
summariesByMiner[miner.name].transactionCount += block.tx.length;
summariesByMiner[miner.name].totalSubsidiesCollected = summariesByMiner[miner.name].totalSubsidiesCollected.add(new Decimal(block.subsidy));
summariesByMiner[miner.name].totalFeesCollected = summariesByMiner[miner.name].totalFeesCollected.add(new Decimal(block.totalFees));
summariesByMiner[miner.name].blockSizeTotal += block.size;
if (blocks[0].weight) {
summariesByMiner[miner.name].blockWeightTotal += block.weight;
}
overallSummary.blockCount++;
overallSummary.transactionCount += block.tx.length;
overallSummary.totalSubsidiesCollected = overallSummary.totalSubsidiesCollected.add(new Decimal(block.subsidy));
overallSummary.totalFeesCollected = overallSummary.totalFeesCollected.add(new Decimal(block.totalFees));
overallSummary.blockSizeTotal += block.size;
if (blocks[0].weight) {
overallSummary.blockWeightTotal += block.weight;
}
}
minerNamesSortedByBlockCount.sort(function(a, b) {
return ((summariesByMiner[a].blockCount > summariesByMiner[b].blockCount) ? -1 : 1);
});
return {summariesByMiner:summariesByMiner, minerNamesSortedByBlockCount:minerNamesSortedByBlockCount, overallSummary:overallSummary};
}
Loading…
Cancel
Save