From 639f427d7bcc26eb8bf98c048c2d7737e3804ccd Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 09:33:26 -0700 Subject: [PATCH 1/8] convert wallet_createSession handler to ts --- .../{handler.js => handler.ts} | 93 +++++++++++++++++-- 1 file changed, 85 insertions(+), 8 deletions(-) rename app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/{handler.js => handler.ts} (68%) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.js b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts similarity index 68% rename from app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.js rename to app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts index e080be148f92..15e4e8cde0f9 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts @@ -9,18 +9,93 @@ import { mergeScopes, bucketScopes, validateAndNormalizeScopes, + ScopesObject, + Caip25Authorization, + ScopeString, } from '@metamask/multichain'; +import { + Caveat, + CaveatSpecificationConstraint, + PermissionController, + PermissionSpecificationConstraint, + RequestedPermissions, + ValidPermission, +} from '@metamask/permission-controller'; +import { Hex, Json, JsonRpcRequest, JsonRpcSuccess } from '@metamask/utils'; +import { NetworkController } from '@metamask/network-controller'; +import { + JsonRpcEngineEndCallback, + JsonRpcEngineNextCallback, +} from '@metamask/json-rpc-engine'; import { PermissionNames } from '../../../../controllers/permissions'; import { MetaMetricsEventCategory, MetaMetricsEventName, + MetaMetricsEventOptions, + MetaMetricsEventPayload, } from '../../../../../../shared/constants/metametrics'; import { shouldEmitDappViewedEvent } from '../../../util'; import { CaveatTypes } from '../../../../../../shared/constants/permissions'; import { MESSAGE_TYPE } from '../../../../../../shared/constants/app'; import { processScopedProperties, validateAndAddEip3085 } from './helpers'; -export async function walletCreateSessionHandler(req, res, _next, end, hooks) { +type AbstractPermissionController = PermissionController< + PermissionSpecificationConstraint, + CaveatSpecificationConstraint +>; + +/** + * Handler for the `wallet_createSession` RPC method. + * + * @param req - The request object. + * @param res - The response object. + * @param _next - The next middleware function. + * @param end - The end function. + * @param hooks - The hooks object. + * @param hooks.listAccounts + * @param hooks.removeNetwork + * @param hooks.addNetwork + * @param hooks.findNetworkClientIdByChainId + * @param hooks.requestPermissionApprovalForOrigin + * @param hooks.sendMetrics + * @param hooks.metamaskState + * @param hooks.metamaskState.metaMetricsId + * @param hooks.metamaskState.permissionHistory + * @param hooks.metamaskState.accounts + * @param hooks.grantPermissions + */ +async function walletCreateSessionHandler( + req: JsonRpcRequest< + Caip25Authorization & { sessionProperties?: Record } + > & { origin: string }, + res: JsonRpcSuccess<{ + sessionScopes: ScopesObject; + sessionProperties?: Record; + }>, + _next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + hooks: { + listAccounts: () => Promise<{ address: string }[]>; + removeNetwork: NetworkController['removeNetwork']; + addNetwork: NetworkController['addNetwork']; + findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId']; + requestPermissionApprovalForOrigin: ( + requestedPermissions: RequestedPermissions, + ) => Promise<{ approvedAccounts: Hex[]; approvedChainIds: Hex[] }>; + sendMetrics: ( + payload: MetaMetricsEventPayload, + options?: MetaMetricsEventOptions, + ) => void; + metamaskState: { + metaMetricsId: string; + permissionHistory: Record; + accounts: Record; + }; + grantPermissions: ( + ...args: Parameters + ) => Record>>; + }, +) { const { origin, params: { @@ -35,7 +110,7 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { return end(new JsonRpcError(5302, 'Invalid sessionProperties requested')); } - const chainIdsForNetworksAdded = []; + const chainIdsForNetworksAdded: Hex[] = []; try { const { normalizedRequiredScopes, normalizedOptionalScopes } = @@ -47,7 +122,7 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { scopedProperties, ); - const existsNetworkClientForChainId = (chainId) => { + const existsNetworkClientForChainId = (chainId: Hex) => { try { hooks.findNetworkClientIdByChainId(chainId); return true; @@ -56,9 +131,9 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { } }; - const existsEip3085ForChainId = (chainId) => { + const existsEip3085ForChainId = (chainId: Hex) => { const scopeString = `eip155:${parseInt(chainId, 16)}`; - return validScopedProperties?.[scopeString]?.eip3085; + return Boolean(validScopedProperties?.[scopeString]?.eip3085); }; const { @@ -97,12 +172,14 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { const supportedEthAccounts = getEthAccounts({ requiredScopes: supportedRequiredScopes, optionalScopes: supportedOptionalScopes, + isMultichainOrigin: true, }) .map((address) => address.toLowerCase()) .filter((address) => existingEvmAddresses.includes(address)); const supportedEthChainIds = getPermittedEthChainIds({ requiredScopes: supportedRequiredScopes, optionalScopes: supportedOptionalScopes, + isMultichainOrigin: true, }); const legacyApproval = await hooks.requestPermissionApprovalForOrigin({ @@ -146,14 +223,14 @@ export async function walletCreateSessionHandler(req, res, _next, end, hooks) { ); await Promise.all( - Object.keys(scopedProperties || {}).map(async (scopeString) => { - const scope = sessionScopes[scopeString]; + Object.keys(validScopedProperties || {}).map(async (scopeString) => { + const scope = sessionScopes[scopeString as ScopeString]; if (!scope) { return; } const chainId = await validateAndAddEip3085({ - eip3085Params: scopedProperties[scopeString].eip3085, + eip3085Params: validScopedProperties[scopeString].eip3085, addNetwork: hooks.addNetwork, findNetworkClientIdByChainId: hooks.findNetworkClientIdByChainId, }); From 068ff52c0f8535c9d367bd5972e3e766f856e289 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 09:55:16 -0700 Subject: [PATCH 2/8] WIP --- .../handlers/wallet-createSession/handler.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts index 15e4e8cde0f9..380ec66d1952 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts @@ -98,13 +98,16 @@ async function walletCreateSessionHandler( ) { const { origin, - params: { - requiredScopes, - optionalScopes, - sessionProperties, - scopedProperties, - }, } = req; + if (!req.params) { + return + } + const { + requiredScopes, + optionalScopes, + sessionProperties, + scopedProperties, + } = req.params if (sessionProperties && Object.keys(sessionProperties).length === 0) { return end(new JsonRpcError(5302, 'Invalid sessionProperties requested')); From c0ee82102a04ea56fbe9d8c048c20295d5811577 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 10:30:22 -0700 Subject: [PATCH 3/8] Fix wallet_addEthereumChain handler types --- .../handlers/wallet-createSession/handler.ts | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts index 380ec66d1952..9fce7c6a9df4 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts @@ -12,16 +12,25 @@ import { ScopesObject, Caip25Authorization, ScopeString, + ScopedProperties, } from '@metamask/multichain'; import { Caveat, CaveatSpecificationConstraint, + invalidParams, PermissionController, PermissionSpecificationConstraint, RequestedPermissions, ValidPermission, } from '@metamask/permission-controller'; -import { Hex, Json, JsonRpcRequest, JsonRpcSuccess } from '@metamask/utils'; +import { + CaipChainId, + Hex, + isPlainObject, + Json, + JsonRpcRequest, + JsonRpcSuccess, +} from '@metamask/utils'; import { NetworkController } from '@metamask/network-controller'; import { JsonRpcEngineEndCallback, @@ -65,9 +74,7 @@ type AbstractPermissionController = PermissionController< * @param hooks.grantPermissions */ async function walletCreateSessionHandler( - req: JsonRpcRequest< - Caip25Authorization & { sessionProperties?: Record } - > & { origin: string }, + req: JsonRpcRequest & { origin: string }, res: JsonRpcSuccess<{ sessionScopes: ScopesObject; sessionProperties?: Record; @@ -75,7 +82,7 @@ async function walletCreateSessionHandler( _next: JsonRpcEngineNextCallback, end: JsonRpcEngineEndCallback, hooks: { - listAccounts: () => Promise<{ address: string }[]>; + listAccounts: () => { address: string }[]; removeNetwork: NetworkController['removeNetwork']; addNetwork: NetworkController['addNetwork']; findNetworkClientIdByChainId: NetworkController['findNetworkClientIdByChainId']; @@ -96,18 +103,16 @@ async function walletCreateSessionHandler( ) => Record>>; }, ) { - const { - origin, - } = req; - if (!req.params) { - return + const { origin } = req; + if (!isPlainObject(req.params)) { + return end(invalidParams({ data: { request: req } })); } const { requiredScopes, optionalScopes, sessionProperties, scopedProperties, - } = req.params + } = req.params; if (sessionProperties && Object.keys(sessionProperties).length === 0) { return end(new JsonRpcError(5302, 'Invalid sessionProperties requested')); @@ -117,12 +122,12 @@ async function walletCreateSessionHandler( try { const { normalizedRequiredScopes, normalizedOptionalScopes } = - validateAndNormalizeScopes(requiredScopes, optionalScopes); + validateAndNormalizeScopes(requiredScopes || {}, optionalScopes || {}); const validScopedProperties = processScopedProperties( normalizedRequiredScopes, normalizedOptionalScopes, - scopedProperties, + scopedProperties as ScopedProperties, ); const existsNetworkClientForChainId = (chainId: Hex) => { @@ -135,7 +140,7 @@ async function walletCreateSessionHandler( }; const existsEip3085ForChainId = (chainId: Hex) => { - const scopeString = `eip155:${parseInt(chainId, 16)}`; + const scopeString: CaipChainId = `eip155:${parseInt(chainId, 16)}`; return Boolean(validScopedProperties?.[scopeString]?.eip3085); }; From adb302f2204070c93371b7246aeeb1455236bdce Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 10:46:17 -0700 Subject: [PATCH 4/8] convert wallet_createSession test handler to ts --- .../{handler.test.js => handler.test.ts} | 80 ++++++++++++------- 1 file changed, 49 insertions(+), 31 deletions(-) rename app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/{handler.test.js => handler.test.ts} (88%) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.js b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts similarity index 88% rename from app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.js rename to app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts index 1b3951644666..1bccea268e89 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts @@ -2,35 +2,44 @@ import { JsonRpcError } from '@metamask/rpc-errors'; import { Caip25CaveatType, Caip25EndowmentPermissionName, - validateAndNormalizeScopes, - bucketScopes, KnownRpcMethods, KnownNotifications, + Caip25Authorization, + ScopesObject, } from '@metamask/multichain'; +import * as Multichain from '@metamask/multichain'; +import { Json, JsonRpcRequest, JsonRpcSuccess } from '@metamask/utils'; import { CaveatTypes } from '../../../../../../shared/constants/permissions'; -import { shouldEmitDappViewedEvent } from '../../../util'; +import * as Util from '../../../util'; import { PermissionNames } from '../../../../controllers/permissions'; import { processScopedProperties, validateAndAddEip3085 } from './helpers'; -import { walletCreateSessionHandler } from './handler'; +import * as Helpers from './helpers'; +import { walletCreateSession } from './handler'; jest.mock('../../../util', () => ({ ...jest.requireActual('../../../util'), shouldEmitDappViewedEvent: jest.fn(), })); +const MockUtil = jest.mocked(Util); jest.mock('@metamask/multichain', () => ({ ...jest.requireActual('@metamask/multichain'), validateAndNormalizeScopes: jest.fn(), bucketScopes: jest.fn(), })); +const MockMultichain = jest.mocked(Multichain); jest.mock('./helpers', () => ({ ...jest.requireActual('./helpers'), validateAndAddEip3085: jest.fn(), processScopedProperties: jest.fn(), })); +const MockHelpers = jest.mocked(Helpers); const baseRequest = { + jsonrpc: '2.0' as const, + id: 0, + method: 'wallet_createSession', origin: 'http://test.com', params: { requiredScopes: { @@ -62,7 +71,7 @@ const createMockedHandler = () => { }); const grantPermissions = jest.fn().mockResolvedValue(undefined); const findNetworkClientIdByChainId = jest.fn().mockReturnValue('mainnet'); - const addNetwork = jest.fn().mockResolvedValue(); + const addNetwork = jest.fn().mockResolvedValue(undefined); const removeNetwork = jest.fn(); const sendMetrics = jest.fn(); const metamaskState = { @@ -75,9 +84,17 @@ const createMockedHandler = () => { }, }; const listAccounts = jest.fn().mockReturnValue([]); - const response = {}; - const handler = (request) => - walletCreateSessionHandler(request, response, next, end, { + const response = { + jsonrpc: '2.0' as const, + id: 0, + } as unknown as JsonRpcSuccess<{ + sessionScopes: ScopesObject; + sessionProperties?: Record; + }>; + const handler = ( + request: JsonRpcRequest & { origin: string }, + ) => + walletCreateSession.implementation(request, response, next, end, { findNetworkClientIdByChainId, requestPermissionApprovalForOrigin, grantPermissions, @@ -106,11 +123,11 @@ const createMockedHandler = () => { describe('wallet_createSession', () => { beforeEach(() => { - validateAndNormalizeScopes.mockReturnValue({ + MockMultichain.validateAndNormalizeScopes.mockReturnValue({ normalizedRequiredScopes: {}, normalizedOptionalScopes: {}, }); - bucketScopes.mockReturnValue({ + MockMultichain.bucketScopes.mockReturnValue({ supportedScopes: {}, supportableScopes: {}, unsupportableScopes: {}, @@ -147,7 +164,7 @@ describe('wallet_createSession', () => { }, }); - expect(validateAndNormalizeScopes).toHaveBeenCalledWith( + expect(MockMultichain.validateAndNormalizeScopes).toHaveBeenCalledWith( baseRequest.params.requiredScopes, { foo: 'bar' }, ); @@ -155,7 +172,7 @@ describe('wallet_createSession', () => { it('throws an error when processing scopes fails', async () => { const { handler, end } = createMockedHandler(); - validateAndNormalizeScopes.mockImplementation(() => { + MockMultichain.validateAndNormalizeScopes.mockImplementation(() => { throw new Error('failed to process scopes'); }); await handler(baseRequest); @@ -164,7 +181,7 @@ describe('wallet_createSession', () => { it('processes the scopedProperties', async () => { const { handler } = createMockedHandler(); - validateAndNormalizeScopes.mockReturnValue({ + MockMultichain.validateAndNormalizeScopes.mockReturnValue({ normalizedRequiredScopes: { 'eip155:1': { methods: ['eth_chainId'], @@ -222,7 +239,7 @@ describe('wallet_createSession', () => { it('buckets the required scopes', async () => { const { handler } = createMockedHandler(); - validateAndNormalizeScopes.mockReturnValue({ + MockMultichain.validateAndNormalizeScopes.mockReturnValue({ normalizedRequiredScopes: { 'eip155:1': { methods: ['eth_chainId'], @@ -234,7 +251,7 @@ describe('wallet_createSession', () => { }); await handler(baseRequest); - expect(bucketScopes).toHaveBeenNthCalledWith( + expect(MockMultichain.bucketScopes).toHaveBeenNthCalledWith( 1, { 'eip155:1': { @@ -250,16 +267,16 @@ describe('wallet_createSession', () => { ); const isChainIdSupportedBody = - bucketScopes.mock.calls[0][1].isChainIdSupported.toString(); + MockMultichain.bucketScopes.mock.calls[0][1].isChainIdSupported.toString(); expect(isChainIdSupportedBody).toContain('findNetworkClientIdByChainId'); const isChainIdSupportableBody = - bucketScopes.mock.calls[0][1].isChainIdSupportable.toString(); + MockMultichain.bucketScopes.mock.calls[0][1].isChainIdSupportable.toString(); expect(isChainIdSupportableBody).toContain('validScopedProperties'); }); it('buckets the optional scopes', async () => { const { handler } = createMockedHandler(); - validateAndNormalizeScopes.mockReturnValue({ + MockMultichain.validateAndNormalizeScopes.mockReturnValue({ normalizedRequiredScopes: {}, normalizedOptionalScopes: { 'eip155:100': { @@ -271,7 +288,7 @@ describe('wallet_createSession', () => { }); await handler(baseRequest); - expect(bucketScopes).toHaveBeenNthCalledWith( + expect(MockMultichain.bucketScopes).toHaveBeenNthCalledWith( 2, { 'eip155:100': { @@ -287,10 +304,10 @@ describe('wallet_createSession', () => { ); const isChainIdSupportedBody = - bucketScopes.mock.calls[1][1].isChainIdSupported.toString(); + MockMultichain.bucketScopes.mock.calls[1][1].isChainIdSupported.toString(); expect(isChainIdSupportedBody).toContain('findNetworkClientIdByChainId'); const isChainIdSupportableBody = - bucketScopes.mock.calls[1][1].isChainIdSupportable.toString(); + MockMultichain.bucketScopes.mock.calls[1][1].isChainIdSupportable.toString(); expect(isChainIdSupportableBody).toContain('validScopedProperties'); }); @@ -309,7 +326,7 @@ describe('wallet_createSession', () => { { address: '0x3' }, { address: '0x4' }, ]); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:1337': { @@ -369,7 +386,7 @@ describe('wallet_createSession', () => { it('validates and upserts EIP 3085 scoped properties when matching sessionScope is defined', async () => { const { handler, findNetworkClientIdByChainId, addNetwork } = createMockedHandler(); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:1': { @@ -409,7 +426,7 @@ describe('wallet_createSession', () => { it('does not validate and upsert EIP 3085 scoped properties when there is no matching sessionScope', async () => { const { handler } = createMockedHandler(); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:1': { @@ -446,7 +463,7 @@ describe('wallet_createSession', () => { it('grants the CAIP-25 permission for the supported scopes and accounts that were approved', async () => { const { handler, grantPermissions, requestPermissionApprovalForOrigin } = createMockedHandler(); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:5': { @@ -528,9 +545,9 @@ describe('wallet_createSession', () => { }); it('emits the dapp viewed metrics event', async () => { - shouldEmitDappViewedEvent.mockReturnValue(true); + MockUtil.shouldEmitDappViewedEvent.mockReturnValue(true); const { handler, sendMetrics } = createMockedHandler(); - bucketScopes.mockReturnValue({ + MockMultichain.bucketScopes.mockReturnValue({ supportedScopes: {}, supportableScopes: {}, unsupportableScopes: {}, @@ -554,7 +571,7 @@ describe('wallet_createSession', () => { it('returns the session ID, properties, and merged scopes', async () => { const { handler, requestPermissionApprovalForOrigin, response } = createMockedHandler(); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:5': { @@ -615,12 +632,13 @@ describe('wallet_createSession', () => { it('reverts any upserted network clients if the request fails', async () => { const { handler, removeNetwork, grantPermissions } = createMockedHandler(); - bucketScopes + MockMultichain.bucketScopes .mockReturnValueOnce({ supportedScopes: { 'eip155:1': { methods: [], notifications: [], + accounts: [], }, }, supportableScopes: {}, @@ -631,14 +649,14 @@ describe('wallet_createSession', () => { supportableScopes: {}, unsupportableScopes: {}, }); - processScopedProperties.mockReturnValue({ + MockHelpers.processScopedProperties.mockReturnValue({ 'eip155:1': { eip3085: { foo: 'bar', }, }, }); - validateAndAddEip3085.mockReturnValue('0xdeadbeef'); + MockHelpers.validateAndAddEip3085.mockResolvedValue('0xdeadbeef'); grantPermissions.mockImplementation(() => { throw new Error('failed to grant permission'); }); From 3305b90a872abaacfccf20a557db5747c009a382 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 10:54:53 -0700 Subject: [PATCH 5/8] Fix spec --- .../wallet-createSession/handler.test.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts index 1bccea268e89..7c10d83a9851 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts @@ -12,7 +12,6 @@ import { Json, JsonRpcRequest, JsonRpcSuccess } from '@metamask/utils'; import { CaveatTypes } from '../../../../../../shared/constants/permissions'; import * as Util from '../../../util'; import { PermissionNames } from '../../../../controllers/permissions'; -import { processScopedProperties, validateAndAddEip3085 } from './helpers'; import * as Helpers from './helpers'; import { walletCreateSession } from './handler'; @@ -207,7 +206,7 @@ describe('wallet_createSession', () => { }, }); - expect(processScopedProperties).toHaveBeenCalledWith( + expect(MockHelpers.processScopedProperties).toHaveBeenCalledWith( { 'eip155:1': { methods: ['eth_chainId'], @@ -228,7 +227,7 @@ describe('wallet_createSession', () => { it('throws an error when processing scopedProperties fails', async () => { const { handler, end } = createMockedHandler(); - processScopedProperties.mockImplementation(() => { + MockHelpers.processScopedProperties.mockImplementation(() => { throw new Error('failed to process scoped properties'); }); await handler(baseRequest); @@ -403,6 +402,13 @@ describe('wallet_createSession', () => { supportableScopes: {}, unsupportableScopes: {}, }); + MockHelpers.processScopedProperties.mockReturnValue({ + 'eip155:1': { + eip3085: { + foo: 'bar', + }, + }, + }); await handler({ ...baseRequest, params: { @@ -417,7 +423,7 @@ describe('wallet_createSession', () => { }, }); - expect(validateAndAddEip3085).toHaveBeenCalledWith({ + expect(MockHelpers.validateAndAddEip3085).toHaveBeenCalledWith({ eip3085Params: { foo: 'bar' }, addNetwork, findNetworkClientIdByChainId, @@ -457,7 +463,7 @@ describe('wallet_createSession', () => { }, }); - expect(validateAndAddEip3085).not.toHaveBeenCalled(); + expect(MockHelpers.validateAndAddEip3085).not.toHaveBeenCalled(); }); it('grants the CAIP-25 permission for the supported scopes and accounts that were approved', async () => { From d79c72a41b28d31a26b4850fdea183a3e2b507c2 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 11:06:26 -0700 Subject: [PATCH 6/8] Fix types --- .../handlers/wallet-createSession/helpers.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/helpers.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/helpers.ts index fa88aeb1c286..10d780c4b110 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/helpers.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/helpers.ts @@ -105,7 +105,7 @@ export const processScopedProperties = ( if (!scope) { continue; } - validScopedProperties[scopeString] = {}; + validScopedProperties[scopeString as CaipChainId] = {}; if (scopedProperty.eip3085) { try { @@ -113,7 +113,8 @@ export const processScopedProperties = ( scopeString, scopedProperty.eip3085, ); - validScopedProperties[scopeString].eip3085 = scopedProperty.eip3085; + validScopedProperties[scopeString as CaipChainId].eip3085 = + scopedProperty.eip3085; } catch (err) { // noop } From 782199f07034e6b3d184f051f09e590eac7a6ce5 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 11:16:22 -0700 Subject: [PATCH 7/8] Bring in updated core package for ScopedProperties type fix --- package.json | 4 ++-- yarn.lock | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index fd094b24ebcc..84218da165e1 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "attributions:generate": "./development/generate-attributions.sh" }, "resolutions": { - "@metamask/controller-utils": "npm:@metamask-previews/controller-utils@11.3.0-preview-257618a8", + "@metamask/controller-utils": "npm:@metamask-previews/controller-utils@11.3.0-preview-ead2f439", "chokidar": "^3.6.0", "gridplus-sdk": "~2.6.0", "gridplus-sdk/secp256k1": "^5.0.1", @@ -345,7 +345,7 @@ "@metamask/message-manager": "^10.1.0", "@metamask/message-signing-snap": "^0.4.0", "@metamask/metamask-eth-abis": "^3.1.1", - "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-257618a8", + "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-ead2f439", "@metamask/name-controller": "^8.0.0", "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A21.0.0#~/.yarn/patches/@metamask-network-controller-npm-21.0.0-559aa8e395.patch", "@metamask/notification-controller": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index e0a7b0cf95be..94412e411a64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4987,9 +4987,9 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:@metamask-previews/controller-utils@11.3.0-preview-257618a8": - version: 11.3.0-preview-257618a8 - resolution: "@metamask-previews/controller-utils@npm:11.3.0-preview-257618a8" +"@metamask/controller-utils@npm:@metamask-previews/controller-utils@11.3.0-preview-ead2f439": + version: 11.3.0-preview-ead2f439 + resolution: "@metamask-previews/controller-utils@npm:11.3.0-preview-ead2f439" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@metamask/eth-query": "npm:^4.0.0" @@ -5000,7 +5000,7 @@ __metadata: bn.js: "npm:^5.2.1" eth-ens-namehash: "npm:^2.0.8" fast-deep-equal: "npm:^3.1.3" - checksum: 10/e3218a2def8cccec501bce3f307130f7dd459082980e44d3d8a400a4de20a0d68bb93fb10a58571a72440b763077b37e31de6466c9b2efeb1dd78f3f6f005ab3 + checksum: 10/14b0e1f5a3cc2e103735ec4c050301187a6b75cf90778cd1505ccc4682c7a0f7d6abe0e59b677b34f3f052875b02abfc3ce01fc78ca015956ee36a1f749072e8 languageName: node linkType: hard @@ -5718,9 +5718,9 @@ __metadata: languageName: node linkType: hard -"@metamask/multichain@npm:@metamask-previews/multichain@0.0.0-preview-257618a8": - version: 0.0.0-preview-257618a8 - resolution: "@metamask-previews/multichain@npm:0.0.0-preview-257618a8" +"@metamask/multichain@npm:@metamask-previews/multichain@0.0.0-preview-ead2f439": + version: 0.0.0-preview-ead2f439 + resolution: "@metamask-previews/multichain@npm:0.0.0-preview-ead2f439" dependencies: "@metamask/api-specs": "npm:^0.10.12" "@metamask/controller-utils": "npm:^11.3.0" @@ -5734,7 +5734,7 @@ __metadata: peerDependencies: "@metamask/network-controller": ^21.0.0 "@metamask/permission-controller": ^11.0.0 - checksum: 10/98fa07065e92d5b4a689fd2c0ff93adfdb380232bfba46e74a388e512e3bb6aad787fc9fec65d48a8faf50537cc9d11236f8d62bae5b262d98cea7f5b494c440 + checksum: 10/d11ab3f5f38a4cb89ba6e90efa038aeb6f480366a83020acd52cb194fdf7c6915f61fe68091b58cba0840928f0c36cc2442f0f0d9e2eaf4a7bfef55fd169b36c languageName: node linkType: hard @@ -26030,7 +26030,7 @@ __metadata: "@metamask/message-manager": "npm:^10.1.0" "@metamask/message-signing-snap": "npm:^0.4.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" - "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-257618a8" + "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-ead2f439" "@metamask/name-controller": "npm:^8.0.0" "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A21.0.0#~/.yarn/patches/@metamask-network-controller-npm-21.0.0-559aa8e395.patch" "@metamask/notification-controller": "npm:^6.0.0" From 06eafbb7f801aa0a3ebd6b7dc39f3189364ee118 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Tue, 22 Oct 2024 13:20:51 -0700 Subject: [PATCH 8/8] use new preview build with loosened get adapter types --- .../wallet-createSession/handler.test.ts | 12 +++++-- .../handlers/wallet-createSession/handler.ts | 32 +++++++++---------- package.json | 4 +-- yarn.lock | 18 +++++------ 4 files changed, 37 insertions(+), 29 deletions(-) diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts index 7c10d83a9851..3bf8f115db40 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.test.ts @@ -158,14 +158,22 @@ describe('wallet_createSession', () => { params: { ...baseRequest.params, optionalScopes: { - foo: 'bar', + foo: { + methods: [], + notifications: [], + }, }, }, }); expect(MockMultichain.validateAndNormalizeScopes).toHaveBeenCalledWith( baseRequest.params.requiredScopes, - { foo: 'bar' }, + { + foo: { + methods: [], + notifications: [], + }, + }, ); }); diff --git a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts index 9fce7c6a9df4..8a36fd775034 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/wallet-createSession/handler.ts @@ -180,14 +180,12 @@ async function walletCreateSessionHandler( const supportedEthAccounts = getEthAccounts({ requiredScopes: supportedRequiredScopes, optionalScopes: supportedOptionalScopes, - isMultichainOrigin: true, }) .map((address) => address.toLowerCase()) .filter((address) => existingEvmAddresses.includes(address)); const supportedEthChainIds = getPermittedEthChainIds({ requiredScopes: supportedRequiredScopes, optionalScopes: supportedOptionalScopes, - isMultichainOrigin: true, }); const legacyApproval = await hooks.requestPermissionApprovalForOrigin({ @@ -231,22 +229,24 @@ async function walletCreateSessionHandler( ); await Promise.all( - Object.keys(validScopedProperties || {}).map(async (scopeString) => { - const scope = sessionScopes[scopeString as ScopeString]; - if (!scope) { - return; - } + Object.entries(validScopedProperties).map( + async ([scopeString, scopedProperty]) => { + const scope = sessionScopes[scopeString as ScopeString]; + if (!scope) { + return; + } - const chainId = await validateAndAddEip3085({ - eip3085Params: validScopedProperties[scopeString].eip3085, - addNetwork: hooks.addNetwork, - findNetworkClientIdByChainId: hooks.findNetworkClientIdByChainId, - }); + const chainId = await validateAndAddEip3085({ + eip3085Params: scopedProperty.eip3085, + addNetwork: hooks.addNetwork, + findNetworkClientIdByChainId: hooks.findNetworkClientIdByChainId, + }); - if (chainId) { - chainIdsForNetworksAdded.push(chainId); - } - }), + if (chainId) { + chainIdsForNetworksAdded.push(chainId); + } + }, + ), ); hooks.grantPermissions({ diff --git a/package.json b/package.json index 84218da165e1..1baac817e7f4 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,7 @@ "attributions:generate": "./development/generate-attributions.sh" }, "resolutions": { - "@metamask/controller-utils": "npm:@metamask-previews/controller-utils@11.3.0-preview-ead2f439", + "@metamask/controller-utils": "npm:@metamask-previews/controller-utils@11.3.0-preview-e34032be", "chokidar": "^3.6.0", "gridplus-sdk": "~2.6.0", "gridplus-sdk/secp256k1": "^5.0.1", @@ -345,7 +345,7 @@ "@metamask/message-manager": "^10.1.0", "@metamask/message-signing-snap": "^0.4.0", "@metamask/metamask-eth-abis": "^3.1.1", - "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-ead2f439", + "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-e34032be", "@metamask/name-controller": "^8.0.0", "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A21.0.0#~/.yarn/patches/@metamask-network-controller-npm-21.0.0-559aa8e395.patch", "@metamask/notification-controller": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index 94412e411a64..772e0a2ab29c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4987,9 +4987,9 @@ __metadata: languageName: node linkType: hard -"@metamask/controller-utils@npm:@metamask-previews/controller-utils@11.3.0-preview-ead2f439": - version: 11.3.0-preview-ead2f439 - resolution: "@metamask-previews/controller-utils@npm:11.3.0-preview-ead2f439" +"@metamask/controller-utils@npm:@metamask-previews/controller-utils@11.3.0-preview-e34032be": + version: 11.3.0-preview-e34032be + resolution: "@metamask-previews/controller-utils@npm:11.3.0-preview-e34032be" dependencies: "@ethereumjs/util": "npm:^8.1.0" "@metamask/eth-query": "npm:^4.0.0" @@ -5000,7 +5000,7 @@ __metadata: bn.js: "npm:^5.2.1" eth-ens-namehash: "npm:^2.0.8" fast-deep-equal: "npm:^3.1.3" - checksum: 10/14b0e1f5a3cc2e103735ec4c050301187a6b75cf90778cd1505ccc4682c7a0f7d6abe0e59b677b34f3f052875b02abfc3ce01fc78ca015956ee36a1f749072e8 + checksum: 10/dda56ae95951e049b848a2378253bae9d936b7a9c665abeb2ef45a17060364f04b3ef1e1820d7934597472a406ec61aaf82169dce1a7932efb3e9510fac76053 languageName: node linkType: hard @@ -5718,9 +5718,9 @@ __metadata: languageName: node linkType: hard -"@metamask/multichain@npm:@metamask-previews/multichain@0.0.0-preview-ead2f439": - version: 0.0.0-preview-ead2f439 - resolution: "@metamask-previews/multichain@npm:0.0.0-preview-ead2f439" +"@metamask/multichain@npm:@metamask-previews/multichain@0.0.0-preview-e34032be": + version: 0.0.0-preview-e34032be + resolution: "@metamask-previews/multichain@npm:0.0.0-preview-e34032be" dependencies: "@metamask/api-specs": "npm:^0.10.12" "@metamask/controller-utils": "npm:^11.3.0" @@ -5734,7 +5734,7 @@ __metadata: peerDependencies: "@metamask/network-controller": ^21.0.0 "@metamask/permission-controller": ^11.0.0 - checksum: 10/d11ab3f5f38a4cb89ba6e90efa038aeb6f480366a83020acd52cb194fdf7c6915f61fe68091b58cba0840928f0c36cc2442f0f0d9e2eaf4a7bfef55fd169b36c + checksum: 10/29cd358bb9c5bd822962b5c1980ac696d720e0f7520506c6580e36f75a8a9582baacb0fc571e6850c57c38d45c0bd75c5ceec12c15fbc6e30f9a4c61aa53784a languageName: node linkType: hard @@ -26030,7 +26030,7 @@ __metadata: "@metamask/message-manager": "npm:^10.1.0" "@metamask/message-signing-snap": "npm:^0.4.0" "@metamask/metamask-eth-abis": "npm:^3.1.1" - "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-ead2f439" + "@metamask/multichain": "npm:@metamask-previews/multichain@0.0.0-preview-e34032be" "@metamask/name-controller": "npm:^8.0.0" "@metamask/network-controller": "patch:@metamask/network-controller@npm%3A21.0.0#~/.yarn/patches/@metamask-network-controller-npm-21.0.0-559aa8e395.patch" "@metamask/notification-controller": "npm:^6.0.0"