From 3d53716f4366212ed7a51b49ce747584b13fd1ce Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Fri, 27 Oct 2017 03:25:34 -0230 Subject: [PATCH] Correct rendering of conversions when conversion rate is a token. (#2498) --- ui/app/components/token-cell.js | 28 +++++++++++++++----------- ui/app/components/tx-list-item.js | 33 ++++++++++++++++++++++++++++--- ui/app/conversion-util.js | 11 ++++++----- 3 files changed, 52 insertions(+), 20 deletions(-) diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 6bb42204e..f55e23f9e 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -6,7 +6,7 @@ const Identicon = require('./identicon') const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const selectors = require('../selectors') const actions = require('../actions') -const { conversionUtil } = require('../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const TokenMenuDropdown = require('./dropdowns/token-menu-dropdown.js') @@ -17,7 +17,7 @@ function mapStateToProps (state) { selectedTokenAddress: state.metamask.selectedTokenAddress, userAddress: selectors.getSelectedAddress(state), tokenExchangeRates: state.metamask.tokenExchangeRates, - ethToUSDRate: state.metamask.conversionRate, + conversionRate: state.metamask.conversionRate, sidebarOpen: state.appState.sidebarOpen, } } @@ -61,7 +61,7 @@ TokenCell.prototype.render = function () { setSelectedToken, selectedTokenAddress, tokenExchangeRates, - ethToUSDRate, + conversionRate, hideSidebar, sidebarOpen, currentCurrency, @@ -70,22 +70,26 @@ TokenCell.prototype.render = function () { const pair = `${symbol.toLowerCase()}_eth`; - let currentTokenToEthRate; + let currentTokenToFiatRate; let currentTokenInFiat; - let formattedUSD = '' + let formattedFiat = '' if (tokenExchangeRates[pair]) { - currentTokenToEthRate = tokenExchangeRates[pair].rate; + currentTokenToFiatRate = multiplyCurrencies( + tokenExchangeRates[pair].rate, + conversionRate + ) currentTokenInFiat = conversionUtil(string, { fromNumericBase: 'dec', fromCurrency: symbol, - toCurrency: 'USD', + toCurrency: currentCurrency.toUpperCase(), numberOfDecimals: 2, - conversionRate: currentTokenToEthRate, - ethToUSDRate, + conversionRate: currentTokenToFiatRate, }) - formattedUSD = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; + formattedFiat = `${currentTokenInFiat} ${currentCurrency.toUpperCase()}`; } + + const showFiat = Boolean(currentTokenInFiat) && currentCurrency.toUpperCase() !== symbol return ( h('div.token-list-item', { @@ -108,9 +112,9 @@ TokenCell.prototype.render = function () { h('h.token-list-item__balance-wrapper', null, [ h('h3.token-list-item__token-balance', `${string || 0} ${symbol}`), - h('div.token-list-item__fiat-amount', { + showFiat && h('div.token-list-item__fiat-amount', { style: {}, - }, formattedUSD), + }, formattedFiat), ]), h('i.fa.fa-ellipsis-h.fa-lg.token-list-item__ellipsis.cursor-pointer', { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 3bb9a2eda..84026700b 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -9,7 +9,7 @@ abiDecoder.addABI(abi) const prefixForNetwork = require('../../lib/etherscan-prefix-for-network') const Identicon = require('./identicon') -const { conversionUtil } = require('../conversion-util') +const { conversionUtil, multiplyCurrencies } = require('../conversion-util') const { getCurrentCurrency } = require('../selectors') @@ -19,6 +19,7 @@ function mapStateToProps (state) { return { tokens: state.metamask.tokens, currentCurrency: getCurrentCurrency(state), + tokenExchangeRates: state.metamask.tokenExchangeRates, } } @@ -88,6 +89,9 @@ TxListItem.prototype.getSendTokenTotal = function () { const { txParams = {}, tokens, + conversionRate, + tokenExchangeRates, + currentCurrency, } = this.props const toAddress = txParams.to @@ -95,12 +99,35 @@ TxListItem.prototype.getSendTokenTotal = function () { const { params = [] } = decodedData || {} const { value } = params[1] || {} const { decimals, symbol } = tokens.filter(({ address }) => address === toAddress)[0] || {} - const multiplier = Math.pow(10, Number(decimals || 0)) const total = Number(value / multiplier) + const pair = symbol && `${symbol.toLowerCase()}_eth`; + + let tokenToFiatRate + let totalInFiat + + if (tokenExchangeRates[pair]) { + tokenToFiatRate = multiplyCurrencies( + tokenExchangeRates[pair].rate, + conversionRate + ) + + totalInFiat = conversionUtil(total, { + fromNumericBase: 'dec', + toNumericBase: 'dec', + fromCurrency: symbol, + toCurrency: currentCurrency, + numberOfDecimals: 2, + conversionRate: tokenToFiatRate, + }) + } + + const showFiat = Boolean(totalInFiat) && currentCurrency.toUpperCase() !== symbol + return { total: `${total} ${symbol}`, + fiatTotal: showFiat && `${totalInFiat} ${currentCurrency.toUpperCase()}`, } } @@ -182,7 +209,7 @@ TxListItem.prototype.render = function () { }), }, total), - h('span.tx-list-fiat-value', fiatTotal), + fiatTotal && h('span.tx-list-fiat-value', fiatTotal), ]), ]), diff --git a/ui/app/conversion-util.js b/ui/app/conversion-util.js index 39215cf1b..cb715460f 100644 --- a/ui/app/conversion-util.js +++ b/ui/app/conversion-util.js @@ -13,7 +13,6 @@ * @param {string} [options.fromDenomination = 'WEI'] The denomination of the passed value * @param {number} [options.numberOfDecimals] The desired number of in the result * @param {number} [options.conversionRate] The rate to use to make the fromCurrency -> toCurrency conversion -* @param {number} [options.ethToUSDRate] If present, a second conversion - at ethToUSDRate - happens after conversionRate is applied. * @returns {(number | string | BN)} * * The utility passes value along with the options as a single object to the `converter` function. @@ -38,6 +37,7 @@ const BIG_NUMBER_GWEI_MULTIPLIER = new BigNumber('1000000000') const convert = R.invoker(1, 'times') const round = R.invoker(2, 'round')(R.__, BigNumber.ROUND_DOWN) const invertConversionRate = conversionRate => () => new BigNumber(1.0).div(conversionRate) +const decToBigNumberViaString = n => R.pipe(String, toBigNumber['dec']) // Setter Maps const toBigNumber = { @@ -95,12 +95,12 @@ const whenPropApplySetterMap = (prop, setterMap) => whenPredSetWithPropAndSetter // Conversion utility function const converter = R.pipe( + whenPredSetCRWithPropAndSetter(R.prop('conversionRate'), 'conversionRate', decToBigNumberViaString), whenPredSetCRWithPropAndSetter(R.prop('invertConversionRate'), 'conversionRate', invertConversionRate), whenPropApplySetterMap('fromNumericBase', toBigNumber), whenPropApplySetterMap('fromDenomination', toNormalizedDenomination), whenPredSetWithPropAndSetter(fromAndToCurrencyPropsNotEqual, 'conversionRate', convert), whenPropApplySetterMap('toDenomination', toSpecifiedDenomination), - whenPredSetWithPropAndSetter(R.prop('ethToUSDRate'), 'ethToUSDRate', convert), whenPredSetWithPropAndSetter(R.prop('numberOfDecimals'), 'numberOfDecimals', round), whenPropApplySetterMap('toNumericBase', baseChange), R.view(R.lensProp('value')) @@ -115,7 +115,6 @@ const conversionUtil = (value, { toDenomination, numberOfDecimals, conversionRate, - ethToUSDRate, invertConversionRate, }) => converter({ fromCurrency, @@ -126,7 +125,6 @@ const conversionUtil = (value, { toDenomination, numberOfDecimals, conversionRate, - ethToUSDRate, invertConversionRate, value: value || '0', }); @@ -152,7 +150,10 @@ const multiplyCurrencies = (a, b, options = {}) => { ...conversionOptions, } = options - const value = (new BigNumber(a, multiplicandBase)).times(b, multiplierBase); + const bigNumberA = new BigNumber(String(a), multiplicandBase) + const bigNumberB = new BigNumber(String(b), multiplierBase) + + const value = bigNumberA.times(bigNumberB); return converter({ value,