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. 39
      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. 45
      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", chain: "main",
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16", txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
summary: "The first transfer of bitcoin.", 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", 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; margin-bottom: 3px;
} }
.col-lg-left { .mb-huge {
padding-right: 8px; margin-bottom: 200px;
} }
.col-lg-right {
padding-left: 8px;
}
.nav-tabs .nav-link.active { .nav-tabs .nav-link.active {

2
routes/baseActionsRouter.js

@ -327,7 +327,7 @@ router.post("/connect", function(req, res, next) {
global.rpcClient = newClient; 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"; req.session.userMessageType = "success";
res.redirect("/"); res.redirect("/");

106
views/address.pug

@ -6,26 +6,27 @@ block headContent
block content block content
if (result && result.validateaddress) if (result && result.validateaddress)
if (!result.validateaddress.isvalid) if (!result.validateaddress.isvalid)
h1(class="h3 text-danger") Invalid Address div.alert.alert-danger.border-danger.mb-huge
br h1.h6.font-weight-bold Invalid Address
small(class="text-monospace") #{address} span.text-monospace #{address}
else else
h1.h3 Address h1.h3 Address
br br
small(class="text-monospace") #{address} small.text-monospace #{address}
hr hr
if (payoutAddressForMiner) if (payoutAddressForMiner)
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;") div.alert.alert-primary.shadow-sm.pb-0
div(class="float-left", style="width: 50px; height: 50px; font-size: 18px;") div.float-left(style="width: 50px; height: 50px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;") 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 p
span This looks like a miner payout address for 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) if (coinConfig.miningPoolsConfigUrls.length > 1)
span (see the configurations: span (see the configurations:
each item, index in coinConfig.miningPoolsConfigUrls each item, index in coinConfig.miningPoolsConfigUrls
@ -39,11 +40,11 @@ block content
span ) span )
else if (global.specialAddresses[address] && global.specialAddresses[address].type == "fun") else if (global.specialAddresses[address] && global.specialAddresses[address].type == "fun")
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;") div.alert.alert-primary.shadow-sm.pb-0
div(class="float-left", style="width: 50px; height: 50px; font-size: 18px;") div.float-left(style="width: 50px; height: 50px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;") 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 // special address info
- var saInfo = global.specialAddresses[address].addressInfo; - var saInfo = global.specialAddresses[address].addressInfo;
@ -76,14 +77,14 @@ block content
div.tab-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 (false && config.electrumXServers && config.electrumXServers.length > 0)
if (session.hideElectrumTrustWarnings != "true") 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. 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; span(aria-hidden="true") &times;
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
@ -145,7 +146,7 @@ block content
div.row div.row
div.summary-split-table-label Balance div.summary-split-table-label Balance
div.summary-split-table-content.text-monospace 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 each item in balance.conflictedResults
- var currencyValue = item.confirmed / coinConfig.baseCurrencyUnit.multiplier; - var currencyValue = item.confirmed / coinConfig.baseCurrencyUnit.multiplier;
@ -198,17 +199,17 @@ block content
div.summary-split-table-label #{flagName} div.summary-split-table-label #{flagName}
div.summary-split-table-content.text-monospace div.summary-split-table-content.text-monospace
if (flags[index]) if (flags[index])
i(class="fas fa-check text-success") i.fas.fa-check.text-success
else else
i(class="fas fa-times text-warning") i.fas.fa-times.text-warning
if (false) if (false)
div(class="card mb-3 shadow-sm") div.card.shadow-sm.mb-3
div.card-header div.card-header
span(class="h6") Flags span.h6 Flags
div.card-body div.card-body
div(class="table-responsive") div.table-responsive
table(class="table text-center") table.table.text-center
thead thead
tr tr
th Is Valid? th Is Valid?
@ -224,9 +225,9 @@ block content
each flag in flags each flag in flags
td td
if (flag) if (flag)
i(class="fas fa-check text-success") i.fas.fa-check.text-success
else else
i(class="fas fa-times text-warning") i.fas.fa-times.text-warning
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body 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 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) if (!crawlerBot && txids && txids.length > 1 && addressApiSupport.sortDesc && addressApiSupport.sortAsc)
div(class="float-right") div.float-right
a(href="#", class="pull-right dropdown-toggle", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false") a.pull-right.dropdown-toggle(href="#", data-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
if (sort == "desc") if (sort == "desc")
span Newest First span Newest First
else else
span Oldest First span Oldest First
div(class="dropdown-menu dropdown-menu-right") div.dropdown-menu.dropdown-menu-right
a(href=("/address/" + address), class="dropdown-item") a.dropdown-item(href=("/address/" + address))
if (sort == "desc") if (sort == "desc")
i(class="fa fa-check") i.fa.fa-check
span Newest First span Newest First
a(href=("/address/" + address + "?sort=asc"), class="dropdown-item") a.dropdown-item(href=("/address/" + address + "?sort=asc"))
if (sort != "desc") if (sort != "desc")
i(class="fa fa-check") i.fa.fa-check
span Oldest First span Oldest First
else if (txids && txids.length > 1 && addressApiSupport.sortDesc && !addressApiSupport.sortAsc) else if (txids && txids.length > 1 && addressApiSupport.sortDesc && !addressApiSupport.sortAsc)
@ -272,13 +273,13 @@ block content
hr hr
if (conflictedTxidResults) if (conflictedTxidResults)
div(class="alert alert-warning", style="padding-bottom: 0;") div.alert.alert-warning.pb-0
div(class="float-left", style="width: 55px; height: 50px; font-size: 18px;") div.float-left(style="width: 55px; height: 50px; font-size: 18px;")
i(class="fas fa-exclamation-triangle fa-2x", style="margin-top: 10px;") i.fas.fa-exclamation-triangle.fa-2x(style="margin-top: 10px;")
h4(class="alert-heading h6 font-weight-bold") Trust Warning h4.alert-heading.h6.font-weight-bold Trust Warning
p 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 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) if (true)
@ -332,7 +333,7 @@ block content
if (addrGainsByTx[tx.txid]) if (addrGainsByTx[tx.txid])
- var currencyValue = addrGainsByTx[tx.txid]; - var currencyValue = addrGainsByTx[tx.txid];
span(class="text-success") + span.text-success +
include includes/value-display.pug include includes/value-display.pug
if (addrLossesByTx[tx.txid]) if (addrLossesByTx[tx.txid])
@ -340,7 +341,7 @@ block content
if (addrLossesByTx[tx.txid]) if (addrLossesByTx[tx.txid])
- var currencyValue = addrLossesByTx[tx.txid]; - var currencyValue = addrLossesByTx[tx.txid];
span(class="text-danger") - span.text-danger -
include includes/value-display.pug include includes/value-display.pug
div.col-md-4 div.col-md-4
@ -393,15 +394,24 @@ block content
div(id="tab-json", class="tab-pane", role="tabpanel") div.tab-pane(id="tab-json", role="tabpanel")
div.highlight div.card.shadow-sm.mb-3
h4 validateaddress div.card-body
pre h4.h6.mb-0 validateaddress
code.json.bg-light(data-lang="json") #{JSON.stringify(result.validateaddress, null, 4)} 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) div.highlight
h4 addressDetails pre
pre code.json.bg-light #{JSON.stringify(addressDetails, null, 4)}
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) if (result.getblock.confirmations < 6)
span.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.") 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 else
span.font-weight-bold.text-success #{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.") 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 i.fas.fa-lock
div#progress-wrapper div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h4.h6 Loading transactions: h4.h6 Loading transactions:
@ -80,7 +80,7 @@ block content
div#main-content(style="display: none;") div#main-content(style="display: none;")
div.row div.row
div.col-lg-6.col-lg-left div.col-xl-4
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Top Value Transactions h3.h6.mb-0 Top Value Transactions
@ -90,19 +90,15 @@ block content
table.table.table-striped.mb-0 table.table.table-striped.mb-0
thead thead
tr tr
th
th.data-header Transaction th.data-header Transaction
th.data-header.text-right Output Value th.data-header.text-right Output Value
tbody(id="tbody-top-value-tx") tbody(id="tbody-top-value-tx")
tr.text-monospace.row-prototype(style="display: none;") tr.text-monospace.row-prototype(style="display: none;")
td
small.text-muted.data-index
td.data-tx-link td.data-tx-link
td.text-right.data-tx-value 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.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Top Fee Transactions h3.h6.mb-0 Top Fee Transactions
@ -112,19 +108,33 @@ block content
table.table.table-striped.mb-0 table.table.table-striped.mb-0
thead thead
tr tr
th
th.data-header Transaction th.data-header Transaction
th.data-header.text-right Fee th.data-header.text-right Fee
tbody(id="tbody-top-fee-tx") tbody(id="tbody-top-fee-tx")
tr.text-monospace.row-prototype(style="display: none;") tr.text-monospace.row-prototype(style="display: none;")
td td.data-tx-link
small.text-muted.data-index 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.data-tx-link
td.text-right.data-tx-value 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.shadow-sm(style="height: 100%;")
div.card-body div.card-body
h3.h6.mb-0 Input Types h3.h6.mb-0 Input Types
@ -138,7 +148,7 @@ block content
td.data-count 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.shadow-sm(style="height: 100%;")
div.card-body div.card-body
h3.h6.mb-0 Output Types h3.h6.mb-0 Output Types
@ -153,7 +163,7 @@ block content
td.data-count td.data-count
div.row div.row
div.col-lg-6.col-lg-left div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Value h3.h6.mb-0 Transaction Value
@ -161,7 +171,7 @@ block content
canvas(id="graph-tx-value") canvas(id="graph-tx-value")
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Value Distribution h3.h6.mb-0 Transaction Value Distribution
@ -169,7 +179,7 @@ block content
canvas(id="chart-tx-value-distribution") 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.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Fee h3.h6.mb-0 Transaction Fee
@ -177,7 +187,7 @@ block content
canvas(id="graph-tx-fee") canvas(id="graph-tx-fee")
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Fee Distribution h3.h6.mb-0 Transaction Fee Distribution
@ -185,29 +195,37 @@ block content
canvas(id="chart-tx-fee-distribution") 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.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Input Count h3.h6.mb-0 Transaction Size
hr 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.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Output Count h3.h6.mb-0 Transaction Size Distribution
hr 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.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transaction Size h3.h6.mb-0 Transaction Input Count
hr 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 txidChunks = !{JSON.stringify(utils.splitArrayIntoChunks(result.getblock.tx, txidChunkSize))};
var blockHeight = !{result.getblock.height}; var blockHeight = !{result.getblock.height};
var satsMultiplier = !{coinConfig.baseCurrencyUnit.multiplier}; var satsMultiplier = !{coinConfig.baseCurrencyUnit.multiplier};
var vByteSizes = false;
$(document).ready(function() { $(document).ready(function() {
loadTransactions(txidChunks, txidChunkSize, txidChunks.length * txidChunkSize); loadTransactions(txidChunks, txidChunkSize, txidChunks.length * txidChunkSize);
@ -263,6 +282,8 @@ block endOfBody
fillTopValueTxTable(summary); fillTopValueTxTable(summary);
fillTopFeeTxTable(summary); fillTopFeeTxTable(summary);
fillTopSizeTxTable(summary);
fillInputOutputTypesTable(summary); fillInputOutputTypesTable(summary);
createGraph("graph-tx-value", summary.txValueGraphData, "Value"); 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-value-distribution", summary.valueDistribution, summary.valueDistributionLabels);
createChart("chart-tx-fee-distribution", summary.feeDistribution, summary.feeDistributionLabels); createChart("chart-tx-fee-distribution", summary.feeDistribution, summary.feeDistributionLabels);
createChart("chart-tx-size-distribution", summary.sizeDistribution, summary.sizeDistributionLabels);
//$(".abc").text(JSON.stringify(summary)); //$(".abc").text(JSON.stringify(summary));
@ -293,8 +315,7 @@ block endOfBody
row.removeClass("row-prototype"); 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.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-link").html(`<a href='/tx/${item.txid}'>${item.txid}</a>`);
row.find(".data-tx-value").text(item.value); row.find(".data-tx-value").text(item.value);
updateCurrencyValue(row.find(".data-tx-value"), item.value); updateCurrencyValue(row.find(".data-tx-value"), item.value);
@ -315,8 +336,7 @@ block endOfBody
row.removeClass("row-prototype"); 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.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-link").html(`<a href='/tx/${item.txid}'>${item.txid}</a>`);
row.find(".data-tx-value").text(item.value); row.find(".data-tx-value").text(item.value);
updateCurrencyValue(row.find(".data-tx-value"), 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) { function fillInputOutputTypesTable(data) {
var sortedInputs = []; var sortedInputs = [];
for (var key in data.inputTypeCounts) { for (var key in data.inputTypeCounts) {
@ -497,6 +536,8 @@ block endOfBody
analysis.txFees = []; analysis.txFees = [];
analysis.txFeeGraphData = []; analysis.txFeeGraphData = [];
analysis.txSizes = [];
analysis.txSizeGraphData = []; analysis.txSizeGraphData = [];
analysis.txInputCountGraphData = []; analysis.txInputCountGraphData = [];
analysis.txOutputCountGraphData = []; analysis.txOutputCountGraphData = [];
@ -517,12 +558,17 @@ block endOfBody
analysis.outputTypeCounts[outputType]++; analysis.outputTypeCounts[outputType]++;
} }
if (txSummary.vsize) {
vByteSizes = true;
}
analysis.txValues.push({txid:txSummary.txid, value:new Decimal(txSummary.totalOutput)}); analysis.txValues.push({txid:txSummary.txid, value:new Decimal(txSummary.totalOutput)});
analysis.txValueGraphData.push({x:i, y:new Decimal(txSummary.totalOutput).toNumber()}); analysis.txValueGraphData.push({x:i, y:new Decimal(txSummary.totalOutput).toNumber()});
analysis.txFees.push({txid:txSummary.txid, value:new Decimal(txSummary.totalFee)}); analysis.txFees.push({txid:txSummary.txid, value:new Decimal(txSummary.totalFee)});
analysis.txFeeGraphData.push({x:i, y:new Decimal(txSummary.totalFee).toNumber()}); 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.txSizeGraphData.push({x:i, y:(txSummary.vsize ? txSummary.vsize : txSummary.size)});
analysis.txInputCountGraphData.push({x:i, y:txSummary.vin.length}); analysis.txInputCountGraphData.push({x:i, y:txSummary.vin.length});
@ -551,11 +597,17 @@ block endOfBody
return b.value.cmp(a.value); 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.topValueTxs = analysis.txValues.slice(0, Math.min(100, analysis.txValues.length));
analysis.topFeeTxs = analysis.txFees.slice(0, Math.min(100, analysis.txFees.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 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 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 topValueSats = parseInt(topValue);
var topFeeSats = parseInt(topFee); var topFeeSats = parseInt(topFee);
@ -568,22 +620,30 @@ block endOfBody
analysis.feeDistribution = []; analysis.feeDistribution = [];
analysis.feeDistributionLabels = []; analysis.feeDistributionLabels = [];
analysis.sizeDistribution = [];
analysis.sizeDistributionLabels = [];
for (var i = 0; i < distributionBucketCount; i++) { for (var i = 0; i < distributionBucketCount; i++) {
analysis.valueDistribution.push(0); 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.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.feeDistribution.push(0);
analysis.feeDistributionLabels.push(`[${new Decimal(i * topFeeSats / distributionBucketCount).toDP(0)} - ${new Decimal((i + 1) * topFeeSats / distributionBucketCount).toDP(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.valueDistributionLabels[distributionBucketCount - 1] = `${new Decimal(topValueSats).dividedBy(satsMultiplier).toDP(3)}+`;
analysis.feeDistributionLabels[distributionBucketCount - 1] = `${topFeeSats}+`; analysis.feeDistributionLabels[distributionBucketCount - 1] = `${topFeeSats}+`;
analysis.sizeDistributionLabels[distributionBucketCount - 1] = `${topSize}+`;
for (var i = 0; i < txResults.length; i++) { for (var i = 0; i < txResults.length; i++) {
var txSummary = txResults[i]; var txSummary = txResults[i];
var valueSats = new Decimal(txSummary.totalOutput).times(satsMultiplier); var valueSats = new Decimal(txSummary.totalOutput).times(satsMultiplier);
var feeSats = new Decimal(txSummary.totalFee).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); var valueBucket = parseInt(distributionBucketCount * valueSats / topValueSats);
if (valueBucket >= distributionBucketCount) { if (valueBucket >= distributionBucketCount) {
@ -595,8 +655,14 @@ block endOfBody
feeBucket = distributionBucketCount - 1; feeBucket = distributionBucketCount - 1;
} }
var sizeBucket = parseInt(distributionBucketCount * size / topSize);
if (sizeBucket >= distributionBucketCount) {
sizeBucket = distributionBucketCount - 1;
}
analysis.valueDistribution[valueBucket]++; analysis.valueDistribution[valueBucket]++;
analysis.feeDistribution[feeBucket]++; analysis.feeDistribution[feeBucket]++;
analysis.sizeDistribution[sizeBucket]++;
} }
return analysis; return analysis;

4
views/block-stats.pug

@ -59,7 +59,7 @@ block content
div.input-group-append div.input-group-append
button.btn.btn-primary(type="submit") Go button.btn.btn-primary(type="submit") Go
div#progress-wrapper div#progress-wrapper.mb-huge
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h4.h6 Loading blocks: h4.h6 Loading blocks:
@ -88,7 +88,7 @@ block content
div.row.clearfix div.row.clearfix
each graphId, graphIndex in graphIds 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.shadow-sm.mb-3.graph-wrapper(id=`graph-wrapper-${graphId}`)
div.card-body div.card-body
h3.h6.mb-0 #{graphTitles[graphIndex]} h3.h6.mb-0 #{graphTitles[graphIndex]}

39
views/blocks.pug

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

22
views/connect.pug

@ -1,28 +1,28 @@
extends layout extends layout
block content block content
h1(class="h2") RPC Connect h1.h3 RPC Connect
hr hr
form(method="post", action="/connect") form(method="post", action="/connect")
input(type="hidden", name="_csrf", value=csrfToken) input(type="hidden", name="_csrf", value=csrfToken)
div(class="form-group") div.form-group
label(for="input-host") Host / IP 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 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 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 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") div.form-group
input(type="submit", class="btn btn-primary btn-block" value="Connect") input.btn.btn-primary.btn-block(type="submit" value="Connect")

22
views/fun.pug

@ -11,23 +11,23 @@ block content
div.card-body 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. 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") div.table-responsive
table(class="table table-striped mt-4") table.table.table-striped
thead thead
tr tr
th(class="data-header") Date th.data-header Date
th(class="data-header") Description th.data-header Description
th(class="data-header") Link th.data-header Link
th(class="data-header") Reference th.data-header Reference
tbody tbody
each item, index in coinConfig.historicalData each item, index in coinConfig.historicalData
if (item.chain == global.activeBlockchain) if (item.chain == global.activeBlockchain)
tr 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") if (item.type == "tx")
a(href=("/tx/" + item.txid), title=item.txid, data-toggle="tooltip") Tx #{item.txid.substring(0, 23)}... a(href=("/tx/" + item.txid), title=item.txid, data-toggle="tooltip") Tx #{item.txid.substring(0, 23)}...
else if (item.type == "block") else if (item.type == "block")
@ -39,7 +39,7 @@ block content
else if (item.type == "link") else if (item.type == "link")
a(href=item.url) #{item.url.substring(0, 20)}... a(href=item.url) #{item.url.substring(0, 20)}...
td(class="data-cell") td.data-cell
if (item.referenceUrl && item.referenceUrl.trim().length > 0) if (item.referenceUrl && item.referenceUrl.trim().length > 0)
- var matches = item.referenceUrl.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i); - var matches = item.referenceUrl.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i);
@ -48,7 +48,7 @@ block content
if (domain) if (domain)
a(href=item.referenceUrl, rel="nofollow") #{domain} a(href=item.referenceUrl, rel="nofollow") #{domain}
i(class="fas fa-external-link-alt") i.fas.fa-external-link-alt
else else
a(href=item.referenceUrl, rel="nofollow") Reference a(href=item.referenceUrl, rel="nofollow") Reference
else else

48
views/includes/block-content.pug

@ -27,10 +27,10 @@ ul.nav.nav-tabs.mb-3
div.tab-content div.tab-content
div.tab-pane.active(id="tab-details", role="tabpanel") div.tab-pane.active(id="tab-details", role="tabpanel")
if (global.specialBlocks && global.specialBlocks[result.getblock.hash]) if (global.specialBlocks && global.specialBlocks[result.getblock.hash])
div(class="alert alert-primary shadow-sm", style="padding-bottom: 0;") div.alert.alert-primary.shadow-sm.pb-0
div(class="float-left", style="width: 55px; height: 55px; font-size: 18px;") div.float-left(style="width: 55px; height: 55px; font-size: 18px;")
i(class="fas fa-certificate fa-2x", style="margin-top: 10px;") 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 // special transaction info
- var sbInfo = global.specialBlocks[result.getblock.hash]; - var sbInfo = global.specialBlocks[result.getblock.hash];
@ -172,11 +172,11 @@ div.tab-content
div(class=sumTableLabelClass) Confirmations div(class=sumTableLabelClass) Confirmations
div.text-monospace(class=sumTableValueClass) div.text-monospace(class=sumTableValueClass)
if (result.getblock.confirmations < 6) 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.") 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 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.") 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 i.fas.fa-lock
@ -367,7 +367,7 @@ div.tab-content
a.ml-2(href=`/block-analysis/${result.getblock.hash}`) See Transaction Analysis &raquo; a.ml-2(href=`/block-analysis/${result.getblock.hash}`) See Transaction Analysis &raquo;
if (false || (!config.demoSite && !crawlerBot && txCount > 20)) 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 small.mr-1.text-muted Show
div.btn-group(role="group") 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 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 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)); - var blockDetails = JSON.parse(JSON.stringify(result.getblock));
- blockDetails.tx = "See 'Transaction IDs'"; - blockDetails.tx = "See 'Transaction IDs'";
@ -443,15 +443,33 @@ div.tab-content
div.tab-content div.tab-content
div.tab-pane.active(id="tab-json-block-summary", role="tabpanel") div.tab-pane.active(id="tab-json-block-summary", role="tabpanel")
pre div.card.shadow-sm.mb-3
code.json.bg-light #{JSON.stringify(blockDetails, null, 4)} 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") div.tab-pane(id="tab-json-tx-ids", role="tabpanel")
pre div.card.shadow-sm.mb-3
code.json.bg-light #{JSON.stringify(result.getblock.tx, null, 4)} 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) if (result.blockstats)
div.tab-pane(id="tab-json-blockstats", role="tabpanel") div.tab-pane(id="tab-json-blockstats", role="tabpanel")
pre div.card.shadow-sm.mb-3
code.json.bg-light #{JSON.stringify(result.blockstats, null, 4)} 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`) span.ml-1(data-toggle="tooltip", title=`Size: ${bSizeK.toLocaleString()} kB`)
i.fas.fa-ellipsis-h.text-muted i.fas.fa-ellipsis-h.text-muted
div(class="progress", style="height: 4px;") div.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-bar(role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.weight / coinConfig.maxBlockWeight), aria-valuemin="0" ,aria-valuemax="100")
else else
td.data-cell.text-monospace.text-right td.data-cell.text-monospace.text-right
@ -181,7 +181,7 @@ div.table-responsive
span #{bSizeK.toLocaleString()} span #{bSizeK.toLocaleString()}
small.font-weight-light.text-muted (#{fullPercent}%) small.font-weight-light.text-muted (#{fullPercent}%)
div(class="progress", style="height: 4px;") div.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-bar(role="progressbar", style=("width: " + fullPercent + "%;"), aria-valuenow=parseInt(100 * block.size / coinConfig.maxBlockSize), aria-valuemin="0" ,aria-valuemax="100")
- var lastBlock = block; - var lastBlock = block;

20
views/includes/donation-modal.pug

@ -17,10 +17,10 @@
if (false) if (false)
h6 h6
span(class="mr-2") Donate (via BTCPay) span.mr-2 Donate (via BTCPay)
- var amounts = [1, 5, 10, 25, 100]; - var amounts = [1, 5, 10, 25, 100];
- var icons = [ "thumbs-up", "beer", "hamburger", "utensils", "grin-hearts" ]; - var icons = [ "thumbs-up", "beer", "hamburger", "utensils", "grin-hearts" ];
div(class="mb-2") div.mb-2
each amount, amtIndex in amounts each amount, amtIndex in amounts
form(method="POST" action=(config.donations.btcpayserver.host + "/api/v1/invoices"), style="display: inline;") form(method="POST" action=(config.donations.btcpayserver.host + "/api/v1/invoices"), style="display: inline;")
input(type='hidden' name='storeId' value=config.donations.btcpayserver.storeId) 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='currency' value='USD')
input(type='hidden' name='notifyEmail' value=config.donations.btcpayserver.notifyEmail) 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])) i(class=("fas mr-2 fa-" + icons[amtIndex]))
span $#{amount.toLocaleString()} span $#{amount.toLocaleString()}
@ -38,8 +38,8 @@
input(type='hidden' name='currency' value='BTC') input(type='hidden' name='currency' value='BTC')
input(type='hidden' name='notifyEmail' value=config.donations.btcpayserver.notifyEmail) 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-bolt") i.fas.mr-2.fa-bolt
span 1 satoshi span 1 satoshi
script. script.
@ -50,20 +50,20 @@
} }
if (false) if (false)
div(id="donate-by-address", class="mt-4") div.mt-4(id="donate-by-address")
h6 Donate by address h6 Donate by address
div(class="mb-3") div.mb-3
each coin, index in config.donations.addresses.coins each coin, index in config.donations.addresses.coins
div(class="text-monospace") div.text-monospace
if (coinConfig.ticker == coin) if (coinConfig.ticker == coin)
span #{config.donations.addresses[coin].address} span #{config.donations.addresses[coin].address}
else else
span #{coin}: 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 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;") 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
span(data-toggle="tooltip", title="This data is at least partially generated from the ElectrumX servers currently configured: ") 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 hashrate7dayData0 = utils.formatLargeNumber(hashrate7d, 0);
- var hashrate1dayData1 = utils.formatLargeNumber(hashrate1d, 1); - var hashrate1dayData1 = utils.formatLargeNumber(hashrate1d, 1);
- var hashrate7dayData1 = utils.formatLargeNumber(hashrate7d, 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 tbody
tr tr
th.px-2.px-lg-0.px-xl-2 th.px-2.px-lg-0.px-xl-2
@ -80,7 +80,7 @@ div.row.index-summary
div(class=colClass) div(class=colClass)
h5.h6 Blockchain h5.h6 Blockchain
table.table.table-borderless.table-sm.table-hover table.table.table-borderless.table-sm.table-hover.mb-lg-0
tbody tbody
tr tr
th.px-2.px-lg-0.px-xl-2 th.px-2.px-lg-0.px-xl-2
@ -157,7 +157,7 @@ div.row.index-summary
div(class=colClass) div(class=colClass)
h5.h6 Financials h5.h6 Financials
table.table.table-borderless.table-sm.table-hover table.table.table-borderless.table-sm.table-hover.mb-lg-0
tbody tbody
if (exchangeRates) if (exchangeRates)
tr tr

2
views/includes/line-graph.pug

@ -1,6 +1,6 @@
script(src="/js/chart.bundle.min.js", integrity="sha384-qgOtiGNaHh9fVWUnRjyHlV39rfbDcvPPkEzL1RHvsHKbuqUqM6uybNuVnghY2z4/") 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") if (session.uiTheme && session.uiTheme == "dark")
script. script.

22
views/includes/pagination.pug

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

2
views/includes/time-ago.pug

@ -2,4 +2,4 @@
span span
span(data-toggle="tooltip", title=(timeAgo.format() + " ago")) 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) if (false)
div.card.mb-4.shadow-sm div.card.mb-3.shadow-sm
div.card-header div.card-header
h2.h6.mb-0 Tools h2.h6.mb-0 Tools
div.card-body div.card-body
@ -13,7 +13,7 @@ if (false)
li li
div.float-left(style="height: 50px; width: 40px; margin-right: 10px;") div.float-left(style="height: 50px; width: 40px; margin-right: 10px;")
span 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} a(href=siteTool.url) #{siteTool.name}
br 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;") a(data-toggle="tooltip", title=("Input #" + txVinIndex.toLocaleString()), style="white-space: nowrap;")
span.font-weight-bold &gt; span.font-weight-bold &gt;
small.d-inline.d-md-none Input 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) if (tx.vin.length > 0)
small.d-inline.d-md-none.font-weight-light.text-muted / #{(tx.vin.length - 1).toLocaleString()} 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;") a(data-toggle="tooltip", title=("Output #" + voutIndex.toLocaleString()), style="white-space: nowrap;")
span.font-weight-bold &lt; span.font-weight-bold &lt;
small.d-inline.d-md-none Output 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) if (tx.vout.length > 0)
small.d-inline.d-md-none.font-weight-light.text-muted / #{(tx.vout.length - 1).toLocaleString()} small.d-inline.d-md-none.font-weight-light.text-muted / #{(tx.vout.length - 1).toLocaleString()}

45
views/index.pug

@ -5,7 +5,7 @@ block headContent
block content block content
if (getblockchaininfo == null) if (getblockchaininfo == null)
div(class="alert alert-warning") div.alert.alert-warning
p.font-weight-bold Unable to get basic blockchain data p.font-weight-bold Unable to get basic blockchain data
ul ul
li If you just started your node, it may still be initializing. li If you just started your node, it may still be initializing.
@ -15,7 +15,7 @@ block content
if (config.demoSite && session.hideHomepageBanner != "true") if (config.demoSite && session.hideHomepageBanner != "true")
div.alert.alert-primary.alert-dismissible.shadow-sm.mb-3(role="alert") div.alert.alert-primary.alert-dismissible.shadow-sm.mb-3(role="alert")
span span
strong #{coinConfig.siteTitle} span.font-weight-bold #{coinConfig.siteTitle}
span is span is
a(href="https://github.com/janoside/btc-rpc-explorer", target="_blank") open-source a(href="https://github.com/janoside/btc-rpc-explorer", target="_blank") open-source
span and easy to set up. It can communicate with your span and easy to set up. It can communicate with your
@ -26,31 +26,32 @@ block content
if (global.sourcecodeProjectMetadata) if (global.sourcecodeProjectMetadata)
div.mt-2 div.mt-2
a(href="https://github.com/janoside/btc-rpc-explorer", class="btn btn-primary mr-3 mb-1") a.btn.btn-primary.btn-sm.mr-3.mb-1(href="https://github.com/janoside/btc-rpc-explorer")
i(class="fas fa-star mr-2") i.fas.fa-star.mr-2
span(class="mr-2") Star span.mr-2 Star
span(class="badge bg-white text-dark") #{global.sourcecodeProjectMetadata.stargazers_count} 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") a.btn.btn-primary.btn-sm.mr-3.mb-1(href="https://github.com/janoside/btc-rpc-explorer/fork")
i(class="fas fa-code-branch mr-2") i.fas.fa-code-branch.mr-2
span(class="mr-2") Fork span.mr-2 Fork
span(class="badge bg-white text-dark") #{global.sourcecodeProjectMetadata.forks_count} span.badge.bg-white.text-dark #{global.sourcecodeProjectMetadata.forks_count}
if (!crawlerBot) if (!crawlerBot)
button.btn.btn-primary(type="button", class="btn btn-primary mb-1", data-toggle="modal", data-target="#exampleModalCenter") button.btn.btn-primary.btn-sm.mb-1(type="button", data-toggle="modal", data-target="#exampleModalCenter")
i(class="fas fa-heart mr-2") i.fas.fa-heart.mr-2
span Support Project span Support Project
div.mt-2 if (false)
a.mr-2(href="https://www.npmjs.com/package/btc-rpc-explorer" rel="nofollow" target="_blank") div.mt-2
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.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") 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%;") 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; span(aria-hidden="true") &times;
if (getblockchaininfo.initialblockdownload) if (getblockchaininfo.initialblockdownload)
@ -105,11 +106,11 @@ block content
include includes/blocks-list.pug include includes/blocks-list.pug
if (false) if (false)
div(class="card mb-4 shadow-sm") div.card.shadow-sm.mb-3
div.card-header div.card-header
div.row div.row
div.col div.col
h2(class="h6 mb-0") Latest Blocks h3.h6.mb-0 Latest Blocks
if (getblockchaininfo.initialblockdownload) if (getblockchaininfo.initialblockdownload)
small (#{(getblockchaininfo.headers - getblockchaininfo.blocks).toLocaleString()} behind) small (#{(getblockchaininfo.headers - getblockchaininfo.blocks).toLocaleString()} behind)
@ -143,7 +144,7 @@ block content
div.row div.row
div.col-lg-6 div.col-lg-6
div.table-responsive div.table-responsive
table.table.text-right.mb-4.mb-lg-0 table.table.text-right.mb-3.mb-lg-0
thead thead
tr tr
th Period th Period

6
views/layout.pug

@ -10,11 +10,11 @@ html(lang="en")
if (session.uiTheme && session.uiTheme == "dark") 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") link(rel="stylesheet", href="/css/dark-touchups.css", integrity="sha384-nUVK/u/fwyNP4THfHo2CtWSoyZaxa65KenBmn/46NaEgGD5uaUFz+N6cqgg8n5t0")
else 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') link(rel='stylesheet', href='/css/styling.css')
@ -135,7 +135,7 @@ html(lang="en")
span.badge.badge-danger.ml-2 #{pageErrors.length.toLocaleString()} span.badge.badge-danger.ml-2 #{pageErrors.length.toLocaleString()}
if (userMessage) 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} span #{userMessage}
block content block content

10
views/mempool-summary.pug

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

2
views/mining-summary.pug

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

52
views/node-status.pug

@ -34,7 +34,7 @@ block content
h3.h6.mb-0 Summary h3.h6.mb-0 Summary
hr hr
table(class="table details-table mb-0") table.table.details-table.mb-0
tr tr
td.properties-header Host : Port td.properties-header Host : Port
td.text-monospace #{global.rpcClient.host + " : " + global.rpcClient.port} td.text-monospace #{global.rpcClient.host + " : " + global.rpcClient.port}
@ -45,7 +45,7 @@ block content
tr tr
td.properties-header Version td.properties-header Version
td.text-monospace #{getnetworkinfo.version} td.text-monospace #{getnetworkinfo.version}
span(class="text-monospace") (#{getnetworkinfo.subversion}) span.text-monospace (#{getnetworkinfo.subversion})
tr tr
td.properties-header Protocol Version td.properties-header Protocol Version
td.text-monospace #{getnetworkinfo.protocolversion} 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 ul.nav.nav-pills.mb-3
li.nav-item 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 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 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.tab-content
div(id="tab-getblockchaininfo", class="tab-pane active", role="tabpanel") div.tab-pane.active(id="tab-getblockchaininfo", role="tabpanel")
pre div.card.shadow-sm.mb-3
code.json.bg-light(data-lang="json") #{JSON.stringify(getblockchaininfo, null, 4)} div.card-body
h4.h6.mb-0 getblockchaininfo
div(id="tab-getnettotals", class="tab-pane", role="tabpanel") hr
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnettotals, null, 4)} div.highlight
pre
div(id="tab-getnetworkinfo", class="tab-pane", role="tabpanel") code.json.bg-light(data-lang="json") #{JSON.stringify(getblockchaininfo, null, 4)}
pre
code.json.bg-light(data-lang="json") #{JSON.stringify(getnetworkinfo, 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 a.nav-link(data-toggle="tab", href="#tab-json", role="tab") JSON
div.tab-content 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) if (peerIpSummary && peerIpSummary.ips)
div(id="map", class="mb-4") div.mb-3(id="map")
div(class="card mb-4 shadow-sm") div.row
div.card-header div.col-md-6
h2(class="h6 mb-0") Summary div.card.shadow-sm.mb-3
div.card-body div.card-body
div.row h3.h6.mb-0 Top Versions
div.col-md-6
span(class="font-weight-bold") Top Versions
hr hr
table(class="table table-striped table-responsive-sm")
table.table.table-striped.table-responsive-sm
thead thead
tr tr
th th
th(class="data-header") Version th.data-header Version
th(class="data-header") Count th.data-header Count
tbody tbody
each item, index in peerSummary.versionSummary each item, index in peerSummary.versionSummary
tr(class=(index >= 5 ? "versions-hidden-rows" : false)) 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.data-cell.text-monospace #{item[0]}
td(class="data-cell text-monospace") #{item[1].toLocaleString()} td.data-cell.text-monospace #{item[1].toLocaleString()}
div.col-md-6 div.col-md-6
span(class="font-weight-bold") Top Service Flags div.card.shadow-sm.mb-3
div.card-body
h3.h6.mb-0 Top Service Flags
hr hr
table(class="table table-striped table-responsive-sm")
table.table.table-striped.table-responsive-sm
thead thead
tr tr
th th
th(class="data-header") Services th.data-header Services
th(class="data-header") Count th.data-header Count
tbody tbody
each item, index in peerSummary.servicesSummary each item, index in peerSummary.servicesSummary
tr(class=(index >= 5 ? "services-hidden-rows" : false)) 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(class="data-cell text-monospace") #{item[0]} td.data-cell.text-monospace #{item[0]}
td(class="data-cell text-monospace") #{item[1].toLocaleString()} td.data-cell.text-monospace #{item[1].toLocaleString()}
div(class="card mb-4 shadow-sm") div.card.shadow-sm.mb-3
div.card-header div.card-body
h2(class="h6 mb-0") #{peerSummary.getpeerinfo.length} h3.h6.mb-0 #{peerSummary.getpeerinfo.length}
if (peerSummary.getpeerinfo.length == 1) if (peerSummary.getpeerinfo.length == 1)
span Peer span Peer
else else
span Peers span Peers
div.card-body hr
table(class="table table-striped table-responsive-sm data-table mt-4")
table.table.table-striped.table-responsive-sm.data-table.mt-4
thead thead
tr tr
th th
th(class="data-header") Version th.data-header Version
th(class="data-header") Address th.data-header Address
th(class="data-header") Services th.data-header Services
if (peerIpSummary && peerIpSummary.ips) 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 tbody
each item, index in peerSummary.getpeerinfo 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"); - var lastRecvAgo = moment.duration(moment.utc(new Date()).diff(moment.utc(new Date(parseInt(item.lastrecv) * 1000)))).format().replace("milliseconds", "ms");
tr tr
th(class="data-cell") #{index + 1} th.data-cell #{index + 1}
td(class="data-cell text-monospace") #{item.subver} td.data-cell.text-monospace #{item.subver}
td(class="data-cell text-monospace") #{item.addr} td.data-cell.text-monospace #{item.addr}
td(class="data-cell text-monospace") #{item.services} td.data-cell.text-monospace #{item.services}
if (peerIpSummary.ips) if (peerIpSummary.ips)
td(class="data-cell text-monospace") td.data-cell.text-monospace
- var ipAddr = item.addr.substring(0, item.addr.lastIndexOf(":")); - var ipAddr = item.addr.substring(0, item.addr.lastIndexOf(":"));
if (peerIpSummary.ips && peerIpSummary.ips.includes(ipAddr)) if (peerIpSummary.ips && peerIpSummary.ips.includes(ipAddr))
- var ipDetails = peerIpSummary.detailsByIp[ipAddr]; - var ipDetails = peerIpSummary.detailsByIp[ipAddr];
@ -127,29 +130,37 @@ block content
- var ipAddr = null; - 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 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';")) 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") div.p-3(style="display: none;", id=("peerinfo_" + index))
h6 Peer Details div.card.shadow-sm.mb-3
pre div.card-body
code.json.bg-light #{JSON.stringify(item, null, 4)} h6.mb-0 Peer Details
hr
div.highlight
pre
code.json.bg-light #{JSON.stringify(item, null, 4)}
if (peerIpSummary && peerIpSummary.detailsByIp && peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))]) if (peerIpSummary && peerIpSummary.detailsByIp && peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))])
hr div.card.shadow-sm.mb-3
div.card-body
h6 IP Geo-Location Info h6.mb-0 IP Geo-Location Info
pre hr
code.json.bg-light #{JSON.stringify(peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))], null, 4)}
div.highlight
pre
code.json.bg-light #{JSON.stringify(peerIpSummary.detailsByIp[item.addr.substring(0, item.addr.lastIndexOf(":"))], null, 4)}
block endOfBody block endOfBody

