Browse Source

- /block-analysis: new "top size tx" table and size distribution chart

- for huge tx: shrink input/output index numbers and don't include thousands separator
- move JSON displays into cards for UI consistency
- tons of frontend code consistency cleanup
- updated bootstrap with thinner column gutters (to avoid the col-lg-left/col-lg-right business I was hacking)
- remove npm links from demo homepage banner
master
Dan Janosik 5 years ago
parent
commit
645d1b5281
No known key found for this signature in database GPG Key ID: C6F8CE9FFDB2CED2
  1. 2
      app/coins/btc.js
  2. 2
      public/css/bootstrap-dark.min.css
  3. 2
      public/css/bootstrap.min.css
  4. 7
      public/css/styling.css
  5. 2
      routes/baseActionsRouter.js
  6. 106
      views/address.pug
  7. 126
      views/block-analysis.pug
  8. 4
      views/block-stats.pug
  9. 41
      views/blocks.pug
  10. 22
      views/connect.pug
  11. 22
      views/fun.pug
  12. 48
      views/includes/block-content.pug
  13. 8
      views/includes/blocks-list.pug
  14. 20
      views/includes/donation-modal.pug
  15. 2
      views/includes/electrum-trust-note.pug
  16. 6
      views/includes/index-network-summary.pug
  17. 2
      views/includes/line-graph.pug
  18. 22
      views/includes/pagination.pug
  19. 2
      views/includes/time-ago.pug
  20. 4
      views/includes/tools-card.pug
  21. 14
      views/includes/transaction-io-details.pug
  22. 43
      views/index.pug
  23. 6
      views/layout.pug
  24. 10
      views/mempool-summary.pug
  25. 2
      views/mining-summary.pug
  26. 52
      views/node-status.pug
  27. 117
      views/peers.pug
  28. 14
      views/search.pug
  29. 10
      views/terminal.pug
  30. 36
      views/transaction.pug
  31. 16
      views/tx-stats.pug
  32. 9
      views/unconfirmed-transactions.pug

2
app/coins/btc.js

