Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/gator-permissions-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Extends the `GatorPermissionsController` to enable attaching metadata(transaction hash, block timestamp) when submitting a permission revocation. ([#7503](https://github.com/MetaMask/core/pull/7503))

### Changed

- Bump `@metamask/transaction-controller` from `^62.5.0` to `^62.7.0` ([#7430](https://github.com/MetaMask/core/pull/7430), [#7494](https://github.com/MetaMask/core/pull/7494))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1235,6 +1235,71 @@ describe('GatorPermissionsController', () => {
});
});

it('should submit revocation metadata when transaction is confirmed', async () => {
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
const rootMessenger = getRootMessenger({
snapControllerHandleRequestActionHandler: mockHandleRequestHandler,
});
const messenger = getMessenger(rootMessenger);

const controller = new GatorPermissionsController({
messenger,
state: {
isGatorPermissionsEnabled: true,
gatorPermissionsProviderSnapId:
MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
},
});

const txId = 'test-tx-id';
const permissionContext = '0x1234567890abcdef1234567890abcdef12345678';
const hash = '0x-mock-hash';

await controller.addPendingRevocation({ txId, permissionContext });

// Emit transaction approved event (user confirms)
rootMessenger.publish('TransactionController:transactionApproved', {
transactionMeta: { id: txId } as TransactionMeta,
});

// Emit transaction confirmed event
rootMessenger.publish('TransactionController:transactionConfirmed', {
id: txId,
hash,
} as TransactionMeta);

await flushPromises();

// Verify submitRevocation was called
expect(mockHandleRequestHandler).toHaveBeenCalledWith({
snapId: MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
origin: 'metamask',
handler: 'onRpcRequest',
request: {
jsonrpc: '2.0',
method: 'permissionsProvider_submitRevocation',
params: {
permissionContext,
revocationMetadata: {
txHash: hash,
},
},
},
});

// Verify that permissions are refreshed after revocation (getGrantedPermissions is called)
expect(mockHandleRequestHandler).toHaveBeenCalledWith({
snapId: MOCK_GATOR_PERMISSIONS_PROVIDER_SNAP_ID,
origin: 'metamask',
handler: 'onRpcRequest',
request: {
jsonrpc: '2.0',
method: 'permissionsProvider_getGrantedPermissions',
params: { isRevoked: false },
},
});
});

it('should cleanup without adding to state when transaction is rejected by user', async () => {
const mockHandleRequestHandler = jest.fn().mockResolvedValue(undefined);
const rootMessenger = getRootMessenger({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ import {
} from './errors';
import { controllerLog } from './logger';
import { GatorPermissionsSnapRpcMethod } from './types';
import type { StoredGatorPermissionSanitized } from './types';
import type {
RevocationMetadata,
StoredGatorPermissionSanitized,
} from './types';
import type {
GatorPermissionsMap,
PermissionTypesWithCustom,
Expand Down Expand Up @@ -948,9 +951,33 @@ export default class GatorPermissionsController extends BaseController<
controllerLog('Transaction confirmed, submitting revocation', {
txId,
permissionContext,
txHash: transactionMeta.hash,
});

this.submitRevocation({ permissionContext })
// Attach metadata by parsing the confirmed transactionMeta
let revocationMetadata: RevocationMetadata | undefined;
const { hash } = transactionMeta;
if (hash === undefined) {
controllerLog(
'Failed to attach transaction hash after revocation transaction confirmed',
{
txId,
permissionContext,
error: new Error(
'Confirmed transaction is missing transaction hash',
),
},
);
} else {
revocationMetadata = {
txHash: hash as Hex,
};
}

const revocationParams = revocationMetadata
? { permissionContext, revocationMetadata }
: { permissionContext };
this.submitRevocation(revocationParams)
.catch((error) => {
controllerLog(
'Failed to submit revocation after transaction confirmed',
Expand Down
12 changes: 12 additions & 0 deletions packages/gator-permissions-controller/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,13 @@ export type DelegationDetails = Pick<
'caveats' | 'delegator' | 'delegate' | 'authority'
>;

/**
* Represents the metadata for confirmed transaction revocation.
*/
export type RevocationMetadata = {
txHash: Hex;
};

/**
* Represents the parameters for submitting a revocation.
*/
Expand All @@ -245,6 +252,11 @@ export type RevocationParams = {
* The permission context as a hex string that identifies the permission to revoke.
*/
permissionContext: Hex;

/**
* The metadata associated with the permission revocation transaction.
*/
revocationMetadata?: RevocationMetadata;
};

/**
Expand Down
Loading