From 390cf09b3f1a91dd516327a6f561b10b6939c01e Mon Sep 17 00:00:00 2001 From: MetaMask Bot Date: Tue, 21 Jun 2022 19:26:15 +0000 Subject: [PATCH 1/8] Version v10.15.1 --- CHANGELOG.md | 5 ++++- package.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0be99f03b..9c4f30e4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.15.1] + ## [10.15.0] ### Added - Add warning when multiple instances of MetaMask are running ([#13836](https://github.com/MetaMask/metamask-extension/pull/13836)) @@ -2964,7 +2966,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Uncategorized - Added the ability to restore accounts from seed words. -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.15.0...HEAD +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.15.1...HEAD +[10.15.1]: https://github.com/MetaMask/metamask-extension/compare/v10.15.0...v10.15.1 [10.15.0]: https://github.com/MetaMask/metamask-extension/compare/v10.14.7...v10.15.0 [10.14.7]: https://github.com/MetaMask/metamask-extension/compare/v10.14.6...v10.14.7 [10.14.6]: https://github.com/MetaMask/metamask-extension/compare/v10.14.5...v10.14.6 diff --git a/package.json b/package.json index 2ec90366c..044cd3a60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-crx", - "version": "10.15.0", + "version": "10.15.1", "private": true, "repository": { "type": "git", From 254e600d079cb52a1565a68d000b16d1682b45e3 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 21 Jun 2022 16:33:54 -0230 Subject: [PATCH 2/8] Destroy ledger keyring when removing last account in ledger keyring (#14993) * Destroy ledger keyring when removing last account in ledger keyring * Update unit tests --- app/scripts/metamask-controller.js | 6 ++++++ app/scripts/metamask-controller.test.js | 21 +++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 377811833..580ed7f30 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -2587,8 +2587,14 @@ export default class MetamaskController extends EventEmitter { // Remove account from the account tracker controller this.accountTracker.removeAccount([address]); + const keyring = await this.keyringController.getKeyringForAccount(address); // Remove account from the keyring await this.keyringController.removeAccount(address); + const updatedKeyringAccounts = keyring ? await keyring.getAccounts() : {}; + if (updatedKeyringAccounts?.length === 0) { + keyring.destroy?.(); + } + return address; } diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 6baf1b113..8c9ecc489 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -769,12 +769,20 @@ describe('MetaMaskController', function () { describe('#removeAccount', function () { let ret; const addressToRemove = '0x1'; + let mockKeyring; beforeEach(async function () { + mockKeyring = { + getAccounts: sinon.stub().returns(Promise.resolve([])), + destroy: sinon.stub(), + }; sinon.stub(metamaskController.preferencesController, 'removeAddress'); sinon.stub(metamaskController.accountTracker, 'removeAccount'); sinon.stub(metamaskController.keyringController, 'removeAccount'); sinon.stub(metamaskController, 'removeAllAccountPermissions'); + sinon + .stub(metamaskController.keyringController, 'getKeyringForAccount') + .returns(Promise.resolve(mockKeyring)); ret = await metamaskController.removeAccount(addressToRemove); }); @@ -784,6 +792,9 @@ describe('MetaMaskController', function () { metamaskController.accountTracker.removeAccount.restore(); metamaskController.preferencesController.removeAddress.restore(); metamaskController.removeAllAccountPermissions.restore(); + + mockKeyring.getAccounts.resetHistory(); + mockKeyring.destroy.resetHistory(); }); it('should call preferencesController.removeAddress', async function () { @@ -817,6 +828,16 @@ describe('MetaMaskController', function () { it('should return address', async function () { assert.equal(ret, '0x1'); }); + it('should call keyringController.getKeyringForAccount', async function () { + assert( + metamaskController.keyringController.getKeyringForAccount.calledWith( + addressToRemove, + ), + ); + }); + it('should call keyring.destroy', async function () { + assert(mockKeyring.destroy.calledOnce); + }); }); describe('#newUnsignedMessage', function () { From 479298fc89c33f34b159255f1d5094766cc454d5 Mon Sep 17 00:00:00 2001 From: Ariella Vu <20778143+digiwand@users.noreply.github.com> Date: Wed, 15 Jun 2022 14:52:32 -0500 Subject: [PATCH 3/8] MetaMetrics: Fixes TypeError: Object.values(...).reduce(...).flat is not a function (#14962) * metametrics: flat is not a function * MetaMetrics: shorten array logic --- app/scripts/controllers/metametrics.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 856461a57..b43efe631 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -620,11 +620,9 @@ export default class MetaMetricsController { * @returns {[]} */ _getAllNFTsFlattened = memoize((allCollectibles = {}) => { - return Object.values(allCollectibles) - .reduce((result, chainNFTs) => { - return result.concat(Object.values(chainNFTs)); - }, []) - .flat(); + return Object.values(allCollectibles).reduce((result, chainNFTs) => { + return result.concat(...Object.values(chainNFTs)); + }, []); }); /** From 506a9872f0f96aef18ff9c3598ad341fbf20ae76 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 15 Jun 2022 15:50:37 +0200 Subject: [PATCH 4/8] Update E2E tests for new test-dapp version (#14939) * Update xDAI E2E information * Use local Ganache instance instead of Gnosis Chain * Bump test-dapp * Bump test-dapp * Enable secondary Ganache server for other test * Fix linting * Improve E2E stability * Update network selector --- package.json | 2 +- test/e2e/tests/chain-interactions.spec.js | 56 +++++++++++------------ test/e2e/tests/dapp-interactions.spec.js | 6 ++- test/e2e/tests/provider-api.spec.js | 4 +- yarn.lock | 8 ++-- 5 files changed, 38 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index 044cd3a60..a8aecef00 100644 --- a/package.json +++ b/package.json @@ -252,7 +252,7 @@ "@metamask/eslint-config-typescript": "^9.0.1", "@metamask/forwarder": "^1.1.0", "@metamask/phishing-warning": "^1.1.0", - "@metamask/test-dapp": "^5.0.0", + "@metamask/test-dapp": "^5.1.1", "@sentry/cli": "^1.58.0", "@storybook/addon-a11y": "^6.3.12", "@storybook/addon-actions": "^6.3.12", diff --git a/test/e2e/tests/chain-interactions.spec.js b/test/e2e/tests/chain-interactions.spec.js index c1879ccef..3b7d57408 100644 --- a/test/e2e/tests/chain-interactions.spec.js +++ b/test/e2e/tests/chain-interactions.spec.js @@ -2,16 +2,19 @@ const { strict: assert } = require('assert'); const { convertToHexValue, withFixtures } = require('../helpers'); describe('Chain Interactions', function () { - it('should add the XDAI chain and not switch the network', async function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; + const port = 8546; + const chainId = 1338; + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: convertToHexValue(25000000000000000000), + }, + ], + concurrent: { port, chainId }, + }; + it('should add the Ganache test chain and not switch the network', async function () { await withFixtures( { dapp: true, @@ -36,12 +39,14 @@ describe('Chain Interactions', function () { ); // verify chain details - const [networkName, networkUrl, chainId] = await driver.findElements( - '.definition-list dd', - ); - assert.equal(await networkName.getText(), 'xDAI Chain'); - assert.equal(await networkUrl.getText(), 'https://dai.poa.network'); - assert.equal(await chainId.getText(), '100'); + const [ + networkName, + networkUrl, + chainIdElement, + ] = await driver.findElements('.definition-list dd'); + assert.equal(await networkName.getText(), `Localhost ${port}`); + assert.equal(await networkUrl.getText(), `http://127.0.0.1:${port}`); + assert.equal(await chainIdElement.getText(), chainId.toString()); // approve add chain, cancel switch chain await driver.clickElement({ text: 'Approve', tag: 'button' }); @@ -55,25 +60,16 @@ describe('Chain Interactions', function () { const networkDisplay = await driver.findElement('.network-display'); await networkDisplay.click(); assert.equal(await networkDisplay.getText(), 'Localhost 8545'); - const xDaiChain = await driver.findElements({ - text: 'xDAI Chain', + const ganacheChain = await driver.findElements({ + text: `Localhost ${port}`, tag: 'span', }); - assert.ok(xDaiChain.length, 1); + assert.ok(ganacheChain.length, 1); }, ); }); - it('should add the XDAI chain and switch the network', async function () { - const ganacheOptions = { - accounts: [ - { - secretKey: - '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', - balance: convertToHexValue(25000000000000000000), - }, - ], - }; + it('should add the Ganache chain and switch the network', async function () { await withFixtures( { dapp: true, @@ -107,7 +103,7 @@ describe('Chain Interactions', function () { // verify current network const networkDisplay = await driver.findElement('.network-display'); - assert.equal(await networkDisplay.getText(), 'xDAI Chain'); + assert.equal(await networkDisplay.getText(), `Localhost ${port}`); }, ); }); diff --git a/test/e2e/tests/dapp-interactions.spec.js b/test/e2e/tests/dapp-interactions.spec.js index af9f0af89..5f5c72e3d 100644 --- a/test/e2e/tests/dapp-interactions.spec.js +++ b/test/e2e/tests/dapp-interactions.spec.js @@ -23,7 +23,10 @@ describe('Dapp interactions', function () { { dapp: true, fixtures: 'imported-account', - ganacheOptions, + ganacheOptions: { + ...ganacheOptions, + concurrent: { port: 8546, chainId: 1338 }, + }, title: this.test.title, }, async ({ driver }) => { @@ -44,6 +47,7 @@ describe('Dapp interactions', function () { // Trigger Notification await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles); await driver.clickElement('#addEthereumChain'); + await driver.waitUntilXWindowHandles(3); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, diff --git a/test/e2e/tests/provider-api.spec.js b/test/e2e/tests/provider-api.spec.js index 14a4ff0eb..b85b4fb32 100644 --- a/test/e2e/tests/provider-api.spec.js +++ b/test/e2e/tests/provider-api.spec.js @@ -47,7 +47,7 @@ describe('MetaMask', function () { await driver.switchToWindowWithTitle('E2E Test Dapp', windowHandles); const switchedNetworkDiv = await driver.waitForSelector({ css: '#network', - text: '1', + text: '0x1', }); const switchedChainIdDiv = await driver.waitForSelector({ css: '#chainId', @@ -55,7 +55,7 @@ describe('MetaMask', function () { }); const accountsDiv = await driver.findElement('#accounts'); - assert.equal(await switchedNetworkDiv.getText(), '1'); + assert.equal(await switchedNetworkDiv.getText(), '0x1'); assert.equal(await switchedChainIdDiv.getText(), '0x1'); assert.equal( await accountsDiv.getText(), diff --git a/yarn.lock b/yarn.lock index 419ccf657..f94777dca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3080,10 +3080,10 @@ dependencies: "@metamask/controllers" "^28.0.0" -"@metamask/test-dapp@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-5.0.0.tgz#ecea832b57ff97782bfdd57a4af3408c7c64c02d" - integrity sha512-eR9JQ0jPOeP/hdQj9hUkqbvinfjVLYTtdHV+mDCN1tsNxiTdninZbltg9bx6Gqp91v9/9YPhlhXCmMQPq/AMxQ== +"@metamask/test-dapp@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@metamask/test-dapp/-/test-dapp-5.1.1.tgz#aadebf28542809650c57aa8f5a3489c748e1414f" + integrity sha512-Vast76cYR9vOvSH9Ut8y8LXZbDledUE2BkiLX+PGP5AOTp8Pn8V6jiYg1D/slBh7M8/Q/1AmdW9D0B+fw7esBQ== "@metamask/types@^1.1.0": version "1.1.0" From 850c68ebb00c49371dccda15c09f535bdc97483e Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Tue, 21 Jun 2022 17:20:40 -0230 Subject: [PATCH 5/8] Update changelog for v10.15.1 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c4f30e4b..08d466ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [10.15.1] +### Fixed +- Fix Ledger connection failures that can occur after remove all hardware wallet accounts and reconnecting ([#14993](https://github.com/MetaMask/metamask-extension/pull/14993)) +- Fix bug that could cause MetaMask to crash in some cases when interacting with tokens or NFTs ([#14962](https://github.com/MetaMask/metamask-extension/pull/14962)) ## [10.15.0] ### Added From 1fd4dfbde420586926d4caf0d529a7a168a4a5b4 Mon Sep 17 00:00:00 2001 From: Micaiah Reid Date: Fri, 10 Jun 2022 10:53:36 -0400 Subject: [PATCH 6/8] Allow locally hosted RPC and Block Explorer Urls with `wallet_addEthereumChain` (#14272) * add function to check if url is localhost * allow localhost rpcUrls in `wallet_addEthereumChain` * allow localhost blockExplorerUrls * wrap new URL in try/catch --- .../handlers/add-ethereum-chain.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js index 519b130bb..db3f4ac1f 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js @@ -77,14 +77,27 @@ async function addEthereumChainHandler( ); } + const isLocalhost = (strUrl) => { + try { + const url = new URL(strUrl); + return url.hostname === 'localhost' || url.hostname === '127.0.0.1'; + } catch (error) { + return false; + } + }; + const firstValidRPCUrl = Array.isArray(rpcUrls) - ? rpcUrls.find((rpcUrl) => validUrl.isHttpsUri(rpcUrl)) + ? rpcUrls.find( + (rpcUrl) => isLocalhost(rpcUrl) || validUrl.isHttpsUri(rpcUrl), + ) : null; const firstValidBlockExplorerUrl = blockExplorerUrls !== null && Array.isArray(blockExplorerUrls) - ? blockExplorerUrls.find((blockExplorerUrl) => - validUrl.isHttpsUri(blockExplorerUrl), + ? blockExplorerUrls.find( + (blockExplorerUrl) => + isLocalhost(blockExplorerUrl) || + validUrl.isHttpsUri(blockExplorerUrl), ) : null; From ba961819f847947e20ac7087d57a82610d2439ff Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 22 Jun 2022 14:24:44 +0200 Subject: [PATCH 7/8] Backport snaps e2e fix (#15008) * Backport snaps e2e fix * Fix selector --- test/e2e/snaps/test-snap-confirm.spec.js | 6 +++--- test/e2e/snaps/test-snap-error.spec.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/snaps/test-snap-confirm.spec.js b/test/e2e/snaps/test-snap-confirm.spec.js index 2100c2ff5..95726b9f6 100644 --- a/test/e2e/snaps/test-snap-confirm.spec.js +++ b/test/e2e/snaps/test-snap-confirm.spec.js @@ -29,8 +29,8 @@ describe('Test Snap Confirm', function () { await driver.press('#password', driver.Key.ENTER); // navigate to test snaps page and connect - await driver.driver.get('https://metamask.github.io/test-snaps/'); - await driver.fill('.snapId', 'npm:@metamask/test-snap-confirm'); + await driver.driver.get('https://metamask.github.io/test-snaps/0.1.3'); + await driver.fill('.snapId1', 'npm:@metamask/test-snap-confirm'); await driver.clickElement({ text: 'Connect To Confirm Snap', tag: 'button', @@ -90,7 +90,7 @@ describe('Test Snap Confirm', function () { await driver.waitUntilXWindowHandles(1, 5000, 10000); windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle('Test Snaps', windowHandles); - const confirmResult = await driver.findElement('.sendResults'); + const confirmResult = await driver.findElement('.confirmResult'); assert.equal(await confirmResult.getText(), 'true'); }, ); diff --git a/test/e2e/snaps/test-snap-error.spec.js b/test/e2e/snaps/test-snap-error.spec.js index 91ebd2ce1..1dac04ac5 100644 --- a/test/e2e/snaps/test-snap-error.spec.js +++ b/test/e2e/snaps/test-snap-error.spec.js @@ -28,7 +28,7 @@ describe('Test Snap Error', function () { await driver.press('#password', driver.Key.ENTER); // navigate to test snaps page and connect - await driver.driver.get('https://metamask.github.io/test-snaps/'); + await driver.driver.get('https://metamask.github.io/test-snaps/0.1.3'); await driver.fill('.snapId2', 'npm:@metamask/test-snap-error'); await driver.clickElement({ text: 'Connect Error Snap', From 324ac0cd78df665410094c23d479ccbbf673c289 Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Wed, 22 Jun 2022 11:46:58 -0230 Subject: [PATCH 8/8] Add exclusion for GHSA-pfrx-2q88-qq97, which is in the 3box dependency tree but not our build (#15005) --- .iyarc | 1 + 1 file changed, 1 insertion(+) diff --git a/.iyarc b/.iyarc index 66e5dd446..bbd5d06c1 100644 --- a/.iyarc +++ b/.iyarc @@ -2,3 +2,4 @@ GHSA-93q8-gq69-wqmw GHSA-257v-vj4p-3w2h GHSA-wm7h-9275-46v2 +GHSA-pfrx-2q88-qq97