@ -345,7 +345,7 @@ module.exports = {
chain: "main",
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
summary: "The first transfer of bitcoin.",
alertBodyHtml: "This transaction is the first instance of the transfer of bitcoin from one person to another. It also has the added distinction of being (one of?) the only known transfers of bitcoin from Satoshi Nakamoto, in this case sending bitcoin to Hal Finney as a test."
alertBodyHtml: "This transaction represents the first ever transfer of bitcoin from one person to another. It also has the added distinction of being (one of?) the only known transfers of bitcoin from Satoshi Nakamoto, in this case sending bitcoin to Hal Finney as a test."
},
{
type: "blockheight",

2
public/css/bootstrap-dark.min.css

File diff suppressed because one or more lines are too long

2
public/css/bootstrap.min.css

File diff suppressed because one or more lines are too long

7
public/css/styling.css

@ -54,13 +54,10 @@ code, .text-monospace {
margin-bottom: 3px;
}
.col-lg-left {
padding-right: 8px;
.mb-huge {
margin-bottom: 200px;
}
.col-lg-right {
padding-left: 8px;
}
.nav-tabs .nav-link.active {

2
routes/baseActionsRouter.js

@ -327,7 +327,7 @@ router.post("/connect", function(req, res, next) {
global.rpcClient = newClient;
req.session.userMessage = "<strong>Connected via RPC</strong>: " + username + " @ " + host + ":" + port;
req.session.userMessage = "<span class='font-weight-bold'>Connected via RPC</span>: " + username + " @ " + host + ":" + port;
req.session.userMessageType = "success";
res.redirect("/");

106
views/address.pug

@ -6,26 +6,27 @@ block headContent
block content
if (result && result.validateaddress)
if (!result.validateaddress.isvalid)
h1(class="h3 text-danger") Invalid Address
br
small(class="text-monospace") #{address}
div.alert.alert-danger.border-danger.mb-huge
h1.h6.font-weight-bold Invalid Address
span.text-monospace #{address}
else
h1.h3 Address
br
small(class="text-monospace") #{address}
small.text-monospace #{address}
hr
if (payoutAddressForMiner)
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;")
div(class="float-left", style="width: 50px; height: 50px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;")
div.alert.alert-primary.shadow-sm.pb-0
div.float-left(style="width: 50px; height: 50px; font-size: 18px;")
i.fas.fa-certificate.fa-2x(style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") #{coinConfig.name} Fun
h4.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun
p
span This looks like a miner payout address for
span(class="font-weight-bold") #{payoutAddressForMiner.name}
span.font-weight-bold #{payoutAddressForMiner.name}
if (coinConfig.miningPoolsConfigUrls.length > 1)
span (see the configurations:
each item, index in coinConfig.miningPoolsConfigUrls
@ -39,11 +40,11 @@ block content
span )
else if (global.specialAddresses[address] && global.specialAddresses[address].type == "fun")
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;")
div(class="float-left", style="width: 50px; height: 50px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;")
div.alert.alert-primary.shadow-sm.pb-0
div.float-left(style="width: 50px; height: 50px; font-size: 18px;")
i.fas.fa-certificate.fa-2x(style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") #{coinConfig.name} Fun
h4.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun
// special address info
- var saInfo = global.specialAddresses[address].addressInfo;
@ -76,14 +77,14 @@ block content
div.tab-content
div(id="tab-details", class="tab-pane active", role="tabpanel")
div.tab-pane.active(id="tab-details", role="tabpanel")
if (false && config.electrumXServers && config.electrumXServers.length > 0)
if (session.hideElectrumTrustWarnings != "true")
div(class="alert alert-primary alert-dismissible clearfix shadow-sm", role="alert")
div.alert.alert-primary.alert-dismissible.clearfix.shadow-sm(role="alert")
span this explorer is database-free, it doesn't natively support address balances and transaction histories. In order to provide this functionality, address balances and transaction history can be requested from a configurable set of ElectrumX servers. If multiple ElectrumX servers are configured, the results are cross-referenced and conflicts noted. For the transaction history displayed below, only the transaction identifiers from ElectrumX are used; the transaction details are requested via RPC from this app's primary node, as usual.
a(href="/changeSetting?name=hideElectrumTrustWarnings&value=true", class="close", aria-label="Close", style="text-decoration: none;")
a.close(href="/changeSetting?name=hideElectrumTrustWarnings&value=true", aria-label="Close", style="text-decoration: none;")
span(aria-hidden="true") &times;
div.card.shadow-sm.mb-3
@ -145,7 +146,7 @@ block content
div.row
div.summary-split-table-label Balance
div.summary-split-table-content.text-monospace
span(class="text-warning") Conflicted ElectrumX Results
span.text-warning Conflicted ElectrumX Results
each item in balance.conflictedResults
- var currencyValue = item.confirmed / coinConfig.baseCurrencyUnit.multiplier;
@ -198,17 +199,17 @@ block content
div.summary-split-table-label #{flagName}
div.summary-split-table-content.text-monospace
if (flags[index])
i(class="fas fa-check text-success")
i.fas.fa-check.text-success
else
i(class="fas fa-times text-warning")
i.fas.fa-times.text-warning
if (false)
div(class="card mb-3 shadow-sm")
div.card.shadow-sm.mb-3
div.card-header
span(class="h6") Flags
span.h6 Flags
div.card-body
div(class="table-responsive")
table(class="table text-center")
div.table-responsive
table.table.text-center
thead
tr
th Is Valid?
@ -224,9 +225,9 @@ block content
each flag in flags
td
if (flag)
i(class="fas fa-check text-success")
i.fas.fa-check.text-success
else
i(class="fas fa-times text-warning")
i.fas.fa-times.text-warning
div.card.shadow-sm.mb-3
div.card-body
@ -248,21 +249,21 @@ block content
small.text-muted.border-dotted.ml-2(title=`The list of transaction IDs for this address was queried from ${config.addressApi}` data-toggle="tooltip") Trust Note
if (!crawlerBot && txids && txids.length > 1 && addressApiSupport.sortDesc && addressApiSupport.sortAsc)
div(class="float-right")
a(href="#", class="pull-right dropdown-toggle", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
div.float-right
a.pull-right.dropdown-toggle(href="#", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
if (sort == "desc")
span Newest First
else
span Oldest First
div(class="dropdown-menu dropdown-menu-right")
a(href=("/address/" + address), class="dropdown-item")
div.dropdown-menu.dropdown-menu-right
a.dropdown-item(href=("/address/" + address))
if (sort == "desc")
i(class="fa fa-check")
i.fa.fa-check
span Newest First
a(href=("/address/" + address + "?sort=asc"), class="dropdown-item")
a.dropdown-item(href=("/address/" + address + "?sort=asc"))
if (sort != "desc")
i(class="fa fa-check")
i.fa.fa-check
span Oldest First
else if (txids && txids.length > 1 && addressApiSupport.sortDesc && !addressApiSupport.sortAsc)
@ -272,13 +273,13 @@ block content
hr
if (conflictedTxidResults)
div(class="alert alert-warning", style="padding-bottom: 0;")
div(class="float-left", style="width: 55px; height: 50px; font-size: 18px;")
i(class="fas fa-exclamation-triangle fa-2x", style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") Trust Warning
div.alert.alert-warning.pb-0
div.float-left(style="width: 55px; height: 50px; font-size: 18px;")
i.fas.fa-exclamation-triangle.fa-2x(style="margin-top: 10px;")
h4.alert-heading.h6.font-weight-bold Trust Warning
p
span The transaction history for this address was requested from mulitple ElectrumX servers and the results did not match. The results below were obtained only from
span(class="font-weight-bold") #{electrumHistory.server}
span.font-weight-bold #{electrumHistory.server}
if (true)
@ -332,7 +333,7 @@ block content
if (addrGainsByTx[tx.txid])
- var currencyValue = addrGainsByTx[tx.txid];
span(class="text-success") +
span.text-success +
include includes/value-display.pug
if (addrLossesByTx[tx.txid])
@ -340,7 +341,7 @@ block content
if (addrLossesByTx[tx.txid])
- var currencyValue = addrLossesByTx[tx.txid];
span(class="text-danger") -
span.text-danger -
include includes/value-display.pug
div.col-md-4
@ -393,15 +394,24 @@ block content
div(id="tab-json", class="tab-pane", role="tabpanel")
div.highlight
h4 validateaddress
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(result.validateaddress, null, 4)}
div.tab-pane(id="tab-json", role="tabpanel")
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 validateaddress
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(result.validateaddress, null, 4)}
if (addressDetails)
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 addressDetails
hr
if (addressDetails)
h4 addressDetails
pre
code.json.bg-light #{JSON.stringify(addressDetails, null, 4)}
div.highlight
pre
code.json.bg-light #{JSON.stringify(addressDetails, null, 4)}

126
views/block-analysis.pug

@ -63,13 +63,13 @@ block content
if (result.getblock.confirmations < 6)
span.font-weight-bold.text-warning #{result.getblock.confirmations.toLocaleString()}
a(data-toggle="tooltip", title="Fewer than 6 confirmations is generally considered 'unsettled' for high-value transactions. The applicability of this guidance may vary.")
i(class="fas fa-unlock-alt")
i.fas.fa-unlock-alt
else
span.font-weight-bold.text-success #{result.getblock.confirmations.toLocaleString()}
a(data-toggle="tooltip", title="6 confirmations is generally considered 'settled'. High-value transactions may require more; low-value transactions may require less.")
i.fas.fa-lock
div#progress-wrapper
div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3
div.card-body
h4.h6 Loading transactions:
@ -80,7 +80,7 @@ block content
div#main-content(style="display: none;")
div.row
div.col-lg-6.col-lg-left
div.col-xl-4
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Value Transactions
@ -90,19 +90,15 @@ block content
table.table.table-striped.mb-0
thead
tr
th
th.data-header Transaction
th.data-header.text-right Output Value
tbody(id="tbody-top-value-tx")
tr.text-monospace.row-prototype(style="display: none;")
td
small.text-muted.data-index
td.data-tx-link
td.text-right.data-tx-value
div.col-lg-6.col-lg-right
div.col-xl-4
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Fee Transactions
@ -112,19 +108,33 @@ block content
table.table.table-striped.mb-0
thead
tr
th
th.data-header Transaction
th.data-header.text-right Fee
tbody(id="tbody-top-fee-tx")
tr.text-monospace.row-prototype(style="display: none;")
td
small.text-muted.data-index
td.data-tx-link
td.text-right.data-tx-value
div.col-xl-4
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Size Transactions
hr
div.table-responsive
table.table.table-striped.mb-0
thead
tr
th.data-header Transaction
th.data-header.text-right Size
tbody(id="tbody-top-size-tx")
tr.text-monospace.row-prototype(style="display: none;")
td.data-tx-link
td.text-right.data-tx-value
div.col-lg-6.col-lg-left.mb-3
div.col-lg-6.mb-3
div.card.shadow-sm(style="height: 100%;")
div.card-body
h3.h6.mb-0 Input Types
@ -138,7 +148,7 @@ block content
td.data-count
div.col-lg-6.col-lg-right.mb-3
div.col-lg-6.mb-3
div.card.shadow-sm(style="height: 100%;")
div.card-body
h3.h6.mb-0 Output Types
@ -153,7 +163,7 @@ block content
td.data-count
div.row
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Value
@ -161,7 +171,7 @@ block content
canvas(id="graph-tx-value")
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Value Distribution
@ -169,7 +179,7 @@ block content
canvas(id="chart-tx-value-distribution")
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Fee
@ -177,7 +187,7 @@ block content
canvas(id="graph-tx-fee")
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Fee Distribution
@ -185,29 +195,37 @@ block content
canvas(id="chart-tx-fee-distribution")
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Input Count
h3.h6.mb-0 Transaction Size
hr
canvas(id="graph-tx-inputs")
canvas(id="graph-tx-size")
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Output Count
h3.h6.mb-0 Transaction Size Distribution
hr
canvas(id="graph-tx-outputs")
canvas(id="chart-tx-size-distribution")
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Size
h3.h6.mb-0 Transaction Input Count
hr
canvas(id="graph-tx-size")
canvas(id="graph-tx-inputs")
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction Output Count
hr
canvas(id="graph-tx-outputs")
@ -221,6 +239,7 @@ block endOfBody
var txidChunks = !{JSON.stringify(utils.splitArrayIntoChunks(result.getblock.tx, txidChunkSize))};
var blockHeight = !{result.getblock.height};
var satsMultiplier = !{coinConfig.baseCurrencyUnit.multiplier};
var vByteSizes = false;
$(document).ready(function() {
loadTransactions(txidChunks, txidChunkSize, txidChunks.length * txidChunkSize);
@ -263,6 +282,8 @@ block endOfBody
fillTopValueTxTable(summary);
fillTopFeeTxTable(summary);
fillTopSizeTxTable(summary);
fillInputOutputTypesTable(summary);
createGraph("graph-tx-value", summary.txValueGraphData, "Value");
@ -273,6 +294,7 @@ block endOfBody
createChart("chart-tx-value-distribution", summary.valueDistribution, summary.valueDistributionLabels);
createChart("chart-tx-fee-distribution", summary.feeDistribution, summary.feeDistributionLabels);
createChart("chart-tx-size-distribution", summary.sizeDistribution, summary.sizeDistributionLabels);
//$(".abc").text(JSON.stringify(summary));
@ -293,8 +315,7 @@ block endOfBody
row.removeClass("row-prototype");
row.find(".data-index").text((i + 1).toLocaleString());
row.find(".data-tx-link").html(`<a href='/tx/${item.txid}'>${item.txid}</a>`);
row.find(".data-tx-link").html(`<a href='/tx/${item.txid}'>${item.txid.substring(0, 14)}<span class='d-inline d-xl-none'>${item.txid.substring(14, 32)}</span><span class='d-none d-xxl-inline'>${item.txid.substring(14, 30)}</span>…</a>`);
row.find(".data-tx-value").text(item.value);
updateCurrencyValue(row.find(".data-tx-value"), item.value);
@ -315,8 +336,7 @@ block endOfBody
row.removeClass("row-prototype");
row.find(".data-index").text((i + 1).toLocaleString());
row.find(".data-tx-link").html(`<a href='/tx/${item.txid}'>${item.txid}</a>`);
row.find(".data-tx-link").html(`<a href='/tx/${item.txid}'>${item.txid.substring(0, 14)}<span class='d-inline d-xl-none'>${item.txid.substring(14, 32)}</span><span class='d-none d-xxl-inline'>${item.txid.substring(14, 30)}</span>…</a>`);
row.find(".data-tx-value").text(item.value);
updateCurrencyValue(row.find(".data-tx-value"), item.value);
@ -327,6 +347,25 @@ block endOfBody
}
}
function fillTopSizeTxTable(data) {
var count = Math.min(10, data.topSizeTxs.length);
for (var i = 0; i < count; i++) {
var item = data.topSizeTxs[i];
var row = $("#tbody-top-size-tx .row-prototype").clone();
row.removeClass("row-prototype");
row.find(".data-tx-link").html(`<a href='/tx/${item.txid}'>${item.txid.substring(0, 14)}<span class='d-inline d-xl-none'>${item.txid.substring(14, 32)}</span><span class='d-none d-xxl-inline'>${item.txid.substring(14, 30)}</span>…</a>`);
row.find(".data-tx-value").html(`<span>${parseInt(item.value).toLocaleString()} <small>${vByteSizes ? "v" : ""}B</small></span>`);
row.show();
$("#tbody-top-size-tx").append(row);
}
}
function fillInputOutputTypesTable(data) {
var sortedInputs = [];
for (var key in data.inputTypeCounts) {
@ -497,6 +536,8 @@ block endOfBody
analysis.txFees = [];
analysis.txFeeGraphData = [];
analysis.txSizes = [];
analysis.txSizeGraphData = [];
analysis.txInputCountGraphData = [];
analysis.txOutputCountGraphData = [];
@ -517,12 +558,17 @@ block endOfBody
analysis.outputTypeCounts[outputType]++;
}
if (txSummary.vsize) {
vByteSizes = true;
}
analysis.txValues.push({txid:txSummary.txid, value:new Decimal(txSummary.totalOutput)});
analysis.txValueGraphData.push({x:i, y:new Decimal(txSummary.totalOutput).toNumber()});
analysis.txFees.push({txid:txSummary.txid, value:new Decimal(txSummary.totalFee)});
analysis.txFeeGraphData.push({x:i, y:new Decimal(txSummary.totalFee).toNumber()});
analysis.txSizes.push({txid:txSummary.txid, value:new Decimal(txSummary.vsize ? txSummary.vsize : txSummary.size)});
analysis.txSizeGraphData.push({x:i, y:(txSummary.vsize ? txSummary.vsize : txSummary.size)});
analysis.txInputCountGraphData.push({x:i, y:txSummary.vin.length});
@ -551,11 +597,17 @@ block endOfBody
return b.value.cmp(a.value);
});
analysis.txSizes.sort(function(a, b) {
return b.value.cmp(a.value);
});
analysis.topValueTxs = analysis.txValues.slice(0, Math.min(100, analysis.txValues.length));
analysis.topFeeTxs = analysis.txFees.slice(0, Math.min(100, analysis.txFees.length));
analysis.topSizeTxs = analysis.txSizes.slice(0, Math.min(100, analysis.txSizes.length));
var topValue = new Decimal(analysis.txValues[parseInt(analysis.txValues.length * 0.1)].value).times(satsMultiplier);
var topFee = new Decimal(analysis.txFees[parseInt(analysis.txFees.length * 0.1)].value).times(satsMultiplier);
var topSize = new Decimal(analysis.txSizes[parseInt(analysis.txSizes.length * 0.1)].value);
var topValueSats = parseInt(topValue);
var topFeeSats = parseInt(topFee);
@ -568,22 +620,30 @@ block endOfBody
analysis.feeDistribution = [];
analysis.feeDistributionLabels = [];
analysis.sizeDistribution = [];
analysis.sizeDistributionLabels = [];
for (var i = 0; i < distributionBucketCount; i++) {
analysis.valueDistribution.push(0);
analysis.valueDistributionLabels.push(`[${new Decimal(i * topValueSats / distributionBucketCount).dividedBy(satsMultiplier).toDP(3)} - ${new Decimal((i + 1) * topValueSats / distributionBucketCount).dividedBy(satsMultiplier).toDP(3)})`);
analysis.feeDistribution.push(0);
analysis.feeDistributionLabels.push(`[${new Decimal(i * topFeeSats / distributionBucketCount).toDP(0)} - ${new Decimal((i + 1) * topFeeSats / distributionBucketCount).toDP(0)})`);
analysis.sizeDistribution.push(0);
analysis.sizeDistributionLabels.push(`[${new Decimal(i * topSize / distributionBucketCount).toDP(0)} - ${new Decimal((i + 1) * topSize / distributionBucketCount).toDP(0)})`);
}
analysis.valueDistributionLabels[distributionBucketCount - 1] = `${new Decimal(topValueSats).dividedBy(satsMultiplier).toDP(3)}+`;
analysis.feeDistributionLabels[distributionBucketCount - 1] = `${topFeeSats}+`;
analysis.sizeDistributionLabels[distributionBucketCount - 1] = `${topSize}+`;
for (var i = 0; i < txResults.length; i++) {
var txSummary = txResults[i];
var valueSats = new Decimal(txSummary.totalOutput).times(satsMultiplier);
var feeSats = new Decimal(txSummary.totalFee).times(satsMultiplier);
var size = new Decimal(txSummary.vsize ? txSummary.vsize : txSummary.size);
var valueBucket = parseInt(distributionBucketCount * valueSats / topValueSats);
if (valueBucket >= distributionBucketCount) {
@ -595,8 +655,14 @@ block endOfBody
feeBucket = distributionBucketCount - 1;
}
var sizeBucket = parseInt(distributionBucketCount * size / topSize);
if (sizeBucket >= distributionBucketCount) {
sizeBucket = distributionBucketCount - 1;
}
analysis.valueDistribution[valueBucket]++;
analysis.feeDistribution[feeBucket]++;
analysis.sizeDistribution[sizeBucket]++;
}
return analysis;

4
views/block-stats.pug

@ -59,7 +59,7 @@ block content
div.input-group-append
button.btn.btn-primary(type="submit") Go
div#progress-wrapper
div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3
div.card-body
h4.h6 Loading blocks:
@ -88,7 +88,7 @@ block content
div.row.clearfix
each graphId, graphIndex in graphIds
div.col-lg-6.float-left(class=(graphIndex % 2 == 0 ? "col-lg-left" : "col-lg-right"))
div.col-lg-6.float-left
div.card.shadow-sm.mb-3.graph-wrapper(id=`graph-wrapper-${graphId}`)
div.card-body
h3.h6.mb-0 #{graphTitles[graphIndex]}

41
views/blocks.pug

@ -9,30 +9,31 @@ block content
if (blocks)
nav(aria-label="Page navigation")
ul(class="pagination justify-content-center")
ul.pagination.justify-content-center
li(class="page-item", class=(sort == "desc" ? "active" : false))
a(class="page-link", href=(sort == "desc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=desc"))
li.page-item(class=(sort == "desc" ? "active" : false))
a.page-link(href=(sort == "desc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=desc"))
span(aria-hidden="true") Newest blocks first
li(class="page-item", class=(sort == "asc" ? "active" : false))
a(class="page-link", href=(sort == "asc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=asc"))
li.page-item(class=(sort == "asc" ? "active" : false))
a.page-link(href=(sort == "asc" ? "javascript:void(0)" : "/blocks?limit=" + limit + "&offset=0" + "&sort=asc"))
span(aria-hidden="true") Oldest blocks first
include includes/blocks-list.pug
if (blockCount > limit)
- var pageNumber = offset / limit + 1;
- var pageCount = Math.floor(blockCount / limit);
- if (pageCount * limit < blockCount) {
- pageCount++;
- }
- var paginationUrlFunction = function(x) {
- return paginationBaseUrl + "?limit=" + limit + "&offset=" + ((x - 1) * limit + "&sort=" + sort);
- }
hr
include includes/pagination.pug
div.card.shadow-sm.mb-3
div.card-body
include includes/blocks-list.pug
if (blockCount > limit)
- var pageNumber = offset / limit + 1;
- var pageCount = Math.floor(blockCount / limit);
- if (pageCount * limit < blockCount) {
- pageCount++;
- }
- var paginationUrlFunction = function(x) {
- return paginationBaseUrl + "?limit=" + limit + "&offset=" + ((x - 1) * limit + "&sort=" + sort);
- }
div.pt-5
include includes/pagination.pug
else
p No blocks found

22
views/connect.pug

@ -1,28 +1,28 @@
extends layout
block content
h1(class="h2") RPC Connect
h1.h3 RPC Connect
hr
form(method="post", action="/connect")
input(type="hidden", name="_csrf", value=csrfToken)
div(class="form-group")
div.form-group
label(for="input-host") Host / IP
input(id="input-host", type="text", name="host", class="form-control", placeholder="Host / IP", value=host)
input.form-control(id="input-host", type="text", name="host", placeholder="Host / IP", value=host)
div(class="form-group")
div.form-group
label(for="input-port") Port
input(id="input-port", type="text", name="port", class="form-control", placeholder="Port", value=port)
input.form-control(id="input-port", type="text", name="port", placeholder="Port", value=port)
div(class="form-group")
div.form-group
label(for="input-username") Username
input(id="input-username", type="text", name="username", class="form-control", placeholder="Username", value=username)
input.form-control(id="input-username", type="text", name="username", placeholder="Username", value=username)
div(class="form-group")
div.form-group
label(for="input-password") Password
input(id="input-password", type="password", name="password", class="form-control", placeholder="Password")
input.form-control(id="input-password", type="password", name="password", placeholder="Password")
div(class="form-group")
input(type="submit", class="btn btn-primary btn-block" value="Connect")
div.form-group
input.btn.btn-primary.btn-block(type="submit" value="Connect")

22
views/fun.pug

@ -11,23 +11,23 @@ block content
div.card-body
p Below is a list of fun/interesting things in the #{coinConfig.name} blockchain. Some are historical firsts, others are just fun or cool.
div(class="table-responsive")
table(class="table table-striped mt-4")
div.table-responsive
table.table.table-striped
thead
tr
th(class="data-header") Date
th(class="data-header") Description
th(class="data-header") Link
th(class="data-header") Reference
th.data-header Date
th.data-header Description
th.data-header Link
th.data-header Reference
tbody
each item, index in coinConfig.historicalData
if (item.chain == global.activeBlockchain)
tr
td(class="data-cell") #{item.date}
td.data-cell #{item.date}
td(class="data-cell") #{item.summary}
td.data-cell #{item.summary}
td(class="data-cell text-monospace")
td.data-cell.text-monospace
if (item.type == "tx")
a(href=("/tx/" + item.txid), title=item.txid, data-toggle="tooltip") Tx #{item.txid.substring(0, 23)}...
else if (item.type == "block")
@ -39,7 +39,7 @@ block content
else if (item.type == "link")
a(href=item.url) #{item.url.substring(0, 20)}...
td(class="data-cell")
td.data-cell
if (item.referenceUrl && item.referenceUrl.trim().length > 0)
- var matches = item.referenceUrl.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i);
@ -48,7 +48,7 @@ block content
if (domain)
a(href=item.referenceUrl, rel="nofollow") #{domain}
i(class="fas fa-external-link-alt")
i.fas.fa-external-link-alt
else
a(href=item.referenceUrl, rel="nofollow") Reference
else

48
views/includes/block-content.pug

@ -27,10 +27,10 @@ ul.nav.nav-tabs.mb-3
div.tab-content
div.tab-pane.active(id="tab-details", role="tabpanel")
if (global.specialBlocks && global.specialBlocks[result.getblock.hash])
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;")
div(class="float-left", style="width: 55px; height: 55px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") #{coinConfig.name} Fun
div.alert.alert-primary.shadow-sm.pb-0
div.float-left(style="width: 55px; height: 55px; font-size: 18px;")
i.fas.fa-certificate.fa-2x(style="margin-top: 10px;")
h4.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun
// special transaction info
- var sbInfo = global.specialBlocks[result.getblock.hash];
@ -172,11 +172,11 @@ div.tab-content
div(class=sumTableLabelClass) Confirmations
div.text-monospace(class=sumTableValueClass)
if (result.getblock.confirmations < 6)
span(class="font-weight-bold text-warning") #{result.getblock.confirmations.toLocaleString()}
span.font-weight-bold.text-warning #{result.getblock.confirmations.toLocaleString()}
a(data-toggle="tooltip", title="Fewer than 6 confirmations is generally considered 'unsettled' for high-value transactions. The applicability of this guidance may vary.")
i(class="fas fa-unlock-alt")
i.fas.fa-unlock-alt
else
span(class="font-weight-bold text-success font-weight-bold") #{result.getblock.confirmations.toLocaleString()}
span.font-weight-bold.text-success #{result.getblock.confirmations.toLocaleString()}
a(data-toggle="tooltip", title="6 confirmations is generally considered 'settled'. High-value transactions may require more; low-value transactions may require less.")
i.fas.fa-lock
@ -367,7 +367,7 @@ div.tab-content
a.ml-2(href=`/block-analysis/${result.getblock.hash}`) See Transaction Analysis &raquo;
if (false || (!config.demoSite && !crawlerBot && txCount > 20))
div(class="col-md-8 text-right")
div.col-md-8.text-right
small.mr-1.text-muted Show
div.btn-group(role="group")
a.btn.btn-sm.btn-primary.px-2.py-0(href=(paginationBaseUrl + "?limit=20"), class=((limit == 20 && txCount > limit) ? "active" : false)) 20
@ -427,7 +427,7 @@ div.tab-content
include ./pagination.pug
div(id="tab-json", class="tab-pane", role="tabpanel")
div.tab-pane(id="tab-json", role="tabpanel")
- var blockDetails = JSON.parse(JSON.stringify(result.getblock));
- blockDetails.tx = "See 'Transaction IDs'";
@ -443,15 +443,33 @@ div.tab-content
div.tab-content
div.tab-pane.active(id="tab-json-block-summary", role="tabpanel")
pre
code.json.bg-light #{JSON.stringify(blockDetails, null, 4)}
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 Block Summary
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(blockDetails, null, 4)}
div.tab-pane(id="tab-json-tx-ids", role="tabpanel")
pre
code.json.bg-light #{JSON.stringify(result.getblock.tx, null, 4)}
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 Transaction IDs
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(result.getblock.tx, null, 4)}
if (result.blockstats)
div.tab-pane(id="tab-json-blockstats", role="tabpanel")
pre
code.json.bg-light #{JSON.stringify(result.blockstats, null, 4)}
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 Block Stats
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(result.blockstats, null, 4)}

8
views/includes/blocks-list.pug

@ -170,8 +170,8 @@ div.table-responsive
span.ml-1(data-toggle="tooltip", title=`Size: ${bSizeK.toLocaleString()} kB`)
i.fas.fa-ellipsis-h.text-muted
div(class="progress", style="height: 4px;")
div(class="progress-bar", role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.weight / coinConfig.maxBlockWeight), aria-valuemin="0" ,aria-valuemax="100")
div.progress(style="height: 4px;")
div.progress-bar(role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.weight / coinConfig.maxBlockWeight), aria-valuemin="0" ,aria-valuemax="100")
else
td.data-cell.text-monospace.text-right
@ -181,7 +181,7 @@ div.table-responsive
span #{bSizeK.toLocaleString()}
small.font-weight-light.text-muted (#{fullPercent}%)
div(class="progress", style="height: 4px;")
div(class="progress-bar", role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.size / coinConfig.maxBlockSize), aria-valuemin="0" ,aria-valuemax="100")
div.progress(style="height: 4px;")
div.progress-bar(role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.size / coinConfig.maxBlockSize), aria-valuemin="0" ,aria-valuemax="100")
- var lastBlock = block;

