diff options
author | kumavis <kumavis@users.noreply.github.com> | 2018-03-31 09:36:08 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-31 09:36:08 +0800 |
commit | 2e57c36f36165e85cabeffc3cf0ade4998e352e1 (patch) | |
tree | 4d7c825b46b64e1773ac73964eb859dd3986052b /ui/app/components | |
parent | e99a707e3d5c0ad439930e72bad4cf0b5e005099 (diff) | |
parent | 2be6f8bae0e516d49c83776a06dcbf82971a0a19 (diff) | |
download | tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar.gz tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar.bz2 tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar.lz tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar.xz tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.tar.zst tangerine-wallet-browser-2e57c36f36165e85cabeffc3cf0ade4998e352e1.zip |
Merge pull request #3762 from danjm/i3471-checkbalanceonconfirmscreen
Checking for sufficient balance in tx confirmation screen
Diffstat (limited to 'ui/app/components')
-rw-r--r-- | ui/app/components/customize-gas-modal/index.js | 3 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-ether.js | 74 | ||||
-rw-r--r-- | ui/app/components/pending-tx/confirm-send-token.js | 69 | ||||
-rw-r--r-- | ui/app/components/send/send-utils.js | 12 |
4 files changed, 147 insertions, 11 deletions
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/pending-tx/confirm-send-ether.js b/ui/app/components/pending-tx/confirm-send-ether.js index b68de4704..2474516d4 100644 --- a/ui/app/components/pending-tx/confirm-send-ether.js +++ b/ui/app/components/pending-tx/confirm-send-ether.js @@ -8,11 +8,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') @@ -35,12 +40,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, } } @@ -91,6 +98,7 @@ function mapDispatchToProps (dispatch) { })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, + updateSendErrors: error => dispatch(actions.updateSendErrors(error)), } } @@ -101,6 +109,18 @@ function ConfirmSendEther () { this.onSubmit = this.onSubmit.bind(this) } +ConfirmSendEther.prototype.componentWillMount = function () { + const { updateSendErrors } = this.props + const txMeta = this.gatherTxMeta() + const balanceIsSufficient = this.isBalanceSufficient(txMeta) + + updateSendErrors({ + insufficientFunds: balanceIsSufficient + ? false + : this.context.t('insufficientFunds'), + }) +} + ConfirmSendEther.prototype.getAmount = function () { const { conversionRate, currentCurrency } = this.props const txMeta = this.gatherTxMeta() @@ -223,7 +243,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 || {} @@ -331,7 +356,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') ]), ]), @@ -340,6 +370,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'), ]), ]), @@ -444,16 +476,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 }) } } @@ -465,6 +509,28 @@ ConfirmSendEther.prototype.cancel = function (event, txMeta) { cancelTransaction(txMeta) } +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 7fe260a61..dd9fdc23f 100644 --- a/ui/app/components/pending-tx/confirm-send-token.js +++ b/ui/app/components/pending-tx/confirm-send-token.js @@ -18,8 +18,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') @@ -46,9 +51,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, @@ -58,6 +64,7 @@ function mapStateToProps (state, ownProps) { currentCurrency: currentCurrency.toUpperCase(), send: state.metamask.send, tokenContract: getSelectedTokenContract(state), + balance, } } @@ -129,6 +136,7 @@ function mapDispatchToProps (dispatch, ownProps) { })) dispatch(actions.showModal({ name: 'CUSTOMIZE_GAS' })) }, + updateSendErrors: error => dispatch(actions.updateSendErrors(error)), } } @@ -140,12 +148,20 @@ function ConfirmSendToken () { } ConfirmSendToken.prototype.componentWillMount = function () { - const { tokenContract, selectedAddress } = this.props + const { tokenContract, selectedAddress, updateSendErrors} = this.props + const txMeta = this.gatherTxMeta() + const balanceIsSufficient = this.isBalanceSufficient(txMeta) tokenContract && tokenContract .balanceOf(selectedAddress) .then(usersToken => { }) this.props.updateTokenExchangeRate() + + updateSendErrors({ + insufficientFunds: balanceIsSufficient + ? false + : this.context.t('insufficientFunds'), + }) } ConfirmSendToken.prototype.getAmount = function () { @@ -306,7 +322,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() @@ -326,7 +342,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') ]), ]), @@ -335,10 +356,20 @@ 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() @@ -455,18 +486,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, } |