From 397e0d128d034d10ab3f44641128f3aef99355a9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 1 Jul 2019 13:03:57 -0700 Subject: [PATCH 1/3] Version 6.7.2 RC1 --- CHANGELOG.md | 15 +++++++++++++++ app/manifest.json | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6960385ba..0bd3ccc7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## Current Develop Branch +## 6.7.2 Mon Jul 01 2019 + +- [#6713](https://github.com/MetaMask/metamask-extension/pull/6713): * Normalize and Validate txParams in TransactionStateManager.addTx too +- [#6759](https://github.com/MetaMask/metamask-extension/pull/6759): Update to Node.js v10 +- [#Fixes #6694 ](https://github.com/MetaMask/metamask-extension/pull/Fixes #6694 ): Fixes #6694 +- [#6743](https://github.com/MetaMask/metamask-extension/pull/6743): * Add tests for ImportWithSeedPhrase#parseSeedPhrase +- [#Fixes #6740](https://github.com/MetaMask/metamask-extension/pull/Fixes #6740): Fixes #6740 +- [#Fixes #6741](https://github.com/MetaMask/metamask-extension/pull/Fixes #6741): Fixes #6741 +- [#6761](https://github.com/MetaMask/metamask-extension/pull/6761): Fixes #6760, correct PropTypes for nextRoute +- [#6754](https://github.com/MetaMask/metamask-extension/pull/6754): There is currently a bug in chrome that prevents reading source maps +- [#6589](https://github.com/MetaMask/metamask-extension/pull/6589): Document hotfix protocol +- [#6738](https://github.com/MetaMask/metamask-extension/pull/6738): Add codeowner for package-lock-old.json package-lock.json package.json packagelock-old.json files +- [#6648](https://github.com/MetaMask/metamask-extension/pull/6648): Add loading view to notification.html +- [#6731](https://github.com/MetaMask/metamask-extension/pull/6731): Add brave as a platform type for MetaMask + ## 6.7.1 Fri Jun 28 2019 - [#6764](https://github.com/MetaMask/metamask-extension/pull/6764): Fix display of token amount on confirm transaction screen diff --git a/app/manifest.json b/app/manifest.json index d09407373..8639577bb 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "6.7.1", + "version": "6.7.2", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", From 05e21208146c65325330746a7860ce086f10e345 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 3 Jul 2019 18:03:44 -0230 Subject: [PATCH 2/3] 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. --- .../network/createLocalhostClient.js | 18 ++++ development/states/send-edit.json | 22 ++++- test/e2e/metamask-ui.spec.js | 26 ++++-- .../advanced-gas-inputs.component.js | 67 ++++++++++---- .../gas-modal-page-container.container.js | 41 +++++---- ...gas-modal-page-container-container.test.js | 23 ++++- ...onfirm-token-transaction-base.container.js | 24 +++-- .../confirm-transaction-base.container.js | 89 ++++++++++--------- ui/app/selectors/confirm-transaction.js | 60 ++++++++++++- 9 files changed, 279 insertions(+), 91 deletions(-) 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) { - 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} />
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,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) + }, } } 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, + } +} From 1c19ce91a421134a41f1e14a60196d8da0e778f0 Mon Sep 17 00:00:00 2001 From: Mark Stacey Date: Thu, 11 Jul 2019 19:05:55 -0300 Subject: [PATCH 3/3] Fix changelog formatting errors The description for one entry has also been corrected. --- CHANGELOG.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd3ccc7f..353018593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,14 @@ ## 6.7.2 Mon Jul 01 2019 -- [#6713](https://github.com/MetaMask/metamask-extension/pull/6713): * Normalize and Validate txParams in TransactionStateManager.addTx too +- [#6713](https://github.com/MetaMask/metamask-extension/pull/6713): * Normalize and Validate txParams in TransactionStateManager.addTx too - [#6759](https://github.com/MetaMask/metamask-extension/pull/6759): Update to Node.js v10 -- [#Fixes #6694 ](https://github.com/MetaMask/metamask-extension/pull/Fixes #6694 ): Fixes #6694 -- [#6743](https://github.com/MetaMask/metamask-extension/pull/6743): * Add tests for ImportWithSeedPhrase#parseSeedPhrase -- [#Fixes #6740](https://github.com/MetaMask/metamask-extension/pull/Fixes #6740): Fixes #6740 -- [#Fixes #6741](https://github.com/MetaMask/metamask-extension/pull/Fixes #6741): Fixes #6741 +- [#6694](https://github.com/MetaMask/metamask-extension/pull/6694): Fixes #6694 +- [#6743](https://github.com/MetaMask/metamask-extension/pull/6743): * Add tests for ImportWithSeedPhrase#parseSeedPhrase +- [#6740](https://github.com/MetaMask/metamask-extension/pull/6740): Fixes #6740 +- [#6741](https://github.com/MetaMask/metamask-extension/pull/6741): Fixes #6741 - [#6761](https://github.com/MetaMask/metamask-extension/pull/6761): Fixes #6760, correct PropTypes for nextRoute -- [#6754](https://github.com/MetaMask/metamask-extension/pull/6754): There is currently a bug in chrome that prevents reading source maps +- [#6754](https://github.com/MetaMask/metamask-extension/pull/6754): Use inline source maps in development - [#6589](https://github.com/MetaMask/metamask-extension/pull/6589): Document hotfix protocol - [#6738](https://github.com/MetaMask/metamask-extension/pull/6738): Add codeowner for package-lock-old.json package-lock.json package.json packagelock-old.json files - [#6648](https://github.com/MetaMask/metamask-extension/pull/6648): Add loading view to notification.html @@ -24,7 +24,7 @@ - [#6623](https://github.com/MetaMask/metamask-extension/pull/6623): Improve contract method data fetching (#6623) - [#6551](https://github.com/MetaMask/metamask-extension/pull/6551): Adds 4byte registry fallback to getMethodData() (#6435) -- [#6718, #6650](https://github.com/MetaMask/metamask-extension/pull/6718, #6650): Add delete to custom RPC form +- [#6718](https://github.com/MetaMask/metamask-extension/pull/6718): Add delete to custom RPC form - [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link - [#6714](https://github.com/MetaMask/metamask-extension/pull/6714): Wrap smaller custom block explorer url text - [#6706](https://github.com/MetaMask/metamask-extension/pull/6706): Pin ethereumjs-tx