20
views/includes/donation-modal.pug

@ -17,10 +17,10 @@
if (false)
h6
span(class="mr-2") Donate (via BTCPay)
span.mr-2 Donate (via BTCPay)
- var amounts = [1, 5, 10, 25, 100];
- var icons = [ "thumbs-up", "beer", "hamburger", "utensils", "grin-hearts" ];
div(class="mb-2")
div.mb-2
each amount, amtIndex in amounts
form(method="POST" action=(config.donations.btcpayserver.host + "/api/v1/invoices"), style="display: inline;")
input(type='hidden' name='storeId' value=config.donations.btcpayserver.storeId)
@ -28,7 +28,7 @@
input(type='hidden' name='currency' value='USD')
input(type='hidden' name='notifyEmail' value=config.donations.btcpayserver.notifyEmail)
button.btn.btn-primary.btn-lg(type='submit', class="mr-2 mb-2")
button.btn.btn-primary.btn-lg.mr-2.mb-2(type='submit')
i(class=("fas mr-2 fa-" + icons[amtIndex]))
span $#{amount.toLocaleString()}
@ -38,8 +38,8 @@
input(type='hidden' name='currency' value='BTC')
input(type='hidden' name='notifyEmail' value=config.donations.btcpayserver.notifyEmail)
button.btn.btn-primary.btn-lg(type='submit', class="mr-2 mb-2")
i(class="fas mr-2 fa-bolt")
button.btn.btn-primary.btn-lg.mr-2.mb-2(type='submit')
i.fas.mr-2.fa-bolt
span 1 satoshi
script.
@ -50,20 +50,20 @@
}
if (false)
div(id="donate-by-address", class="mt-4")
div.mt-4(id="donate-by-address")
h6 Donate by address
div(class="mb-3")
div.mb-3
each coin, index in config.donations.addresses.coins
div(class="text-monospace")
div.text-monospace
if (coinConfig.ticker == coin)
span #{config.donations.addresses[coin].address}
else
span #{coin}:
a(href=(config.donations.addresses.sites[coin] + "/address/" + config.donations.addresses[coin].address), class="text-wrap") #{config.donations.addresses[coin].address}
a.text-wrap(href=(config.donations.addresses.sites[coin] + "/address/" + config.donations.addresses[coin].address)) #{config.donations.addresses[coin].address}
each coin, index in config.donations.addresses.coins
div(style="display: inline-block; max-width: 150px;", class="text-center mb-3 word-wrap text-monospace", class=(index > 0 ? "ml-md-3" : false))
div.text-center.mb-3.word-wrap.text-monospace(style="display: inline-block; max-width: 150px;", class=(index > 0 ? "ml-md-3" : false))
img(src=donationAddressQrCodeUrls[coin], alt=config.donations.addresses[coin].address, style="border: solid 1px #ccc;")

