1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-10-22 11:22:43 +02:00

Version 6.7.2 gas limit fix (#6786)

* Introduce delay for eth_estimateGas calls with in test

* Add test that fails when gas estimates of contract method calls without gas are too high.

* Get transaction gas data from unApprovedTxs instead of confirmTransaction

* Fix selection of gas data in gas-modal-page-container.container

* Lint changes related to Version-6.7.2-gasLimitFix

* Fix e2e tests on Version-6.7.2-gasLimitFix

* Fix unit and integration tests for changes from Version-6.7.2-gasLimitFix

* more e2e fixes

* Add assertions for transaction values on confirm screen

* Fix display of transaction amount on confirm screen.
This commit is contained in:
Dan J Miller 2019-07-03 18:03:44 -02:30 committed by Dan Finlay
parent e768ed9b16
commit 632c9b21e2
9 changed files with 279 additions and 91 deletions

View File

@ -2,9 +2,12 @@ const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware')
const createFetchMiddleware = require('eth-json-rpc-middleware/fetch')
const createBlockRefRewriteMiddleware = require('eth-json-rpc-middleware/block-ref-rewrite')
const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector')
const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware')
const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware')
const BlockTracker = require('eth-block-tracker')
const inTest = process.env.IN_TEST === 'true'
module.exports = createLocalhostClient
function createLocalhostClient () {
@ -13,9 +16,24 @@ function createLocalhostClient () {
const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 })
const networkMiddleware = mergeMiddleware([
createEstimateGasMiddleware(),
createBlockRefRewriteMiddleware({ blockTracker }),
createBlockTrackerInspectorMiddleware({ blockTracker }),
fetchMiddleware,
])
return { networkMiddleware, blockTracker }
}
function delay (time) {
return new Promise(resolve => setTimeout(resolve, time))
}
function createEstimateGasMiddleware () {
return createAsyncMiddleware(async (req, _, next) => {
if (req.method === 'eth_estimateGas' && inTest) {
await delay(2000)
}
return next()
})
}

View File

