diff --git a/.gitignore b/.gitignore index e8ce5e7d53..20aa9132d7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # App artifacts /_build /apps/*/cover +/apps/*/logs /cover /db /deps @@ -15,8 +16,7 @@ erl_crash.dump npm-debug.log # Static artifacts -/apps/block_scout_web/assets/node_modules -/apps/explorer/node_modules +/apps/**/node_modules # Since we are building assets from assets/, # we ignore priv/static. You may want to comment @@ -30,7 +30,6 @@ npm-debug.log # secrets files as long as you replace their contents by environment # variables. /apps/*/config/*.secret.exs -/apps/*/cover/ # Wallaby screenshots screenshots/ diff --git a/apps/block_scout_web/assets/__tests__/lib/currency.js b/apps/block_scout_web/assets/__tests__/lib/currency.js index cf5ec22e50..3c79433416 100644 --- a/apps/block_scout_web/assets/__tests__/lib/currency.js +++ b/apps/block_scout_web/assets/__tests__/lib/currency.js @@ -1,7 +1,11 @@ import { formatUsdValue } from '../../js/lib/currency' test('formatUsdValue', () => { - expect(formatUsdValue(0.0000001)).toEqual('< $0.000001 USD') + window.localized = { + 'Less than': 'Less than' + } + expect(formatUsdValue(0)).toEqual('$0.000000 USD') + expect(formatUsdValue(0.0000001)).toEqual('Less than $0.000001 USD') expect(formatUsdValue(0.123456789)).toEqual('$0.123457 USD') expect(formatUsdValue(0.1234)).toEqual('$0.123400 USD') expect(formatUsdValue(1.23456789)).toEqual('$1.23 USD') diff --git a/apps/block_scout_web/assets/__tests__/pages/chain.js b/apps/block_scout_web/assets/__tests__/pages/chain.js index 36866ddaf0..dca639315b 100644 --- a/apps/block_scout_web/assets/__tests__/pages/chain.js +++ b/apps/block_scout_web/assets/__tests__/pages/chain.js @@ -40,7 +40,6 @@ test('RECEIVED_NEW_EXCHANGE_RATE', () => { msg: { exchangeRate: { availableSupply: 1000000, - usdValue: 1.23, marketCapUsd: 1230000 }, marketHistoryData: { data: 'some stuff' } @@ -50,7 +49,6 @@ test('RECEIVED_NEW_EXCHANGE_RATE', () => { expect(output.availableSupply).toEqual(1000000) expect(output.marketHistoryData).toEqual({ data: 'some stuff' }) - expect(output.usdExchangeRate).toEqual(1.23) expect(output.usdMarketCap).toEqual(1230000) }) diff --git a/apps/block_scout_web/assets/js/app.js b/apps/block_scout_web/assets/js/app.js index a8bd35b021..a01a3610b7 100644 --- a/apps/block_scout_web/assets/js/app.js +++ b/apps/block_scout_web/assets/js/app.js @@ -21,6 +21,7 @@ import 'bootstrap' import './locale' import './lib/clipboard_buttons' +import './lib/currency' import './lib/from_now' import './lib/loading_element' import './lib/market_history_chart' @@ -31,6 +32,7 @@ import './lib/pretty_json' import './lib/try_api' import './lib/token_balance_dropdown' import './lib/token_transfers_toggle' +import './lib/stop_propagation' import './pages/address' import './pages/block' diff --git a/apps/block_scout_web/assets/js/lib/currency.js b/apps/block_scout_web/assets/js/lib/currency.js index a2c76d9fb4..e8a4a4b065 100644 --- a/apps/block_scout_web/assets/js/lib/currency.js +++ b/apps/block_scout_web/assets/js/lib/currency.js @@ -1,8 +1,44 @@ +import $ from 'jquery' +import humps from 'humps' import numeral from 'numeral' +import { BigNumber } from 'bignumber.js' +import socket from '../socket' export function formatUsdValue (value) { - if (value < 0.000001) return '< $0.000001 USD' + if (value === 0) return '$0.000000 USD' + if (value < 0.000001) return `${window.localized['Less than']} $0.000001 USD` if (value < 1) return `$${numeral(value).format('0.000000')} USD` if (value < 100000) return `$${numeral(value).format('0,0.00')} USD` return `$${numeral(value).format('0,0')} USD` } + +function weiToEther (wei) { + return new BigNumber(wei).dividedBy('1000000000000000000').toNumber() +} + +function etherToUSD (ether, usdExchangeRate) { + return new BigNumber(ether).multipliedBy(usdExchangeRate).toNumber() +} + +function formatAllUsdValues () { + $('[data-usd-value]').each((i, el) => { + el.innerHTML = formatUsdValue(el.dataset.usdValue) + }) +} +formatAllUsdValues() + +function tryUpdateCalculatedUsdValues (el, usdExchangeRate = el.dataset.usdExchangeRate) { + if (!el.dataset.hasOwnProperty('weiValue')) return + const ether = weiToEther(el.dataset.weiValue) + const usd = etherToUSD(ether, usdExchangeRate) + const formattedUsd = formatUsdValue(usd) + if (formattedUsd !== el.innerHTML) el.innerHTML = formattedUsd +} +function updateAllCalculatedUsdValues (usdExchangeRate) { + $('[data-usd-exchange-rate]').each((i, el) => tryUpdateCalculatedUsdValues(el, usdExchangeRate)) +} +updateAllCalculatedUsdValues() + +export const exchangeRateChannel = socket.channel(`exchange_rate:new_rate`) +exchangeRateChannel.join() +exchangeRateChannel.on('new_rate', (msg) => updateAllCalculatedUsdValues(humps.camelizeKeys(msg).exchangeRate.usdValue)) diff --git a/apps/block_scout_web/assets/js/lib/market_history_chart.js b/apps/block_scout_web/assets/js/lib/market_history_chart.js index d130fc2c36..7cc6527fcf 100644 --- a/apps/block_scout_web/assets/js/lib/market_history_chart.js +++ b/apps/block_scout_web/assets/js/lib/market_history_chart.js @@ -1,6 +1,7 @@ import Chart from 'chart.js' import humps from 'humps' import numeral from 'numeral' +import { formatUsdValue } from '../lib/currency' import sassVariables from '../../css/app.scss' const config = { @@ -33,7 +34,7 @@ const config = { }, ticks: { beginAtZero: true, - callback: (value, index, values) => formatPrice(value), + callback: (value, index, values) => `$${numeral(value).format('0,0.00')}`, maxTicksLimit: 4 } }, { @@ -56,10 +57,10 @@ const config = { callbacks: { label: ({datasetIndex, yLabel}, {datasets}) => { const label = datasets[datasetIndex].label - if (datasets[datasetIndex].label === 'Price') { - return `${label}: ${formatPrice(yLabel)}` - } else if (datasets[datasetIndex].label === 'Market Cap') { - return `${label}: ${formatMarketCap(yLabel)}` + if (datasets[datasetIndex].yAxisID === 'price') { + return `${label}: ${formatUsdValue(yLabel)}` + } else if (datasets[datasetIndex].yAxisID === 'marketCap') { + return `${label}: ${formatUsdValue(yLabel)}` } else { return yLabel } @@ -69,14 +70,6 @@ const config = { } } -function formatPrice (price) { - return `$${numeral(price).format('0,0.00[0000000000000000]')}` -} - -function formatMarketCap (marketCap) { - return numeral(marketCap).format('($0,0a)') -} - function getPriceData (marketHistoryData) { return marketHistoryData.map(({ date, closingPrice }) => ({x: date, y: closingPrice})) } @@ -88,7 +81,7 @@ function getMarketCapData (marketHistoryData, availableSupply) { class MarketHistoryChart { constructor (el, availableSupply, marketHistoryData) { this.price = { - label: 'Price', + label: window.localized['Price'], yAxisID: 'price', data: getPriceData(marketHistoryData), fill: false, @@ -98,7 +91,7 @@ class MarketHistoryChart { lineTension: 0 } this.marketCap = { - label: 'Market Cap', + label: window.localized['Market Cap'], yAxisID: 'marketCap', data: getMarketCapData(marketHistoryData, availableSupply), fill: false, diff --git a/apps/block_scout_web/assets/js/lib/stop_propagation.js b/apps/block_scout_web/assets/js/lib/stop_propagation.js new file mode 100644 index 0000000000..c32fb6b049 --- /dev/null +++ b/apps/block_scout_web/assets/js/lib/stop_propagation.js @@ -0,0 +1,3 @@ +import $ from 'jquery' + +$('[data-selector="stop-propagation"]').click((event) => event.stopPropagation()) diff --git a/apps/block_scout_web/assets/js/pages/chain.js b/apps/block_scout_web/assets/js/pages/chain.js index eed9a1eb0d..43b2a2b464 100644 --- a/apps/block_scout_web/assets/js/pages/chain.js +++ b/apps/block_scout_web/assets/js/pages/chain.js @@ -4,7 +4,7 @@ import numeral from 'numeral' import router from '../router' import socket from '../socket' import { updateAllAges } from '../lib/from_now' -import { formatUsdValue } from '../lib/currency' +import { exchangeRateChannel, formatUsdValue } from '../lib/currency' import { batchChannel, initRedux } from '../utils' import { createMarketHistoryChart } from '../lib/market_history_chart' @@ -19,7 +19,6 @@ export const initialState = { newBlock: null, newTransactions: [], transactionCount: null, - usdExchangeRate: null, usdMarketCap: null } @@ -45,7 +44,6 @@ export function reducer (state = initialState, action) { return Object.assign({}, state, { availableSupply: action.msg.exchangeRate.availableSupply, marketHistoryData: action.msg.marketHistoryData, - usdExchangeRate: action.msg.exchangeRate.usdValue, usdMarketCap: action.msg.exchangeRate.marketCapUsd }) } @@ -85,8 +83,6 @@ router.when('', { exactPathMatch: true }).then(() => initRedux(reducer, { blocksChannel.join() blocksChannel.on('new_block', msg => store.dispatch({ type: 'RECEIVED_NEW_BLOCK', msg: humps.camelizeKeys(msg) })) - const exchangeRateChannel = socket.channel(`exchange_rate:new_rate`) - exchangeRateChannel.join() exchangeRateChannel.on('new_rate', (msg) => store.dispatch({ type: 'RECEIVED_NEW_EXCHANGE_RATE', msg: humps.camelizeKeys(msg) })) const transactionsChannel = socket.channel(`transactions:new_transaction`) @@ -103,7 +99,6 @@ router.when('', { exactPathMatch: true }).then(() => initRedux(reducer, { const $blockList = $('[data-selector="chain-block-list"]') const $channelBatching = $('[data-selector="channel-batching-message"]') const $channelBatchingCount = $('[data-selector="channel-batching-count"]') - const $exchangeRate = $('[data-selector="exchange-rate"]') const $marketCap = $('[data-selector="market-cap"]') const $transactionsList = $('[data-selector="transactions-list"]') const $transactionCount = $('[data-selector="transaction-count"]') @@ -114,9 +109,6 @@ router.when('', { exactPathMatch: true }).then(() => initRedux(reducer, { if (oldState.averageBlockTime !== state.averageBlockTime) { $averageBlockTime.empty().append(state.averageBlockTime) } - if (oldState.usdExchangeRate !== state.usdExchangeRate) { - $exchangeRate.empty().append(formatUsdValue(state.usdExchangeRate)) - } if (oldState.usdMarketCap !== state.usdMarketCap) { $marketCap.empty().append(formatUsdValue(state.usdMarketCap)) } diff --git a/apps/block_scout_web/assets/package-lock.json b/apps/block_scout_web/assets/package-lock.json index a44439f92e..caf95acc73 100644 --- a/apps/block_scout_web/assets/package-lock.json +++ b/apps/block_scout_web/assets/package-lock.json @@ -1448,6 +1448,11 @@ "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, + "bignumber.js": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz", + "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ==" + }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", diff --git a/apps/block_scout_web/assets/package.json b/apps/block_scout_web/assets/package.json index 49f60bba6d..f363ff1246 100644 --- a/apps/block_scout_web/assets/package.json +++ b/apps/block_scout_web/assets/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "@fortawesome/fontawesome-free": "^5.1.0-4", + "bignumber.js": "^7.2.1", "bootstrap": "^4.1.0", "chart.js": "^2.7.2", "clipboard": "^2.0.1", diff --git a/apps/block_scout_web/lib/block_scout_web/exchange_rates/usd.ex b/apps/block_scout_web/lib/block_scout_web/exchange_rates/usd.ex deleted file mode 100644 index 34b2a1f258..0000000000 --- a/apps/block_scout_web/lib/block_scout_web/exchange_rates/usd.ex +++ /dev/null @@ -1,42 +0,0 @@ -defmodule BlockScoutWeb.ExchangeRates.USD do - @moduledoc """ - Struct and associated conversion functions for USD currency - """ - - @typedoc """ - Represents USD currency - - * `:value` - value in USD - """ - @type t :: %__MODULE__{ - value: Decimal.t() | nil - } - - defstruct ~w(value)a - - alias Explorer.Chain.Wei - alias Explorer.ExchangeRates.Token - - def from(nil), do: null() - - def from(%Decimal{} = usd_decimal) do - %__MODULE__{value: usd_decimal} - end - - def from(nil, _), do: null() - - def from(_, nil), do: null() - - def from(%Wei{value: nil}, _), do: null() - - def from(_, %Token{usd_value: nil}), do: null() - - def from(%Wei{} = wei, %Token{usd_value: exchange_rate}) do - ether = Wei.to(wei, :ether) - %__MODULE__{value: Decimal.mult(ether, exchange_rate)} - end - - def null do - %__MODULE__{value: nil} - end -end diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex index 1c4c9bba4a..4ce0b0934b 100644 --- a/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex +++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_balance_card.html.eex @@ -4,9 +4,12 @@
- - <%= gettext("Fetching tokens...") %> -
- - -<%= raw query_params(@module_name, @action) %>