From 8882ca60812168785d3ecef68095f4daded7a77c Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 29 Apr 2026 14:01:49 +0200 Subject: [PATCH 1/3] fix: Stop relying on account metadata for MultichainRoutingService --- .../MultichainRoutingService.test.ts | 51 ++++++++++++++++++- .../multichain/MultichainRoutingService.ts | 43 +++++++++------- .../src/test-utils/multichain.ts | 4 -- packages/snaps-utils/src/account.ts | 2 +- 4 files changed, 77 insertions(+), 23 deletions(-) diff --git a/packages/snaps-controllers/src/multichain/MultichainRoutingService.test.ts b/packages/snaps-controllers/src/multichain/MultichainRoutingService.test.ts index bbdb8d374f..d6faa252ac 100644 --- a/packages/snaps-controllers/src/multichain/MultichainRoutingService.test.ts +++ b/packages/snaps-controllers/src/multichain/MultichainRoutingService.test.ts @@ -37,6 +37,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'AccountsController:listMultichainAccounts', () => MOCK_BTC_ACCOUNTS, @@ -90,6 +97,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'AccountsController:listMultichainAccounts', () => MOCK_SOLANA_ACCOUNTS, @@ -142,6 +156,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'AccountsController:listMultichainAccounts', () => MOCK_SOLANA_ACCOUNTS, @@ -231,7 +252,7 @@ describe('MultichainRoutingService', () => { }); expect(messenger.call).toHaveBeenNthCalledWith( - 5, + 6, 'SnapController:handleRequest', { snapId: MOCK_SNAP_ID, @@ -302,6 +323,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'SnapController:handleRequest', async ({ handler }) => { @@ -352,6 +380,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'SnapController:handleRequest', async ({ handler }) => { @@ -405,6 +440,13 @@ describe('MultichainRoutingService', () => { withSnapKeyring, }); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + rootMessenger.registerActionHandler( 'SnapController:handleRequest', async ({ handler }) => { @@ -577,6 +619,13 @@ describe('MultichainRoutingService', () => { () => MOCK_SOLANA_ACCOUNTS, ); + rootMessenger.registerActionHandler( + 'SnapController:getRunnableSnaps', + () => { + return [getTruncatedSnap()]; + }, + ); + expect( messenger.call( 'MultichainRoutingService:getSupportedAccounts', diff --git a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts index 8140a36bd6..dd248fd057 100644 --- a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts +++ b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts @@ -166,17 +166,7 @@ export class MultichainRoutingService { scope: CaipChainId, request: JsonRpcRequest, ) { - const accounts = this.#messenger - .call('AccountsController:listMultichainAccounts', scope) - .filter( - ( - account: InternalAccount, - ): account is InternalAccount & { - metadata: Required; - } => - Boolean(account.metadata.snap?.enabled) && - account.methods.includes(request.method), - ); + const accounts = this.#getSupportedAccountsMetadata(scope, request.method); // If no accounts can service the request, return null. if (accounts.length === 0) { @@ -349,12 +339,31 @@ export class MultichainRoutingService { * Get a list of metadata for supported accounts for a given scope from the client. * * @param scope - The CAIP-2 scope. + * @param method - An optional method that the account should support. * @returns A list of metadata for the supported accounts. */ - #getSupportedAccountsMetadata(scope: CaipChainId): InternalAccount[] { + #getSupportedAccountsMetadata( + scope: CaipChainId, + method?: string, + ): (InternalAccount & { + metadata: Required; + })[] { + const runnableSnaps = this.#messenger + .call('SnapController:getRunnableSnaps') + .map((snap) => snap.id); return this.#messenger .call('AccountsController:listMultichainAccounts', scope) - .filter((account: InternalAccount) => account.metadata.snap?.enabled); + .filter( + ( + account: InternalAccount, + ): account is InternalAccount & { + metadata: Required; + } => + account.metadata.snap?.id !== undefined && + runnableSnaps.includes(account.metadata.snap?.id) && + ((method !== undefined && account.methods.includes(method)) || + method === undefined), + ); } /** @@ -395,10 +404,10 @@ export class MultichainRoutingService { * @returns True if the router can service the scope, otherwise false. */ isSupportedScope(scope: CaipChainId): boolean { - const hasAccountSnap = this.#messenger - .call('AccountsController:listMultichainAccounts', scope) - .some((account: InternalAccount) => account.metadata.snap?.enabled); // We currently assume here that if one Snap exists that service the scope, we can service the scope generally. - return hasAccountSnap || this.#getProtocolSnaps(scope).length > 0; + return ( + this.#getSupportedAccountsMetadata(scope).length > 0 || + this.#getProtocolSnaps(scope).length > 0 + ); } } diff --git a/packages/snaps-controllers/src/test-utils/multichain.ts b/packages/snaps-controllers/src/test-utils/multichain.ts index 8bac8bf167..5cf815ec9f 100644 --- a/packages/snaps-controllers/src/test-utils/multichain.ts +++ b/packages/snaps-controllers/src/test-utils/multichain.ts @@ -22,9 +22,7 @@ export const MOCK_BTC_ACCOUNTS = [ lastSelected: 1729154128902, name: 'Bitcoin Account', snap: { - enabled: true, id: MOCK_SNAP_ID, - name: 'Bitcoin', }, }, methods: ['sendBitcoin'], @@ -50,9 +48,7 @@ export const MOCK_SOLANA_ACCOUNTS = [ lastSelected: 1729154128902, name: 'Solana Account', snap: { - enabled: true, id: MOCK_SNAP_ID, - name: 'Solana', }, }, methods: ['signAndSendTransaction'], diff --git a/packages/snaps-utils/src/account.ts b/packages/snaps-utils/src/account.ts index ea55a18a22..c2da0a6e15 100644 --- a/packages/snaps-utils/src/account.ts +++ b/packages/snaps-utils/src/account.ts @@ -15,7 +15,7 @@ export type InternalAccount = { scopes: CaipChainId[]; metadata: { name: string; - snap?: { id: SnapId; enabled: boolean; name: string }; + snap?: { id: SnapId }; }; }; From 6e2dc80e9b212b5be27d1b9131c9d2278c93c8a8 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 29 Apr 2026 14:12:32 +0200 Subject: [PATCH 2/3] Flip condition --- .../src/multichain/MultichainRoutingService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts index dd248fd057..461583a60d 100644 --- a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts +++ b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts @@ -361,8 +361,7 @@ export class MultichainRoutingService { } => account.metadata.snap?.id !== undefined && runnableSnaps.includes(account.metadata.snap?.id) && - ((method !== undefined && account.methods.includes(method)) || - method === undefined), + (method === undefined || account.methods.includes(method)), ); } From a5425d0ddf0cbf768304f42511a2c3fa5458d352 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 29 Apr 2026 14:13:35 +0200 Subject: [PATCH 3/3] Add newline --- .../snaps-controllers/src/multichain/MultichainRoutingService.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts index 461583a60d..533eb53730 100644 --- a/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts +++ b/packages/snaps-controllers/src/multichain/MultichainRoutingService.ts @@ -351,6 +351,7 @@ export class MultichainRoutingService { const runnableSnaps = this.#messenger .call('SnapController:getRunnableSnaps') .map((snap) => snap.id); + return this.#messenger .call('AccountsController:listMultichainAccounts', scope) .filter(