2
views/includes/electrum-trust-note.pug

@ -1,3 +1,3 @@
span
span(data-toggle="tooltip", title="This data is at least partially generated from the ElectrumX servers currently configured: ")
i(class="fas fa-exclamation-triangle text-warning")
i.fas.fa-exclamation-triangle.text-warning

6
views/includes/index-network-summary.pug

@ -12,7 +12,7 @@ div.row.index-summary
- var hashrate7dayData0 = utils.formatLargeNumber(hashrate7d, 0);
- var hashrate1dayData1 = utils.formatLargeNumber(hashrate1d, 1);
- var hashrate7dayData1 = utils.formatLargeNumber(hashrate7d, 1);
table.table.table-borderless.table-sm.table-hover
table.table.table-borderless.table-sm.table-hover.mb-lg-0
tbody
tr
th.px-2.px-lg-0.px-xl-2
@ -80,7 +80,7 @@ div.row.index-summary
div(class=colClass)
h5.h6 Blockchain
table.table.table-borderless.table-sm.table-hover
table.table.table-borderless.table-sm.table-hover.mb-lg-0
tbody
tr
th.px-2.px-lg-0.px-xl-2
@ -157,7 +157,7 @@ div.row.index-summary
div(class=colClass)
h5.h6 Financials
table.table.table-borderless.table-sm.table-hover
table.table.table-borderless.table-sm.table-hover.mb-lg-0
tbody
if (exchangeRates)
tr

