extends layout block headContent title Address #{address} block content if (result && result.validateaddress) if (!result.validateaddress.isvalid) 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.text-monospace #{address} hr if (payoutAddressForMiner) 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.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun p span This looks like a miner payout address for span.font-weight-bold #{payoutAddressForMiner.name} if (coinConfig.miningPoolsConfigUrls.length > 1) span (see the configurations: each item, index in coinConfig.miningPoolsConfigUrls if (index > 0) span , a(href=item) config ##{index + 1} span ) else span (see the configuration a(href=coinConfig.miningPoolsConfigUrls[0]) here span ) else if (global.specialAddresses[address] && global.specialAddresses[address].type == "fun") 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.alert-heading.h6.font-weight-bold #{coinConfig.name} Fun // special address info - var saInfo = global.specialAddresses[address].addressInfo; if (saInfo.alertBodyHtml) p span !{saInfo.alertBodyHtml} if (saInfo.referenceUrl && saInfo.referenceUrl.trim().length > 0 && saInfo.alertBodyHtml.indexOf(saInfo.referenceUrl) == -1) span a(href=saInfo.referenceUrl) Read more else p span #{saInfo.summary} if (saInfo.referenceUrl && saInfo.referenceUrl.trim().length > 0) span a(href=saInfo.referenceUrl) Read more if (false) pre code.json.bg-light #{JSON.stringify(addressObj, null, 4)} ul.nav.nav-tabs.mb-3 li.nav-item a.nav-link.active(data-toggle="tab", href="#tab-details", role="tab") Details li.nav-item a.nav-link(data-toggle="tab", href="#tab-json", role="tab") JSON div.tab-content div.tab-pane.active(id="tab-details", role="tabpanel") if (false && config.electrumXServers && config.electrumXServers.length > 0) if (session.hideElectrumTrustWarnings != "true") 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.close(href="/changeSetting?name=hideElectrumTrustWarnings&value=true", aria-label="Close", style="text-decoration: none;") span(aria-hidden="true") × div.card.shadow-sm.mb-3 div.card-body h3.h6.mb-0 Summary if (config.addressApi) small.text-muted.border-dotted.ml-2(title=`Some details for this address were queried from ${config.addressApi}` data-toggle="tooltip") Trust Note hr div.row div.col-md-6 if (addressObj.hash) div.row div.summary-split-table-label Hash 160 div.summary-split-table-content.text-monospace #{addressObj.hash.toString("hex")} if (result.validateaddress.scriptPubKey) div.row div.summary-split-table-label Script Public Key div.summary-split-table-content.text-monospace #{result.validateaddress.scriptPubKey} if (addressObj.hasOwnProperty("version")) div.row div.summary-split-table-label Version div.summary-split-table-content.text-monospace #{addressObj.version} if (result.validateaddress.hasOwnProperty("witness_version")) div.row div.summary-split-table-label Witness Version div.summary-split-table-content.text-monospace #{result.validateaddress.witness_version} if (result.validateaddress.witness_program) div.row div.summary-split-table-label Witness Program div.summary-split-table-content.text-monospace #{result.validateaddress.witness_program} if (firstSeenTransaction && firstSeenTransaction.confirmations > 0) div.row div.summary-split-table-label First Seen div.summary-split-table-content.text-monospace if (getblockchaininfo) span Block ##{(getblockchaininfo.blocks - firstSeenTransaction.confirmations).toLocaleString()} else a(href=("/block/" + firstSeenTransaction.blockhash)) #{firstSeenTransaction.blockhash} br span #{moment.utc(new Date(firstSeenTransaction.time * 1000)).format("Y-MM-DD HH:mm:ss")} utc - var timeAgoTime = firstSeenTransaction.time; include includes/time-ago.pug if (false) pre code.json.bg-light #{JSON.stringify(firstSeenTransaction)} if (balance) if (balance.conflictedResults) div.row div.summary-split-table-label Balance div.summary-split-table-content.text-monospace span.text-warning Conflicted ElectrumX Results each item in balance.conflictedResults - var currencyValue = item.confirmed / coinConfig.baseCurrencyUnit.multiplier; include includes/value-display.pug else div.row div.summary-split-table-label Balance div.summary-split-table-content.text-monospace - var currencyValue = balance.result.confirmed / coinConfig.baseCurrencyUnit.multiplier; include includes/value-display.pug if (balance.unconfirmed) div.row div.summary-split-table-label Unconfirmed div.summary-split-table-content.text-monospace - var currencyValue = balance.unconfirmed / coinConfig.baseCurrencyUnit.multiplier; include includes/value-display.pug if (addressDetails && addressDetails.balanceSat) div.row div.summary-split-table-label Balance div.summary-split-table-content.text-monospace - var currencyValue = new Decimal(addressDetails.balanceSat).dividedBy(coinConfig.baseCurrencyUnit.multiplier); include includes/value-display.pug if (addressDetails && addressDetails.txCount) div.row div.summary-split-table-label Transactions div.summary-split-table-content.text-monospace #{addressDetails.txCount.toLocaleString()} div.row div.summary-split-table-label QR Code div.summary-split-table-content.text-monospace img(src=addressQrCodeUrl, alt=address, style="border: solid 1px #ccc;") div.col-md-6 if (electrumScripthash) div.row div.summary-split-table-label Scripthash div.summary-split-table-content.text-monospace #{electrumScripthash} - var x = result.validateaddress; - var flagNames = ["Is Valid?", "Is Script?", "Is Witness?", "Is Mine?", "Is Watch-Only?"]; - var flags = [x.isvalid, x.isscript, x.iswitness, x.ismine, x.iswatchonly]; each flagName, index in flagNames div.row div.summary-split-table-label #{flagName} div.summary-split-table-content.text-monospace if (flags[index]) i.fas.fa-check.text-success else i.fas.fa-times.text-warning if (false) div.card.shadow-sm.mb-3 div.card-header span.h6 Flags div.card-body div.table-responsive table.table.text-center thead tr th Is Valid? th Is Script? th Is Witness? th Is Mine? th Is Watch-Only? tbody tr - var x = result.validateaddress; - var flags = [x.isvalid, x.isscript, x.iswitness, x.ismine, x.iswatchonly]; each flag in flags td if (flag) i.fas.fa-check.text-success else i.fas.fa-times.text-warning div.card.shadow-sm.mb-3 div.card-body div.clearfix div.float-left h3.h6.mb-0 if (addressDetails && addressDetails.txCount) if (addressDetails.txCount == 1) span 1 Transaction else span #{addressDetails.txCount.toLocaleString()} Transactions else span Transactions if (config.addressApi) if (config.addressApi == "electrumx") small.text-muted.border-dotted.ml-2(title=`The list of transaction IDs for this address was queried from ElectrumX (using the configured server(s))` data-toggle="tooltip") Trust Note else 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.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.dropdown-menu.dropdown-menu-right a.dropdown-item(href=("/address/" + address)) if (sort == "desc") i.fa.fa-check span Newest First a.dropdown-item(href=("/address/" + address + "?sort=asc")) if (sort != "desc") i.fa.fa-check span Oldest First else if (txids && txids.length > 1 && addressApiSupport.sortDesc && !addressApiSupport.sortAsc) div.float-right span.text-muted Newest First hr if (conflictedTxidResults) 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.font-weight-bold #{electrumHistory.server} if (true) if (addressApiError && addressApiError.error && addressApiError.error.code && addressApiError.error.code == -32600) span Failed to retrieve transaction history from ElectrumX. See a(href="https://github.com/janoside/btc-rpc-explorer/issues/67") Issue #67 span for more information. else if (addressApiError && addressApiError.userText) div.text-danger Error: #{addressApiError.userText} else if (addressDetailsErrors && addressDetailsErrors.length > 0) each err in addressDetailsErrors if (err.e && err.e.error && err.e.error.message == "history too large") span Failed to retrieve transaction history from ElectrumX. See a(href="https://github.com/janoside/btc-rpc-explorer/issues/67") Issue #67 span for more information. else if (err == "No address API configured") span No address API is configured. See a(href="https://github.com/janoside/btc-rpc-explorer/blob/master/.env-sample") the example configuration file span for help setting up an address API if desired. else if (transactions.length == 0) span No transactions found each tx, txIndex in transactions //pre // code.json.bg-light #{JSON.stringify(tx, null, 4)} div.card.shadow-sm(class=((txIndex < (transactions.length - 1) || txids.length > limit) ? "mb-3" : "")) div.card-header.text-monospace.clearfix div.float-left.mr-0 if (sort == "desc") span ##{(addressDetails.txCount - offset - txIndex).toLocaleString()} else span ##{(offset + txIndex + 1).toLocaleString()} span – div.row div.col-md-8 if (tx && tx.txid) a(href=("/tx/" + tx.txid)) #{tx.txid} if (global.specialTransactions && global.specialTransactions[tx.txid]) span a(data-toggle="tooltip", title=(coinConfig.name + " Fun! See transaction for details")) i.fas.fa-certificate.text-primary br if (addrGainsByTx[tx.txid]) - var currencyValue = addrGainsByTx[tx.txid]; span.text-success + include includes/value-display.pug if (addrLossesByTx[tx.txid]) span / if (addrLossesByTx[tx.txid]) - var currencyValue = addrLossesByTx[tx.txid]; span.text-danger - include includes/value-display.pug div.col-md-4 div.text-md-right if (tx.time) - var timestampHuman = tx.time; include includes/timestamp-human.pug br - var timeAgoTime = tx.time; small.text-muted ( include includes/time-ago-text.pug span ago) else span.text-danger Unconfirmed div.card-body if (true) - var txInputs = txInputsByTransaction[tx.txid]; - var blockHeight = blockHeightsByTxid[tx.txid]; - var txIOHighlightAddress = address; include includes/transaction-io-details.pug else p Since this explorer is database-free, it doesn't natively support address transaction history. However, you can configure it to communicate with one or more ElectrumX servers to build and display this data. In doing so, you should be aware that you'll be trusting those ElectrumX servers. If you configure multiple servers the results obtained from each will be cross-referenced against the others. Communicating with ElectrumX servers will also impact your privacy since the servers will know what addresses you're interested in. If these tradeoffs are acceptable, you can see a list of public ElectrumX servers here: a(href="https://uasf.saltylemon.org/electrum") https://uasf.saltylemon.org/electrum if (false) pre code.json.bg-light #{JSON.stringify(transactions, null, 4)} if (!crawlerBot && addressDetails && addressDetails.txCount > limit) - var txCount = addressDetails.txCount; - var pageNumber = offset / limit + 1; - var pageCount = Math.floor(txCount / limit); - if (pageCount * limit < txCount) { - pageCount++; - } - var paginationUrlFunction = function(x) { - return paginationBaseUrl + "&limit=" + limit + "&offset=" + ((x - 1) * limit); - } hr.mt-3 include includes/pagination.pug 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 div.highlight pre code.json.bg-light #{JSON.stringify(addressDetails, null, 4)}