From 53fe6f158110c6eb9c20a8a9719171ca5748a176 Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Wed, 26 Aug 2026 15:52:48 +0200 Subject: [PATCH 1/2] feat(solana-wallet-snap): use shareable permissions helepers in Solana snap --- eslint-suppressions.json | 5 +- .../src/core/validation/validators.ts | 12 --- packages/solana-wallet-snap/src/index.ts | 7 +- .../solana-wallet-snap/src/permissions.ts | 86 +++++++++---------- 4 files changed, 46 insertions(+), 64 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index c178c43f8..76836683d 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -1034,9 +1034,6 @@ "packages/solana-wallet-snap/src/core/validation/validators.ts": { "@typescript-eslint/no-explicit-any": { "count": 3 - }, - "@typescript-eslint/only-throw-error": { - "count": 2 } }, "packages/solana-wallet-snap/src/entities/instructions/instructions.ts": { @@ -1823,4 +1820,4 @@ "count": 2 } } -} +} \ No newline at end of file diff --git a/packages/solana-wallet-snap/src/core/validation/validators.ts b/packages/solana-wallet-snap/src/core/validation/validators.ts index 4084c8c36..8c423d6f2 100644 --- a/packages/solana-wallet-snap/src/core/validation/validators.ts +++ b/packages/solana-wallet-snap/src/core/validation/validators.ts @@ -2,22 +2,10 @@ import { getJsonError, InvalidParamsError, SnapError, - UnauthorizedError, } from '@metamask/snaps-sdk'; import type { Infer, Struct } from '@metamask/superstruct'; import { assert } from '@metamask/superstruct'; -import { originPermissions } from '../../permissions'; - -export const validateOrigin = (origin: string, method: string): void => { - if (!origin) { - throw new UnauthorizedError('Origin not found'); - } - if (!originPermissions.get(origin)?.has(method)) { - throw new UnauthorizedError('Permission denied'); - } -}; - /** * Validates that the request parameters conform to the expected structure defined by the provided struct. * diff --git a/packages/solana-wallet-snap/src/index.ts b/packages/solana-wallet-snap/src/index.ts index 194addacf..c498accb7 100644 --- a/packages/solana-wallet-snap/src/index.ts +++ b/packages/solana-wallet-snap/src/index.ts @@ -1,5 +1,6 @@ import { KeyringRpcMethod } from '@metamask/keyring-api'; import { handleKeyringRequest } from '@metamask/keyring-snap-sdk/v2'; +import { validateOrigin } from '@metamask/snap-networks-utils'; import { MethodNotFoundError } from '@metamask/snaps-sdk'; import type { Json, @@ -36,10 +37,10 @@ import { onProtocolRequest as onProtocolRequestHandler } from './core/handlers/o import { handlers as onRpcRequestHandlers } from './core/handlers/onRpcRequest'; import { withCatchAndThrowSnapError } from './core/utils/errors'; import logger from './core/utils/logger'; -import { validateOrigin } from './core/validation/validators'; import { eventHandlers as confirmSignInEvents } from './features/confirmation/views/ConfirmSignIn/events'; import { eventHandlers as confirmSignMessageEvents } from './features/confirmation/views/ConfirmSignMessage/events'; import { eventHandlers as confirmSignAndSendTransactionEvents } from './features/confirmation/views/ConfirmTransactionRequest/events'; +import { originPermissions } from './permissions'; import { installPolyfills } from './polyfills'; import snapContext, { clientRequestHandler, @@ -70,7 +71,7 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ const { method } = request; - validateOrigin(origin, method); + validateOrigin(origin, method, originPermissions); const handler = onRpcRequestHandlers[method]; @@ -105,7 +106,7 @@ export const onKeyringRequest: OnKeyringRequestHandler = async ({ }): Promise => { logger.log('[🔑 onKeyringRequest]', request.method, request); - validateOrigin(origin, request.method); + validateOrigin(origin, request.method, originPermissions); // This is a temporal fix to prevent the swap/bridge functionality breaking // TODO: Remove this once changes in bridge-status-controller are in place diff --git a/packages/solana-wallet-snap/src/permissions.ts b/packages/solana-wallet-snap/src/permissions.ts index 7636a0f4f..68cbdbeec 100644 --- a/packages/solana-wallet-snap/src/permissions.ts +++ b/packages/solana-wallet-snap/src/permissions.ts @@ -1,50 +1,49 @@ import { KeyringRpcMethod } from '@metamask/keyring-api'; import { KeyringSnapRpcMethod } from '@metamask/keyring-api/v2'; +import { + createOriginPermissions, + DEFAULT_DEV_ORIGINS, + DEFAULT_PROD_ORIGINS, +} from '@metamask/snap-networks-utils'; import { ClientRequestMethod } from './core/handlers/onClientRequest'; import { TestDappRpcRequestMethod } from './core/handlers/onRpcRequest/types'; import { ConfigProvider } from './core/services/config/ConfigProvider'; -const prodOrigins = ['https://portfolio.metamask.io']; - const config = new ConfigProvider().get(); const isDev = ['local', 'test'].includes(config.environment); -const allowedOrigins = isDev ? ['http://localhost:3000'] : prodOrigins; - -const dappPermissions = isDev - ? new Set([ - // Keyring v2 methods - KeyringSnapRpcMethod.GetAccounts, - KeyringSnapRpcMethod.GetAccount, - KeyringSnapRpcMethod.DeleteAccount, - KeyringSnapRpcMethod.GetAccountBalances, - KeyringSnapRpcMethod.SubmitRequest, - KeyringSnapRpcMethod.GetAccountTransactions, - KeyringSnapRpcMethod.GetAccountAssets, - KeyringSnapRpcMethod.SetSelectedAccounts, - // Keyring v1 methods kept for backwards compatibility — callers using - // old method names are still accepted by the permission layer. - KeyringRpcMethod.ListAccounts, - KeyringRpcMethod.CreateAccount, - KeyringRpcMethod.FilterAccountChains, - KeyringRpcMethod.DiscoverAccounts, - KeyringRpcMethod.ListAccountTransactions, - KeyringRpcMethod.ListAccountAssets, - // Methods specific to the test dapp - TestDappRpcRequestMethod.ListWebSockets, - TestDappRpcRequestMethod.ListSubscriptions, - TestDappRpcRequestMethod.TestOnStart, - TestDappRpcRequestMethod.TestOnInstall, - TestDappRpcRequestMethod.TestOnUpdate, - TestDappRpcRequestMethod.SynchronizeAccounts, - TestDappRpcRequestMethod.SetAccountSelected, - TestDappRpcRequestMethod.ConfirmSend, - TestDappRpcRequestMethod.SignRewardsMessage, - ]) - : new Set([]); +const dappMethods = [ + // Keyring v2 methods + KeyringSnapRpcMethod.GetAccounts, + KeyringSnapRpcMethod.GetAccount, + KeyringSnapRpcMethod.DeleteAccount, + KeyringSnapRpcMethod.GetAccountBalances, + KeyringSnapRpcMethod.SubmitRequest, + KeyringSnapRpcMethod.GetAccountTransactions, + KeyringSnapRpcMethod.GetAccountAssets, + KeyringSnapRpcMethod.SetSelectedAccounts, + // Keyring v1 methods kept for backwards compatibility — callers using + // old method names are still accepted by the permission layer. + KeyringRpcMethod.ListAccounts, + KeyringRpcMethod.CreateAccount, + KeyringRpcMethod.FilterAccountChains, + KeyringRpcMethod.DiscoverAccounts, + KeyringRpcMethod.ListAccountTransactions, + KeyringRpcMethod.ListAccountAssets, + // Methods specific to the test dapp + TestDappRpcRequestMethod.ListWebSockets, + TestDappRpcRequestMethod.ListSubscriptions, + TestDappRpcRequestMethod.TestOnStart, + TestDappRpcRequestMethod.TestOnInstall, + TestDappRpcRequestMethod.TestOnUpdate, + TestDappRpcRequestMethod.SynchronizeAccounts, + TestDappRpcRequestMethod.SetAccountSelected, + TestDappRpcRequestMethod.ConfirmSend, + TestDappRpcRequestMethod.SignRewardsMessage, +]; -const metamaskPermissions = new Set([ +const metamaskMethods = [ // Keyring v2 methods KeyringSnapRpcMethod.GetAccounts, KeyringSnapRpcMethod.GetAccount, @@ -67,13 +66,10 @@ const metamaskPermissions = new Set([ // Client methods ClientRequestMethod.SignAndSendTransactionWithoutConfirmation, ClientRequestMethod.SignProofOfOwnership, -]); - -const metamask = 'metamask'; - -export const originPermissions = new Map>([]); +]; -for (const origin of allowedOrigins) { - originPermissions.set(origin, dappPermissions); -} -originPermissions.set(metamask, metamaskPermissions); +export const originPermissions = createOriginPermissions({ + dappMethods: isDev ? dappMethods : [], + metamaskMethods, + origins: isDev ? DEFAULT_DEV_ORIGINS : DEFAULT_PROD_ORIGINS, +}); From 0897653c9e1792e97ee22b252aa76e3e5bc48b98 Mon Sep 17 00:00:00 2001 From: Julien Fontanel Date: Wed, 26 Aug 2026 16:39:25 +0200 Subject: [PATCH 2/2] fix: shasum + lint --- eslint-suppressions.json | 2 +- packages/solana-wallet-snap/snap.manifest.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 76836683d..f95381c04 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -1820,4 +1820,4 @@ "count": 2 } } -} \ No newline at end of file +} diff --git a/packages/solana-wallet-snap/snap.manifest.json b/packages/solana-wallet-snap/snap.manifest.json index e527789b0..72533ac68 100644 --- a/packages/solana-wallet-snap/snap.manifest.json +++ b/packages/solana-wallet-snap/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/internal-snaps.git" }, "source": { - "shasum": "mmsPn3F/291/s6sb7cq9t9PbNYFCSk26kQ9bIpw54r8=", + "shasum": "5kNtwtBEH5sTzUllGtgXdv0fTfHEdVplRb3DAOgLMd0=", "location": { "npm": { "filePath": "dist/bundle.js",