2
views/includes/line-graph.pug

@ -1,6 +1,6 @@
script(src="/js/chart.bundle.min.js", integrity="sha384-qgOtiGNaHh9fVWUnRjyHlV39rfbDcvPPkEzL1RHvsHKbuqUqM6uybNuVnghY2z4/")
canvas(id=graphData.id, class="mb-4")
canvas.mb-3(id=graphData.id)
if (session.uiTheme && session.uiTheme == "dark")
script.

22
views/includes/pagination.pug

@ -4,23 +4,23 @@
- }
nav(aria-label="Page navigation")
ul(class="pagination pagination-lg justify-content-center flex-wrap")
li(class="page-item", class=(pageNumber == 1 ? "disabled" : false))
a(class="page-link", href=(pageNumber == 1 ? "javascript:void(0)" : paginationUrlFunction(pageNumber - 1)), aria-label="Previous")
ul.pagination.pagination-lg.justify-content-center.flex-wrap
li.page-item(class=(pageNumber == 1 ? "disabled" : false))
a.page-link(href=(pageNumber == 1 ? "javascript:void(0)" : paginationUrlFunction(pageNumber - 1)), aria-label="Previous")
span(aria-hidden="true") &laquo;
each x, xIndex in pageNumbers
if (x >= (pageNumber - 4) && x <= (pageNumber + 4) || xIndex == 0 || xIndex == (pageNumbers.length - 1))
li(class="page-item", class=(x == pageNumber ? "active" : false))
a(class="page-link", href=(paginationUrlFunction(x))) #{x}
li.page-item(class=(x == pageNumber ? "active" : false))
a.page-link(href=(paginationUrlFunction(x))) #{x}
if (x == 1 && pageNumber > 6)
li(class="page-item disabled")
a(class="page-link", href="javascript:void(0)") ...
li.page-item.disabled
a.page-link(href="javascript:void(0)") ...
else if (x == (pageCount - 1) && pageNumber < (pageCount - 5))
li(class="page-item disabled")
a(class="page-link", href="javascript:void(0)") ...
li.page-item.disabled
a.page-link(href="javascript:void(0)") ...
li(class="page-item", class=(pageNumber == pageCount ? "disabled" : false))
a(class="page-link", href=(pageNumber == pageCount ? "javascript:void(0)" : paginationUrlFunction(pageNumber + 1)), aria-label="Next")
li.page-item(class=(pageNumber == pageCount ? "disabled" : false))
a.page-link(href=(pageNumber == pageCount ? "javascript:void(0)" : paginationUrlFunction(pageNumber + 1)), aria-label="Next")
span(aria-hidden="true") &raquo;

2
views/includes/time-ago.pug

@ -2,4 +2,4 @@
span
span(data-toggle="tooltip", title=(timeAgo.format() + " ago"))
i(class="far fa-clock")
i.far.fa-clock

4
views/includes/tools-card.pug

@ -1,5 +1,5 @@
if (false)
div.card.mb-4.shadow-sm
div.card.mb-3.shadow-sm
div.card-header
h2.h6.mb-0 Tools
div.card-body
@ -13,7 +13,7 @@ if (false)
li
div.float-left(style="height: 50px; width: 40px; margin-right: 10px;")
span
i(class=siteTool.fontawesome, class="fa-2x mr-2", style="margin-top: 6px;")
i.fa-2x.mr-2(class=siteTool.fontawesome, style="margin-top: 6px;")
a(href=siteTool.url) #{siteTool.name}
br

