extends layout block headContent title Mining Summary block content h1.h3 Mining Summary hr div.card.shadow-sm.mb-3 div.card-body h3.h6.mb-0 Block Range hr div.clearfix div.float-left.mr-4 div(id="time-range-buttons") h3.h6 Latest N Blocks 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.float-left.mr-4 div(id="block-selections-buttons") h3.h6 Preconfigured div.dropdown button.btn.btn-outline-primary.dropdown-toggle(type="button", id="preconfigured-dropdown", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false") Selections div.dropdown-menu(aria-labelledby="preconfigured-dropdown") a.dropdown-item(href="javascript:void(0)", data-blocks="0-199") First 200 Blocks a.dropdown-item(href="javascript:void(0)", data-blocks="209900-210100") First Halving ±100 a.dropdown-item(href="javascript:void(0)", data-blocks="419900-420100") Second Halving ±100 a.dropdown-item(href="javascript:void(0)", data-blocks="481724-481924") SegWit Activation ±100 div.float-left div(id="time-range-buttons") h3.h6 Custom Range form.form-inline.mr-3(id="custom-range-form") div.input-group input.form-control(type="text", id="custom-range-start", placeholder="min height", style="width: 125px;") input.form-control(type="text", id="custom-range-end", placeholder="max height", style="width: 125px;") div.input-group-append button.btn.btn-primary(type="submit") Go div#progress-wrapper div.card.shadow-sm.mb-3 div.card-body h4.h6 Loading blocks: span(id="block-progress-text") div.progress(id="progress-bar", style="height: 7px;") div.progress-bar(id="data-progress", role="progressbar", aria-valuenow="0", aria-valuemin="0" ,aria-valuemax="100") div.card.shadow-sm.mb-3(id="summary-table", style="display: none;") div.card-body div.table-responsive 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 //- 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"); $("#preconfigured-dropdown").removeClass("btn-primary").addClass("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); }); $("#block-selections-buttons .dropdown-item").on("click", function() { // highlight current selection $("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary"); $("#preconfigured-dropdown").removeClass("btn-outline-primary").addClass("btn-primary"); var blocks = $(this).attr("data-blocks"); var bStartEnd = blocks.split("-"); var bStart = parseInt(bStartEnd[0]); var bEnd = parseInt(bStartEnd[1]); $(".miner-summary-row").remove(); $("#data-progress").css("width", "0%"); $("#block-progress-text").text(""); $("#main-content").hide(); $("#progress-wrapper").show(); getData(bEnd, bEnd - bStart + 1, 15); }); $("#custom-range-form").on("submit", function() { // highlight current selection $("#time-range-buttons .block-count-btn").removeClass("btn-primary").addClass("btn-outline-primary"); $("#preconfigured-dropdown").removeClass("btn-primary").addClass("btn-outline-primary"); var bStart = parseInt($("#custom-range-start").val()); var bEnd = parseInt($("#custom-range-end").val()); $(".miner-summary-row").remove(); $("#data-progress").css("width", "0%"); $("#block-progress-text").text(""); $("#main-content").hide(); $("#progress-wrapper").show(); getData(bEnd, bEnd - bStart + 1, 15); return false; }); getData(currentBlockHeight, 144, 15); }); function getData(blockStart, count, chunkSize) { $("#time-range-buttons .block-count-btn").addClass("disabled"); $("#block-selections-buttons .dropdown-item").addClass("disabled"); var chunks = []; var blockIndex = blockStart; while (blockIndex > blockStart - count) { var chunk = []; for (var i = blockIndex; (i > (blockIndex - chunkSize) && i > (blockStart - count)); i--) { chunk.push(i); } blockIndex -= chunkSize; chunks.push(chunk); } console.log(JSON.stringify(chunks)); //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"); $("#block-selections-buttons .dropdown-item").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()); if (summary.overallSummary.totalFeesCollected > 0) { row.find(".miner-fees-percent").text(` (${new Decimal(minerSummary.totalFeesCollected).dividedBy(summary.overallSummary.totalFeesCollected).times(100).toDecimalPlaces(1)}%)`); } updateCurrencyValue(row.find(".miner-subsidy"), minerSummary.totalSubsidiesCollected); updateCurrencyValue(row.find(".miner-fees"), minerSummary.totalFeesCollected); 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(); }; 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}; }