@metamask/snaps-controllers 12.1.0 → 12.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -1
- package/dist/multichain/MultichainRouter.cjs +1 -0
- package/dist/multichain/MultichainRouter.cjs.map +1 -1
- package/dist/multichain/MultichainRouter.d.cts +1 -0
- package/dist/multichain/MultichainRouter.d.cts.map +1 -1
- package/dist/multichain/MultichainRouter.d.mts +1 -0
- package/dist/multichain/MultichainRouter.d.mts.map +1 -1
- package/dist/multichain/MultichainRouter.mjs +1 -0
- package/dist/multichain/MultichainRouter.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +17 -0
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +15 -2
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +15 -2
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +18 -1
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [12.2.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add `isMinimumPlatformVersion` action ([#3405](https://github.com/MetaMask/snaps/pull/3405))
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Pass origin to `SnapKeyring` via `MultichainRouter` ([#3403](https://github.com/MetaMask/snaps/pull/3403))
|
|
19
|
+
|
|
10
20
|
## [12.1.0]
|
|
11
21
|
|
|
12
22
|
### Added
|
|
@@ -756,7 +766,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
756
766
|
- The version of the package no longer needs to match the version of all other
|
|
757
767
|
MetaMask Snaps packages.
|
|
758
768
|
|
|
759
|
-
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.
|
|
769
|
+
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.2.0...HEAD
|
|
770
|
+
[12.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.1.0...@metamask/snaps-controllers@12.2.0
|
|
760
771
|
[12.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.0.1...@metamask/snaps-controllers@12.1.0
|
|
761
772
|
[12.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.0.0...@metamask/snaps-controllers@12.0.1
|
|
762
773
|
[12.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@11.2.3...@metamask/snaps-controllers@12.0.0
|
|
@@ -65,6 +65,7 @@ class MultichainRouter {
|
|
|
65
65
|
const accountId = await __classPrivateFieldGet(this, _MultichainRouter_instances, "m", _MultichainRouter_getSnapAccountId).call(this, connectedAddresses, scope, request);
|
|
66
66
|
if (accountId) {
|
|
67
67
|
return __classPrivateFieldGet(this, _MultichainRouter_withSnapKeyring, "f").call(this, async ({ keyring }) => keyring.submitRequest({
|
|
68
|
+
origin,
|
|
68
69
|
account: accountId,
|
|
69
70
|
scope,
|
|
70
71
|
method,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainRouter.cjs","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedMessenger } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n getProtocolCaveatScopes,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipChainId,\n JsonRpcParams,\n} from '@metamask/utils';\nimport {\n assert,\n hasProperty,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport { getRunnableSnaps } from '../snaps';\nimport type { GetAllSnaps, HandleSnapRequest } from '../snaps';\n\nexport type MultichainRouterHandleRequestAction = {\n type: `${typeof name}:handleRequest`;\n handler: MultichainRouter['handleRequest'];\n};\n\nexport type MultichainRouterGetSupportedMethodsAction = {\n type: `${typeof name}:getSupportedMethods`;\n handler: MultichainRouter['getSupportedMethods'];\n};\n\nexport type MultichainRouterGetSupportedAccountsAction = {\n type: `${typeof name}:getSupportedAccounts`;\n handler: MultichainRouter['getSupportedAccounts'];\n};\n\nexport type MultichainRouterIsSupportedScopeAction = {\n type: `${typeof name}:isSupportedScope`;\n handler: MultichainRouter['isSupportedScope'];\n};\n\ntype SnapKeyring = {\n submitRequest: (request: {\n account: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n scope: CaipChainId;\n }) => Promise<Json>;\n resolveAccountAddress: (\n snapId: SnapId,\n scope: CaipChainId,\n request: Json,\n ) => Promise<{ address: CaipAccountId } | null>;\n};\n\n// Expecting a bound function that calls KeyringController.withKeyring selecting the Snap keyring\ntype WithSnapKeyringFunction = <ReturnType>(\n operation: ({ keyring }: { keyring: SnapKeyring }) => Promise<ReturnType>,\n) => Promise<ReturnType>;\n\nexport type AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type MultichainRouterActions =\n | MultichainRouterHandleRequestAction\n | MultichainRouterGetSupportedMethodsAction\n | MultichainRouterGetSupportedAccountsAction\n | MultichainRouterIsSupportedScopeAction;\n\nexport type MultichainRouterAllowedActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | AccountsControllerListMultichainAccountsAction;\n\nexport type MultichainRouterEvents = never;\n\nexport type MultichainRouterMessenger = RestrictedMessenger<\n typeof name,\n MultichainRouterActions | MultichainRouterAllowedActions,\n never,\n MultichainRouterAllowedActions['type'],\n MultichainRouterEvents['type']\n>;\n\nexport type MultichainRouterArgs = {\n messenger: MultichainRouterMessenger;\n withSnapKeyring: WithSnapKeyringFunction;\n};\n\ntype ProtocolSnap = {\n snapId: SnapId;\n methods: string[];\n};\n\nconst name = 'MultichainRouter';\n\nexport class MultichainRouter {\n name: typeof name = name;\n\n state = null;\n\n readonly #messenger: MultichainRouterMessenger;\n\n readonly #withSnapKeyring: WithSnapKeyringFunction;\n\n constructor({ messenger, withSnapKeyring }: MultichainRouterArgs) {\n this.#messenger = messenger;\n this.#withSnapKeyring = withSnapKeyring;\n\n this.#messenger.registerActionHandler(\n `${name}:handleRequest`,\n async (...args) => this.handleRequest(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedMethods`,\n (...args) => this.getSupportedMethods(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedAccounts`,\n (...args) => this.getSupportedAccounts(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:isSupportedScope`,\n (...args) => this.isSupportedScope(...args),\n );\n }\n\n /**\n * Attempts to resolve the account address to use for a given request by inspecting the request itself.\n *\n * The request is sent to to an account Snap via the SnapKeyring that will attempt this resolution.\n *\n * @param snapId - The ID of the Snap to send the request to.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns The resolved address if found, otherwise null.\n * @throws If the invocation of the SnapKeyring fails.\n */\n async #resolveRequestAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n try {\n const result = await this.#withSnapKeyring(async ({ keyring }) =>\n keyring.resolveAccountAddress(snapId, scope, request),\n );\n const address = result?.address;\n return address ? parseCaipAccountId(address).address : null;\n } catch {\n throw rpcErrors.internal();\n }\n }\n\n /**\n * Get the account ID of the account that should service the RPC request via an account Snap.\n *\n * This function checks whether any accounts exist that can service a given request by\n * using a combination of the resolveAccountAddress functionality and the connected accounts.\n *\n * If an account is expected to service this request but none is found, the function will throw.\n *\n * @param connectedAddresses - The CAIP-10 addresses connected to the requesting origin.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns An account ID if found, otherwise null.\n * @throws If no account is found, but the accounts exist that could service the request.\n */\n async #getSnapAccountId(\n connectedAddresses: CaipAccountId[],\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n const accounts = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter(\n (\n account: InternalAccount,\n ): account is InternalAccount & {\n metadata: Required<InternalAccount['metadata']>;\n } =>\n Boolean(account.metadata.snap?.enabled) &&\n account.methods.includes(request.method),\n );\n\n // If no accounts can service the request, return null.\n if (accounts.length === 0) {\n return null;\n }\n\n const resolutionSnapId = accounts[0].metadata.snap.id;\n\n // Attempt to resolve the address that should be used for signing.\n const address = await this.#resolveRequestAddress(\n resolutionSnapId,\n scope,\n request,\n );\n\n const parsedConnectedAddresses = connectedAddresses.map(\n (connectedAddress) => parseCaipAccountId(connectedAddress).address,\n );\n\n // If we have a resolved address, try to find the selected account based on that\n // otherwise, default to one of the connected accounts.\n // TODO: Eventually let the user choose if we have more than one option for the account.\n const selectedAccount = accounts.find(\n (account) =>\n parsedConnectedAddresses.includes(account.address) &&\n (!address || account.address === address),\n );\n\n if (!selectedAccount) {\n throw rpcErrors.invalidParams({\n message: 'No available account found for request.',\n });\n }\n\n return selectedAccount.id;\n }\n\n /**\n * Get all protocol Snaps that can service a given CAIP-2 scope.\n *\n * Protocol Snaps are deemed fit to service a scope if they are runnable\n * and have the proper permissions set for the scope.\n *\n * @param scope - A CAIP-2 scope.\n * @returns A list of all the protocol Snaps available and their RPC methods.\n */\n #getProtocolSnaps(scope: CaipChainId) {\n const allSnaps = this.#messenger.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(allSnaps);\n\n return filteredSnaps.reduce<ProtocolSnap[]>((accumulator, snap) => {\n const permissions = this.#messenger.call(\n 'PermissionController:getPermissions',\n snap.id,\n );\n\n if (permissions && hasProperty(permissions, SnapEndowments.Protocol)) {\n const permission = permissions[SnapEndowments.Protocol];\n const scopes = getProtocolCaveatScopes(permission);\n if (scopes && hasProperty(scopes, scope)) {\n accumulator.push({\n snapId: snap.id,\n methods: scopes[scope].methods,\n });\n }\n }\n\n return accumulator;\n }, []);\n }\n\n /**\n * Handle an incoming JSON-RPC request tied to a specific scope by routing\n * to either a procotol Snap or an account Snap.\n *\n * Note: Addresses are considered case sensitive by the MultichainRouter as\n * not all non-EVM chains are case insensitive.\n *\n * @param options - An options bag.\n * @param options.connectedAddresses - Addresses currently connected to the origin.\n * @param options.origin - The origin of the RPC request.\n * @param options.request - The JSON-RPC request.\n * @param options.scope - The CAIP-2 scope for the request.\n * @returns The response from the chosen Snap.\n * @throws If no handler was found.\n */\n async handleRequest({\n connectedAddresses,\n origin,\n scope,\n request: rawRequest,\n }: {\n connectedAddresses: CaipAccountId[];\n origin: string;\n scope: CaipChainId;\n request: JsonRpcRequest;\n }): Promise<Json> {\n // Explicitly block EVM scopes, just in case.\n assert(\n !scope.startsWith(KnownCaipNamespace.Eip155) &&\n !scope.startsWith('wallet:eip155'),\n );\n\n // Re-create the request to simplify and remove additional properties that may be present in MM middleware.\n const request = {\n jsonrpc: '2.0' as const,\n id: rawRequest.id ?? nanoid(),\n method: rawRequest.method,\n ...(rawRequest.params ? { params: rawRequest.params } : {}),\n };\n\n const { method, params } = request;\n\n // If the RPC request can be serviced by an account Snap, route it there.\n const accountId = await this.#getSnapAccountId(\n connectedAddresses,\n scope,\n request,\n );\n\n if (accountId) {\n return this.#withSnapKeyring(async ({ keyring }) =>\n keyring.submitRequest({\n account: accountId,\n scope,\n method,\n params: params as JsonRpcParams,\n }),\n );\n }\n\n // If the RPC request cannot be serviced by an account Snap,\n // but has a protocol Snap available, route it there.\n const protocolSnaps = this.#getProtocolSnaps(scope);\n const protocolSnap = protocolSnaps.find((snap) =>\n snap.methods.includes(method),\n );\n\n if (protocolSnap) {\n return this.#messenger.call('SnapController:handleRequest', {\n snapId: protocolSnap.snapId,\n origin,\n request: {\n method: '',\n params: {\n request,\n scope,\n },\n },\n handler: HandlerType.OnProtocolRequest,\n }) as Promise<Json>;\n }\n\n // If no compatible account or protocol Snaps were found, throw.\n throw rpcErrors.methodNotFound();\n }\n\n /**\n * Get a list of metadata for supported accounts for a given scope from the client.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of metadata for the supported accounts.\n */\n #getSupportedAccountsMetadata(scope: CaipChainId): InternalAccount[] {\n return this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter((account: InternalAccount) => account.metadata.snap?.enabled);\n }\n\n /**\n * Get a list of supported methods for a given scope.\n * This combines both protocol and account Snaps supported methods.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of supported methods.\n */\n getSupportedMethods(scope: CaipChainId): string[] {\n const accountMethods = this.#getSupportedAccountsMetadata(scope).flatMap(\n (account) => account.methods,\n );\n\n const protocolMethods = this.#getProtocolSnaps(scope).flatMap(\n (snap) => snap.methods,\n );\n\n return Array.from(new Set([...accountMethods, ...protocolMethods]));\n }\n\n /**\n * Get a list of supported accounts for a given scope.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of CAIP-10 addresses.\n */\n getSupportedAccounts(scope: CaipChainId): string[] {\n return this.#getSupportedAccountsMetadata(scope).map(\n (account) => `${scope}:${account.address}`,\n );\n }\n\n /**\n * Determine whether a given CAIP-2 scope is supported by the router.\n *\n * @param scope - The CAIP-2 scope.\n * @returns True if the router can service the scope, otherwise false.\n */\n isSupportedScope(scope: CaipChainId): boolean {\n const hasAccountSnap = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .some((account: InternalAccount) => account.metadata.snap?.enabled);\n // We currently assume here that if one Snap exists that service the scope, we can service the scope generally.\n return hasAccountSnap || this.#getProtocolSnaps(scope).length > 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MultichainRouter.cjs","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedMessenger } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n getProtocolCaveatScopes,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipChainId,\n JsonRpcParams,\n} from '@metamask/utils';\nimport {\n assert,\n hasProperty,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport { getRunnableSnaps } from '../snaps';\nimport type { GetAllSnaps, HandleSnapRequest } from '../snaps';\n\nexport type MultichainRouterHandleRequestAction = {\n type: `${typeof name}:handleRequest`;\n handler: MultichainRouter['handleRequest'];\n};\n\nexport type MultichainRouterGetSupportedMethodsAction = {\n type: `${typeof name}:getSupportedMethods`;\n handler: MultichainRouter['getSupportedMethods'];\n};\n\nexport type MultichainRouterGetSupportedAccountsAction = {\n type: `${typeof name}:getSupportedAccounts`;\n handler: MultichainRouter['getSupportedAccounts'];\n};\n\nexport type MultichainRouterIsSupportedScopeAction = {\n type: `${typeof name}:isSupportedScope`;\n handler: MultichainRouter['isSupportedScope'];\n};\n\ntype SnapKeyring = {\n submitRequest: (request: {\n origin: string;\n account: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n scope: CaipChainId;\n }) => Promise<Json>;\n resolveAccountAddress: (\n snapId: SnapId,\n scope: CaipChainId,\n request: Json,\n ) => Promise<{ address: CaipAccountId } | null>;\n};\n\n// Expecting a bound function that calls KeyringController.withKeyring selecting the Snap keyring\ntype WithSnapKeyringFunction = <ReturnType>(\n operation: ({ keyring }: { keyring: SnapKeyring }) => Promise<ReturnType>,\n) => Promise<ReturnType>;\n\nexport type AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type MultichainRouterActions =\n | MultichainRouterHandleRequestAction\n | MultichainRouterGetSupportedMethodsAction\n | MultichainRouterGetSupportedAccountsAction\n | MultichainRouterIsSupportedScopeAction;\n\nexport type MultichainRouterAllowedActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | AccountsControllerListMultichainAccountsAction;\n\nexport type MultichainRouterEvents = never;\n\nexport type MultichainRouterMessenger = RestrictedMessenger<\n typeof name,\n MultichainRouterActions | MultichainRouterAllowedActions,\n never,\n MultichainRouterAllowedActions['type'],\n MultichainRouterEvents['type']\n>;\n\nexport type MultichainRouterArgs = {\n messenger: MultichainRouterMessenger;\n withSnapKeyring: WithSnapKeyringFunction;\n};\n\ntype ProtocolSnap = {\n snapId: SnapId;\n methods: string[];\n};\n\nconst name = 'MultichainRouter';\n\nexport class MultichainRouter {\n name: typeof name = name;\n\n state = null;\n\n readonly #messenger: MultichainRouterMessenger;\n\n readonly #withSnapKeyring: WithSnapKeyringFunction;\n\n constructor({ messenger, withSnapKeyring }: MultichainRouterArgs) {\n this.#messenger = messenger;\n this.#withSnapKeyring = withSnapKeyring;\n\n this.#messenger.registerActionHandler(\n `${name}:handleRequest`,\n async (...args) => this.handleRequest(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedMethods`,\n (...args) => this.getSupportedMethods(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedAccounts`,\n (...args) => this.getSupportedAccounts(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:isSupportedScope`,\n (...args) => this.isSupportedScope(...args),\n );\n }\n\n /**\n * Attempts to resolve the account address to use for a given request by inspecting the request itself.\n *\n * The request is sent to to an account Snap via the SnapKeyring that will attempt this resolution.\n *\n * @param snapId - The ID of the Snap to send the request to.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns The resolved address if found, otherwise null.\n * @throws If the invocation of the SnapKeyring fails.\n */\n async #resolveRequestAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n try {\n const result = await this.#withSnapKeyring(async ({ keyring }) =>\n keyring.resolveAccountAddress(snapId, scope, request),\n );\n const address = result?.address;\n return address ? parseCaipAccountId(address).address : null;\n } catch {\n throw rpcErrors.internal();\n }\n }\n\n /**\n * Get the account ID of the account that should service the RPC request via an account Snap.\n *\n * This function checks whether any accounts exist that can service a given request by\n * using a combination of the resolveAccountAddress functionality and the connected accounts.\n *\n * If an account is expected to service this request but none is found, the function will throw.\n *\n * @param connectedAddresses - The CAIP-10 addresses connected to the requesting origin.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns An account ID if found, otherwise null.\n * @throws If no account is found, but the accounts exist that could service the request.\n */\n async #getSnapAccountId(\n connectedAddresses: CaipAccountId[],\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n const accounts = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter(\n (\n account: InternalAccount,\n ): account is InternalAccount & {\n metadata: Required<InternalAccount['metadata']>;\n } =>\n Boolean(account.metadata.snap?.enabled) &&\n account.methods.includes(request.method),\n );\n\n // If no accounts can service the request, return null.\n if (accounts.length === 0) {\n return null;\n }\n\n const resolutionSnapId = accounts[0].metadata.snap.id;\n\n // Attempt to resolve the address that should be used for signing.\n const address = await this.#resolveRequestAddress(\n resolutionSnapId,\n scope,\n request,\n );\n\n const parsedConnectedAddresses = connectedAddresses.map(\n (connectedAddress) => parseCaipAccountId(connectedAddress).address,\n );\n\n // If we have a resolved address, try to find the selected account based on that\n // otherwise, default to one of the connected accounts.\n // TODO: Eventually let the user choose if we have more than one option for the account.\n const selectedAccount = accounts.find(\n (account) =>\n parsedConnectedAddresses.includes(account.address) &&\n (!address || account.address === address),\n );\n\n if (!selectedAccount) {\n throw rpcErrors.invalidParams({\n message: 'No available account found for request.',\n });\n }\n\n return selectedAccount.id;\n }\n\n /**\n * Get all protocol Snaps that can service a given CAIP-2 scope.\n *\n * Protocol Snaps are deemed fit to service a scope if they are runnable\n * and have the proper permissions set for the scope.\n *\n * @param scope - A CAIP-2 scope.\n * @returns A list of all the protocol Snaps available and their RPC methods.\n */\n #getProtocolSnaps(scope: CaipChainId) {\n const allSnaps = this.#messenger.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(allSnaps);\n\n return filteredSnaps.reduce<ProtocolSnap[]>((accumulator, snap) => {\n const permissions = this.#messenger.call(\n 'PermissionController:getPermissions',\n snap.id,\n );\n\n if (permissions && hasProperty(permissions, SnapEndowments.Protocol)) {\n const permission = permissions[SnapEndowments.Protocol];\n const scopes = getProtocolCaveatScopes(permission);\n if (scopes && hasProperty(scopes, scope)) {\n accumulator.push({\n snapId: snap.id,\n methods: scopes[scope].methods,\n });\n }\n }\n\n return accumulator;\n }, []);\n }\n\n /**\n * Handle an incoming JSON-RPC request tied to a specific scope by routing\n * to either a procotol Snap or an account Snap.\n *\n * Note: Addresses are considered case sensitive by the MultichainRouter as\n * not all non-EVM chains are case insensitive.\n *\n * @param options - An options bag.\n * @param options.connectedAddresses - Addresses currently connected to the origin.\n * @param options.origin - The origin of the RPC request.\n * @param options.request - The JSON-RPC request.\n * @param options.scope - The CAIP-2 scope for the request.\n * @returns The response from the chosen Snap.\n * @throws If no handler was found.\n */\n async handleRequest({\n connectedAddresses,\n origin,\n scope,\n request: rawRequest,\n }: {\n connectedAddresses: CaipAccountId[];\n origin: string;\n scope: CaipChainId;\n request: JsonRpcRequest;\n }): Promise<Json> {\n // Explicitly block EVM scopes, just in case.\n assert(\n !scope.startsWith(KnownCaipNamespace.Eip155) &&\n !scope.startsWith('wallet:eip155'),\n );\n\n // Re-create the request to simplify and remove additional properties that may be present in MM middleware.\n const request = {\n jsonrpc: '2.0' as const,\n id: rawRequest.id ?? nanoid(),\n method: rawRequest.method,\n ...(rawRequest.params ? { params: rawRequest.params } : {}),\n };\n\n const { method, params } = request;\n\n // If the RPC request can be serviced by an account Snap, route it there.\n const accountId = await this.#getSnapAccountId(\n connectedAddresses,\n scope,\n request,\n );\n\n if (accountId) {\n return this.#withSnapKeyring(async ({ keyring }) =>\n keyring.submitRequest({\n origin,\n account: accountId,\n scope,\n method,\n params: params as JsonRpcParams,\n }),\n );\n }\n\n // If the RPC request cannot be serviced by an account Snap,\n // but has a protocol Snap available, route it there.\n const protocolSnaps = this.#getProtocolSnaps(scope);\n const protocolSnap = protocolSnaps.find((snap) =>\n snap.methods.includes(method),\n );\n\n if (protocolSnap) {\n return this.#messenger.call('SnapController:handleRequest', {\n snapId: protocolSnap.snapId,\n origin,\n request: {\n method: '',\n params: {\n request,\n scope,\n },\n },\n handler: HandlerType.OnProtocolRequest,\n }) as Promise<Json>;\n }\n\n // If no compatible account or protocol Snaps were found, throw.\n throw rpcErrors.methodNotFound();\n }\n\n /**\n * Get a list of metadata for supported accounts for a given scope from the client.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of metadata for the supported accounts.\n */\n #getSupportedAccountsMetadata(scope: CaipChainId): InternalAccount[] {\n return this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter((account: InternalAccount) => account.metadata.snap?.enabled);\n }\n\n /**\n * Get a list of supported methods for a given scope.\n * This combines both protocol and account Snaps supported methods.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of supported methods.\n */\n getSupportedMethods(scope: CaipChainId): string[] {\n const accountMethods = this.#getSupportedAccountsMetadata(scope).flatMap(\n (account) => account.methods,\n );\n\n const protocolMethods = this.#getProtocolSnaps(scope).flatMap(\n (snap) => snap.methods,\n );\n\n return Array.from(new Set([...accountMethods, ...protocolMethods]));\n }\n\n /**\n * Get a list of supported accounts for a given scope.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of CAIP-10 addresses.\n */\n getSupportedAccounts(scope: CaipChainId): string[] {\n return this.#getSupportedAccountsMetadata(scope).map(\n (account) => `${scope}:${account.address}`,\n );\n }\n\n /**\n * Determine whether a given CAIP-2 scope is supported by the router.\n *\n * @param scope - The CAIP-2 scope.\n * @returns True if the router can service the scope, otherwise false.\n */\n isSupportedScope(scope: CaipChainId): boolean {\n const hasAccountSnap = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .some((account: InternalAccount) => account.metadata.snap?.enabled);\n // We currently assume here that if one Snap exists that service the scope, we can service the scope generally.\n return hasAccountSnap || this.#getProtocolSnaps(scope).length > 0;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainRouter.d.cts","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"MultichainRouter.d.cts","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainRouter.d.mts","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"MultichainRouter.d.mts","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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"}
|
|
@@ -62,6 +62,7 @@ export class MultichainRouter {
|
|
|
62
62
|
const accountId = await __classPrivateFieldGet(this, _MultichainRouter_instances, "m", _MultichainRouter_getSnapAccountId).call(this, connectedAddresses, scope, request);
|
|
63
63
|
if (accountId) {
|
|
64
64
|
return __classPrivateFieldGet(this, _MultichainRouter_withSnapKeyring, "f").call(this, async ({ keyring }) => keyring.submitRequest({
|
|
65
|
+
origin,
|
|
65
66
|
account: accountId,
|
|
66
67
|
scope,
|
|
67
68
|
method,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultichainRouter.mjs","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedMessenger } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n getProtocolCaveatScopes,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipChainId,\n JsonRpcParams,\n} from '@metamask/utils';\nimport {\n assert,\n hasProperty,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport { getRunnableSnaps } from '../snaps';\nimport type { GetAllSnaps, HandleSnapRequest } from '../snaps';\n\nexport type MultichainRouterHandleRequestAction = {\n type: `${typeof name}:handleRequest`;\n handler: MultichainRouter['handleRequest'];\n};\n\nexport type MultichainRouterGetSupportedMethodsAction = {\n type: `${typeof name}:getSupportedMethods`;\n handler: MultichainRouter['getSupportedMethods'];\n};\n\nexport type MultichainRouterGetSupportedAccountsAction = {\n type: `${typeof name}:getSupportedAccounts`;\n handler: MultichainRouter['getSupportedAccounts'];\n};\n\nexport type MultichainRouterIsSupportedScopeAction = {\n type: `${typeof name}:isSupportedScope`;\n handler: MultichainRouter['isSupportedScope'];\n};\n\ntype SnapKeyring = {\n submitRequest: (request: {\n account: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n scope: CaipChainId;\n }) => Promise<Json>;\n resolveAccountAddress: (\n snapId: SnapId,\n scope: CaipChainId,\n request: Json,\n ) => Promise<{ address: CaipAccountId } | null>;\n};\n\n// Expecting a bound function that calls KeyringController.withKeyring selecting the Snap keyring\ntype WithSnapKeyringFunction = <ReturnType>(\n operation: ({ keyring }: { keyring: SnapKeyring }) => Promise<ReturnType>,\n) => Promise<ReturnType>;\n\nexport type AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type MultichainRouterActions =\n | MultichainRouterHandleRequestAction\n | MultichainRouterGetSupportedMethodsAction\n | MultichainRouterGetSupportedAccountsAction\n | MultichainRouterIsSupportedScopeAction;\n\nexport type MultichainRouterAllowedActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | AccountsControllerListMultichainAccountsAction;\n\nexport type MultichainRouterEvents = never;\n\nexport type MultichainRouterMessenger = RestrictedMessenger<\n typeof name,\n MultichainRouterActions | MultichainRouterAllowedActions,\n never,\n MultichainRouterAllowedActions['type'],\n MultichainRouterEvents['type']\n>;\n\nexport type MultichainRouterArgs = {\n messenger: MultichainRouterMessenger;\n withSnapKeyring: WithSnapKeyringFunction;\n};\n\ntype ProtocolSnap = {\n snapId: SnapId;\n methods: string[];\n};\n\nconst name = 'MultichainRouter';\n\nexport class MultichainRouter {\n name: typeof name = name;\n\n state = null;\n\n readonly #messenger: MultichainRouterMessenger;\n\n readonly #withSnapKeyring: WithSnapKeyringFunction;\n\n constructor({ messenger, withSnapKeyring }: MultichainRouterArgs) {\n this.#messenger = messenger;\n this.#withSnapKeyring = withSnapKeyring;\n\n this.#messenger.registerActionHandler(\n `${name}:handleRequest`,\n async (...args) => this.handleRequest(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedMethods`,\n (...args) => this.getSupportedMethods(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedAccounts`,\n (...args) => this.getSupportedAccounts(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:isSupportedScope`,\n (...args) => this.isSupportedScope(...args),\n );\n }\n\n /**\n * Attempts to resolve the account address to use for a given request by inspecting the request itself.\n *\n * The request is sent to to an account Snap via the SnapKeyring that will attempt this resolution.\n *\n * @param snapId - The ID of the Snap to send the request to.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns The resolved address if found, otherwise null.\n * @throws If the invocation of the SnapKeyring fails.\n */\n async #resolveRequestAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n try {\n const result = await this.#withSnapKeyring(async ({ keyring }) =>\n keyring.resolveAccountAddress(snapId, scope, request),\n );\n const address = result?.address;\n return address ? parseCaipAccountId(address).address : null;\n } catch {\n throw rpcErrors.internal();\n }\n }\n\n /**\n * Get the account ID of the account that should service the RPC request via an account Snap.\n *\n * This function checks whether any accounts exist that can service a given request by\n * using a combination of the resolveAccountAddress functionality and the connected accounts.\n *\n * If an account is expected to service this request but none is found, the function will throw.\n *\n * @param connectedAddresses - The CAIP-10 addresses connected to the requesting origin.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns An account ID if found, otherwise null.\n * @throws If no account is found, but the accounts exist that could service the request.\n */\n async #getSnapAccountId(\n connectedAddresses: CaipAccountId[],\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n const accounts = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter(\n (\n account: InternalAccount,\n ): account is InternalAccount & {\n metadata: Required<InternalAccount['metadata']>;\n } =>\n Boolean(account.metadata.snap?.enabled) &&\n account.methods.includes(request.method),\n );\n\n // If no accounts can service the request, return null.\n if (accounts.length === 0) {\n return null;\n }\n\n const resolutionSnapId = accounts[0].metadata.snap.id;\n\n // Attempt to resolve the address that should be used for signing.\n const address = await this.#resolveRequestAddress(\n resolutionSnapId,\n scope,\n request,\n );\n\n const parsedConnectedAddresses = connectedAddresses.map(\n (connectedAddress) => parseCaipAccountId(connectedAddress).address,\n );\n\n // If we have a resolved address, try to find the selected account based on that\n // otherwise, default to one of the connected accounts.\n // TODO: Eventually let the user choose if we have more than one option for the account.\n const selectedAccount = accounts.find(\n (account) =>\n parsedConnectedAddresses.includes(account.address) &&\n (!address || account.address === address),\n );\n\n if (!selectedAccount) {\n throw rpcErrors.invalidParams({\n message: 'No available account found for request.',\n });\n }\n\n return selectedAccount.id;\n }\n\n /**\n * Get all protocol Snaps that can service a given CAIP-2 scope.\n *\n * Protocol Snaps are deemed fit to service a scope if they are runnable\n * and have the proper permissions set for the scope.\n *\n * @param scope - A CAIP-2 scope.\n * @returns A list of all the protocol Snaps available and their RPC methods.\n */\n #getProtocolSnaps(scope: CaipChainId) {\n const allSnaps = this.#messenger.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(allSnaps);\n\n return filteredSnaps.reduce<ProtocolSnap[]>((accumulator, snap) => {\n const permissions = this.#messenger.call(\n 'PermissionController:getPermissions',\n snap.id,\n );\n\n if (permissions && hasProperty(permissions, SnapEndowments.Protocol)) {\n const permission = permissions[SnapEndowments.Protocol];\n const scopes = getProtocolCaveatScopes(permission);\n if (scopes && hasProperty(scopes, scope)) {\n accumulator.push({\n snapId: snap.id,\n methods: scopes[scope].methods,\n });\n }\n }\n\n return accumulator;\n }, []);\n }\n\n /**\n * Handle an incoming JSON-RPC request tied to a specific scope by routing\n * to either a procotol Snap or an account Snap.\n *\n * Note: Addresses are considered case sensitive by the MultichainRouter as\n * not all non-EVM chains are case insensitive.\n *\n * @param options - An options bag.\n * @param options.connectedAddresses - Addresses currently connected to the origin.\n * @param options.origin - The origin of the RPC request.\n * @param options.request - The JSON-RPC request.\n * @param options.scope - The CAIP-2 scope for the request.\n * @returns The response from the chosen Snap.\n * @throws If no handler was found.\n */\n async handleRequest({\n connectedAddresses,\n origin,\n scope,\n request: rawRequest,\n }: {\n connectedAddresses: CaipAccountId[];\n origin: string;\n scope: CaipChainId;\n request: JsonRpcRequest;\n }): Promise<Json> {\n // Explicitly block EVM scopes, just in case.\n assert(\n !scope.startsWith(KnownCaipNamespace.Eip155) &&\n !scope.startsWith('wallet:eip155'),\n );\n\n // Re-create the request to simplify and remove additional properties that may be present in MM middleware.\n const request = {\n jsonrpc: '2.0' as const,\n id: rawRequest.id ?? nanoid(),\n method: rawRequest.method,\n ...(rawRequest.params ? { params: rawRequest.params } : {}),\n };\n\n const { method, params } = request;\n\n // If the RPC request can be serviced by an account Snap, route it there.\n const accountId = await this.#getSnapAccountId(\n connectedAddresses,\n scope,\n request,\n );\n\n if (accountId) {\n return this.#withSnapKeyring(async ({ keyring }) =>\n keyring.submitRequest({\n account: accountId,\n scope,\n method,\n params: params as JsonRpcParams,\n }),\n );\n }\n\n // If the RPC request cannot be serviced by an account Snap,\n // but has a protocol Snap available, route it there.\n const protocolSnaps = this.#getProtocolSnaps(scope);\n const protocolSnap = protocolSnaps.find((snap) =>\n snap.methods.includes(method),\n );\n\n if (protocolSnap) {\n return this.#messenger.call('SnapController:handleRequest', {\n snapId: protocolSnap.snapId,\n origin,\n request: {\n method: '',\n params: {\n request,\n scope,\n },\n },\n handler: HandlerType.OnProtocolRequest,\n }) as Promise<Json>;\n }\n\n // If no compatible account or protocol Snaps were found, throw.\n throw rpcErrors.methodNotFound();\n }\n\n /**\n * Get a list of metadata for supported accounts for a given scope from the client.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of metadata for the supported accounts.\n */\n #getSupportedAccountsMetadata(scope: CaipChainId): InternalAccount[] {\n return this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter((account: InternalAccount) => account.metadata.snap?.enabled);\n }\n\n /**\n * Get a list of supported methods for a given scope.\n * This combines both protocol and account Snaps supported methods.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of supported methods.\n */\n getSupportedMethods(scope: CaipChainId): string[] {\n const accountMethods = this.#getSupportedAccountsMetadata(scope).flatMap(\n (account) => account.methods,\n );\n\n const protocolMethods = this.#getProtocolSnaps(scope).flatMap(\n (snap) => snap.methods,\n );\n\n return Array.from(new Set([...accountMethods, ...protocolMethods]));\n }\n\n /**\n * Get a list of supported accounts for a given scope.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of CAIP-10 addresses.\n */\n getSupportedAccounts(scope: CaipChainId): string[] {\n return this.#getSupportedAccountsMetadata(scope).map(\n (account) => `${scope}:${account.address}`,\n );\n }\n\n /**\n * Determine whether a given CAIP-2 scope is supported by the router.\n *\n * @param scope - The CAIP-2 scope.\n * @returns True if the router can service the scope, otherwise false.\n */\n isSupportedScope(scope: CaipChainId): boolean {\n const hasAccountSnap = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .some((account: InternalAccount) => account.metadata.snap?.enabled);\n // We currently assume here that if one Snap exists that service the scope, we can service the scope generally.\n return hasAccountSnap || this.#getProtocolSnaps(scope).length > 0;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"MultichainRouter.mjs","sourceRoot":"","sources":["../../src/multichain/MultichainRouter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RestrictedMessenger } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport {\n getProtocolCaveatScopes,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { Json, JsonRpcRequest, SnapId } from '@metamask/snaps-sdk';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipChainId,\n JsonRpcParams,\n} from '@metamask/utils';\nimport {\n assert,\n hasProperty,\n KnownCaipNamespace,\n parseCaipAccountId,\n} from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport { getRunnableSnaps } from '../snaps';\nimport type { GetAllSnaps, HandleSnapRequest } from '../snaps';\n\nexport type MultichainRouterHandleRequestAction = {\n type: `${typeof name}:handleRequest`;\n handler: MultichainRouter['handleRequest'];\n};\n\nexport type MultichainRouterGetSupportedMethodsAction = {\n type: `${typeof name}:getSupportedMethods`;\n handler: MultichainRouter['getSupportedMethods'];\n};\n\nexport type MultichainRouterGetSupportedAccountsAction = {\n type: `${typeof name}:getSupportedAccounts`;\n handler: MultichainRouter['getSupportedAccounts'];\n};\n\nexport type MultichainRouterIsSupportedScopeAction = {\n type: `${typeof name}:isSupportedScope`;\n handler: MultichainRouter['isSupportedScope'];\n};\n\ntype SnapKeyring = {\n submitRequest: (request: {\n origin: string;\n account: string;\n method: string;\n params?: Json[] | Record<string, Json>;\n scope: CaipChainId;\n }) => Promise<Json>;\n resolveAccountAddress: (\n snapId: SnapId,\n scope: CaipChainId,\n request: Json,\n ) => Promise<{ address: CaipAccountId } | null>;\n};\n\n// Expecting a bound function that calls KeyringController.withKeyring selecting the Snap keyring\ntype WithSnapKeyringFunction = <ReturnType>(\n operation: ({ keyring }: { keyring: SnapKeyring }) => Promise<ReturnType>,\n) => Promise<ReturnType>;\n\nexport type AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type MultichainRouterActions =\n | MultichainRouterHandleRequestAction\n | MultichainRouterGetSupportedMethodsAction\n | MultichainRouterGetSupportedAccountsAction\n | MultichainRouterIsSupportedScopeAction;\n\nexport type MultichainRouterAllowedActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | AccountsControllerListMultichainAccountsAction;\n\nexport type MultichainRouterEvents = never;\n\nexport type MultichainRouterMessenger = RestrictedMessenger<\n typeof name,\n MultichainRouterActions | MultichainRouterAllowedActions,\n never,\n MultichainRouterAllowedActions['type'],\n MultichainRouterEvents['type']\n>;\n\nexport type MultichainRouterArgs = {\n messenger: MultichainRouterMessenger;\n withSnapKeyring: WithSnapKeyringFunction;\n};\n\ntype ProtocolSnap = {\n snapId: SnapId;\n methods: string[];\n};\n\nconst name = 'MultichainRouter';\n\nexport class MultichainRouter {\n name: typeof name = name;\n\n state = null;\n\n readonly #messenger: MultichainRouterMessenger;\n\n readonly #withSnapKeyring: WithSnapKeyringFunction;\n\n constructor({ messenger, withSnapKeyring }: MultichainRouterArgs) {\n this.#messenger = messenger;\n this.#withSnapKeyring = withSnapKeyring;\n\n this.#messenger.registerActionHandler(\n `${name}:handleRequest`,\n async (...args) => this.handleRequest(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedMethods`,\n (...args) => this.getSupportedMethods(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:getSupportedAccounts`,\n (...args) => this.getSupportedAccounts(...args),\n );\n\n this.#messenger.registerActionHandler(\n `${name}:isSupportedScope`,\n (...args) => this.isSupportedScope(...args),\n );\n }\n\n /**\n * Attempts to resolve the account address to use for a given request by inspecting the request itself.\n *\n * The request is sent to to an account Snap via the SnapKeyring that will attempt this resolution.\n *\n * @param snapId - The ID of the Snap to send the request to.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns The resolved address if found, otherwise null.\n * @throws If the invocation of the SnapKeyring fails.\n */\n async #resolveRequestAddress(\n snapId: SnapId,\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n try {\n const result = await this.#withSnapKeyring(async ({ keyring }) =>\n keyring.resolveAccountAddress(snapId, scope, request),\n );\n const address = result?.address;\n return address ? parseCaipAccountId(address).address : null;\n } catch {\n throw rpcErrors.internal();\n }\n }\n\n /**\n * Get the account ID of the account that should service the RPC request via an account Snap.\n *\n * This function checks whether any accounts exist that can service a given request by\n * using a combination of the resolveAccountAddress functionality and the connected accounts.\n *\n * If an account is expected to service this request but none is found, the function will throw.\n *\n * @param connectedAddresses - The CAIP-10 addresses connected to the requesting origin.\n * @param scope - The CAIP-2 scope for the request.\n * @param request - The JSON-RPC request.\n * @returns An account ID if found, otherwise null.\n * @throws If no account is found, but the accounts exist that could service the request.\n */\n async #getSnapAccountId(\n connectedAddresses: CaipAccountId[],\n scope: CaipChainId,\n request: JsonRpcRequest,\n ) {\n const accounts = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter(\n (\n account: InternalAccount,\n ): account is InternalAccount & {\n metadata: Required<InternalAccount['metadata']>;\n } =>\n Boolean(account.metadata.snap?.enabled) &&\n account.methods.includes(request.method),\n );\n\n // If no accounts can service the request, return null.\n if (accounts.length === 0) {\n return null;\n }\n\n const resolutionSnapId = accounts[0].metadata.snap.id;\n\n // Attempt to resolve the address that should be used for signing.\n const address = await this.#resolveRequestAddress(\n resolutionSnapId,\n scope,\n request,\n );\n\n const parsedConnectedAddresses = connectedAddresses.map(\n (connectedAddress) => parseCaipAccountId(connectedAddress).address,\n );\n\n // If we have a resolved address, try to find the selected account based on that\n // otherwise, default to one of the connected accounts.\n // TODO: Eventually let the user choose if we have more than one option for the account.\n const selectedAccount = accounts.find(\n (account) =>\n parsedConnectedAddresses.includes(account.address) &&\n (!address || account.address === address),\n );\n\n if (!selectedAccount) {\n throw rpcErrors.invalidParams({\n message: 'No available account found for request.',\n });\n }\n\n return selectedAccount.id;\n }\n\n /**\n * Get all protocol Snaps that can service a given CAIP-2 scope.\n *\n * Protocol Snaps are deemed fit to service a scope if they are runnable\n * and have the proper permissions set for the scope.\n *\n * @param scope - A CAIP-2 scope.\n * @returns A list of all the protocol Snaps available and their RPC methods.\n */\n #getProtocolSnaps(scope: CaipChainId) {\n const allSnaps = this.#messenger.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(allSnaps);\n\n return filteredSnaps.reduce<ProtocolSnap[]>((accumulator, snap) => {\n const permissions = this.#messenger.call(\n 'PermissionController:getPermissions',\n snap.id,\n );\n\n if (permissions && hasProperty(permissions, SnapEndowments.Protocol)) {\n const permission = permissions[SnapEndowments.Protocol];\n const scopes = getProtocolCaveatScopes(permission);\n if (scopes && hasProperty(scopes, scope)) {\n accumulator.push({\n snapId: snap.id,\n methods: scopes[scope].methods,\n });\n }\n }\n\n return accumulator;\n }, []);\n }\n\n /**\n * Handle an incoming JSON-RPC request tied to a specific scope by routing\n * to either a procotol Snap or an account Snap.\n *\n * Note: Addresses are considered case sensitive by the MultichainRouter as\n * not all non-EVM chains are case insensitive.\n *\n * @param options - An options bag.\n * @param options.connectedAddresses - Addresses currently connected to the origin.\n * @param options.origin - The origin of the RPC request.\n * @param options.request - The JSON-RPC request.\n * @param options.scope - The CAIP-2 scope for the request.\n * @returns The response from the chosen Snap.\n * @throws If no handler was found.\n */\n async handleRequest({\n connectedAddresses,\n origin,\n scope,\n request: rawRequest,\n }: {\n connectedAddresses: CaipAccountId[];\n origin: string;\n scope: CaipChainId;\n request: JsonRpcRequest;\n }): Promise<Json> {\n // Explicitly block EVM scopes, just in case.\n assert(\n !scope.startsWith(KnownCaipNamespace.Eip155) &&\n !scope.startsWith('wallet:eip155'),\n );\n\n // Re-create the request to simplify and remove additional properties that may be present in MM middleware.\n const request = {\n jsonrpc: '2.0' as const,\n id: rawRequest.id ?? nanoid(),\n method: rawRequest.method,\n ...(rawRequest.params ? { params: rawRequest.params } : {}),\n };\n\n const { method, params } = request;\n\n // If the RPC request can be serviced by an account Snap, route it there.\n const accountId = await this.#getSnapAccountId(\n connectedAddresses,\n scope,\n request,\n );\n\n if (accountId) {\n return this.#withSnapKeyring(async ({ keyring }) =>\n keyring.submitRequest({\n origin,\n account: accountId,\n scope,\n method,\n params: params as JsonRpcParams,\n }),\n );\n }\n\n // If the RPC request cannot be serviced by an account Snap,\n // but has a protocol Snap available, route it there.\n const protocolSnaps = this.#getProtocolSnaps(scope);\n const protocolSnap = protocolSnaps.find((snap) =>\n snap.methods.includes(method),\n );\n\n if (protocolSnap) {\n return this.#messenger.call('SnapController:handleRequest', {\n snapId: protocolSnap.snapId,\n origin,\n request: {\n method: '',\n params: {\n request,\n scope,\n },\n },\n handler: HandlerType.OnProtocolRequest,\n }) as Promise<Json>;\n }\n\n // If no compatible account or protocol Snaps were found, throw.\n throw rpcErrors.methodNotFound();\n }\n\n /**\n * Get a list of metadata for supported accounts for a given scope from the client.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of metadata for the supported accounts.\n */\n #getSupportedAccountsMetadata(scope: CaipChainId): InternalAccount[] {\n return this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .filter((account: InternalAccount) => account.metadata.snap?.enabled);\n }\n\n /**\n * Get a list of supported methods for a given scope.\n * This combines both protocol and account Snaps supported methods.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of supported methods.\n */\n getSupportedMethods(scope: CaipChainId): string[] {\n const accountMethods = this.#getSupportedAccountsMetadata(scope).flatMap(\n (account) => account.methods,\n );\n\n const protocolMethods = this.#getProtocolSnaps(scope).flatMap(\n (snap) => snap.methods,\n );\n\n return Array.from(new Set([...accountMethods, ...protocolMethods]));\n }\n\n /**\n * Get a list of supported accounts for a given scope.\n *\n * @param scope - The CAIP-2 scope.\n * @returns A list of CAIP-10 addresses.\n */\n getSupportedAccounts(scope: CaipChainId): string[] {\n return this.#getSupportedAccountsMetadata(scope).map(\n (account) => `${scope}:${account.address}`,\n );\n }\n\n /**\n * Determine whether a given CAIP-2 scope is supported by the router.\n *\n * @param scope - The CAIP-2 scope.\n * @returns True if the router can service the scope, otherwise false.\n */\n isSupportedScope(scope: CaipChainId): boolean {\n const hasAccountSnap = this.#messenger\n .call('AccountsController:listMultichainAccounts', scope)\n .some((account: InternalAccount) => account.metadata.snap?.enabled);\n // We currently assume here that if one Snap exists that service the scope, we can service the scope generally.\n return hasAccountSnap || this.#getProtocolSnaps(scope).length > 0;\n }\n}\n"]}
|
|
@@ -526,6 +526,22 @@ class SnapController extends base_controller_1.BaseController {
|
|
|
526
526
|
(0, utils_1.assert)(encoded.length < snaps_utils_1.MAX_FILE_SIZE, `Failed to encode static file to "${encoding}": Static files must be less than 64 MB when encoded.`);
|
|
527
527
|
return encoded;
|
|
528
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* Determine if a given Snap ID supports a given minimum version of the Snaps platform
|
|
531
|
+
* by inspecting the platformVersion in the Snap manifest.
|
|
532
|
+
*
|
|
533
|
+
* @param snapId - The Snap ID.
|
|
534
|
+
* @param version - The version.
|
|
535
|
+
* @returns True if the platform version is equal or greater to the passed version, false otherwise.
|
|
536
|
+
*/
|
|
537
|
+
isMinimumPlatformVersion(snapId, version) {
|
|
538
|
+
const snap = this.getExpect(snapId);
|
|
539
|
+
const { platformVersion } = snap.manifest;
|
|
540
|
+
if (!platformVersion) {
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
return (0, semver_1.gte)(platformVersion, version);
|
|
544
|
+
}
|
|
529
545
|
/**
|
|
530
546
|
* Completely clear the controller's state: delete all associated data,
|
|
531
547
|
* handlers, event listeners, and permissions; tear down all snap providers.
|
|
@@ -1147,6 +1163,7 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_dynamicPerm
|
|
|
1147
1163
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:revokeDynamicPermissions`, (...args) => this.revokeDynamicSnapPermissions(...args));
|
|
1148
1164
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:getFile`, async (...args) => this.getSnapFile(...args));
|
|
1149
1165
|
this.messagingSystem.registerActionHandler(`${exports.controllerName}:stopAllSnaps`, async (...args) => this.stopAllSnaps(...args));
|
|
1166
|
+
this.messagingSystem.registerActionHandler(`${exports.controllerName}:isMinimumPlatformVersion`, (...args) => this.isMinimumPlatformVersion(...args));
|
|
1150
1167
|
}, _SnapController_handlePreinstalledSnaps = function _SnapController_handlePreinstalledSnaps(preinstalledSnaps) {
|
|
1151
1168
|
for (const { snapId, manifest, files, removable, hidden, hideSnapBranding, } of preinstalledSnaps) {
|
|
1152
1169
|
const existingSnap = this.get(snapId);
|