diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js
index 09b1d3c1c..3a435e5d0 100644
--- a/app/scripts/controllers/network/createLocalhostClient.js
+++ b/app/scripts/controllers/network/createLocalhostClient.js
@@ -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()
+ })
+}
diff --git a/development/states/send-edit.json b/development/states/send-edit.json
index df97e1ef5..f77060b23 100644
--- a/development/states/send-edit.json
+++ b/development/states/send-edit.json
@@ -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,
diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js
index c98a8a965..2226d44bb 100644
--- a/test/e2e/metamask-ui.spec.js
+++ b/test/e2e/metamask-ui.spec.js
@@ -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 () {
diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js
index d6c259033..d942fd150 100644
--- a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js
+++ b/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js
@@ -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) {
+ componentDidUpdate (prevProps) {
+ const { customGasPrice: prevCustomGasPrice, customGasLimit: prevCustomGasLimit } = prevProps
+ const { customGasPrice, customGasLimit } = this.props
+ const { gasPrice, gasLimit } = this.state
+
+ 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))
}
- }, 1000, { trailing: true })
+ }
+
+ onChangeGasPrice = (e) => {
+ this.setState({ gasPrice: e.target.value })
+ this.changeGasPrice({ target: { value: e.target.value } })
+ }
- onChangeGasLimit = (val) => {
- this.props.updateCustomGasLimit(val)
- this.debouncedGasLimitReset(val)
+ 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}
/>
onChange(value + 1)}
+ onClick={() => onChange({ target: { value: value + 1 } })}
>
onChange(Math.max(value - 1, 0))}
+ onClick={() => onChange({ target: { value: Math.max(value - 1, 0) } })}
>
@@ -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 {
{ 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,
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
index 9da9a2ef6..c260d6798 100644
--- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
+++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
@@ -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),
diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
index dbe61d5cf..03d254eee 100644
--- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
+++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js
@@ -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(),
diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
index fc5e2f90d..5d2ccb083 100644
--- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
+++ b/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js
@@ -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)
diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js
index e769d8974..2a1b78a8e 100644
--- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js
+++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js
@@ -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,23 +33,26 @@ const mapStateToProps = (state, ownProps) => {
const { id: paramsTransactionId } = params
const { showFiatInTestnets } = preferencesSelector(state)
const isMainnet = getIsMainnet(state)
- const { confirmTransaction, metamask, gas } = state
+ const { confirmTransaction, metamask } = state
+ const {
+ conversionRate,
+ identities,
+ currentCurrency,
+ selectedAddress,
+ selectedAddressTxList,
+ assetImages,
+ network,
+ unapprovedTxs,
+ metaMetricsSendCount,
+ } = metamask
const {
- ethTransactionAmount,
- ethTransactionFee,
- ethTransactionTotal,
- fiatTransactionAmount,
- fiatTransactionFee,
- fiatTransactionTotal,
- hexTransactionAmount,
- hexTransactionFee,
- hexTransactionTotal,
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,
@@ -56,26 +60,10 @@ const mapStateToProps = (state, ownProps) => {
gas: gasLimit,
value: amount,
data,
- } = txParams
+ } = transaction && transaction.txParams || txParams
const accounts = getMetaMaskAccounts(state)
- const {
- conversionRate,
- identities,
- currentCurrency,
- selectedAddress,
- selectedAddressTxList,
- assetImages,
- network,
- unapprovedTxs,
- metaMetricsSendCount,
- } = metamask
const assetImage = assetImages[txParamsToAddress]
- const {
- customGasLimit,
- customGasPrice,
- } = gas
-
const { balance } = accounts[selectedAddress]
const { name: fromName } = identities[selectedAddress]
const toAddress = propsToAddress || txParamsToAddress
@@ -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)
+ },
}
}
diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js
index 9b5eda82f..82df4e776 100644
--- a/ui/app/selectors/confirm-transaction.js
+++ b/ui/app/selectors/confirm-transaction.js
@@ -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,
+ }
+}