|
| 1 | +import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; |
| 2 | +import { PermissionConstraint, RequestedPermissions } from '@metamask/permission-controller'; |
| 3 | +import { hasProperty, type Json, type JsonRpcParams } from '@metamask/utils'; |
| 4 | +import { SnapEndowments } from '../endowments'; |
| 5 | +import { isEqual } from '@metamask/snaps-utils'; |
| 6 | + |
| 7 | +export interface PreinstalledSnapsMiddlewareHooks { |
| 8 | + getPermittedEvmAccounts: () => string[]; |
| 9 | + getAllEvmAccounts: () => string[]; |
| 10 | + getPermissions: () => Record<string, PermissionConstraint> | undefined; |
| 11 | + grantPermissions: (permissions: RequestedPermissions) => void; |
| 12 | +} |
| 13 | + |
| 14 | +/** |
| 15 | + * Creates a middleware that automatically grants permissions to preinstalled Snaps |
| 16 | + * that want to use the Ethereum provider endowment. |
| 17 | + * |
| 18 | + * @param hooks - The hooks used by the middleware. |
| 19 | + * @returns The middleware. |
| 20 | + */ |
| 21 | +export function createPreinstalledSnapsMiddleware( |
| 22 | + { getPermittedEvmAccounts, getAllEvmAccounts, getPermissions, grantPermissions }: PreinstalledSnapsMiddlewareHooks, |
| 23 | +): JsonRpcMiddleware<JsonRpcParams, Json> { |
| 24 | + return function methodMiddleware(request, _response, next, _end) { |
| 25 | + if (!request.method.startsWith("wallet") && !request.method.startsWith("eth")) { |
| 26 | + return next(); |
| 27 | + } |
| 28 | + |
| 29 | + const permissions = getPermissions(); |
| 30 | + |
| 31 | + if (!permissions || !hasProperty(permissions, SnapEndowments.EthereumProvider)) { |
| 32 | + return next(); |
| 33 | + } |
| 34 | + |
| 35 | + const evmAccounts = getAllEvmAccounts(); |
| 36 | + const existingEvmAccounts = getPermittedEvmAccounts(); |
| 37 | + |
| 38 | + if (isEqual(evmAccounts, existingEvmAccounts)) { |
| 39 | + return next(); |
| 40 | + } |
| 41 | + |
| 42 | + grantPermissions({ |
| 43 | + 'endowment:caip25': { |
| 44 | + caveats: [ |
| 45 | + { |
| 46 | + type: 'authorizedScopes', |
| 47 | + value: { |
| 48 | + requiredScopes: {}, |
| 49 | + optionalScopes: { |
| 50 | + 'wallet:eip155': { |
| 51 | + accounts: evmAccounts.map(account => `wallet:eip155:${account}`), |
| 52 | + }, |
| 53 | + }, |
| 54 | + sessionProperties: {}, |
| 55 | + isMultichainOrigin: false, |
| 56 | + }, |
| 57 | + }, |
| 58 | + ], |
| 59 | + }, |
| 60 | + }); |
| 61 | + |
| 62 | + return next(); |
| 63 | + }; |
| 64 | +} |
0 commit comments