diff options
22 files changed, 214 insertions, 75 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9537657ec..3e2b481de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Improved performance of 3D fox logo. - Fetch token prices based on contract address, not symbol - Fix bug that prevents setting language locale in settings. +- Show checksum addresses throughout the UI ## 4.5.5 Fri Apr 06 2018 diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index b372326ee..3b20ab49a 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -908,5 +908,8 @@ }, "youSign": { "message": "You are signing" + }, + "generatingTransaction": { + "message": "Generating transaction" } } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 34b603b96..63d27c40e 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -102,7 +102,6 @@ ConfigManager.prototype.setShowSeedWords = function (should) { this.setData(data) } - ConfigManager.prototype.getShouldShowSeedWords = function () { var data = this.getData() return data.showSeedWords @@ -118,6 +117,27 @@ ConfigManager.prototype.getSeedWords = function () { var data = this.getData() return data.seedWords } + +/** + * Called to set the isRevealingSeedWords flag. This happens only when the user chooses to reveal + * the seed words and not during the first time flow. + * @param {boolean} reveal - Value to set the isRevealingSeedWords flag. + */ +ConfigManager.prototype.setIsRevealingSeedWords = function (reveal = false) { + const data = this.getData() + data.isRevealingSeedWords = reveal + this.setData(data) +} + +/** + * Returns the isRevealingSeedWords flag. + * @returns {boolean|undefined} + */ +ConfigManager.prototype.getIsRevealingSeedWords = function () { + const data = this.getData() + return data.isRevealingSeedWords +} + ConfigManager.prototype.setRpcTarget = function (rpcUrl) { var config = this.getConfig() config.provider = { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a12b6776e..782bc50ac 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -308,6 +308,7 @@ module.exports = class MetamaskController extends EventEmitter { lostAccounts: this.configManager.getLostAccounts(), seedWords: this.configManager.getSeedWords(), forgottenPassword: this.configManager.getPasswordForgotten(), + isRevealingSeedWords: Boolean(this.configManager.getIsRevealingSeedWords()), }, } } @@ -347,6 +348,7 @@ module.exports = class MetamaskController extends EventEmitter { clearSeedWordCache: this.clearSeedWordCache.bind(this), resetAccount: nodeify(this.resetAccount, this), importAccountWithStrategy: this.importAccountWithStrategy.bind(this), + setIsRevealingSeedWords: this.configManager.setIsRevealingSeedWords.bind(this.configManager), // vault management submitPassword: nodeify(keyringController.submitPassword, keyringController), diff --git a/mascara/src/app/first-time/confirm-seed-screen.js b/mascara/src/app/first-time/confirm-seed-screen.js index 438f383b1..7c0431431 100644 --- a/mascara/src/app/first-time/confirm-seed-screen.js +++ b/mascara/src/app/first-time/confirm-seed-screen.js @@ -9,7 +9,7 @@ import Identicon from '../../../../ui/app/components/identicon' import { confirmSeedWords, showModal } from '../../../../ui/app/actions' import Breadcrumbs from './breadcrumbs' import LoadingScreen from './loading-screen' -import { DEFAULT_ROUTE } from '../../../../ui/app/routes' +import { DEFAULT_ROUTE, INITIALIZE_BACKUP_PHRASE_ROUTE } from '../../../../ui/app/routes' class ConfirmSeedScreen extends Component { static propTypes = { @@ -53,7 +53,7 @@ class ConfirmSeedScreen extends Component { } render () { - const { seedWords } = this.props + const { seedWords, history } = this.props const { selectedSeeds, shuffledSeeds } = this.state const isValid = seedWords === selectedSeeds.map(([_, seed]) => seed).join(' ') @@ -66,6 +66,16 @@ class ConfirmSeedScreen extends Component { <div className="first-view-main-wrapper"> <div className="first-view-main"> <div className="backup-phrase"> + <a + className="backup-phrase__back-button" + onClick={e => { + e.preventDefault() + history.push(INITIALIZE_BACKUP_PHRASE_ROUTE) + }} + href="#" + > + {`< Back`} + </a> <Identicon address={this.props.address} diameter={70} /> <div className="backup-phrase__content-wrapper"> <div> diff --git a/mascara/src/app/first-time/seed-screen.js b/mascara/src/app/first-time/seed-screen.js index d004be77b..9af9ca3be 100644 --- a/mascara/src/app/first-time/seed-screen.js +++ b/mascara/src/app/first-time/seed-screen.js @@ -8,6 +8,7 @@ import Identicon from '../../../../ui/app/components/identicon' import Breadcrumbs from './breadcrumbs' import LoadingScreen from './loading-screen' import { DEFAULT_ROUTE, INITIALIZE_CONFIRM_SEED_ROUTE } from '../../../../ui/app/routes' +import { confirmSeedWords } from '../../../../ui/app/actions' const LockIcon = props => ( <svg @@ -44,6 +45,8 @@ class BackupPhraseScreen extends Component { address: PropTypes.string.isRequired, seedWords: PropTypes.string, history: PropTypes.object, + isRevealingSeedWords: PropTypes.bool, + clearSeedWords: PropTypes.func, }; static defaultProps = { @@ -58,6 +61,14 @@ class BackupPhraseScreen extends Component { } componentWillMount () { + this.checkSeedWords() + } + + componentDidUpdate () { + this.checkSeedWords() + } + + checkSeedWords () { const { seedWords, history } = this.props if (!seedWords) { @@ -92,9 +103,29 @@ class BackupPhraseScreen extends Component { ) } - renderSecretScreen () { + renderSubmitButton () { + const { isRevealingSeedWords, clearSeedWords, history } = this.props const { isShowingSecret } = this.state - const { history } = this.props + + return isRevealingSeedWords + ? <button + className="first-time-flow__button" + onClick={() => clearSeedWords().then(() => history.push(DEFAULT_ROUTE))} + disabled={!isShowingSecret} + > + Done + </button> + : <button + className="first-time-flow__button" + onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)} + disabled={!isShowingSecret} + > + Next + </button> + } + + renderSecretScreen () { + const { isRevealingSeedWords } = this.props return ( <div className="backup-phrase__content-wrapper"> @@ -121,14 +152,8 @@ class BackupPhraseScreen extends Component { </div> </div> <div className="backup-phrase__next-button"> - <button - className="first-time-flow__button" - onClick={() => isShowingSecret && history.push(INITIALIZE_CONFIRM_SEED_ROUTE)} - disabled={!isShowingSecret} - > - Next - </button> - <Breadcrumbs total={3} currentIndex={1} /> + { this.renderSubmitButton() } + { !isRevealingSeedWords && <Breadcrumbs total={3} currentIndex={1} />} </div> </div> ) @@ -150,13 +175,25 @@ class BackupPhraseScreen extends Component { } } +const mapStateToProps = ({ metamask, appState }) => { + const { selectedAddress, seedWords, isRevealingSeedWords } = metamask + const { isLoading } = appState + + return { + seedWords, + isRevealingSeedWords, + isLoading, + address: selectedAddress, + } +} + +const mapDispatchToProps = dispatch => { + return { + clearSeedWords: () => dispatch(confirmSeedWords()), + } +} + export default compose( withRouter, - connect( - ({ metamask: { selectedAddress, seedWords }, appState: { isLoading } }) => ({ - seedWords, - isLoading, - address: selectedAddress, - }) - ) + connect(mapStateToProps, mapDispatchToProps), )(BackupPhraseScreen) diff --git a/test/integration/lib/tx-list-items.js b/test/integration/lib/tx-list-items.js index d0056eb94..0c0c5a77f 100644 --- a/test/integration/lib/tx-list-items.js +++ b/test/integration/lib/tx-list-items.js @@ -53,7 +53,7 @@ async function runTxListItemsTest(assert, done) { const confirmedTokenTx = txListItems[6] const confirmedTokenTxAddress = await findAsync($(confirmedTokenTx), '.tx-list-account') - assert.equal(confirmedTokenTxAddress[0].textContent, '0xe7884118...81a9', 'confirmedTokenTx has correct address') + assert.equal(confirmedTokenTxAddress[0].textContent, '0xE7884118...81a9', 'confirmedTokenTx has correct address') const rejectedTx = txListItems[7] const rejectedTxRenderedStatus = await findAsync($(rejectedTx), '.tx-list-status') diff --git a/ui/app/actions.js b/ui/app/actions.js index f5cdd32bc..73335db97 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -351,7 +351,6 @@ function confirmSeedWords () { 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) @@ -362,6 +361,9 @@ function confirmSeedWords () { resolve(account) }) }) + .then(() => dispatch(setIsRevealingSeedWords(false))) + .then(() => dispatch(actions.hideLoadingIndication())) + .catch(() => dispatch(actions.hideLoadingIndication())) } } @@ -446,11 +448,13 @@ function requestRevealSeed (password) { } dispatch(actions.showNewVaultSeed(result)) - dispatch(actions.hideLoadingIndication()) resolve() }) }) }) + .then(() => dispatch(setIsRevealingSeedWords(true))) + .then(() => dispatch(actions.hideLoadingIndication())) + .catch(() => dispatch(actions.hideLoadingIndication())) } } @@ -1907,3 +1911,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 827b4e9ce..0b38b1326 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -56,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 () { @@ -137,8 +146,6 @@ class App extends Component { loadingMessage: loadMessage, }), - // this.renderLoadingIndicator({ isLoading, isLoadingNetwork, loadMessage }), - // content this.renderRoutes(), ]) @@ -302,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 @@ -406,6 +402,8 @@ App.propTypes = { isMouseUser: PropTypes.bool, setMouseUserState: PropTypes.func, t: PropTypes.func, + isRevealingSeedWords: PropTypes.bool, + clearSeedWords: PropTypes.func, } function mapStateToProps (state) { @@ -486,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/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/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/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/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/tx-list-item.js b/ui/app/components/tx-list-item.js index 403f83ab9..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') @@ -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') 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/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/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) : '' +} diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index 31498a3a9..7fadbceff 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -1,6 +1,6 @@ var iconFactory const isValidAddress = require('ethereumjs-util').isValidAddress -const toChecksumAddress = require('ethereumjs-util').toChecksumAddress +const { checksumAddress } = require('../app/util') const contractMap = require('eth-contract-metadata') module.exports = function (jazzicon) { @@ -16,7 +16,7 @@ function IconFactory (jazzicon) { } IconFactory.prototype.iconForAddress = function (address, diameter) { - const addr = toChecksumAddress(address) + const addr = checksumAddress(address) if (iconExistsFor(addr)) { return imageElFor(addr) } |