From 171d38c8dbbe78c206e57c5d838ab672ef61f23b Mon Sep 17 00:00:00 2001 From: Dan Date: Wed, 20 Sep 2017 20:34:03 -0230 Subject: 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(-) (limited to 'ui/app/components/send-token/index.js') 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, ]) -- cgit v1.2.3 From a1d87b821b7e0a444257065d284b13f98e4d3173 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 21:45:51 -0230 Subject: 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(-) (limited to 'ui/app/components/send-token/index.js') 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), -- cgit v1.2.3 From fc3e071ad699f6c3586a20f12e06e6f456b0eea3 Mon Sep 17 00:00:00 2001 From: Dan Date: Mon, 25 Sep 2017 22:09:10 -0230 Subject: Send token now estimates gas and price. --- ui/app/components/send-token/index.js | 45 ++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) (limited to 'ui/app/components/send-token/index.js') 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( -- cgit v1.2.3