14
views/search.pug

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

10
views/terminal.pug

@ -11,21 +11,21 @@ block content
div.col div.col
if (!config.demoSite && (!config.credentials.rpc || !config.credentials.rpc.rpc)) if (!config.demoSite && (!config.credentials.rpc || !config.credentials.rpc.rpc))
span(style="float: right;") span(style="float: right;")
a(href="/disconnect", class="btn btn-secondary") Disconnect from node a.btn.btn-secondary(href="/disconnect") Disconnect from node
hr hr
:markdown-it :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). 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 div.card-body
form(id="terminal-form") form(id="terminal-form")
div(class="form-group") div.form-group
label(for="input-cmd") Command 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 hr

36
views/transaction.pug

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

16
views/tx-stats.pug

@ -17,7 +17,7 @@ block content
if (true) if (true)
div.row div.row
div.col-lg-6.col-lg-left div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transactions, 24hr 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"}; - var graphData = {id:"graphDay", dataVar:"txCountDataDay", labels:txStatsDay.txLabels, title:"Transactions, 24hr", xaxisTitle:"Block", xaxisStep:5, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug include ./includes/line-graph.pug
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transactions, 7day 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"}; - var graphData = {id:"graphWeek", dataVar:"txCountDataWeek", labels:txStatsWeek.txLabels, title:"Transactions, 7day", xaxisTitle:"Block", xaxisStep:100, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug include ./includes/line-graph.pug
div.col-lg-6.col-lg-left div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transactions, 30day 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"}; - var graphData = {id:"graphMonth", dataVar:"txCountDataMonth", labels:txStatsMonth.txLabels, title:"Transactions, 30day", xaxisTitle:"Block", xaxisStep:500, yaxisTitle:"Tx Count"};
include ./includes/line-graph.pug include ./includes/line-graph.pug
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Transactions, All time h3.h6.mb-0 Transactions, All time
@ -71,7 +71,7 @@ block content
div.row div.row
div.col-lg-6.col-lg-left div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Tx Rate, 24hr 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"}; - 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 include ./includes/line-graph.pug
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Tx Rate, 7day 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"}; - 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 include ./includes/line-graph.pug
div.col-lg-6.col-lg-left div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Tx Rate, 30day 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"}; - 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 include ./includes/line-graph.pug
div.col-lg-6.col-lg-right div.col-lg-6
div.card.shadow-sm.mb-3 div.card.shadow-sm.mb-3
div.card-body div.card-body
h3.h6.mb-0 Tx Rate, All time h3.h6.mb-0 Tx Rate, All time

9
views/unconfirmed-transactions.pug

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

Loading…
Cancel
Save