14
views/includes/transaction-io-details.pug

@ -31,7 +31,12 @@ div.row.text-monospace
a(data-toggle="tooltip", title=("Input #" + txVinIndex.toLocaleString()), style="white-space: nowrap;")
span.font-weight-bold &gt;
small.d-inline.d-md-none Input
span ##{txVinIndex.toLocaleString()}
if (tx.vin.length > 9)
small.word-wrap ##{txVinIndex}
else
span ##{txVinIndex.toLocaleString()}
if (tx.vin.length > 0)
small.d-inline.d-md-none.font-weight-light.text-muted / #{(tx.vin.length - 1).toLocaleString()}
@ -143,7 +148,12 @@ div.row.text-monospace
a(data-toggle="tooltip", title=("Output #" + voutIndex.toLocaleString()), style="white-space: nowrap;")
span.font-weight-bold &lt;
small.d-inline.d-md-none Output
span ##{voutIndex.toLocaleString()}
if (tx.vout.length > 999)
small.word-wrap ##{voutIndex}
else
span ##{voutIndex.toLocaleString()}
if (tx.vout.length > 0)
small.d-inline.d-md-none.font-weight-light.text-muted / #{(tx.vout.length - 1).toLocaleString()}

43
views/index.pug

@ -5,7 +5,7 @@ block headContent
block content
if (getblockchaininfo == null)
div(class="alert alert-warning")
div.alert.alert-warning
p.font-weight-bold Unable to get basic blockchain data
ul
li If you just started your node, it may still be initializing.
@ -15,7 +15,7 @@ block content
if (config.demoSite && session.hideHomepageBanner != "true")
div.alert.alert-primary.alert-dismissible.shadow-sm.mb-3(role="alert")
span
strong #{coinConfig.siteTitle}
span.font-weight-bold #{coinConfig.siteTitle}
span is
a(href="https://github.com/janoside/btc-rpc-explorer", target="_blank") open-source
span and easy to set up. It can communicate with your
@ -26,31 +26,32 @@ block content
if (global.sourcecodeProjectMetadata)
div.mt-2
a(href="https://github.com/janoside/btc-rpc-explorer", class="btn btn-primary mr-3 mb-1")
i(class="fas fa-star mr-2")
span(class="mr-2") Star
span(class="badge bg-white text-dark") #{global.sourcecodeProjectMetadata.stargazers_count}
a.btn.btn-primary.btn-sm.mr-3.mb-1(href="https://github.com/janoside/btc-rpc-explorer")
i.fas.fa-star.mr-2
span.mr-2 Star
span.badge.bg-white.text-dark #{global.sourcecodeProjectMetadata.stargazers_count}
a(href="https://github.com/janoside/btc-rpc-explorer/fork", class="btn btn-primary mr-3 mb-1")
i(class="fas fa-code-branch mr-2")
span(class="mr-2") Fork
span(class="badge bg-white text-dark") #{global.sourcecodeProjectMetadata.forks_count}
a.btn.btn-primary.btn-sm.mr-3.mb-1(href="https://github.com/janoside/btc-rpc-explorer/fork")
i.fas.fa-code-branch.mr-2
span.mr-2 Fork
span.badge.bg-white.text-dark #{global.sourcecodeProjectMetadata.forks_count}
if (!crawlerBot)
button.btn.btn-primary(type="button", class="btn btn-primary mb-1", data-toggle="modal", data-target="#exampleModalCenter")
i(class="fas fa-heart mr-2")
button.btn.btn-primary.btn-sm.mb-1(type="button", data-toggle="modal", data-target="#exampleModalCenter")
i.fas.fa-heart.mr-2
span Support Project
div.mt-2
a.mr-2(href="https://www.npmjs.com/package/btc-rpc-explorer" rel="nofollow" target="_blank")
img(src="https://camo.githubusercontent.com/a2a28dff9062102df7988314d014e68d4612bd83/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6274632d7270632d6578706c6f7265722e7376673f7374796c653d666c6174" alt="npm version" data-canonical-src="https://img.shields.io/npm/v/btc-rpc-explorer.svg?style=flat" style="max-width:100%;")
if (false)
div.mt-2
a.mr-2(href="https://www.npmjs.com/package/btc-rpc-explorer" rel="nofollow" target="_blank")
img(src="https://camo.githubusercontent.com/a2a28dff9062102df7988314d014e68d4612bd83/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f6274632d7270632d6578706c6f7265722e7376673f7374796c653d666c6174" alt="npm version" data-canonical-src="https://img.shields.io/npm/v/btc-rpc-explorer.svg?style=flat" style="max-width:100%;")
a(href="https://npmcharts.com/compare/btc-rpc-explorer?minimal=true" rel="nofollow" target="_blank")
img(src="https://camo.githubusercontent.com/07914c9a0c2f22f7493952dc969c57164bb14f77/687474703a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f6274632d7270632d6578706c6f7265722e7376673f7374796c653d666c6174" alt="NPM downloads" data-canonical-src="http://img.shields.io/npm/dm/btc-rpc-explorer.svg?style=flat" style="max-width:100%;")
a(href="https://npmcharts.com/compare/btc-rpc-explorer?minimal=true" rel="nofollow" target="_blank")
img(src="https://camo.githubusercontent.com/07914c9a0c2f22f7493952dc969c57164bb14f77/687474703a2f2f696d672e736869656c64732e696f2f6e706d2f646d2f6274632d7270632d6578706c6f7265722e7376673f7374796c653d666c6174" alt="NPM downloads" data-canonical-src="http://img.shields.io/npm/dm/btc-rpc-explorer.svg?style=flat" style="max-width:100%;")
a(href="/changeSetting?name=hideHomepageBanner&value=true", class="close", aria-label="Close", style="text-decoration: none;")
a.close(href="/changeSetting?name=hideHomepageBanner&value=true", aria-label="Close", style="text-decoration: none;")
span(aria-hidden="true") &times;
if (getblockchaininfo.initialblockdownload)
@ -105,11 +106,11 @@ block content
include includes/blocks-list.pug
if (false)
div(class="card mb-4 shadow-sm")
div.card.shadow-sm.mb-3
div.card-header
div.row
div.col
h2(class="h6 mb-0") Latest Blocks
h3.h6.mb-0 Latest Blocks
if (getblockchaininfo.initialblockdownload)
small (#{(getblockchaininfo.headers - getblockchaininfo.blocks).toLocaleString()} behind)
@ -143,7 +144,7 @@ block content
div.row
div.col-lg-6
div.table-responsive
table.table.text-right.mb-4.mb-lg-0
table.table.text-right.mb-3.mb-lg-0
thead
tr
th Period

6
views/layout.pug

@ -10,11 +10,11 @@ html(lang="en")
if (session.uiTheme && session.uiTheme == "dark")
link(rel="stylesheet", href="/css/bootstrap-dark.min.css", integrity="sha384-oqee0tym2HUHJW9STPyrefrgfODvg8w9lfqk+s/IbxHhuJpoPbAbPqj8ylGM3TUK")
link(rel="stylesheet", href="/css/bootstrap-dark.min.css", integrity="sha384-yHrdw+uFPe64ykHEYlYL2lmT0s+veKi1+lmxNqB3jVMOl9iX0h9xDLxcgtFtiV6M")
link(rel="stylesheet", href="/css/dark-touchups.css", integrity="sha384-nUVK/u/fwyNP4THfHo2CtWSoyZaxa65KenBmn/46NaEgGD5uaUFz+N6cqgg8n5t0")
else
link(rel="stylesheet", href="/css/bootstrap.min.css", integrity="sha384-Jo2q7h5Bg8GPJ+O6zM58Rvi6URN9ux4TSqZ4TlNnJzRWwVmEgDrqniWV//1yqqiR")
link(rel="stylesheet", href="/css/bootstrap.min.css", integrity="sha384-QO/VzYasHIIVEtFdqGXHU2wxSK0pjVxX4mrM68IQhYpi0vTCM0ZIuV/KQbPZMfXg")
link(rel='stylesheet', href='/css/styling.css')
@ -135,7 +135,7 @@ html(lang="en")
span.badge.badge-danger.ml-2 #{pageErrors.length.toLocaleString()}
if (userMessage)
div.alert(class=(userMessageType ? ("alert-" + userMessageType) : "alert-warning"), role="alert")
div.alert(class=(userMessageType ? `alert-${userMessageType} border-${userMessageType}` : "alert-warning border-warning"), role="alert")
span #{userMessage}
block content

10
views/mempool-summary.pug

@ -7,7 +7,7 @@ block content
h1.h3 Mempool Summary
hr
div#progress-wrapper
div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3
div.card-body
h4.h6 Loading mempool transactions:
@ -48,10 +48,10 @@ block content
h3.h6.mb-0 Transactions by fee rate
hr
canvas.mb-4(id="mempoolBarChart", height="100")
canvas.mb-3(id="mempoolBarChart", height="100")
div.table-responsive
table.table.table-striped.mb-4
table.table.table-striped.mb-3
thead
tr
th Fee Rate
@ -72,14 +72,14 @@ block content
h3.h6.mb-0 Transactions by size
hr
canvas.mb-4(id="txSizesBarChart", height="100")
canvas.mb-3(id="txSizesBarChart", height="100")
div.card.shadow-sm.mb-3
div.card-body.px-2.px-md-3
h3.h6.mb-0 Transactions by age
hr
canvas.mb-4(id="txAgesBarChart", height="100")
canvas.mb-3(id="txAgesBarChart", height="100")
block endOfBody

2
views/mining-summary.pug

@ -49,7 +49,7 @@ block content
div.input-group-append
button.btn.btn-primary(type="submit") Go
div#progress-wrapper
div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3
div.card-body
h4.h6 Loading blocks:

52
views/node-status.pug

@ -34,7 +34,7 @@ block content
h3.h6.mb-0 Summary
hr
table(class="table details-table mb-0")
table.table.details-table.mb-0
tr
td.properties-header Host : Port
td.text-monospace #{global.rpcClient.host + " : " + global.rpcClient.port}
@ -45,7 +45,7 @@ block content
tr
td.properties-header Version
td.text-monospace #{getnetworkinfo.version}
span(class="text-monospace") (#{getnetworkinfo.subversion})
span.text-monospace (#{getnetworkinfo.subversion})
tr
td.properties-header Protocol Version
td.text-monospace #{getnetworkinfo.protocolversion}
@ -163,27 +163,45 @@ block content
div(id="tab-json", class="tab-pane", role="tabpanel")
div.tab-pane(id="tab-json", role="tabpanel")
ul.nav.nav-pills.mb-3
li.nav-item
a(data-toggle="tab", href="#tab-getblockchaininfo", class="nav-link active", role="tab") getblockchaininfo
a.nav-link.active(data-toggle="tab", href="#tab-getblockchaininfo", role="tab") getblockchaininfo
li.nav-item
a(data-toggle="tab", href="#tab-getnettotals", class="nav-link", role="tab") getnettotals
a.nav-link(data-toggle="tab", href="#tab-getnettotals", role="tab") getnettotals
li.nav-item
a(data-toggle="tab", href="#tab-getnetworkinfo", class="nav-link", role="tab") getnetworkinfo
a.nav-link(data-toggle="tab", href="#tab-getnetworkinfo", role="tab") getnetworkinfo
div.tab-content
div(id="tab-getblockchaininfo", class="tab-pane active", role="tabpanel")
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getblockchaininfo, null, 4)}
div(id="tab-getnettotals", class="tab-pane", role="tabpanel")
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnettotals, null, 4)}
div(id="tab-getnetworkinfo", class="tab-pane", role="tabpanel")
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnetworkinfo, null, 4)}
div.tab-pane.active(id="tab-getblockchaininfo", role="tabpanel")
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 getblockchaininfo
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getblockchaininfo, null, 4)}
div.tab-pane(id="tab-getnettotals", role="tabpanel")
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 getnettotals
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnettotals, null, 4)}
div.tab-pane(id="tab-getnetworkinfo", role="tabpanel")
div.card.shadow-sm.mb-3
div.card-body
h4.h6.mb-0 getnetworkinfo
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnetworkinfo, null, 4)}

