diff options
Diffstat (limited to 'ui/app/send-v2.js')
-rw-r--r-- | ui/app/send-v2.js | 131 |
1 files changed, 108 insertions, 23 deletions
diff --git a/ui/app/send-v2.js b/ui/app/send-v2.js index 6ce3e1b70..8ad2b912c 100644 --- a/ui/app/send-v2.js +++ b/ui/app/send-v2.js @@ -10,14 +10,19 @@ const MemoTextArea = require('./components/send/memo-textarea') const GasFeeDisplay = require('./components/send/gas-fee-display-v2') const { MIN_GAS_TOTAL } = require('./components/send/send-constants') +const abi = require('human-standard-token-abi') const { multiplyCurrencies, conversionGreaterThan, } = require('./conversion-util') const { + calcTokenAmount, +} = require('./token-util') +const { isBalanceSufficient, -} = require('./components/send/send-utils.js') + isTokenBalanceSufficient, +} = require('./components/send/send-utils') const { isValidAddress } = require('./util') module.exports = SendTransactionScreen @@ -40,6 +45,37 @@ function SendTransactionScreen () { this.validateAmount = this.validateAmount.bind(this) } +const getParamsForGasEstimate = function (selectedAddress, symbol, data) { + const estimatedGasParams = { + from: selectedAddress, + gas: '746a528800', + } + + if (symbol) { + Object.assign(estimatedGasParams, { value: '0x0' }) + } + + if (data) { + Object.assign(estimatedGasParams, { data }) + } + + return estimatedGasParams +} + +SendTransactionScreen.prototype.updateSendTokenBalance = function (usersToken) { + if (!usersToken) return + + const { + selectedToken = {}, + updateSendTokenBalance, + } = this.props + const { decimals } = selectedToken || {} + + const tokenBalance = calcTokenAmount(usersToken.balance.toString(), decimals) + + updateSendTokenBalance(tokenBalance) +} + SendTransactionScreen.prototype.componentWillMount = function () { const { updateTokenExchangeRate, @@ -49,32 +85,25 @@ SendTransactionScreen.prototype.componentWillMount = function () { selectedAddress, data, updateGasTotal, + updateSendTokenBalance, + from, + tokenContract, } = this.props - const { symbol } = selectedToken || {} - - const estimateGasParams = { - from: selectedAddress, - gas: '746a528800', - } + const { symbol, decimals } = selectedToken || {} if (symbol) { updateTokenExchangeRate(symbol) - Object.assign(estimateGasParams, { value: '0x0' }) } - if (data) { - Object.assign(estimateGasParams, { data }) - } + const estimateGasParams = getParamsForGasEstimate(selectedAddress, symbol, data) Promise .all([ getGasPrice(), - estimateGas({ - from: selectedAddress, - gas: '746a528800', - }), + estimateGas(estimateGasParams), + tokenContract && tokenContract.balanceOf(from.address) ]) - .then(([gasPrice, gas]) => { + .then(([gasPrice, gas, usersToken]) => { const newGasTotal = multiplyCurrencies(gas, gasPrice, { toNumericBase: 'hex', @@ -82,9 +111,36 @@ SendTransactionScreen.prototype.componentWillMount = function () { multiplierBase: 16, }) updateGasTotal(newGasTotal) + this.updateSendTokenBalance(usersToken) }) } +SendTransactionScreen.prototype.componentDidUpdate = function (prevProps) { + const { + from: { balance }, + gasTotal, + tokenBalance, + amount, + selectedToken, + } = this.props + const { + from: { balance: prevBalance }, + gasTotal: prevGasTotal, + tokenBalance: prevTokenBalance, + } = prevProps + + const notFirstRender = [prevBalance, prevGasTotal].every(n => n !== null) + + const balanceHasChanged = balance !== prevBalance + const gasTotalHasChange = gasTotal !== prevGasTotal + const tokenBalanceHasChanged = selectedToken && tokenBalance !== prevTokenBalance + const amountValidationChange = balanceHasChanged || gasTotalHasChange || tokenBalanceHasChanged + + if (notFirstRender && amountValidationChange) { + this.validateAmount(amount) + } +} + SendTransactionScreen.prototype.renderHeaderIcon = function () { const { selectedToken } = this.props @@ -144,12 +200,31 @@ SendTransactionScreen.prototype.renderErrorMessage = function (errorType) { : null } +SendTransactionScreen.prototype.handleFromChange = async function (newFrom) { + const { + from, + updateSendFrom, + updateSendTokenBalance, + tokenContract, + selectedToken, + } = this.props + const { decimals } = selectedToken || {} + + if (tokenContract) { + const usersToken = await tokenContract.balanceOf(newFrom.address) + this.updateSendTokenBalance(usersToken) + } + updateSendFrom(newFrom) +} + SendTransactionScreen.prototype.renderFromRow = function () { const { from, fromAccounts, conversionRate, updateSendFrom, + updateSendTokenBalance, + tokenContract, } = this.props const { fromDropdownOpen } = this.state @@ -163,7 +238,7 @@ SendTransactionScreen.prototype.renderFromRow = function () { dropdownOpen: fromDropdownOpen, accounts: fromAccounts, selectedAccount: from, - onSelect: updateSendFrom, + onSelect: newFrom => this.handleFromChange(newFrom), openDropdown: () => this.setState({ fromDropdownOpen: true }), closeDropdown: () => this.setState({ fromDropdownOpen: false }), conversionRate, @@ -239,21 +314,31 @@ SendTransactionScreen.prototype.validateAmount = function (value) { primaryCurrency, selectedToken, gasTotal, + tokenBalance, } = this.props + const { decimals } = selectedToken || {} const amount = value let amountError = null const sufficientBalance = isBalanceSufficient({ - amount, + amount: selectedToken ? '0x0' : amount, gasTotal, balance, primaryCurrency, - selectedToken, amountConversionRate, conversionRate, }) + let sufficientTokens + if (selectedToken) { + sufficientTokens = isTokenBalanceSufficient({ + tokenBalance, + amount, + decimals, + }) + } + const amountLessThanZero = conversionGreaterThan( { value: 0, fromNumericBase: 'dec' }, { value: amount, fromNumericBase: 'hex' }, @@ -261,6 +346,8 @@ SendTransactionScreen.prototype.validateAmount = function (value) { if (!sufficientBalance) { amountError = 'Insufficient funds.' + } else if (selectedToken && !sufficientTokens) { + amountError = 'Insufficient tokens.' } else if (amountLessThanZero) { amountError = 'Can not send negative amounts of ETH.' } @@ -275,10 +362,9 @@ SendTransactionScreen.prototype.renderAmountRow = function () { convertedCurrency, amountConversionRate, errors, + amount, } = this.props - const { amount } = this.state - return h('div.send-v2__form-row', [ h('div.send-v2__form-label', [ @@ -335,8 +421,7 @@ SendTransactionScreen.prototype.renderGasRow = function () { } SendTransactionScreen.prototype.renderMemoRow = function () { - const { updateSendMemo } = this.props - const { memo } = this.state + const { updateSendMemo, memo } = this.props return h('div.send-v2__form-row', [ |