diff --git a/app/scripts/controllers/permissions/background-api.js b/app/scripts/controllers/permissions/background-api.js index b181eb54ce70..2cc89705f41c 100644 --- a/app/scripts/controllers/permissions/background-api.js +++ b/app/scripts/controllers/permissions/background-api.js @@ -12,16 +12,12 @@ import { getPermittedEthChainIds, setPermittedEthChainIds, } from '../../lib/multichain-api/adapters/caip-permission-adapter-permittedChains'; -import { - CaveatTypes, - RestrictedMethods, -} from '../../../../shared/constants/permissions'; +import { RestrictedMethods } from '../../../../shared/constants/permissions'; import { PermissionNames } from './specifications'; export function getPermissionBackgroundApiMethods({ permissionController, approvalController, - networkController, }) { // To add more than one account when already connected to the dapp const addMoreAccounts = (origin, accounts) => { @@ -75,17 +71,23 @@ export function getPermissionBackgroundApiMethods({ throw new Error('tried to add chains when none have been permissioned'); // TODO: better error } + // get the list of permitted eth accounts before we modify the permitted chains and potentially lose some + const ethAccounts = getEthAccounts(caip25Caveat.value); + const ethChainIds = getPermittedEthChainIds(caip25Caveat.value); const updatedEthChainIds = Array.from( new Set([...ethChainIds, ...chainIds]), ); - const updatedCaveatValue = setPermittedEthChainIds( + let updatedCaveatValue = setPermittedEthChainIds( caip25Caveat.value, updatedEthChainIds, ); + // ensure that the list of permitted eth accounts is intact after permitted chain updates + updatedCaveatValue = setEthAccounts(updatedCaveatValue, ethAccounts); + permissionController.updateCaveat( origin, Caip25EndowmentPermissionName, @@ -95,11 +97,6 @@ export function getPermissionBackgroundApiMethods({ }; const requestAccountsAndChainPermissionsWithId = (origin) => { - const { chainId } = - networkController.getNetworkConfigurationByNetworkClientId( - networkController.state.selectedNetworkClientId, - ); - const id = nanoid(); // NOTE: the eth_accounts/permittedChains approvals will be combined in the future. // Until they are actually combined, when testing, you must request both @@ -115,14 +112,7 @@ export function getPermissionBackgroundApiMethods({ }, permissions: { [RestrictedMethods.eth_accounts]: {}, - [PermissionNames.permittedChains]: { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: [chainId], - }, - ], - }, + [PermissionNames.permittedChains]: {}, }, }, type: MethodNames.requestPermissions, diff --git a/app/scripts/controllers/permissions/background-api.test.js b/app/scripts/controllers/permissions/background-api.test.js index d2abd4df4e46..3deca2135f68 100644 --- a/app/scripts/controllers/permissions/background-api.test.js +++ b/app/scripts/controllers/permissions/background-api.test.js @@ -1,13 +1,14 @@ import { MethodNames } from '@metamask/permission-controller'; -import { - CaveatTypes, - RestrictedMethods, -} from '../../../../shared/constants/permissions'; +import { RestrictedMethods } from '../../../../shared/constants/permissions'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../../lib/multichain-api/caip25permissions'; import { flushPromises } from '../../../../test/lib/timer-helpers'; +import { + KnownNotifications, + KnownRpcMethods, +} from '../../lib/multichain-api/scope'; import { getPermissionBackgroundApiMethods } from './background-api'; import { PermissionNames } from './specifications'; @@ -469,45 +470,7 @@ describe('permission background API methods', () => { }); describe('requestAccountsAndChainPermissionsWithId', () => { - it('gets the networkConfiguration for the current globally selected network client', () => { - const networkController = { - state: { - selectedNetworkClientId: 'mainnet', - }, - getNetworkConfigurationByNetworkClientId: jest.fn().mockReturnValue({ - chainId: '0x1', - }), - }; - const approvalController = { - addAndShowApprovalRequest: jest.fn().mockResolvedValue({ - approvedChainIds: ['0x1', '0x5'], - approvedAccounts: ['0xdeadbeef'], - }), - }; - const permissionController = { - grantPermissions: jest.fn(), - }; - - getPermissionBackgroundApiMethods({ - networkController, - approvalController, - permissionController, - }).requestAccountsAndChainPermissionsWithId('foo.com'); - - expect( - networkController.getNetworkConfigurationByNetworkClientId, - ).toHaveBeenCalledWith('mainnet'); - }); - it('requests eth_accounts and permittedChains approval and returns the request id', async () => { - const networkController = { - state: { - selectedNetworkClientId: 'mainnet', - }, - getNetworkConfigurationByNetworkClientId: jest.fn().mockReturnValue({ - chainId: '0x1', - }), - }; const approvalController = { addAndShowApprovalRequest: jest.fn().mockResolvedValue({ approvedChainIds: ['0x1', '0x5'], @@ -519,7 +482,6 @@ describe('permission background API methods', () => { }; const result = getPermissionBackgroundApiMethods({ - networkController, approvalController, permissionController, }).requestAccountsAndChainPermissionsWithId('foo.com'); @@ -539,14 +501,7 @@ describe('permission background API methods', () => { }, permissions: { [RestrictedMethods.eth_accounts]: {}, - [PermissionNames.permittedChains]: { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: ['0x1'], - }, - ], - }, + [PermissionNames.permittedChains]: {}, }, }, type: MethodNames.requestPermissions, @@ -555,14 +510,6 @@ describe('permission background API methods', () => { }); it('grants a legacy CAIP-25 permission (isMultichainOrigin: false) with the approved eip155 chainIds and accounts', async () => { - const networkController = { - state: { - selectedNetworkClientId: 'mainnet', - }, - getNetworkConfigurationByNetworkClientId: jest.fn().mockReturnValue({ - chainId: '0x1', - }), - }; const approvalController = { addAndShowApprovalRequest: jest.fn().mockResolvedValue({ approvedChainIds: ['0x1', '0x5'], @@ -574,7 +521,6 @@ describe('permission background API methods', () => { }; getPermissionBackgroundApiMethods({ - networkController, approvalController, permissionController, }).requestAccountsAndChainPermissionsWithId('foo.com'); @@ -594,13 +540,13 @@ describe('permission background API methods', () => { requiredScopes: {}, optionalScopes: { 'eip155:1': { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: ['eip155:1:0xdeadbeef'], }, 'eip155:5': { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: ['eip155:5:0xdeadbeef'], }, }, @@ -649,7 +595,7 @@ describe('permission background API methods', () => { ); }); - it('calls updateCaveat with the chain added', () => { + it('calls updateCaveat with the chain added and all eip155 accounts synced', () => { const permissionController = { getCaveat: jest.fn().mockReturnValue({ value: { @@ -661,7 +607,7 @@ describe('permission background API methods', () => { 'eip155:10': { methods: [], notifications: [], - accounts: ['eip155:10:0x1', 'eip155:10:0x2'], + accounts: ['eip155:10:0x2'], }, }, optionalScopes: { @@ -675,7 +621,7 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], - accounts: ['eip155:1:0x2', 'eip155:1:0x3'], + accounts: ['eip155:1:0x1'], }, }, isMultichainOrigin: true, @@ -698,6 +644,7 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], + accounts: ['eip155:1:0x1', 'eip155:1:0x2'], }, 'eip155:10': { methods: [], @@ -716,12 +663,12 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], - accounts: ['eip155:1:0x2', 'eip155:1:0x3'], + accounts: ['eip155:1:0x1', 'eip155:1:0x2'], }, 'eip155:1337': { - methods: [], - notifications: [], - accounts: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, + accounts: ['eip155:1337:0x1', 'eip155:1337:0x2'], }, }, isMultichainOrigin: true, @@ -765,7 +712,7 @@ describe('permission background API methods', () => { ); }); - it('calls updateCaveat with the chains added', () => { + it('calls updateCaveat with the chains added and all eip155 accounts synced', () => { const permissionController = { getCaveat: jest.fn().mockReturnValue({ value: { @@ -777,7 +724,7 @@ describe('permission background API methods', () => { 'eip155:10': { methods: [], notifications: [], - accounts: ['eip155:10:0x1', 'eip155:10:0x2'], + accounts: ['eip155:10:0x2'], }, }, optionalScopes: { @@ -791,7 +738,7 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], - accounts: ['eip155:1:0x2', 'eip155:1:0x3'], + accounts: ['eip155:1:0x1'], }, }, isMultichainOrigin: true, @@ -814,6 +761,7 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], + accounts: ['eip155:1:0x1', 'eip155:1:0x2'], }, 'eip155:10': { methods: [], @@ -832,17 +780,17 @@ describe('permission background API methods', () => { 'eip155:1': { methods: [], notifications: [], - accounts: ['eip155:1:0x2', 'eip155:1:0x3'], + accounts: ['eip155:1:0x1', 'eip155:1:0x2'], }, 'eip155:4': { - methods: [], - notifications: [], - accounts: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, + accounts: ['eip155:4:0x1', 'eip155:4:0x2'], }, 'eip155:5': { - methods: [], - notifications: [], - accounts: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, + accounts: ['eip155:5:0x1', 'eip155:5:0x2'], }, }, isMultichainOrigin: true, diff --git a/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.test.ts b/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.test.ts index 2df27c39d6e2..aa125193ce95 100644 --- a/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.test.ts +++ b/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.test.ts @@ -1,4 +1,5 @@ import { Caip25CaveatValue } from '../caip25permissions'; +import { KnownNotifications, KnownRpcMethods } from '../scope'; import { addPermittedEthChainId, getPermittedEthChainIds, @@ -89,8 +90,8 @@ describe('CAIP-25 permittedChains adapters', () => { accounts: ['eip155:100:0x100'], }, 'eip155:101': { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: [], }, }, @@ -272,8 +273,8 @@ describe('CAIP-25 permittedChains adapters', () => { accounts: ['eip155:100:0x100'], }, 'eip155:101': { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: [], }, }, diff --git a/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.ts b/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.ts index b1a9ab355b94..8e840c6c327e 100644 --- a/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.ts +++ b/app/scripts/lib/multichain-api/adapters/caip-permission-adapter-permittedChains.ts @@ -2,6 +2,8 @@ import { Hex, KnownCaipNamespace } from '@metamask/utils'; import { toHex } from '@metamask/controller-utils'; import { Caip25CaveatValue } from '../caip25permissions'; import { + KnownNotifications, + KnownRpcMethods, mergeScopes, parseScopeString, ScopesObject, @@ -44,8 +46,8 @@ export const addPermittedEthChainId = ( optionalScopes: { ...caip25CaveatValue.optionalScopes, [scopeString]: { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: [], }, }, diff --git a/app/scripts/lib/multichain-api/wallet-createSession/handler.js b/app/scripts/lib/multichain-api/wallet-createSession/handler.js index affc03cecef2..3a0ed777d049 100644 --- a/app/scripts/lib/multichain-api/wallet-createSession/handler.js +++ b/app/scripts/lib/multichain-api/wallet-createSession/handler.js @@ -1,5 +1,5 @@ import { EthereumRpcError } from 'eth-rpc-errors'; -import { RestrictedMethods } from '../../../../../shared/constants/permissions'; +import { CaveatTypes } from '../../../../../shared/constants/permissions'; import { mergeScopes, validateAndFlattenScopes, @@ -16,7 +16,16 @@ import { MetaMetricsEventCategory, MetaMetricsEventName, } from '../../../../../shared/constants/metametrics'; -import { assignAccountsToScopes, validateAndAddEip3085 } from './helpers'; +import { PermissionNames } from '../../../controllers/permissions'; +import { + getEthAccounts, + setEthAccounts, +} from '../adapters/caip-permission-adapter-eth-accounts'; +import { + getPermittedEthChainIds, + setPermittedEthChainIds, +} from '../adapters/caip-permission-adapter-permittedChains'; +import { validateAndAddEip3085 } from './helpers'; export async function walletCreateSessionHandler(req, res, _next, end, hooks) { // TODO: Does this handler need a rate limiter/lock like the one in eth_requestAccounts? @@ -91,38 +100,60 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { unsupportableOptionalScopes, }); - // use old account popup for now to get the accounts + // These should be EVM accounts already although the name does not necessary imply that + // These addresses are lowercased already + const existingEvmAddresses = hooks + .listAccounts() + .map((account) => account.address); + const supportedEthAccounts = getEthAccounts({ + requiredScopes: supportedRequiredScopes, + optionalScopes: supportedOptionalScopes, + }) + .map((address) => address.toLowerCase()) + .filter((address) => existingEvmAddresses.includes(address)); + const supportedEthChainIds = getPermittedEthChainIds({ + requiredScopes: supportedRequiredScopes, + optionalScopes: supportedOptionalScopes, + }); + const legacyApproval = await hooks.requestPermissionApprovalForOrigin({ - [RestrictedMethods.eth_accounts]: {}, + [PermissionNames.eth_accounts]: { + caveats: [ + { + type: CaveatTypes.restrictReturnedAccounts, + value: supportedEthAccounts, + }, + ], + }, + [PermissionNames.permittedChains]: { + caveats: [ + { + type: CaveatTypes.restrictNetworkSwitching, + value: supportedEthChainIds, + }, + ], + }, }); - assignAccountsToScopes( - supportedRequiredScopes, - legacyApproval.approvedAccounts, - ); - assignAccountsToScopes( - supportableRequiredScopes, - legacyApproval.approvedAccounts, - ); - assignAccountsToScopes( - supportedOptionalScopes, - legacyApproval.approvedAccounts, + + let caip25CaveatValue = { + requiredScopes: supportedRequiredScopes, + optionalScopes: supportedOptionalScopes, + isMultichainOrigin: true, + // TODO: preserve sessionProperties? + }; + + caip25CaveatValue = setPermittedEthChainIds( + caip25CaveatValue, + legacyApproval.approvedChainIds, ); - assignAccountsToScopes( - supportableOptionalScopes, + caip25CaveatValue = setEthAccounts( + caip25CaveatValue, legacyApproval.approvedAccounts, ); - const grantedRequiredScopes = mergeScopes( - supportedRequiredScopes, - supportableRequiredScopes, - ); - const grantedOptionalScopes = mergeScopes( - supportedOptionalScopes, - supportableOptionalScopes, - ); const sessionScopes = mergeScopes( - grantedRequiredScopes, - grantedOptionalScopes, + caip25CaveatValue.requiredScopes, + caip25CaveatValue.optionalScopes, ); await Promise.all( @@ -153,11 +184,7 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { caveats: [ { type: Caip25CaveatType, - value: { - requiredScopes: grantedRequiredScopes, - optionalScopes: grantedOptionalScopes, - isMultichainOrigin: true, - }, + value: caip25CaveatValue, }, ], }, diff --git a/app/scripts/lib/multichain-api/wallet-createSession/handler.test.js b/app/scripts/lib/multichain-api/wallet-createSession/handler.test.js index ef615b720f47..8df1e48040e3 100644 --- a/app/scripts/lib/multichain-api/wallet-createSession/handler.test.js +++ b/app/scripts/lib/multichain-api/wallet-createSession/handler.test.js @@ -1,18 +1,21 @@ import { EthereumRpcError } from 'eth-rpc-errors'; -import { RestrictedMethods } from '../../../../../shared/constants/permissions'; +import { CaveatTypes } from '../../../../../shared/constants/permissions'; import { validateAndFlattenScopes, processScopedProperties, bucketScopes, assertScopesSupported, + KnownRpcMethods, + KnownNotifications, } from '../scope'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25permissions'; import { shouldEmitDappViewedEvent } from '../../util'; +import { PermissionNames } from '../../../controllers/permissions'; import { walletCreateSessionHandler } from './handler'; -import { assignAccountsToScopes, validateAndAddEip3085 } from './helpers'; +import { validateAndAddEip3085 } from './helpers'; jest.mock('../../util', () => ({ ...jest.requireActual('../../util'), @@ -20,7 +23,13 @@ jest.mock('../../util', () => ({ })); jest.mock('../scope', () => ({ - ...jest.requireActual('../scope'), + ...jest.requireActual('../scope/assert'), + ...jest.requireActual('../scope/authorization'), + ...jest.requireActual('../scope/filter'), + ...jest.requireActual('../scope/scope'), + ...jest.requireActual('../scope/supported'), + ...jest.requireActual('../scope/transform'), + ...jest.requireActual('../scope/validation'), validateAndFlattenScopes: jest.fn(), processScopedProperties: jest.fn(), bucketScopes: jest.fn(), @@ -29,7 +38,6 @@ jest.mock('../scope', () => ({ jest.mock('./helpers', () => ({ ...jest.requireActual('./helpers'), - assignAccountsToScopes: jest.fn(), validateAndAddEip3085: jest.fn(), })); @@ -61,6 +69,7 @@ const createMockedHandler = () => { const end = jest.fn(); const requestPermissionApprovalForOrigin = jest.fn().mockResolvedValue({ approvedAccounts: ['0x1', '0x2', '0x3', '0x4'], + approvedChainIds: ['0x1', '0x5'], }); const grantPermissions = jest.fn().mockResolvedValue(undefined); const findNetworkClientIdByChainId = jest.fn().mockReturnValue('mainnet'); @@ -89,6 +98,7 @@ const createMockedHandler = () => { '0x3': {}, }, }; + const listAccounts = jest.fn().mockReturnValue([]); const response = {}; const handler = (request) => walletCreateSessionHandler(request, response, next, end, { @@ -101,6 +111,7 @@ const createMockedHandler = () => { multichainSubscriptionManager, metamaskState, sendMetrics, + listAccounts, }); return { @@ -116,6 +127,7 @@ const createMockedHandler = () => { multichainSubscriptionManager, metamaskState, sendMetrics, + listAccounts, handler, }; }; @@ -131,7 +143,6 @@ describe('wallet_createSession', () => { supportableScopes: {}, unsupportableScopes: {}, }); - assignAccountsToScopes.mockImplementation((value) => value); }); afterEach(() => { @@ -190,10 +201,10 @@ describe('wallet_createSession', () => { }, }, flattenedOptionalScopes: { - 'eip155:64': { + 'eip155:100': { methods: ['eth_chainId'], notifications: ['accountsChanged', 'chainChanged'], - accounts: ['eip155:64:0x4'], + accounts: ['eip155:100:0x4'], }, }, }); @@ -216,10 +227,10 @@ describe('wallet_createSession', () => { }, }, { - 'eip155:64': { + 'eip155:100': { methods: ['eth_chainId'], notifications: ['accountsChanged', 'chainChanged'], - accounts: ['eip155:64:0x4'], + accounts: ['eip155:100:0x4'], }, }, { foo: 'bar' }, @@ -279,10 +290,10 @@ describe('wallet_createSession', () => { validateAndFlattenScopes.mockReturnValue({ flattenedRequiredScopes: {}, flattenedOptionalScopes: { - 'eip155:64': { + 'eip155:100': { methods: ['eth_chainId'], notifications: ['accountsChanged', 'chainChanged'], - accounts: ['eip155:64:0x4'], + accounts: ['eip155:100:0x4'], }, }, }); @@ -291,10 +302,10 @@ describe('wallet_createSession', () => { expect(bucketScopes).toHaveBeenNthCalledWith( 2, { - 'eip155:64': { + 'eip155:100': { methods: ['eth_chainId'], notifications: ['accountsChanged', 'chainChanged'], - accounts: ['eip155:64:0x4'], + accounts: ['eip155:100:0x4'], }, }, expect.objectContaining({ @@ -311,144 +322,64 @@ describe('wallet_createSession', () => { expect(isChainIdSupportableBody).toContain('validScopedProperties'); }); - it('requests approval for account permission with no args even if there is accounts in the scope', async () => { - const { handler, requestPermissionApprovalForOrigin } = - createMockedHandler(); - bucketScopes - .mockReturnValueOnce({ - supportedScopes: { - 'eip155:1': { - methods: [], - notifications: [], - accounts: ['eip155:1:0x1', 'eip155:1:0x2'], - }, - }, - supportableScopes: { - 'eip155:5': { - methods: [], - notifications: [], - accounts: ['eip155:5:0x2', 'eip155:5:0x3'], - }, - }, - unsupportableScopes: { - 'eip155:64': { - methods: [], - notifications: [], - accounts: ['eip155:64:0x4'], - }, - }, - }) - .mockReturnValueOnce({ - supportedScopes: { - 'eip155:2': { - methods: [], - notifications: [], - accounts: ['eip155:2:0x1', 'eip155:1:0x2'], - }, - }, - supportableScopes: { - 'eip155:6': { - methods: [], - notifications: [], - accounts: ['eip155:6:0x2', 'eip155:6:0x3'], - }, - }, - unsupportableScopes: { - 'eip155:65': { - methods: [], - notifications: [], - accounts: ['eip155:65:0x4'], - }, - }, - }); + it('gets a list of evm accounts in the wallet', async () => { + const { handler, listAccounts } = createMockedHandler(); await handler(baseRequest); - expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ - [RestrictedMethods.eth_accounts]: {}, - }); + expect(listAccounts).toHaveBeenCalled(); }); - it('assigns the permitted accounts to the scopeObjects', async () => { - const { handler } = createMockedHandler(); + it('requests approval for account and permitted chains permission based on the supported eth accounts and eth chains from the supported scopes in the request', async () => { + const { handler, listAccounts, requestPermissionApprovalForOrigin } = + createMockedHandler(); + listAccounts.mockReturnValue([ + { address: '0x1' }, + { address: '0x3' }, + { address: '0x4' }, + ]); bucketScopes .mockReturnValueOnce({ supportedScopes: { - 'eip155:1': { - methods: [], - notifications: [], - }, - }, - supportableScopes: { - 'eip155:5': { - methods: [], - notifications: [], - }, - }, - unsupportableScopes: { - 'eip155:64': { + 'eip155:1337': { methods: [], notifications: [], + accounts: ['eip155:1:0x1', 'eip155:1:0x2'], }, }, + supportableScopes: {}, + unsupportableScopes: {}, }) .mockReturnValueOnce({ supportedScopes: { - 'eip155:2': { - methods: [], - notifications: [], - }, - }, - supportableScopes: { - 'eip155:6': { - methods: [], - notifications: [], - }, - }, - unsupportableScopes: { - 'eip155:65': { + 'eip155:100': { methods: [], notifications: [], + accounts: ['eip155:2:0x1', 'eip155:2:0x3', 'eip155:2:0xdeadbeef'], }, }, + supportableScopes: {}, + unsupportableScopes: {}, }); await handler(baseRequest); - expect(assignAccountsToScopes).toHaveBeenCalledWith( - { - 'eip155:1': { - methods: [], - notifications: [], - }, - }, - ['0x1', '0x2', '0x3', '0x4'], - ); - expect(assignAccountsToScopes).toHaveBeenCalledWith( - { - 'eip155:5': { - methods: [], - notifications: [], - }, - }, - ['0x1', '0x2', '0x3', '0x4'], - ); - expect(assignAccountsToScopes).toHaveBeenCalledWith( - { - 'eip155:2': { - methods: [], - notifications: [], - }, + expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ + [PermissionNames.eth_accounts]: { + caveats: [ + { + type: CaveatTypes.restrictReturnedAccounts, + value: ['0x1', '0x3'], + }, + ], }, - ['0x1', '0x2', '0x3', '0x4'], - ); - expect(assignAccountsToScopes).toHaveBeenCalledWith( - { - 'eip155:6': { - methods: [], - notifications: [], - }, + [PermissionNames.permittedChains]: { + caveats: [ + { + type: CaveatTypes.restrictNetworkSwitching, + value: ['0x539', '0x64'], + }, + ], }, - ['0x1', '0x2', '0x3', '0x4'], - ); + }); }); it('throws an error when requesting account permission approval fails', async () => { @@ -540,41 +471,36 @@ describe('wallet_createSession', () => { expect(validateAndAddEip3085).not.toHaveBeenCalled(); }); - it('grants the CAIP-25 permission for the supported and supportable scopes', async () => { - const { handler, grantPermissions } = createMockedHandler(); + it('grants the CAIP-25 permission for the supported scopes and accounts that were approved', async () => { + const { handler, grantPermissions, requestPermissionApprovalForOrigin } = + createMockedHandler(); bucketScopes .mockReturnValueOnce({ supportedScopes: { - 'eip155:1': { + 'eip155:5': { methods: ['eth_chainId'], notifications: ['accountsChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x2'], - }, - }, - supportableScopes: { - 'eip155:2': { - methods: ['eth_chainId'], - notifications: [], + accounts: [], }, }, + supportableScopes: {}, unsupportableScopes: {}, }) .mockReturnValueOnce({ supportedScopes: { - 'eip155:1': { + 'eip155:100': { methods: ['eth_sendTransaction'], notifications: ['chainChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x3'], - }, - }, - supportableScopes: { - 'eip155:64': { - methods: ['net_version'], - notifications: ['chainChanged'], + accounts: ['eip155:1:0x3'], }, }, + supportableScopes: {}, unsupportableScopes: {}, }); + requestPermissionApprovalForOrigin.mockResolvedValue({ + approvedAccounts: ['0x1', '0x2'], + approvedChainIds: ['0x5', '0x64', '0x539'], // 5, 100, 1337 + }); await handler(baseRequest); expect(grantPermissions).toHaveBeenCalledWith({ @@ -586,25 +512,22 @@ describe('wallet_createSession', () => { type: Caip25CaveatType, value: { requiredScopes: { - 'eip155:1': { + 'eip155:5': { methods: ['eth_chainId'], notifications: ['accountsChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x2'], - }, - 'eip155:2': { - methods: ['eth_chainId'], - notifications: [], + accounts: ['eip155:5:0x1', 'eip155:5:0x2'], }, }, optionalScopes: { - 'eip155:1': { + 'eip155:100': { methods: ['eth_sendTransaction'], notifications: ['chainChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x3'], + accounts: ['eip155:100:0x1', 'eip155:100:0x2'], }, - 'eip155:64': { - methods: ['net_version'], - notifications: ['chainChanged'], + 'eip155:1337': { + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, + accounts: ['eip155:1337:0x1', 'eip155:1337:0x2'], }, }, isMultichainOrigin: true, @@ -652,40 +575,40 @@ describe('wallet_createSession', () => { }); it('returns the session ID, properties, and merged scopes', async () => { - const { handler, response } = createMockedHandler(); + const { handler, requestPermissionApprovalForOrigin, response } = + createMockedHandler(); bucketScopes .mockReturnValueOnce({ supportedScopes: { - 'eip155:1': { + 'eip155:5': { methods: ['eth_chainId'], notifications: ['accountsChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x2'], - }, - }, - supportableScopes: { - 'eip155:2': { - methods: ['eth_chainId'], - notifications: [], + accounts: ['eip155:5:0x1'], }, }, + supportableScopes: {}, unsupportableScopes: {}, }) .mockReturnValueOnce({ supportedScopes: { - 'eip155:1': { - methods: ['eth_sendTransaction'], - notifications: ['chainChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x3'], - }, - }, - supportableScopes: { - 'eip155:64': { + 'eip155:5': { methods: ['net_version'], + notifications: ['chainChanged', 'accountsChanged'], + accounts: [], + }, + 'eip155:100': { + methods: ['eth_sendTransaction'], notifications: ['chainChanged'], + accounts: ['eip155:1:0x3'], }, }, + supportableScopes: {}, unsupportableScopes: {}, }); + requestPermissionApprovalForOrigin.mockResolvedValue({ + approvedAccounts: ['0x1', '0x2'], + approvedChainIds: ['0x5', '0x64'], // 5, 100 + }); await handler(baseRequest); expect(response.result).toStrictEqual({ @@ -694,18 +617,15 @@ describe('wallet_createSession', () => { foo: 'bar', }, sessionScopes: { - 'eip155:1': { - methods: ['eth_chainId', 'eth_sendTransaction'], + 'eip155:5': { + methods: ['eth_chainId', 'net_version'], notifications: ['accountsChanged', 'chainChanged'], - accounts: ['eip155:1:0x1', 'eip155:1:0x2', 'eip155:1:0x3'], - }, - 'eip155:2': { - methods: ['eth_chainId'], - notifications: [], + accounts: ['eip155:5:0x1', 'eip155:5:0x2'], }, - 'eip155:64': { - methods: ['net_version'], + 'eip155:100': { + methods: ['eth_sendTransaction'], notifications: ['chainChanged'], + accounts: ['eip155:100:0x1', 'eip155:100:0x2'], }, }, }); diff --git a/app/scripts/lib/multichain-api/wallet-createSession/helpers.test.ts b/app/scripts/lib/multichain-api/wallet-createSession/helpers.test.ts index ef2e10aabb5d..118f98d569ff 100644 --- a/app/scripts/lib/multichain-api/wallet-createSession/helpers.test.ts +++ b/app/scripts/lib/multichain-api/wallet-createSession/helpers.test.ts @@ -1,7 +1,6 @@ import { RpcEndpointType } from '@metamask/network-controller'; import * as EthereumChainUtils from '../../rpc-method-middleware/handlers/ethereum-chain-utils'; -import { ScopesObject } from '../scope'; -import { assignAccountsToScopes, validateAndAddEip3085 } from './helpers'; +import { validateAndAddEip3085 } from './helpers'; jest.mock('../../rpc-method-middleware/handlers/ethereum-chain-utils', () => ({ validateAddEthereumChainParams: jest.fn(), @@ -13,56 +12,6 @@ describe('wallet_createSession helpers', () => { jest.resetAllMocks(); }); - describe('assignAccountsToScopes', () => { - it('overwrites the accounts property of each scope object with a CAIP-10 id built from the scopeString and passed in accounts', () => { - const scopes: ScopesObject = { - 'eip155:1': { - methods: [], - notifications: [], - accounts: ['will:be:overwitten'], - }, - 'eip155:5': { - methods: [], - notifications: [], - accounts: ['will:be:overwitten'], - }, - }; - - assignAccountsToScopes(scopes, ['0x1', '0x2', '0x3']); - - expect(scopes).toStrictEqual({ - 'eip155:1': { - methods: [], - notifications: [], - accounts: ['eip155:1:0x1', 'eip155:1:0x2', 'eip155:1:0x3'], - }, - 'eip155:5': { - methods: [], - notifications: [], - accounts: ['eip155:5:0x1', 'eip155:5:0x2', 'eip155:5:0x3'], - }, - }); - }); - - it('does not assign accounts for the wallet scope', () => { - const scopes: ScopesObject = { - wallet: { - methods: [], - notifications: [], - }, - }; - - assignAccountsToScopes(scopes, ['0x1', '0x2', '0x3']); - - expect(scopes).toStrictEqual({ - wallet: { - methods: [], - notifications: [], - }, - }); - }); - }); - describe('validateAndAddEip3085', () => { const addNetwork = jest.fn(); const findNetworkClientIdByChainId = jest.fn(); diff --git a/app/scripts/lib/multichain-api/wallet-createSession/helpers.ts b/app/scripts/lib/multichain-api/wallet-createSession/helpers.ts index 12e00aed32aa..2470feeaf25d 100644 --- a/app/scripts/lib/multichain-api/wallet-createSession/helpers.ts +++ b/app/scripts/lib/multichain-api/wallet-createSession/helpers.ts @@ -1,24 +1,10 @@ -import { CaipAccountId, Hex } from '@metamask/utils'; +import { Hex } from '@metamask/utils'; import { NetworkController, RpcEndpointType, } from '@metamask/network-controller'; -import { ScopesObject } from '../scope'; import { validateAddEthereumChainParams } from '../../rpc-method-middleware/handlers/ethereum-chain-utils'; -export const assignAccountsToScopes = ( - scopes: ScopesObject, - accounts: Hex[], -) => { - Object.entries(scopes).forEach(([scopeString, scopeObject]) => { - if (scopeString !== 'wallet') { - scopeObject.accounts = accounts.map( - (account) => `${scopeString}:${account}` as unknown as CaipAccountId, // do we need checks here? - ); - } - }); -}; - export const validateAndAddEip3085 = async ({ eip3085Params, addNetwork, diff --git a/app/scripts/lib/multichain-api/wallet-requestPermissions.js b/app/scripts/lib/multichain-api/wallet-requestPermissions.js index cb10c09f5948..70a63750e65b 100644 --- a/app/scripts/lib/multichain-api/wallet-requestPermissions.js +++ b/app/scripts/lib/multichain-api/wallet-requestPermissions.js @@ -23,7 +23,6 @@ export const requestPermissionsHandler = { grantPermissions: true, requestPermissionApprovalForOrigin: true, getAccounts: true, - getNetworkConfigurationByNetworkClientId: true, }, }; @@ -41,7 +40,6 @@ export const requestPermissionsHandler = { * @param options.grantPermissions * @param options.requestPermissionApprovalForOrigin * @param options.getAccounts - * @param options.getNetworkConfigurationByNetworkClientId * @returns A promise that resolves to nothing */ async function requestPermissionsImplementation( @@ -56,10 +54,9 @@ async function requestPermissionsImplementation( grantPermissions, requestPermissionApprovalForOrigin, getAccounts, - getNetworkConfigurationByNetworkClientId, }, ) { - const { origin, params, networkClientId } = req; + const { origin, params } = req; if (!Array.isArray(params) || !isPlainObject(params[0])) { return end(invalidParams({ data: { request: req } })); @@ -90,16 +87,7 @@ async function requestPermissionsImplementation( } if (!legacyRequestedPermissions[PermissionNames.permittedChains]) { - const { chainId } = - getNetworkConfigurationByNetworkClientId(networkClientId); - legacyRequestedPermissions[PermissionNames.permittedChains] = { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: [chainId], - }, - ], - }; + legacyRequestedPermissions[PermissionNames.permittedChains] = {}; } legacyApproval = await requestPermissionApprovalForOrigin( diff --git a/app/scripts/lib/multichain-api/wallet-requestPermissions.test.js b/app/scripts/lib/multichain-api/wallet-requestPermissions.test.js index 431c682bbcd6..cae18dbbc106 100644 --- a/app/scripts/lib/multichain-api/wallet-requestPermissions.test.js +++ b/app/scripts/lib/multichain-api/wallet-requestPermissions.test.js @@ -94,9 +94,6 @@ const createMockedHandler = () => { }, }), ); - const getNetworkConfigurationByNetworkClientId = jest.fn().mockReturnValue({ - chainId: '0x1', - }); const updateCaveat = jest.fn(); const grantPermissions = jest.fn().mockReturnValue( Object.freeze({ @@ -125,7 +122,6 @@ const createMockedHandler = () => { requestPermissionsHandler.implementation(request, response, next, end, { requestPermissionsForOrigin, getPermissionsForOrigin, - getNetworkConfigurationByNetworkClientId, updateCaveat, grantPermissions, requestPermissionApprovalForOrigin, @@ -139,7 +135,6 @@ const createMockedHandler = () => { end, requestPermissionsForOrigin, getPermissionsForOrigin, - getNetworkConfigurationByNetworkClientId, updateCaveat, grantPermissions, requestPermissionApprovalForOrigin, @@ -175,12 +170,9 @@ describe('requestPermissionsHandler', () => { ); }); - it('requests approval from the ApprovalController for eth_accounts and permittedChains with the chainId for the currently selected networkClientId (either global or dapp selected) when only eth_accounts is specified in params', async () => { - const { - handler, - getNetworkConfigurationByNetworkClientId, - requestPermissionApprovalForOrigin, - } = createMockedHandler(); + it('requests approval from the ApprovalController for eth_accounts and permittedChains when only eth_accounts is specified in params', async () => { + const { handler, requestPermissionApprovalForOrigin } = + createMockedHandler(); await handler({ ...getBaseRequest(), @@ -193,30 +185,17 @@ describe('requestPermissionsHandler', () => { ], }); - expect(getNetworkConfigurationByNetworkClientId).toHaveBeenCalledWith( - 'mainnet', - ); expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ [RestrictedMethods.eth_accounts]: { foo: 'bar', }, - [PermissionNames.permittedChains]: { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: ['0x1'], - }, - ], - }, + [PermissionNames.permittedChains]: {}, }); }); it('requests approval from the ApprovalController for eth_accounts and permittedChains when only permittedChains is specified in params', async () => { - const { - handler, - getNetworkConfigurationByNetworkClientId, - requestPermissionApprovalForOrigin, - } = createMockedHandler(); + const { handler, requestPermissionApprovalForOrigin } = + createMockedHandler(); await handler({ ...getBaseRequest(), @@ -234,7 +213,6 @@ describe('requestPermissionsHandler', () => { ], }); - expect(getNetworkConfigurationByNetworkClientId).not.toHaveBeenCalled(); expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ [RestrictedMethods.eth_accounts]: {}, [PermissionNames.permittedChains]: { @@ -249,11 +227,8 @@ describe('requestPermissionsHandler', () => { }); it('requests approval from the ApprovalController for eth_accounts and permittedChains when both are specified in params', async () => { - const { - handler, - getNetworkConfigurationByNetworkClientId, - requestPermissionApprovalForOrigin, - } = createMockedHandler(); + const { handler, requestPermissionApprovalForOrigin } = + createMockedHandler(); await handler({ ...getBaseRequest(), @@ -274,7 +249,6 @@ describe('requestPermissionsHandler', () => { ], }); - expect(getNetworkConfigurationByNetworkClientId).not.toHaveBeenCalled(); expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ [RestrictedMethods.eth_accounts]: { foo: 'bar', diff --git a/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.test.js b/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.test.js index ec1d14c1d1db..eb5030a51aa5 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.test.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/ethereum-chain-utils.test.js @@ -6,6 +6,10 @@ import { } from '../../multichain-api/caip25permissions'; import { CaveatTypes } from '../../../../../shared/constants/permissions'; import { PermissionNames } from '../../../controllers/permissions'; +import { + KnownNotifications, + KnownRpcMethods, +} from '../../multichain-api/scope'; import * as EthChainUtils from './ethereum-chain-utils'; describe('Ethereum Chain Utils', () => { @@ -245,8 +249,8 @@ describe('Ethereum Chain Utils', () => { requiredScopes: {}, optionalScopes: { 'eip155:1': { - methods: [], - notifications: [], + methods: KnownRpcMethods.eip155, + notifications: KnownNotifications.eip155, accounts: [], }, }, diff --git a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js index df0abab11ac3..e5f962234b29 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.js @@ -9,10 +9,7 @@ import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../../multichain-api/caip25permissions'; -import { - CaveatTypes, - RestrictedMethods, -} from '../../../../../shared/constants/permissions'; +import { RestrictedMethods } from '../../../../../shared/constants/permissions'; import { setEthAccounts } from '../../multichain-api/adapters/caip-permission-adapter-eth-accounts'; import { PermissionNames } from '../../../controllers/permissions'; import { setPermittedEthChainIds } from '../../multichain-api/adapters/caip-permission-adapter-permittedChains'; @@ -35,7 +32,6 @@ const requestEthereumAccounts = { sendMetrics: true, metamaskState: true, grantPermissions: true, - getNetworkConfigurationByNetworkClientId: true, }, }; export default requestEthereumAccounts; @@ -75,7 +71,6 @@ async function requestEthereumAccountsHandler( sendMetrics, metamaskState, grantPermissions, - getNetworkConfigurationByNetworkClientId, }, ) { const { origin } = req; @@ -104,22 +99,11 @@ async function requestEthereumAccountsHandler( return undefined; } - const { chainId } = getNetworkConfigurationByNetworkClientId( - req.networkClientId, - ); - let legacyApproval; try { legacyApproval = await requestPermissionApprovalForOrigin({ [RestrictedMethods.eth_accounts]: {}, - [PermissionNames.permittedChains]: { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: [chainId], - }, - ], - }, + [PermissionNames.permittedChains]: {}, }); } catch (err) { res.error = err; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.test.js b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.test.js index 1ccf1ca27366..d54b468a510d 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.test.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/request-accounts.test.js @@ -4,10 +4,7 @@ import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../../multichain-api/caip25permissions'; -import { - CaveatTypes, - RestrictedMethods, -} from '../../../../../shared/constants/permissions'; +import { RestrictedMethods } from '../../../../../shared/constants/permissions'; import { PermissionNames } from '../../../controllers/permissions'; import PermittedChainsAdapters from '../../multichain-api/adapters/caip-permission-adapter-permittedChains'; import EthAccountsAdapters from '../../multichain-api/adapters/caip-permission-adapter-eth-accounts'; @@ -66,9 +63,6 @@ const createMockedHandler = () => { }, }; const grantPermissions = jest.fn(); - const getNetworkConfigurationByNetworkClientId = jest.fn().mockReturnValue({ - chainId: '0x1', - }); const response = {}; const handler = (request) => requestEthereumAccounts.implementation(request, response, next, end, { @@ -78,7 +72,6 @@ const createMockedHandler = () => { sendMetrics, metamaskState, grantPermissions, - getNetworkConfigurationByNetworkClientId, }); return { @@ -90,7 +83,6 @@ const createMockedHandler = () => { requestPermissionApprovalForOrigin, sendMetrics, grantPermissions, - getNetworkConfigurationByNetworkClientId, handler, }; }; @@ -159,16 +151,6 @@ describe('requestEthereumAccountsHandler', () => { }); describe('eip155 account permissions do not exist', () => { - it('gets the network configuration for the request networkClientId', async () => { - const { handler, getNetworkConfigurationByNetworkClientId } = - createMockedHandler(); - - await handler(baseRequest); - expect(getNetworkConfigurationByNetworkClientId).toHaveBeenCalledWith( - 'mainnet', - ); - }); - it('requests eth_accounts and permittedChains approval', async () => { const { handler, requestPermissionApprovalForOrigin } = createMockedHandler(); @@ -176,14 +158,7 @@ describe('requestEthereumAccountsHandler', () => { await handler(baseRequest); expect(requestPermissionApprovalForOrigin).toHaveBeenCalledWith({ [RestrictedMethods.eth_accounts]: {}, - [PermissionNames.permittedChains]: { - caveats: [ - { - type: CaveatTypes.restrictNetworkSwitching, - value: ['0x1'], - }, - ], - }, + [PermissionNames.permittedChains]: {}, }); }); diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 320f3933170c..4f194d64e52d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -3734,7 +3734,6 @@ export default class MetamaskController extends EventEmitter { ...getPermissionBackgroundApiMethods({ permissionController, approvalController, - networkController, }), ///: BEGIN:ONLY_INCLUDE_IF(build-mmi) @@ -5988,10 +5987,6 @@ export default class MetamaskController extends EventEmitter { grantPermissions: this.permissionController.grantPermissions.bind( this.permissionController, ), - getNetworkConfigurationByNetworkClientId: - this.networkController.getNetworkConfigurationByNetworkClientId.bind( - this.networkController, - ), updateCaveat: this.permissionController.updateCaveat.bind( this.permissionController, ), @@ -6164,6 +6159,9 @@ export default class MetamaskController extends EventEmitter { this.networkController.findNetworkClientIdByChainId.bind( this.networkController, ), + listAccounts: this.accountsController.listAccounts.bind( + this.accountsController, + ), addNetwork: this.networkController.addNetwork.bind( this.networkController, ), diff --git a/ui/components/app/permissions-connect-permission-list/permissions-connect-permission-list.js b/ui/components/app/permissions-connect-permission-list/permissions-connect-permission-list.js index da15d384849c..e0bed04e5429 100644 --- a/ui/components/app/permissions-connect-permission-list/permissions-connect-permission-list.js +++ b/ui/components/app/permissions-connect-permission-list/permissions-connect-permission-list.js @@ -7,6 +7,7 @@ import { getSnapsMetadata } from '../../../selectors'; import { getSnapName } from '../../../helpers/utils/util'; import PermissionCell from '../permission-cell'; import { Box } from '../../component-library'; +import { CaveatTypes } from '../../../../shared/constants/permissions'; /** * Get one or more permission descriptions for a permission name. @@ -17,6 +18,10 @@ import { Box } from '../../component-library'; * @returns {JSX.Element} A permission description node. */ function getDescriptionNode(permission, index, accounts) { + const permissionValue = permission?.permissionValue?.caveats?.find( + (caveat) => caveat.type === CaveatTypes.restrictNetworkSwitching, + )?.value; + return ( ); } diff --git a/ui/components/multichain/edit-accounts-modal/edit-accounts-modal.tsx b/ui/components/multichain/edit-accounts-modal/edit-accounts-modal.tsx index d9303951af2d..4ce30ea396a1 100644 --- a/ui/components/multichain/edit-accounts-modal/edit-accounts-modal.tsx +++ b/ui/components/multichain/edit-accounts-modal/edit-accounts-modal.tsx @@ -30,6 +30,7 @@ import { } from '../../../helpers/constants/design-system'; import { getURLHost } from '../../../helpers/utils/util'; import { MergedInternalAccount } from '../../../selectors/selectors.types'; +import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils'; type EditAccountsModalProps = { activeTabOrigin: string; @@ -131,8 +132,12 @@ export const EditAccountsModal: React.FC = ({ isPinned={Boolean(account.pinned)} startAccessory={ + isEqualCaseInsensitive( + selectedAccountAddress, + account.address, + ), )} /> } diff --git a/ui/components/multichain/pages/review-permissions-page/site-cell/site-cell.tsx b/ui/components/multichain/pages/review-permissions-page/site-cell/site-cell.tsx index 4bc42604adf3..309b8ef7b20d 100644 --- a/ui/components/multichain/pages/review-permissions-page/site-cell/site-cell.tsx +++ b/ui/components/multichain/pages/review-permissions-page/site-cell/site-cell.tsx @@ -14,6 +14,7 @@ import { } from '../../../../component-library'; import { EditAccountsModal, EditNetworksModal } from '../../..'; import { MergedInternalAccount } from '../../../../../selectors/selectors.types'; +import { isEqualCaseInsensitive } from '../../../../../../shared/modules/string-utils'; import { SiteCellTooltip } from './site-cell-tooltip'; import { SiteCellConnectionListItem } from './site-cell-connection-list-item'; @@ -54,7 +55,9 @@ export const SiteCell: React.FC = ({ const [showEditNetworksModal, setShowEditNetworksModal] = useState(false); const selectedAccounts = accounts.filter(({ address }) => - selectedAccountAddresses.includes(address), + selectedAccountAddresses.some((selectedAccountAddress) => + isEqualCaseInsensitive(selectedAccountAddress, address), + ), ); const selectedNetworks = allNetworks.filter(({ chainId }) => selectedChainIds.includes(chainId), diff --git a/ui/pages/permissions-connect/connect-page/connect-page.tsx b/ui/pages/permissions-connect/connect-page/connect-page.tsx index a30047fbd38a..59399b584a3e 100644 --- a/ui/pages/permissions-connect/connect-page/connect-page.tsx +++ b/ui/pages/permissions-connect/connect-page/connect-page.tsx @@ -33,6 +33,11 @@ import { import { MergedInternalAccount } from '../../../selectors/selectors.types'; import { mergeAccounts } from '../../../components/multichain/account-list-menu/account-list-menu'; import { TEST_CHAINS } from '../../../../shared/constants/network'; +import { + CaveatTypes, + EndowmentTypes, + RestrictedMethods, +} from '../../../../shared/constants/permissions'; import PermissionsConnectFooter from '../../../components/app/permissions-connect-footer'; export type ConnectPageRequest = { @@ -57,6 +62,20 @@ export const ConnectPage: React.FC = ({ }) => { const t = useI18nContext(); + const ethAccountsPermission = + request?.permissions?.[RestrictedMethods.eth_accounts]; + const requestedAccounts = + ethAccountsPermission?.caveats?.find( + (caveat) => caveat.type === CaveatTypes.restrictReturnedAccounts, + )?.value || []; + + const permittedChainsPermission = + request?.permissions?.[EndowmentTypes.permittedChains]; + const requestedChainIds = + permittedChainsPermission?.caveats?.find( + (caveat) => caveat.type === CaveatTypes.restrictNetworkSwitching, + )?.value || []; + const networkConfigurations = useSelector(getNetworkConfigurationsByChainId); const [nonTestNetworks, testNetworks] = useMemo( () => @@ -70,7 +89,10 @@ export const ConnectPage: React.FC = ({ ), [networkConfigurations], ); - const defaultSelectedChainIds = nonTestNetworks.map(({ chainId }) => chainId); + const defaultSelectedChainIds = + requestedChainIds.length > 0 + ? requestedChainIds + : nonTestNetworks.map(({ chainId }) => chainId); const [selectedChainIds, setSelectedChainIds] = useState( defaultSelectedChainIds, ); @@ -84,7 +106,10 @@ export const ConnectPage: React.FC = ({ }, [accounts, internalAccounts]); const currentAccount = useSelector(getSelectedInternalAccount); - const defaultAccountsAddresses = [currentAccount?.address]; + const defaultAccountsAddresses = + requestedAccounts.length > 0 + ? requestedAccounts + : [currentAccount?.address]; const [selectedAccountAddresses, setSelectedAccountAddresses] = useState( defaultAccountsAddresses, );