117
views/peers.pug

@ -31,72 +31,75 @@ block content
a.nav-link(data-toggle="tab", href="#tab-json", role="tab") JSON
div.tab-content
div(id="tab-summary", class="tab-pane active", role="tabpanel")
div.tab-pane.active(id="tab-summary", role="tabpanel")
if (peerIpSummary && peerIpSummary.ips)
div(id="map", class="mb-4")
div.mb-3(id="map")
div(class="card mb-4 shadow-sm")
div.card-header
h2(class="h6 mb-0") Summary
div.card-body
div.row
div.col-md-6
span(class="font-weight-bold") Top Versions
div.row
div.col-md-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Versions
hr
table(class="table table-striped table-responsive-sm")
table.table.table-striped.table-responsive-sm
thead
tr
th
th(class="data-header") Version
th(class="data-header") Count
th.data-header Version
th.data-header Count
tbody
each item, index in peerSummary.versionSummary
tr(class=(index >= 5 ? "versions-hidden-rows" : false))
td(class="data-cell font-weight-bold") #{index + 1}
td.data-cell.font-weight-bold #{index + 1}
td(class="data-cell text-monospace") #{item[0]}
td(class="data-cell text-monospace") #{item[1].toLocaleString()}
td.data-cell.text-monospace #{item[0]}
td.data-cell.text-monospace #{item[1].toLocaleString()}
div.col-md-6
span(class="font-weight-bold") Top Service Flags
div.col-md-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Service Flags
hr
table(class="table table-striped table-responsive-sm")
table.table.table-striped.table-responsive-sm
thead
tr
th
th(class="data-header") Services
th(class="data-header") Count
th.data-header Services
th.data-header Count
tbody
each item, index in peerSummary.servicesSummary
tr(class=(index >= 5 ? "services-hidden-rows" : false))
td(class="data-cell font-weight-bold") #{index + 1}
td.data-cell.font-weight-bold #{index + 1}
td.data-cell.text-monospace #{item[0]}
td.data-cell.text-monospace #{item[1].toLocaleString()}
td(class="data-cell text-monospace") #{item[0]}
td(class="data-cell text-monospace") #{item[1].toLocaleString()}
div(class="card mb-4 shadow-sm")
div.card-header
h2(class="h6 mb-0") #{peerSummary.getpeerinfo.length}
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 #{peerSummary.getpeerinfo.length}
if (peerSummary.getpeerinfo.length == 1)
span Peer
else
span Peers
div.card-body
table(class="table table-striped table-responsive-sm data-table mt-4")
hr
table.table.table-striped.table-responsive-sm.data-table.mt-4
thead
tr
th
th(class="data-header") Version
th(class="data-header") Address
th(class="data-header") Services
th.data-header Version
th.data-header Address
th.data-header Services
if (peerIpSummary && peerIpSummary.ips)
th(class="data-header") Location
th.data-header Location
th(class="data-header") Last Send / Receive
th.data-header Last Send / Receive
tbody
each item, index in peerSummary.getpeerinfo
@ -104,14 +107,14 @@ block content
- var lastRecvAgo = moment.duration(moment.utc(new Date()).diff(moment.utc(new Date(parseInt(item.lastrecv) * 1000)))).format().replace("milliseconds", "ms");
tr
th(class="data-cell") #{index + 1}
th.data-cell #{index + 1}
td(class="data-cell text-monospace") #{item.subver}
td(class="data-cell text-monospace") #{item.addr}
td(class="data-cell text-monospace") #{item.services}
td.data-cell.text-monospace #{item.subver}
td.data-cell.text-monospace #{item.addr}
td.data-cell.text-monospace #{item.services}
if (peerIpSummary.ips)
td(class="data-cell text-monospace")
td.data-cell.text-monospace
- var ipAddr = item.addr.substring(0, item.addr.lastIndexOf(":"));
if (peerIpSummary.ips && peerIpSummary.ips.includes(ipAddr))
- var ipDetails = peerIpSummary.detailsByIp[ipAddr];
@ -127,29 +130,37 @@ block content
- var ipAddr = null;
td(class="data-cell text-monospace") #{lastSendAgo} / #{lastRecvAgo}
td.data-cell.text-monospace #{lastSendAgo} / #{lastRecvAgo}
div(id="tab-json", class="tab-pane", role="tabpanel")
div.tab-pane(id="tab-json", role="tabpanel")
each item, index in peerSummary.getpeerinfo
div(class="border-bottom p-1")
div.border-bottom.p-1
a(href="javascript:void(0)" onclick=("javascript:var peer = document.getElementById('peerinfo_" + index + "'); peer.style.display = peer.style.display === 'none' ? '' : 'none';"))
i(class="fas fa-plus-circle")
i.fas.fa-plus-circle
span(class="text-monospace") #{item.addr}
span.text-monospace #{item.addr}
div(style="display: none;", id=("peerinfo_" + index), class="p-3")
h6 Peer Details
pre
code.json.bg-light #{JSON.stringify(item, null, 4)}
div.p-3(style="display: none;", id=("peerinfo_" + index))
div.card.shadow-sm.mb-3
div.card-body
h6.mb-0 Peer Details
hr
if (peerIpSummary && peerIpSummary.detailsByIp && peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))])
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(item, null, 4)}
h6 IP Geo-Location Info
pre
code.json.bg-light #{JSON.stringify(peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))], null, 4)}
if (peerIpSummary && peerIpSummary.detailsByIp && peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))])
div.card.shadow-sm.mb-3
div.card-body
h6.mb-0 IP Geo-Location Info
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))], null, 4)}
block endOfBody

