aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkumavis <kumavis@users.noreply.github.com>2018-03-31 09:36:08 +0800
committerGitHub <noreply@github.com>2018-03-31 09:36:08 +0800
commit2e57c36f36165e85cabeffc3cf0ade4998e352e1 (patch)
tree4d7c825b46b64e1773ac73964eb859dd3986052b
parente99a707e3d5c0ad439930e72bad4cf0b5e005099 (diff)
parent2be6f8bae0e516d49c83776a06dcbf82971a0a19 (diff)
downloadtangerine-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
-rw-r--r--ui/app/components/customize-gas-modal/index.js3
-rw-r--r--ui/app/components/pending-tx/confirm-send-ether.js74
-rw-r--r--ui/app/components/pending-tx/confirm-send-token.js69
-rw-r--r--ui/app/components/send/send-utils.js12
-rw-r--r--ui/app/css/itcss/components/confirm.scss25
-rw-r--r--ui/app/send-v2.js13
6 files changed, 175 insertions, 21 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,
}
diff --git a/ui/app/css/itcss/components/confirm.scss b/ui/app/css/itcss/components/confirm.scss
index abe138f54..85ff14e6e 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,30 @@ 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-confirm-button {
height: 50px;
border-radius: 4px;
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js
index 910312b47..bcc5cb03d 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')
@@ -132,7 +133,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 })
})
@@ -140,19 +141,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 },