@ -1,4 +1,9 @@
{
"confirmTransaction": {
"txData": {
"id": 4768706228115573
}
},
"metamask": {
"completedOnboarding": true,
"isInitialized": true,
@ -66,7 +71,22 @@
],
"tokens": [],
"transactions": {},
"selectedAddressTxList": [],
"selectedAddressTxList": [{
"id": 4768706228115573,
"time": 1487363153561,
"status": "unapproved",
"gasMultiplier": 1,
"metamaskNetworkId": "3",
"txParams": {
"from": "0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb",
"to": "0x2f8d4a878cfa04a6e60d46362f5644deab66572d",
"value": "0x1bc16d674ec80000",
"metamaskId": 4768706228115573,
"metamaskNetworkId": "3",
"gas": "0xea60",
"gasPrice": "0xba43b7400"
}
}],
"unapprovedTxs": {
"4768706228115573": {
"id": 4768706228115573,

View File

@ -340,7 +340,7 @@ describe('MetaMask', function () {
it('confirms the transaction', async function () {
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await delay(largeDelayMs)
await delay(largeDelayMs * 2)
})
it('finds the transaction in the transactions list', async function () {
@ -428,6 +428,10 @@ describe('MetaMask', function () {
})
it('confirms the transaction', async function () {
const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text'))
const transactionAmount = transactionAmounts[0]
assert.equal(await transactionAmount.getText(), '1')
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await delay(largeDelayMs)
@ -528,7 +532,7 @@ describe('MetaMask', function () {
await delay(50)
await gasLimitInput.sendKeys('25000')
await delay(tinyDelayMs)
await delay(largeDelayMs * 2)
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000)
await confirmButton.click()
@ -685,11 +689,13 @@ describe('MetaMask', function () {
})
it('confirms a transaction', async () => {
await delay(tinyDelayMs)
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`), 10000)
await confirmButton.click()
await delay(regularDelayMs)
await delay(largeDelayMs * 2)
const navigationElement = await findElement(driver, By.css('.confirm-page-container-navigation'))
await delay(tinyDelayMs)
const navigationText = await navigationElement.getText()
assert.equal(navigationText.includes('4'), true, 'transaction confirmed')
})
@ -792,7 +798,7 @@ describe('MetaMask', function () {
await driver.wait(until.elementTextMatches(contractStatus, /Deposit\sinitiated/), 10000)
await driver.switchTo().window(extension)
await delay(largeDelayMs)
await delay(largeDelayMs * 2)
await findElements(driver, By.css('.transaction-list-item'))
const [txListValue] = await findElements(driver, By.css('.transaction-list-item__amount--primary'))
@ -812,6 +818,8 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
const [gasPriceInput, gasLimitInput] = await findElements(driver, By.css('.advanced-tab__gas-edit-row__input'))
const gasLimitValue = await gasLimitInput.getAttribute('value')
assert(Number(gasLimitValue) < 100000, 'Gas Limit too high')
await gasPriceInput.sendKeys(Key.chord(Key.CONTROL, 'a'))
await delay(50)
@ -870,7 +878,7 @@ describe('MetaMask', function () {
await delay(regularDelayMs)
await driver.switchTo().window(extension)
await delay(regularDelayMs)
await delay(largeDelayMs * 2)
const txListItem = await findElement(driver, By.css('.transaction-list-item'))
await txListItem.click()
@ -1102,6 +1110,10 @@ describe('MetaMask', function () {
await txListValue.click()
await delay(regularDelayMs)
const transactionAmounts = await findElements(driver, By.css('.currency-display-component__text'))
const transactionAmount = transactionAmounts[0]
assert(await transactionAmount.getText(), '1.5 TST')
// Set the gas limit
const configureGas = await driver.wait(until.elementLocated(By.css('.confirm-detail-row__header-text--edit')), 10000)
await configureGas.click()
@ -1340,10 +1352,10 @@ describe('MetaMask', function () {
})
it('submits the transaction', async function () {
await delay(regularDelayMs)
await delay(largeDelayMs * 2)
const confirmButton = await findElement(driver, By.xpath(`//button[contains(text(), 'Confirm')]`))
await confirmButton.click()
await delay(regularDelayMs)
await delay(largeDelayMs * 2)
})
it('finds the transaction in the transactions list', async function () {

View File

@ -8,6 +8,17 @@ export default class AdvancedTabContent extends Component {
t: PropTypes.func,
}
constructor (props) {
super(props)
this.state = {
gasPrice: this.props.customGasPrice,
gasLimit: this.props.customGasLimit,
}
this.changeGasPrice = debounce(this.changeGasPrice, 500)
this.changeGasLimit = debounce(this.changeGasLimit, 500)
}
static propTypes = {
updateCustomGasPrice: PropTypes.func,
updateCustomGasLimit: PropTypes.func,
@ -20,15 +31,40 @@ export default class AdvancedTabContent extends Component {
showGasLimitInfoModal: PropTypes.func,
}
debouncedGasLimitReset = debounce((dVal) => {
if (dVal < 21000) {
this.props.updateCustomGasLimit(21000)
}
}, 1000, { trailing: true })
componentDidUpdate (prevProps) {
const { customGasPrice: prevCustomGasPrice, customGasLimit: prevCustomGasLimit } = prevProps
const { customGasPrice, customGasLimit } = this.props
const { gasPrice, gasLimit } = this.state
onChangeGasLimit = (val) => {
this.props.updateCustomGasLimit(val)
this.debouncedGasLimitReset(val)
if (customGasPrice !== prevCustomGasPrice && customGasPrice !== gasPrice) {
this.setState({ gasPrice: customGasPrice })
}
if (customGasLimit !== prevCustomGasLimit && customGasLimit !== gasLimit) {
this.setState({ gasLimit: customGasLimit })
}
}
onChangeGasLimit = (e) => {
this.setState({ gasLimit: e.target.value })
this.changeGasLimit({ target: { value: e.target.value } })
}
changeGasLimit = (e) => {
if (e.target.value < 21000) {
this.setState({ gasLimit: 21000 })
this.props.updateCustomGasLimit(21000)
} else {
this.props.updateCustomGasLimit(Number(e.target.value))
}
}
onChangeGasPrice = (e) => {
this.setState({ gasPrice: e.target.value })
this.changeGasPrice({ target: { value: e.target.value } })
}
changeGasPrice = (e) => {
this.props.updateCustomGasPrice(Number(e.target.value))
}
gasInputError ({ labelKey, insufficientBalance, customPriceIsSafe, isSpeedUp, value }) {
@ -74,7 +110,7 @@ export default class AdvancedTabContent extends Component {
})}
type="number"
value={value}
onChange={event => onChange(Number(event.target.value))}
onChange={onChange}
/>
<div className={classnames('advanced-gas-inputs__gas-edit-row__input-arrows', {
'advanced-gas-inputs__gas-edit-row__input--error': isInError && errorType === 'error',
@ -82,13 +118,13 @@ export default class AdvancedTabContent extends Component {
})}>
<div
className="advanced-gas-inputs__gas-edit-row__input-arrows__i-wrap"
onClick={() => onChange(value + 1)}
onClick={() => onChange({ target: { value: value + 1 } })}
>
<i className="fa fa-sm fa-angle-up" />
</div>
<div
className="advanced-gas-inputs__gas-edit-row__input-arrows__i-wrap"
onClick={() => onChange(Math.max(value - 1, 0))}
onClick={() => onChange({ target: { value: Math.max(value - 1, 0) } })}
>
<i className="fa fa-sm fa-angle-down" />
</div>
@ -120,9 +156,6 @@ export default class AdvancedTabContent extends Component {
render () {
const {
customGasPrice,
updateCustomGasPrice,
customGasLimit,
insufficientBalance,
customPriceIsSafe,
isSpeedUp,
@ -134,8 +167,8 @@ export default class AdvancedTabContent extends Component {
<div className="advanced-gas-inputs__gas-edit-rows">
{ this.renderGasEditRow({
labelKey: 'gasPrice',
value: customGasPrice,
onChange: updateCustomGasPrice,
value: this.state.gasPrice,
onChange: this.onChangeGasPrice,
insufficientBalance,
customPriceIsSafe,
showGWEI: true,
@ -144,7 +177,7 @@ export default class AdvancedTabContent extends Component {
}) }
{ this.renderGasEditRow({
labelKey: 'gasLimit',
value: customGasLimit,
value: this.state.gasLimit,
onChange: this.onChangeGasLimit,
insufficientBalance,
customPriceIsSafe,

View File

@ -9,6 +9,7 @@ import {
hideSidebar,
updateSendAmount,
setGasTotal,
updateTransaction,
} from '../../../../store/actions'
import {
setCustomGasPrice,
@ -22,9 +23,6 @@ import {
hideGasButtonGroup,
updateSendErrors,
} from '../../../../ducks/send/send.duck'
import {
updateGasAndCalculate,
} from '../../../../ducks/confirm-transaction/confirm-transaction.duck'
import {
conversionRateSelector as getConversionRate,
getCurrentCurrency,
@ -51,9 +49,6 @@ import {
import {
getTokenBalance,
} from '../../../../pages/send/send.selectors'
import {
submittedPendingTransactionsSelector,
} from '../../../../selectors/transactions'
import {
formatCurrency,
} from '../../../../helpers/utils/confirm-tx.util'
@ -77,11 +72,16 @@ import { getMaxModeOn } from '../../../../pages/send/send-content/send-amount-ro
import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils'
const mapStateToProps = (state, ownProps) => {
const { selectedAddressTxList } = state.metamask
const { modalState: { props: modalProps } = {} } = state.appState.modal || {}
const { txData = {} } = modalProps || {}
const { transaction = {} } = ownProps
const selectedTransaction = selectedAddressTxList.find(({ id }) => id === (transaction.id || txData.id))
const buttonDataLoading = getBasicGasEstimateLoadingStatus(state)
const gasEstimatesLoading = getGasEstimatesLoadingStatus(state)
const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = getTxParams(state, transaction.id)
const { gasPrice: currentGasPrice, gas: currentGasLimit, value } = getTxParams(state, selectedTransaction)
const customModalGasPriceInHex = getCustomGasPrice(state) || currentGasPrice
const customModalGasLimitInHex = getCustomGasLimit(state) || currentGasLimit
const customGasTotal = calcGasTotal(customModalGasLimitInHex, customModalGasPriceInHex)
@ -118,6 +118,7 @@ const mapStateToProps = (state, ownProps) => {
conversionRate,
})
return {
hideBasic,
isConfirm: isConfirm(state),
@ -151,6 +152,7 @@ const mapStateToProps = (state, ownProps) => {
transactionFee: addHexWEIsToRenderableEth('0x0', customGasTotal),
sendAmount,
},
transaction: txData || transaction,
isSpeedUp: transaction.status === 'submitted',
txId: transaction.id,
insufficientBalance,
@ -179,10 +181,10 @@ const mapDispatchToProps = dispatch => {
dispatch(setGasLimit(newLimit))
dispatch(setGasPrice(newPrice))
},
updateConfirmTxGasAndCalculate: (gasLimit, gasPrice) => {
updateConfirmTxGasAndCalculate: (gasLimit, gasPrice, updatedTx) => {
updateCustomGasPrice(gasPrice)
dispatch(setCustomGasLimit(addHexPrefix(gasLimit.toString(16))))
return dispatch(updateGasAndCalculate({ gasLimit, gasPrice }))
return dispatch(updateTransaction(updatedTx))
},
createSpeedUpTransaction: (txId, gasPrice) => {
return dispatch(createSpeedUpTransaction(txId, gasPrice))
@ -214,6 +216,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
selectedToken,
tokenBalance,
customGasLimit,
transaction,
} = stateProps
const {
updateCustomGasPrice: dispatchUpdateCustomGasPrice,
@ -234,7 +237,15 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
...ownProps,
onSubmit: (gasLimit, gasPrice) => {
if (isConfirm) {
dispatchUpdateConfirmTxGasAndCalculate(gasLimit, gasPrice)
const updatedTx = {
...transaction,
txParams: {
...transaction.txParams,
gas: gasLimit,
gasPrice,
},
}
dispatchUpdateConfirmTxGasAndCalculate(gasLimit, gasPrice, updatedTx)
dispatchHideModal()
} else if (isSpeedUp) {
dispatchCreateSpeedUpTransaction(txId, gasPrice)
@ -282,12 +293,10 @@ function calcCustomGasLimit (customGasLimitInHex) {
return parseInt(customGasLimitInHex, 16)
}
function getTxParams (state, transactionId) {
const { confirmTransaction: { txData }, metamask: { send } } = state
const pendingTransactions = submittedPendingTransactionsSelector(state)
const pendingTransaction = pendingTransactions.find(({ id }) => id === transactionId)
const { txParams: pendingTxParams } = pendingTransaction || {}
return txData.txParams || pendingTxParams || {
function getTxParams (state, selectedTransaction = {}) {
const { metamask: { send } } = state
const { txParams } = selectedTransaction
return txParams || {
from: send.from,
gas: send.gasLimit || '0x5208',
gasPrice: send.gasPrice || getFastPriceEstimateInHexWEI(state, true),

View File

@ -63,6 +63,9 @@ describe('gas-modal-page-container container', () => {
modalState: {
props: {
hideBasic: true,
txData: {
id: 34,
},
},
},
},
@ -82,6 +85,14 @@ describe('gas-modal-page-container container', () => {
provider: {
type: 'mainnet',
},
selectedAddressTxList: [{
id: 34,
txParams: {
gas: '0x1600000',
gasPrice: '0x3200000',
value: '0x640000000000000',
},
}],
},
gas: {
basicEstimates: {
@ -152,6 +163,9 @@ describe('gas-modal-page-container container', () => {
maxModeOn: false,
selectedToken: null,
tokenBalance: '0x0',
transaction: {
id: 34,
},
}
const baseMockOwnProps = { transaction: { id: 34 } }
const tests = [
@ -168,7 +182,7 @@ describe('gas-modal-page-container container', () => {
mockOwnProps: Object.assign({}, baseMockOwnProps, {
transaction: { id: 34, status: 'submitted' },
}),
expectedResult: Object.assign({}, baseExpectedResult, { isSpeedUp: true }),
expectedResult: Object.assign({}, baseExpectedResult, { isSpeedUp: true, transaction: { id: 34 } }),
},
{
mockState: Object.assign({}, baseMockState, {
@ -317,8 +331,10 @@ describe('gas-modal-page-container container', () => {
it('should dispatch a updateGasAndCalculate action with the correct props', () => {
mapDispatchToPropsObject.updateConfirmTxGasAndCalculate('ffff', 'aaaa')
assert.equal(dispatchSpy.callCount, 3)
assert(confirmTransactionActionSpies.updateGasAndCalculate.calledOnce)
assert.deepEqual(confirmTransactionActionSpies.updateGasAndCalculate.getCall(0).args[0], { gasLimit: 'ffff', gasPrice: 'aaaa' })
assert(actionSpies.setGasPrice.calledOnce)
assert(actionSpies.setGasLimit.calledOnce)
assert.equal(actionSpies.setGasLimit.getCall(0).args[0], 'ffff')
assert.equal(actionSpies.setGasPrice.getCall(0).args[0], 'aaaa')
})
})
@ -337,6 +353,7 @@ describe('gas-modal-page-container container', () => {
},
isConfirm: true,
someOtherStateProp: 'baz',
transaction: {},
}
dispatchProps = {
updateCustomGasPrice: sinon.spy(),

View File

@ -1,7 +1,10 @@
import { connect } from 'react-redux'
import { compose } from 'recompose'
import { withRouter } from 'react-router-dom'
import ConfirmTokenTransactionBase from './confirm-token-transaction-base.component'
import {
contractExchangeRateSelector,
transactionFeeSelector,
} from '../../selectors/confirm-transaction'
import { tokenSelector } from '../../selectors/tokens'
import {
@ -14,15 +17,21 @@ import {
} from '../../helpers/utils/token-util'
const mapStateToProps = (state) => {
const { confirmTransaction, metamask: { currentCurrency, conversionRate } } = state
const mapStateToProps = (state, ownProps) => {
const { match: { params = {} } } = ownProps
const { id: paramsTransactionId } = params
const { confirmTransaction, metamask: { currentCurrency, conversionRate, selectedAddressTxList } } = state
const {
txData: { txParams: { to: tokenAddress, data } = {} } = {},
fiatTransactionTotal,
ethTransactionTotal,
txData: { id: transactionId, txParams: { to: tokenAddress, data } = {} } = {},
} = confirmTransaction
const transaction = selectedAddressTxList.find(({ id }) => id === (Number(paramsTransactionId) || transactionId)) || {}
const {
ethTransactionTotal,
fiatTransactionTotal,
} = transactionFeeSelector(state, transaction)
const tokens = tokenSelector(state)
const currentToken = tokens && tokens.find(({ address }) => tokenAddress === address)
const { decimals, symbol: tokenSymbol } = currentToken || {}
@ -46,4 +55,7 @@ const mapStateToProps = (state) => {
}
}
export default connect(mapStateToProps)(ConfirmTokenTransactionBase)
export default compose(
withRouter,
connect(mapStateToProps)
)(ConfirmTokenTransactionBase)

View File

@ -6,9 +6,9 @@ import contractMap from 'eth-contract-metadata'
import ConfirmTransactionBase from './confirm-transaction-base.component'
import {
clearConfirmTransaction,
updateGasAndCalculate,
} from '../../ducks/confirm-transaction/confirm-transaction.duck'
import { clearSend, cancelTx, cancelTxs, updateAndApproveTx, showModal, setMetaMetricsSendCount } from '../../store/actions'
import { clearSend, cancelTx, cancelTxs, updateAndApproveTx, showModal, setMetaMetricsSendCount, updateTransaction } from '../../store/actions'
import {
INSUFFICIENT_FUNDS_ERROR_KEY,
GAS_LIMIT_TOO_LOW_ERROR_KEY,
@ -19,6 +19,7 @@ import { conversionGreaterThan } from '../../helpers/utils/conversion-util'
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'
import { checksumAddress, addressSlicer, valuesFor } from '../../helpers/utils/util'
import { getMetaMaskAccounts, getAdvancedInlineGasShown, preferencesSelector, getIsMainnet, getKnownMethodData } from '../../selectors/selectors'
import { transactionFeeSelector } from '../../selectors/confirm-transaction'
const casedContractMap = Object.keys(contractMap).reduce((acc, base) => {
return {
@ -32,32 +33,7 @@ const mapStateToProps = (state, ownProps) => {
const { id: paramsTransactionId } = params
const { showFiatInTestnets } = preferencesSelector(state)
const isMainnet = getIsMainnet(state)
const { confirmTransaction, metamask, gas } = state
const {
ethTransactionAmount,
ethTransactionFee,
ethTransactionTotal,
fiatTransactionAmount,
fiatTransactionFee,
fiatTransactionTotal,
hexTransactionAmount,
hexTransactionFee,
hexTransactionTotal,
tokenData,
txData,
tokenProps,
nonce,
} = confirmTransaction
const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory } = txData
const {
from: fromAddress,
to: txParamsToAddress,
gasPrice,
gas: gasLimit,
value: amount,
data,
} = txParams
const accounts = getMetaMaskAccounts(state)
const { confirmTransaction, metamask } = state
const {
conversionRate,
identities,
@ -69,12 +45,24 @@ const mapStateToProps = (state, ownProps) => {
unapprovedTxs,
metaMetricsSendCount,
} = metamask
const assetImage = assetImages[txParamsToAddress]
const {
customGasLimit,
customGasPrice,
} = gas
tokenData,
txData,
tokenProps,
nonce,
} = confirmTransaction
const { txParams = {}, lastGasPrice, id: transactionId, transactionCategory } = txData
const transaction = R.find(({ id }) => id === (transactionId || Number(paramsTransactionId)))(selectedAddressTxList) || {}
const {
from: fromAddress,
to: txParamsToAddress,
gasPrice,
gas: gasLimit,
value: amount,
data,
} = transaction && transaction.txParams || txParams
const accounts = getMetaMaskAccounts(state)
const assetImage = assetImages[txParamsToAddress]
const { balance } = accounts[selectedAddress]
const { name: fromName } = identities[selectedAddress]
@ -88,9 +76,20 @@ const mapStateToProps = (state, ownProps) => {
)
const isTxReprice = Boolean(lastGasPrice)
const transaction = R.find(({ id }) => id === (transactionId || Number(paramsTransactionId)))(selectedAddressTxList)
const transactionStatus = transaction ? transaction.status : ''
const {
ethTransactionAmount,
ethTransactionFee,
ethTransactionTotal,
fiatTransactionAmount,
fiatTransactionFee,
fiatTransactionTotal,
hexTransactionAmount,
hexTransactionFee,
hexTransactionTotal,
} = transactionFeeSelector(state, transaction)
if (transaction && transaction.simulationFails) {
txData.simulationFails = transaction.simulationFails
}
@ -125,7 +124,7 @@ const mapStateToProps = (state, ownProps) => {
hexTransactionAmount,
hexTransactionFee,
hexTransactionTotal,
txData: Object.keys(txData).length ? txData : transaction || {},
txData: { ...txData, ...transaction },
tokenData,
methodData,
tokenProps,
@ -139,8 +138,8 @@ const mapStateToProps = (state, ownProps) => {
unapprovedTxCount,
currentNetworkUnapprovedTxs,
customGas: {
gasLimit: customGasLimit || gasLimit,
gasPrice: customGasPrice || gasPrice,
gasLimit,
gasPrice,
},
advancedInlineGasShown: getAdvancedInlineGasShown(state),
insufficientBalance,
@ -161,8 +160,8 @@ const mapDispatchToProps = dispatch => {
showCustomizeGasModal: ({ txData, onSubmit, validate }) => {
return dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData, onSubmit, validate }))
},
updateGasAndCalculate: ({ gasLimit, gasPrice }) => {
return dispatch(updateGasAndCalculate({ gasLimit, gasPrice }))
updateGasAndCalculate: (updatedTx) => {
return dispatch(updateTransaction(updatedTx))
},
showRejectTransactionsConfirmationModal: ({ onSubmit, unapprovedTxCount }) => {
return dispatch(showModal({ name: 'REJECT_TRANSACTIONS', onSubmit, unapprovedTxCount }))
@ -239,7 +238,17 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
validate: validateEditGas,
}),
cancelAllTransactions: () => dispatchCancelAllTransactions(valuesFor(unapprovedTxs)),
updateGasAndCalculate: dispatchUpdateGasAndCalculate,
updateGasAndCalculate: ({ gasLimit, gasPrice }) => {
const updatedTx = {
...txData,
txParams: {
...txData.txParams,
gas: gasLimit,
gasPrice,
},
}
dispatchUpdateGasAndCalculate(updatedTx)
},
}
}

View File

@ -1,7 +1,17 @@
import { createSelector } from 'reselect'
import txHelper from '../../lib/tx-helper'
import { calcTokenAmount } from '../helpers/utils/token-util'
import { roundExponential } from '../helpers/utils/confirm-tx.util'
import {
roundExponential,
getValueFromWeiHex,
getHexGasTotal,
getTransactionFee,
addFiat,
addEth,
} from '../helpers/utils/confirm-tx.util'
import {
sumHexes,
} from '../helpers/utils/transactions.util'
const unapprovedTxsSelector = state => state.metamask.unapprovedTxs
const unapprovedMsgsSelector = state => state.metamask.unapprovedMsgs
@ -207,3 +217,51 @@ export const contractExchangeRateSelector = createSelector(
tokenAddressSelector,
(contractExchangeRates, tokenAddress) => contractExchangeRates[tokenAddress]
)
export const transactionFeeSelector = function (state, txData) {
const currentCurrency = currentCurrencySelector(state)
const conversionRate = conversionRateSelector(state)
const nativeCurrency = getNativeCurrency(state)
const { txParams: { value = '0x0', gas: gasLimit = '0x0', gasPrice = '0x0' } = {} } = txData
const fiatTransactionAmount = getValueFromWeiHex({
value, fromCurrency: nativeCurrency, toCurrency: currentCurrency, conversionRate, numberOfDecimals: 2,
})
const ethTransactionAmount = getValueFromWeiHex({
value, fromCurrency: nativeCurrency, toCurrency: nativeCurrency, conversionRate, numberOfDecimals: 6,
})
const hexTransactionFee = getHexGasTotal({ gasLimit, gasPrice })
const fiatTransactionFee = getTransactionFee({
value: hexTransactionFee,
fromCurrency: nativeCurrency,
toCurrency: currentCurrency,
numberOfDecimals: 2,
conversionRate,
})
const ethTransactionFee = getTransactionFee({
value: hexTransactionFee,
fromCurrency: nativeCurrency,
toCurrency: nativeCurrency,
numberOfDecimals: 6,
conversionRate,
})
const fiatTransactionTotal = addFiat(fiatTransactionFee, fiatTransactionAmount)
const ethTransactionTotal = addEth(ethTransactionFee, ethTransactionAmount)
const hexTransactionTotal = sumHexes(value, hexTransactionFee)
return {
hexTransactionAmount: value,
fiatTransactionAmount,
ethTransactionAmount,
hexTransactionFee,
fiatTransactionFee,
ethTransactionFee,
fiatTransactionTotal,
ethTransactionTotal,
hexTransactionTotal,
}
}