Skip to content

Commit

Permalink
Add isSupportedScope
Browse files Browse the repository at this point in the history
  • Loading branch information
FrederikBolding committed Jan 20, 2025
1 parent da4b464 commit d920440
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 29 deletions.
4 changes: 2 additions & 2 deletions packages/snaps-controllers/coverage.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"branches": 93.16,
"functions": 96.73,
"lines": 98.11,
"functions": 96.76,
"lines": 98.12,
"statements": 97.84
}
67 changes: 47 additions & 20 deletions packages/snaps-controllers/src/multichain/MultichainRouter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,9 +297,7 @@ describe('MultichainRouter', () => {
);

expect(
messenger.call('MultichainRouter:getSupportedMethods', {
scope: SOLANA_CAIP2,
}),
messenger.call('MultichainRouter:getSupportedMethods', SOLANA_CAIP2),
).toStrictEqual(['signAndSendTransaction', 'getVersion']);
});

Expand Down Expand Up @@ -329,9 +327,7 @@ describe('MultichainRouter', () => {
);

expect(
messenger.call('MultichainRouter:getSupportedMethods', {
scope: SOLANA_CAIP2,
}),
messenger.call('MultichainRouter:getSupportedMethods', SOLANA_CAIP2),
).toStrictEqual(['signAndSendTransaction']);
});

Expand Down Expand Up @@ -361,15 +357,13 @@ describe('MultichainRouter', () => {
);

expect(
messenger.call('MultichainRouter:getSupportedMethods', {
scope: SOLANA_CAIP2,
}),
messenger.call('MultichainRouter:getSupportedMethods', SOLANA_CAIP2),
).toStrictEqual(['getVersion']);
});
});

describe('getSupportedAccounts', () => {
it('returns a set of both protocol and account Snap methods', async () => {
it('returns a set of accounts for the requested scope', async () => {
const rootMessenger = getRootMultichainRouterMessenger();
const messenger = getRestrictedMultichainRouterMessenger(rootMessenger);
const withSnapKeyring = getMockWithSnapKeyring();
Expand All @@ -380,27 +374,60 @@ describe('MultichainRouter', () => {
withSnapKeyring,
});

rootMessenger.registerActionHandler('SnapController:getAll', () => {
return [getTruncatedSnap()];
rootMessenger.registerActionHandler(
'AccountsController:listMultichainAccounts',
() => MOCK_SOLANA_ACCOUNTS,
);

expect(
messenger.call('MultichainRouter:getSupportedAccounts', SOLANA_CAIP2),
).toStrictEqual([
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv',
]);
});
});

describe('isSupportedScope', () => {
it('returns true if an account Snap exists', async () => {
const rootMessenger = getRootMultichainRouterMessenger();
const messenger = getRestrictedMultichainRouterMessenger(rootMessenger);
const withSnapKeyring = getMockWithSnapKeyring();

/* eslint-disable-next-line no-new */
new MultichainRouter({
messenger,
withSnapKeyring,
});

rootMessenger.registerActionHandler(
'AccountsController:listMultichainAccounts',
() => MOCK_SOLANA_ACCOUNTS,
);

expect(
messenger.call('MultichainRouter:isSupportedScope', SOLANA_CAIP2),
).toBe(true);
});

it('returns false if no account Snap is found', async () => {
const rootMessenger = getRootMultichainRouterMessenger();
const messenger = getRestrictedMultichainRouterMessenger(rootMessenger);
const withSnapKeyring = getMockWithSnapKeyring();

/* eslint-disable-next-line no-new */
new MultichainRouter({
messenger,
withSnapKeyring,
});

rootMessenger.registerActionHandler(
'PermissionController:getPermissions',
() => MOCK_SOLANA_SNAP_PERMISSIONS,
'AccountsController:listMultichainAccounts',
() => [],
);

expect(
messenger.call('MultichainRouter:getSupportedAccounts', {
scope: SOLANA_CAIP2,
}),
).toStrictEqual([
'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp:7S3P4HxJpyyigGzodYwHtCxZyUQe9JiBMHyRWXArAaKv',
]);
messenger.call('MultichainRouter:isSupportedScope', SOLANA_CAIP2),
).toBe(false);
});
});
});
36 changes: 29 additions & 7 deletions packages/snaps-controllers/src/multichain/MultichainRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ export type MultichainRouterGetSupportedAccountsAction = {
handler: MultichainRouter['getSupportedAccounts'];
};

export type MultichainRouterIsSupportedScopeAction = {
type: `${typeof name}:isSupportedScope`;
handler: MultichainRouter['isSupportedScope'];
};

// Since the AccountsController depends on snaps-controllers we manually type this
type InternalAccount = {
id: string;
Expand Down Expand Up @@ -68,7 +73,8 @@ export type AccountsControllerListMultichainAccountsAction = {
export type MultichainRouterActions =
| MultichainRouterHandleRequestAction
| MultichainRouterGetSupportedMethodsAction
| MultichainRouterGetSupportedAccountsAction;
| MultichainRouterGetSupportedAccountsAction
| MultichainRouterIsSupportedScopeAction;

export type MultichainRouterAllowedActions =
| GetAllSnaps
Expand Down Expand Up @@ -121,6 +127,11 @@ export class MultichainRouter {
`${name}:getSupportedAccounts`,
(...args) => this.getSupportedAccounts(...args),
);

this.#messenger.registerActionHandler(
`${name}:isSupportedScope`,
(...args) => this.isSupportedScope(...args),
);
}

async #resolveRequestAddress(
Expand Down Expand Up @@ -294,11 +305,10 @@ export class MultichainRouter {
* Get a list of supported methods for a given scope.
* This combines both protocol and account Snaps supported methods.
*
* @param options - An options bag.
* @param options.scope - The CAIP-2 scope.
* @param scope - The CAIP-2 scope.
* @returns A list of supported methods.
*/
getSupportedMethods({ scope }: { scope: CaipChainId }): string[] {
getSupportedMethods(scope: CaipChainId): string[] {
const accountMethods = this.#messenger
.call('AccountsController:listMultichainAccounts', scope)
.filter((account: InternalAccount) => account.metadata.snap?.enabled)
Expand All @@ -314,14 +324,26 @@ export class MultichainRouter {
/**
* Get a list of supported accounts for a given scope.
*
* @param options - An options bag.
* @param options.scope - The CAIP-2 scope.
* @param scope - The CAIP-2 scope.
* @returns A list of CAIP-10 addresses.
*/
getSupportedAccounts({ scope }: { scope: CaipChainId }): string[] {
getSupportedAccounts(scope: CaipChainId): string[] {
return this.#messenger
.call('AccountsController:listMultichainAccounts', scope)
.filter((account: InternalAccount) => account.metadata.snap?.enabled)
.map((account) => `${scope}:${account.address}`);
}

/**
* Determine whether a given CAIP-2 scope is supported by the router.
*
* @param scope - The CAIP-2 scope.
* @returns True if the router can service the scope, otherwise false.
*/
isSupportedScope(scope: CaipChainId): boolean {
// We currently assume here that if one Snap exists that service the scope, we can service the scope generally.
return this.#messenger
.call('AccountsController:listMultichainAccounts', scope)
.some((account: InternalAccount) => account.metadata.snap?.enabled);
}
}

0 comments on commit d920440

Please sign in to comment.