Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/jl/caip-multichain-migrate-core'…
Browse files Browse the repository at this point in the history
… into jl/caip-multichain-migrate-core
  • Loading branch information
jiexi committed Jan 17, 2025
2 parents c1b4b29 + 1bf080d commit 540899a
Show file tree
Hide file tree
Showing 12 changed files with 235 additions and 174 deletions.
12 changes: 2 additions & 10 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2489,10 +2489,8 @@ export default class MetamaskController extends EventEmitter {
const selectedAddress =
this.accountsController.getSelectedAccount().address;
return selectedAddress ? [selectedAddress] : [];
} else if (this.isUnlocked()) {
return this.getPermittedAccounts(innerOrigin);
}
return []; // changing this is a breaking change
return this.getPermittedAccounts(innerOrigin);
},
// tx signing
processTransaction: (transactionParams, dappRequest) =>
Expand Down Expand Up @@ -5437,12 +5435,10 @@ export default class MetamaskController extends EventEmitter {
* return permissioned accounts to the dapp when the wallet is locked.
*
* @param {string} origin - The origin whose exposed accounts to retrieve.
* @param {object} [options] - The options object
* @param {boolean} [options.ignoreLock] - If accounts should be returned even if the wallet is locked.
* @returns {Promise<string[]>} The origin's permitted accounts, or an empty
* array.
*/
getPermittedAccounts(origin, { ignoreLock } = {}) {
getPermittedAccounts(origin) {
let caveat;
try {
caveat = this.permissionController.getCaveat(
Expand All @@ -5463,10 +5459,6 @@ export default class MetamaskController extends EventEmitter {
return [];
}

if (!this.isUnlocked() && !ignoreLock) {
return [];
}

const ethAccounts = getEthAccounts(caveat.value);
return this.sortAccountsByLastSelected(ethAccounts);
}
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/fixture-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ class FixtureBuilder {
});
}

withPermissionControllerConnectedToTestDappMultichain({
withPermissionControllerConnectedToMultichainTestDapp({
account = '',
useLocalhostHostname = false,
} = {}) {
Expand Down Expand Up @@ -573,7 +573,7 @@ class FixtureBuilder {
});
}

withPermissionControllerConnectedToTestDappMultichainWithTwoAccounts({
withPermissionControllerConnectedToMultichainTestDappWithTwoAccounts({
scopes = ['eip155:1337'],
}) {
const optionalScopes = scopes
Expand Down
10 changes: 2 additions & 8 deletions test/e2e/flask/multichain-api/connect.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import {
WINDOW_TITLES,
withFixtures,
} from '../../helpers';
import { Driver } from '../../webdriver/driver';

import FixtureBuilder from '../../fixture-builder';
import type { FixtureCallbackArgs } from './testHelpers';

describe('Multichain API', function () {
it('should connect the wallet to the multichain test dapp via `externally_connectable` and successfully create a session with the requested chains', async function () {
Expand All @@ -30,13 +30,7 @@ describe('Multichain API', function () {
fixtures: new FixtureBuilder().withPopularNetworks().build(),
title: this.test?.fullTitle(),
},
async ({
driver,
extensionId,
}: {
driver: Driver;
extensionId: string;
}) => {
async ({ driver, extensionId }: FixtureCallbackArgs) => {
await unlockWallet(driver);

await openDapp(driver, undefined, DAPP_URL);
Expand Down
189 changes: 189 additions & 0 deletions test/e2e/flask/multichain-api/password-locked.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { strict as assert } from 'assert';
import {
ACCOUNT_1,
WALLET_PASSWORD,
WINDOW_TITLES,
withFixtures,
} from '../../helpers';
import { Driver } from '../../webdriver/driver';
import FixtureBuilder from '../../fixture-builder';
import {
DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
escapeColon,
type FixtureCallbackArgs,
getExpectedSessionScope,
getSessionScopes,
openMultichainDappAndConnectWalletWithExternallyConnectable,
passwordLockMetamaskExtension,
} from './testHelpers';

describe("A dapp is connected with account and chain permissions previously granted via `wallet_createSession`, user's extension becomes password locked", function () {
describe('the dapp sends a request through the Multichain API that requires user confirmation on the permitted account', function () {
it('should prompts the user to unlock MetaMask before showing the request confirmation', async function () {
await withFixtures(
{
title: this.test?.fullTitle(),
fixtures: new FixtureBuilder()
.withNetworkControllerTripleGanache()
.withPermissionControllerConnectedToMultichainTestDapp()
.build(),
...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
},
async ({ driver, extensionId }: FixtureCallbackArgs) => {
await openMultichainDappAndConnectWalletWithExternallyConnectable(
driver,
extensionId,
);
await passwordLockMetamaskExtension(driver);
await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

await driver.clickElementSafe(
'[data-testid="eip155:1337-eth_sendTransaction-option"]',
);
await driver.clickElement(
'[data-testid="invoke-method-eip155:1337-btn"]',
);

await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

const unlockExtensionPageWebElement0 = await driver.findElement(
'[data-testid="unlock-page"]',
);

assert.ok(
unlockExtensionPageWebElement0,
'Should prompt user to unlock Metamask Extension',
);

/**
* We unlock metamask extension to assert a transfer request is being made
*/
await driver.fill('[data-testid="unlock-password"]', WALLET_PASSWORD);
await driver.clickElementSafe('[data-testid="unlock-submit"]');

const transferRequestWebElement = await driver.findElement({
text: 'Transfer request',
type: 'h3',
});

assert.ok(
transferRequestWebElement,
'Should be attempting to make via wallet extension transfer',
);

await driver.clickElementSafe(
'[data-testid="confirm-footer-cancel-button"]',
);

/**
* We lock extension again to repeat action and assertion for `wallet_addEthereumChain`
*/
await passwordLockMetamaskExtension(driver);

await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

await driver.clickElementSafe(
'[data-testid="wallet:eip155-wallet_addEthereumChain-option"]',
);
await driver.clickElement(
'[data-testid="invoke-method-wallet:eip155-btn"]',
);

await driver.switchToWindowWithTitle(WINDOW_TITLES.Dialog);

const unlockExtensionPageWebElement1 = await driver.findElement(
'[data-testid="unlock-page"]',
);

assert.ok(
unlockExtensionPageWebElement1,
'Should prompt user to unlock Metamask Extension',
);

/**
* We unlock metamask extension to assert a request for adding chain is being made
*/
await driver.fill('[data-testid="unlock-password"]', WALLET_PASSWORD);
await driver.clickElementSafe('[data-testid="unlock-submit"]');

const addChainWebElement = await driver.findElement({
text: 'Add Gnosis',
type: 'h3',
});

assert.ok(
addChainWebElement,
'Should be attempting to add Gnosis Chain',
);
},
);
});
});

describe('the dapp sends requests through the Multichain API that do NOT require user confirmation', function () {
const SCOPE = 'eip155:1337';
const CHAIN_ID = '0x539';
it('should handle the requests without prompting the user to unlock the wallet', async function () {
await withFixtures(
{
title: this.test?.fullTitle(),
fixtures: new FixtureBuilder()
.withNetworkControllerTripleGanache()
.withPermissionControllerConnectedToMultichainTestDapp()
.build(),
...DEFAULT_MULTICHAIN_TEST_DAPP_FIXTURE_OPTIONS,
},
async ({
driver,
extensionId,
}: {
driver: Driver;
extensionId: string;
}) => {
await openMultichainDappAndConnectWalletWithExternallyConnectable(
driver,
extensionId,
);
await passwordLockMetamaskExtension(driver);

await driver.switchToWindowWithTitle(
WINDOW_TITLES.MultichainTestDApp,
);

const parsedResult = await getSessionScopes(driver);
const sessionScope = parsedResult.sessionScopes[SCOPE];
const expectedSessionScope = getExpectedSessionScope(SCOPE, [
ACCOUNT_1,
]);

await driver.clickElementSafe(
`[data-testid="${SCOPE}-eth_chainId-option"]`,
);
await driver.clickElementSafe(
`[data-testid="invoke-method-${SCOPE}-btn"]`,
);
const chainIdResultWebElement = await driver.findElement(
`#invoke-method-${escapeColon(SCOPE)}-eth_chainId-result-0`,
);
const chainId = await chainIdResultWebElement.getText();

assert.deepStrictEqual(
sessionScope,
expectedSessionScope,
`Should receive result that specifies expected session scopes for ${SCOPE}`,
);

assert.deepStrictEqual(
chainId,
`"${CHAIN_ID}"`,
'Should get expected result from calling eth_chainId',
);
},
);
});
});
});
15 changes: 15 additions & 0 deletions test/e2e/flask/multichain-api/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
} from '../../helpers';
import { Driver } from '../../webdriver/driver';

export type FixtureCallbackArgs = { driver: Driver; extensionId: string };

/**
* Default options for setting up Multichain E2E test environment
*/
Expand Down Expand Up @@ -197,6 +199,19 @@ export const updateNetworkCheckboxes = async (
await driver.clickElement({ text: 'Update', tag: 'button' });
};

/**
* Password locks user's metamask extension.
*
* @param driver - E2E test driver {@link Driver}, wrapping the Selenium WebDriver.
*/
export const passwordLockMetamaskExtension = async (
driver: Driver,
): Promise<void> => {
await driver.switchToWindowWithTitle(WINDOW_TITLES.ExtensionInFullScreenView);
await driver.clickElementSafe('[data-testid="account-options-menu-button"]');
await driver.clickElementSafe('[data-testid="global-menu-lock"]');
};

/**
* Sometimes we need to escape colon character when using {@link Driver.findElement}, otherwise selenium will treat this as an invalid selector.
*
Expand Down
Loading

0 comments on commit 540899a

Please sign in to comment.