diff --git a/packages/snaps-controllers/src/snaps/SnapController.test.tsx b/packages/snaps-controllers/src/snaps/SnapController.test.tsx index f8aa458bc1..057dc7e7a4 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.test.tsx +++ b/packages/snaps-controllers/src/snaps/SnapController.test.tsx @@ -6011,275 +6011,6 @@ describe('SnapController', () => { snapController.destroy(); }); - it('grants the `endowment:caip25` 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', - () => ({ - 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': {}, - 'endowment:caip25': { - caveats: [ - { - type: 'authorizedScopes', - value: { - requiredScopes: {}, - optionalScopes: { - 'eip155:1': { - accounts: [], - }, - }, - sessionProperties: {}, - isMultichainOrigin: false, - }, - }, - ], - }, - }; - - expect(messenger.call).toHaveBeenCalledWith( - 'PermissionController:grantPermissions', - { - approvedPermissions, - subject: { origin: MOCK_SNAP_ID }, - requestData: expect.any(Object), - }, - ); - - snapController.destroy(); - }); - - it('grants the `endowment:caip25` permission when updating a Snap with `endowment:ethereum-provider`', async () => { - const newVersion = '1.0.2'; - const newVersionRange = '>=1.0.1'; - - const rootMessenger = getControllerMessenger(); - const messenger = getSnapControllerMessenger(rootMessenger); - - rootMessenger.registerActionHandler( - 'SelectedNetworkController:getNetworkClientIdForDomain', - () => 'mainnet', - ); - - rootMessenger.registerActionHandler( - 'NetworkController:getNetworkClientById', - () => ({ - configuration: { - chainId: '0x1', - }, - }), - ); - - const { manifest: originalManifest } = - await getMockSnapFilesWithUpdatedChecksum({ - manifest: getSnapManifest({ - initialPermissions: { - 'endowment:page-home': {}, - }, - }), - }); - - const { manifest: updatedManifest } = - await getMockSnapFilesWithUpdatedChecksum({ - manifest: getSnapManifest({ - version: newVersion, - initialPermissions: { - 'endowment:page-home': {}, - 'endowment:ethereum-provider': {}, - }, - }), - }); - - const detectLocationMock = jest - .fn() - .mockImplementationOnce( - () => - new LoopbackLocation({ - manifest: originalManifest, - }), - ) - .mockImplementationOnce( - () => - new LoopbackLocation({ - manifest: updatedManifest, - }), - ); - - const controller = getSnapController( - getSnapControllerOptions({ - messenger, - detectSnapLocation: detectLocationMock, - }), - ); - - await controller.installSnaps(MOCK_ORIGIN, { [MOCK_SNAP_ID]: {} }); - await controller.stopSnap(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), - }, - ); - - jest.mocked(messenger.call).mockClear(); - - const result = await controller.installSnaps(MOCK_ORIGIN, { - [MOCK_SNAP_ID]: { version: newVersionRange }, - }); - - const updatedApprovedPermissions = { - 'endowment:page-home': { - caveats: null, - }, - 'endowment:ethereum-provider': {}, - 'endowment:caip25': { - caveats: [ - { - type: 'authorizedScopes', - value: { - requiredScopes: {}, - optionalScopes: { - 'eip155:1': { - accounts: [], - }, - }, - sessionProperties: {}, - isMultichainOrigin: false, - }, - }, - ], - }, - }; - - expect(messenger.call).toHaveBeenCalledWith( - 'PermissionController:grantPermissions', - { - approvedPermissions: updatedApprovedPermissions, - subject: { origin: MOCK_SNAP_ID }, - requestData: expect.any(Object), - }, - ); - - expect(result).toStrictEqual({ - [MOCK_SNAP_ID]: getTruncatedSnap({ - version: newVersion, - initialPermissions: updatedManifest.result.initialPermissions, - }), - }); - - controller.destroy(); - }); - - it('does not grant the `endowment:caip25` 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'); @@ -11804,12 +11535,12 @@ describe('SnapController', () => { const callActionSpy = jest.spyOn(messenger, 'call'); messenger.call('SnapController:revokeDynamicPermissions', MOCK_SNAP_ID, [ - 'eth_accounts', + 'endowment:caip25', ]); expect(callActionSpy).toHaveBeenCalledWith( 'PermissionController:revokePermissions', - { [MOCK_SNAP_ID]: ['eth_accounts'] }, + { [MOCK_SNAP_ID]: ['endowment:caip25'] }, ); snapController.destroy(); diff --git a/packages/snaps-controllers/src/snaps/SnapController.ts b/packages/snaps-controllers/src/snaps/SnapController.ts index c547231b21..0a547002f3 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.ts +++ b/packages/snaps-controllers/src/snaps/SnapController.ts @@ -117,12 +117,10 @@ import type { SemVerRange, CaipAssetType, JsonRpcRequest, - Hex, SemVerVersion, CaipAssetTypeOrId, } from '@metamask/utils'; import { - hexToNumber, assert, assertIsJsonRpcRequest, assertStruct, @@ -647,20 +645,6 @@ export type SnapControllerEvents = | SnapDisabled | SnapControllerStateChangeEvent; -type NetworkControllerGetNetworkClientById = { - type: `NetworkController:getNetworkClientById`; - handler: (customNetworkClientId: string) => { - configuration: { - chainId: Hex; - }; - }; -}; - -type SelectedNetworkControllerGetNetworkClientIdForDomain = { - type: `SelectedNetworkController:getNetworkClientIdForDomain`; - handler: (domain: string) => string; -}; - export type AllowedActions = | GetEndowments | GetPermissions @@ -684,9 +668,7 @@ export type AllowedActions = | Update | ResolveVersion | CreateInterface - | GetInterface - | NetworkControllerGetNetworkClientById - | SelectedNetworkControllerGetNetworkClientIdForDomain; + | GetInterface; export type AllowedEvents = | ExecutionServiceEvents @@ -953,7 +935,7 @@ export class SnapController extends BaseController< closeAllConnections, messenger, state, - dynamicPermissions = ['eth_accounts'], + dynamicPermissions = ['endowment:caip25'], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = inMilliseconds(5, Duration.Second), @@ -4380,58 +4362,6 @@ export class SnapController extends BaseController< return { newConnections, unusedConnections, approvedConnections }; } - /** - * 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.messenger.call( - 'SelectedNetworkController:getNetworkClientIdForDomain', - snapId, - ); - - const { configuration } = this.messenger.call( - 'NetworkController:getNetworkClientById', - networkClientId, - ); - - const chainId = hexToNumber(configuration.chainId); - - // This needs to be assigned to have proper type inference. - const modifiedPermissions: RequestedPermissions = { - ...newPermissions, - 'endowment:caip25': { - caveats: [ - { - type: 'authorizedScopes', - value: { - requiredScopes: {}, - optionalScopes: { - [`eip155:${chainId}`]: { - accounts: [], - }, - }, - sessionProperties: {}, - isMultichainOrigin: false, - }, - }, - ], - }, - }; - - return modifiedPermissions; - } - - return newPermissions; - } - /** * Update the permissions for a snap following an install, update or rollback. * @@ -4466,13 +4396,8 @@ export class SnapController extends BaseController< } if (isNonEmptyArray(Object.keys(newPermissions))) { - const approvedPermissions = this.#getPermissionsToGrant( - snapId, - newPermissions, - ); - this.messenger.call('PermissionController:grantPermissions', { - approvedPermissions, + approvedPermissions: newPermissions, subject: { origin: snapId }, requestData, });