From 171d38c8dbbe78c206e57c5d838ab672ef61f23b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: [PATCH 1/5] Handles errors with to field and renders warnings from backend in send token. --- ui/app/components/send-token/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index dd8ca6b9d..8dd277f1d 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -346,7 +346,7 @@ SendTokenScreen.prototype.render = function () { this.renderAmountInput(), this.renderGasInput(), this.renderMemoInput(), - warning && h('div.send-screen-input-wrapper--error', + warning && h('div.send-screen-input-wrapper--error', {}, h('div.send-screen-input-wrapper__error-message', [ warning, ]) From a1d87b821b7e0a444257065d284b13f98e4d3173 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 21:45:51 -0230 Subject: [PATCH 2/5] Update send token to handle errors onBlur events and prevent clicking send until all errors handled --- ui/app/components/send-token/index.js | 71 ++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 12 deletions(-) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 8dd277f1d..166088898 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -5,7 +5,7 @@ const classnames = require('classnames') const inherits = require('util').inherits const actions = require('../../actions') const selectors = require('../../selectors') -const { isValidAddress } = require('../../util') +const { isValidAddress, allNull } = require('../../util') // const BalanceComponent = require('./balance-component') const Identicon = require('../identicon') @@ -65,7 +65,8 @@ function SendTokenScreen () { Component.call(this) this.state = { to: '', - amount: '', + amount: '0x0', + amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, gasPrice: '0x5d21dba00', @@ -113,6 +114,46 @@ SendTokenScreen.prototype.validate = function () { } } +SendTokenScreen.prototype.setErrorsFor = function (field) { + const { balance, selectedToken } = this.props + const { errors: previousErrors } = this.state + + const { + isValid, + errors: newErrors + } = this.validate() + + const nextErrors = Object.assign({}, previousErrors, { + [field]: newErrors[field] || null + }) + + if (!isValid) { + this.setState({ + errors: nextErrors, + isValid, + }) + } +} + +SendTokenScreen.prototype.clearErrorsFor = function (field) { + const { errors: previousErrors } = this.state + const nextErrors = Object.assign({}, previousErrors, { + [field]: null + }) + + this.setState({ + errors: nextErrors, + isValid: allNull(nextErrors), + }) +} + +SendTokenScreen.prototype.getAmountToSend = function (amount, selectedToken) { + const { decimals } = selectedToken || {} + const multiplier = Math.pow(10, Number(decimals || 0)) + const sendAmount = Number(amount * multiplier).toString(16) + return sendAmount +} + SendTokenScreen.prototype.submit = function () { const { to, @@ -132,11 +173,6 @@ SendTokenScreen.prototype.submit = function () { } = this.props const { nickname = ' ' } = identities[to] || {} - const { isValid, errors } = this.validate() - - if (!isValid) { - return this.setState({ errors }) - } hideWarning() addToAddressBook(to, nickname) @@ -148,9 +184,7 @@ SendTokenScreen.prototype.submit = function () { gasPrice: gasPrice, } - const { decimals } = selectedToken || {} - const multiplier = Math.pow(10, Number(decimals || 0)) - const sendAmount = Number(amount * multiplier).toString(16) + const sendAmount = this.getAmountToSend(amount, selectedToken) signTokenTx(selectedTokenAddress, to, sendAmount, txParams) } @@ -181,6 +215,8 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), + onBlur: () => this.setErrorsFor('to'), + onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ // Corresponds to the addresses owned. @@ -234,8 +270,9 @@ SendTokenScreen.prototype.renderAmountInput = function () { value: amount, onChange: e => this.setState({ amount: e.target.value, - errors: {}, }), + onBlur: () => this.setErrorsFor('amount'), + onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), ]) @@ -272,6 +309,14 @@ SendTokenScreen.prototype.renderGasInput = function () { onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) }, + onBlur: () => { + this.setErrorsFor('gasLimit') + this.setErrorsFor('gasPrice') + }, + onFocus: () => { + this.clearErrorsFor('gasLimit') + this.clearErrorsFor('gasPrice') + }, }), h('div.send-screen-gas-labels', {}, [ @@ -311,10 +356,12 @@ SendTokenScreen.prototype.renderMemoInput = function () { SendTokenScreen.prototype.renderButtons = function () { const { selectedAddress, backToAccountDetail } = this.props + const { isValid } = this.validate() return h('div.send-token__button-group', [ h('button.send-token__button-next.btn-secondary', { - onClick: () => this.submit(), + className: !isValid && 'send-screen__send-button__disabled', + onClick: () => isValid && this.submit(), }, ['Next']), h('button.send-token__button-cancel.btn-tertiary', { onClick: () => backToAccountDetail(selectedAddress), From 88c4226bf1dca8647a45f3921396daaa88bbf939 Mon Sep 17 00:00:00 2001 From: Dan Date: Fri, 22 Sep 2017 01:45:26 -0230 Subject: [PATCH 3/5] Estimate gasPrice and gasLimit in send screen. --- ui/app/actions.js | 57 +++++++++++++++++++++++++++++++++++++ ui/app/reducers/metamask.js | 22 ++++++++++++++ ui/app/send.js | 54 ++++++++++++++++++++++++++++++----- 3 files changed, 126 insertions(+), 7 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index 0a2b4a636..a43809fc0 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -129,6 +129,17 @@ var actions = { cancelAllTx: cancelAllTx, viewPendingTx: viewPendingTx, VIEW_PENDING_TX: 'VIEW_PENDING_TX', + // send screen + estimateGas, + updateGasEstimate, + UPDATE_GAS_ESTIMATE: 'UPDATE_GAS_ESTIMATE', + updateGasPrice, + UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE', + getGasPrice, + CLEAR_GAS_ESTIMATE: 'CLEAR_GAS_ESTIMATE', + CLEAR_GAS_PRICE: 'CLEAR_GAS_PRICE', + clearGasEstimate, + clearGasPrice, // app messages confirmSeedWords: confirmSeedWords, showAccountDetail: showAccountDetail, @@ -449,6 +460,26 @@ function signTx (txData) { } } +function estimateGas ({ to, amount }) { + return (dispatch) => { + global.ethQuery.estimateGas({ to, amount }, (err, data) => { + if (err) return dispatch(actions.displayWarning(err.message)) + dispatch(actions.hideWarning()) + dispatch(actions.updateGasEstimate(data)) + }) + } +} + +function getGasPrice () { + return (dispatch) => { + global.ethQuery.gasPrice((err, data) => { + if (err) return dispatch(actions.displayWarning(err.message)) + dispatch(actions.hideWarning()) + dispatch(actions.updateGasPrice(data)) + }) + } +} + function sendTx (txData) { log.info(`actions - sendTx: ${JSON.stringify(txData.txParams)}`) return (dispatch) => { @@ -506,6 +537,32 @@ function txError (err) { } } +function updateGasEstimate (gas) { + return { + type: actions.UPDATE_GAS_ESTIMATE, + value: gas, + } +} + +function clearGasEstimate () { + return { + type: actions.CLEAR_GAS_ESTIMATE, + } +} + +function updateGasPrice (gasPrice) { + return { + type: actions.UPDATE_GAS_PRICE, + value: gasPrice, + } +} + +function clearGasPrice () { + return { + type: actions.CLEAR_GAS_PRICE, + } +} + function cancelMsg (msgData) { log.debug(`background.cancelMessage`) background.cancelMessage(msgData.id) diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index cdc98d05e..e78f51f3a 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -19,6 +19,8 @@ function reduceMetamask (state, action) { addressBook: [], selectedTokenAddress: null, tokenExchangeRates: {}, + estimatedGas: null, + blockGasPrice: null, }, state.metamask) switch (action.type) { @@ -74,6 +76,26 @@ function reduceMetamask (state, action) { }, }) + case actions.UPDATE_GAS_ESTIMATE: + return extend(metamaskState, { + estimatedGas: action.value, + }) + + case actions.UPDATE_GAS_PRICE: + return extend(metamaskState, { + blockGasPrice: action.value, + }) + + case actions.CLEAR_GAS_ESTIMATE: + return extend(metamaskState, { + estimatedGas: null, + }) + + case actions.CLEAR_GAS_PRICE: + return extend(metamaskState, { + blockGasPrice: null, + }) + case actions.COMPLETED_TX: var stringId = String(action.id) newState = extend(metamaskState, { diff --git a/ui/app/send.js b/ui/app/send.js index 16fe470be..4ce7fc475 100644 --- a/ui/app/send.js +++ b/ui/app/send.js @@ -16,6 +16,10 @@ const { hideWarning, addToAddressBook, signTx, + estimateGas, + getGasPrice, + clearGasEstimate, + clearGasPrice, } = require('./actions') const { stripHexPrefix, addHexPrefix } = require('ethereumjs-util') const { isHex, numericBalance, isValidAddress, allNull } = require('./util') @@ -33,6 +37,8 @@ function mapStateToProps (state) { addressBook, conversionRate, currentBlockGasLimit: blockGasLimit, + estimatedGas, + blockGasPrice, } = state.metamask const { warning } = state.appState const selectedIdentity = getSelectedIdentity(state) @@ -46,6 +52,8 @@ function mapStateToProps (state) { addressBook, conversionRate, blockGasLimit, + blockGasPrice, + estimatedGas, warning, selectedIdentity, error: warning && warning.split('.')[0], @@ -67,8 +75,11 @@ function SendTransactionScreen () { to: '', amount: 0, amountToSend: '0x0', - gasPrice: '0x5d21dba00', - gas: '0x7b0d', + gasPrice: null, + gas: null, + amount: '0x0', + gasPrice: null, + gas: null, txData: null, memo: '', }, @@ -87,6 +98,7 @@ function SendTransactionScreen () { this.getAmountToSend = this.getAmountToSend.bind(this) this.setErrorsFor = this.setErrorsFor.bind(this) this.clearErrorsFor = this.clearErrorsFor.bind(this) + this.estimateGasAndPrice = this.estimateGasAndPrice.bind(this) this.renderFromInput = this.renderFromInput.bind(this) this.renderToInput = this.renderToInput.bind(this) @@ -96,6 +108,11 @@ function SendTransactionScreen () { this.renderErrorMessage = this.renderErrorMessage.bind(this) } +SendTransactionScreen.prototype.componentWillMount = function() { + this.props.dispatch(clearGasEstimate()) + this.props.dispatch(clearGasPrice()) +} + SendTransactionScreen.prototype.renderErrorMessage = function(errorType, warning) { const { errors } = this.state const errorMessage = errors[errorType]; @@ -159,7 +176,10 @@ SendTransactionScreen.prototype.renderToInput = function (to, identities, addres }, }) }, - onBlur: () => this.setErrorsFor('to'), + onBlur: () => { + this.setErrorsFor('to') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('to'), }), @@ -212,7 +232,10 @@ SendTransactionScreen.prototype.renderAmountInput = function (activeCurrency) { ), }) }, - onBlur: () => this.setErrorsFor('amount'), + onBlur: () => { + this.setErrorsFor('amount') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('amount'), }), @@ -293,6 +316,8 @@ SendTransactionScreen.prototype.render = function () { identities, addressBook, conversionRate, + estimatedGas, + blockGasPrice, } = props const { blockGasLimit, newTx, activeCurrency, isValid } = this.state @@ -316,7 +341,13 @@ SendTransactionScreen.prototype.render = function () { this.renderAmountInput(activeCurrency), - this.renderGasInput(gasPrice, gas, activeCurrency, conversionRate, blockGasLimit), + this.renderGasInput( + gasPrice || blockGasPrice || '0x0', + gas || estimatedGas || '0x0', + activeCurrency, + conversionRate, + blockGasLimit + ), this.renderMemoInput(), @@ -351,6 +382,15 @@ SendTransactionScreen.prototype.setActiveCurrency = function (newCurrency) { this.setState({ activeCurrency: newCurrency }) } +SendTransactionScreen.prototype.estimateGasAndPrice = function () { + const { errors, sendAmount, newTx } = this.state + + if (!errors.to && !errors.amount && newTx.amount > 0) { + this.props.dispatch(getGasPrice()) + this.props.dispatch(estimateGas({ to: newTx.to, amount: sendAmount })) + } +} + SendTransactionScreen.prototype.back = function () { var address = this.props.address this.props.dispatch(backToAccountDetail(address)) @@ -471,7 +511,7 @@ SendTransactionScreen.prototype.clearErrorsFor = function (field) { SendTransactionScreen.prototype.onSubmit = function (event) { event.preventDefault() - const { warning, balance, amountToSend } = this.props + const { warning, balance } = this.props const state = this.state || {} const recipient = state.newTx.to @@ -489,7 +529,7 @@ SendTransactionScreen.prototype.onSubmit = function (event) { from: this.state.newTx.from, to: this.state.newTx.to, - value: amountToSend, + value: this.state.newTx.amountToSend, gas: this.state.newTx.gas, gasPrice: this.state.newTx.gasPrice, From 79bcb88db3946260c832402d97e0c800cdeba5a9 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 21:00:32 -0230 Subject: [PATCH 4/5] Refactor to store estimated gas and price in local state, return promise from actions. --- ui/app/actions.js | 60 +++++++++++-------------------------- ui/app/reducers/metamask.js | 22 -------------- ui/app/send.js | 37 ++++++++++++----------- 3 files changed, 38 insertions(+), 81 deletions(-) diff --git a/ui/app/actions.js b/ui/app/actions.js index a43809fc0..a0dbbbf11 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -131,15 +131,7 @@ var actions = { VIEW_PENDING_TX: 'VIEW_PENDING_TX', // send screen estimateGas, - updateGasEstimate, - UPDATE_GAS_ESTIMATE: 'UPDATE_GAS_ESTIMATE', - updateGasPrice, - UPDATE_GAS_PRICE: 'UPDATE_GAS_PRICE', getGasPrice, - CLEAR_GAS_ESTIMATE: 'CLEAR_GAS_ESTIMATE', - CLEAR_GAS_PRICE: 'CLEAR_GAS_PRICE', - clearGasEstimate, - clearGasPrice, // app messages confirmSeedWords: confirmSeedWords, showAccountDetail: showAccountDetail, @@ -462,20 +454,30 @@ function signTx (txData) { function estimateGas ({ to, amount }) { return (dispatch) => { - global.ethQuery.estimateGas({ to, amount }, (err, data) => { - if (err) return dispatch(actions.displayWarning(err.message)) - dispatch(actions.hideWarning()) - dispatch(actions.updateGasEstimate(data)) + return new Promise((resolve, reject) => { + global.ethQuery.estimateGas({ to, amount }, (err, data) => { + if (err) { + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + dispatch(actions.hideWarning()) + return resolve(data) + }) }) } } function getGasPrice () { return (dispatch) => { - global.ethQuery.gasPrice((err, data) => { - if (err) return dispatch(actions.displayWarning(err.message)) - dispatch(actions.hideWarning()) - dispatch(actions.updateGasPrice(data)) + return new Promise((resolve, reject) => { + global.ethQuery.gasPrice((err, data) => { + if (err) { + dispatch(actions.displayWarning(err.message)) + return reject(err) + } + dispatch(actions.hideWarning()) + return resolve(data) + }) }) } } @@ -537,32 +539,6 @@ function txError (err) { } } -function updateGasEstimate (gas) { - return { - type: actions.UPDATE_GAS_ESTIMATE, - value: gas, - } -} - -function clearGasEstimate () { - return { - type: actions.CLEAR_GAS_ESTIMATE, - } -} - -function updateGasPrice (gasPrice) { - return { - type: actions.UPDATE_GAS_PRICE, - value: gasPrice, - } -} - -function clearGasPrice () { - return { - type: actions.CLEAR_GAS_PRICE, - } -} - function cancelMsg (msgData) { log.debug(`background.cancelMessage`) background.cancelMessage(msgData.id) diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index e78f51f3a..cdc98d05e 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -19,8 +19,6 @@ function reduceMetamask (state, action) { addressBook: [], selectedTokenAddress: null, tokenExchangeRates: {}, - estimatedGas: null, - blockGasPrice: null, }, state.metamask) switch (action.type) { @@ -76,26 +74,6 @@ function reduceMetamask (state, action) { }, }) - case actions.UPDATE_GAS_ESTIMATE: - return extend(metamaskState, { - estimatedGas: action.value, - }) - - case actions.UPDATE_GAS_PRICE: - return extend(metamaskState, { - blockGasPrice: action.value, - }) - - case actions.CLEAR_GAS_ESTIMATE: - return extend(metamaskState, { - estimatedGas: null, - }) - - case actions.CLEAR_GAS_PRICE: - return extend(metamaskState, { - blockGasPrice: null, - }) - case actions.COMPLETED_TX: var stringId = String(action.id) newState = extend(metamaskState, { diff --git a/ui/app/send.js b/ui/app/send.js index 4ce7fc475..033692910 100644 --- a/ui/app/send.js +++ b/ui/app/send.js @@ -18,8 +18,6 @@ const { signTx, estimateGas, getGasPrice, - clearGasEstimate, - clearGasPrice, } = require('./actions') const { stripHexPrefix, addHexPrefix } = require('ethereumjs-util') const { isHex, numericBalance, isValidAddress, allNull } = require('./util') @@ -52,8 +50,6 @@ function mapStateToProps (state) { addressBook, conversionRate, blockGasLimit, - blockGasPrice, - estimatedGas, warning, selectedIdentity, error: warning && warning.split('.')[0], @@ -73,16 +69,15 @@ function SendTransactionScreen () { newTx: { from: '', to: '', - amount: 0, amountToSend: '0x0', gasPrice: null, gas: null, amount: '0x0', - gasPrice: null, - gas: null, txData: null, memo: '', }, + blockGasPrice: null, + estimatedGas: null, activeCurrency: 'USD', tooltipIsOpen: false, errors: {}, @@ -108,11 +103,6 @@ function SendTransactionScreen () { this.renderErrorMessage = this.renderErrorMessage.bind(this) } -SendTransactionScreen.prototype.componentWillMount = function() { - this.props.dispatch(clearGasEstimate()) - this.props.dispatch(clearGasPrice()) -} - SendTransactionScreen.prototype.renderErrorMessage = function(errorType, warning) { const { errors } = this.state const errorMessage = errors[errorType]; @@ -316,11 +306,16 @@ SendTransactionScreen.prototype.render = function () { identities, addressBook, conversionRate, - estimatedGas, - blockGasPrice, } = props - const { blockGasLimit, newTx, activeCurrency, isValid } = this.state + const { + blockGasLimit, + newTx, + activeCurrency, + isValid, + blockGasPrice, + estimatedGas, + } = this.state const { gas, gasPrice } = newTx return ( @@ -386,8 +381,16 @@ SendTransactionScreen.prototype.estimateGasAndPrice = function () { const { errors, sendAmount, newTx } = this.state if (!errors.to && !errors.amount && newTx.amount > 0) { - this.props.dispatch(getGasPrice()) - this.props.dispatch(estimateGas({ to: newTx.to, amount: sendAmount })) + Promise.all([ + this.props.dispatch(getGasPrice()), + this.props.dispatch(estimateGas({ to: newTx.to, amount: sendAmount })), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, + }) + }) } } From fc3e071ad699f6c3586a20f12e06e6f456b0eea3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 22:09:10 -0230 Subject: [PATCH 5/5] Send token now estimates gas and price. --- ui/app/components/send-token/index.js | 45 ++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/ui/app/components/send-token/index.js b/ui/app/components/send-token/index.js index 166088898..e4f13a874 100644 --- a/ui/app/components/send-token/index.js +++ b/ui/app/components/send-token/index.js @@ -57,6 +57,9 @@ function mapDispatchToProps (dispatch) { dispatch(actions.signTokenTx(tokenAddress, toAddress, amount, txData)) ), updateTokenExchangeRate: token => dispatch(actions.updateTokenExchangeRate(token)), + estimateGas: ({ to, amount }) => dispatch(actions.estimateGas({ to, amount })), + getGasPrice: () => dispatch(actions.getGasPrice()), + } } @@ -69,8 +72,8 @@ function SendTokenScreen () { amountToSend: '0x0', selectedCurrency: 'USD', isGasTooltipOpen: false, - gasPrice: '0x5d21dba00', - gasLimit: '0x7b0d', + gasPrice: null, + gasLimit: null, errors: {}, } } @@ -84,6 +87,24 @@ SendTokenScreen.prototype.componentWillMount = function () { updateTokenExchangeRate(symbol) } +SendTokenScreen.prototype.estimateGasAndPrice = function () { + const { selectedToken } = this.props + const { errors, amount, to } = this.state + + if (!errors.to && !errors.amount && amount > 0) { + Promise.all([ + this.props.getGasPrice(), + this.props.estimateGas({ to, amount: this.getAmountToSend(amount, selectedToken) }), + ]) + .then(([blockGasPrice, estimatedGas]) => { + this.setState({ + blockGasPrice, + estimatedGas, + }) + }) + } +} + SendTokenScreen.prototype.validate = function () { const { to, @@ -215,7 +236,10 @@ SendTokenScreen.prototype.renderToAddressInput = function () { to: e.target.value, errors: {}, }), - onBlur: () => this.setErrorsFor('to'), + onBlur: () => { + this.setErrorsFor('to') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('to'), }), h('datalist#addresses', [ @@ -271,7 +295,10 @@ SendTokenScreen.prototype.renderAmountInput = function () { onChange: e => this.setState({ amount: e.target.value, }), - onBlur: () => this.setErrorsFor('amount'), + onBlur: () => { + this.setErrorsFor('amount') + this.estimateGasAndPrice() + }, onFocus: () => this.clearErrorsFor('amount'), }), h('div.send-screen-input-wrapper__error-message', [ errorMessage ]), @@ -283,6 +310,8 @@ SendTokenScreen.prototype.renderGasInput = function () { isGasTooltipOpen, gasPrice, gasLimit, + blockGasPrice, + estimatedGas, selectedCurrency, errors: { gasPrice: gasPriceErrorMessage, @@ -303,8 +332,8 @@ SendTokenScreen.prototype.renderGasInput = function () { }, [ isGasTooltipOpen && h(GasTooltip, { className: 'send-tooltip', - gasPrice, - gasLimit, + gasPrice: gasPrice || blockGasPrice || '0x0', + gasLimit: gasLimit || estimatedGas || '0x0', onClose: () => this.setState({ isGasTooltipOpen: false }), onFeeChange: ({ gasLimit, gasPrice }) => { this.setState({ gasLimit, gasPrice, errors: {} }) @@ -327,9 +356,9 @@ SendTokenScreen.prototype.renderGasInput = function () { h(GasFeeDisplay, { conversionRate, tokenExchangeRate, - gasPrice, + gasPrice: gasPrice || blockGasPrice || '0x0', activeCurrency: selectedCurrency, - gas: gasLimit, + gas: gasLimit || estimatedGas || '0x0', blockGasLimit: currentBlockGasLimit, }), h(