diff --git a/packages/examples/packages/ethereum-provider/snap.manifest.json b/packages/examples/packages/ethereum-provider/snap.manifest.json index 9d1b5d629c..2469c6165d 100644 --- a/packages/examples/packages/ethereum-provider/snap.manifest.json +++ b/packages/examples/packages/ethereum-provider/snap.manifest.json @@ -7,7 +7,7 @@ "url": "https://github.com/MetaMask/snaps.git" }, "source": { - "shasum": "8f7Fo6y40+L0x+KHkDCq2wjEMrkTL+L6e2NSNBZYVLA=", + "shasum": "hVuKuTyTaza8ezHZLGeC5Yq4E7LZPgO/spV7qwOEDlE=", "location": { "npm": { "filePath": "dist/bundle.js", diff --git a/packages/examples/packages/ethereum-provider/src/index.ts b/packages/examples/packages/ethereum-provider/src/index.ts index 0683c38f1e..5f0a52bf79 100644 --- a/packages/examples/packages/ethereum-provider/src/index.ts +++ b/packages/examples/packages/ethereum-provider/src/index.ts @@ -10,7 +10,23 @@ import { hexToNumber, } from '@metamask/utils'; -import type { PersonalSignParams, SignTypedDataParams } from './types'; +import type { + BaseParams, + PersonalSignParams, + SignTypedDataParams, +} from './types'; + +/** + * Set the active Ethereum chain for the Snap. + * + * @param chainId - The chain ID to switch to. + */ +async function switchChain(chainId: Hex) { + await ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [{ chainId }], + }); +} /** * Get the current gas price using the `ethereum` global. This is essentially @@ -207,6 +223,9 @@ async function signTypedData(message: string, from: string) { * @see https://docs.metamask.io/snaps/reference/rpc-api/#wallet_invokesnap */ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => { + const { chainId = '0x1' } = (request.params as BaseParams) ?? {}; + await switchChain(chainId); + switch (request.method) { case 'getGasPrice': return await getGasPrice(); diff --git a/packages/examples/packages/ethereum-provider/src/types.ts b/packages/examples/packages/ethereum-provider/src/types.ts index 807c7ef54c..6e580fb82d 100644 --- a/packages/examples/packages/ethereum-provider/src/types.ts +++ b/packages/examples/packages/ethereum-provider/src/types.ts @@ -1,4 +1,10 @@ -export type PersonalSignParams = { +import type { Hex } from '@metamask/utils'; + +export type BaseParams = { + chainId?: Hex; +}; + +export type PersonalSignParams = BaseParams & { message: string; }; diff --git a/packages/snaps-controllers/coverage.json b/packages/snaps-controllers/coverage.json index 7a462547c5..9ee4839855 100644 --- a/packages/snaps-controllers/coverage.json +++ b/packages/snaps-controllers/coverage.json @@ -1,6 +1,6 @@ { - "branches": 92.96, + "branches": 92.97, "functions": 96.56, - "lines": 98.05, - "statements": 97.77 + "lines": 98.06, + "statements": 97.78 } diff --git a/packages/snaps-controllers/package.json b/packages/snaps-controllers/package.json index 9d95c45715..59ca469881 100644 --- a/packages/snaps-controllers/package.json +++ b/packages/snaps-controllers/package.json @@ -84,11 +84,13 @@ "@metamask/json-rpc-engine": "^10.0.2", "@metamask/json-rpc-middleware-stream": "^8.0.6", "@metamask/key-tree": "^10.0.2", + "@metamask/network-controller": "^22.1.1", "@metamask/object-multiplex": "^2.1.0", "@metamask/permission-controller": "^11.0.5", "@metamask/phishing-controller": "^12.3.1", "@metamask/post-message-stream": "^9.0.0", "@metamask/rpc-errors": "^7.0.2", + "@metamask/selected-network-controller": "^20.0.2", "@metamask/snaps-registry": "^3.2.3", "@metamask/snaps-rpc-methods": "workspace:^", "@metamask/snaps-sdk": "workspace:^", diff --git a/packages/snaps-controllers/src/snaps/SnapController.test.tsx b/packages/snaps-controllers/src/snaps/SnapController.test.tsx index aaa463bfed..2a2f9a14c1 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.test.tsx +++ b/packages/snaps-controllers/src/snaps/SnapController.test.tsx @@ -103,7 +103,10 @@ import { waitForStateChange, } from '../test-utils'; import { delay } from '../utils'; -import { LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS } from './constants'; +import { + LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS, + PERMITTED_CHAINS_ENDOWMENT, +} from './constants'; import { SnapsRegistryStatus } from './registry'; import type { SnapControllerState } from './SnapController'; import { @@ -4877,6 +4880,216 @@ describe('SnapController', () => { snapController.destroy(); }); + it('grants the `endowment:permitted-chains` permission to a Snap with `endowment:ethereum-provider`', async () => { + const rootMessenger = getControllerMessenger(); + const messenger = getSnapControllerMessenger(rootMessenger); + + rootMessenger.registerActionHandler( + 'PermissionController:getPermissions', + () => ({}), + ); + + rootMessenger.registerActionHandler( + 'SelectedNetworkController:getNetworkClientIdForDomain', + () => 'mainnet', + ); + + rootMessenger.registerActionHandler( + 'NetworkController:getNetworkClientById', + () => ({ + // @ts-expect-error - Partial network client. + configuration: { + chainId: '0x1', + }, + }), + ); + + const { manifest } = await getMockSnapFilesWithUpdatedChecksum({ + manifest: getSnapManifest({ + initialPermissions: { + 'endowment:page-home': {}, + 'endowment:ethereum-provider': {}, + }, + }), + }); + + const snapController = getSnapController( + getSnapControllerOptions({ + messenger, + detectSnapLocation: loopbackDetect({ manifest }), + }), + ); + + await snapController.installSnaps(MOCK_ORIGIN, { + [MOCK_SNAP_ID]: {}, + }); + + const approvedPermissions = { + 'endowment:page-home': { + caveats: null, + }, + 'endowment:ethereum-provider': {}, + [PERMITTED_CHAINS_ENDOWMENT]: { + caveats: [ + { + type: 'restrictNetworkSwitching', + value: ['0x1'], + }, + ], + }, + }; + + expect(messenger.call).toHaveBeenCalledWith( + 'PermissionController:grantPermissions', + { + approvedPermissions, + subject: { origin: MOCK_SNAP_ID }, + requestData: expect.any(Object), + }, + ); + + snapController.destroy(); + }); + + it('overrides the `endowment:permitted-chains` permission if the Snap specifies it in its manifest', async () => { + const rootMessenger = getControllerMessenger(); + const messenger = getSnapControllerMessenger(rootMessenger); + + rootMessenger.registerActionHandler( + 'PermissionController:getPermissions', + () => ({}), + ); + + rootMessenger.registerActionHandler( + 'SelectedNetworkController:getNetworkClientIdForDomain', + () => 'mainnet', + ); + + rootMessenger.registerActionHandler( + 'NetworkController:getNetworkClientById', + () => ({ + // @ts-expect-error - Partial network client. + configuration: { + chainId: '0x1', + }, + }), + ); + + const { manifest } = await getMockSnapFilesWithUpdatedChecksum({ + manifest: getSnapManifest({ + initialPermissions: { + 'endowment:page-home': {}, + 'endowment:ethereum-provider': {}, + [PERMITTED_CHAINS_ENDOWMENT]: { + caveats: [ + { + type: 'restrictNetworkSwitching', + value: ['0x5'], + }, + ], + }, + }, + }), + }); + + const snapController = getSnapController( + getSnapControllerOptions({ + messenger, + detectSnapLocation: loopbackDetect({ manifest }), + }), + ); + + await snapController.installSnaps(MOCK_ORIGIN, { + [MOCK_SNAP_ID]: {}, + }); + + const approvedPermissions = { + 'endowment:page-home': { + caveats: null, + }, + 'endowment:ethereum-provider': {}, + [PERMITTED_CHAINS_ENDOWMENT]: { + caveats: [ + { + type: 'restrictNetworkSwitching', + value: ['0x1'], + }, + ], + }, + }; + + expect(messenger.call).toHaveBeenCalledWith( + 'PermissionController:grantPermissions', + { + approvedPermissions, + subject: { origin: MOCK_SNAP_ID }, + requestData: expect.any(Object), + }, + ); + + snapController.destroy(); + }); + + it('does not grant the `endowment:permitted-chains` permission if the Snap does not have the `endowment:ethereum-provider` permission', async () => { + const rootMessenger = getControllerMessenger(); + const messenger = getSnapControllerMessenger(rootMessenger); + + rootMessenger.registerActionHandler( + 'PermissionController:getPermissions', + () => ({}), + ); + + rootMessenger.registerActionHandler( + 'SelectedNetworkController:getNetworkClientIdForDomain', + () => { + throw new Error('This should not be called.'); + }, + ); + + rootMessenger.registerActionHandler( + 'NetworkController:getNetworkClientById', + () => { + throw new Error('This should not be called.'); + }, + ); + + const { manifest } = await getMockSnapFilesWithUpdatedChecksum({ + manifest: getSnapManifest({ + initialPermissions: { + 'endowment:page-home': {}, + }, + }), + }); + + const snapController = getSnapController( + getSnapControllerOptions({ + messenger, + detectSnapLocation: loopbackDetect({ manifest }), + }), + ); + + await snapController.installSnaps(MOCK_ORIGIN, { + [MOCK_SNAP_ID]: {}, + }); + + const approvedPermissions = { + 'endowment:page-home': { + caveats: null, + }, + }; + + expect(messenger.call).toHaveBeenCalledWith( + 'PermissionController:grantPermissions', + { + approvedPermissions, + subject: { origin: MOCK_SNAP_ID }, + requestData: expect.any(Object), + }, + ); + + snapController.destroy(); + }); + it('supports preinstalled snaps', async () => { const rootMessenger = getControllerMessenger(); jest.spyOn(rootMessenger, 'call'); diff --git a/packages/snaps-controllers/src/snaps/SnapController.ts b/packages/snaps-controllers/src/snaps/SnapController.ts index 655c1bcdec..c1057adcee 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.ts +++ b/packages/snaps-controllers/src/snaps/SnapController.ts @@ -9,6 +9,7 @@ import type { } from '@metamask/base-controller'; import { BaseController } from '@metamask/base-controller'; import type { CryptographicFunctions } from '@metamask/key-tree'; +import type { NetworkControllerGetNetworkClientByIdAction } from '@metamask/network-controller'; import type { Caveat, GetEndowments, @@ -31,6 +32,7 @@ import type { } from '@metamask/permission-controller'; import { SubjectType } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; +import type { SelectedNetworkControllerGetNetworkClientIdForDomainAction } from '@metamask/selected-network-controller'; import type { BlockReason } from '@metamask/snaps-registry'; import { WALLET_SNAP_PERMISSION_KEY, @@ -125,10 +127,10 @@ import type { TerminateAllSnapsAction, TerminateSnapAction, } from '../services'; -import type { EncryptionResult } from '../types'; -import { - type ExportableKeyEncryptor, - type KeyDerivationOptions, +import type { + EncryptionResult, + ExportableKeyEncryptor, + KeyDerivationOptions, } from '../types'; import { fetchSnap, @@ -140,6 +142,7 @@ import { import { ALLOWED_PERMISSIONS, LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS, + PERMITTED_CHAINS_ENDOWMENT, } from './constants'; import type { SnapLocation } from './location'; import { detectSnapLocation } from './location'; @@ -612,7 +615,9 @@ export type AllowedActions = | Update | ResolveVersion | CreateInterface - | GetInterface; + | GetInterface + | NetworkControllerGetNetworkClientByIdAction + | SelectedNetworkControllerGetNetworkClientIdForDomainAction; export type AllowedEvents = | ExecutionServiceEvents @@ -3920,7 +3925,48 @@ export class SnapController extends BaseController< } /** - * Updates the permissions for a snap following an install, update or rollback. + * Get the permissions to grant to a Snap following an install, update or + * rollback. + * + * @param snapId - The snap ID. + * @param newPermissions - The new permissions to be granted. + * @returns The permissions to grant to the Snap. + */ + #getPermissionsToGrant(snapId: SnapId, newPermissions: RequestedPermissions) { + if (Object.keys(newPermissions).includes(SnapEndowments.EthereumProvider)) { + // This will return the globally selected network if the Snap doesn't have + // one set. + const networkClientId = this.messagingSystem.call( + 'SelectedNetworkController:getNetworkClientIdForDomain', + snapId, + ); + + const { configuration } = this.messagingSystem.call( + 'NetworkController:getNetworkClientById', + networkClientId, + ); + + // This needs to be assigned to have proper type inference. + const modifiedPermissions: RequestedPermissions = { + ...newPermissions, + [PERMITTED_CHAINS_ENDOWMENT]: { + caveats: [ + { + type: 'restrictNetworkSwitching', + value: [configuration.chainId], + }, + ], + }, + }; + + return modifiedPermissions; + } + + return newPermissions; + } + + /** + * Update the permissions for a snap following an install, update or rollback. * * Grants newly requested permissions and revokes unused/revoked permissions. * @@ -3953,8 +3999,13 @@ export class SnapController extends BaseController< } if (isNonEmptyArray(Object.keys(newPermissions))) { + const approvedPermissions = this.#getPermissionsToGrant( + snapId, + newPermissions, + ); + this.messagingSystem.call('PermissionController:grantPermissions', { - approvedPermissions: newPermissions, + approvedPermissions, subject: { origin: snapId }, requestData, }); diff --git a/packages/snaps-controllers/src/snaps/constants.ts b/packages/snaps-controllers/src/snaps/constants.ts index 2125d9976d..4877ee521a 100644 --- a/packages/snaps-controllers/src/snaps/constants.ts +++ b/packages/snaps-controllers/src/snaps/constants.ts @@ -20,3 +20,5 @@ export const LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS = { iterations: 10_000, }, }; + +export const PERMITTED_CHAINS_ENDOWMENT = 'endowment:permitted-chains'; diff --git a/packages/snaps-controllers/src/test-utils/controller.ts b/packages/snaps-controllers/src/test-utils/controller.ts index c4b33a9f8b..2b991f3e6c 100644 --- a/packages/snaps-controllers/src/test-utils/controller.ts +++ b/packages/snaps-controllers/src/test-utils/controller.ts @@ -476,6 +476,7 @@ export const getSnapControllerMessenger = ( 'ExecutionService:terminateAllSnaps', 'ExecutionService:terminateSnap', 'ExecutionService:handleRpcRequest', + 'NetworkController:getNetworkClientById', 'PermissionController:getEndowments', 'PermissionController:hasPermission', 'PermissionController:hasPermissions', @@ -488,6 +489,7 @@ export const getSnapControllerMessenger = ( 'PermissionController:getSubjectNames', 'PhishingController:maybeUpdateState', 'PhishingController:testOrigin', + 'SelectedNetworkController:getNetworkClientIdForDomain', 'SnapController:get', 'SnapController:handleRequest', 'SnapController:getSnapState', diff --git a/packages/snaps-execution-environments/src/common/utils.ts b/packages/snaps-execution-environments/src/common/utils.ts index d7e143e086..aa188dd86c 100644 --- a/packages/snaps-execution-environments/src/common/utils.ts +++ b/packages/snaps-execution-environments/src/common/utils.ts @@ -55,7 +55,6 @@ export const BLOCKED_RPC_METHODS = Object.freeze([ 'eth_decrypt', 'eth_getEncryptionPublicKey', 'wallet_addEthereumChain', - 'wallet_switchEthereumChain', 'wallet_watchAsset', 'wallet_registerOnboarding', 'wallet_scanQRCode', diff --git a/packages/snaps-simulation/src/middleware/internal-methods/middleware.ts b/packages/snaps-simulation/src/middleware/internal-methods/middleware.ts index 777ef497b9..6465e2a048 100644 --- a/packages/snaps-simulation/src/middleware/internal-methods/middleware.ts +++ b/packages/snaps-simulation/src/middleware/internal-methods/middleware.ts @@ -6,6 +6,7 @@ import { getAccountsHandler } from './accounts'; import { getChainIdHandler } from './chain-id'; import { getNetworkVersionHandler } from './net-version'; import { getProviderStateHandler } from './provider-state'; +import { getSwitchEthereumChainHandler } from './switch-ethereum-chain'; export type InternalMethodsMiddlewareHooks = { /** @@ -23,6 +24,7 @@ const methodHandlers = { eth_accounts: getAccountsHandler, eth_chainId: getChainIdHandler, net_version: getNetworkVersionHandler, + wallet_switchEthereumChain: getSwitchEthereumChainHandler, /* eslint-enable @typescript-eslint/naming-convention */ }; diff --git a/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.test.ts b/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.test.ts new file mode 100644 index 0000000000..436213c61b --- /dev/null +++ b/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.test.ts @@ -0,0 +1,28 @@ +import type { Json, PendingJsonRpcResponse } from '@metamask/utils'; + +import { getSwitchEthereumChainHandler } from './switch-ethereum-chain'; + +describe('getSwitchEthereumChainHandler', () => { + it('returns `null`', async () => { + const end = jest.fn(); + const result: PendingJsonRpcResponse = { + jsonrpc: '2.0' as const, + id: 1, + }; + + await getSwitchEthereumChainHandler( + { + jsonrpc: '2.0', + id: 1, + method: 'wallet_switchEthereumChain', + params: [], + }, + result, + jest.fn(), + end, + ); + + expect(end).toHaveBeenCalled(); + expect(result.result).toBeNull(); + }); +}); diff --git a/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.ts b/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.ts new file mode 100644 index 0000000000..8b71af03ae --- /dev/null +++ b/packages/snaps-simulation/src/middleware/internal-methods/switch-ethereum-chain.ts @@ -0,0 +1,32 @@ +import type { + JsonRpcEngineEndCallback, + JsonRpcEngineNextCallback, +} from '@metamask/json-rpc-engine'; +import type { + Json, + JsonRpcRequest, + PendingJsonRpcResponse, +} from '@metamask/utils'; + +/** + * A mock handler for the `wallet_switchEthereumChain` method that always + * returns `null`. + * + * @param _request - Incoming JSON-RPC request. This is ignored for this + * specific handler. + * @param response - The outgoing JSON-RPC response, modified to return the + * result. + * @param _next - The `json-rpc-engine` middleware next handler. + * @param end - The `json-rpc-engine` middleware end handler. + * @returns The response. + */ +export async function getSwitchEthereumChainHandler( + _request: JsonRpcRequest, + response: PendingJsonRpcResponse, + _next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + // hooks: GetAccountsHandlerHooks, +) { + response.result = null; + return end(); +} diff --git a/yarn.lock b/yarn.lock index 9207cf36cb..39c603aa36 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4463,7 +4463,7 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-block-tracker@npm:^11.0.4": +"@metamask/eth-block-tracker@npm:^11.0.3, @metamask/eth-block-tracker@npm:^11.0.4": version: 11.0.4 resolution: "@metamask/eth-block-tracker@npm:11.0.4" dependencies: @@ -4476,7 +4476,19 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-middleware@npm:^15.1.2": +"@metamask/eth-json-rpc-infura@npm:^10.0.0": + version: 10.0.0 + resolution: "@metamask/eth-json-rpc-infura@npm:10.0.0" + dependencies: + "@metamask/eth-json-rpc-provider": "npm:^4.1.5" + "@metamask/json-rpc-engine": "npm:^10.0.0" + "@metamask/rpc-errors": "npm:^7.0.0" + "@metamask/utils": "npm:^9.1.0" + checksum: 10/17e0147ff86c48107983035e9bda4d16fba321ee0e29733347e9338a4c795c506a2ffd643c44c9d5334886696412cf288f852d06311fed0d76edc8847ee6b8de + languageName: node + linkType: hard + +"@metamask/eth-json-rpc-middleware@npm:^15.0.1, @metamask/eth-json-rpc-middleware@npm:^15.1.2": version: 15.1.2 resolution: "@metamask/eth-json-rpc-middleware@npm:15.1.2" dependencies: @@ -4495,7 +4507,7 @@ __metadata: languageName: node linkType: hard -"@metamask/eth-json-rpc-provider@npm:^4.1.5, @metamask/eth-json-rpc-provider@npm:^4.1.7": +"@metamask/eth-json-rpc-provider@npm:^4.1.5, @metamask/eth-json-rpc-provider@npm:^4.1.6, @metamask/eth-json-rpc-provider@npm:^4.1.7": version: 4.1.7 resolution: "@metamask/eth-json-rpc-provider@npm:4.1.7" dependencies: @@ -4946,7 +4958,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/json-rpc-engine@npm:^10.0.2": +"@metamask/json-rpc-engine@npm:^10.0.0, @metamask/json-rpc-engine@npm:^10.0.1, @metamask/json-rpc-engine@npm:^10.0.2": version: 10.0.2 resolution: "@metamask/json-rpc-engine@npm:10.0.2" dependencies: @@ -5207,6 +5219,32 @@ __metadata: languageName: unknown linkType: soft +"@metamask/network-controller@npm:^22.1.1": + version: 22.1.1 + resolution: "@metamask/network-controller@npm:22.1.1" + dependencies: + "@metamask/base-controller": "npm:^7.0.2" + "@metamask/controller-utils": "npm:^11.4.4" + "@metamask/eth-block-tracker": "npm:^11.0.3" + "@metamask/eth-json-rpc-infura": "npm:^10.0.0" + "@metamask/eth-json-rpc-middleware": "npm:^15.0.1" + "@metamask/eth-json-rpc-provider": "npm:^4.1.6" + "@metamask/eth-query": "npm:^4.0.0" + "@metamask/json-rpc-engine": "npm:^10.0.1" + "@metamask/rpc-errors": "npm:^7.0.1" + "@metamask/swappable-obj-proxy": "npm:^2.3.0" + "@metamask/utils": "npm:^10.0.0" + async-mutex: "npm:^0.5.0" + fast-deep-equal: "npm:^3.1.3" + immer: "npm:^9.0.6" + loglevel: "npm:^1.8.1" + reselect: "npm:^5.1.1" + uri-js: "npm:^4.4.1" + uuid: "npm:^8.3.2" + checksum: 10/688d9ef111e66699d6129e5c4022db683d64441d437d3ad01160cefc892897115b3d5061aa174693775e3c20060b4a20c112c8a4f1c426f5f7c2f79a1839d564 + languageName: node + linkType: hard + "@metamask/network-example-snap@workspace:^, @metamask/network-example-snap@workspace:packages/examples/packages/network-access": version: 0.0.0-use.local resolution: "@metamask/network-example-snap@workspace:packages/examples/packages/network-access" @@ -5454,7 +5492,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/rpc-errors@npm:^7.0.2": +"@metamask/rpc-errors@npm:^7.0.0, @metamask/rpc-errors@npm:^7.0.1, @metamask/rpc-errors@npm:^7.0.2": version: 7.0.2 resolution: "@metamask/rpc-errors@npm:7.0.2" dependencies: @@ -5481,6 +5519,21 @@ __metadata: languageName: node linkType: hard +"@metamask/selected-network-controller@npm:^20.0.2": + version: 20.0.2 + resolution: "@metamask/selected-network-controller@npm:20.0.2" + dependencies: + "@metamask/base-controller": "npm:^7.0.2" + "@metamask/json-rpc-engine": "npm:^10.0.1" + "@metamask/swappable-obj-proxy": "npm:^2.3.0" + "@metamask/utils": "npm:^10.0.0" + peerDependencies: + "@metamask/network-controller": ^22.0.0 + "@metamask/permission-controller": ^11.0.0 + checksum: 10/02f6215d19f1bae60a50f9f73855151c3af40323ab3e7652965700bed48d2b5cc40a039408f68599b3f689cad6404f95368707089976bf1b303a4f2c7b2673c9 + languageName: node + linkType: hard + "@metamask/send-flow-example-snap@workspace:^, @metamask/send-flow-example-snap@workspace:packages/examples/packages/send-flow": version: 0.0.0-use.local resolution: "@metamask/send-flow-example-snap@workspace:packages/examples/packages/send-flow" @@ -5719,11 +5772,13 @@ __metadata: "@metamask/json-rpc-engine": "npm:^10.0.2" "@metamask/json-rpc-middleware-stream": "npm:^8.0.6" "@metamask/key-tree": "npm:^10.0.2" + "@metamask/network-controller": "npm:^22.1.1" "@metamask/object-multiplex": "npm:^2.1.0" "@metamask/permission-controller": "npm:^11.0.5" "@metamask/phishing-controller": "npm:^12.3.1" "@metamask/post-message-stream": "npm:^9.0.0" "@metamask/rpc-errors": "npm:^7.0.2" + "@metamask/selected-network-controller": "npm:^20.0.2" "@metamask/snaps-registry": "npm:^3.2.3" "@metamask/snaps-rpc-methods": "workspace:^" "@metamask/snaps-sdk": "workspace:^" @@ -6372,6 +6427,13 @@ __metadata: languageName: node linkType: hard +"@metamask/swappable-obj-proxy@npm:^2.3.0": + version: 2.3.0 + resolution: "@metamask/swappable-obj-proxy@npm:2.3.0" + checksum: 10/1255c599de9237f06df2390719d6dfcb1f168873df61bbaad5ce376efbc057e2030260b94855569313faeb412b7df9b062d209f4b0b163a3dc02f29d42139e1f + languageName: node + linkType: hard + "@metamask/template-snap@npm:^0.7.0": version: 0.7.0 resolution: "@metamask/template-snap@npm:0.7.0" @@ -6465,6 +6527,23 @@ __metadata: languageName: unknown linkType: soft +"@metamask/utils@npm:^10.0.0": + version: 10.0.1 + resolution: "@metamask/utils@npm:10.0.1" + dependencies: + "@ethereumjs/tx": "npm:^4.2.0" + "@metamask/superstruct": "npm:^3.1.0" + "@noble/hashes": "npm:^1.3.1" + "@scure/base": "npm:^1.1.3" + "@types/debug": "npm:^4.1.7" + debug: "npm:^4.3.4" + pony-cause: "npm:^2.1.10" + semver: "npm:^7.5.4" + uuid: "npm:^9.0.1" + checksum: 10/c8e3d7578d05a1da4abb6c6712ec78ef6990801269f6529f4bb237b7d6e228d10a40738ccab81ad554f2fd51670267d086dc5be1a31c6d1f7040d4c0469d9d13 + languageName: node + linkType: hard + "@metamask/utils@npm:^11.0.1": version: 11.0.1 resolution: "@metamask/utils@npm:11.0.1" @@ -6482,9 +6561,9 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^9.0.0": - version: 9.2.1 - resolution: "@metamask/utils@npm:9.2.1" +"@metamask/utils@npm:^9.0.0, @metamask/utils@npm:^9.1.0": + version: 9.3.0 + resolution: "@metamask/utils@npm:9.3.0" dependencies: "@ethereumjs/tx": "npm:^4.2.0" "@metamask/superstruct": "npm:^3.1.0" @@ -6495,7 +6574,7 @@ __metadata: pony-cause: "npm:^2.1.10" semver: "npm:^7.5.4" uuid: "npm:^9.0.1" - checksum: 10/2192797afd91af19898e107afeaf63e89b61dc7285e0a75d0cc814b5b288e4cdfc856781b01904034c4d2c1efd9bdab512af24c7e4dfe7b77a03f1f3d9dec7e8 + checksum: 10/ed6648cd973bbf3b4eb0e862903b795a99d27784c820e19f62f0bc0ddf353e98c2858d7e9aaebc0249a586391b344e35b9249d13c08e3ea0c74b23dc1c6b1558 languageName: node linkType: hard @@ -17162,10 +17241,10 @@ __metadata: languageName: node linkType: hard -"loglevel@npm:^1.6.0": - version: 1.8.1 - resolution: "loglevel@npm:1.8.1" - checksum: 10/36a786082a7e4f1d962de330122291da3a102b88dbde81a45eb92a045c38b0903783958ba39dce641440c0413da303410e7f2565f897bccad828853bd5974c86 +"loglevel@npm:^1.6.0, loglevel@npm:^1.8.1": + version: 1.9.2 + resolution: "loglevel@npm:1.9.2" + checksum: 10/6153d8db308323f7ee20130bc40309e7a976c30a10379d8666b596d9c6441965c3e074c8d7ee3347fe5cfc059c0375b6f3e8a10b93d5b813cc5547f5aa412a29 languageName: node linkType: hard @@ -20204,6 +20283,13 @@ __metadata: languageName: node linkType: hard +"reselect@npm:^5.1.1": + version: 5.1.1 + resolution: "reselect@npm:5.1.1" + checksum: 10/1fdae11a39ed9c8d85a24df19517c8372ee24fefea9cce3fae9eaad8e9cefbba5a3d4940c6fe31296b6addf76e035588c55798f7e6e147e1b7c0855f119e7fa5 + languageName: node + linkType: hard + "resolve-alpn@npm:^1.2.0": version: 1.2.1 resolution: "resolve-alpn@npm:1.2.1" @@ -22774,47 +22860,7 @@ __metadata: languageName: node linkType: hard -"vite@npm:^4.3.9": - version: 4.5.5 - resolution: "vite@npm:4.5.5" - dependencies: - esbuild: "npm:^0.18.10" - fsevents: "npm:~2.3.2" - postcss: "npm:^8.4.27" - rollup: "npm:^3.27.1" - peerDependencies: - "@types/node": ">= 14" - less: "*" - lightningcss: ^1.21.0 - sass: "*" - stylus: "*" - sugarss: "*" - terser: ^5.4.0 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - bin: - vite: bin/vite.js - checksum: 10/2e8b39e004f2b2e72506b816700b3aafaf3f85bdcb9dd9392075bb234ce7333f859a0d2078a85ce5d0039f0f659ca564a7366af587848e5166f14b136cb0ad37 - languageName: node - linkType: hard - -"vite@npm:~4.4.6": +"vite@npm:^4.3.9, vite@npm:~4.4.6": version: 4.4.12 resolution: "vite@npm:4.4.12" dependencies: