diff --git a/app.js b/app.js index 9b6cb39..cccff53 100755 --- a/app.js +++ b/app.js @@ -19,6 +19,7 @@ var pug = require("pug"); var momentDurationFormat = require("moment-duration-format"); var rpcApi = require("./app/rpcApi.js"); var coins = require("./app/coins.js"); +var request = require("request"); var baseActionsRouter = require('./routes/baseActionsRouter'); @@ -50,6 +51,41 @@ app.use(session({ app.use(express.static(path.join(__dirname, 'public'))); +function refreshExchangeRate() { + if (coins[env.coin].exchangeRateData) { + request(coins[env.coin].exchangeRateData.jsonUrl, function(error, response, body) { + if (!error && response.statusCode == 200) { + var responseBody = JSON.parse(body); + + var exchangeRate = coins[env.coin].exchangeRateData.responseBodySelectorFunction(responseBody); + if (exchangeRate > 0) { + global.exchangeRate = exchangeRate; + global.exchangeRateUpdateTime = new Date(); + + console.log("Using exchange rate: " + global.exchangeRate + " USD/" + coins[env.coin].name + " starting at " + global.exchangeRateUpdateTime); + + } else { + console.log("Unable to get exchange rate data"); + } + } else { + console.log("Error " + response.statusCode) + } + }); + } +} + + + +app.runOnStartup = function() { + if (global.exchangeRate == null) { + refreshExchangeRate(); + } + + // refresh exchange rate periodically + setInterval(refreshExchangeRate, 1800000); +}; + + app.locals.sourcecodeVersion = null; app.use(function(req, res, next) { diff --git a/app/coins/btc.js b/app/coins/btc.js index 2ad4e0a..fc83586 100644 --- a/app/coins/btc.js +++ b/app/coins/btc.js @@ -151,5 +151,16 @@ module.exports = { note: "First block mined that was greater than 1MB.", referenceUrl: "https://en.bit.news/bitfury-mined-first-segwit-block-size-1-mb/" } - ] + ], + exchangeRateData:{ + jsonUrl:"https://api.coinmarketcap.com/v1/ticker/Bitcoin/", + exchangedCurrencyName:"usd", + responseBodySelectorFunction:function(responseBody) { + if (responseBody[0] && responseBody[0].price_usd) { + return responseBody[0].price_usd; + } + + return -1; + } + } }; \ No newline at end of file diff --git a/app/coins/ltc.js b/app/coins/ltc.js index bd4cf32..dcf779a 100644 --- a/app/coins/ltc.js +++ b/app/coins/ltc.js @@ -71,5 +71,16 @@ module.exports = { note: "The Litecoin genesis block.", referenceUrl: "https://medium.com/@SatoshiLite/satoshilite-1e2dad89a017" } - ] + ], + exchangeRateData:{ + jsonUrl:"https://api.coinmarketcap.com/v1/ticker/Litecoin/", + exchangedCurrencyName:"usd", + responseBodySelectorFunction:function(responseBody) { + if (responseBody[0] && responseBody[0].price_usd) { + return responseBody[0].price_usd; + } + + return -1; + } + } }; \ No newline at end of file diff --git a/app/utils.js b/app/utils.js index 3cfd9f6..5716bde 100644 --- a/app/utils.js +++ b/app/utils.js @@ -144,6 +144,17 @@ function addThousandsSeparators(x) { return parts.join("."); } +function formatExchangedCurrency(amount) { + if (global.exchangeRate != null) { + var dec = new Decimal(amount); + dec = dec.times(global.exchangeRate); + + return addThousandsSeparators(dec.toDecimalPlaces(2)) + " " + coins[env.coin].exchangeRateData.exchangedCurrencyName; + } + + return ""; +} + module.exports = { doSmartRedirect: doSmartRedirect, @@ -154,4 +165,5 @@ module.exports = { getRandomString: getRandomString, formatBytes: formatBytes, formatCurrencyAmount: formatCurrencyAmount, + formatExchangedCurrency: formatExchangedCurrency }; diff --git a/bin/www b/bin/www index 52ced52..9f93c1b 100644 --- a/bin/www +++ b/bin/www @@ -5,5 +5,9 @@ var app = require('../app'); app.set('port', process.env.PORT || 3002); var server = app.listen(app.get('port'), function() { - debug('Express server listening on port ' + server.address().port); + debug('Express server listening on port ' + server.address().port); + + if (app.runOnStartup) { + app.runOnStartup(); + } }); diff --git a/views/includes/block-content.pug b/views/includes/block-content.pug index 5cbdf8b..6e3d01c 100644 --- a/views/includes/block-content.pug +++ b/views/includes/block-content.pug @@ -142,6 +142,10 @@ div(class="tab-content") span(class="tag monospace") coinbase span(class="monospace") Newly minted coins td(class="monospace") #{utils.formatCurrencyAmount(utils.getBlockReward(result.getblock.height), currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(utils.getBlockReward(result.getblock.height))) + i(class="fas fa-exchange-alt") each txInput, txInputIndex in result.txInputsByTransaction[tx.txid] if (txInput) @@ -161,6 +165,10 @@ div(class="tab-content") if (vout.value) - totalInputValue = totalInputValue.plus(new Decimal(vout.value)); span(class="monospace") #{utils.formatCurrencyAmount(vout.value, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(vout.value)) + i(class="fas fa-exchange-alt") - var coinbaseCount = tx.vin[0].coinbase ? 1 : 0; if ((tx.vin.length - coinbaseCount) > result.txInputsByTransaction[tx.txid].length) @@ -175,6 +183,10 @@ div(class="tab-content") td td strong(class="monospace") #{utils.formatCurrencyAmount(totalInputValue, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(totalInputValue)) + i(class="fas fa-exchange-alt") div(class="col-md-6") @@ -206,6 +218,11 @@ div(class="tab-content") span(class="monospace text-muted") #{utils.hex2ascii(vout.scriptPubKey.asm.substring("OP_RETURN ".length))} td span(class="monospace") #{utils.formatCurrencyAmount(vout.value, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(vout.value)) + i(class="fas fa-exchange-alt") + - totalOutputValue = totalOutputValue.plus(vout.value); tr @@ -213,6 +230,10 @@ div(class="tab-content") td td strong(class="monospace") #{utils.formatCurrencyAmount(totalOutputValue, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(totalOutputValue)) + i(class="fas fa-exchange-alt") //pre // code #{JSON.stringify(tx, null, 4)} diff --git a/views/transaction.pug b/views/transaction.pug index d5c1a21..d15fd09 100644 --- a/views/transaction.pug +++ b/views/transaction.pug @@ -116,12 +116,21 @@ block content if (result.getrawtransaction.vin[0].coinbase) tr th(class="table-active properties-header") Total Network Fees - td(class="monospace") #{utils.formatCurrencyAmount(new Decimal(totalOutputValue).minus(totalInputValue), currencyFormatType)} (#{global.exchangeRate}) + td(class="monospace") + span #{utils.formatCurrencyAmount(new Decimal(totalOutputValue).minus(totalInputValue), currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(new Decimal(totalOutputValue).minus(totalInputValue))) + i(class="fas fa-exchange-alt") else tr th(class="table-active properties-header") Network Fee Paid td(class="monospace") strong #{utils.formatCurrencyAmount(new Decimal(totalInputValue).minus(totalOutputValue), currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(new Decimal(totalInputValue).minus(totalOutputValue))) + i(class="fas fa-exchange-alt") span(class="text-muted") (#{utils.formatCurrencyAmount(totalInputValue, currencyFormatType)} - #{utils.formatCurrencyAmount(totalOutputValue, currencyFormatType)}) br span ~#{new DecimalRounded(totalInputValue).minus(totalOutputValue).dividedBy(result.getrawtransaction.size).times(100000000)} sat/B @@ -165,6 +174,10 @@ block content span(class="tag monospace") coinbase span(class="monospace") Newly minted coins td(class="monospace") #{utils.formatCurrencyAmount(utils.getBlockReward(result.getblock.height), currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(utils.getBlockReward(result.getblock.height))) + i(class="fas fa-exchange-alt") each txInput, txInputIndex in result.txInputs if (txInput) @@ -183,12 +196,20 @@ block content td if (vout.value) span(class="monospace") #{utils.formatCurrencyAmount(vout.value, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(vout.value)) + i(class="fas fa-exchange-alt") tr td td td strong(class="monospace") #{utils.formatCurrencyAmount(totalInputValue, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(totalInputValue)) + i(class="fas fa-exchange-alt") div(class="col-md-6") @@ -218,12 +239,20 @@ block content span(class="monospace text-muted") #{utils.hex2ascii(vout.scriptPubKey.asm.substring("OP_RETURN ".length))} td span(class="monospace") #{utils.formatCurrencyAmount(vout.value, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(vout.value)) + i(class="fas fa-exchange-alt") tr td td td strong(class="monospace") #{utils.formatCurrencyAmount(totalOutputValue, currencyFormatType)} + if (global.exchangeRate) + span + span(data-toggle="tooltip", title=utils.formatExchangedCurrency(totalOutputValue)) + i(class="fas fa-exchange-alt") div(id="tab-scripts", class="tab-pane", role="tabpanel") h3 Input Scripts