14
views/search.pug

@ -7,10 +7,12 @@ block content
h1.h3 Search
hr
div(class="mb-5")
form(method="post", action="/search", class="form")
div.mb-5
form.form(method="post", action="/search")
input(type="hidden", name="_csrf", value=csrfToken)
div(class="input-group input-group-lg")
input(type="text", class="form-control form-control-sm", name="query", placeholder="block height/hash, txid, address", value=(query), style="width: 300px;")
div(class="input-group-append")
button(type="submit", class="btn btn-primary") Search
div.input-group.input-group-lg
input.form-control.form-control-sm(type="text", name="query", placeholder="block height/hash, txid, address", value=(query), style="width: 300px;")
div.input-group-append
button.btn.btn-primary(type="submit") Search

10
views/terminal.pug

@ -11,21 +11,21 @@ block content
div.col
if (!config.demoSite && (!config.credentials.rpc || !config.credentials.rpc.rpc))
span(style="float: right;")
a(href="/disconnect", class="btn btn-secondary") Disconnect from node
a.btn.btn-secondary(href="/disconnect") Disconnect from node
hr
:markdown-it
Use this interactive terminal to send RPC commands to your node. Results will be shown inline. To browse all available RPC commands you can use the [RPC Browser](/rpc-browser).
div(class="card mb-3 shadow-sm")
div.card.shadow-sm.mb-3
div.card-body
form(id="terminal-form")
div(class="form-group")
div.form-group
label(for="input-cmd") Command
input(type="text", id="input-cmd", name="cmd", class="form-control")
input.form-control(type="text", id="input-cmd", name="cmd")
input(type="submit", class="btn btn-primary btn-block", value="Send")
input.btn.btn-primary.btn-block(type="submit", value="Send")
hr

36
views/transaction.pug

@ -41,11 +41,11 @@ block content
div.tab-content
div.tab-pane.active(id="tab-details", role="tabpanel")
if (global.specialTransactions && global.specialTransactions[txid])
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;")
div(class="float-left", style="width: 55px; height: 55px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;")
div.alert.alert-primary.shadow-sm.pb-0
div.float-left(style="width: 55px; height: 55px; font-size: 18px;")
i.fas.fa-certificate.fa-2x(style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") #{coinConfig.name} Fun
h4.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun
// special transaction info
- var stInfo = global.specialTransactions[txid];
@ -211,7 +211,7 @@ block content
- var item1 = utils.formatCurrencyAmount(totalInputValue, currencyFormatType);
- var item2 = utils.formatCurrencyAmount(totalOutputValue, currencyFormatType);
span.ml-2(title=(item1.simpleVal + " - " + item2.simpleVal), data-toggle="tooltip")
i(class="fas fa-ellipsis-h")
i.fas.fa-ellipsis-h
if (feePaid > 0)
div.row
@ -363,15 +363,23 @@ block content
span.text-muted (decoded) #{utils.hex2ascii(vout.scriptPubKey.asm)}
div.tab-pane(id="tab-json", role="tabpanel")
h3.h5 Transaction
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(result.getrawtransaction, null, 4)}
h3.h5 UTXOs
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(utxos, null, 4)}
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transaction
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(result.getrawtransaction, null, 4)}
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 UTXOs
hr
div.highlight
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(utxos, null, 4)}
if (mempoolDetails)
h3.h5 Mempool Details

16
views/tx-stats.pug

@ -17,7 +17,7 @@ block content
if (true)
div.row
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transactions, 24hr
@ -30,7 +30,7 @@ block content
- var graphData = {id:"graphDay", dataVar:"txCountDataDay", labels:txStatsDay.txLabels, title:"Transactions, 24hr", xaxisTitle:"Block", xaxisStep:5, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transactions, 7day
@ -43,7 +43,7 @@ block content
- var graphData = {id:"graphWeek", dataVar:"txCountDataWeek", labels:txStatsWeek.txLabels, title:"Transactions, 7day", xaxisTitle:"Block", xaxisStep:100, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transactions, 30day
@ -56,7 +56,7 @@ block content
- var graphData = {id:"graphMonth", dataVar:"txCountDataMonth", labels:txStatsMonth.txLabels, title:"Transactions, 30day", xaxisTitle:"Block", xaxisStep:500, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Transactions, All time
@ -71,7 +71,7 @@ block content
div.row
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Tx Rate, 24hr
@ -84,7 +84,7 @@ block content
- var graphData = {id:"graphRateDay", dataVar:"txRateDataDay", labels:txStatsDay.txLabels, title:"Tx Rate, 24hr", xaxisTitle:"Block", xaxisStep:5, yaxisTitle:"Tx Per Sec"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Tx Rate, 7day
@ -97,7 +97,7 @@ block content
- var graphData = {id:"graphRateWeek", dataVar:"txRateDataWeek", labels:txStatsWeek.txLabels, title:"Tx Rate, 7day", xaxisTitle:"Block", xaxisStep:100, yaxisTitle:"Tx Per Sec"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-left
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Tx Rate, 30day
@ -110,7 +110,7 @@ block content
- var graphData = {id:"graphRateMonth", dataVar:"txRateDataMonth", labels:txStatsMonth.txLabels, title:"Tx Rate, 30day", xaxisTitle:"Block", xaxisStep:500, yaxisTitle:"Tx Per Sec"};
include ./includes/line-graph.pug
div.col-lg-6.col-lg-right
div.col-lg-6
div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Tx Rate, All time

9
views/unconfirmed-transactions.pug

@ -15,19 +15,20 @@ block content
- var txCount = mempoolDetails.txCount;
div.card.shadow-sm.mb-3
div.card-header
h3.h6
div.card-body
h3.h6.mb-0
if (txCount == 1)
span 1 Transaction
else
span #{txCount.toLocaleString()} Transactions
div.card-body
hr
each tx, txIndex in mempoolDetails.transactions
div.card.shadow-sm.mb-3
div.card-header.text-monospace
if (tx && tx.txid)
strong ##{(txIndex + offset).toLocaleString()}
span ##{(txIndex + offset).toLocaleString()}
span &ndash;
a(href=("/tx/" + tx.txid)) #{tx.txid}

Loading…
Cancel
Save