Skip to content

Commit

Permalink
Fix gas estimate for tokens (#7753)
Browse files Browse the repository at this point in the history
* Make gas estimate update on debounced token amount change, not just on blur after change

* Updated tests

* Ensure `updateGas` is bound early

Co-authored-by: Mark Stacey <markjstacey@gmail.com>
  • Loading branch information
danjm and Gudahtt committed Jan 10, 2020
1 parent 77b42c4 commit 7b8e87e
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 38 deletions.
1 change: 1 addition & 0 deletions test/e2e/metamask-ui.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,7 @@ describe('MetaMask', function () {

// Continue to next screen
const nextScreen = await findElement(driver, By.xpath(`//button[contains(text(), 'Next')]`))
await driver.wait(until.elementIsEnabled(nextScreen))
await nextScreen.click()
await delay(regularDelayMs)
})
Expand Down
2 changes: 1 addition & 1 deletion ui/app/components/ui/token-input/token-input.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default class TokenInput extends PureComponent {
}

handleBlur = () => {
this.props.onBlur(this.state.hexValue)
this.props.onBlur && this.props.onBlur(this.state.hexValue)
}

renderConversionComponent () {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import debounce from 'lodash.debounce'
import SendRowWrapper from '../send-row-wrapper'
import AmountMaxButton from './amount-max-button'
import UserPreferencedCurrencyInput from '../../../../components/app/user-preferenced-currency-input'
Expand Down Expand Up @@ -32,6 +33,8 @@ export default class SendAmountRow extends Component {
t: PropTypes.func,
}

updateGas = debounce(this.updateGas.bind(this), 500)

validateAmount (amount) {
const {
amountConversionRate,
Expand Down Expand Up @@ -90,8 +93,8 @@ export default class SendAmountRow extends Component {

return (
<Component
onChange={newAmount => this.validateAmount(newAmount)}
onBlur={newAmount => {
onChange={newAmount => {
this.validateAmount(newAmount)
this.updateGas(newAmount)
this.updateAmount(newAmount)
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
import AmountMaxButton from '../amount-max-button/amount-max-button.container'
import UserPreferencedTokenInput from '../../../../../components/app/user-preferenced-token-input'

import timeout from '../../../../../../lib/test-timeout'

const propsMethodSpies = {
setMaxModeTo: sinon.spy(),
updateSendAmount: sinon.spy(),
Expand Down Expand Up @@ -153,9 +155,8 @@ describe('SendAmountRow Component', function () {
assert(wrapper.find(SendRowWrapper).childAt(1).is(UserPreferencedTokenInput))
})

it('should render the UserPreferencedTokenInput with the correct props', () => {
it('should render the UserPreferencedTokenInput with the correct props', async () => {
const {
onBlur,
onChange,
error,
value,
Expand All @@ -164,8 +165,9 @@ describe('SendAmountRow Component', function () {
assert.equal(value, 'mockAmount')
assert.equal(SendAmountRow.prototype.updateGas.callCount, 0)
assert.equal(SendAmountRow.prototype.updateAmount.callCount, 0)
onBlur('mockNewAmount')
assert.equal(SendAmountRow.prototype.updateGas.callCount, 1)
assert.equal(SendAmountRow.prototype.validateAmount.callCount, 0)
onChange('mockNewAmount')
await timeout(501)
assert.deepEqual(
SendAmountRow.prototype.updateGas.getCall(0).args,
['mockNewAmount']
Expand All @@ -175,8 +177,6 @@ describe('SendAmountRow Component', function () {
SendAmountRow.prototype.updateAmount.getCall(0).args,
['mockNewAmount']
)
assert.equal(SendAmountRow.prototype.validateAmount.callCount, 0)
onChange('mockNewAmount')
assert.equal(SendAmountRow.prototype.validateAmount.callCount, 1)
assert.deepEqual(
SendAmountRow.prototype.validateAmount.getCall(0).args,
Expand Down
5 changes: 3 additions & 2 deletions ui/app/pages/send/send-footer/send-footer.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class SendFooter extends Component {
update: PropTypes.func,
sendErrors: PropTypes.object,
gasEstimateType: PropTypes.string,
gasIsLoading: PropTypes.bool,
}

static contextTypes = {
Expand Down Expand Up @@ -102,10 +103,10 @@ export default class SendFooter extends Component {
}

formShouldBeDisabled () {
const { data, inError, selectedToken, tokenBalance, gasTotal, to, gasLimit } = this.props
const { data, inError, selectedToken, tokenBalance, gasTotal, to, gasLimit, gasIsLoading } = this.props
const missingTokenBalance = selectedToken && !tokenBalance
const gasLimitTooLow = gasLimit < 5208 // 5208 is hex value of 21000, minimum gas limit
const shouldBeDisabled = inError || !gasTotal || missingTokenBalance || !(data || to) || gasLimitTooLow
const shouldBeDisabled = inError || !gasTotal || missingTokenBalance || !(data || to) || gasLimitTooLow || gasIsLoading
return shouldBeDisabled
}

Expand Down
2 changes: 2 additions & 0 deletions ui/app/pages/send/send-footer/send-footer.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
getUnapprovedTxs,
getSendErrors,
} from '../send.selectors'
import { getGasIsLoading } from '../../../selectors/selectors'
import {
isSendFormInError,
} from './send-footer.selectors'
Expand Down Expand Up @@ -62,6 +63,7 @@ function mapStateToProps (state) {
unapprovedTxs: getUnapprovedTxs(state),
sendErrors: getSendErrors(state),
gasEstimateType,
gasIsLoading: getGasIsLoading(state),
}
}

Expand Down
14 changes: 14 additions & 0 deletions ui/app/pages/send/send-footer/tests/send-footer-component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,30 +81,44 @@ describe('SendFooter Component', function () {
'should return true if inError is truthy': {
inError: true,
expectedResult: true,
gasIsLoading: false,
},
'should return true if gasTotal is falsy': {
inError: false,
gasTotal: false,
expectedResult: true,
gasIsLoading: false,
},
'should return true if to is truthy': {
to: '0xsomevalidAddress',
inError: false,
gasTotal: false,
expectedResult: true,
gasIsLoading: false,
},
'should return true if selectedToken is truthy and tokenBalance is falsy': {
selectedToken: true,
tokenBalance: null,
expectedResult: true,
gasIsLoading: false,
},
'should return true if gasIsLoading is truthy but all other params are falsy': {
inError: false,
gasTotal: null,
selectedToken: null,
tokenBalance: 0,
expectedResult: true,
gasIsLoading: true,
},
'should return false if inError is false and all other params are truthy': {
inError: false,
gasTotal: '0x123',
selectedToken: true,
tokenBalance: 123,
expectedResult: false,
gasIsLoading: false,
},

}
Object.entries(config).map(([description, obj]) => {
it(description, () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import assert from 'assert'
import proxyquire from 'proxyquire'
import sinon from 'sinon'

let mapStateToProps
let mapDispatchToProps

const actionSpies = {
Expand All @@ -22,8 +21,7 @@ const utilsStubs = {

proxyquire('../send-footer.container.js', {
'react-redux': {
connect: (ms, md) => {
mapStateToProps = ms
connect: (_, md) => {
mapDispatchToProps = md
return () => ({})
},
Expand Down Expand Up @@ -55,30 +53,6 @@ proxyquire('../send-footer.container.js', {

describe('send-footer container', () => {

describe('mapStateToProps()', () => {

it('should map the correct properties to props', () => {
assert.deepEqual(mapStateToProps('mockState'), {
amount: 'mockAmount:mockState',
data: 'mockHexData:mockState',
selectedToken: 'mockSelectedToken:mockState',
editingTransactionId: 'mockEditingTransactionId:mockState',
from: 'mockFromObject:mockState',
gasLimit: 'mockGasLimit:mockState',
gasPrice: 'mockGasPrice:mockState',
gasTotal: 'mockGasTotal:mockState',
inError: 'mockInError:mockState',
to: 'mockTo:mockState',
toAccounts: 'mockToAccounts:mockState',
tokenBalance: 'mockTokenBalance:mockState',
unapprovedTxs: 'mockUnapprovedTxs:mockState',
sendErrors: 'mockSendErrors:mockState',
gasEstimateType: 'mockGasEstimateType:mockState',
})
})

})

describe('mapDispatchToProps()', () => {
let dispatchSpy
let mapDispatchToPropsObject
Expand Down

0 comments on commit 7b8e87e

Please sign in to comment.