Lots of improvements to value displays:

- use mixins instead of include
- new settings: displayCurrency and localCurrency that work in tandem to build value displays
- cleanup/simplify utils functions
- simpler/better options UI for currency settings
- most "value displays" use a default mixin "+valueDisplay" and a few special-case value displays use a new "+valueDisplaySpecial" to simplify happy-flow logic

And:

- move "fun" items into separate file (btc.js is getting ridiculous)
- new currencies.js file for global currency data
- tweak header nav styles
This commit is contained in:
Dan Janosik 2021-04-04 16:14:48 -04:00
parent c2d22f1c39
commit 8af6906e65
No known key found for this signature in database
GPG key ID: 846311D3D259BFF1
18 changed files with 804 additions and 628 deletions

16
app.js
View file

@ -51,6 +51,8 @@ const markdown = require("markdown-it")();
const v8 = require("v8");
const axios = require("axios");
require("./app/currencies.js");
const package_json = require('./package.json');
global.appVersion = package_json.version;
@ -620,9 +622,13 @@ expressApp.use(function(req, res, next) {
res.locals.userSettings = userSettings;
// currency format type
if (!userSettings.currencyFormatType) {
userSettings.currencyFormatType = "btc";
if (!userSettings.displayCurrency) {
userSettings.displayCurrency = "btc";
}
if (!userSettings.localCurrency) {
userSettings.localCurrency = "usd";
}
// theme
@ -631,8 +637,8 @@ expressApp.use(function(req, res, next) {
}
res.locals.currencyFormatType = userSettings.currencyFormatType;
global.currencyFormatType = userSettings.currencyFormatType;
res.locals.displayCurrency = userSettings.displayCurrency;
res.locals.localCurrency = userSettings.localCurrency;
if (!["/", "/connect"].includes(req.originalUrl)) {

View file

@ -3,6 +3,8 @@
const Decimal = require("decimal.js");
const Decimal8 = Decimal.clone({ precision:8, rounding:8 });
const btcFun = require("./btcFun.js");
var currencyUnits = [
{
type:"native",
@ -77,9 +79,6 @@ module.exports = {
"regtest":"Regtest Explorer",
"signet":"Signet Explorer",
},
siteDescriptionHtml:"<b>BTC Explorer</b> is <a href='https://github.com/janoside/btc-rpc-explorer). If you run your own [Bitcoin Full Node](https://bitcoin.org/en/full-node), **BTC Explorer** can easily run alongside it, communicating via RPC calls. See the project [ReadMe](https://github.com/janoside/btc-rpc-explorer) for a list of features and instructions for running.",
nodeTitle:"Bitcoin Full Node",
nodeUrl:"https://bitcoin.org/en/full-node",
demoSiteUrlsByNetwork: {
"main": "https://explorer.btc21.org",
"test": "https://testnet.btc21.org",
@ -413,386 +412,7 @@ module.exports = {
}
},
genesisCoinbaseOutputAddressScripthash:"8b01df4e368ea28f8dc0423bcf7a4923e3a12d307c875e47a0cfbf90b5c39161",
historicalData: [
{
type: "blockheight",
date: "2009-01-03",
chain: "main",
blockHeight: 0,
blockHash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
summary: "The Bitcoin Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the <b>Genesis Block</b>. This block was mined by Bitcoin's creator <b>Satoshi Nakamoto</b>.<br/>Read more here: <a href='https://en.bitcoin.it/wiki/Genesis_block'>bitcoin.it/wiki/Genesis_block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2009-01-03",
chain: "main",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the <b>coinbase transaction</b> of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
{
type: "tx",
date: "2009-10-12",
chain: "main",
txid: "7dff938918f07619abd38e4510890396b1cef4fbeca154fb7aafba8843295ea2",
blockHeight: 24835,
summary: "First bitcoin traded for fiat currency.",
alertBodyHtml: "In this first-known BTC-to-fiat transaction, 5,050 BTC were exchanged for 5.02 USD, at an effective exchange rate of ~0.001 USD/BTC.",
referenceUrl: "https://twitter.com/marttimalmi/status/423455561703624704"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP",
summary:"SHA1 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA1 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"35Snmmy3uhaer2gTboc81ayCip4m9DT4ko",
summary:"SHA256 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA256 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"3KyiQEGqqdb4nqfhUzGKN6KPhXmQsLNpay",
summary:"RIPEMD160 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a RIPEMD160 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"39VXyuoc6SXYKp9TcAhoiN1mb4ns6z3Yu6",
summary:"RIPEMD160(SHA256()) collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a RIPEMD160(SHA256()) collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"3DUQQvz4t57Jy7jxE86kyFcNpKtURNf1VW",
summary:"SHA256(SHA256()) collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA256(SHA256()) collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type: "blockheight",
date: "2017-08-24",
chain: "main",
blockHeight: 481824,
blockHash: "0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893",
summary: "First SegWit block.",
referenceUrl: "https://twitter.com/conio/status/900722226911219712"
},
{
type: "blockheight",
date: "2012-11-28",
chain: "main",
blockHeight: 210000,
blockHash: "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e",
summary: "First block of subsidy era #2 (25 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "tx",
date: "2015-07-07",
chain: "main",
txid: "bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08",
blockHeight: 364292,
summary: "The Megatransaction",
alertBodyHtml: "This transaction filled the entire 1MB block, mostly sweeping weak brainwallets. At the time, it needed 25 seconds to validate.",
referenceUrl: "https://rusty.ozlabs.org/?p=522"
},
{
type: "blockheight",
date: "2016-07-09",
chain: "main",
blockHeight: 420000,
blockHash: "000000000000000002cce816c0ab2c5c269cb081896b7dcb34b8422d6b74ffa1",
summary: "First block of subsidy era #3 (12.5 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "blockheight",
date: "2020-05-11",
chain: "main",
blockHeight: 630000,
blockHash: "000000000000000000024bead8df69990852c202db0e0097c1a12ea637d7e96d",
summary: "First block of subsidy era #4 (6.25 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "blockheight",
date: "2020-05-11",
chain: "main",
blockHeight: 629999,
blockHash: "0000000000000000000d656be18bb095db1b23bd797266b0ac3ba720b1962b1e",
summary: "'Times 09/Apr/2020 With $2.3T Injection, Fed's Plan Far Exceeds 2008 Rescue'",
alertBodyHtml: "With the coinbase message 'Times 09/Apr/2020 With $2.3T Injection, Fed's Plan Far Exceeds 2008 Rescue', this final block of subsidy era #3 (12.5 BTC) echoes the spiritual call-to-action of <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Satoshi's genesis block</a>.",
},
{
type: "tx",
date: "2017-08-24",
chain: "main",
txid: "8f907925d2ebe48765103e6845c06f1f2bb77c6adc1cc002865865eb5cfd5c1c",
blockHeight: 481824,
summary: "First SegWit transaction.",
referenceUrl: "https://twitter.com/KHS9NE/status/900553902923362304"
},
{
type: "tx",
date: "2014-06-16",
chain: "main",
txid: "143a3d7e7599557f9d63e7f224f34d33e9251b2c23c38f95631b3a54de53f024",
blockHeight: 306204,
summary: "Star Wars: A New Hope",
referenceUrl: ""
},
{
type: "tx",
date: "2010-05-22",
chain: "main",
txid: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
blockHeight: 57043,
summary: "The 'Bitcoin Pizza' transaction.",
alertBodyHtml: "This is the famous 'Bitcoin Pizza' transaction, one of the earliest 'real-world' transactions, in which 10,000 BTC was paid for 2 large pizzas worth ~41 USD (at an effective exchange rate of ~$0.04/BTC).",
referenceUrl: "https://bitcointalk.org/index.php?topic=137.0"
},
{
type: "tx",
date: "2011-05-18",
chain: "main",
txid: "5d80a29be1609db91658b401f85921a86ab4755969729b65257651bb9fd2c10d",
blockHeight: 124724,
summary: "Destroyed bitcoin.",
referenceUrl: "https://bitcointalk.org/index.php?topic=7253.msg184414#msg184414",
referenceUrl2: "https://www.reddit.com/r/Bitcoin/comments/7mhoks/til_in_2011_a_user_running_a_modified_mining/"
},
{
type: "blockheight",
date: "2009-01-12",
chain: "main",
blockHeight: 170,
blockHash: "00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee",
summary: "First block containing a (non-coinbase) transaction.",
alertBodyHtml: "This block comes 9 days after the genesis block and is the first to contain a transfer of bitcoin. Before this block all blocks contained only coinbase transactions, which mint new bitcoin.<br/>See transaction #1 (f4184fc…) below for more info.",
referenceUrl: "https://bitcointalk.org/index.php?topic=91806.msg1012234#msg1012234"
},
{
type: "tx",
date: "2009-01-12",
chain: "main",
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
blockHeight: 170,
summary: "The first transfer of bitcoin.",
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",
date: "2017-08-25",
chain: "main",
blockHeight: 481947,
blockHash: "00000000000000000139cb443e16442fcd07a4a0e0788dd045ee3cf268982016",
summary: "First block mined that was greater than 1MB.",
referenceUrl: "https://en.bit.news/bitfury-mined-first-segwit-block-size-1-mb/"
},
{
type: "blockheight",
date: "2018-01-20",
chain: "main",
blockHeight: 505225,
blockHash: "0000000000000000001bbb529c64ddf55edec8f4ebc0a0ccf1d3bb21c278bfa7",
summary: "First block mined that was greater than 2MB.",
referenceUrl: "https://twitter.com/BitGo/status/954998877920247808"
},
{
type: "tx",
date: "2017-12-30",
chain: "main",
txid: "9bf8853b3a823bbfa1e54017ae11a9e1f4d08a854dcce9f24e08114f2c921182",
blockHeight: 501726,
summary: "Block reward lost",
alertBodyHtml: "This coinbase transaction completely fails to collect the block's mining reward. 12.5 BTC were lost.",
referenceUrl: "https://bitcoin.stackexchange.com/a/67012/3397"
},
{
type:"address",
date:"2011-12-03",
chain: "main",
address:"1JryTePceSiWVpoNBU8SbwiT7J4ghzijzW",
summary:"Brainwallet address for 'Satoshi Nakamoto'",
referenceUrl:"https://twitter.com/MrHodl/status/1041448002005741568",
alertBodyHtml:"This address was generated from the SHA256 hash of 'Satoshi Nakamoto' as example of the 'brainwallet' concept."
},
{
type: "tx",
date: "2010-11-14",
chain: "main",
txid: "e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468",
blockHeight: 91880,
summary: "Duplicated coinbase transaction #1",
referenceUrl: "https://bitcoin.stackexchange.com/questions/38994/will-there-be-21-million-bitcoins-eventually/38998#38998",
alertBodyHtml: "This is one of 2 'duplicate coinbase' transactions. An early bitcoin bug (fixed by <a href='https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki'>BIP30</a>) allowed identical coinbase transactions - a newer duplicate would overwrite older copies. This transaction was the coinbase transaction for <a href='./block-height/91722'>Block #91,722</a> and, ~16 hours later, <a href='./block-height/91880'>Block #91,880</a>. The 50 BTC claimed as the coinbase for block 91,722 were also overwritten and lost."
},
{
type: "tx",
date: "2010-11-14",
chain: "main",
txid: "d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599",
blockHeight: 91842,
summary: "Duplicated coinbase transaction #2",
referenceUrl: "https://bitcoin.stackexchange.com/questions/38994/will-there-be-21-million-bitcoins-eventually/38998#38998",
alertBodyHtml: "This is one of 2 'duplicate coinbase' transactions. An early bitcoin bug (fixed by <a href='https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki'>BIP30</a>) allowed identical coinbase transactions - a newer duplicate would overwrite older copies. This transaction was the coinbase transaction for <a href='./block-height/91812'>Block #91,812</a> and, ~3 hours later, <a href='./block-height/91842'>Block #91,842</a>. The 50 BTC claimed as the coinbase for block 91,812 were also overwritten and lost."
},
{
type: "tx",
date: "2020-03-11",
chain: "main",
txid: "eeea72f5c9fe07178013eac84c3705443321d5453befd7591f52d22ac39b3963",
blockHeight: 621259,
summary: "500+ million USD transferred for < 1 USD fee (2020 prices)."
},
{
type: "tx",
date: "2020-05-20",
chain: "main",
txid: "cb1440c787d8a46977886405a34da89939e1b04907f567bf182ef27ce53a8d71",
blockHeight: 631058,
summary: "Very old coins (mined ~1 month after genesis) move unexpectedly, causing uproar",
alertBodyHtml: "On May 5, 2020, 50 BTC mined on Feb 9, 2009 (~1 month after Satoshi mined the Genesis block), moved unexpectedly after being dormant for 11+ years. Some observers wondered if they were coins from Satoshi's stash (they likely <a href='https://twitter.com/zackvoell/status/1263120133054255104'>were not</a>) and got excited.",
referenceUrl: "https://twitter.com/WhalePanda/status/1263120678380867586"
},
{
type: "address",
date: "2020-07-15",
chain: "main",
address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
summary: "July 2020 Twitter hack BTC address",
alertBodyHtml: "On July 15, 2020 a hack involving many prominent Twitter accounts, including Elon Musk's, Bill Gates', and Cash App's, scammed many people to send BTC to this address.",
referenceUrl: "https://twitter.com/lawmaster/status/1283694581926723585"
},
{
type: "tx",
date: "2011-11-16",
chain: "main",
txid: "29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf",
blockHeight: 153509,
summary: "The current largest output transaction.",
alertBodyHtml: "This transaction from November 2011 spends 11 UTXOs worth 50,000 BTC to create a single 550,000 BTC UTXO. This is currently the largest output transaction.",
referenceUrl: "https://blockchair.com/bitcoin/transactions?s=output_total(desc)#"
},
{
type: "tx",
date: "2013-04-06",
chain: "main",
txid: "54e48e5f5c656b26c3bca14a8c95aa583d07ebe84dde3b7dd4a78f4e4186e713",
blockHeight: 230009,
summary: "The Bitcoin whitepaper embedded in the Bitcoin blockchain.",
alertBodyHtml: "This transaction encodes the Bitcoin whitepaper PDF in 945 of its 947 outputs. You can view the PDF, decoded from data served by your own node here: <a href='./bitcoin-whitepaper'>bitcoin whitepaper</a>. Or read more about the technical details - ",
referenceUrl: "https://bitcoin.stackexchange.com/questions/35959/how-is-the-whitepaper-decoded-from-the-blockchain-tx-with-1000x-m-of-n-multisi"
},
{
type: "link",
date: "2021-01-31",
chain: "main",
address: "1Hf2CKoVDyPj7dNn3vgTeFMgDqVvbVNZQq",
url: "./address/1Hf2CKoVDyPj7dNn3vgTeFMgDqVvbVNZQq?sort=asc&limit=2&offset=11",
summary: "Transaction output values used to encode botnet command-and-control IP address",
alertBodyHtml: "Two of the transactions sent to this address encode the IP address of a botnet's command-and-control server. Using the censorship-resistant Bitcoin network to serve this data makes the botnet more resistant to takedown. The output value '6957' (in transaction <a href='./tx/35ef7fa5dd1e4d572279a74a83082bd3e77a0c3a468723b5def5d014ed634e84'>35ef7fa5dd…</a>) and the output value '36305' (in transaction <a href='./tx/3a1fcdea5495fb3a1aa410772860afd7841ba8830ffc0ab474d4d69458244e42'>3a1fcdea54…</a>) combine to encode the IPv4 address '209.141.45.27'.",
referenceUrl: "https://arstechnica.com/information-technology/2021/02/crooks-use-the-bitcoin-blockchain-to-protect-their-botnets-from-takedown/"
},
{
type: "blockheight",
date: "2013-03-24",
chain: "main",
blockHeight: 227835,
blockHash: "00000000000001aa077d7aa84c532a4d69bdbff519609d1da0835261b7a74eb6",
summary: "The last 'Version 1' block.",
alertBodyHtml: "This block was the last 'Version 1' block to be mined. <a href='https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki'>BIP-34</a> defined 'Version 2' blocks and the 'bip34' soft fork was officially locked in 96 blocks after this one, in block #<a href='./block-height/227931'>227,931</a>.",
referenceUrl: "https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki"
},
{
type: "tx",
date: "2013-11-05",
chain: "main",
txid: "d29c9c0e8e4d2a9790922af73f0b8d51f0bd4bb19940d9cf910ead8fbe85bc9b",
blockHeight: 268060,
summary: "Never gonna give you up...",
alertBodyHtml: "This transaction includes a 983-byte OP_RETURN output. Although the default max size for OP_RETURN data is often quoted as 80 bytes, the 80-byte limit is a non-consensus rule that can vary from node to node (and is only enforced at mempool-acceptance time).",
referenceUrl: "https://bitcoin.stackexchange.com/q/78572/3397"
},
{
type: "blockheight",
date: "2021-01-29",
chain: "main",
blockHeight: 668197,
blockHash: "000000000000000000023c31edf49adb2306d0db74e6f1f032ef76deaa7a464a",
summary: "In retrospect, it was inevitable",
alertBodyHtml: "Shortly before a $1B+ USD Tesla treasury investment into Bitcoin was announced, Elon Musk updated his Twitter profile to just say '#Bitcoin' and cryptically tweeted 'It was inevitable'. Miner 'yhc5t3p' with F2Pool immortalized the tweet soon after.",
referenceUrl: "https://twitter.com/elonmusk/status/1355068728128516101"
},
// testnet
{
type: "blockheight",
date: "2011-02-02",
chain: "test",
blockHeight: 0,
blockHash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
summary: "The Bitcoin (regtest) Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the 'Genesis Block'. You can read more about <a href='https://en.bitcoin.it/wiki/Genesis_block'>the genesis block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2011-02-02",
chain: "test",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the coinbase transaction of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
// regtest
{
type: "blockheight",
date: "2011-02-02",
chain: "regtest",
blockHeight: 0,
blockHash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206",
summary: "The Bitcoin (regtest) Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the 'Genesis Block'. You can read more about <a href='https://en.bitcoin.it/wiki/Genesis_block'>the genesis block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2011-02-02",
chain: "regtest",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the coinbase transaction of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
],
historicalData: btcFun.items,
exchangeRateData:{
jsonUrl:"https://api.coindesk.com/v1/bpi/currentprice.json",
responseBodySelectorFunction:function(responseBody) {

382
app/coins/btcFun.js Normal file
View file

@ -0,0 +1,382 @@
module.exports = {
items: [
{
type: "blockheight",
date: "2009-01-03",
chain: "main",
blockHeight: 0,
blockHash: "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
summary: "The Bitcoin Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the <b>Genesis Block</b>. This block was mined by Bitcoin's creator <b>Satoshi Nakamoto</b>.<br/>Read more here: <a href='https://en.bitcoin.it/wiki/Genesis_block'>bitcoin.it/wiki/Genesis_block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2009-01-03",
chain: "main",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the <b>coinbase transaction</b> of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
{
type: "tx",
date: "2009-10-12",
chain: "main",
txid: "7dff938918f07619abd38e4510890396b1cef4fbeca154fb7aafba8843295ea2",
blockHeight: 24835,
summary: "First bitcoin traded for fiat currency.",
alertBodyHtml: "In this first-known BTC-to-fiat transaction, 5,050 BTC were exchanged for 5.02 USD, at an effective exchange rate of ~0.001 USD/BTC.",
referenceUrl: "https://twitter.com/marttimalmi/status/423455561703624704"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"37k7toV1Nv4DfmQbmZ8KuZDQCYK9x5KpzP",
summary:"SHA1 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA1 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"35Snmmy3uhaer2gTboc81ayCip4m9DT4ko",
summary:"SHA256 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA256 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"3KyiQEGqqdb4nqfhUzGKN6KPhXmQsLNpay",
summary:"RIPEMD160 collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a RIPEMD160 collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"39VXyuoc6SXYKp9TcAhoiN1mb4ns6z3Yu6",
summary:"RIPEMD160(SHA256()) collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a RIPEMD160(SHA256()) collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type:"address",
date:"2013-09-13",
chain: "main",
address:"3DUQQvz4t57Jy7jxE86kyFcNpKtURNf1VW",
summary:"SHA256(SHA256()) collision bounty",
alertBodyHtml:"On September 13, 2013 a P2SH address was setup which allowed anyone who found a SHA256(SHA256()) collision to construct a transaction that could spend from this address.",
referenceUrl:"https://bitcointalk.org/index.php?topic=293382.0"
},
{
type: "blockheight",
date: "2017-08-24",
chain: "main",
blockHeight: 481824,
blockHash: "0000000000000000001c8018d9cb3b742ef25114f27563e3fc4a1902167f9893",
summary: "First SegWit block.",
referenceUrl: "https://twitter.com/conio/status/900722226911219712"
},
{
type: "blockheight",
date: "2012-11-28",
chain: "main",
blockHeight: 210000,
blockHash: "000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e",
summary: "First block of subsidy era #2 (25 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "tx",
date: "2015-07-07",
chain: "main",
txid: "bb41a757f405890fb0f5856228e23b715702d714d59bf2b1feb70d8b2b4e3e08",
blockHeight: 364292,
summary: "The Megatransaction",
alertBodyHtml: "This transaction filled the entire 1MB block, mostly sweeping weak brainwallets. At the time, it needed 25 seconds to validate.",
referenceUrl: "https://rusty.ozlabs.org/?p=522"
},
{
type: "blockheight",
date: "2016-07-09",
chain: "main",
blockHeight: 420000,
blockHash: "000000000000000002cce816c0ab2c5c269cb081896b7dcb34b8422d6b74ffa1",
summary: "First block of subsidy era #3 (12.5 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "blockheight",
date: "2020-05-11",
chain: "main",
blockHeight: 630000,
blockHash: "000000000000000000024bead8df69990852c202db0e0097c1a12ea637d7e96d",
summary: "First block of subsidy era #4 (6.25 BTC).",
referenceUrl: "https://github.com/bitcoin/bitcoin/blob/master/src/validation.cpp#L1240"
},
{
type: "blockheight",
date: "2020-05-11",
chain: "main",
blockHeight: 629999,
blockHash: "0000000000000000000d656be18bb095db1b23bd797266b0ac3ba720b1962b1e",
summary: "'Times 09/Apr/2020 With $2.3T Injection, Fed's Plan Far Exceeds 2008 Rescue'",
alertBodyHtml: "With the coinbase message 'Times 09/Apr/2020 With $2.3T Injection, Fed's Plan Far Exceeds 2008 Rescue', this final block of subsidy era #3 (12.5 BTC) echoes the spiritual call-to-action of <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Satoshi's genesis block</a>.",
},
{
type: "tx",
date: "2017-08-24",
chain: "main",
txid: "8f907925d2ebe48765103e6845c06f1f2bb77c6adc1cc002865865eb5cfd5c1c",
blockHeight: 481824,
summary: "First SegWit transaction.",
referenceUrl: "https://twitter.com/KHS9NE/status/900553902923362304"
},
{
type: "tx",
date: "2014-06-16",
chain: "main",
txid: "143a3d7e7599557f9d63e7f224f34d33e9251b2c23c38f95631b3a54de53f024",
blockHeight: 306204,
summary: "Star Wars: A New Hope",
referenceUrl: ""
},
{
type: "tx",
date: "2010-05-22",
chain: "main",
txid: "a1075db55d416d3ca199f55b6084e2115b9345e16c5cf302fc80e9d5fbf5d48d",
blockHeight: 57043,
summary: "The 'Bitcoin Pizza' transaction.",
alertBodyHtml: "This is the famous 'Bitcoin Pizza' transaction, one of the earliest 'real-world' transactions, in which 10,000 BTC was paid for 2 large pizzas worth ~41 USD (at an effective exchange rate of ~$0.04/BTC).",
referenceUrl: "https://bitcointalk.org/index.php?topic=137.0"
},
{
type: "tx",
date: "2011-05-18",
chain: "main",
txid: "5d80a29be1609db91658b401f85921a86ab4755969729b65257651bb9fd2c10d",
blockHeight: 124724,
summary: "Destroyed bitcoin.",
referenceUrl: "https://bitcointalk.org/index.php?topic=7253.msg184414#msg184414",
referenceUrl2: "https://www.reddit.com/r/Bitcoin/comments/7mhoks/til_in_2011_a_user_running_a_modified_mining/"
},
{
type: "blockheight",
date: "2009-01-12",
chain: "main",
blockHeight: 170,
blockHash: "00000000d1145790a8694403d4063f323d499e655c83426834d4ce2f8dd4a2ee",
summary: "First block containing a (non-coinbase) transaction.",
alertBodyHtml: "This block comes 9 days after the genesis block and is the first to contain a transfer of bitcoin. Before this block all blocks contained only coinbase transactions, which mint new bitcoin.<br/>See transaction #1 (f4184fc…) below for more info.",
referenceUrl: "https://bitcointalk.org/index.php?topic=91806.msg1012234#msg1012234"
},
{
type: "tx",
date: "2009-01-12",
chain: "main",
txid: "f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16",
blockHeight: 170,
summary: "The first transfer of bitcoin.",
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",
date: "2017-08-25",
chain: "main",
blockHeight: 481947,
blockHash: "00000000000000000139cb443e16442fcd07a4a0e0788dd045ee3cf268982016",
summary: "First block mined that was greater than 1MB.",
referenceUrl: "https://en.bit.news/bitfury-mined-first-segwit-block-size-1-mb/"
},
{
type: "blockheight",
date: "2018-01-20",
chain: "main",
blockHeight: 505225,
blockHash: "0000000000000000001bbb529c64ddf55edec8f4ebc0a0ccf1d3bb21c278bfa7",
summary: "First block mined that was greater than 2MB.",
referenceUrl: "https://twitter.com/BitGo/status/954998877920247808"
},
{
type: "tx",
date: "2017-12-30",
chain: "main",
txid: "9bf8853b3a823bbfa1e54017ae11a9e1f4d08a854dcce9f24e08114f2c921182",
blockHeight: 501726,
summary: "Block reward lost",
alertBodyHtml: "This coinbase transaction completely fails to collect the block's mining reward. 12.5 BTC were lost.",
referenceUrl: "https://bitcoin.stackexchange.com/a/67012/3397"
},
{
type:"address",
date:"2011-12-03",
chain: "main",
address:"1JryTePceSiWVpoNBU8SbwiT7J4ghzijzW",
summary:"Brainwallet address for 'Satoshi Nakamoto'",
referenceUrl:"https://twitter.com/MrHodl/status/1041448002005741568",
alertBodyHtml:"This address was generated from the SHA256 hash of 'Satoshi Nakamoto' as example of the 'brainwallet' concept."
},
{
type: "tx",
date: "2010-11-14",
chain: "main",
txid: "e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468",
blockHeight: 91880,
summary: "Duplicated coinbase transaction #1",
referenceUrl: "https://bitcoin.stackexchange.com/questions/38994/will-there-be-21-million-bitcoins-eventually/38998#38998",
alertBodyHtml: "This is one of 2 'duplicate coinbase' transactions. An early bitcoin bug (fixed by <a href='https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki'>BIP30</a>) allowed identical coinbase transactions - a newer duplicate would overwrite older copies. This transaction was the coinbase transaction for <a href='./block-height/91722'>Block #91,722</a> and, ~16 hours later, <a href='./block-height/91880'>Block #91,880</a>. The 50 BTC claimed as the coinbase for block 91,722 were also overwritten and lost."
},
{
type: "tx",
date: "2010-11-14",
chain: "main",
txid: "d5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599",
blockHeight: 91842,
summary: "Duplicated coinbase transaction #2",
referenceUrl: "https://bitcoin.stackexchange.com/questions/38994/will-there-be-21-million-bitcoins-eventually/38998#38998",
alertBodyHtml: "This is one of 2 'duplicate coinbase' transactions. An early bitcoin bug (fixed by <a href='https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki'>BIP30</a>) allowed identical coinbase transactions - a newer duplicate would overwrite older copies. This transaction was the coinbase transaction for <a href='./block-height/91812'>Block #91,812</a> and, ~3 hours later, <a href='./block-height/91842'>Block #91,842</a>. The 50 BTC claimed as the coinbase for block 91,812 were also overwritten and lost."
},
{
type: "tx",
date: "2020-03-11",
chain: "main",
txid: "eeea72f5c9fe07178013eac84c3705443321d5453befd7591f52d22ac39b3963",
blockHeight: 621259,
summary: "500+ million USD transferred for < 1 USD fee (2020 prices)."
},
{
type: "tx",
date: "2020-05-20",
chain: "main",
txid: "cb1440c787d8a46977886405a34da89939e1b04907f567bf182ef27ce53a8d71",
blockHeight: 631058,
summary: "Very old coins (mined ~1 month after genesis) move unexpectedly, causing uproar",
alertBodyHtml: "On May 5, 2020, 50 BTC mined on Feb 9, 2009 (~1 month after Satoshi mined the Genesis block), moved unexpectedly after being dormant for 11+ years. Some observers wondered if they were coins from Satoshi's stash (they likely <a href='https://twitter.com/zackvoell/status/1263120133054255104'>were not</a>) and got excited.",
referenceUrl: "https://twitter.com/WhalePanda/status/1263120678380867586"
},
{
type: "address",
date: "2020-07-15",
chain: "main",
address: "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
summary: "July 2020 Twitter hack BTC address",
alertBodyHtml: "On July 15, 2020 a hack involving many prominent Twitter accounts, including Elon Musk's, Bill Gates', and Cash App's, scammed many people to send BTC to this address.",
referenceUrl: "https://twitter.com/lawmaster/status/1283694581926723585"
},
{
type: "tx",
date: "2011-11-16",
chain: "main",
txid: "29a3efd3ef04f9153d47a990bd7b048a4b2d213daaa5fb8ed670fb85f13bdbcf",
blockHeight: 153509,
summary: "The current largest output transaction.",
alertBodyHtml: "This transaction from November 2011 spends 11 UTXOs worth 50,000 BTC to create a single 550,000 BTC UTXO. This is currently the largest output transaction.",
referenceUrl: "https://blockchair.com/bitcoin/transactions?s=output_total(desc)#"
},
{
type: "tx",
date: "2013-04-06",
chain: "main",
txid: "54e48e5f5c656b26c3bca14a8c95aa583d07ebe84dde3b7dd4a78f4e4186e713",
blockHeight: 230009,
summary: "The Bitcoin whitepaper embedded in the Bitcoin blockchain.",
alertBodyHtml: "This transaction encodes the Bitcoin whitepaper PDF in 945 of its 947 outputs. You can view the PDF, decoded from data served by your own node here: <a href='./bitcoin-whitepaper'>bitcoin whitepaper</a>. Or read more about the technical details - ",
referenceUrl: "https://bitcoin.stackexchange.com/questions/35959/how-is-the-whitepaper-decoded-from-the-blockchain-tx-with-1000x-m-of-n-multisi"
},
{
type: "link",
date: "2021-01-31",
chain: "main",
address: "1Hf2CKoVDyPj7dNn3vgTeFMgDqVvbVNZQq",
url: "./address/1Hf2CKoVDyPj7dNn3vgTeFMgDqVvbVNZQq?sort=asc&limit=2&offset=11",
summary: "Transaction output values used to encode botnet command-and-control IP address",
alertBodyHtml: "Two of the transactions sent to this address encode the IP address of a botnet's command-and-control server. Using the censorship-resistant Bitcoin network to serve this data makes the botnet more resistant to takedown. The output value '6957' (in transaction <a href='./tx/35ef7fa5dd1e4d572279a74a83082bd3e77a0c3a468723b5def5d014ed634e84'>35ef7fa5dd…</a>) and the output value '36305' (in transaction <a href='./tx/3a1fcdea5495fb3a1aa410772860afd7841ba8830ffc0ab474d4d69458244e42'>3a1fcdea54…</a>) combine to encode the IPv4 address '209.141.45.27'.",
referenceUrl: "https://arstechnica.com/information-technology/2021/02/crooks-use-the-bitcoin-blockchain-to-protect-their-botnets-from-takedown/"
},
{
type: "blockheight",
date: "2013-03-24",
chain: "main",
blockHeight: 227835,
blockHash: "00000000000001aa077d7aa84c532a4d69bdbff519609d1da0835261b7a74eb6",
summary: "The last 'Version 1' block.",
alertBodyHtml: "This block was the last 'Version 1' block to be mined. <a href='https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki'>BIP-34</a> defined 'Version 2' blocks and the 'bip34' soft fork was officially locked in 96 blocks after this one, in block #<a href='./block-height/227931'>227,931</a>.",
referenceUrl: "https://github.com/bitcoin/bips/blob/master/bip-0034.mediawiki"
},
{
type: "tx",
date: "2013-11-05",
chain: "main",
txid: "d29c9c0e8e4d2a9790922af73f0b8d51f0bd4bb19940d9cf910ead8fbe85bc9b",
blockHeight: 268060,
summary: "Never gonna give you up...",
alertBodyHtml: "This transaction includes a 983-byte OP_RETURN output. Although the default max size for OP_RETURN data is often quoted as 80 bytes, the 80-byte limit is a non-consensus rule that can vary from node to node (and is only enforced at mempool-acceptance time).",
referenceUrl: "https://bitcoin.stackexchange.com/q/78572/3397"
},
{
type: "blockheight",
date: "2021-01-29",
chain: "main",
blockHeight: 668197,
blockHash: "000000000000000000023c31edf49adb2306d0db74e6f1f032ef76deaa7a464a",
summary: "In retrospect, it was inevitable",
alertBodyHtml: "Shortly before a $1B+ USD Tesla treasury investment into Bitcoin was announced, Elon Musk updated his Twitter profile to just say '#Bitcoin' and cryptically tweeted 'It was inevitable'. Miner 'yhc5t3p' with F2Pool immortalized the tweet soon after.",
referenceUrl: "https://twitter.com/elonmusk/status/1355068728128516101"
},
// testnet
{
type: "blockheight",
date: "2011-02-02",
chain: "test",
blockHeight: 0,
blockHash: "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943",
summary: "The Bitcoin (regtest) Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the 'Genesis Block'. You can read more about <a href='https://en.bitcoin.it/wiki/Genesis_block'>the genesis block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2011-02-02",
chain: "test",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the coinbase transaction of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
// regtest
{
type: "blockheight",
date: "2011-02-02",
chain: "regtest",
blockHeight: 0,
blockHash: "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206",
summary: "The Bitcoin (regtest) Genesis Block.",
alertBodyHtml: "This is the first block in the Bitcoin blockchain, known as the 'Genesis Block'. You can read more about <a href='https://en.bitcoin.it/wiki/Genesis_block'>the genesis block</a>.",
referenceUrl: "https://en.bitcoin.it/wiki/Genesis_block"
},
{
type: "tx",
date: "2011-02-02",
chain: "regtest",
txid: "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
blockHeight: 0,
summary: "The coinbase transaction of the Genesis Block.",
alertBodyHtml: "This transaction doesn't really exist! This is the coinbase transaction of the <a href='./block/000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f'>Bitcoin Genesis Block</a>. For more background about this special-case transaction, you can read <a href='https://github.com/bitcoin/bitcoin/issues/3303'>this brief discussion</a> among some of the <a href='https://bitcoin.org'>Bitcoin</a> developers.",
referenceUrl: "https://github.com/bitcoin/bitcoin/issues/3303"
},
]
};

View file

@ -93,7 +93,7 @@ module.exports = {
privacyMode: (process.env.BTCEXP_PRIVACY_MODE.toLowerCase() == "true"),
slowDeviceMode: slowDeviceMode,
demoSite: (process.env.BTCEXP_DEMO.toLowerCase() == "true"),
queryExchangeRates: (process.env.BTCEXP_NO_RATES.toLowerCase() != "true"),
queryExchangeRates: (process.env.BTCEXP_NO_RATES.toLowerCase() != "true" && process.env.BTCEXP_PRIVACY_MODE.toLowerCase() != "true"),
noInmemoryRpcCache: (process.env.BTCEXP_NO_INMEMORY_RPC_CACHE.toLowerCase() == "true"),
rpcConcurrency: (process.env.BTCEXP_RPC_CONCURRENCY || 10),

48
app/currencies.js Normal file
View file

@ -0,0 +1,48 @@
global.currencyTypes = {
"btc": {
id: "btc",
type:"native",
name:"BTC",
multiplier:1,
default:true,
decimalPlaces:8
},
"sat": {
id: "sat",
type:"native",
name:"sat",
multiplier:100000000,
decimalPlaces:0
},
"usd": {
id: "usd",
type:"exchanged",
name:"USD",
multiplier:"usd",
decimalPlaces:2,
symbol:"$"
},
"eur": {
id: "eur",
type:"exchanged",
name:"EUR",
multiplier:"eur",
decimalPlaces:2,
symbol:"€"
},
"gbp": {
id: "gbp",
type:"exchanged",
name:"GBP",
multiplier:"gbp",
decimalPlaces:2,
symbol:"£"
},
};
global.currencySymbols = {
"btc": "₿",
"usd": "$",
"eur": "€",
"gbp": "£"
};

View file

@ -171,92 +171,76 @@ function getRandomString(length, chars) {
return result;
}
var formatCurrencyCache = {};
function getCurrencyFormatInfo(formatType) {
if (formatCurrencyCache[formatType] == null) {
for (var x = 0; x < coins[config.coin].currencyUnits.length; x++) {
var currencyUnit = coins[config.coin].currencyUnits[x];
for (var y = 0; y < currencyUnit.values.length; y++) {
var currencyUnitValue = currencyUnit.values[y];
if (currencyUnitValue == formatType) {
formatCurrencyCache[formatType] = currencyUnit;
}
}
}
}
if (formatCurrencyCache[formatType] != null) {
return formatCurrencyCache[formatType];
}
return null;
}
function formatCurrencyAmountWithForcedDecimalPlaces(amount, formatType, forcedDecimalPlaces) {
var formatInfo = getCurrencyFormatInfo(formatType);
if (formatInfo != null) {
var dec = new Decimal(amount);
formatType = formatType.toLowerCase();
var decimalPlaces = formatInfo.decimalPlaces;
//if (decimalPlaces == 0 && dec < 1) {
// decimalPlaces = 5;
//}
debugLog(`formatCurrencyAmountWithForcedDecimalPlaces(${amount}, ${formatType}, ${forcedDecimalPlaces})`);
var currencyType = global.currencyTypes[formatType];
if (currencyType == null) {
throw `Unknown currency type: ${formatType}`;
}
var dec = new Decimal(amount);
var decimalPlaces = currencyType.decimalPlaces;
//if (decimalPlaces == 0 && dec < 1) {
// decimalPlaces = 5;
//}
if (forcedDecimalPlaces >= 0) {
decimalPlaces = forcedDecimalPlaces;
}
if (currencyType.type == "native") {
dec = dec.times(currencyType.multiplier);
if (forcedDecimalPlaces >= 0) {
decimalPlaces = forcedDecimalPlaces;
}
// toFixed will keep trailing zeroes
var baseStr = addThousandsSeparators(dec.toFixed(decimalPlaces));
if (formatInfo.type == "native") {
dec = dec.times(formatInfo.multiplier);
return {val:baseStr, currencyUnit:currencyType.name, simpleVal:baseStr, intVal:parseInt(dec)};
if (forcedDecimalPlaces >= 0) {
// toFixed will keep trailing zeroes
var baseStr = addThousandsSeparators(dec.toFixed(decimalPlaces));
} else {
// toDP will strip trailing zeroes
var baseStr = addThousandsSeparators(dec.toDP(decimalPlaces));
return {val:baseStr, currencyUnit:formatInfo.name, simpleVal:baseStr};
var returnVal = {currencyUnit:currencyType.name, simpleVal:baseStr, intVal:parseInt(dec)};
// max digits in "val"
var maxValDigits = config.site.valueDisplayMaxLargeDigits;
if (baseStr.indexOf(".") == -1) {
returnVal.val = baseStr;
} else {
// toDP will strip trailing zeroes
var baseStr = addThousandsSeparators(dec.toDP(decimalPlaces));
if (baseStr.length - baseStr.indexOf(".") - 1 > maxValDigits) {
returnVal.val = baseStr.substring(0, baseStr.indexOf(".") + maxValDigits + 1);
returnVal.lessSignificantDigits = baseStr.substring(baseStr.indexOf(".") + maxValDigits + 1);
var returnVal = {currencyUnit:formatInfo.name, simpleVal:baseStr};
// max digits in "val"
var maxValDigits = config.site.valueDisplayMaxLargeDigits;
if (baseStr.indexOf(".") == -1) {
returnVal.val = baseStr;
} else {
if (baseStr.length - baseStr.indexOf(".") - 1 > maxValDigits) {
returnVal.val = baseStr.substring(0, baseStr.indexOf(".") + maxValDigits + 1);
returnVal.lessSignificantDigits = baseStr.substring(baseStr.indexOf(".") + maxValDigits + 1);
} else {
returnVal.val = baseStr;
}
returnVal.val = baseStr;
}
return returnVal;
}
} else if (formatInfo.type == "exchanged") {
if (global.exchangeRates != null && global.exchangeRates[formatInfo.multiplier] != null) {
dec = dec.times(global.exchangeRates[formatInfo.multiplier]);
var baseStr = addThousandsSeparators(dec.toDecimalPlaces(decimalPlaces));
return {val:baseStr, currencyUnit:formatInfo.name, simpleVal:baseStr};
} else {
return formatCurrencyAmountWithForcedDecimalPlaces(amount, coinConfig.defaultCurrencyUnit.name, forcedDecimalPlaces);
}
return returnVal;
}
} else if (currencyType.type == "exchanged") {
//console.log(JSON.stringify(global.exchangeRates) + " - " + currencyType.name);
if (global.exchangeRates != null && global.exchangeRates[currencyType.id] != null) {
dec = dec.times(global.exchangeRates[currencyType.id]);
var baseStr = addThousandsSeparators(dec.toDecimalPlaces(decimalPlaces));
return {val:baseStr, currencyUnit:currencyType.name, simpleVal:baseStr, intVal:parseInt(dec)};
} else {
return formatCurrencyAmountWithForcedDecimalPlaces(amount, coinConfig.defaultCurrencyUnit.name, forcedDecimalPlaces);
}
} else {
throw `Unknown currency type: ${currencyType.type}`;
}
return amount;
}
function formatCurrencyAmount(amount, formatType) {
@ -275,32 +259,11 @@ function addThousandsSeparators(x) {
return parts.join(".");
}
function formatValueInActiveCurrency(amount) {
if (global.currencyFormatType && global.exchangeRates[global.currencyFormatType.toLowerCase()]) {
return formatExchangedCurrency(amount, global.currencyFormatType);
function satoshisPerUnitOfLocalCurrency(localCurrency) {
if (global.exchangeRates != null) {
var exchangeType = localCurrency;
} else {
return formatExchangedCurrency(amount, "usd");
}
}
function formatValueInGoldOunces(amount) {
var currencyFormat = global.currencyFormatType.toLowerCase() || "usd";
if (global.exchangeRates[currencyFormat] && global.goldExchangeRates[currencyFormat]) {
return formatExchangedCurrency(amount, "au", false);
} else {
return formatExchangedCurrency(amount, "usd");
}
}
function satoshisPerUnitOfActiveCurrency() {
if (global.currencyFormatType != null && global.exchangeRates != null) {
var exchangeType = global.currencyFormatType.toLowerCase();
if (!global.exchangeRates[global.currencyFormatType.toLowerCase()]) {
if (!global.exchangeRates[localCurrency]) {
// if current display currency is a native unit, default to USD for exchange values
exchangeType = "usd";
}
@ -313,43 +276,30 @@ function satoshisPerUnitOfActiveCurrency() {
dec = one.dividedBy(dec);
var unitName = coins[config.coin].baseCurrencyUnit.name;
var formatInfo = getCurrencyFormatInfo(unitName);
var satCurrencyType = global.currencyTypes["sat"];
var localCurrencyType = global.currencyTypes[localCurrency];
// BTC/USD -> sat/USD
dec = dec.times(formatInfo.multiplier);
dec = dec.times(satCurrencyType.multiplier);
var exchangedAmt = parseInt(dec);
if (exchangeType == "eur") {
return {amt:addThousandsSeparators(exchangedAmt), unit:`${unitName}/€`};
} else {
return {amt:addThousandsSeparators(exchangedAmt), unit:`${unitName}/$`};
}
return {amt:addThousandsSeparators(exchangedAmt), unit:`sat/${localCurrencyType.symbol}`}
}
return null;
if (global.currencyFormatType) {
return formatExchangedCurrency(amount, global.currencyFormatType);
} else {
return formatExchangedCurrency(amount, "usd");
}
}
function formatExchangedCurrency(amount, exchangeType, includeUnit=true) {
function getExchangedCurrencyFormatData(amount, exchangeType, includeUnit=true) {
if (global.exchangeRates != null && global.exchangeRates[exchangeType.toLowerCase()] != null) {
var dec = new Decimal(amount);
dec = dec.times(global.exchangeRates[exchangeType.toLowerCase()]);
var exchangedAmt = parseFloat(Math.round(dec * 100) / 100).toFixed(2);
if (exchangeType == "eur") {
return (includeUnit ? "€" : "") + addThousandsSeparators(exchangedAmt);
} else {
return (includeUnit ? "$" : "") + addThousandsSeparators(exchangedAmt);
return {
symbol: global.currencySymbols[exchangeType],
value: addThousandsSeparators(exchangedAmt),
unit: exchangeType
}
} else if (exchangeType == "au") {
@ -358,7 +308,39 @@ function formatExchangedCurrency(amount, exchangeType, includeUnit=true) {
dec = dec.times(global.exchangeRates.usd).dividedBy(global.goldExchangeRates.usd);
var exchangedAmt = parseFloat(Math.round(dec * 100) / 100).toFixed(2);
return addThousandsSeparators(exchangedAmt) + (includeUnit ? "oz" : "");
return {
symbol: "AU",
value: addThousandsSeparators(exchangedAmt),
unit: "oz"
}
}
}
return "";
}
function formatExchangedCurrency(amount, exchangeType) {
if (global.exchangeRates != null && global.exchangeRates[exchangeType.toLowerCase()] != null) {
var dec = new Decimal(amount);
dec = dec.times(global.exchangeRates[exchangeType.toLowerCase()]);
var exchangedAmt = parseFloat(Math.round(dec * 100) / 100).toFixed(2);
return {
val: addThousandsSeparators(exchangedAmt),
symbol: global.currencyTypes[exchangeType].symbol,
unit: exchangeType
};
} else if (exchangeType == "au") {
if (global.exchangeRates != null && global.goldExchangeRates != null) {
var dec = new Decimal(amount);
dec = dec.times(global.exchangeRates.usd).dividedBy(global.goldExchangeRates.usd);
var exchangedAmt = parseFloat(Math.round(dec * 100) / 100).toFixed(2);
return {
val: addThousandsSeparators(exchangedAmt),
unit: "oz",
symbol: "AU"
};
}
}
@ -567,7 +549,7 @@ function estimatedSupply(height) {
}
function refreshExchangeRates() {
if (!config.queryExchangeRates || config.privacyMode) {
if (!config.queryExchangeRates) {
return;
}
@ -593,24 +575,32 @@ function refreshExchangeRates() {
}
if (coins[config.coin].goldExchangeRateData) {
request(coins[config.coin].goldExchangeRateData.jsonUrl, function(error, response, body) {
if (error == null && response && response.statusCode && response.statusCode == 200) {
var responseBody = JSON.parse(body);
if (process.env.NODE_ENV == "local") {
global.goldExchangeRates = {usd: 1731.2};
global.goldExchangeRatesUpdateTime = new Date();
var exchangeRates = coins[config.coin].goldExchangeRateData.responseBodySelectorFunction(responseBody);
if (exchangeRates != null) {
global.goldExchangeRates = exchangeRates;
global.goldExchangeRatesUpdateTime = new Date();
debugLog("Using DEBUG gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime);
debugLog("Using gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime);
} else {
request(coins[config.coin].goldExchangeRateData.jsonUrl, function(error, response, body) {
if (error == null && response && response.statusCode && response.statusCode == 200) {
var responseBody = JSON.parse(body);
var exchangeRates = coins[config.coin].goldExchangeRateData.responseBodySelectorFunction(responseBody);
if (exchangeRates != null) {
global.goldExchangeRates = exchangeRates;
global.goldExchangeRatesUpdateTime = new Date();
debugLog("Using gold exchange rates: " + JSON.stringify(global.goldExchangeRates) + " starting at " + global.goldExchangeRatesUpdateTime);
} else {
debugLog("Unable to get gold exchange rate data");
}
} else {
debugLog("Unable to get gold exchange rate data");
logError("34082yt78yewewe", {error:error, response:response, body:body});
}
} else {
logError("34082yt78yewewe", {error:error, response:response, body:body});
}
});
});
}
}
}
@ -696,16 +686,43 @@ function parseExponentStringDouble(val) {
}
function formatLargeNumber(n, decimalPlaces) {
for (var i = 0; i < exponentScales.length; i++) {
var item = exponentScales[i];
try {
for (var i = 0; i < exponentScales.length; i++) {
var item = exponentScales[i];
var fraction = new Decimal(n / item.val);
if (fraction >= 1) {
return [fraction.toDecimalPlaces(decimalPlaces), item];
var fraction = new Decimal(n / item.val);
if (fraction >= 1) {
return [fraction.toDP(decimalPlaces), item];
}
}
}
return [new Decimal(n).toDecimalPlaces(decimalPlaces), {}];
return [new Decimal(n).toDP(decimalPlaces), {}];
} catch (err) {
logError("ru92huefhew", err, { n:n, decimalPlaces:decimalPlaces });
throw err;
}
}
function formatLargeNumberSignificant(n, significantDigits) {
try {
for (var i = 0; i < exponentScales.length; i++) {
var item = exponentScales[i];
var fraction = new Decimal(n / item.val);
if (fraction >= 1) {
return [fraction.toDP(Math.max(0, significantDigits - `${Math.floor(fraction)}`.length)), item];
}
}
return [new Decimal(n).toDP(significantDigits), {}];
} catch (err) {
logError("38fhcdugdeogwe", err, { n:n, significantDigits:significantDigits });
throw err;
}
}
function rgbToHsl(r, g, b) {
@ -947,13 +964,11 @@ module.exports = {
splitArrayIntoChunks: splitArrayIntoChunks,
splitArrayIntoChunksByChunkCount: splitArrayIntoChunksByChunkCount,
getRandomString: getRandomString,
getCurrencyFormatInfo: getCurrencyFormatInfo,
formatCurrencyAmount: formatCurrencyAmount,
formatCurrencyAmountWithForcedDecimalPlaces: formatCurrencyAmountWithForcedDecimalPlaces,
formatExchangedCurrency: formatExchangedCurrency,
formatValueInActiveCurrency: formatValueInActiveCurrency,
formatValueInGoldOunces: formatValueInGoldOunces,
satoshisPerUnitOfActiveCurrency: satoshisPerUnitOfActiveCurrency,
getExchangedCurrencyFormatData: getExchangedCurrencyFormatData,
satoshisPerUnitOfLocalCurrency: satoshisPerUnitOfLocalCurrency,
addThousandsSeparators: addThousandsSeparators,
formatCurrencyAmountInSmallestUnits: formatCurrencyAmountInSmallestUnits,
seededRandom: seededRandom,
@ -965,6 +980,7 @@ module.exports = {
refreshExchangeRates: refreshExchangeRates,
parseExponentStringDouble: parseExponentStringDouble,
formatLargeNumber: formatLargeNumber,
formatLargeNumberSignificant: formatLargeNumberSignificant,
geoLocateIpAddresses: geoLocateIpAddresses,
getTxTotalInputOutputValues: getTxTotalInputOutputValues,
rgbToHsl: rgbToHsl,

View file

@ -70,6 +70,9 @@ $alert-padding-x: $spacer;
$alert-dismissible-padding-r: $alert-padding-x * 2.5;
$dropdown-min-width: 11rem;
code {
background-color: $body-bg !important;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -96,7 +96,7 @@ block content
+summaryItem("Balance")
span(class=(addressDetails.balanceSat > 0 ? "text-success" : false))
- var currencyValue = new Decimal(addressDetails.balanceSat).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include includes/value-display.pug
+valueDisplay(currencyValue)
if (addressDetails && addressDetails.unconfirmedBalanceSat)
+summaryItem("Unconfirmed Balance")
@ -107,24 +107,24 @@ block content
span -
- var currencyValue = new Decimal(Math.abs(addressDetails.unconfirmedBalanceSat)).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include includes/value-display.pug
+valueDisplay(currencyValue)
if (addressDetails && addressDetails.totalReceivedSat)
+summaryItem("Total Received / Sent")
span(class=(addressDetails.totalReceivedSat > 0 ? "text-success" : false))
if (addressDetails.totalReceivedSat)
span +
span.me-1 +
- var currencyValue = new Decimal(Math.abs(addressDetails.totalReceivedSat)).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include includes/value-display.pug
+valueDisplay(currencyValue)
br
span(class=(addressDetails.totalSentSat > 0 ? "text-danger" : false))
if (addressDetails.totalSentSat > 0)
span -
span.me-1 -
- var currencyValue = new Decimal(Math.abs(addressDetails.totalSentSat)).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include includes/value-display.pug
+valueDisplay(currencyValue)
if (flags.length > 0)
+summaryItem("Flags")

View file

@ -88,7 +88,8 @@ block content
if (result.blockstats.total_out)
- var currencyValue = new Decimal(result.blockstats.total_out).plus(new Decimal(result.blockstats.totalfee)).plus(new Decimal(result.blockstats.subsidy));
- currencyValue = currencyValue.dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include ./includes/value-display.pug
+valueDisplay(currencyValue)
else
span 0
@ -98,11 +99,11 @@ block content
+summaryItem("Total Fees")
if (result.blockstats.totalfee)
- var currencyValue = new Decimal(result.blockstats.totalfee).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include ./includes/value-display.pug
+valueDisplay(currencyValue)
else
- var currencyValue = new Decimal(result.getblock.totalFees);
include ./includes/value-display.pug
+valueDisplay(currencyValue)
if (result.blockstats.feerate_percentiles)
+summaryItem("Rate Percentiles", null, "sat/vB")
@ -137,7 +138,8 @@ block content
+summaryItem("Min / Max Values")
if (result.blockstats.minfee)
- var currencyValue = new Decimal(result.blockstats.minfee).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include ./includes/value-display.pug
+valueDisplay(currencyValue)
else
span 0
@ -145,7 +147,8 @@ block content
if (result.blockstats.maxfee)
- var currencyValue = new Decimal(result.blockstats.maxfee).dividedBy(coinConfig.baseCurrencyUnit.multiplier);
include ./includes/value-display.pug
+valueDisplay(currencyValue)
else
span 0

View file

@ -136,9 +136,20 @@
if (blockstatsByHeight)
td.font-monospace.text-end
if (blockstatsByHeight[block.height])
- var currencyValue = parseInt(new Decimal(blockstatsByHeight[block.height].total_out).plus(blockstatsByHeight[block.height].subsidy).plus(blockstatsByHeight[block.height].totalfee).dividedBy(coinConfig.baseCurrencyUnit.multiplier));
- var satValue = new Decimal(blockstatsByHeight[block.height].total_out).plus(blockstatsByHeight[block.height].subsidy).plus(blockstatsByHeight[block.height].totalfee);
- var currencyValue = parseInt(satValue.dividedBy(coinConfig.baseCurrencyUnit.multiplier));
- var currencyValueDecimals = 0;
include ./value-display.pug
if (userSettings.displayCurrency == "local")
+valueDisplaySpecial(currencyValue, 3, false, 1000000)
else if (userSettings.displayCurrency == "sat")
+valueDisplaySpecial(currencyValue, satValue > 1000000 ? 3 : 0, false, 1000000)
else
+valueDisplaySpecial(currencyValue, 0)
//+valueDisplaySpecial(currencyValue, 1, ["sat", "local"].includes(userSettings.displayCurrency))
if (block.totalFees == null)
- block.totalFees = Decimal(blockstatsByHeight[block.height].totalfee).dividedBy(coinConfig.baseCurrencyUnit.multiplier)
@ -164,10 +175,19 @@
span.border-dotted(title=`Value: ${feeEstimateVal}`, data-bs-toggle="tooltip") #{currencyValue}
td.font-monospace.text-end
if block.totalFees
if (block.totalFees)
- var currencyValue = new Decimal(block.totalFees);
- var currencyValueDecimals = 3;
include ./value-display.pug
if (userSettings.displayCurrency == "local")
+valueDisplaySpecial(block.totalFees, 0, false, 1000000)
else if (userSettings.displayCurrency == "sat")
+valueDisplaySpecial(block.totalFees, 3, false, 1000000)
else
+valueDisplaySpecial(block.totalFees, 4)
else
span(title="This data is unavailable due to blockchain pruning", data-bs-toggle="tooltip")
i.fas.fa-backspace.text-danger

View file

@ -12,41 +12,45 @@ if (exchangeRates)
- var colCount = 3 + (networkVolume ? 1 : 0) + (goldExchangeRates ? 1 : 0);
+summaryRow(colCount)
+summaryItem("Exchange Rate", `Source: ${new URL(coinConfig.exchangeRateData.jsonUrl).hostname}`)
span.text-success #{utils.formatValueInActiveCurrency(1.0)}
- var formatData = utils.formatExchangedCurrency(1.0, userSettings.localCurrency);
span.text-success
span.me-1 #{formatData.symbol}
| #{formatData.val}
+summaryItem("Sats Rate")
- var satsRateData = utils.satoshisPerUnitOfActiveCurrency();
- var satsRateData = utils.satoshisPerUnitOfLocalCurrency(userSettings.localCurrency);
span #{satsRateData.amt}
small #{satsRateData.unit}
+summaryItem("Market Cap")
- var supply = utils.estimatedSupply(getblockchaininfo.blocks);
- var activeCurrency = ["usd", "eur"].includes(global.currencyFormatType) ? global.currencyFormatType : "usd";
- var xxx = utils.formatLargeNumber(parseFloat(supply) * exchangeRates[activeCurrency], 3);
- var mcapData = utils.formatLargeNumber(parseFloat(supply) * global.exchangeRates[userSettings.localCurrency], 3);
if (activeCurrency == "eur")
span.me-1 €
else
span.me-1 $
span #{xxx[0]}
if (xxx[1].textDesc)
span #{xxx[1].textDesc}
span.me-1 #{global.currencyTypes[userSettings.localCurrency].symbol}
span #{mcapData[0]}
if (mcapData[1].textDesc)
span.ms-1 #{mcapData[1].textDesc}
else
span x 10
sup #{xxx[1].exponent}
sup #{mcapData[1].exponent}
// ["154.9",{"val":1000000000,"name":"giga","abbreviation":"G","exponent":"9"}]
if (goldExchangeRates)
if (global.goldExchangeRates["usd"] && global.exchangeRates["usd"])
// usd is the only bridge for our data sources
+summaryItem("Gold Rate", `Source: ${new URL(coinConfig.goldExchangeRateData.jsonUrl).hostname}`)
span.text-warning #{utils.formatValueInGoldOunces(1.0)}
small.ms-1.text-muted oz
- var formatData = utils.formatExchangedCurrency(1.0, "au");
span.text-warning #{formatData.val}
small.ms-1.text-muted #{formatData.unit}
if (networkVolume)
+summaryItem("24hr Volume", `Total output of all transactions over the last 24hrs (blocks: [#${networkVolume.d1.endBlock.toLocaleString()} - #${networkVolume.d1.startBlock.toLocaleString()}]).`)
- var currencyValue = parseInt(networkVolume.d1.amt);
- var currencyValueDecimals = 0;
include ./value-display.pug
+valueDisplaySpecial(networkVolume.d1.amt, userSettings.displayCurrency == "local" ? 4 : 0, ["sat", "local"].includes(userSettings.displayCurrency))

View file

@ -135,14 +135,14 @@ mixin txList(visibleTxs, txCount, limit, offset, inputsByTxid, options)
span.fw-light.ms-1 sat/vB
if (options.addrGainsByTxid && options.addrGainsByTxid[tx.txid])
- var currencyValue = options.addrGainsByTxid[tx.txid];
span.badge.bg-success.me-2 +
include ./value-display.pug
span.badge.bg-success.me-2
span.me-1 +
+valueDisplay(options.addrGainsByTxid[tx.txid])
if (options.addrLossesByTxid && options.addrLossesByTxid[tx.txid])
- var currencyValue = options.addrLossesByTxid[tx.txid];
span.badge.bg-danger.me-2 -
include ./value-display.pug
span.badge.bg-danger.me-2
span.me-1 -
+valueDisplay(options.addrLossesByTxid[tx.txid])
if (options.showDates)
+darkBadge
@ -198,6 +198,86 @@ mixin pageTab(name, defaultActive=false)
block
mixin valueDisplay(val)
if (val > 0)
- var localCurrencyDisplay = userSettings.displayCurrency == "local";
- var parts = utils.formatCurrencyAmount(val, localCurrencyDisplay ? userSettings.localCurrency : userSettings.displayCurrency);
//span #{JSON.stringify(parts)}
if (localCurrencyDisplay)
span.me-1 #{global.currencySymbols[userSettings.localCurrency]}
//| #{JSON.stringify(parts)}
span(class=(localCurrencyDisplay ? "border-dotted" : false), title=(localCurrencyDisplay ? `${utils.formatCurrencyAmount(val, coinConfig.defaultCurrencyUnit.name.toLowerCase()).simpleVal} BTC` : false), data-bs-toggle=(localCurrencyDisplay ? "tooltip" : false)) #{parts.val}
if (parts.lessSignificantDigits)
span.text-small.text-muted.ms-1 #{parts.lessSignificantDigits}
if (userSettings.displayCurrency != "local")
if (exchangeRates)
- var localCurFormatData = utils.getExchangedCurrencyFormatData(val, userSettings.localCurrency);
span.text-tiny.border-dotted.fw-light.ms-1(style="letter-spacing: -0.5px;", data-bs-toggle="tooltip", title=`<span class="me-tiny">${localCurFormatData.symbol}</span><span>${localCurFormatData.value}</span>`, data-bs-html="true") #{parts.currencyUnit}
else
span.text-tiny.fw-light.ms-1(style="letter-spacing: -0.5px;") #{parts.currencyUnit}
else if (userSettings.displayCurrency == "local")
else
span.font-monospace 0
mixin valueDisplaySpecial(val, maxDecimals=-1, summarizeAlways=false, summarizeMin=Infinity)
if (maxDecimals == -1 && summarizeAlways == false && summarizeMin == undefined)
+valueDisplay(val)
else
if (val > 0)
- var localCurrencyDisplay = userSettings.displayCurrency == "local";
if (maxDecimals > 0)
- var parts = utils.formatCurrencyAmountWithForcedDecimalPlaces(val, localCurrencyDisplay ? userSettings.localCurrency : userSettings.displayCurrency, maxDecimals);
else
- var parts = utils.formatCurrencyAmount(val, localCurrencyDisplay ? userSettings.localCurrency : userSettings.displayCurrency);
//span #{JSON.stringify(parts)}
if (localCurrencyDisplay)
span.me-1 #{global.currencySymbols[userSettings.localCurrency]}
//| #{JSON.stringify(parts)}
if (summarizeAlways || parts.intVal >= summarizeMin)
//span #{JSON.stringify(parts)}
- var largeNumberData = utils.formatLargeNumberSignificant(parts.intVal, maxDecimals >= 0 ? maxDecimals : 2);
//span #{JSON.stringify(largeNumberData)} #{parts.intVal}
span(class=(localCurrencyDisplay ? "border-dotted" : false), title=(localCurrencyDisplay ? `${utils.formatCurrencyAmount(val, coinConfig.defaultCurrencyUnit.name.toLowerCase()).simpleVal} BTC` : false), data-bs-toggle=(localCurrencyDisplay ? "tooltip" : false)) #{largeNumberData[0]} #{largeNumberData[1].textDesc}
else if (maxDecimals == 0)
span(class=(localCurrencyDisplay ? "border-dotted" : false), title=(localCurrencyDisplay ? `${utils.formatCurrencyAmount(val, coinConfig.defaultCurrencyUnit.name.toLowerCase()).simpleVal} BTC` : false), data-bs-toggle=(localCurrencyDisplay ? "tooltip" : false)) #{parts.intVal.toLocaleString()}
else if (maxDecimals > 0)
span(class=(localCurrencyDisplay ? "border-dotted" : false), title=(localCurrencyDisplay ? `${utils.formatCurrencyAmount(val, coinConfig.defaultCurrencyUnit.name.toLowerCase()).simpleVal} BTC` : false), data-bs-toggle=(localCurrencyDisplay ? "tooltip" : false)) #{parts.val}
else
span(class=(localCurrencyDisplay ? "border-dotted" : false), title=(localCurrencyDisplay ? `${utils.formatCurrencyAmount(val, coinConfig.defaultCurrencyUnit.name.toLowerCase()).simpleVal} BTC` : false), data-bs-toggle=(localCurrencyDisplay ? "tooltip" : false)) #{parts.val}
if (parts.lessSignificantDigits)
span.text-small.text-muted.ms-1 #{parts.lessSignificantDigits}
if (userSettings.displayCurrency != "local")
if (exchangeRates)
- var localCurFormatData = utils.getExchangedCurrencyFormatData(val, userSettings.localCurrency);
span.text-tiny.border-dotted.fw-light.ms-1(style="letter-spacing: -0.5px;", data-bs-toggle="tooltip", title=`<span class="me-tiny">${localCurFormatData.symbol}</span><span>${localCurFormatData.value}</span>`, data-bs-html="true") #{parts.currencyUnit}
else
span.text-tiny.fw-light.ms-1(style="letter-spacing: -0.5px;") #{parts.currencyUnit}
else if (userSettings.displayCurrency == "local")
else
span.font-monospace 0
mixin confirmations(confirmations, abbreviated=true)
if (confirmations < 6)
span.text-warning.border-dotted(title="Fewer than 6 confirmations is generally considered <b>unsettled</b> for high-value transactions because block <b>re-organizations</b> that could affect them have reasonable probability.", data-bs-toggle="tooltip", data-bs-html="true") #{confirmations.toLocaleString()}

View file

@ -111,13 +111,12 @@ div.row.font-monospace
span(class=(tx.vin.length == 1 ? "fw-bold" : false))
- var currencyValue = coinConfig.blockRewardFunction(blockHeight, activeBlockchain);
include ./value-display.pug
+valueDisplay(currencyValue)
else
if (vout && vout.value)
- var currencyValue = vout.value;
span(class=(tx.vin.length == 1 ? "fw-bold" : "fw-light"))
include ./value-display.pug
+valueDisplay(vout.value)
else if (!global.txindexAvailable)
span(title="This data is unavailable. Your node must have its transaction index (txindex) setting enabled to view it.", data-bs-toggle="tooltip")
@ -150,7 +149,7 @@ div.row.font-monospace
div.tx-io-value.mt-3.mt-md-0
- var currencyValue = new Decimal(totalIOValues.output).minus(new Decimal(totalIOValues.input));
include ./value-display.pug
+valueDisplay(currencyValue)
hr
if (totalIOValues.input && totalIOValues.input > 0 && tx.vin.length > 1)
@ -160,9 +159,8 @@ div.row.font-monospace
if (totalIOValues.input > 0)
span.d-block.d-md-none Total Input:
- var currencyValue = totalIOValues.input;
span.fw-bold
include ./value-display.pug
+valueDisplay(totalIOValues.input)
div.d-lg-none
@ -273,9 +271,8 @@ div.row.font-monospace
i.fas.fa-fire.text-danger.me-2
if (vout.value > 0)
- var currencyValue = vout.value;
span(class=(nonZeroVoutValueCount == 1 ? "fw-bold" : "fw-light"))
include ./value-display.pug
+valueDisplay(vout.value)
if (voutIndex < (tx.vout.length - 1) || nonZeroVoutValueCount > 1)
@ -294,7 +291,6 @@ div.row.font-monospace
span.d-block.d-md-none Total Output:
span.fw-bold
- var currencyValue = totalIOValues.output;
include ./value-display.pug
+valueDisplay(totalIOValues.output)

View file

@ -1,25 +1,3 @@
- var currencyFormatInfo = utils.getCurrencyFormatInfo(currencyFormatType);
include ./shared-mixins.pug
if (currencyValue > 0)
if (currencyValueDecimals)
- var parts = utils.formatCurrencyAmountWithForcedDecimalPlaces(currencyValue, currencyFormatType, currencyValueDecimals);
else
- var parts = utils.formatCurrencyAmount(currencyValue, currencyFormatType);
//span #{JSON.stringify(currencyFormatInfo)}
span.font-monospace #{parts.val}#{(currencyValueDecimals && currencyFormatInfo.type == "native" && currencyFormatInfo.multiplier <= 1000) ? "…" : ""}
if (parts.lessSignificantDigits)
span.font-monospace.text-small(style="margin-left: 2px;") #{parts.lessSignificantDigits}
if (currencyFormatInfo.type == "native")
if (exchangeRates)
small.border-dotted.ms-1(data-bs-toggle="tooltip", title=utils.formatExchangedCurrency(currencyValue, "usd")) #{parts.currencyUnit}
else
small.ms-1 #{parts.currencyUnit}
else if (currencyFormatInfo.type == "exchanged")
small.border-dotted.ms-1(data-bs-toggle="tooltip", title=`${utils.formatCurrencyAmount(currencyValue, coinConfig.defaultCurrencyUnit.name).simpleVal} BTC`) #{parts.currencyUnit}
else
span.font-monospace 0
+valueDisplay(currencyValue)

View file

@ -11,10 +11,10 @@ html(lang="en")
if (userSettings.uiTheme == "light")
link(rel="stylesheet", href="./style/light.css", integrity="sha384-0HMhvK5rDBDNS0ANsUY5iBfRF7xMjvTSKQx2re9alLxtYOplwKvMOh3anoGoGty9")
link(rel="stylesheet", href="./style/light.css", integrity="sha384-9DIN3gGc9Z3sDFJ6h5VtrGrNwdQPposuzMjOxOyPTRQsTRKHPfVyeDDr3Zmd2N3t")
else
link(rel="stylesheet", href="./style/dark.css", integrity="sha384-v5UpWLhdaBtBi2/2zEhWcICoskr5rv6y9V8l01yFnwVFtLqYXuoXGkKdY2VioqO7")
link(rel="stylesheet", href="./style/dark.css", integrity="sha384-zpNCUS1UwIhAXfQEbKJrdD5ru/NdNfhTQmOu/ajr5ypIJrHMKIY7CpqYNuWUeZED")
link(rel="icon", type="image/png", href=`./img/logo/${config.coin.toLowerCase()}.png`)
@ -66,9 +66,9 @@ html(lang="en")
if (config.demoSite && homepage)
li.nav-item.dropdown.me-2
a.nav-link.dropdown-toggle.bg-header-footer-highlight.rounded(href="javascript:void(0)", role="button", data-bs-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
span.fa-layers.fa-fw.me-1
i.fas.fa-circle.text-white(data-fa-transform="shrink-2")
i.fab.fa-bitcoin(style=`color: ${coinConfig.coinColorsByNetwork[activeBlockchain]}`)
span.fa-layers.fa-fw.me-2.ms-1
i.fas.fa-circle.fa-lg.text-white(data-fa-transform="shrink-2")
i.fab.fa-bitcoin.fa-lg(style=`color: ${coinConfig.coinColorsByNetwork[activeBlockchain]}`)
div.dropdown-menu.dropdown-menu-end.shadow(aria-label="Demo Sites")
span.dropdown-header Public Demo Sites
@ -85,8 +85,8 @@ html(lang="en")
if (config.siteTools)
li.nav-item.dropdown.me-2
a.nav-link.rounded.bg-header-footer-highlight.dropdown-toggle(href="javascript:void(0)", role="button", data-bs-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
i.fas.fa-tools.me-2
a.nav-link.rounded.bg-header-footer-highlight.text-white.dropdown-toggle(href="javascript:void(0)", role="button", data-bs-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
i.fas.fa-tools.me-2.ms-1
| Tools
div.dropdown-menu.dropdown-menu-end.shadow(aria-label="Tools Items")
span.dropdown-header Tools
@ -99,18 +99,39 @@ html(lang="en")
span #{item.name}
li.nav-item.dropdown.me-4
a.nav-link.rounded.bg-header-footer-highlight.dropdown-toggle(href="javascript:void(0)", id="navbarDropdown", role="button", data-bs-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
i.fas.fa-cog.me-1
div.dropdown-menu.dropdown-menu-end.shadow(aria-labelledby="navbarDropdown")
if (coinConfig.currencyUnits)
span.dropdown-header Currency Units
each item in coinConfig.currencyUnits
if (item.type == "native" || (config.queryExchangeRates && !config.privacyMode))
a.dropdown-item(href=`./changeSetting?name=currencyFormatType&value=${item.values[0]}`)
each valueName in item.values
if (currencyFormatType == valueName)
a.nav-link.rounded.bg-header-footer-highlight.text-white.dropdown-toggle(href="javascript:void(0)", id="navbarDropdown", role="button", data-bs-toggle="dropdown", aria-haspopup="true", aria-expanded="false")
i.fas.fa-cog.me-2.ms-1
.dropdown-menu.dropdown-menu-end.shadow(aria-labelledby="navbarDropdown")
span.dropdown-header Display Currency
- var items = ["BTC", "sat"];
if (config.queryExchangeRates)
- items.push("local");
.btn-group.ms-3
each item in items
if (userSettings.displayCurrency == item.toLowerCase())
span.btn.btn-primary.btn-sm #{item}
else
a.btn.btn-outline-primary.btn-sm(href=`./changeSetting?name=displayCurrency&value=${item.toLowerCase()}`) #{item}
if (config.queryExchangeRates)
hr.dropdown-divider.mt-3.mb-1
span.dropdown-header Local Currency
- var items = ["USD", "EUR", "GBP"];
each item in items
a.dropdown-item(href=`./changeSetting?name=localCurrency&value=${item.toLowerCase()}`)
.clearfix
.float-start
span #{item}
.float-end
if (userSettings.localCurrency == item.toLowerCase())
i.fas.fa-check
span #{item.name}

View file

@ -136,7 +136,7 @@ block content
+summaryItem("Fees Collected", "The aggregate fees collected by the miner that created this coinbase transaction.")
- var currencyValue = new Decimal(totalOutputValue).minus(totalInputValue);
include includes/value-display.pug
+valueDisplay(currencyValue)
else
+summaryItem("Fee Rate", null, "sat/vB")
@ -158,8 +158,7 @@ block content
else
- var feePaid = mempoolDetails ? new Decimal(mempoolDetails.entry.fees.base) : new Decimal(totalInputValue).minus(totalOutputValue);
- var currencyValue = feePaid;
include includes/value-display.pug
+valueDisplay(feePaid)
@ -195,7 +194,7 @@ block content
+summaryItem("Value Destroyed", "The miner of this transaction's block failed to collect this value. As a result, it is permanently lost.")
- var currencyValue = new Decimal(blockRewardMax).minus(totalOutputValue);
span.text-danger
include includes/value-display.pug
+valueDisplay(currencyValue)
if (tx.locktime > 0)
+summaryItem("Locktime")