diff options
author | Alexander Tseung <alextsg@gmail.com> | 2018-04-03 16:03:31 +0800 |
---|---|---|
committer | Alexander Tseung <alextsg@gmail.com> | 2018-04-03 16:03:31 +0800 |
commit | 35875863d2feafc1f653e17e0f58efc2f18ddc46 (patch) | |
tree | 5d40581a08201b3f37c7b31fe2aab4675d827f6b /ui | |
parent | 516c1869b0f366a42282a66e14185ce630f883dd (diff) | |
parent | c14ec4191741c444dcf5b7c3e177c17a10374c16 (diff) | |
download | tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.gz tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.bz2 tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.lz tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.xz tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.tar.zst tangerine-wallet-browser-35875863d2feafc1f653e17e0f58efc2f18ddc46.zip |
Fix merge conflicts. Modify send workflow
Diffstat (limited to 'ui')
-rw-r--r-- | ui/app/actions.js | 5 | ||||
-rw-r--r-- | ui/app/app.js | 5 | ||||
-rw-r--r-- | ui/app/components/customize-gas-modal/index.js | 3 | ||||
-rw-r--r-- | ui/app/components/dropdowns/network-dropdown.js | 8 | ||||
-rw-r--r-- | ui/app/components/identicon.js | 5 | ||||
-rw-r--r-- | ui/app/components/pages/home.js | 29 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-ether.js | 110 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-token.js | 107 | ||||
-rw-r--r-- | ui/app/components/send/send-utils.js | 12 | ||||
-rw-r--r-- | ui/app/components/tx-list-item.js | 21 | ||||
-rw-r--r-- | ui/app/components/tx-list.js | 5 | ||||
-rw-r--r-- | ui/app/conf-tx.js | 25 | ||||
-rw-r--r-- | ui/app/css/itcss/components/confirm.scss | 36 | ||||
-rw-r--r-- | ui/app/send-v2.js | 17 | ||||
-rw-r--r-- | ui/index.js | 10 |
15 files changed, 331 insertions, 67 deletions
diff --git a/ui/app/actions.js b/ui/app/actions.js index 08df31e1f..0748a5bea 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -1374,7 +1374,7 @@ function retryTransaction (txId) { function setProviderType (type) { return (dispatch) => { - log.debug(`background.setProviderType`) + log.debug(`background.setProviderType`, type) background.setProviderType(type, (err, result) => { if (err) { log.error(err) @@ -1395,13 +1395,14 @@ function updateProviderType (type) { } function setRpcTarget (newRpc) { - log.debug(`background.setRpcTarget: ${newRpc}`) return (dispatch) => { + log.debug(`background.setRpcTarget: ${newRpc}`) background.setCustomRpc(newRpc, (err, result) => { if (err) { log.error(err) return dispatch(self.displayWarning('Had a problem changing networks!')) } + dispatch(actions.setSelectedToken()) }) } } diff --git a/ui/app/app.js b/ui/app/app.js index 52e5e00a8..82871d970 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -77,7 +77,6 @@ class App extends Component { component: RevealSeedPage, mascaraComponent: MascaraSeedScreen, }), - // h(Initialized, { path: CONFIRM_SEED_ROUTE, exact, component: MascaraConfirmSeedScreen }), h(Initialized, { path: UNLOCK_ROUTE, exact, component: UnlockPage }), h(Initialized, { path: SETTINGS_ROUTE, component: Settings }), h(Initialized, { path: RESTORE_VAULT_ROUTE, exact, component: RestoreVaultPage }), @@ -214,7 +213,6 @@ class App extends Component { networkDropdownOpen, showNetworkDropdown, hideNetworkDropdown, - currentView, isInitialized, welcomeScreenSeen, isPopup, @@ -276,7 +274,7 @@ class App extends Component { h(NetworkIndicator, { network, provider, - disabled: currentView.name === 'confTx', + disabled: this.props.location.pathname === CONFIRM_TRANSACTION_ROUTE, onClick: (event) => { event.preventDefault() event.stopPropagation() @@ -395,6 +393,7 @@ App.propTypes = { showNetworkDropdown: PropTypes.func, hideNetworkDropdown: PropTypes.func, history: PropTypes.object, + location: PropTypes.object, dispatch: PropTypes.func, toggleAccountMenu: PropTypes.func, selectedAddress: PropTypes.string, diff --git a/ui/app/components/customize-gas-modal/index.js b/ui/app/components/customize-gas-modal/index.js index 825366cb2..4c693d1c3 100644 --- a/ui/app/components/customize-gas-modal/index.js +++ b/ui/app/components/customize-gas-modal/index.js @@ -65,6 +65,7 @@ function mapDispatchToProps (dispatch) { updateGasLimit: newGasLimit => dispatch(actions.updateGasLimit(newGasLimit)), updateGasTotal: newGasTotal => dispatch(actions.updateGasTotal(newGasTotal)), updateSendAmount: newAmount => dispatch(actions.updateSendAmount(newAmount)), + updateSendErrors: error => dispatch(actions.updateSendErrors(error)), } } @@ -112,6 +113,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { selectedToken, balance, updateSendAmount, + updateSendErrors, } = this.props if (maxModeOn && !selectedToken) { @@ -126,6 +128,7 @@ CustomizeGasModal.prototype.save = function (gasPrice, gasLimit, gasTotal) { updateGasPrice(ethUtil.addHexPrefix(gasPrice)) updateGasLimit(ethUtil.addHexPrefix(gasLimit)) updateGasTotal(ethUtil.addHexPrefix(gasTotal)) + updateSendErrors({ insufficientFunds: false }) hideModal() } diff --git a/ui/app/components/dropdowns/network-dropdown.js b/ui/app/components/dropdowns/network-dropdown.js index 94e5d967b..9e47f38ef 100644 --- a/ui/app/components/dropdowns/network-dropdown.js +++ b/ui/app/components/dropdowns/network-dropdown.js @@ -203,18 +203,18 @@ NetworkDropdown.prototype.render = function () { { key: 'default', closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => props.setRpcTarget('http://localhost:8545'), + onClick: () => props.setProviderType('localhost'), style: dropdownMenuItemStyle, }, [ - activeNetwork === 'http://localhost:8545' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), + providerType === 'localhost' ? h('i.fa.fa-check') : h('.network-check__transparent', '✓'), h(NetworkDropdownIcon, { - isSelected: activeNetwork === 'http://localhost:8545', + isSelected: providerType === 'localhost', innerBorder: '1px solid #9b9b9b', }), h('span.network-name-item', { style: { - color: activeNetwork === 'http://localhost:8545' ? '#ffffff' : '#9b9b9b', + color: providerType === 'localhost' ? '#ffffff' : '#9b9b9b', }, }, this.context.t('localhost')), ] diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index 7cc5a4de0..dce9b0449 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -105,9 +105,8 @@ IdenticonComponent.prototype.componentDidUpdate = function () { function _generateBlockie (container, address, diameter) { const img = new Image() img.src = toDataUrl(address) - const dia = !diameter || diameter < 50 ? 50 : diameter - img.height = dia * 1.25 - img.width = dia * 1.25 + img.height = diameter + img.width = diameter container.appendChild(img) } diff --git a/ui/app/components/pages/home.js b/ui/app/components/pages/home.js index ffe35a2a8..177d9b4e7 100644 --- a/ui/app/components/pages/home.js +++ b/ui/app/components/pages/home.js @@ -27,21 +27,6 @@ const { } = require('../../routes') class Home extends Component { - componentDidMount () { - const { - unapprovedTxs = {}, - unapprovedMsgCount = 0, - unapprovedPersonalMsgCount = 0, - unapprovedTypedMessagesCount = 0, - } = this.props - - // unapprovedTxs and unapproved messages - if (Object.keys(unapprovedTxs).length || - unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) { - this.props.history.push(CONFIRM_TRANSACTION_ROUTE) - } - } - render () { log.debug('rendering primary') const { @@ -51,6 +36,10 @@ class Home extends Component { currentView, activeAddress, seedWords, + unapprovedTxs = {}, + unapprovedMsgCount = 0, + unapprovedPersonalMsgCount = 0, + unapprovedTypedMessagesCount = 0, } = this.props // notices @@ -81,6 +70,16 @@ class Home extends Component { }) } + // unapprovedTxs and unapproved messages + if (Object.keys(unapprovedTxs).length || + unapprovedTypedMessagesCount + unapprovedMsgCount + unapprovedPersonalMsgCount > 0) { + return h(Redirect, { + to: { + pathname: CONFIRM_TRANSACTION_ROUTE, + }, + }) + } + // if (!props.noActiveNotices) { // log.debug('rendering notice screen for unread notices.') // return h(NoticeScreen, { diff --git a/ui/app/components/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index 3576d4405..4e2f763fc 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -10,11 +10,16 @@ const clone = require('clone') const ethUtil = require('ethereumjs-util') const BN = ethUtil.BN const hexToBn = require('../../../../app/scripts/lib/hex-to-bn') +const classnames = require('classnames') const { conversionUtil, addCurrencies, multiplyCurrencies, } = require('../../conversion-util') +const { + getGasTotal, + isBalanceSufficient, +} = require('../send/send-utils') const GasFeeDisplay = require('../send/gas-fee-display-v2') const SenderToRecipient = require('../sender-to-recipient') const NetworkDisplay = require('../network-display') @@ -41,12 +46,14 @@ function mapStateToProps (state) { } = state.metamask const accounts = state.metamask.accounts const selectedAddress = state.metamask.selectedAddress || Object.keys(accounts)[0] + const { balance } = accounts[selectedAddress] return { conversionRate, identities, selectedAddress, currentCurrency, send, + balance, } } @@ -96,6 +103,7 @@ function mapDispatchToProps (dispatch) { })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, + updateSendErrors: error => dispatch(actions.updateSendErrors(error)), } } @@ -106,6 +114,52 @@ function ConfirmSendEther () { this.onSubmit = this.onSubmit.bind(this) } +ConfirmSendEther.prototype.updateComponentSendErrors = function (prevProps) { + const { + balance: oldBalance, + conversionRate: oldConversionRate, + } = prevProps + const { + updateSendErrors, + balance, + conversionRate, + send: { + errors: { + simulationFails, + }, + }, + } = this.props + const txMeta = this.gatherTxMeta() + + const shouldUpdateBalanceSendErrors = balance && [ + balance !== oldBalance, + conversionRate !== oldConversionRate, + ].some(x => Boolean(x)) + + if (shouldUpdateBalanceSendErrors) { + const balanceIsSufficient = this.isBalanceSufficient(txMeta) + updateSendErrors({ + insufficientFunds: balanceIsSufficient ? false : this.context.t('insufficientFunds'), + }) + } + + const shouldUpdateSimulationSendError = Boolean(txMeta.simulationFails) !== Boolean(simulationFails) + + if (shouldUpdateSimulationSendError) { + updateSendErrors({ + simulationFails: !txMeta.simulationFails ? false : this.context.t('transactionError'), + }) + } +} + +ConfirmSendEther.prototype.componentWillMount = function () { + this.updateComponentSendErrors({}) +} + +ConfirmSendEther.prototype.componentDidUpdate = function (prevProps) { + this.updateComponentSendErrors(prevProps) +} + ConfirmSendEther.prototype.getAmount = function () { const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() @@ -234,7 +288,12 @@ ConfirmSendEther.prototype.render = function () { conversionRate, currentCurrency: convertedCurrency, showCustomizeGasModal, - send: { gasTotal, gasLimit: sendGasLimit, gasPrice: sendGasPrice }, + send: { + gasTotal, + gasLimit: sendGasLimit, + gasPrice: sendGasPrice, + errors, + }, } = this.props const txMeta = this.gatherTxMeta() const txParams = txMeta.txParams || {} @@ -342,7 +401,12 @@ ConfirmSendEther.prototype.render = function () { ]), h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [ - h('div.confirm-screen-section-column', [ + h('div', { + className: classnames({ + 'confirm-screen-section-column--with-error': errors['insufficientFunds'], + 'confirm-screen-section-column': !errors['insufficientFunds'], + }), + }, [ h('span.confirm-screen-label', [ this.context.t('total') + ' ' ]), h('div.confirm-screen-total-box__subtitle', [ this.context.t('amountPlusGas') ]), ]), @@ -351,6 +415,8 @@ ConfirmSendEther.prototype.render = function () { h('div.confirm-screen-row-info', `${totalInFIAT} ${currentCurrency.toUpperCase()}`), h('div.confirm-screen-row-detail', `${totalInETH} ETH`), ]), + + this.renderErrorMessage('insufficientFunds'), ]), ]), @@ -436,8 +502,10 @@ ConfirmSendEther.prototype.render = function () { ]), h('form#pending-tx-form', { + className: 'confirm-screen-form', onSubmit: this.onSubmit, }, [ + this.renderErrorMessage('simulationFails'), h('.page-container__footer', [ // Cancel Button h('button.btn-cancel.page-container__footer-button.allcaps', { @@ -455,16 +523,28 @@ ConfirmSendEther.prototype.render = function () { ) } +ConfirmSendEther.prototype.renderErrorMessage = function (message) { + const { send: { errors } } = this.props + + return errors[message] + ? h('div.confirm-screen-error', [ errors[message] ]) + : null +} + ConfirmSendEther.prototype.onSubmit = function (event) { event.preventDefault() + const { updateSendErrors } = this.props const txMeta = this.gatherTxMeta() const valid = this.checkValidity() + const balanceIsSufficient = this.isBalanceSufficient(txMeta) this.setState({ valid, submitting: true }) - if (valid && this.verifyGasParams()) { + if (valid && this.verifyGasParams() && balanceIsSufficient) { this.props.sendTransaction(txMeta, event) + } else if (!balanceIsSufficient) { + updateSendErrors({ insufficientFunds: this.context.t('insufficientFunds') }) } else { - this.props.dispatch(actions.displayWarning(this.context.t('invalidGasParams'))) + updateSendErrors({ invalidGasParams: this.context.t('invalidGasParams') }) this.setState({ submitting: false }) } } @@ -477,6 +557,28 @@ ConfirmSendEther.prototype.cancel = function (event, txMeta) { .then(() => this.props.history.push(DEFAULT_ROUTE)) } +ConfirmSendEther.prototype.isBalanceSufficient = function (txMeta) { + const { + balance, + conversionRate, + } = this.props + const { + txParams: { + gas, + gasPrice, + value: amount, + }, + } = txMeta + const gasTotal = getGasTotal(gas, gasPrice) + + return isBalanceSufficient({ + amount, + gasTotal, + balance, + conversionRate, + }) +} + ConfirmSendEther.prototype.checkValidity = function () { const form = this.getFormEl() const valid = form.checkValidity() diff --git a/ui/app/components/pending-tx/confirm-send-token.js b/ui/app/components/pending-tx/confirm-send-token.js index 9f978b848..5e6d0747d 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -20,8 +20,13 @@ const { addCurrencies, } = require('../../conversion-util') const { + getGasTotal, + isBalanceSufficient, +} = require('../send/send-utils') +const { calcTokenAmount, } = require('../../token-util') +const classnames = require('classnames') const { MIN_GAS_PRICE_HEX } = require('../send/send-constants') @@ -52,9 +57,10 @@ function mapStateToProps (state, ownProps) { identities, currentCurrency, } = state.metamask + const accounts = state.metamask.accounts const selectedAddress = getSelectedAddress(state) const tokenExchangeRate = getTokenExchangeRate(state, symbol) - + const { balance } = accounts[selectedAddress] return { conversionRate, identities, @@ -64,6 +70,7 @@ function mapStateToProps (state, ownProps) { currentCurrency: currentCurrency.toUpperCase(), send: state.metamask.send, tokenContract: getSelectedTokenContract(state), + balance, } } @@ -135,6 +142,7 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, + updateSendErrors: error => dispatch(actions.updateSendErrors(error)), } } @@ -151,6 +159,44 @@ ConfirmSendToken.prototype.editTransaction = function (txMeta) { history.push(SEND_ROUTE) } +ConfirmSendToken.prototype.updateComponentSendErrors = function (prevProps) { + const { + balance: oldBalance, + conversionRate: oldConversionRate, + } = prevProps + const { + updateSendErrors, + balance, + conversionRate, + send: { + errors: { + simulationFails, + }, + }, + } = this.props + const txMeta = this.gatherTxMeta() + + const shouldUpdateBalanceSendErrors = balance && [ + balance !== oldBalance, + conversionRate !== oldConversionRate, + ].some(x => Boolean(x)) + + if (shouldUpdateBalanceSendErrors) { + const balanceIsSufficient = this.isBalanceSufficient(txMeta) + updateSendErrors({ + insufficientFunds: balanceIsSufficient ? false : this.context.t('insufficientFunds'), + }) + } + + const shouldUpdateSimulationSendError = Boolean(txMeta.simulationFails) !== Boolean(simulationFails) + + if (shouldUpdateSimulationSendError) { + updateSendErrors({ + simulationFails: !txMeta.simulationFails ? false : this.context.t('transactionError'), + }) + } +} + ConfirmSendToken.prototype.componentWillMount = function () { const { tokenContract, selectedAddress } = this.props tokenContract && tokenContract @@ -158,6 +204,11 @@ ConfirmSendToken.prototype.componentWillMount = function () { .then(usersToken => { }) this.props.updateTokenExchangeRate() + this.updateComponentSendErrors({}) +} + +ConfirmSendToken.prototype.componentDidUpdate = function (prevProps) { + this.updateComponentSendErrors(prevProps) } ConfirmSendToken.prototype.getAmount = function () { @@ -318,7 +369,7 @@ ConfirmSendToken.prototype.renderGasFee = function () { } ConfirmSendToken.prototype.renderTotalPlusGas = function () { - const { token: { symbol }, currentCurrency } = this.props + const { token: { symbol }, currentCurrency, send: { errors } } = this.props const { fiat: fiatAmount, token: tokenAmount } = this.getAmount() const { fiat: fiatGas, token: tokenGas } = this.getGasFee() @@ -338,7 +389,12 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { ) : ( h('section.flex-row.flex-center.confirm-screen-row.confirm-screen-total-box ', [ - h('div.confirm-screen-section-column', [ + h('div', { + className: classnames({ + 'confirm-screen-section-column--with-error': errors['insufficientFunds'], + 'confirm-screen-section-column': !errors['insufficientFunds'], + }), + }, [ h('span.confirm-screen-label', [ this.context.t('total') + ' ' ]), h('div.confirm-screen-total-box__subtitle', [ this.context.t('amountPlusGas') ]), ]), @@ -347,12 +403,21 @@ ConfirmSendToken.prototype.renderTotalPlusGas = function () { h('div.confirm-screen-row-info', `${tokenAmount} ${symbol}`), h('div.confirm-screen-row-detail', `+ ${fiatGas} ${currentCurrency} ${this.context.t('gas')}`), ]), + + this.renderErrorMessage('insufficientFunds'), ]) ) } +ConfirmSendToken.prototype.renderErrorMessage = function (message) { + const { send: { errors } } = this.props + + return errors[message] + ? h('div.confirm-screen-error', [ errors[message] ]) + : null +} + ConfirmSendToken.prototype.render = function () { - const { editTransaction } = this.props const txMeta = this.gatherTxMeta() const { from: { @@ -379,7 +444,7 @@ ConfirmSendToken.prototype.render = function () { h('div.page-container', [ h('div.page-container__header', [ !txMeta.lastGasPrice && h('button.confirm-screen-back-button', { - onClick: () => editTransaction(txMeta), + onClick: () => this.editTransaction(txMeta), }, this.context.t('edit')), h('div.page-container__title', title), h('div.page-container__subtitle', subtitle), @@ -448,8 +513,10 @@ ConfirmSendToken.prototype.render = function () { ]), h('form#pending-tx-form', { + className: 'confirm-screen-form', onSubmit: this.onSubmit, }, [ + this.renderErrorMessage('simulationFails'), h('.page-container__footer', [ // Cancel Button h('button.btn-cancel.page-container__footer-button.allcaps', { @@ -467,18 +534,44 @@ ConfirmSendToken.prototype.render = function () { ConfirmSendToken.prototype.onSubmit = function (event) { event.preventDefault() + const { updateSendErrors } = this.props const txMeta = this.gatherTxMeta() const valid = this.checkValidity() + const balanceIsSufficient = this.isBalanceSufficient(txMeta) this.setState({ valid, submitting: true }) - if (valid && this.verifyGasParams()) { + if (valid && this.verifyGasParams() && balanceIsSufficient) { this.props.sendTransaction(txMeta, event) + } else if (!balanceIsSufficient) { + updateSendErrors({ insufficientFunds: this.context.t('insufficientFunds') }) } else { - this.props.dispatch(actions.displayWarning(this.context.t('invalidGasParams'))) + updateSendErrors({ invalidGasParams: this.context.t('invalidGasParams') }) this.setState({ submitting: false }) } } +ConfirmSendToken.prototype.isBalanceSufficient = function (txMeta) { + const { + balance, + conversionRate, + } = this.props + const { + txParams: { + gas, + gasPrice, + }, + } = txMeta + const gasTotal = getGasTotal(gas, gasPrice) + + return isBalanceSufficient({ + amount: '0', + gasTotal, + balance, + conversionRate, + }) +} + + ConfirmSendToken.prototype.cancel = function (event, txMeta) { event.preventDefault() const { cancelTransaction } = this.props diff --git a/ui/app/components/send/send-utils.js b/ui/app/components/send/send-utils.js index d8211930d..71bfb2668 100644 --- a/ui/app/components/send/send-utils.js +++ b/ui/app/components/send/send-utils.js @@ -2,6 +2,7 @@ const { addCurrencies, conversionUtil, conversionGTE, + multiplyCurrencies, } = require('../../conversion-util') const { calcTokenAmount, @@ -31,7 +32,7 @@ function isBalanceSufficient ({ { value: totalAmount, fromNumericBase: 'hex', - conversionRate: amountConversionRate, + conversionRate: amountConversionRate || conversionRate, fromCurrency: primaryCurrency, }, ) @@ -62,7 +63,16 @@ function isTokenBalanceSufficient ({ return tokenBalanceIsSufficient } +function getGasTotal (gasLimit, gasPrice) { + return multiplyCurrencies(gasLimit, gasPrice, { + toNumericBase: 'hex', + multiplicandBase: 16, + multiplierBase: 16, + }) +} + module.exports = { + getGasTotal, isBalanceSufficient, isTokenBalanceSufficient, } diff --git a/ui/app/components/tx-list-item.js b/ui/app/components/tx-list-item.js index 622664786..42c008798 100644 --- a/ui/app/components/tx-list-item.js +++ b/ui/app/components/tx-list-item.js @@ -68,20 +68,24 @@ TxListItem.prototype.getAddressText = function () { const { address, txParams = {}, + isMsg, } = this.props const decodedData = txParams.data && abiDecoder.decodeMethod(txParams.data) const { name: txDataName, params = [] } = decodedData || {} const { value } = params[0] || {} - switch (txDataName) { - case 'transfer': - return `${value.slice(0, 10)}...${value.slice(-4)}` - default: - return address - ? `${address.slice(0, 10)}...${address.slice(-4)}` - : this.context.t('contractDeployment') + let addressText + if (txDataName === 'transfer' || address) { + const addressToRender = txDataName === 'transfer' ? value : address + addressText = `${addressToRender.slice(0, 10)}...${addressToRender.slice(-4)}` + } else if (isMsg) { + addressText = this.context.t('sigRequest') + } else { + addressText = this.context.t('contractDeployment') } + + return addressText } TxListItem.prototype.getSendEtherTotal = function () { @@ -191,6 +195,9 @@ TxListItem.prototype.showRetryButton = function () { transactionId, txParams, } = this.props + if (!txParams) { + return false + } const currentNonce = txParams.nonce const currentNonceTxs = selectedAddressTxList.filter(tx => tx.txParams.nonce === currentNonce) const currentNonceSubmittedTxs = currentNonceTxs.filter(tx => tx.status === 'submitted') diff --git a/ui/app/components/tx-list.js b/ui/app/components/tx-list.js index 70643aa36..554febcff 100644 --- a/ui/app/components/tx-list.js +++ b/ui/app/components/tx-list.js @@ -82,9 +82,9 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa const props = { dateString: formatDate(transaction.time), - address: transaction.txParams.to, + address: transaction.txParams && transaction.txParams.to, transactionStatus: transaction.status, - transactionAmount: transaction.txParams.value, + transactionAmount: transaction.txParams && transaction.txParams.value, transactionId: transaction.id, transactionHash: transaction.hash, transactionNetworkId: transaction.metamaskNetworkId, @@ -106,6 +106,7 @@ TxList.prototype.renderTransactionListItem = function (transaction, conversionRa const opts = { key: transactionId || transactionHash, txParams: transaction.txParams, + isMsg: Boolean(transaction.msgParams), transactionStatus, transactionId, dateString, diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index 3134cf331..886d98be7 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -55,11 +55,25 @@ function ConfirmTxScreen () { Component.call(this) } +ConfirmTxScreen.prototype.componentDidMount = function () { + const { + unapprovedTxs = {}, + network, + send, + } = this.props + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) + + if (unconfTxList.length === 0 && !send.to) { + this.props.history.push(DEFAULT_ROUTE) + } +} + ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { const { - unapprovedTxs, + unapprovedTxs = {}, network, selectedAddressTxList, + send, } = this.props const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network) @@ -67,7 +81,7 @@ ConfirmTxScreen.prototype.componentDidUpdate = function (prevProps) { const prevTx = selectedAddressTxList.find(({ id }) => id === prevTxData.id) || {} const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network) - if (prevTx.status === 'dropped' && unconfTxList.length === 0) { + if (unconfTxList.length === 0 && (prevTx.status === 'dropped' || !send.to)) { this.props.history.push(DEFAULT_ROUTE) } } @@ -109,13 +123,6 @@ ConfirmTxScreen.prototype.render = function () { */ log.info(`rendering a combined ${unconfTxList.length} unconf msg & txs`) - if (unconfTxList.length === 0) { - return h(Redirect, { - to: { - pathname: DEFAULT_ROUTE, - }, - }) - } return currentTxView({ // Properties diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss index abe138f54..47762e8de 100644 --- a/ui/app/css/itcss/components/confirm.scss +++ b/ui/app/css/itcss/components/confirm.scss @@ -266,6 +266,7 @@ section .confirm-screen-account-number, .confirm-screen-total-box { background-color: $wild-sand; + position: relative; .confirm-screen-label { line-height: 21px; @@ -287,6 +288,41 @@ section .confirm-screen-account-number, } } +.confirm-screen-error { + font-size: 12px; + line-height: 12px; + color: #f00; + position: absolute; + right: 12px; + width: 80px; + text-align: right; +} + +.confirm-screen-row.confirm-screen-total-box { + .confirm-screen-section-column--with-error { + flex: 0.6; + } +} + +@media screen and (max-width: 379px) { + .confirm-screen-row.confirm-screen-total-box { + .confirm-screen-section-column--with-error { + flex: 0.4; + } + } +} + +.confirm-screen-form { + position: relative; + + .confirm-screen-error { + right: 0; + width: 100%; + margin-top: 7px; + text-align: center; + } +} + .confirm-screen-confirm-button { height: 50px; border-radius: 4px; diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index abbb97643..b4d38495d 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -27,6 +27,7 @@ const { const { isBalanceSufficient, isTokenBalanceSufficient, + getGasTotal, } = require('./components/send/send-utils') const { isValidAddress } = require('./util') const { CONFIRM_TRANSACTION_ROUTE, DEFAULT_ROUTE } = require('./routes') @@ -133,7 +134,7 @@ SendTransactionScreen.prototype.updateGas = function () { estimateGas(estimateGasParams), ]) .then(([gasPrice, gas]) => { - const newGasTotal = this.getGasTotal(gas, gasPrice) + const newGasTotal = getGasTotal(gas, gasPrice) updateGasTotal(newGasTotal) this.setState({ gasLoadingError: false }) }) @@ -141,19 +142,11 @@ SendTransactionScreen.prototype.updateGas = function () { this.setState({ gasLoadingError: true }) }) } else { - const newGasTotal = this.getGasTotal(gasLimit, gasPrice) + const newGasTotal = getGasTotal(gasLimit, gasPrice) updateGasTotal(newGasTotal) } } -SendTransactionScreen.prototype.getGasTotal = function (gasLimit, gasPrice) { - return multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) -} - SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) { const { from: { balance }, @@ -642,6 +635,10 @@ SendTransactionScreen.prototype.onSubmit = function (event) { txParams.to = to } + Object.keys(txParams).forEach(key => { + txParams[key] = ethUtil.addHexPrefix(txParams[key]) + }) + selectedToken ? signTokenTx(selectedToken.address, to, amount, txParams) : signTx(txParams) diff --git a/ui/index.js b/ui/index.js index 1e0e9f1cc..746e28eab 100644 --- a/ui/index.js +++ b/ui/index.js @@ -69,6 +69,16 @@ async function startApp (metamaskState, accountManager, opts) { store.dispatch(actions.updateMetamaskState(metamaskState)) }) + // global metamask api - used by tooling + global.metamask = { + updateCurrentLocale: (code) => { + store.dispatch(actions.updateCurrentLocale(code)) + }, + setProviderType: (type) => { + store.dispatch(actions.setProviderType(type)) + }, + } + // start app render( h(Root, { |