mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Auto update gas estimate when to changes.
This commit is contained in:
parent
3d597cd1d2
commit
0f20fce9b7
@ -383,6 +383,8 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController),
|
updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController),
|
||||||
retryTransaction: nodeify(this.retryTransaction, this),
|
retryTransaction: nodeify(this.retryTransaction, this),
|
||||||
getFilteredTxList: nodeify(txController.getFilteredTxList, txController),
|
getFilteredTxList: nodeify(txController.getFilteredTxList, txController),
|
||||||
|
isNonceTaken: nodeify(txController.isNonceTaken, txController),
|
||||||
|
estimateGas: nodeify(this.estimateGas, this),
|
||||||
|
|
||||||
// messageManager
|
// messageManager
|
||||||
signMessage: nodeify(this.signMessage, this),
|
signMessage: nodeify(this.signMessage, this),
|
||||||
@ -921,6 +923,18 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
estimateGas (estimateGasParams) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
return this.txController.txGasUtil.query.estimateGas(estimateGasParams, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolve(res)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// PASSWORD MANAGEMENT
|
// PASSWORD MANAGEMENT
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
@ -731,16 +731,21 @@ function updateGasData ({
|
|||||||
selectedAddress,
|
selectedAddress,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
to,
|
to,
|
||||||
|
value,
|
||||||
}) {
|
}) {
|
||||||
|
const estimatedGasPrice = estimateGasPriceFromRecentBlocks(recentBlocks)
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
Promise.resolve(estimateGasPriceFromRecentBlocks(recentBlocks)),
|
Promise.resolve(estimatedGasPrice),
|
||||||
estimateGas({
|
estimateGas({
|
||||||
|
estimateGasMethod: background.estimateGas,
|
||||||
blockGasLimit,
|
blockGasLimit,
|
||||||
data,
|
data,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
to,
|
to,
|
||||||
|
value,
|
||||||
|
gasPrice: estimatedGasPrice,
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
.then(([gasPrice, gas]) => {
|
.then(([gasPrice, gas]) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
import PageContainerContent from '../../page-container/page-container-content.component'
|
import PageContainerContent from '../../page-container/page-container-content.component'
|
||||||
import SendAmountRow from './send-amount-row/'
|
import SendAmountRow from './send-amount-row/'
|
||||||
import SendFromRow from './send-from-row/'
|
import SendFromRow from './send-from-row/'
|
||||||
@ -7,12 +8,16 @@ import SendToRow from './send-to-row/'
|
|||||||
|
|
||||||
export default class SendContent extends Component {
|
export default class SendContent extends Component {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
updateGas: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<PageContainerContent>
|
<PageContainerContent>
|
||||||
<div className="send-v2__form">
|
<div className="send-v2__form">
|
||||||
<SendFromRow />
|
<SendFromRow />
|
||||||
<SendToRow />
|
<SendToRow updateGas={(updateData) => this.props.updateGas(updateData)} />
|
||||||
<SendAmountRow />
|
<SendAmountRow />
|
||||||
<SendGasRow />
|
<SendGasRow />
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,6 +2,7 @@ import React, { Component } from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import SendRowWrapper from '../send-row-wrapper/'
|
import SendRowWrapper from '../send-row-wrapper/'
|
||||||
import EnsInput from '../../../ens-input'
|
import EnsInput from '../../../ens-input'
|
||||||
|
import { getToErrorObject } from './send-to-row.utils.js'
|
||||||
|
|
||||||
export default class SendToRow extends Component {
|
export default class SendToRow extends Component {
|
||||||
|
|
||||||
@ -13,14 +14,19 @@ export default class SendToRow extends Component {
|
|||||||
to: PropTypes.string,
|
to: PropTypes.string,
|
||||||
toAccounts: PropTypes.array,
|
toAccounts: PropTypes.array,
|
||||||
toDropdownOpen: PropTypes.bool,
|
toDropdownOpen: PropTypes.bool,
|
||||||
|
updateGas: PropTypes.func,
|
||||||
updateSendTo: PropTypes.func,
|
updateSendTo: PropTypes.func,
|
||||||
updateSendToError: PropTypes.func,
|
updateSendToError: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleToChange (to, nickname = '') {
|
handleToChange (to, nickname = '') {
|
||||||
const { updateSendTo, updateSendToError } = this.props
|
const { updateSendTo, updateSendToError, updateGas } = this.props
|
||||||
|
const toErrorObject = getToErrorObject(to)
|
||||||
updateSendTo(to, nickname)
|
updateSendTo(to, nickname)
|
||||||
updateSendToError(to)
|
updateSendToError(toErrorObject)
|
||||||
|
if (toErrorObject.to === null) {
|
||||||
|
updateGas({ to })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
@ -8,7 +8,6 @@ import {
|
|||||||
getToDropdownOpen,
|
getToDropdownOpen,
|
||||||
sendToIsInError,
|
sendToIsInError,
|
||||||
} from './send-to-row.selectors.js'
|
} from './send-to-row.selectors.js'
|
||||||
import { getToErrorObject } from './send-to-row.utils.js'
|
|
||||||
import {
|
import {
|
||||||
updateSendTo,
|
updateSendTo,
|
||||||
} from '../../../../actions'
|
} from '../../../../actions'
|
||||||
@ -36,8 +35,8 @@ function mapDispatchToProps (dispatch) {
|
|||||||
closeToDropdown: () => dispatch(closeToDropdown()),
|
closeToDropdown: () => dispatch(closeToDropdown()),
|
||||||
openToDropdown: () => dispatch(openToDropdown()),
|
openToDropdown: () => dispatch(openToDropdown()),
|
||||||
updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)),
|
updateSendTo: (to, nickname) => dispatch(updateSendTo(to, nickname)),
|
||||||
updateSendToError: (to) => {
|
updateSendToError: (toErrorObject) => {
|
||||||
dispatch(updateSendErrors(getToErrorObject(to)))
|
dispatch(updateSendErrors(toErrorObject))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ function getToErrorObject (to) {
|
|||||||
let toError = null
|
let toError = null
|
||||||
|
|
||||||
if (!to) {
|
if (!to) {
|
||||||
toError = REQUIRED_ERROR
|
toError = REQUIRED_ERROR
|
||||||
} else if (!isValidAddress(to)) {
|
} else if (!isValidAddress(to)) {
|
||||||
toError = INVALID_RECIPIENT_ADDRESS_ERROR
|
toError = INVALID_RECIPIENT_ADDRESS_ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
return { to: toError }
|
return { to: toError }
|
||||||
|
@ -2,7 +2,15 @@ import React from 'react'
|
|||||||
import assert from 'assert'
|
import assert from 'assert'
|
||||||
import { shallow } from 'enzyme'
|
import { shallow } from 'enzyme'
|
||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
import SendToRow from '../send-to-row.component.js'
|
import proxyquire from 'proxyquire'
|
||||||
|
|
||||||
|
const SendToRow = proxyquire('../send-to-row.component.js', {
|
||||||
|
'./send-to-row.utils.js': {
|
||||||
|
getToErrorObject: (to) => ({
|
||||||
|
to: to === false ? null : `mockToErrorObject:${to}`,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
}).default
|
||||||
|
|
||||||
import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
|
import SendRowWrapper from '../../send-row-wrapper/send-row-wrapper.component'
|
||||||
import EnsInput from '../../../../ens-input'
|
import EnsInput from '../../../../ens-input'
|
||||||
@ -10,6 +18,7 @@ import EnsInput from '../../../../ens-input'
|
|||||||
const propsMethodSpies = {
|
const propsMethodSpies = {
|
||||||
closeToDropdown: sinon.spy(),
|
closeToDropdown: sinon.spy(),
|
||||||
openToDropdown: sinon.spy(),
|
openToDropdown: sinon.spy(),
|
||||||
|
updateGas: sinon.spy(),
|
||||||
updateSendTo: sinon.spy(),
|
updateSendTo: sinon.spy(),
|
||||||
updateSendToError: sinon.spy(),
|
updateSendToError: sinon.spy(),
|
||||||
}
|
}
|
||||||
@ -29,6 +38,7 @@ describe('SendToRow Component', function () {
|
|||||||
to={'mockTo'}
|
to={'mockTo'}
|
||||||
toAccounts={['mockAccount']}
|
toAccounts={['mockAccount']}
|
||||||
toDropdownOpen={false}
|
toDropdownOpen={false}
|
||||||
|
updateGas={propsMethodSpies.updateGas}
|
||||||
updateSendTo={propsMethodSpies.updateSendTo}
|
updateSendTo={propsMethodSpies.updateSendTo}
|
||||||
updateSendToError={propsMethodSpies.updateSendToError}
|
updateSendToError={propsMethodSpies.updateSendToError}
|
||||||
/>, { context: { t: str => str + '_t' } })
|
/>, { context: { t: str => str + '_t' } })
|
||||||
@ -61,10 +71,21 @@ describe('SendToRow Component', function () {
|
|||||||
assert.equal(propsMethodSpies.updateSendToError.callCount, 1)
|
assert.equal(propsMethodSpies.updateSendToError.callCount, 1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
propsMethodSpies.updateSendToError.getCall(0).args,
|
propsMethodSpies.updateSendToError.getCall(0).args,
|
||||||
['mockTo2']
|
[{ to: 'mockToErrorObject:mockTo2' }]
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not call updateGas if there is a to error', () => {
|
||||||
|
assert.equal(propsMethodSpies.updateGas.callCount, 0)
|
||||||
|
instance.handleToChange('mockTo2')
|
||||||
|
assert.equal(propsMethodSpies.updateGas.callCount, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should call updateGas if there is no to error', () => {
|
||||||
|
assert.equal(propsMethodSpies.updateGas.callCount, 0)
|
||||||
|
instance.handleToChange(false)
|
||||||
|
assert.equal(propsMethodSpies.updateGas.callCount, 1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
|
@ -31,7 +31,6 @@ proxyquire('../send-to-row.container.js', {
|
|||||||
getToDropdownOpen: (s) => `mockToDropdownOpen:${s}`,
|
getToDropdownOpen: (s) => `mockToDropdownOpen:${s}`,
|
||||||
sendToIsInError: (s) => `mockInError:${s}`,
|
sendToIsInError: (s) => `mockInError:${s}`,
|
||||||
},
|
},
|
||||||
'./send-to-row.utils.js': { getToErrorObject: (t) => `mockError:${t}` },
|
|
||||||
'../../../../actions': actionSpies,
|
'../../../../actions': actionSpies,
|
||||||
'../../../../ducks/send.duck': duckActionSpies,
|
'../../../../ducks/send.duck': duckActionSpies,
|
||||||
})
|
})
|
||||||
@ -99,12 +98,12 @@ describe('send-to-row container', () => {
|
|||||||
|
|
||||||
describe('updateSendToError()', () => {
|
describe('updateSendToError()', () => {
|
||||||
it('should dispatch an action', () => {
|
it('should dispatch an action', () => {
|
||||||
mapDispatchToPropsObject.updateSendToError('mockTo')
|
mapDispatchToPropsObject.updateSendToError('mockToErrorObject')
|
||||||
assert(dispatchSpy.calledOnce)
|
assert(dispatchSpy.calledOnce)
|
||||||
assert(duckActionSpies.updateSendErrors.calledOnce)
|
assert(duckActionSpies.updateSendErrors.calledOnce)
|
||||||
assert.equal(
|
assert.equal(
|
||||||
duckActionSpies.updateSendErrors.getCall(0).args[0],
|
duckActionSpies.updateSendErrors.getCall(0).args[0],
|
||||||
'mockError:mockTo'
|
'mockToErrorObject'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -42,7 +42,6 @@ function constructUpdatedTx ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (selectedToken) {
|
if (selectedToken) {
|
||||||
console.log(`ethAbi.rawEncode`, ethAbi.rawEncode)
|
|
||||||
const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call(
|
const data = TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call(
|
||||||
ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]),
|
ethAbi.rawEncode(['address', 'uint256'], [to, ethUtil.addHexPrefix(amount)]),
|
||||||
x => ('00' + x.toString(16)).slice(-2)
|
x => ('00' + x.toString(16)).slice(-2)
|
||||||
|
@ -39,8 +39,9 @@ export default class SendTransactionScreen extends PersistentForm {
|
|||||||
updateSendTokenBalance: PropTypes.func,
|
updateSendTokenBalance: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
updateGas () {
|
updateGas ({ to } = {}) {
|
||||||
const {
|
const {
|
||||||
|
amount,
|
||||||
blockGasLimit,
|
blockGasLimit,
|
||||||
data,
|
data,
|
||||||
editingTransactionId,
|
editingTransactionId,
|
||||||
@ -61,6 +62,8 @@ export default class SendTransactionScreen extends PersistentForm {
|
|||||||
recentBlocks,
|
recentBlocks,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
|
to: to && to.toLowerCase(),
|
||||||
|
value: amount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +150,7 @@ export default class SendTransactionScreen extends PersistentForm {
|
|||||||
return (
|
return (
|
||||||
<div className="page-container">
|
<div className="page-container">
|
||||||
<SendHeader history={history}/>
|
<SendHeader history={history}/>
|
||||||
<SendContent/>
|
<SendContent updateGas={(updateData) => this.updateGas(updateData)}/>
|
||||||
<SendFooter history={history}/>
|
<SendFooter history={history}/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -76,9 +76,11 @@ function mapDispatchToProps (dispatch) {
|
|||||||
recentBlocks,
|
recentBlocks,
|
||||||
selectedAddress,
|
selectedAddress,
|
||||||
selectedToken,
|
selectedToken,
|
||||||
|
to,
|
||||||
|
value,
|
||||||
}) => {
|
}) => {
|
||||||
!editingTransactionId
|
!editingTransactionId
|
||||||
? dispatch(updateGasData({ recentBlocks, selectedAddress, selectedToken, data, blockGasLimit }))
|
? dispatch(updateGasData({ recentBlocks, selectedAddress, selectedToken, data, blockGasLimit, to, value }))
|
||||||
: dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice)))
|
: dispatch(setGasTotal(calcGasTotal(gasLimit, gasPrice)))
|
||||||
},
|
},
|
||||||
updateSendTokenBalance: ({ selectedToken, tokenContract, address }) => {
|
updateSendTokenBalance: ({ selectedToken, tokenContract, address }) => {
|
||||||
|
@ -15,8 +15,8 @@ const {
|
|||||||
ONE_GWEI_IN_WEI_HEX,
|
ONE_GWEI_IN_WEI_HEX,
|
||||||
SIMPLE_GAS_COST,
|
SIMPLE_GAS_COST,
|
||||||
} = require('./send.constants')
|
} = require('./send.constants')
|
||||||
const EthQuery = require('ethjs-query')
|
|
||||||
const abi = require('ethereumjs-abi')
|
const abi = require('ethereumjs-abi')
|
||||||
|
const ethUtil = require('ethereumjs-util')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
calcGasTotal,
|
calcGasTotal,
|
||||||
@ -165,40 +165,44 @@ function doesAmountErrorRequireUpdate ({
|
|||||||
return amountErrorRequiresUpdate
|
return amountErrorRequiresUpdate
|
||||||
}
|
}
|
||||||
|
|
||||||
async function estimateGas ({ selectedAddress, selectedToken, data, blockGasLimit, to }) {
|
async function estimateGas ({ selectedAddress, selectedToken, data, blockGasLimit, to, value, gasPrice, estimateGasMethod }) {
|
||||||
const ethQuery = new EthQuery(global.ethereumProvider)
|
|
||||||
const { symbol } = selectedToken || {}
|
const { symbol } = selectedToken || {}
|
||||||
const estimatedGasParams = { from: selectedAddress }
|
const paramsForGasEstimate = { from: selectedAddress, value, gasPrice }
|
||||||
|
|
||||||
if (symbol) {
|
if (symbol) {
|
||||||
Object.assign(estimatedGasParams, { value: '0x0' })
|
Object.assign(paramsForGasEstimate, { value: '0x0' })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
Object.assign(estimatedGasParams, { data })
|
Object.assign(paramsForGasEstimate, { data })
|
||||||
}
|
}
|
||||||
// if recipient has no code, gas is 21k max:
|
// if recipient has no code, gas is 21k max:
|
||||||
const hasRecipient = Boolean(to)
|
const hasRecipient = Boolean(to)
|
||||||
let code
|
let code
|
||||||
if (hasRecipient) code = await ethQuery.getCode(to)
|
if (hasRecipient) code = await global.eth.getCode(to)
|
||||||
|
|
||||||
if (hasRecipient && (!code || code === '0x')) {
|
if (hasRecipient && (!code || code === '0x')) {
|
||||||
return SIMPLE_GAS_COST
|
return SIMPLE_GAS_COST
|
||||||
}
|
}
|
||||||
|
|
||||||
estimatedGasParams.to = to
|
paramsForGasEstimate.to = to
|
||||||
|
|
||||||
// if not, fall back to block gasLimit
|
// if not, fall back to block gasLimit
|
||||||
estimatedGasParams.gas = multiplyCurrencies(blockGasLimit, 0.95, {
|
paramsForGasEstimate.gas = ethUtil.addHexPrefix(multiplyCurrencies(blockGasLimit, 0.95, {
|
||||||
multiplicandBase: 16,
|
multiplicandBase: 16,
|
||||||
multiplierBase: 10,
|
multiplierBase: 10,
|
||||||
roundDown: '0',
|
roundDown: '0',
|
||||||
toNumericBase: 'hex',
|
toNumericBase: 'hex',
|
||||||
})
|
}))
|
||||||
|
|
||||||
// run tx
|
// run tx
|
||||||
const estimatedGas = await ethQuery.estimateGas(estimatedGasParams)
|
return new Promise((resolve, reject) => {
|
||||||
return estimatedGas.toString(16)
|
estimateGasMethod(paramsForGasEstimate, (err, estimatedGas) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err)
|
||||||
|
}
|
||||||
|
resolve(estimatedGas.toString(16))
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateTokenTransferData (selectedAddress, selectedToken) {
|
function generateTokenTransferData (selectedAddress, selectedToken) {
|
||||||
|
@ -217,9 +217,17 @@ describe.only('Send Component', function () {
|
|||||||
recentBlocks: ['mockBlock'],
|
recentBlocks: ['mockBlock'],
|
||||||
selectedAddress: 'mockSelectedAddress',
|
selectedAddress: 'mockSelectedAddress',
|
||||||
selectedToken: 'mockSelectedToken',
|
selectedToken: 'mockSelectedToken',
|
||||||
|
to: undefined,
|
||||||
|
value: 'mockAmount',
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should call updateAndSetGasTotal with to set to lowercase if passed', () => {
|
||||||
|
propsMethodSpies.updateAndSetGasTotal.resetHistory()
|
||||||
|
wrapper.instance().updateGas({ to: '0xABC' })
|
||||||
|
assert.equal(propsMethodSpies.updateAndSetGasTotal.getCall(0).args[0].to, '0xabc')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('render', () => {
|
describe('render', () => {
|
||||||
|
@ -99,6 +99,8 @@ describe('send container', () => {
|
|||||||
recentBlocks: ['mockBlock'],
|
recentBlocks: ['mockBlock'],
|
||||||
selectedAddress: '0x4',
|
selectedAddress: '0x4',
|
||||||
selectedToken: { address: '0x1' },
|
selectedToken: { address: '0x1' },
|
||||||
|
to: 'mockTo',
|
||||||
|
value: 'mockValue',
|
||||||
}
|
}
|
||||||
|
|
||||||
it('should dispatch a setGasTotal action when editingTransactionId is truthy', () => {
|
it('should dispatch a setGasTotal action when editingTransactionId is truthy', () => {
|
||||||
@ -111,14 +113,14 @@ describe('send container', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should dispatch an updateGasData action when editingTransactionId is falsy', () => {
|
it('should dispatch an updateGasData action when editingTransactionId is falsy', () => {
|
||||||
const { selectedAddress, selectedToken, data, recentBlocks, blockGasLimit } = mockProps
|
const { selectedAddress, selectedToken, data, recentBlocks, blockGasLimit, to, value } = mockProps
|
||||||
mapDispatchToPropsObject.updateAndSetGasTotal(
|
mapDispatchToPropsObject.updateAndSetGasTotal(
|
||||||
Object.assign({}, mockProps, {editingTransactionId: false})
|
Object.assign({}, mockProps, {editingTransactionId: false})
|
||||||
)
|
)
|
||||||
assert(dispatchSpy.calledOnce)
|
assert(dispatchSpy.calledOnce)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
actionSpies.updateGasData.getCall(0).args[0],
|
actionSpies.updateGasData.getCall(0).args[0],
|
||||||
{ selectedAddress, selectedToken, data, recentBlocks, blockGasLimit }
|
{ selectedAddress, selectedToken, data, recentBlocks, blockGasLimit, to, value }
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -24,14 +24,6 @@ const stubs = {
|
|||||||
rawEncode: sinon.stub().returns([16, 1100]),
|
rawEncode: sinon.stub().returns([16, 1100]),
|
||||||
}
|
}
|
||||||
|
|
||||||
const EthQuery = function () {}
|
|
||||||
EthQuery.prototype.estimateGas = sinon.stub().callsFake(
|
|
||||||
(data) => Promise.resolve({ toString: (n) => `mockToString:${n}` })
|
|
||||||
)
|
|
||||||
EthQuery.prototype.getCode = sinon.stub().callsFake(
|
|
||||||
(address) => Promise.resolve(address.match(/isContract/) ? 'not-0x' : '0x')
|
|
||||||
)
|
|
||||||
|
|
||||||
const sendUtils = proxyquire('../send.utils.js', {
|
const sendUtils = proxyquire('../send.utils.js', {
|
||||||
'../../conversion-util': {
|
'../../conversion-util': {
|
||||||
addCurrencies: stubs.addCurrencies,
|
addCurrencies: stubs.addCurrencies,
|
||||||
@ -43,7 +35,6 @@ const sendUtils = proxyquire('../send.utils.js', {
|
|||||||
'ethereumjs-abi': {
|
'ethereumjs-abi': {
|
||||||
rawEncode: stubs.rawEncode,
|
rawEncode: stubs.rawEncode,
|
||||||
},
|
},
|
||||||
'ethjs-query': EthQuery,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -249,6 +240,9 @@ describe('send utils', () => {
|
|||||||
blockGasLimit: '0x64',
|
blockGasLimit: '0x64',
|
||||||
selectedAddress: 'mockAddress',
|
selectedAddress: 'mockAddress',
|
||||||
to: '0xisContract',
|
to: '0xisContract',
|
||||||
|
estimateGasMethod: sinon.stub().callsFake(
|
||||||
|
(data, cb) => cb(null, { toString: (n) => `mockToString:${n}` })
|
||||||
|
),
|
||||||
}
|
}
|
||||||
const baseExpectedCall = {
|
const baseExpectedCall = {
|
||||||
from: 'mockAddress',
|
from: 'mockAddress',
|
||||||
@ -256,53 +250,51 @@ describe('send utils', () => {
|
|||||||
to: '0xisContract',
|
to: '0xisContract',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
global.eth = {
|
||||||
|
getCode: sinon.stub().callsFake(
|
||||||
|
(address) => Promise.resolve(address.match(/isContract/) ? 'not-0x' : '0x')
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
EthQuery.prototype.estimateGas.resetHistory()
|
baseMockParams.estimateGasMethod.resetHistory()
|
||||||
EthQuery.prototype.getCode.resetHistory()
|
global.eth.getCode.resetHistory()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call ethQuery.estimateGas with the expected params', async () => {
|
it('should call ethQuery.estimateGas with the expected params', async () => {
|
||||||
const result = await estimateGas(baseMockParams)
|
const result = await estimateGas(baseMockParams)
|
||||||
assert.equal(EthQuery.prototype.estimateGas.callCount, 1)
|
assert.equal(baseMockParams.estimateGasMethod.callCount, 1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
EthQuery.prototype.estimateGas.getCall(0).args[0],
|
baseMockParams.estimateGasMethod.getCall(0).args[0],
|
||||||
baseExpectedCall
|
Object.assign({ gasPrice: undefined, value: undefined }, baseExpectedCall)
|
||||||
)
|
)
|
||||||
assert.equal(result, 'mockToString:16')
|
assert.equal(result, 'mockToString:16')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call ethQuery.estimateGas with a value of 0x0 if the passed selectedToken has a symbol', async () => {
|
it('should call ethQuery.estimateGas with a value of 0x0 if the passed selectedToken has a symbol', async () => {
|
||||||
const result = await estimateGas(Object.assign({ selectedToken: { symbol: true } }, baseMockParams))
|
const result = await estimateGas(Object.assign({ selectedToken: { symbol: true } }, baseMockParams))
|
||||||
assert.equal(EthQuery.prototype.estimateGas.callCount, 1)
|
assert.equal(baseMockParams.estimateGasMethod.callCount, 1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
EthQuery.prototype.estimateGas.getCall(0).args[0],
|
baseMockParams.estimateGasMethod.getCall(0).args[0],
|
||||||
Object.assign({ value: '0x0' }, baseExpectedCall)
|
Object.assign({ gasPrice: undefined, value: '0x0' }, baseExpectedCall)
|
||||||
)
|
)
|
||||||
assert.equal(result, 'mockToString:16')
|
assert.equal(result, 'mockToString:16')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should call ethQuery.estimateGas with data if data is passed', async () => {
|
it('should call ethQuery.estimateGas with data if data is passed', async () => {
|
||||||
const result = await estimateGas(Object.assign({ data: 'mockData' }, baseMockParams))
|
const result = await estimateGas(Object.assign({ data: 'mockData' }, baseMockParams))
|
||||||
assert.equal(EthQuery.prototype.estimateGas.callCount, 1)
|
assert.equal(baseMockParams.estimateGasMethod.callCount, 1)
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
EthQuery.prototype.estimateGas.getCall(0).args[0],
|
baseMockParams.estimateGasMethod.getCall(0).args[0],
|
||||||
Object.assign({ data: 'mockData' }, baseExpectedCall)
|
Object.assign({ gasPrice: undefined, value: undefined, data: 'mockData' }, baseExpectedCall)
|
||||||
)
|
|
||||||
assert.equal(result, 'mockToString:16')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should call ethQuery.estimateGas with data if data is passed', async () => {
|
|
||||||
const result = await estimateGas(Object.assign({ data: 'mockData' }, baseMockParams))
|
|
||||||
assert.equal(EthQuery.prototype.estimateGas.callCount, 1)
|
|
||||||
assert.deepEqual(
|
|
||||||
EthQuery.prototype.estimateGas.getCall(0).args[0],
|
|
||||||
Object.assign({ data: 'mockData' }, baseExpectedCall)
|
|
||||||
)
|
)
|
||||||
assert.equal(result, 'mockToString:16')
|
assert.equal(result, 'mockToString:16')
|
||||||
})
|
})
|
||||||
|
|
||||||
it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async () => {
|
it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async () => {
|
||||||
assert.equal(EthQuery.prototype.estimateGas.callCount, 0)
|
assert.equal(baseMockParams.estimateGasMethod.callCount, 0)
|
||||||
const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123' }))
|
const result = await estimateGas(Object.assign({}, baseMockParams, { to: '0x123' }))
|
||||||
assert.equal(result, SIMPLE_GAS_COST)
|
assert.equal(result, SIMPLE_GAS_COST)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user