From 11aa3a1fe6965fd96ec1a209c633c3952efa6401 Mon Sep 17 00:00:00 2001 From: hanzel98 Date: Tue, 23 Sep 2025 18:24:38 -0600 Subject: [PATCH 1/4] chore: addded new action on the GatorPermissionsController to allow the consumer to submitRevocation --- .../src/GatorPermissionsController.test.ts | 86 +++++++++++++++++++ .../src/GatorPermissionsController.ts | 52 ++++++++++- .../gator-permissions-controller/src/index.ts | 2 + .../gator-permissions-controller/src/types.ts | 14 +++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/packages/gator-permissions-controller/src/GatorPermissionsController.test.ts b/packages/gator-permissions-controller/src/GatorPermissionsController.test.ts index 5802328d7e0..48653a61e42 100644 --- a/packages/gator-permissions-controller/src/GatorPermissionsController.test.ts +++ b/packages/gator-permissions-controller/src/GatorPermissionsController.test.ts @@ -29,6 +29,7 @@ import type { GatorPermissionsMap, StoredGatorPermission, PermissionTypesWithCustom, + RevocationParams, } from './types'; import type { ExtractAvailableAction, @@ -688,6 +689,91 @@ describe('GatorPermissionsController', () => { ).toThrow('Failed to decode permission'); }); }); + + describe('submitRevocation', () => { + it('should successfully submit a revocation when gator permissions are enabled', async () => { + const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined); + const messenger = getMessenger( + getRootMessenger({ + snapControllerHandleRequestActionHandler: mockHandleRequestHandler, + }), + ); + + const controller = new GatorPermissionsController({ + messenger, + state: { + isGatorPermissionsEnabled: true, + gatorPermissionsProviderSnapId: + MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID, + }, + }); + + const revocationParams: RevocationParams = { + delegationHash: '0x1234567890abcdef1234567890abcdef12345678', + }; + + await controller.submitRevocation(revocationParams); + + expect(mockHandleRequestHandler).toHaveBeenCalledWith({ + snapId: MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID, + origin: 'metamask', + handler: 'onRpcRequest', + request: { + jsonrpc: '2.0', + method: 'permissionsProvider_submitRevocation', + params: revocationParams, + }, + }); + }); + + it('should throw GatorPermissionsNotEnabledError when gator permissions are disabled', async () => { + const messenger = getMessenger(); + const controller = new GatorPermissionsController({ + messenger, + state: { + isGatorPermissionsEnabled: false, + }, + }); + + const revocationParams: RevocationParams = { + delegationHash: '0x1234567890abcdef1234567890abcdef12345678', + }; + + await expect( + controller.submitRevocation(revocationParams), + ).rejects.toThrow('Gator permissions are not enabled'); + }); + + it('should throw GatorPermissionsProviderError when snap request fails', async () => { + const mockHandleRequestHandler = jest + .fn() + .mockRejectedValue(new Error('Snap request failed')); + const messenger = getMessenger( + getRootMessenger({ + snapControllerHandleRequestActionHandler: mockHandleRequestHandler, + }), + ); + + const controller = new GatorPermissionsController({ + messenger, + state: { + isGatorPermissionsEnabled: true, + gatorPermissionsProviderSnapId: + MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID, + }, + }); + + const revocationParams: RevocationParams = { + delegationHash: '0x1234567890abcdef1234567890abcdef12345678', + }; + + await expect( + controller.submitRevocation(revocationParams), + ).rejects.toThrow( + 'Failed to handle snap request to gator permissions provider for method permissionsProvider_submitRevocation', + ); + }); + }); }); /** diff --git a/packages/gator-permissions-controller/src/GatorPermissionsController.ts b/packages/gator-permissions-controller/src/GatorPermissionsController.ts index aeaa9886681..a3fc3d7fe28 100644 --- a/packages/gator-permissions-controller/src/GatorPermissionsController.ts +++ b/packages/gator-permissions-controller/src/GatorPermissionsController.ts @@ -32,6 +32,7 @@ import { type PermissionTypesWithCustom, type StoredGatorPermission, type DelegationDetails, + type RevocationParams, } from './types'; import { deserializeGatorPermissionsMap, @@ -179,6 +180,14 @@ export type GatorPermissionsControllerDecodePermissionFromPermissionContextForOr handler: GatorPermissionsController['decodePermissionFromPermissionContextForOrigin']; }; +/** + * The action which can be used to submit a revocation. + */ +export type GatorPermissionsControllerSubmitRevocationAction = { + type: `${typeof controllerName}:submitRevocation`; + handler: GatorPermissionsController['submitRevocation']; +}; + /** * All actions that {@link GatorPermissionsController} registers, to be called * externally. @@ -188,7 +197,8 @@ export type GatorPermissionsControllerActions = | GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction | GatorPermissionsControllerEnableGatorPermissionsAction | GatorPermissionsControllerDisableGatorPermissionsAction - | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction; + | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction + | GatorPermissionsControllerSubmitRevocationAction; /** * All actions that {@link GatorPermissionsController} calls internally. @@ -298,6 +308,11 @@ export default class GatorPermissionsController extends BaseController< `${controllerName}:decodePermissionFromPermissionContextForOrigin`, this.decodePermissionFromPermissionContextForOrigin.bind(this), ); + + this.messagingSystem.registerActionHandler( + `${controllerName}:submitRevocation`, + this.submitRevocation.bind(this), + ); } /** @@ -598,4 +613,39 @@ export default class GatorPermissionsController extends BaseController< }); } } + + /** + * Submits a revocation to the gator permissions provider snap. + * + * @param revocationParams - The revocation parameters containing the delegation hash. + * @returns A promise that resolves when the revocation is submitted successfully. + * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled. + * @throws {GatorPermissionsProviderError} If the snap request fails. + */ + public async submitRevocation( + revocationParams: RevocationParams, + ): Promise { + this.#assertGatorPermissionsEnabled(); + + try { + await this.messagingSystem.call('SnapController:handleRequest', { + snapId: this.state.gatorPermissionsProviderSnapId, + origin: 'metamask', + handler: HandlerType.OnRpcRequest, + request: { + jsonrpc: '2.0', + method: GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, + params: revocationParams, + }, + }); + + controllerLog('Successfully submitted revocation', revocationParams); + } catch (error) { + controllerLog('Failed to submit revocation', error); + throw new GatorPermissionsProviderError({ + method: GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, + cause: error as Error, + }); + } + } } diff --git a/packages/gator-permissions-controller/src/index.ts b/packages/gator-permissions-controller/src/index.ts index c2170783ff2..b753a64ec74 100644 --- a/packages/gator-permissions-controller/src/index.ts +++ b/packages/gator-permissions-controller/src/index.ts @@ -11,6 +11,7 @@ export type { GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction, GatorPermissionsControllerEnableGatorPermissionsAction, GatorPermissionsControllerDisableGatorPermissionsAction, + GatorPermissionsControllerSubmitRevocationAction, GatorPermissionsControllerActions, GatorPermissionsControllerEvents, GatorPermissionsControllerStateChangeEvent, @@ -31,6 +32,7 @@ export type { GatorPermissionsMapByPermissionType, GatorPermissionsListByPermissionTypeAndChainId, DelegationDetails, + RevocationParams, } from './types'; export type { diff --git a/packages/gator-permissions-controller/src/types.ts b/packages/gator-permissions-controller/src/types.ts index 6d875cc37f6..930f91c3de9 100644 --- a/packages/gator-permissions-controller/src/types.ts +++ b/packages/gator-permissions-controller/src/types.ts @@ -32,6 +32,10 @@ export enum GatorPermissionsSnapRpcMethod { * This method is used by the metamask to request a permissions provider to get granted permissions for all sites. */ PermissionProviderGetGrantedPermissions = 'permissionsProvider_getGrantedPermissions', + /** + * This method is used by the metamask to submit a revocation to the permissions provider. + */ + PermissionProviderSubmitRevocation = 'permissionsProvider_submitRevocation', } /** @@ -220,3 +224,13 @@ export type DelegationDetails = Pick< Delegation, 'caveats' | 'delegator' | 'delegate' | 'authority' >; + +/** + * Represents the parameters for submitting a revocation. + */ +export type RevocationParams = { + /** + * The delegation hash as a hex string that identifies the permission to revoke. + */ + delegationHash: Hex; +}; From f49214fa909684fc5610745becb45d0f6794664f Mon Sep 17 00:00:00 2001 From: hanzel98 Date: Wed, 24 Sep 2025 11:44:48 -0600 Subject: [PATCH 2/4] feat: implement submitRevocation action for GatorPermissionsController - Add RevocationParams type with delegationHash field - Add PermissionProviderSubmitRevocation RPC method enum - Implement submitRevocation method with proper error handling - Add comprehensive test suite with 100% coverage - Export new types in public API This enables MetaMask clients to submit permission revocations through the gator permissions provider snap using the permissionsProvider_submitRevocation RPC method. --- .../src/GatorPermissionsController.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/gator-permissions-controller/src/GatorPermissionsController.ts b/packages/gator-permissions-controller/src/GatorPermissionsController.ts index a3fc3d7fe28..d5d38fa3e1f 100644 --- a/packages/gator-permissions-controller/src/GatorPermissionsController.ts +++ b/packages/gator-permissions-controller/src/GatorPermissionsController.ts @@ -634,7 +634,8 @@ export default class GatorPermissionsController extends BaseController< handler: HandlerType.OnRpcRequest, request: { jsonrpc: '2.0', - method: GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, + method: + GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, params: revocationParams, }, }); @@ -643,7 +644,8 @@ export default class GatorPermissionsController extends BaseController< } catch (error) { controllerLog('Failed to submit revocation', error); throw new GatorPermissionsProviderError({ - method: GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, + method: + GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation, cause: error as Error, }); } From 1833a20f2e863968f1804a0daef11f019e5fdab2 Mon Sep 17 00:00:00 2001 From: hanzel98 Date: Wed, 24 Sep 2025 12:47:26 -0600 Subject: [PATCH 3/4] docs: update CHANGELOG.md for submitRevocation feature --- packages/gator-permissions-controller/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/gator-permissions-controller/CHANGELOG.md b/packages/gator-permissions-controller/CHANGELOG.md index 6c50009762c..ec39aeddc0f 100644 --- a/packages/gator-permissions-controller/CHANGELOG.md +++ b/packages/gator-permissions-controller/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Add `submitRevocation` action to submit permission revocations through the gator permissions provider snap + - New `RevocationParams` type with `delegationHash` field + - New `GatorPermissionsControllerSubmitRevocationAction` action type + - Supports `permissionsProvider_submitRevocation` RPC method + ## [0.2.0] ### Added From bf3f8c7d482672229643ccde1d5a60e9871ab7c7 Mon Sep 17 00:00:00 2001 From: hanzel98 Date: Wed, 24 Sep 2025 12:55:54 -0600 Subject: [PATCH 4/4] docs: deleted changelog --- packages/gator-permissions-controller/CHANGELOG.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/packages/gator-permissions-controller/CHANGELOG.md b/packages/gator-permissions-controller/CHANGELOG.md index ec39aeddc0f..6c50009762c 100644 --- a/packages/gator-permissions-controller/CHANGELOG.md +++ b/packages/gator-permissions-controller/CHANGELOG.md @@ -7,13 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -### Added - -- Add `submitRevocation` action to submit permission revocations through the gator permissions provider snap - - New `RevocationParams` type with `delegationHash` field - - New `GatorPermissionsControllerSubmitRevocationAction` action type - - Supports `permissionsProvider_submitRevocation` RPC method - ## [0.2.0] ### Added