diff options
Merge branch 'master' into i3725-refactor-send-component
Diffstat (limited to 'ui/app')
46 files changed, 292 insertions, 196 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js index 4ac553812..674669eed 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -3,6 +3,7 @@ const getBuyEthUrl = require('../../app/scripts/lib/buy-eth-url') const { getTokenAddressFromTokenObject } = require('./util') const ethUtil = require('ethereumjs-util') const { fetchLocale } = require('../i18n-helper') +const log = require('loglevel') var actions = { _setBackgroundConnection: _setBackgroundConnection, @@ -222,8 +223,6 @@ var actions = { coinBaseSubview: coinBaseSubview, SHAPESHIFT_SUBVIEW: 'SHAPESHIFT_SUBVIEW', shapeShiftSubview: shapeShiftSubview, - UPDATE_TOKEN_EXCHANGE_RATE: 'UPDATE_TOKEN_EXCHANGE_RATE', - updateTokenExchangeRate, PAIR_UPDATE: 'PAIR_UPDATE', pairUpdate: pairUpdate, coinShiftRquest: coinShiftRquest, @@ -348,13 +347,11 @@ function transitionBackward () { } } -function confirmSeedWords () { +function clearSeedWordCache () { + log.debug(`background.clearSeedWordCache`) return dispatch => { - dispatch(actions.showLoadingIndication()) - log.debug(`background.clearSeedWordCache`) return new Promise((resolve, reject) => { background.clearSeedWordCache((err, account) => { - dispatch(actions.hideLoadingIndication()) if (err) { dispatch(actions.displayWarning(err.message)) return reject(err) @@ -368,6 +365,22 @@ function confirmSeedWords () { } } +function confirmSeedWords () { + return async dispatch => { + dispatch(actions.showLoadingIndication()) + const account = await dispatch(clearSeedWordCache()) + return dispatch(setIsRevealingSeedWords(false)) + .then(() => { + dispatch(actions.hideLoadingIndication()) + return account + }) + .catch(() => { + dispatch(actions.hideLoadingIndication()) + return account + }) + } +} + function createNewVaultAndRestore (password, seed) { return (dispatch) => { dispatch(actions.showLoadingIndication()) @@ -449,11 +462,13 @@ function requestRevealSeed (password) { } dispatch(actions.showNewVaultSeed(result)) - dispatch(actions.hideLoadingIndication()) resolve() }) }) }) + .then(() => dispatch(setIsRevealingSeedWords(true))) + .then(() => dispatch(actions.hideLoadingIndication())) + .catch(() => dispatch(actions.hideLoadingIndication())) } } @@ -1753,28 +1768,6 @@ function shapeShiftRequest (query, options, cb) { } } -function updateTokenExchangeRate (token = '') { - const pair = `${token.toLowerCase()}_eth` - - return dispatch => { - if (!token) { - return - } - - shapeShiftRequest('marketinfo', { pair }, marketinfo => { - if (!marketinfo.error) { - dispatch({ - type: actions.UPDATE_TOKEN_EXCHANGE_RATE, - payload: { - pair, - marketinfo, - }, - }) - } - }) - } -} - function setFeatureFlag (feature, activated, notificationType) { return (dispatch) => { dispatch(actions.showLoadingIndication()) @@ -1932,3 +1925,11 @@ function updateNetworkEndpointType (networkEndpointType) { value: networkEndpointType, } } + +function setIsRevealingSeedWords (reveal) { + return dispatch => { + log.debug(`background.setIsRevealingSeedWords`) + background.setIsRevealingSeedWords(reveal) + return forceUpdateMetamaskState(dispatch) + } +} diff --git a/ui/app/app.js b/ui/app/app.js index 75c3febb0..0b38b1326 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -6,6 +6,7 @@ const { compose } = require('recompose') const h = require('react-hyperscript') const actions = require('./actions') const classnames = require('classnames') +const log = require('loglevel') // init const InitializeScreen = require('../../mascara/src/app/first-time').default @@ -55,11 +56,20 @@ const { class App extends Component { componentWillMount () { - const { currentCurrency, setCurrentCurrencyToUSD } = this.props + const { + currentCurrency, + setCurrentCurrencyToUSD, + isRevealingSeedWords, + clearSeedWords, + } = this.props if (!currentCurrency) { setCurrentCurrencyToUSD() } + + if (isRevealingSeedWords) { + clearSeedWords() + } } renderRoutes () { @@ -136,8 +146,6 @@ class App extends Component { loadingMessage: loadMessage, }), - // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), - // content this.renderRoutes(), ]) @@ -301,17 +309,6 @@ class App extends Component { ) } - renderLoadingIndicator ({ isLoading, isLoadingNetwork, loadMessage }) { - const { isMascara } = this.props - - return isMascara - ? null - : h(Loading, { - isLoading: isLoading || isLoadingNetwork, - loadingMessage: loadMessage, - }) - } - toggleMetamaskActive () { if (!this.props.isUnlocked) { // currently inactive: redirect to password box @@ -405,6 +402,8 @@ App.propTypes = { isMouseUser: PropTypes.bool, setMouseUserState: PropTypes.func, t: PropTypes.func, + isRevealingSeedWords: PropTypes.bool, + clearSeedWords: PropTypes.func, } function mapStateToProps (state) { @@ -485,6 +484,7 @@ function mapDispatchToProps (dispatch, ownProps) { setCurrentCurrencyToUSD: () => dispatch(actions.setCurrentCurrency('usd')), toggleAccountMenu: () => dispatch(actions.toggleAccountMenu()), setMouseUserState: (isMouseUser) => dispatch(actions.setMouseUserState(isMouseUser)), + clearSeedWords: () => dispatch(actions.confirmSeedWords()), } } diff --git a/ui/app/components/account-dropdowns.js b/ui/app/components/account-dropdowns.js index 03955e077..043008a36 100644 --- a/ui/app/components/account-dropdowns.js +++ b/ui/app/components/account-dropdowns.js @@ -7,8 +7,8 @@ const connect = require('react-redux').connect const Dropdown = require('./dropdown').Dropdown const DropdownMenuItem = require('./dropdown').DropdownMenuItem const Identicon = require('./identicon') -const ethUtil = require('ethereumjs-util') const copyToClipboard = require('copy-to-clipboard') +const { checksumAddress } = require('../util') class AccountDropdowns extends Component { constructor (props) { @@ -212,8 +212,7 @@ class AccountDropdowns extends Component { closeMenu: () => {}, onClick: () => { const { selected } = this.props - const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) - copyToClipboard(checkSumAddress) + copyToClipboard(checksumAddress(selected)) }, }, this.context.t('copyAddress'), diff --git a/ui/app/components/balance-component.js b/ui/app/components/balance-component.js index d591ab455..e31552f2d 100644 --- a/ui/app/components/balance-component.js +++ b/ui/app/components/balance-component.js @@ -4,6 +4,8 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const TokenBalance = require('./token-balance') const Identicon = require('./identicon') +const currencyFormatter = require('currency-formatter') +const currencies = require('currency-formatter/currencies') const { formatBalance, generateBalanceObject } = require('../util') @@ -97,9 +99,17 @@ BalanceComponent.prototype.renderFiatAmount = function (fiatDisplayNumber, fiatS const shouldNotRenderFiat = fiatDisplayNumber === 'N/A' || Number(fiatDisplayNumber) === 0 if (shouldNotRenderFiat) return null + const upperCaseFiatSuffix = fiatSuffix.toUpperCase() + + const display = currencies.find(currency => currency.code === upperCaseFiatSuffix) + ? currencyFormatter.format(Number(fiatDisplayNumber), { + code: upperCaseFiatSuffix, + }) + : `${fiatPrefix}${fiatDisplayNumber} ${upperCaseFiatSuffix}` + return h('div.fiat-amount', { style: {}, - }, `${fiatPrefix}${fiatDisplayNumber} ${fiatSuffix}`) + }, display) } BalanceComponent.prototype.getTokenBalance = function (formattedBalance, shorten) { @@ -117,5 +127,9 @@ BalanceComponent.prototype.getFiatDisplayNumber = function (formattedBalance, co const splitBalance = formattedBalance.split(' ') - return (Number(splitBalance[0]) * conversionRate).toFixed(2) + const convertedNumber = (Number(splitBalance[0]) * conversionRate) + const wholePart = Math.floor(convertedNumber) + const decimalPart = convertedNumber - wholePart + + return wholePart + Number(decimalPart.toPrecision(2)) } diff --git a/ui/app/components/buy-button-subview.js b/ui/app/components/buy-button-subview.js index 9ac565cf4..fda7c3e17 100644 --- a/ui/app/components/buy-button-subview.js +++ b/ui/app/components/buy-button-subview.js @@ -9,7 +9,7 @@ const ShapeshiftForm = require('./shapeshift-form') const Loading = require('./loading') const AccountPanel = require('./account-panel') const RadioList = require('./custom-radio-list') -const networkNames = require('../../../app/scripts/config.js').networkNames +const { getNetworkDisplayName } = require('../../../app/scripts/controllers/network/util') BuyButtonSubview.contextTypes = { t: PropTypes.func, @@ -148,7 +148,7 @@ BuyButtonSubview.prototype.primarySubview = function () { case '3': case '4': case '42': - const networkName = networkNames[network] + const networkName = getNetworkDisplayName(network) const label = `${networkName} ${this.context.t('testFaucet')}` return ( h('div.flex-column', { diff --git a/ui/app/components/dropdowns/components/account-dropdowns.js b/ui/app/components/dropdowns/components/account-dropdowns.js index a133f0e29..179b6617f 100644 --- a/ui/app/components/dropdowns/components/account-dropdowns.js +++ b/ui/app/components/dropdowns/components/account-dropdowns.js @@ -7,7 +7,7 @@ const connect = require('react-redux').connect const Dropdown = require('./dropdown').Dropdown const DropdownMenuItem = require('./dropdown').DropdownMenuItem const Identicon = require('../../identicon') -const ethUtil = require('ethereumjs-util') +const { checksumAddress } = require('../../../util') const copyToClipboard = require('copy-to-clipboard') const { formatBalance } = require('../../../util') @@ -311,8 +311,7 @@ class AccountDropdowns extends Component { closeMenu: () => {}, onClick: () => { const { selected } = this.props - const checkSumAddress = selected && ethUtil.toChecksumAddress(selected) - copyToClipboard(checkSumAddress) + copyToClipboard(checksumAddress(selected)) }, style: Object.assign( dropdownMenuItemStyle, diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 9e47f38ef..dcd6b4370 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -3,12 +3,14 @@ const PropTypes = require('prop-types') const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect +const { withRouter } = require('react-router-dom') +const { compose } = require('recompose') const actions = require('../../actions') const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const NetworkDropdownIcon = require('./components/network-dropdown-icon') const R = require('ramda') - +const { SETTINGS_ROUTE } = require('../../routes') // classes from nodes of the toggle element. const notToggleElementClassnames = [ @@ -41,9 +43,6 @@ function mapDispatchToProps (dispatch) { setRpcTarget: (target) => { dispatch(actions.setRpcTarget(target)) }, - showConfigPage: () => { - dispatch(actions.showConfigPage()) - }, showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), } @@ -59,7 +58,10 @@ NetworkDropdown.contextTypes = { t: PropTypes.func, } -module.exports = connect(mapStateToProps, mapDispatchToProps)(NetworkDropdown) +module.exports = compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(NetworkDropdown) // TODO: specify default props and proptypes @@ -227,7 +229,7 @@ NetworkDropdown.prototype.render = function () { DropdownMenuItem, { closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.props.showConfigPage(), + onClick: () => this.props.history.push(SETTINGS_ROUTE), style: dropdownMenuItemStyle, }, [ diff --git a/ui/app/components/ens-input.js b/ui/app/components/ens-input.js index feb0a7037..aff4b6ef6 100644 --- a/ui/app/components/ens-input.js +++ b/ui/app/components/ens-input.js @@ -11,6 +11,7 @@ const ensRE = /.+\..+$/ const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000' const connect = require('react-redux').connect const ToAutoComplete = require('./send/to-autocomplete') +const log = require('loglevel') EnsInput.contextTypes = { t: PropTypes.func, diff --git a/ui/app/components/loading.js b/ui/app/components/loading.js index cb6fa51fb..b9afc550f 100644 --- a/ui/app/components/loading.js +++ b/ui/app/components/loading.js @@ -1,6 +1,7 @@ const { Component } = require('react') const h = require('react-hyperscript') const PropTypes = require('prop-types') +const classnames = require('classnames') class LoadingIndicator extends Component { renderMessage () { @@ -10,14 +11,16 @@ class LoadingIndicator extends Component { render () { return ( - h('.full-flex-height.loading-overlay', {}, [ - h('img', { - src: 'images/loading.svg', - }), + h('.loading-overlay', { + className: classnames({ 'loading-overlay--full-screen': this.props.fullScreen }), + }, [ + h('.flex-center.flex-column', [ + h('img', { + src: 'images/loading.svg', + }), - h('br'), - - this.renderMessage(), + this.renderMessage(), + ]), ]) ) } @@ -25,6 +28,7 @@ class LoadingIndicator extends Component { LoadingIndicator.propTypes = { loadingMessage: PropTypes.string, + fullScreen: PropTypes.bool, } module.exports = LoadingIndicator diff --git a/ui/app/components/modals/buy-options-modal.js b/ui/app/components/modals/buy-options-modal.js index d871e7516..c70510b5f 100644 --- a/ui/app/components/modals/buy-options-modal.js +++ b/ui/app/components/modals/buy-options-modal.js @@ -4,7 +4,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') -const networkNames = require('../../../../app/scripts/config.js').networkNames +const { getNetworkDisplayName } = require('../../../../app/scripts/controllers/network/util') function mapStateToProps (state) { return { @@ -52,7 +52,7 @@ BuyOptions.prototype.renderModalContentOption = function (title, header, onClick BuyOptions.prototype.render = function () { const { network, toCoinbase, address, toFaucet } = this.props const isTestNetwork = ['3', '4', '42'].find(n => n === network) - const networkName = networkNames[network] + const networkName = getNetworkDisplayName(network) return h('div', {}, [ h('div.buy-modal-content.transfers-subview', { diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index 0dc611f50..ad5f9b695 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -4,7 +4,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../actions') -const networkNames = require('../../../../app/scripts/config.js').networkNames +const { getNetworkDisplayName } = require('../../../../app/scripts/controllers/network/util') const ShapeshiftForm = require('../shapeshift-form') let DIRECT_DEPOSIT_ROW_TITLE @@ -122,7 +122,7 @@ DepositEtherModal.prototype.render = function () { const { buyingWithShapeshift } = this.state const isTestNetwork = ['3', '4', '42'].find(n => n === network) - const networkName = networkNames[network] + const networkName = getNetworkDisplayName(network) return h('div.page-container.page-container--full-width.page-container--full-height', {}, [ diff --git a/ui/app/components/modals/export-private-key-modal.js b/ui/app/components/modals/export-private-key-modal.js index 1f80aed39..447e43b7a 100644 --- a/ui/app/components/modals/export-private-key-modal.js +++ b/ui/app/components/modals/export-private-key-modal.js @@ -3,12 +3,13 @@ const PropTypes = require('prop-types') const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect -const ethUtil = require('ethereumjs-util') +const { stripHexPrefix } = require('ethereumjs-util') const actions = require('../../actions') const AccountModalContainer = require('./account-modal-container') const { getSelectedIdentity } = require('../../selectors') const ReadOnlyInput = require('../readonly-input') const copyToClipboard = require('copy-to-clipboard') +const { checksumAddress } = require('../../util') function mapStateToProps (state) { return { @@ -60,7 +61,7 @@ ExportPrivateKeyModal.prototype.renderPasswordLabel = function (privateKey) { } ExportPrivateKeyModal.prototype.renderPasswordInput = function (privateKey) { - const plainKey = privateKey && ethUtil.stripHexPrefix(privateKey) + const plainKey = privateKey && stripHexPrefix(privateKey) return privateKey ? h(ReadOnlyInput, { @@ -121,7 +122,7 @@ ExportPrivateKeyModal.prototype.render = function () { h(ReadOnlyInput, { wrapperClass: 'ellip-address-wrapper', inputClass: 'qr-ellip-address ellip-address', - value: address, + value: checksumAddress(address), }), h('div.account-modal-divider'), diff --git a/ui/app/components/modals/modal.js b/ui/app/components/modals/modal.js index 9250cc77e..43dcd20ae 100644 --- a/ui/app/components/modals/modal.js +++ b/ui/app/components/modals/modal.js @@ -5,7 +5,8 @@ const connect = require('react-redux').connect const FadeModal = require('boron').FadeModal const actions = require('../../actions') const isMobileView = require('../../../lib/is-mobile-view') -const isPopupOrNotification = require('../../../../app/scripts/lib/is-popup-or-notification') +const { getEnvironmentType } = require('../../../../app/scripts/lib/util') +const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums') // Modal Components const BuyOptions = require('./buy-options-modal') @@ -162,7 +163,7 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', @@ -179,7 +180,7 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', @@ -196,7 +197,7 @@ const MODALS = { ], mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '449px', @@ -208,7 +209,7 @@ const MODALS = { contents: h(ConfirmResetAccount), mobileModalStyle: { width: '95%', - top: isPopupOrNotification() === 'popup' ? '52vh' : '36.5vh', + top: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { width: '473px', diff --git a/ui/app/components/pages/home.js b/ui/app/components/pages/home.js index 7857a2a99..90b8e1d37 100644 --- a/ui/app/components/pages/home.js +++ b/ui/app/components/pages/home.js @@ -5,6 +5,7 @@ const { Redirect, withRouter } = require('react-router-dom') const { compose } = require('recompose') const h = require('react-hyperscript') const actions = require('../../actions') +const log = require('loglevel') // init const NewKeyChainScreen = require('../../new-keychain') diff --git a/ui/app/components/pages/keychains/restore-vault.js b/ui/app/components/pages/keychains/restore-vault.js index d57894e00..33575bfbb 100644 --- a/ui/app/components/pages/keychains/restore-vault.js +++ b/ui/app/components/pages/keychains/restore-vault.js @@ -6,6 +6,7 @@ const connect = require('../../../metamask-connect') const h = require('react-hyperscript') const { createNewVaultAndRestore, unMarkPasswordForgotten } = require('../../../actions') const { DEFAULT_ROUTE } = require('../../../routes') +const log = require('loglevel') class RestoreVaultPage extends PersistentForm { constructor (props) { diff --git a/ui/app/components/pages/settings/info.js b/ui/app/components/pages/settings/info.js index eb9be66e6..bd9040499 100644 --- a/ui/app/components/pages/settings/info.js +++ b/ui/app/components/pages/settings/info.js @@ -3,6 +3,14 @@ const PropTypes = require('prop-types') const h = require('react-hyperscript') class Info extends Component { + constructor (props) { + super(props) + + this.state = { + version: global.platform.getVersion(), + } + } + renderLogo () { return ( h('div.settings__info-logo-wrapper', [ @@ -76,7 +84,7 @@ class Info extends Component { this.renderLogo(), h('div.settings__info-item', [ h('div.settings__info-version-header', 'MetaMask Version'), - h('div.settings__info-version-number', '4.0.0'), + h('div.settings__info-version-number', this.state.version), ]), h('div.settings__info-item', [ h( diff --git a/ui/app/components/pages/settings/settings.js b/ui/app/components/pages/settings/settings.js index 05a7379fb..bdefe56f8 100644 --- a/ui/app/components/pages/settings/settings.js +++ b/ui/app/components/pages/settings/settings.js @@ -12,7 +12,7 @@ const SimpleDropdown = require('../../dropdowns/simple-dropdown') const ToggleButton = require('react-toggle-button') const { REVEAL_SEED_ROUTE } = require('../../../routes') const locales = require('../../../../../app/_locales/index.json') -const { OLD_UI_NETWORK_TYPE } = require('../../../../../app/scripts/config').enums +const { OLD_UI_NETWORK_TYPE } = require('../../../../../app/scripts/controllers/network/enums') const getInfuraCurrencyOptions = () => { const sortedCurrencies = infuraCurrencies.objects.sort((a, b) => { diff --git a/ui/app/components/pages/unlock.js b/ui/app/components/pages/unlock.js index b3320da21..30144b978 100644 --- a/ui/app/components/pages/unlock.js +++ b/ui/app/components/pages/unlock.js @@ -11,11 +11,12 @@ const { setNetworkEndpoints, setFeatureFlag, } = require('../../actions') -const environmentType = require('../../../../app/scripts/lib/environment-type') +const { ENVIRONMENT_TYPE_POPUP } = require('../../../../app/scripts/lib/enums') +const { getEnvironmentType } = require('../../../../app/scripts/lib/util') const getCaretCoordinates = require('textarea-caret') const EventEmitter = require('events').EventEmitter const Mascot = require('../mascot') -const { OLD_UI_NETWORK_TYPE } = require('../../../../app/scripts/config').enums +const { OLD_UI_NETWORK_TYPE } = require('../../../../app/scripts/controllers/network/enums') const { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE } = require('../../routes') class UnlockScreen extends Component { @@ -131,7 +132,7 @@ class UnlockScreen extends Component { this.props.markPasswordForgotten() this.props.history.push(RESTORE_VAULT_ROUTE) - if (environmentType() === 'popup') { + if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser() } }, diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 3ee614a2a..16dbd273b 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -23,6 +23,8 @@ const { const GasFeeDisplay = require('../send/gas-fee-display-v2') const SenderToRecipient = require('../sender-to-recipient') const NetworkDisplay = require('../network-display') +const currencyFormatter = require('currency-formatter') +const currencies = require('currency-formatter/currencies') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') const { SEND_ROUTE, DEFAULT_ROUTE } = require('../../routes') @@ -275,6 +277,16 @@ ConfirmSendEther.prototype.getData = function () { } } +ConfirmSendEther.prototype.convertToRenderableCurrency = function (value, currencyCode) { + const upperCaseCurrencyCode = currencyCode.toUpperCase() + + return currencies.find(currency => currency.code === upperCaseCurrencyCode) + ? currencyFormatter.format(Number(value), { + code: upperCaseCurrencyCode, + }) + : value +} + ConfirmSendEther.prototype.editTransaction = function (txMeta) { const { editTransaction, history } = this.props editTransaction(txMeta) @@ -319,6 +331,9 @@ ConfirmSendEther.prototype.render = function () { ? 'Increase your gas fee to attempt to overwrite and speed up your transaction' : 'Please review your transaction.' + const convertedAmountInFiat = this.convertToRenderableCurrency(amountInFIAT, currentCurrency) + const convertedTotalInFiat = this.convertToRenderableCurrency(totalInFIAT, currentCurrency) + // This is from the latest master // It handles some of the errors that we are not currently handling // Leaving as comments fo reference @@ -365,7 +380,7 @@ ConfirmSendEther.prototype.render = function () { // `You're sending to Recipient ...${toAddress.slice(toAddress.length - 4)}`, // ]), - h('h3.flex-center.confirm-screen-send-amount', [`${amountInFIAT}`]), + h('h3.flex-center.confirm-screen-send-amount', [`${convertedAmountInFiat}`]), h('h3.flex-center.confirm-screen-send-amount-currency', [ currentCurrency.toUpperCase() ]), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), @@ -412,7 +427,7 @@ ConfirmSendEther.prototype.render = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`), + h('div.confirm-screen-row-info', `${convertedTotalInFiat} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${totalInETH} ETH`), ]), diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 6942f9b51..656093b3d 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -27,6 +27,8 @@ const { calcTokenAmount, } = require('../../token-util') const classnames = require('classnames') +const currencyFormatter = require('currency-formatter') +const currencies = require('currency-formatter/currencies') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -48,7 +50,7 @@ module.exports = compose( function mapStateToProps (state, ownProps) { - const { token: { symbol }, txData } = ownProps + const { token: { address }, txData } = ownProps const { txParams } = txData || {} const tokenData = txParams.data && abiDecoder.decodeMethod(txParams.data) @@ -59,7 +61,7 @@ function mapStateToProps (state, ownProps) { } = state.metamask const accounts = state.metamask.accounts const selectedAddress = getSelectedAddress(state) - const tokenExchangeRate = getTokenExchangeRate(state, symbol) + const tokenExchangeRate = getTokenExchangeRate(state, address) const { balance } = accounts[selectedAddress] return { conversionRate, @@ -75,12 +77,9 @@ function mapStateToProps (state, ownProps) { } function mapDispatchToProps (dispatch, ownProps) { - const { token: { symbol } } = ownProps - return { backToAccountDetail: address => dispatch(actions.backToAccountDetail(address)), cancelTransaction: ({ id }) => dispatch(actions.cancelTx({ id })), - updateTokenExchangeRate: () => dispatch(actions.updateTokenExchangeRate(symbol)), editTransaction: txMeta => { const { token: { address } } = ownProps const { txParams = {}, id } = txMeta @@ -203,7 +202,6 @@ ConfirmSendToken.prototype.componentWillMount = function () { .balanceOf(selectedAddress) .then(usersToken => { }) - this.props.updateTokenExchangeRate() this.updateComponentSendErrors({}) } @@ -322,10 +320,12 @@ ConfirmSendToken.prototype.renderHeroAmount = function () { const txParams = txMeta.txParams || {} const { memo = '' } = txParams + const convertedAmountInFiat = this.convertToRenderableCurrency(fiatAmount, currentCurrency) + return fiatAmount ? ( h('div.confirm-send-token__hero-amount-wrapper', [ - h('h3.flex-center.confirm-screen-send-amount', `${fiatAmount}`), + h('h3.flex-center.confirm-screen-send-amount', `${convertedAmountInFiat}`), h('h3.flex-center.confirm-screen-send-amount-currency', currentCurrency), h('div.flex-center.confirm-memo-wrapper', [ h('h3.confirm-screen-send-memo', [ memo ? `"${memo}"` : '' ]), @@ -373,6 +373,9 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, token: tokenGas } = this.getGasFee() + const totalInFIAT = fiatAmount && fiatGas && addCurrencies(fiatAmount, fiatGas) + const convertedTotalInFiat = this.convertToRenderableCurrency(totalInFIAT, currentCurrency) + return fiatAmount && fiatGas ? ( h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [ @@ -382,7 +385,7 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ]), h('div.confirm-screen-section-column', [ - h('div.confirm-screen-row-info', `${addCurrencies(fiatAmount, fiatGas)} ${currentCurrency}`), + h('div.confirm-screen-row-info', `${convertedTotalInFiat} ${currentCurrency}`), h('div.confirm-screen-row-detail', `${addCurrencies(tokenAmount, tokenGas || '0')} ${symbol}`), ]), ]) @@ -417,6 +420,16 @@ ConfirmSendToken.prototype.renderErrorMessage = function (message) { : null } +ConfirmSendToken.prototype.convertToRenderableCurrency = function (value, currencyCode) { + const upperCaseCurrencyCode = currencyCode.toUpperCase() + + return currencies.find(currency => currency.code === upperCaseCurrencyCode) + ? currencyFormatter.format(Number(value), { + code: upperCaseCurrencyCode, + }) + : value +} + ConfirmSendToken.prototype.render = function () { const txMeta = this.gatherTxMeta() const { diff --git a/ui/app/components/pending-tx/index.js b/ui/app/components/pending-tx/index.js index acdd99364..6ee83ba7e 100644 --- a/ui/app/components/pending-tx/index.js +++ b/ui/app/components/pending-tx/index.js @@ -1,6 +1,7 @@ const Component = require('react').Component const connect = require('react-redux').connect const h = require('react-hyperscript') +const PropTypes = require('prop-types') const clone = require('clone') const abi = require('human-standard-token-abi') const abiDecoder = require('abi-decoder') @@ -11,6 +12,7 @@ const util = require('../../util') const ConfirmSendEther = require('./confirm-send-ether') const ConfirmSendToken = require('./confirm-send-token') const ConfirmDeployContract = require('./confirm-deploy-contract') +const Loading = require('../loading') const TX_TYPES = { DEPLOY_CONTRACT: 'deploy_contract', @@ -53,10 +55,24 @@ function PendingTx () { } } -PendingTx.prototype.componentWillMount = async function () { +PendingTx.prototype.componentDidMount = function () { + this.setTokenData() +} + +PendingTx.prototype.componentDidUpdate = function (prevProps, prevState) { + if (prevState.isFetching) { + this.setTokenData() + } +} + +PendingTx.prototype.setTokenData = async function () { const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} + if (txMeta.loadingDefaults) { + return + } + if (!txParams.to) { return this.setState({ transactionType: TX_TYPES.DEPLOY_CONTRACT, @@ -125,7 +141,10 @@ PendingTx.prototype.render = function () { const { sendTransaction } = this.props if (isFetching) { - return h('noscript') + return h(Loading, { + fullScreen: true, + loadingMessage: this.context.t('generatingTransaction'), + }) } switch (transactionType) { @@ -150,6 +169,12 @@ PendingTx.prototype.render = function () { sendTransaction, }) default: - return h('noscript') + return h(Loading, { + fullScreen: true, + }) } } + +PendingTx.contextTypes = { + t: PropTypes.func, +} diff --git a/ui/app/components/qr-code.js b/ui/app/components/qr-code.js index 83885539c..3b2c62f49 100644 --- a/ui/app/components/qr-code.js +++ b/ui/app/components/qr-code.js @@ -3,8 +3,9 @@ const h = require('react-hyperscript') const qrCode = require('qrcode-npm').qrcode const inherits = require('util').inherits const connect = require('react-redux').connect -const isHexPrefixed = require('ethereumjs-util').isHexPrefixed +const { isHexPrefixed } = require('ethereumjs-util') const ReadOnlyInput = require('./readonly-input') +const { checksumAddress } = require('../util') module.exports = connect(mapStateToProps)(QrCodeView) @@ -24,16 +25,16 @@ function QrCodeView () { QrCodeView.prototype.render = function () { const props = this.props - const Qr = props.Qr - const address = `${isHexPrefixed(Qr.data) ? 'ethereum:' : ''}${Qr.data}` + const { message, data } = props.Qr + const address = `${isHexPrefixed(data) ? 'ethereum:' : ''}${data}` const qrImage = qrCode(4, 'M') qrImage.addData(address) qrImage.make() return h('.div.flex-column.flex-center', [ - Array.isArray(Qr.message) + Array.isArray(message) ? h('.message-container', this.renderMultiMessage()) - : Qr.message && h('.qr-header', Qr.message), + : message && h('.qr-header', message), this.props.warning ? this.props.warning && h('span.error.flex-center', { style: { @@ -50,7 +51,7 @@ QrCodeView.prototype.render = function () { h(ReadOnlyInput, { wrapperClass: 'ellip-address-wrapper', inputClass: 'qr-ellip-address', - value: Qr.data, + value: checksumAddress(data), }), ]) } diff --git a/ui/app/components/send/account-list-item.js b/ui/app/components/send/account-list-item.js index 1ad3f69c1..b5e604a6e 100644 --- a/ui/app/components/send/account-list-item.js +++ b/ui/app/components/send/account-list-item.js @@ -2,6 +2,7 @@ const Component = require('react').Component const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect +const { checksumAddress } = require('../../util') const Identicon = require('../identicon') const CurrencyDisplay = require('./currency-display') const { conversionRateSelector, getCurrentCurrency } = require('../../selectors') @@ -56,7 +57,7 @@ AccountListItem.prototype.render = function () { ]), - displayAddress && name && h('div.account-list-item__account-address', address), + displayAddress && name && h('div.account-list-item__account-address', checksumAddress(address)), displayBalance && h(CurrencyDisplay, { primaryCurrency: 'ETH', diff --git a/ui/app/components/send/currency-display.js b/ui/app/components/send/currency-display.js index 819fee0a0..a7bd5d7ea 100644 --- a/ui/app/components/send/currency-display.js +++ b/ui/app/components/send/currency-display.js @@ -3,6 +3,8 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const CurrencyInput = require('../currency-input') const { conversionUtil, multiplyCurrencies } = require('../../conversion-util') +const currencyFormatter = require('currency-formatter') +const currencies = require('currency-formatter/currencies') module.exports = CurrencyDisplay @@ -53,12 +55,32 @@ CurrencyDisplay.prototype.getValueToRender = function () { }) } +CurrencyDisplay.prototype.getConvertedValueToRender = function (nonFormattedValue) { + const { primaryCurrency, convertedCurrency, conversionRate } = this.props + + let convertedValue = conversionUtil(nonFormattedValue, { + fromNumericBase: 'dec', + fromCurrency: primaryCurrency, + toCurrency: convertedCurrency, + numberOfDecimals: 2, + conversionRate, + }) + convertedValue = Number(convertedValue).toFixed(2) + + const upperCaseCurrencyCode = convertedCurrency.toUpperCase() + + return currencies.find(currency => currency.code === upperCaseCurrencyCode) + ? currencyFormatter.format(Number(convertedValue), { + code: upperCaseCurrencyCode, + }) + : convertedValue +} + CurrencyDisplay.prototype.render = function () { const { className = 'currency-display', primaryBalanceClassName = 'currency-display__input', convertedBalanceClassName = 'currency-display__converted-value', - conversionRate, primaryCurrency, convertedCurrency, readOnly = false, @@ -68,14 +90,7 @@ CurrencyDisplay.prototype.render = function () { const valueToRender = this.getValueToRender() - let convertedValue = conversionUtil(valueToRender, { - fromNumericBase: 'dec', - fromCurrency: primaryCurrency, - toCurrency: convertedCurrency, - numberOfDecimals: 2, - conversionRate, - }) - convertedValue = Number(convertedValue).toFixed(2) + const convertedValueToRender = this.getConvertedValueToRender(valueToRender) return h('div', { className, @@ -108,7 +123,7 @@ CurrencyDisplay.prototype.render = function () { h('div', { className: convertedBalanceClassName, - }, `${convertedValue} ${convertedCurrency.toUpperCase()}`), + }, `${convertedValueToRender} ${convertedCurrency.toUpperCase()}`), ]) diff --git a/ui/app/components/send/send-v2-container.js b/ui/app/components/send/send-v2-container.js index aca1a5a0a..adfc91240 100644 --- a/ui/app/components/send/send-v2-container.js +++ b/ui/app/components/send/send-v2-container.js @@ -66,7 +66,6 @@ function mapDispatchToProps (dispatch) { showCustomizeGasModal: () => dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })), estimateGas: params => dispatch(actions.estimateGas(params)), getGasPrice: () => dispatch(actions.getGasPrice()), - updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), signTokenTx: (tokenAddress, toAddress, amount, txData) => ( dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index 2f71c0687..1900ccec7 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const TokenTracker = require('eth-token-tracker') const connect = require('react-redux').connect const selectors = require('../selectors') +const log = require('loglevel') function mapStateToProps (state) { return { diff --git a/ui/app/components/token-cell.js b/ui/app/components/token-cell.js index 0332fde88..c84117d84 100644 --- a/ui/app/components/token-cell.js +++ b/ui/app/components/token-cell.js @@ -16,7 +16,7 @@ function mapStateToProps (state) { currentCurrency: state.metamask.currentCurrency, selectedTokenAddress: state.metamask.selectedTokenAddress, userAddress: selectors.getSelectedAddress(state), - tokenExchangeRates: state.metamask.tokenExchangeRates, + contractExchangeRates: state.metamask.contractExchangeRates, conversionRate: state.metamask.conversionRate, sidebarOpen: state.appState.sidebarOpen, } @@ -25,7 +25,6 @@ function mapStateToProps (state) { function mapDispatchToProps (dispatch) { return { setSelectedToken: address => dispatch(actions.setSelectedToken(address)), - updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), hideSidebar: () => dispatch(actions.hideSidebar()), } } @@ -41,15 +40,6 @@ function TokenCell () { } } -TokenCell.prototype.componentWillMount = function () { - const { - updateTokenExchangeRate, - symbol, - } = this.props - - updateTokenExchangeRate(symbol) -} - TokenCell.prototype.render = function () { const { tokenMenuOpen } = this.state const props = this.props @@ -60,7 +50,7 @@ TokenCell.prototype.render = function () { network, setSelectedToken, selectedTokenAddress, - tokenExchangeRates, + contractExchangeRates, conversionRate, hideSidebar, sidebarOpen, @@ -68,15 +58,13 @@ TokenCell.prototype.render = function () { // userAddress, } = props - const pair = `${symbol.toLowerCase()}_eth` - let currentTokenToFiatRate let currentTokenInFiat let formattedFiat = '' - if (tokenExchangeRates[pair]) { + if (contractExchangeRates[address]) { currentTokenToFiatRate = multiplyCurrencies( - tokenExchangeRates[pair].rate, + contractExchangeRates[address], conversionRate ) currentTokenInFiat = conversionUtil(string, { diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 150a3762d..4189cf801 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -6,6 +6,7 @@ const TokenTracker = require('eth-token-tracker') const TokenCell = require('./token-cell.js') const connect = require('react-redux').connect const selectors = require('../selectors') +const log = require('loglevel') function mapStateToProps (state) { return { diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 42c008798..bd4ea80a6 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -9,6 +9,7 @@ const abiDecoder = require('abi-decoder') abiDecoder.addABI(abi) const Identicon = require('./identicon') const contractMap = require('eth-contract-metadata') +const { checksumAddress } = require('../util') const actions = require('../actions') const { conversionUtil, multiplyCurrencies } = require('../conversion-util') @@ -27,7 +28,7 @@ function mapStateToProps (state) { return { tokens: state.metamask.tokens, currentCurrency: getCurrentCurrency(state), - tokenExchangeRates: state.metamask.tokenExchangeRates, + contractExchangeRates: state.metamask.contractExchangeRates, selectedAddressTxList: state.metamask.selectedAddressTxList, } } @@ -74,10 +75,12 @@ TxListItem.prototype.getAddressText = function () { const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { name: txDataName, params = [] } = decodedData || {} const { value } = params[0] || {} + const checksummedAddress = checksumAddress(address) + const checksummedValue = checksumAddress(value) let addressText if (txDataName === 'transfer' || address) { - const addressToRender = txDataName === 'transfer' ? value : address + const addressToRender = txDataName === 'transfer' ? checksummedValue : checksummedAddress addressText = `${addressToRender.slice(0, 10)}...${addressToRender.slice(-4)}` } else if (isMsg) { addressText = this.context.t('sigRequest') @@ -142,31 +145,29 @@ TxListItem.prototype.getTokenInfo = async function () { ({ decimals, symbol } = await tokenInfoGetter(toAddress)) } - return { decimals, symbol } + return { decimals, symbol, address: toAddress } } TxListItem.prototype.getSendTokenTotal = async function () { const { txParams = {}, conversionRate, - tokenExchangeRates, + contractExchangeRates, currentCurrency, } = this.props const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { params = [] } = decodedData || {} const { value } = params[1] || {} - const { decimals, symbol } = await this.getTokenInfo() + const { decimals, symbol, address } = await this.getTokenInfo() const total = calcTokenAmount(value, decimals) - const pair = symbol && `${symbol.toLowerCase()}_eth` - let tokenToFiatRate let totalInFiat - if (tokenExchangeRates[pair]) { + if (contractExchangeRates[address]) { tokenToFiatRate = multiplyCurrencies( - tokenExchangeRates[pair].rate, + contractExchangeRates[address], conversionRate ) @@ -220,7 +221,6 @@ TxListItem.prototype.resubmit = function () { TxListItem.prototype.render = function () { const { transactionStatus, - transactionAmount, onClick, transactionId, dateString, @@ -229,7 +229,6 @@ TxListItem.prototype.render = function () { txParams, } = this.props const { total, fiatTotal, isTokenTx } = this.state - const showFiatTotal = transactionAmount !== '0x0' && fiatTotal return h(`div${className || ''}`, { key: transactionId, @@ -288,7 +287,7 @@ TxListItem.prototype.render = function () { h('span.tx-list-value', total), - showFiatTotal && h('span.tx-list-fiat-value', fiatTotal), + fiatTotal && h('span.tx-list-fiat-value', fiatTotal), ]), ]), diff --git a/ui/app/components/tx-view.js b/ui/app/components/tx-view.js index 80aac35c4..263f992c0 100644 --- a/ui/app/components/tx-view.js +++ b/ui/app/components/tx-view.js @@ -2,13 +2,13 @@ const Component = require('react').Component const PropTypes = require('prop-types') const connect = require('react-redux').connect const h = require('react-hyperscript') -const ethUtil = require('ethereumjs-util') const inherits = require('util').inherits const { withRouter } = require('react-router-dom') const { compose } = require('recompose') const actions = require('../actions') const selectors = require('../selectors') const { SEND_ROUTE } = require('../routes') +const { checksumAddress: toChecksumAddress } = require('../util') const BalanceComponent = require('./balance-component') const TxList = require('./tx-list') @@ -32,7 +32,7 @@ function mapStateToProps (state) { const network = state.metamask.network const selectedTokenAddress = state.metamask.selectedTokenAddress const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] - const checksumAddress = selectedAddress && ethUtil.toChecksumAddress(selectedAddress) + const checksumAddress = toChecksumAddress(selectedAddress) const identity = identities[selectedAddress] return { diff --git a/ui/app/components/wallet-view.js b/ui/app/components/wallet-view.js index e3e1b8903..9e430f87b 100644 --- a/ui/app/components/wallet-view.js +++ b/ui/app/components/wallet-view.js @@ -6,6 +6,7 @@ const { withRouter } = require('react-router-dom') const { compose } = require('recompose') const inherits = require('util').inherits const classnames = require('classnames') +const { checksumAddress } = require('../util') const Identicon = require('./identicon') // const AccountDropdowns = require('./dropdowns/index.js').AccountDropdowns const Tooltip = require('./tooltip-v2.js') @@ -107,6 +108,8 @@ WalletView.prototype.render = function () { // temporary logs + fake extra wallets // console.log('walletview, selectedAccount:', selectedAccount) + const checksummedAddress = checksumAddress(selectedAddress) + const keyring = keyrings.find((kr) => { return kr.accounts.includes(selectedAddress) || kr.accounts.includes(selectedIdentity.address) @@ -135,7 +138,7 @@ WalletView.prototype.render = function () { }, [ h(Identicon, { diameter: 54, - address: selectedAddress, + address: checksummedAddress, }), h('span.account-name', { @@ -158,7 +161,7 @@ WalletView.prototype.render = function () { 'wallet-view__address__pressed': this.state.copyToClipboardPressed, }), onClick: () => { - copyToClipboard(selectedAddress) + copyToClipboard(checksummedAddress) this.setState({ hasCopied: true }) setTimeout(() => this.setState({ hasCopied: false }), 3000) }, @@ -169,7 +172,7 @@ WalletView.prototype.render = function () { this.setState({ copyToClipboardPressed: false }) }, }, [ - `${selectedAddress.slice(0, 4)}...${selectedAddress.slice(-4)}`, + `${checksummedAddress.slice(0, 4)}...${checksummedAddress.slice(-4)}`, h('i.fa.fa-clipboard', { style: { marginLeft: '8px' } }), ]), ]), diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index fee7cd36f..b71538e31 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -6,6 +6,7 @@ const { withRouter } = require('react-router-dom') const { compose } = require('recompose') const actions = require('./actions') const txHelper = require('../lib/tx-helper') +const log = require('loglevel') const PendingTx = require('./components/pending-tx') const SignatureRequest = require('./components/signature-request') diff --git a/ui/app/css/itcss/components/add-token.scss b/ui/app/css/itcss/components/add-token.scss index 2fdda6f43..01579c27c 100644 --- a/ui/app/css/itcss/components/add-token.scss +++ b/ui/app/css/itcss/components/add-token.scss @@ -36,6 +36,7 @@ font-weight: 400; line-height: 21px; margin-left: 8px; + cursor:pointer; } } diff --git a/ui/app/css/itcss/components/loading-overlay.scss b/ui/app/css/itcss/components/loading-overlay.scss index 15009c1e6..a92fffec5 100644 --- a/ui/app/css/itcss/components/loading-overlay.scss +++ b/ui/app/css/itcss/components/loading-overlay.scss @@ -1,13 +1,14 @@ .loading-overlay { - left: 0px; + left: 0; z-index: 50; position: absolute; flex-direction: column; display: flex; justify-content: center; align-items: center; + flex: 1 1 auto; width: 100%; - background: rgba(255, 255, 255, 0.8); + background: rgba(255, 255, 255, .8); @media screen and (max-width: 575px) { margin-top: 56px; @@ -18,4 +19,11 @@ margin-top: 75px; height: calc(100% - 75px); } + + &--full-screen { + position: fixed; + height: 100vh; + width: 100vw; + margin-top: 0; + } } diff --git a/ui/app/css/itcss/components/network.scss b/ui/app/css/itcss/components/network.scss index c34b5cd06..6c8be0b6d 100644 --- a/ui/app/css/itcss/components/network.scss +++ b/ui/app/css/itcss/components/network.scss @@ -139,7 +139,7 @@ .network-dropdown-title { height: 25px; - width: 75px; + width: 120px; color: $white; font-family: Roboto; font-size: 18px; diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index 89d2be891..362feeec8 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -789,6 +789,7 @@ display: flex; justify-content: center; align-items: center; + padding: 0 3px; cursor: pointer; } diff --git a/ui/app/first-time/init-menu.js b/ui/app/first-time/init-menu.js index 692b01c8c..6cb548bb9 100644 --- a/ui/app/first-time/init-menu.js +++ b/ui/app/first-time/init-menu.js @@ -8,8 +8,9 @@ const actions = require('../actions') const Tooltip = require('../components/tooltip') const getCaretCoordinates = require('textarea-caret') const { RESTORE_VAULT_ROUTE, DEFAULT_ROUTE } = require('../routes') -const environmentType = require('../../../app/scripts/lib/environment-type') -const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums +const { getEnvironmentType } = require('../../../app/scripts/lib/util') +const { ENVIRONMENT_TYPE_POPUP } = require('../../../app/scripts/lib/enums') +const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/controllers/network/enums') class InitializeMenuScreen extends Component { constructor (props) { @@ -180,7 +181,7 @@ class InitializeMenuScreen extends Component { showRestoreVault () { this.props.markPasswordForgotten() - if (environmentType() === 'popup') { + if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser() } diff --git a/ui/app/keychains/hd/restore-vault.js b/ui/app/keychains/hd/restore-vault.js index 38ad14adb..913d20505 100644 --- a/ui/app/keychains/hd/restore-vault.js +++ b/ui/app/keychains/hd/restore-vault.js @@ -4,6 +4,7 @@ const PersistentForm = require('../../../lib/persistent-form') const connect = require('react-redux').connect const h = require('react-hyperscript') const actions = require('../../actions') +const log = require('loglevel') RestoreVaultScreen.contextTypes = { t: PropTypes.func, diff --git a/ui/app/main-container.js b/ui/app/main-container.js index 6dd4ff151..c305687ea 100644 --- a/ui/app/main-container.js +++ b/ui/app/main-container.js @@ -4,6 +4,7 @@ const inherits = require('util').inherits const AccountAndTransactionDetails = require('./account-and-transaction-details') const Settings = require('./components/pages/settings') const UnlockScreen = require('./components/pages/unlock') +const log = require('loglevel') module.exports = MainContainer diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index 74a0f9299..2b39eb8db 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -1,6 +1,7 @@ const extend = require('xtend') const actions = require('../actions') const txHelper = require('../../lib/tx-helper') +const log = require('loglevel') module.exports = reduceApp diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 6d0a5bb10..bb35cf990 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -1,8 +1,9 @@ const extend = require('xtend') const actions = require('../actions') const MetamascaraPlatform = require('../../../app/scripts/platforms/window') -const environmentType = require('../../../app/scripts/lib/environment-type') -const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/config').enums +const { getEnvironmentType } = require('../../../app/scripts/lib/util') +const { ENVIRONMENT_TYPE_POPUP } = require('../../../app/scripts/lib/enums') +const { OLD_UI_NETWORK_TYPE } = require('../../../app/scripts/controllers/network/enums') module.exports = reduceMetamask @@ -15,7 +16,7 @@ function reduceMetamask (state, action) { isUnlocked: false, isAccountMenuOpen: false, isMascara: window.platform instanceof MetamascaraPlatform, - isPopup: environmentType() === 'popup', + isPopup: getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP, rpcTarget: 'https://rawtestrpc.metamask.io/', identities: {}, unapprovedTxs: {}, @@ -24,6 +25,7 @@ function reduceMetamask (state, action) { frequentRpcList: [], addressBook: [], selectedTokenAddress: null, + contractExchangeRates: {}, tokenExchangeRates: {}, tokens: [], send: { @@ -176,15 +178,6 @@ function reduceMetamask (state, action) { conversionDate: action.value.conversionDate, }) - case actions.UPDATE_TOKEN_EXCHANGE_RATE: - const { payload: { pair, marketinfo } } = action - return extend(metamaskState, { - tokenExchangeRates: { - ...metamaskState.tokenExchangeRates, - [pair]: marketinfo, - }, - }) - case actions.UPDATE_TOKENS: return extend(metamaskState, { tokens: action.newTokens, @@ -358,7 +351,7 @@ function reduceMetamask (state, action) { welcomeScreenSeen: true, }) - case action.SET_CURRENT_LOCALE: + case actions.SET_CURRENT_LOCALE: return extend(metamaskState, { currentLocale: action.value, }) diff --git a/ui/app/select-app.js b/ui/app/select-app.js index d1565e2fb..808f9ba56 100644 --- a/ui/app/select-app.js +++ b/ui/app/select-app.js @@ -7,7 +7,7 @@ const App = require('./app') const OldApp = require('../../old-ui/app/app') const { autoAddToBetaUI } = require('./selectors') const { setFeatureFlag, setNetworkEndpoints } = require('./actions') -const { BETA_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums +const { BETA_UI_NETWORK_TYPE } = require('../../app/scripts/controllers/network/enums') const I18nProvider = require('./i18n-provider') function mapStateToProps (state) { diff --git a/ui/app/selectors.js b/ui/app/selectors.js index 2bdc39004..60cc264da 100644 --- a/ui/app/selectors.js +++ b/ui/app/selectors.js @@ -62,22 +62,15 @@ function getSelectedToken (state) { } function getSelectedTokenExchangeRate (state) { - const tokenExchangeRates = state.metamask.tokenExchangeRates + const contractExchangeRates = state.metamask.contractExchangeRates const selectedToken = getSelectedToken(state) || {} - const { symbol = '' } = selectedToken - - const pair = `${symbol.toLowerCase()}_eth` - const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} - - return tokenExchangeRate + const { address } = selectedToken + return contractExchangeRates[address] || 0 } -function getTokenExchangeRate (state, tokenSymbol) { - const pair = `${tokenSymbol.toLowerCase()}_eth` - const tokenExchangeRates = state.metamask.tokenExchangeRates - const { rate: tokenExchangeRate = 0 } = tokenExchangeRates[pair] || {} - - return tokenExchangeRate +function getTokenExchangeRate (state, address) { + const contractExchangeRates = state.metamask.contractExchangeRates + return contractExchangeRates[address] || 0 } function conversionRateSelector (state) { diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 9c540671b..c5085d9ec 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -93,17 +93,6 @@ SendTransactionScreen.prototype.updateSendTokenBalance = function (usersToken) { } SendTransactionScreen.prototype.componentWillMount = function () { - const { - updateTokenExchangeRate, - selectedToken = {}, - } = this.props - - const { symbol } = selectedToken || {} - - if (symbol) { - updateTokenExchangeRate(symbol) - } - this.updateGas() } diff --git a/ui/app/unlock.js b/ui/app/unlock.js index 84d8b7e7c..099e5f9c6 100644 --- a/ui/app/unlock.js +++ b/ui/app/unlock.js @@ -6,8 +6,9 @@ const connect = require('react-redux').connect const actions = require('./actions') const getCaretCoordinates = require('textarea-caret') const EventEmitter = require('events').EventEmitter -const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/config').enums -const environmentType = require('../../app/scripts/lib/environment-type') +const { OLD_UI_NETWORK_TYPE } = require('../../app/scripts/controllers/network/enums') +const { getEnvironmentType } = require('../../app/scripts/lib/util') +const { ENVIRONMENT_TYPE_POPUP } = require('../../app/scripts/lib/enums') const Mascot = require('./components/mascot') @@ -77,7 +78,7 @@ UnlockScreen.prototype.render = function () { h('p.pointer', { onClick: () => { this.props.dispatch(actions.markPasswordForgotten()) - if (environmentType() === 'popup') { + if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP) { global.platform.openExtensionInBrowser() } }, diff --git a/ui/app/util.js b/ui/app/util.js index bbe2bb09e..8e9390dfb 100644 --- a/ui/app/util.js +++ b/ui/app/util.js @@ -57,6 +57,7 @@ module.exports = { isInvalidChecksumAddress, allNull, getTokenAddressFromTokenObject, + checksumAddress, } function valuesFor (obj) { @@ -67,7 +68,7 @@ function valuesFor (obj) { function addressSummary (address, firstSegLength = 10, lastSegLength = 4, includeHex = true) { if (!address) return '' - let checked = ethUtil.toChecksumAddress(address) + let checked = checksumAddress(address) if (!includeHex) { checked = ethUtil.stripHexPrefix(checked) } @@ -76,7 +77,7 @@ function addressSummary (address, firstSegLength = 10, lastSegLength = 4, includ function miniAddressSummary (address) { if (!address) return '' - var checked = ethUtil.toChecksumAddress(address) + var checked = checksumAddress(address) return checked ? checked.slice(0, 4) + '...' + checked.slice(-4) : '...' } @@ -287,3 +288,13 @@ function allNull (obj) { function getTokenAddressFromTokenObject (token) { return Object.values(token)[0].address.toLowerCase() } + +/** + * Safely checksumms a potentially-null address + * + * @param {String} [address] - address to checksum + * @returns {String} - checksummed address + */ +function checksumAddress (address) { + return address ? ethUtil.toChecksumAddress(address) : '' +} |