From e768ed9b167c2e9d856e1ff1a4a3e495d39d1083 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 1 Jul 2019 13:03:57 -0700 Subject: [PATCH 1/7] 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 632c9b21e297f3255ecbb4a70812aa53c87b2ff4 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 3 Jul 2019 18:03:44 -0230 Subject: [PATCH 2/7] 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/beta/metamask-beta-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 7c7e8f097..c83968ae8 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/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 7aa386637..b0ec25cd9 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-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 a6deccd81096ad4bbef0f1fa6e816c41ecb57ba5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 18 Jul 2019 19:23:03 -0700 Subject: [PATCH 3/7] Fix resubmit bug --- app/scripts/controllers/transactions/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 1ae925835..c4371c25b 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -68,6 +68,7 @@ class TransactionController extends EventEmitter { this.blockTracker = opts.blockTracker this.signEthTx = opts.signTransaction this.getGasPrice = opts.getGasPrice + this.inProcessOfSigning = new Set() this.memStore = new ObservableStore({}) this.query = new EthQuery(this.provider) @@ -354,6 +355,15 @@ class TransactionController extends EventEmitter { @param txId {number} - the tx's Id */ async approveTransaction (txId) { + // TODO: Move this safety out of this function. + // Since this transaction is async, + // we need to keep track of what is currently being signed, + // So that we do not increment nonce + resubmit something + // that is already being incrmented & signed. + if (this.inProcessOfSigning.has(txId)) { + return + } + this.inProcessOfSigning.add(txId) let nonceLock try { // approve @@ -387,6 +397,8 @@ class TransactionController extends EventEmitter { if (nonceLock) nonceLock.releaseLock() // continue with error chain throw err + } finally { + this.inProcessOfSigning.delete(txId) } } /** From 4139019d0f4dd83f56da400ca7e0e6d1976d1716 Mon Sep 17 00:00:00 2001 From: Dan Finlay <542863+danfinlay@users.noreply.github.com> Date: Thu, 18 Jul 2019 20:48:07 -0700 Subject: [PATCH 4/7] Version 6.7.3 (#6889) --- CHANGELOG.md | 4 ++++ app/manifest.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bd3ccc7f..d06aecb01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Current Develop Branch +## 6.7.3 Thu Jul 18 2019 + +- [#6888](https://github.com/MetaMask/metamask-extension/pull/6888): Fix bug with resubmitting unsigned transactions. + ## 6.7.2 Mon Jul 01 2019 - [#6713](https://github.com/MetaMask/metamask-extension/pull/6713): * Normalize and Validate txParams in TransactionStateManager.addTx too diff --git a/app/manifest.json b/app/manifest.json index 8639577bb..d994e7518 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "__MSG_appName__", "short_name": "__MSG_appName__", - "version": "6.7.2", + "version": "6.7.3", "manifest_version": 2, "author": "https://metamask.io", "description": "__MSG_appDescription__", From 1e5b678772f0089a84e389771e840195c15bbadb Mon Sep 17 00:00:00 2001 From: Dan Miller Date: Mon, 5 Aug 2019 15:27:50 -0230 Subject: [PATCH 5/7] Ensure showing of add contact dialog on send accounts for checksum inputs --- ui/app/pages/send/send-content/send-content.component.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/pages/send/send-content/send-content.component.js b/ui/app/pages/send/send-content/send-content.component.js index c08a018da..aff675e7a 100644 --- a/ui/app/pages/send/send-content/send-content.component.js +++ b/ui/app/pages/send/send-content/send-content.component.js @@ -48,7 +48,7 @@ export default class SendContent extends Component { maybeRenderAddContact () { const { t } = this.context const { to, addressBook = [], ownedAccounts = [], showAddToAddressBookModal } = this.props - const isOwnedAccount = !!ownedAccounts.find(({ address }) => address === to) + const isOwnedAccount = !!ownedAccounts.find(({ address }) => address.toLowerCase() === to.toLowerCase()) const contact = addressBook.find(({ address }) => address === to) || {} if (isOwnedAccount || contact.name) { From 010e3927da0f98857c1703b9c568e91abce72db9 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 6 Aug 2019 00:54:19 -0230 Subject: [PATCH 6/7] Show seed phrase challenge in browser (#6961) * Open backup challenge screen, prompted from notification, in browser window * Remove no longer used showingSeedPhraseBackupAfterOnboarding related code * Make incremental-security.spec.js click through the seed phrase success screen --- test/e2e/incremental-security.spec.js | 6 ++++++ ui/app/ducks/app/app.js | 12 ------------ ui/app/helpers/constants/routes.js | 3 +++ .../first-time-flow.component.js | 11 +++++++++++ .../first-time-flow.container.js | 8 ++++++-- .../seed-phrase/seed-phrase.component.js | 11 +++++++++++ ui/app/pages/home/home.component.js | 13 ++++++++----- ui/app/pages/home/home.container.js | 2 -- ui/app/store/actions.js | 17 ----------------- 9 files changed, 45 insertions(+), 38 deletions(-) diff --git a/test/e2e/incremental-security.spec.js b/test/e2e/incremental-security.spec.js index 5b0990581..ecd6f5999 100644 --- a/test/e2e/incremental-security.spec.js +++ b/test/e2e/incremental-security.spec.js @@ -280,6 +280,12 @@ describe('MetaMask', function () { await delay(regularDelayMs) }) + it('can click through the success screen', async () => { + const confirm = await findElement(driver, By.xpath(`//button[contains(text(), 'All Done')]`)) + await confirm.click() + await delay(regularDelayMs) + }) + it('should have the correct amount of eth', async () => { const balances = await findElements(driver, By.css('.currency-display-component__text')) await driver.wait(until.elementTextMatches(balances[0], /1/), 15000) diff --git a/ui/app/ducks/app/app.js b/ui/app/ducks/app/app.js index 6fe2a3a9a..029c755cd 100644 --- a/ui/app/ducks/app/app.js +++ b/ui/app/ducks/app/app.js @@ -73,7 +73,6 @@ function reduceApp (state, action) { networksTabSelectedRpcUrl: '', networksTabIsInAddMode: false, loadingMethodData: false, - showingSeedPhraseBackupAfterOnboarding: false, }, state.appState) switch (action.type) { @@ -757,17 +756,6 @@ function reduceApp (state, action) { loadingMethodData: false, }) - case actions.SHOW_SEED_PHRASE_BACKUP_AFTER_ONBOARDING: - return extend(appState, { - showingSeedPhraseBackupAfterOnboarding: true, - }) - - case actions.HIDE_SEED_PHRASE_BACKUP_AFTER_ONBOARDING: - return extend(appState, { - showingSeedPhraseBackupAfterOnboarding: false, - }) - - default: return appState } diff --git a/ui/app/helpers/constants/routes.js b/ui/app/helpers/constants/routes.js index adcd3f14d..cd26b3628 100644 --- a/ui/app/helpers/constants/routes.js +++ b/ui/app/helpers/constants/routes.js @@ -32,6 +32,7 @@ const INITIALIZE_CREATE_PASSWORD_ROUTE = '/initialize/create-password' const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = '/initialize/create-password/import-with-seed-phrase' const INITIALIZE_SELECT_ACTION_ROUTE = '/initialize/select-action' const INITIALIZE_SEED_PHRASE_ROUTE = '/initialize/seed-phrase' +const INITIALIZE_BACKUP_SEED_PHRASE_ROUTE = '/initialize/backup-seed-phrase' const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow' const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm' const INITIALIZE_METAMETRICS_OPT_IN_ROUTE = '/initialize/metametrics-opt-in' @@ -90,4 +91,6 @@ module.exports = { CONTACT_MY_ACCOUNTS_VIEW_ROUTE, CONTACT_MY_ACCOUNTS_EDIT_ROUTE, NETWORKS_ROUTE, + INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, } + diff --git a/ui/app/pages/first-time-flow/first-time-flow.component.js b/ui/app/pages/first-time-flow/first-time-flow.component.js index df9631e15..91415d2ee 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.component.js +++ b/ui/app/pages/first-time-flow/first-time-flow.component.js @@ -18,6 +18,7 @@ import { INITIALIZE_SELECT_ACTION_ROUTE, INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_METAMETRICS_OPT_IN_ROUTE, + INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, } from '../../helpers/constants/routes' export default class FirstTimeFlow extends PureComponent { @@ -113,6 +114,16 @@ export default class FirstTimeFlow extends PureComponent { /> )} /> + ( + + )} + /> ( diff --git a/ui/app/pages/first-time-flow/first-time-flow.container.js b/ui/app/pages/first-time-flow/first-time-flow.container.js index 76fd12bcd..ec9920d74 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.container.js +++ b/ui/app/pages/first-time-flow/first-time-flow.container.js @@ -7,9 +7,13 @@ import { unlockAndGetSeedPhrase, verifySeedPhrase, } from '../../store/actions' +import { + INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, +} from '../../helpers/constants/routes' -const mapStateToProps = state => { - const { metamask: { completedOnboarding, isInitialized, isUnlocked, seedPhraseBackedUp }, appState: { showingSeedPhraseBackupAfterOnboarding } } = state +const mapStateToProps = (state, ownProps) => { + const { metamask: { completedOnboarding, isInitialized, isUnlocked, seedPhraseBackedUp } } = state + const showingSeedPhraseBackupAfterOnboarding = Boolean(ownProps.location.pathname.match(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE)) return { completedOnboarding, diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js index 79cb27c52..ae38757d9 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -6,6 +6,7 @@ import ConfirmSeedPhrase from './confirm-seed-phrase' import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, + INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes' import HTML5Backend from 'react-dnd-html5-backend' @@ -68,6 +69,16 @@ export default class SeedPhrase extends PureComponent { /> )} /> + ( + + )} + />
diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index dca4c8540..66d962ff1 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -12,7 +12,7 @@ import { RESTORE_VAULT_ROUTE, CONFIRM_TRANSACTION_ROUTE, CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE, - INITIALIZE_SEED_PHRASE_ROUTE, + INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, } from '../../helpers/constants/routes' export default class Home extends PureComponent { @@ -43,8 +43,8 @@ export default class Home extends PureComponent { viewingUnconnectedDapp: PropTypes.bool.isRequired, forceApproveProviderRequestByOrigin: PropTypes.func, shouldShowSeedPhraseReminder: PropTypes.bool, - showSeedPhraseBackupAfterOnboarding: PropTypes.bool, rejectProviderRequestByOrigin: PropTypes.func, + isPopup: PropTypes.bool, } componentWillMount () { @@ -82,8 +82,8 @@ export default class Home extends PureComponent { viewingUnconnectedDapp, forceApproveProviderRequestByOrigin, shouldShowSeedPhraseReminder, - showSeedPhraseBackupAfterOnboarding, rejectProviderRequestByOrigin, + isPopup, } = this.props if (forgottenPassword) { @@ -140,8 +140,11 @@ export default class Home extends PureComponent { descriptionText={t('backupApprovalNotice')} acceptText={t('backupNow')} onAccept={() => { - showSeedPhraseBackupAfterOnboarding() - history.push(INITIALIZE_SEED_PHRASE_ROUTE) + if (isPopup) { + global.platform.openExtensionInBrowser(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) + } else { + history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE) + } }} infoText={t('backupApprovalInfo')} key="home-backupApprovalNotice" diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index 434d4b7e3..f03ffdc02 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -7,7 +7,6 @@ import { getCurrentEthBalance } from '../../selectors/selectors' import { forceApproveProviderRequestByOrigin, unsetMigratedPrivacyMode, - showSeedPhraseBackupAfterOnboarding, rejectProviderRequestByOrigin, } from '../../store/actions' import { getEnvironmentType } from '../../../../app/scripts/lib/util' @@ -60,7 +59,6 @@ const mapDispatchToProps = (dispatch) => ({ unsetMigratedPrivacyMode: () => dispatch(unsetMigratedPrivacyMode()), forceApproveProviderRequestByOrigin: (origin) => dispatch(forceApproveProviderRequestByOrigin(origin)), rejectProviderRequestByOrigin: origin => dispatch(rejectProviderRequestByOrigin(origin)), - showSeedPhraseBackupAfterOnboarding: () => dispatch(showSeedPhraseBackupAfterOnboarding()), }) export default compose( diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 9d8c7c6b2..adb5fe450 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -377,11 +377,6 @@ var actions = { LOADING_TOKEN_PARAMS_FINISHED: 'LOADING_TOKEN_PARAMS_FINISHED', setSeedPhraseBackedUp, - showSeedPhraseBackupAfterOnboarding, - SHOW_SEED_PHRASE_BACKUP_AFTER_ONBOARDING: 'SHOW_SEED_PHRASE_BACKUP_AFTER_ONBOARDING', - hideSeedPhraseBackupAfterOnboarding, - HIDE_SEED_PHRASE_BACKUP_AFTER_ONBOARDING: 'HIDE_SEED_PHRASE_BACKUP_AFTER_ONBOARDING', - verifySeedPhrase, SET_SEED_PHRASE_BACKED_UP_TO_TRUE: 'SET_SEED_PHRASE_BACKED_UP_TO_TRUE', } @@ -2796,15 +2791,3 @@ function setSeedPhraseBackedUp (seedPhraseBackupState) { }) } } - -function showSeedPhraseBackupAfterOnboarding () { - return { - type: actions.SHOW_SEED_PHRASE_BACKUP_AFTER_ONBOARDING, - } -} - -function hideSeedPhraseBackupAfterOnboarding () { - return { - type: actions.HIDE_SEED_PHRASE_BACKUP_AFTER_ONBOARDING, - } -} From 3136dd39eaed13a32bd4aa54415842e75bb8a2bd Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 6 Aug 2019 00:54:36 -0230 Subject: [PATCH 7/7] Only show notification expand icon when there are > 1 notifications that 'shouldBeRendered' (#6965) --- .../multiple-notifications.component.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js index 95dbb5c9a..09020c467 100644 --- a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js +++ b/ui/app/components/app/multiple-notifications/multiple-notifications.component.js @@ -16,21 +16,20 @@ export default class MultipleNotifications extends PureComponent { const { showAll } = this.state const { notifications, classNames = [] } = this.props + const notificationsToBeRendered = notifications.filter(notificationConfig => notificationConfig.shouldBeRendered) + return (
- {notifications - .filter(notificationConfig => notificationConfig.shouldBeRendered) - .map(notificationConfig => notificationConfig.component) - } + { notificationsToBeRendered.map(notificationConfig => notificationConfig.component) }
this.setState({ showAll: !showAll })} > - {notifications.length > 1 ? 1 ? : null}