@metamask-previews/gator-permissions-controller 0.4.0-preview-89bb4b56 → 0.5.0-preview-152da47f
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 +9 -1
- package/dist/GatorPermissionsController.cjs +54 -6
- package/dist/GatorPermissionsController.cjs.map +1 -1
- package/dist/GatorPermissionsController.d.cts +11 -4
- package/dist/GatorPermissionsController.d.cts.map +1 -1
- package/dist/GatorPermissionsController.d.mts +11 -4
- package/dist/GatorPermissionsController.d.mts.map +1 -1
- package/dist/GatorPermissionsController.mjs +54 -6
- package/dist/GatorPermissionsController.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.5.0]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Does not add a pending revocation if user cancels the transaction ([#7157](https://github.com/MetaMask/core/pull/7157))
|
|
15
|
+
- **BREAKING** The GatorPermissionsController messenger must allow `TransactionController:transactionApproved` and `TransactionController:transactionRejected` events ([#7157](https://github.com/MetaMask/core/pull/7157))
|
|
16
|
+
|
|
10
17
|
## [0.4.0]
|
|
11
18
|
|
|
12
19
|
### Added
|
|
@@ -67,7 +74,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
67
74
|
|
|
68
75
|
- Initial release ([#6033](https://github.com/MetaMask/core/pull/6033))
|
|
69
76
|
|
|
70
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.
|
|
77
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.5.0...HEAD
|
|
78
|
+
[0.5.0]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.4.0...@metamask/gator-permissions-controller@0.5.0
|
|
71
79
|
[0.4.0]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.3.0...@metamask/gator-permissions-controller@0.4.0
|
|
72
80
|
[0.3.0]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.2.2...@metamask/gator-permissions-controller@0.3.0
|
|
73
81
|
[0.2.2]: https://github.com/MetaMask/core/compare/@metamask/gator-permissions-controller@0.2.1...@metamask/gator-permissions-controller@0.2.2
|
|
@@ -288,8 +288,15 @@ class GatorPermissionsController extends base_controller_1.BaseController {
|
|
|
288
288
|
/**
|
|
289
289
|
* Adds a pending revocation that will be submitted once the transaction is confirmed.
|
|
290
290
|
*
|
|
291
|
-
* This method sets up listeners for
|
|
292
|
-
*
|
|
291
|
+
* This method sets up listeners for the user's approval/rejection decision and
|
|
292
|
+
* terminal transaction states (confirmed, failed, dropped). The flow is:
|
|
293
|
+
* 1. Wait for user to approve or reject the transaction
|
|
294
|
+
* 2. If approved, add to pending revocations state
|
|
295
|
+
* 3. If rejected, cleanup without adding to state
|
|
296
|
+
* 4. If confirmed, submit the revocation
|
|
297
|
+
* 5. If failed or dropped, cleanup
|
|
298
|
+
*
|
|
299
|
+
* Includes a timeout safety net to prevent memory leaks if the transaction never
|
|
293
300
|
* reaches a terminal state.
|
|
294
301
|
*
|
|
295
302
|
* @param params - The pending revocation parameters.
|
|
@@ -302,16 +309,29 @@ class GatorPermissionsController extends base_controller_1.BaseController {
|
|
|
302
309
|
permissionContext,
|
|
303
310
|
});
|
|
304
311
|
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_assertGatorPermissionsEnabled).call(this);
|
|
305
|
-
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_addPendingRevocationToState).call(this, txId, permissionContext);
|
|
306
312
|
// Track handlers and timeout for cleanup
|
|
307
313
|
const handlers = {
|
|
314
|
+
approved: undefined,
|
|
315
|
+
rejected: undefined,
|
|
308
316
|
confirmed: undefined,
|
|
309
317
|
failed: undefined,
|
|
310
318
|
dropped: undefined,
|
|
311
319
|
timeoutId: undefined,
|
|
312
320
|
};
|
|
321
|
+
// Helper to unsubscribe from approval/rejection events after decision is made
|
|
322
|
+
const cleanupApprovalHandlers = () => {
|
|
323
|
+
if (handlers.approved) {
|
|
324
|
+
this.messenger.unsubscribe('TransactionController:transactionApproved', handlers.approved);
|
|
325
|
+
handlers.approved = undefined;
|
|
326
|
+
}
|
|
327
|
+
if (handlers.rejected) {
|
|
328
|
+
this.messenger.unsubscribe('TransactionController:transactionRejected', handlers.rejected);
|
|
329
|
+
handlers.rejected = undefined;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
313
332
|
// Cleanup function to unsubscribe from all events and clear timeout
|
|
314
|
-
const cleanup = (txIdToRemove) => {
|
|
333
|
+
const cleanup = (txIdToRemove, removeFromState = true) => {
|
|
334
|
+
cleanupApprovalHandlers();
|
|
315
335
|
if (handlers.confirmed) {
|
|
316
336
|
this.messenger.unsubscribe('TransactionController:transactionConfirmed', handlers.confirmed);
|
|
317
337
|
}
|
|
@@ -324,8 +344,33 @@ class GatorPermissionsController extends base_controller_1.BaseController {
|
|
|
324
344
|
if (handlers.timeoutId !== undefined) {
|
|
325
345
|
clearTimeout(handlers.timeoutId);
|
|
326
346
|
}
|
|
327
|
-
// Remove the pending revocation from the state
|
|
328
|
-
|
|
347
|
+
// Remove the pending revocation from the state (only if it was added)
|
|
348
|
+
if (removeFromState) {
|
|
349
|
+
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_removePendingRevocationFromStateByTxId).call(this, txIdToRemove);
|
|
350
|
+
}
|
|
351
|
+
};
|
|
352
|
+
// Handle approved transaction - add to pending revocations state
|
|
353
|
+
handlers.approved = (payload) => {
|
|
354
|
+
if (payload.transactionMeta.id === txId) {
|
|
355
|
+
(0, logger_1.controllerLog)('Transaction approved by user, adding to pending revocations', {
|
|
356
|
+
txId,
|
|
357
|
+
permissionContext,
|
|
358
|
+
});
|
|
359
|
+
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_addPendingRevocationToState).call(this, txId, permissionContext);
|
|
360
|
+
// Unsubscribe from approval/rejection events since decision is made
|
|
361
|
+
cleanupApprovalHandlers();
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
// Handle rejected transaction - cleanup without adding to state
|
|
365
|
+
handlers.rejected = (payload) => {
|
|
366
|
+
if (payload.transactionMeta.id === txId) {
|
|
367
|
+
(0, logger_1.controllerLog)('Transaction rejected by user, cleaning up listeners', {
|
|
368
|
+
txId,
|
|
369
|
+
permissionContext,
|
|
370
|
+
});
|
|
371
|
+
// Don't remove from state since it was never added
|
|
372
|
+
cleanup(payload.transactionMeta.id, false);
|
|
373
|
+
}
|
|
329
374
|
};
|
|
330
375
|
// Handle confirmed transaction - submit revocation
|
|
331
376
|
handlers.confirmed = (transactionMeta) => {
|
|
@@ -365,6 +410,9 @@ class GatorPermissionsController extends base_controller_1.BaseController {
|
|
|
365
410
|
cleanup(payload.transactionMeta.id);
|
|
366
411
|
}
|
|
367
412
|
};
|
|
413
|
+
// Subscribe to user approval/rejection events
|
|
414
|
+
this.messenger.subscribe('TransactionController:transactionApproved', handlers.approved);
|
|
415
|
+
this.messenger.subscribe('TransactionController:transactionRejected', handlers.rejected);
|
|
368
416
|
// Subscribe to terminal transaction events
|
|
369
417
|
this.messenger.subscribe('TransactionController:transactionConfirmed', handlers.confirmed);
|
|
370
418
|
this.messenger.subscribe('TransactionController:transactionFailed', handlers.failed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatorPermissionsController.cjs","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Signer } from '@metamask/7715-permission-types';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest, HasSnap } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n TransactionControllerTransactionConfirmedEvent,\n TransactionControllerTransactionDroppedEvent,\n TransactionControllerTransactionFailedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport type { DecodedPermission } from './decodePermission';\nimport {\n getPermissionDataAndExpiry,\n identifyPermissionByEnforcers,\n reconstructDecodedPermission,\n} from './decodePermission';\nimport {\n GatorPermissionsFetchError,\n GatorPermissionsNotEnabledError,\n GatorPermissionsProviderError,\n OriginNotAllowedError,\n PermissionDecodingError,\n} from './errors';\nimport { controllerLog } from './logger';\nimport type { StoredGatorPermissionSanitized } from './types';\nimport {\n GatorPermissionsSnapRpcMethod,\n type GatorPermissionsMap,\n type PermissionTypesWithCustom,\n type StoredGatorPermission,\n type DelegationDetails,\n type RevocationParams,\n type PendingRevocationParams,\n} from './types';\nimport {\n deserializeGatorPermissionsMap,\n serializeGatorPermissionsMap,\n} from './utils';\n\n// === GENERAL ===\n\n// Unique name for the controller\nconst controllerName = 'GatorPermissionsController';\n\n// Default value for the gator permissions provider snap id\nconst defaultGatorPermissionsProviderSnapId =\n 'npm:@metamask/gator-permissions-snap' as SnapId;\n\nconst defaultGatorPermissionsMap: GatorPermissionsMap = {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n};\n\n/**\n * Delegation framework version used to select the correct deployed enforcer\n * contract addresses from `@metamask/delegation-deployments`.\n */\nexport const DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\n/**\n * Timeout duration for pending revocations (2 hours in milliseconds).\n * After this time, event listeners will be cleaned up to prevent memory leaks.\n */\nconst PENDING_REVOCATION_TIMEOUT = 2 * 60 * 60 * 1000;\n\nconst contractsByChainId = DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION];\n\n// === STATE ===\n\n/**\n * State shape for GatorPermissionsController\n */\nexport type GatorPermissionsControllerState = {\n /**\n * Flag that indicates if the gator permissions feature is enabled\n */\n isGatorPermissionsEnabled: boolean;\n\n /**\n * JSON serialized object containing gator permissions fetched from profile sync\n */\n gatorPermissionsMapSerialized: string;\n\n /**\n * Flag that indicates that fetching permissions is in progress\n * This is used to show a loading spinner in the UI\n */\n isFetchingGatorPermissions: boolean;\n\n /**\n * The ID of the Snap of the gator permissions provider snap\n * Default value is `@metamask/gator-permissions-snap`\n */\n gatorPermissionsProviderSnapId: SnapId;\n\n /**\n * List of gator permission pending a revocation transaction\n */\n pendingRevocations: {\n txId: string;\n permissionContext: Hex;\n }[];\n};\n\nconst gatorPermissionsControllerMetadata: StateMetadata<GatorPermissionsControllerState> =\n {\n isGatorPermissionsEnabled: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsMapSerialized: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isFetchingGatorPermissions: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsProviderSnapId: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n pendingRevocations: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n } satisfies StateMetadata<GatorPermissionsControllerState>;\n\n/**\n * Constructs the default {@link GatorPermissionsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link GatorPermissionsController} state.\n */\nexport function getDefaultGatorPermissionsControllerState(): GatorPermissionsControllerState {\n return {\n isGatorPermissionsEnabled: false,\n gatorPermissionsMapSerialized: serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n ),\n isFetchingGatorPermissions: false,\n gatorPermissionsProviderSnapId: defaultGatorPermissionsProviderSnapId,\n pendingRevocations: [],\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the\n * {@link GatorPermissionsController}.\n */\nexport type GatorPermissionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n GatorPermissionsControllerState\n>;\n\n/**\n * The action which can be used to fetch and update gator permissions.\n */\nexport type GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction = {\n type: `${typeof controllerName}:fetchAndUpdateGatorPermissions`;\n handler: GatorPermissionsController['fetchAndUpdateGatorPermissions'];\n};\n\n/**\n * The action which can be used to enable gator permissions.\n */\nexport type GatorPermissionsControllerEnableGatorPermissionsAction = {\n type: `${typeof controllerName}:enableGatorPermissions`;\n handler: GatorPermissionsController['enableGatorPermissions'];\n};\n\n/**\n * The action which can be used to disable gator permissions.\n */\nexport type GatorPermissionsControllerDisableGatorPermissionsAction = {\n type: `${typeof controllerName}:disableGatorPermissions`;\n handler: GatorPermissionsController['disableGatorPermissions'];\n};\n\nexport type GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction =\n {\n type: `${typeof controllerName}:decodePermissionFromPermissionContextForOrigin`;\n handler: GatorPermissionsController['decodePermissionFromPermissionContextForOrigin'];\n };\n\n/**\n * The action which can be used to submit a revocation.\n */\nexport type GatorPermissionsControllerSubmitRevocationAction = {\n type: `${typeof controllerName}:submitRevocation`;\n handler: GatorPermissionsController['submitRevocation'];\n};\n\n/**\n * The action which can be used to add a pending revocation.\n */\nexport type GatorPermissionsControllerAddPendingRevocationAction = {\n type: `${typeof controllerName}:addPendingRevocation`;\n handler: GatorPermissionsController['addPendingRevocation'];\n};\n\n/**\n * All actions that {@link GatorPermissionsController} registers, to be called\n * externally.\n */\nexport type GatorPermissionsControllerActions =\n | GatorPermissionsControllerGetStateAction\n | GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction\n | GatorPermissionsControllerEnableGatorPermissionsAction\n | GatorPermissionsControllerDisableGatorPermissionsAction\n | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction\n | GatorPermissionsControllerSubmitRevocationAction\n | GatorPermissionsControllerAddPendingRevocationAction;\n\n/**\n * All actions that {@link GatorPermissionsController} calls internally.\n *\n * SnapsController:handleRequest and SnapsController:has are allowed to be called\n * internally because they are used to fetch gator permissions from the Snap.\n */\ntype AllowedActions = HandleSnapRequest | HasSnap;\n\n/**\n * The event that {@link GatorPermissionsController} publishes when updating state.\n */\nexport type GatorPermissionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n GatorPermissionsControllerState\n >;\n\n/**\n * All events that {@link GatorPermissionsController} publishes, to be subscribed to\n * externally.\n */\nexport type GatorPermissionsControllerEvents =\n GatorPermissionsControllerStateChangeEvent;\n\n/**\n * Events that {@link GatorPermissionsController} is allowed to subscribe to internally.\n */\ntype AllowedEvents =\n | GatorPermissionsControllerStateChangeEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionDroppedEvent;\n\n/**\n * Messenger type for the GatorPermissionsController.\n */\nexport type GatorPermissionsControllerMessenger = Messenger<\n typeof controllerName,\n GatorPermissionsControllerActions | AllowedActions,\n GatorPermissionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller that manages gator permissions by reading from profile sync\n */\nexport default class GatorPermissionsController extends BaseController<\n typeof controllerName,\n GatorPermissionsControllerState,\n GatorPermissionsControllerMessenger\n> {\n /**\n * Creates a GatorPermissionsController instance.\n *\n * @param args - The arguments to this function.\n * @param args.messenger - Messenger used to communicate with BaseV2 controller.\n * @param args.state - Initial state to set on this controller.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: GatorPermissionsControllerMessenger;\n state?: Partial<GatorPermissionsControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: gatorPermissionsControllerMetadata,\n messenger,\n state: {\n ...getDefaultGatorPermissionsControllerState(),\n ...state,\n isFetchingGatorPermissions: false,\n },\n });\n\n this.#registerMessageHandlers();\n }\n\n #setIsFetchingGatorPermissions(isFetchingGatorPermissions: boolean) {\n this.update((state) => {\n state.isFetchingGatorPermissions = isFetchingGatorPermissions;\n });\n }\n\n #setIsGatorPermissionsEnabled(isGatorPermissionsEnabled: boolean) {\n this.update((state) => {\n state.isGatorPermissionsEnabled = isGatorPermissionsEnabled;\n });\n }\n\n #addPendingRevocationToState(txId: string, permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = [\n ...state.pendingRevocations,\n { txId, permissionContext },\n ];\n });\n }\n\n #removePendingRevocationFromStateByTxId(txId: string) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) => pendingRevocations.txId !== txId,\n );\n });\n }\n\n #removePendingRevocationFromStateByPermissionContext(permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) =>\n pendingRevocations.permissionContext !== permissionContext,\n );\n });\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchAndUpdateGatorPermissions`,\n this.fetchAndUpdateGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:enableGatorPermissions`,\n this.enableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:disableGatorPermissions`,\n this.disableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:decodePermissionFromPermissionContextForOrigin`,\n this.decodePermissionFromPermissionContextForOrigin.bind(this),\n );\n\n const submitRevocationAction = `${controllerName}:submitRevocation`;\n\n this.messenger.registerActionHandler(\n submitRevocationAction,\n this.submitRevocation.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addPendingRevocation`,\n this.addPendingRevocation.bind(this),\n );\n }\n\n /**\n * Asserts that the gator permissions are enabled.\n *\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n */\n #assertGatorPermissionsEnabled() {\n if (!this.state.isGatorPermissionsEnabled) {\n throw new GatorPermissionsNotEnabledError();\n }\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap of the gator permissions provider snap.\n * @param args.params - Optional parameters to pass to the snap method.\n * @returns A promise that resolves with the gator permissions.\n */\n async #handleSnapRequestToGatorPermissionsProvider({\n snapId,\n params,\n }: {\n snapId: SnapId;\n params?: Json;\n }): Promise<\n StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null\n > {\n try {\n const response = (await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n ...(params !== undefined && { params }),\n },\n },\n )) as StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null;\n\n return response;\n } catch (error) {\n controllerLog(\n 'Failed to handle snap request to gator permissions provider',\n error,\n );\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Sanitizes a stored gator permission by removing the fields that are not expose to MetaMask client.\n *\n * @param storedGatorPermission - The stored gator permission to sanitize.\n * @returns The sanitized stored gator permission.\n */\n #sanitizeStoredGatorPermission(\n storedGatorPermission: StoredGatorPermission<\n Signer,\n PermissionTypesWithCustom\n >,\n ): StoredGatorPermissionSanitized<Signer, PermissionTypesWithCustom> {\n const { permissionResponse } = storedGatorPermission;\n const { rules, dependencyInfo, signer, ...rest } = permissionResponse;\n return {\n ...storedGatorPermission,\n permissionResponse: {\n ...rest,\n },\n };\n }\n\n /**\n * Categorizes stored gator permissions by type and chainId.\n *\n * @param storedGatorPermissions - An array of stored gator permissions.\n * @returns The gator permissions map.\n */\n #categorizePermissionsDataByTypeAndChainId(\n storedGatorPermissions:\n | StoredGatorPermission<Signer, PermissionTypesWithCustom>[]\n | null,\n ): GatorPermissionsMap {\n if (!storedGatorPermissions) {\n return defaultGatorPermissionsMap;\n }\n\n return storedGatorPermissions.reduce(\n (gatorPermissionsMap, storedGatorPermission) => {\n const { permissionResponse } = storedGatorPermission;\n const permissionType = permissionResponse.permission.type;\n const { chainId } = permissionResponse;\n\n const sanitizedStoredGatorPermission =\n this.#sanitizeStoredGatorPermission(storedGatorPermission);\n\n switch (permissionType) {\n case 'native-token-stream':\n case 'native-token-periodic':\n case 'erc20-token-stream':\n case 'erc20-token-periodic':\n if (!gatorPermissionsMap[permissionType][chainId]) {\n gatorPermissionsMap[permissionType][chainId] = [];\n }\n\n (\n gatorPermissionsMap[permissionType][\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n default:\n if (!gatorPermissionsMap.other[chainId]) {\n gatorPermissionsMap.other[chainId] = [];\n }\n\n (\n gatorPermissionsMap.other[\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n }\n\n return gatorPermissionsMap;\n },\n {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n } as GatorPermissionsMap,\n );\n }\n\n /**\n * Gets the gator permissions map from the state.\n *\n * @returns The gator permissions map.\n */\n get gatorPermissionsMap(): GatorPermissionsMap {\n return deserializeGatorPermissionsMap(\n this.state.gatorPermissionsMapSerialized,\n );\n }\n\n /**\n * Gets the gator permissions provider snap id that is used to fetch gator permissions.\n *\n * @returns The gator permissions provider snap id.\n */\n get permissionsProviderSnapId(): SnapId {\n return this.state.gatorPermissionsProviderSnapId;\n }\n\n /**\n * Enables gator permissions for the user.\n */\n public async enableGatorPermissions() {\n this.#setIsGatorPermissionsEnabled(true);\n }\n\n /**\n * Clears the gator permissions map and disables the feature.\n */\n public async disableGatorPermissions() {\n this.update((state) => {\n state.isGatorPermissionsEnabled = false;\n state.gatorPermissionsMapSerialized = serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n );\n });\n }\n\n /**\n * Gets the pending revocations list.\n *\n * @returns The pending revocations list.\n */\n get pendingRevocations(): { txId: string; permissionContext: Hex }[] {\n return this.state.pendingRevocations;\n }\n\n /**\n * Fetches the gator permissions from profile sync and updates the state.\n *\n * @param params - Optional parameters to pass to the snap's getGrantedPermissions method.\n * @returns A promise that resolves to the gator permissions map.\n * @throws {GatorPermissionsFetchError} If the gator permissions fetch fails.\n */\n public async fetchAndUpdateGatorPermissions(\n params?: Json,\n ): Promise<GatorPermissionsMap> {\n try {\n this.#setIsFetchingGatorPermissions(true);\n this.#assertGatorPermissionsEnabled();\n\n const permissionsData =\n await this.#handleSnapRequestToGatorPermissionsProvider({\n snapId: this.state.gatorPermissionsProviderSnapId,\n params,\n });\n\n const gatorPermissionsMap =\n this.#categorizePermissionsDataByTypeAndChainId(permissionsData);\n\n this.update((state) => {\n state.gatorPermissionsMapSerialized =\n serializeGatorPermissionsMap(gatorPermissionsMap);\n });\n\n return gatorPermissionsMap;\n } catch (error) {\n controllerLog('Failed to fetch gator permissions', error);\n throw new GatorPermissionsFetchError({\n message: 'Failed to fetch gator permissions',\n cause: error as Error,\n });\n } finally {\n this.#setIsFetchingGatorPermissions(false);\n }\n }\n\n /**\n * Decodes a permission context into a structured permission for a specific origin.\n *\n * This method validates the caller origin, decodes the provided `permissionContext`\n * into delegations, identifies the permission type from the caveat enforcers,\n * extracts the permission-specific data and expiry, and reconstructs a\n * {@link DecodedPermission} containing chainId, account addresses, signer, type and data.\n *\n * @param args - The arguments to this function.\n * @param args.origin - The caller's origin; must match the configured permissions provider Snap id.\n * @param args.chainId - Numeric EIP-155 chain id used for resolving enforcer contracts and encoding.\n * @param args.delegation - delegation representing the permission.\n * @param args.metadata - metadata included in the request.\n * @param args.metadata.justification - the justification as specified in the request metadata.\n * @param args.metadata.origin - the origin as specified in the request metadata.\n *\n * @returns A decoded permission object suitable for UI consumption and follow-up actions.\n * @throws If the origin is not allowed, the context cannot be decoded into exactly one delegation,\n * or the enforcers/terms do not match a supported permission type.\n */\n public decodePermissionFromPermissionContextForOrigin({\n origin,\n chainId,\n delegation: { caveats, delegator, delegate, authority },\n metadata: { justification, origin: specifiedOrigin },\n }: {\n origin: string;\n chainId: number;\n metadata: {\n justification: string;\n origin: string;\n };\n delegation: DelegationDetails;\n }): DecodedPermission {\n if (origin !== this.permissionsProviderSnapId) {\n throw new OriginNotAllowedError({ origin });\n }\n\n const contracts = contractsByChainId[chainId];\n\n if (!contracts) {\n throw new Error(`Contracts not found for chainId: ${chainId}`);\n }\n\n try {\n const enforcers = caveats.map((caveat) => caveat.enforcer);\n\n const permissionType = identifyPermissionByEnforcers({\n enforcers,\n contracts,\n });\n\n const { expiry, data } = getPermissionDataAndExpiry({\n contracts,\n caveats,\n permissionType,\n });\n\n const permission = reconstructDecodedPermission({\n chainId,\n permissionType,\n delegator,\n delegate,\n authority,\n expiry,\n data,\n justification,\n specifiedOrigin,\n });\n\n return permission;\n } catch (error) {\n throw new PermissionDecodingError({\n cause: error as Error,\n });\n }\n }\n\n /**\n * Submits a revocation to the gator permissions provider snap.\n *\n * @param revocationParams - The revocation parameters containing the permission context.\n * @returns A promise that resolves when the revocation is submitted successfully.\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n * @throws {GatorPermissionsProviderError} If the snap request fails.\n */\n public async submitRevocation(\n revocationParams: RevocationParams,\n ): Promise<void> {\n controllerLog('submitRevocation method called', {\n permissionContext: revocationParams.permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n try {\n const snapRequest = {\n snapId: this.state.gatorPermissionsProviderSnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n params: revocationParams,\n },\n };\n\n const result = await this.messenger.call(\n 'SnapController:handleRequest',\n snapRequest,\n );\n\n this.#removePendingRevocationFromStateByPermissionContext(\n revocationParams.permissionContext,\n );\n\n controllerLog('Successfully submitted revocation', {\n permissionContext: revocationParams.permissionContext,\n result,\n });\n } catch (error) {\n controllerLog('Failed to submit revocation', {\n error,\n permissionContext: revocationParams.permissionContext,\n });\n\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Adds a pending revocation that will be submitted once the transaction is confirmed.\n *\n * This method sets up listeners for terminal transaction states (confirmed, failed, dropped)\n * and includes a timeout safety net to prevent memory leaks if the transaction never\n * reaches a terminal state.\n *\n * @param params - The pending revocation parameters.\n * @returns A promise that resolves when the listener is set up.\n */\n public async addPendingRevocation(\n params: PendingRevocationParams,\n ): Promise<void> {\n const { txId, permissionContext } = params;\n\n controllerLog('addPendingRevocation method called', {\n txId,\n permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n this.#addPendingRevocationToState(txId, permissionContext);\n\n type PendingRevocationHandlers = {\n confirmed?: (\n ...args: TransactionControllerTransactionConfirmedEvent['payload']\n ) => void;\n failed?: (\n ...args: TransactionControllerTransactionFailedEvent['payload']\n ) => void;\n dropped?: (\n ...args: TransactionControllerTransactionDroppedEvent['payload']\n ) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n };\n\n // Track handlers and timeout for cleanup\n const handlers: PendingRevocationHandlers = {\n confirmed: undefined,\n failed: undefined,\n dropped: undefined,\n timeoutId: undefined,\n };\n\n // Cleanup function to unsubscribe from all events and clear timeout\n const cleanup = (txIdToRemove: string) => {\n if (handlers.confirmed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n }\n if (handlers.failed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n }\n if (handlers.dropped) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n }\n if (handlers.timeoutId !== undefined) {\n clearTimeout(handlers.timeoutId);\n }\n\n // Remove the pending revocation from the state\n this.#removePendingRevocationFromStateByTxId(txIdToRemove);\n };\n\n // Handle confirmed transaction - submit revocation\n handlers.confirmed = (transactionMeta) => {\n if (transactionMeta.id === txId) {\n controllerLog('Transaction confirmed, submitting revocation', {\n txId,\n permissionContext,\n });\n\n this.submitRevocation({ permissionContext }).catch((error) => {\n controllerLog(\n 'Failed to submit revocation after transaction confirmed',\n {\n txId,\n permissionContext,\n error,\n },\n );\n });\n\n cleanup(transactionMeta.id);\n }\n };\n\n // Handle failed transaction - cleanup without submitting revocation\n handlers.failed = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction failed, cleaning up revocation listener', {\n txId,\n permissionContext,\n error: payload.error,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Handle dropped transaction - cleanup without submitting revocation\n handlers.dropped = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction dropped, cleaning up revocation listener', {\n txId,\n permissionContext,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Subscribe to terminal transaction events\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n\n // Set timeout as safety net to prevent memory leaks\n handlers.timeoutId = setTimeout(() => {\n controllerLog('Pending revocation timed out, cleaning up listeners', {\n txId,\n permissionContext,\n });\n cleanup(txId);\n }, PENDING_REVOCATION_TIMEOUT);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"GatorPermissionsController.cjs","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Signer } from '@metamask/7715-permission-types';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest, HasSnap } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n TransactionControllerTransactionApprovedEvent,\n TransactionControllerTransactionConfirmedEvent,\n TransactionControllerTransactionDroppedEvent,\n TransactionControllerTransactionFailedEvent,\n TransactionControllerTransactionRejectedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport type { DecodedPermission } from './decodePermission';\nimport {\n getPermissionDataAndExpiry,\n identifyPermissionByEnforcers,\n reconstructDecodedPermission,\n} from './decodePermission';\nimport {\n GatorPermissionsFetchError,\n GatorPermissionsNotEnabledError,\n GatorPermissionsProviderError,\n OriginNotAllowedError,\n PermissionDecodingError,\n} from './errors';\nimport { controllerLog } from './logger';\nimport type { StoredGatorPermissionSanitized } from './types';\nimport {\n GatorPermissionsSnapRpcMethod,\n type GatorPermissionsMap,\n type PermissionTypesWithCustom,\n type StoredGatorPermission,\n type DelegationDetails,\n type RevocationParams,\n type PendingRevocationParams,\n} from './types';\nimport {\n deserializeGatorPermissionsMap,\n serializeGatorPermissionsMap,\n} from './utils';\n\n// === GENERAL ===\n\n// Unique name for the controller\nconst controllerName = 'GatorPermissionsController';\n\n// Default value for the gator permissions provider snap id\nconst defaultGatorPermissionsProviderSnapId =\n 'npm:@metamask/gator-permissions-snap' as SnapId;\n\nconst defaultGatorPermissionsMap: GatorPermissionsMap = {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n};\n\n/**\n * Delegation framework version used to select the correct deployed enforcer\n * contract addresses from `@metamask/delegation-deployments`.\n */\nexport const DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\n/**\n * Timeout duration for pending revocations (2 hours in milliseconds).\n * After this time, event listeners will be cleaned up to prevent memory leaks.\n */\nconst PENDING_REVOCATION_TIMEOUT = 2 * 60 * 60 * 1000;\n\nconst contractsByChainId = DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION];\n\n// === STATE ===\n\n/**\n * State shape for GatorPermissionsController\n */\nexport type GatorPermissionsControllerState = {\n /**\n * Flag that indicates if the gator permissions feature is enabled\n */\n isGatorPermissionsEnabled: boolean;\n\n /**\n * JSON serialized object containing gator permissions fetched from profile sync\n */\n gatorPermissionsMapSerialized: string;\n\n /**\n * Flag that indicates that fetching permissions is in progress\n * This is used to show a loading spinner in the UI\n */\n isFetchingGatorPermissions: boolean;\n\n /**\n * The ID of the Snap of the gator permissions provider snap\n * Default value is `@metamask/gator-permissions-snap`\n */\n gatorPermissionsProviderSnapId: SnapId;\n\n /**\n * List of gator permission pending a revocation transaction\n */\n pendingRevocations: {\n txId: string;\n permissionContext: Hex;\n }[];\n};\n\nconst gatorPermissionsControllerMetadata: StateMetadata<GatorPermissionsControllerState> =\n {\n isGatorPermissionsEnabled: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsMapSerialized: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isFetchingGatorPermissions: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsProviderSnapId: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n pendingRevocations: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n } satisfies StateMetadata<GatorPermissionsControllerState>;\n\n/**\n * Constructs the default {@link GatorPermissionsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link GatorPermissionsController} state.\n */\nexport function getDefaultGatorPermissionsControllerState(): GatorPermissionsControllerState {\n return {\n isGatorPermissionsEnabled: false,\n gatorPermissionsMapSerialized: serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n ),\n isFetchingGatorPermissions: false,\n gatorPermissionsProviderSnapId: defaultGatorPermissionsProviderSnapId,\n pendingRevocations: [],\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the\n * {@link GatorPermissionsController}.\n */\nexport type GatorPermissionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n GatorPermissionsControllerState\n>;\n\n/**\n * The action which can be used to fetch and update gator permissions.\n */\nexport type GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction = {\n type: `${typeof controllerName}:fetchAndUpdateGatorPermissions`;\n handler: GatorPermissionsController['fetchAndUpdateGatorPermissions'];\n};\n\n/**\n * The action which can be used to enable gator permissions.\n */\nexport type GatorPermissionsControllerEnableGatorPermissionsAction = {\n type: `${typeof controllerName}:enableGatorPermissions`;\n handler: GatorPermissionsController['enableGatorPermissions'];\n};\n\n/**\n * The action which can be used to disable gator permissions.\n */\nexport type GatorPermissionsControllerDisableGatorPermissionsAction = {\n type: `${typeof controllerName}:disableGatorPermissions`;\n handler: GatorPermissionsController['disableGatorPermissions'];\n};\n\nexport type GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction =\n {\n type: `${typeof controllerName}:decodePermissionFromPermissionContextForOrigin`;\n handler: GatorPermissionsController['decodePermissionFromPermissionContextForOrigin'];\n };\n\n/**\n * The action which can be used to submit a revocation.\n */\nexport type GatorPermissionsControllerSubmitRevocationAction = {\n type: `${typeof controllerName}:submitRevocation`;\n handler: GatorPermissionsController['submitRevocation'];\n};\n\n/**\n * The action which can be used to add a pending revocation.\n */\nexport type GatorPermissionsControllerAddPendingRevocationAction = {\n type: `${typeof controllerName}:addPendingRevocation`;\n handler: GatorPermissionsController['addPendingRevocation'];\n};\n\n/**\n * All actions that {@link GatorPermissionsController} registers, to be called\n * externally.\n */\nexport type GatorPermissionsControllerActions =\n | GatorPermissionsControllerGetStateAction\n | GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction\n | GatorPermissionsControllerEnableGatorPermissionsAction\n | GatorPermissionsControllerDisableGatorPermissionsAction\n | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction\n | GatorPermissionsControllerSubmitRevocationAction\n | GatorPermissionsControllerAddPendingRevocationAction;\n\n/**\n * All actions that {@link GatorPermissionsController} calls internally.\n *\n * SnapsController:handleRequest and SnapsController:has are allowed to be called\n * internally because they are used to fetch gator permissions from the Snap.\n */\ntype AllowedActions = HandleSnapRequest | HasSnap;\n\n/**\n * The event that {@link GatorPermissionsController} publishes when updating state.\n */\nexport type GatorPermissionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n GatorPermissionsControllerState\n >;\n\n/**\n * All events that {@link GatorPermissionsController} publishes, to be subscribed to\n * externally.\n */\nexport type GatorPermissionsControllerEvents =\n GatorPermissionsControllerStateChangeEvent;\n\n/**\n * Events that {@link GatorPermissionsController} is allowed to subscribe to internally.\n */\ntype AllowedEvents =\n | GatorPermissionsControllerStateChangeEvent\n | TransactionControllerTransactionApprovedEvent\n | TransactionControllerTransactionRejectedEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionDroppedEvent;\n\n/**\n * Messenger type for the GatorPermissionsController.\n */\nexport type GatorPermissionsControllerMessenger = Messenger<\n typeof controllerName,\n GatorPermissionsControllerActions | AllowedActions,\n GatorPermissionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller that manages gator permissions by reading from profile sync\n */\nexport default class GatorPermissionsController extends BaseController<\n typeof controllerName,\n GatorPermissionsControllerState,\n GatorPermissionsControllerMessenger\n> {\n /**\n * Creates a GatorPermissionsController instance.\n *\n * @param args - The arguments to this function.\n * @param args.messenger - Messenger used to communicate with BaseV2 controller.\n * @param args.state - Initial state to set on this controller.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: GatorPermissionsControllerMessenger;\n state?: Partial<GatorPermissionsControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: gatorPermissionsControllerMetadata,\n messenger,\n state: {\n ...getDefaultGatorPermissionsControllerState(),\n ...state,\n isFetchingGatorPermissions: false,\n },\n });\n\n this.#registerMessageHandlers();\n }\n\n #setIsFetchingGatorPermissions(isFetchingGatorPermissions: boolean) {\n this.update((state) => {\n state.isFetchingGatorPermissions = isFetchingGatorPermissions;\n });\n }\n\n #setIsGatorPermissionsEnabled(isGatorPermissionsEnabled: boolean) {\n this.update((state) => {\n state.isGatorPermissionsEnabled = isGatorPermissionsEnabled;\n });\n }\n\n #addPendingRevocationToState(txId: string, permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = [\n ...state.pendingRevocations,\n { txId, permissionContext },\n ];\n });\n }\n\n #removePendingRevocationFromStateByTxId(txId: string) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) => pendingRevocations.txId !== txId,\n );\n });\n }\n\n #removePendingRevocationFromStateByPermissionContext(permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) =>\n pendingRevocations.permissionContext !== permissionContext,\n );\n });\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchAndUpdateGatorPermissions`,\n this.fetchAndUpdateGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:enableGatorPermissions`,\n this.enableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:disableGatorPermissions`,\n this.disableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:decodePermissionFromPermissionContextForOrigin`,\n this.decodePermissionFromPermissionContextForOrigin.bind(this),\n );\n\n const submitRevocationAction = `${controllerName}:submitRevocation`;\n\n this.messenger.registerActionHandler(\n submitRevocationAction,\n this.submitRevocation.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addPendingRevocation`,\n this.addPendingRevocation.bind(this),\n );\n }\n\n /**\n * Asserts that the gator permissions are enabled.\n *\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n */\n #assertGatorPermissionsEnabled() {\n if (!this.state.isGatorPermissionsEnabled) {\n throw new GatorPermissionsNotEnabledError();\n }\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap of the gator permissions provider snap.\n * @param args.params - Optional parameters to pass to the snap method.\n * @returns A promise that resolves with the gator permissions.\n */\n async #handleSnapRequestToGatorPermissionsProvider({\n snapId,\n params,\n }: {\n snapId: SnapId;\n params?: Json;\n }): Promise<\n StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null\n > {\n try {\n const response = (await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n ...(params !== undefined && { params }),\n },\n },\n )) as StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null;\n\n return response;\n } catch (error) {\n controllerLog(\n 'Failed to handle snap request to gator permissions provider',\n error,\n );\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Sanitizes a stored gator permission by removing the fields that are not expose to MetaMask client.\n *\n * @param storedGatorPermission - The stored gator permission to sanitize.\n * @returns The sanitized stored gator permission.\n */\n #sanitizeStoredGatorPermission(\n storedGatorPermission: StoredGatorPermission<\n Signer,\n PermissionTypesWithCustom\n >,\n ): StoredGatorPermissionSanitized<Signer, PermissionTypesWithCustom> {\n const { permissionResponse } = storedGatorPermission;\n const { rules, dependencyInfo, signer, ...rest } = permissionResponse;\n return {\n ...storedGatorPermission,\n permissionResponse: {\n ...rest,\n },\n };\n }\n\n /**\n * Categorizes stored gator permissions by type and chainId.\n *\n * @param storedGatorPermissions - An array of stored gator permissions.\n * @returns The gator permissions map.\n */\n #categorizePermissionsDataByTypeAndChainId(\n storedGatorPermissions:\n | StoredGatorPermission<Signer, PermissionTypesWithCustom>[]\n | null,\n ): GatorPermissionsMap {\n if (!storedGatorPermissions) {\n return defaultGatorPermissionsMap;\n }\n\n return storedGatorPermissions.reduce(\n (gatorPermissionsMap, storedGatorPermission) => {\n const { permissionResponse } = storedGatorPermission;\n const permissionType = permissionResponse.permission.type;\n const { chainId } = permissionResponse;\n\n const sanitizedStoredGatorPermission =\n this.#sanitizeStoredGatorPermission(storedGatorPermission);\n\n switch (permissionType) {\n case 'native-token-stream':\n case 'native-token-periodic':\n case 'erc20-token-stream':\n case 'erc20-token-periodic':\n if (!gatorPermissionsMap[permissionType][chainId]) {\n gatorPermissionsMap[permissionType][chainId] = [];\n }\n\n (\n gatorPermissionsMap[permissionType][\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n default:\n if (!gatorPermissionsMap.other[chainId]) {\n gatorPermissionsMap.other[chainId] = [];\n }\n\n (\n gatorPermissionsMap.other[\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n }\n\n return gatorPermissionsMap;\n },\n {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n } as GatorPermissionsMap,\n );\n }\n\n /**\n * Gets the gator permissions map from the state.\n *\n * @returns The gator permissions map.\n */\n get gatorPermissionsMap(): GatorPermissionsMap {\n return deserializeGatorPermissionsMap(\n this.state.gatorPermissionsMapSerialized,\n );\n }\n\n /**\n * Gets the gator permissions provider snap id that is used to fetch gator permissions.\n *\n * @returns The gator permissions provider snap id.\n */\n get permissionsProviderSnapId(): SnapId {\n return this.state.gatorPermissionsProviderSnapId;\n }\n\n /**\n * Enables gator permissions for the user.\n */\n public async enableGatorPermissions() {\n this.#setIsGatorPermissionsEnabled(true);\n }\n\n /**\n * Clears the gator permissions map and disables the feature.\n */\n public async disableGatorPermissions() {\n this.update((state) => {\n state.isGatorPermissionsEnabled = false;\n state.gatorPermissionsMapSerialized = serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n );\n });\n }\n\n /**\n * Gets the pending revocations list.\n *\n * @returns The pending revocations list.\n */\n get pendingRevocations(): { txId: string; permissionContext: Hex }[] {\n return this.state.pendingRevocations;\n }\n\n /**\n * Fetches the gator permissions from profile sync and updates the state.\n *\n * @param params - Optional parameters to pass to the snap's getGrantedPermissions method.\n * @returns A promise that resolves to the gator permissions map.\n * @throws {GatorPermissionsFetchError} If the gator permissions fetch fails.\n */\n public async fetchAndUpdateGatorPermissions(\n params?: Json,\n ): Promise<GatorPermissionsMap> {\n try {\n this.#setIsFetchingGatorPermissions(true);\n this.#assertGatorPermissionsEnabled();\n\n const permissionsData =\n await this.#handleSnapRequestToGatorPermissionsProvider({\n snapId: this.state.gatorPermissionsProviderSnapId,\n params,\n });\n\n const gatorPermissionsMap =\n this.#categorizePermissionsDataByTypeAndChainId(permissionsData);\n\n this.update((state) => {\n state.gatorPermissionsMapSerialized =\n serializeGatorPermissionsMap(gatorPermissionsMap);\n });\n\n return gatorPermissionsMap;\n } catch (error) {\n controllerLog('Failed to fetch gator permissions', error);\n throw new GatorPermissionsFetchError({\n message: 'Failed to fetch gator permissions',\n cause: error as Error,\n });\n } finally {\n this.#setIsFetchingGatorPermissions(false);\n }\n }\n\n /**\n * Decodes a permission context into a structured permission for a specific origin.\n *\n * This method validates the caller origin, decodes the provided `permissionContext`\n * into delegations, identifies the permission type from the caveat enforcers,\n * extracts the permission-specific data and expiry, and reconstructs a\n * {@link DecodedPermission} containing chainId, account addresses, signer, type and data.\n *\n * @param args - The arguments to this function.\n * @param args.origin - The caller's origin; must match the configured permissions provider Snap id.\n * @param args.chainId - Numeric EIP-155 chain id used for resolving enforcer contracts and encoding.\n * @param args.delegation - delegation representing the permission.\n * @param args.metadata - metadata included in the request.\n * @param args.metadata.justification - the justification as specified in the request metadata.\n * @param args.metadata.origin - the origin as specified in the request metadata.\n *\n * @returns A decoded permission object suitable for UI consumption and follow-up actions.\n * @throws If the origin is not allowed, the context cannot be decoded into exactly one delegation,\n * or the enforcers/terms do not match a supported permission type.\n */\n public decodePermissionFromPermissionContextForOrigin({\n origin,\n chainId,\n delegation: { caveats, delegator, delegate, authority },\n metadata: { justification, origin: specifiedOrigin },\n }: {\n origin: string;\n chainId: number;\n metadata: {\n justification: string;\n origin: string;\n };\n delegation: DelegationDetails;\n }): DecodedPermission {\n if (origin !== this.permissionsProviderSnapId) {\n throw new OriginNotAllowedError({ origin });\n }\n\n const contracts = contractsByChainId[chainId];\n\n if (!contracts) {\n throw new Error(`Contracts not found for chainId: ${chainId}`);\n }\n\n try {\n const enforcers = caveats.map((caveat) => caveat.enforcer);\n\n const permissionType = identifyPermissionByEnforcers({\n enforcers,\n contracts,\n });\n\n const { expiry, data } = getPermissionDataAndExpiry({\n contracts,\n caveats,\n permissionType,\n });\n\n const permission = reconstructDecodedPermission({\n chainId,\n permissionType,\n delegator,\n delegate,\n authority,\n expiry,\n data,\n justification,\n specifiedOrigin,\n });\n\n return permission;\n } catch (error) {\n throw new PermissionDecodingError({\n cause: error as Error,\n });\n }\n }\n\n /**\n * Submits a revocation to the gator permissions provider snap.\n *\n * @param revocationParams - The revocation parameters containing the permission context.\n * @returns A promise that resolves when the revocation is submitted successfully.\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n * @throws {GatorPermissionsProviderError} If the snap request fails.\n */\n public async submitRevocation(\n revocationParams: RevocationParams,\n ): Promise<void> {\n controllerLog('submitRevocation method called', {\n permissionContext: revocationParams.permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n try {\n const snapRequest = {\n snapId: this.state.gatorPermissionsProviderSnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n params: revocationParams,\n },\n };\n\n const result = await this.messenger.call(\n 'SnapController:handleRequest',\n snapRequest,\n );\n\n this.#removePendingRevocationFromStateByPermissionContext(\n revocationParams.permissionContext,\n );\n\n controllerLog('Successfully submitted revocation', {\n permissionContext: revocationParams.permissionContext,\n result,\n });\n } catch (error) {\n controllerLog('Failed to submit revocation', {\n error,\n permissionContext: revocationParams.permissionContext,\n });\n\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Adds a pending revocation that will be submitted once the transaction is confirmed.\n *\n * This method sets up listeners for the user's approval/rejection decision and\n * terminal transaction states (confirmed, failed, dropped). The flow is:\n * 1. Wait for user to approve or reject the transaction\n * 2. If approved, add to pending revocations state\n * 3. If rejected, cleanup without adding to state\n * 4. If confirmed, submit the revocation\n * 5. If failed or dropped, cleanup\n *\n * Includes a timeout safety net to prevent memory leaks if the transaction never\n * reaches a terminal state.\n *\n * @param params - The pending revocation parameters.\n * @returns A promise that resolves when the listener is set up.\n */\n public async addPendingRevocation(\n params: PendingRevocationParams,\n ): Promise<void> {\n const { txId, permissionContext } = params;\n\n controllerLog('addPendingRevocation method called', {\n txId,\n permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n type PendingRevocationHandlers = {\n approved?: (\n ...args: TransactionControllerTransactionApprovedEvent['payload']\n ) => void;\n rejected?: (\n ...args: TransactionControllerTransactionRejectedEvent['payload']\n ) => void;\n confirmed?: (\n ...args: TransactionControllerTransactionConfirmedEvent['payload']\n ) => void;\n failed?: (\n ...args: TransactionControllerTransactionFailedEvent['payload']\n ) => void;\n dropped?: (\n ...args: TransactionControllerTransactionDroppedEvent['payload']\n ) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n };\n\n // Track handlers and timeout for cleanup\n const handlers: PendingRevocationHandlers = {\n approved: undefined,\n rejected: undefined,\n confirmed: undefined,\n failed: undefined,\n dropped: undefined,\n timeoutId: undefined,\n };\n\n // Helper to unsubscribe from approval/rejection events after decision is made\n const cleanupApprovalHandlers = () => {\n if (handlers.approved) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionApproved',\n handlers.approved,\n );\n handlers.approved = undefined;\n }\n if (handlers.rejected) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionRejected',\n handlers.rejected,\n );\n handlers.rejected = undefined;\n }\n };\n\n // Cleanup function to unsubscribe from all events and clear timeout\n const cleanup = (txIdToRemove: string, removeFromState = true) => {\n cleanupApprovalHandlers();\n if (handlers.confirmed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n }\n if (handlers.failed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n }\n if (handlers.dropped) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n }\n if (handlers.timeoutId !== undefined) {\n clearTimeout(handlers.timeoutId);\n }\n\n // Remove the pending revocation from the state (only if it was added)\n if (removeFromState) {\n this.#removePendingRevocationFromStateByTxId(txIdToRemove);\n }\n };\n\n // Handle approved transaction - add to pending revocations state\n handlers.approved = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog(\n 'Transaction approved by user, adding to pending revocations',\n {\n txId,\n permissionContext,\n },\n );\n\n this.#addPendingRevocationToState(txId, permissionContext);\n\n // Unsubscribe from approval/rejection events since decision is made\n cleanupApprovalHandlers();\n }\n };\n\n // Handle rejected transaction - cleanup without adding to state\n handlers.rejected = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction rejected by user, cleaning up listeners', {\n txId,\n permissionContext,\n });\n\n // Don't remove from state since it was never added\n cleanup(payload.transactionMeta.id, false);\n }\n };\n\n // Handle confirmed transaction - submit revocation\n handlers.confirmed = (transactionMeta) => {\n if (transactionMeta.id === txId) {\n controllerLog('Transaction confirmed, submitting revocation', {\n txId,\n permissionContext,\n });\n\n this.submitRevocation({ permissionContext }).catch((error) => {\n controllerLog(\n 'Failed to submit revocation after transaction confirmed',\n {\n txId,\n permissionContext,\n error,\n },\n );\n });\n\n cleanup(transactionMeta.id);\n }\n };\n\n // Handle failed transaction - cleanup without submitting revocation\n handlers.failed = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction failed, cleaning up revocation listener', {\n txId,\n permissionContext,\n error: payload.error,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Handle dropped transaction - cleanup without submitting revocation\n handlers.dropped = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction dropped, cleaning up revocation listener', {\n txId,\n permissionContext,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Subscribe to user approval/rejection events\n this.messenger.subscribe(\n 'TransactionController:transactionApproved',\n handlers.approved,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionRejected',\n handlers.rejected,\n );\n\n // Subscribe to terminal transaction events\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n\n // Set timeout as safety net to prevent memory leaks\n handlers.timeoutId = setTimeout(() => {\n controllerLog('Pending revocation timed out, cleaning up listeners', {\n txId,\n permissionContext,\n });\n cleanup(txId);\n }, PENDING_REVOCATION_TIMEOUT);\n }\n}\n"]}
|
|
@@ -3,7 +3,7 @@ import { BaseController } from "@metamask/base-controller";
|
|
|
3
3
|
import type { Messenger } from "@metamask/messenger";
|
|
4
4
|
import type { HandleSnapRequest, HasSnap } from "@metamask/snaps-controllers";
|
|
5
5
|
import type { SnapId } from "@metamask/snaps-sdk";
|
|
6
|
-
import type { TransactionControllerTransactionConfirmedEvent, TransactionControllerTransactionDroppedEvent, TransactionControllerTransactionFailedEvent } from "@metamask/transaction-controller";
|
|
6
|
+
import type { TransactionControllerTransactionApprovedEvent, TransactionControllerTransactionConfirmedEvent, TransactionControllerTransactionDroppedEvent, TransactionControllerTransactionFailedEvent, TransactionControllerTransactionRejectedEvent } from "@metamask/transaction-controller";
|
|
7
7
|
import type { Hex, Json } from "@metamask/utils";
|
|
8
8
|
import type { DecodedPermission } from "./decodePermission/index.cjs";
|
|
9
9
|
import { type GatorPermissionsMap, type DelegationDetails, type RevocationParams, type PendingRevocationParams } from "./types.cjs";
|
|
@@ -120,7 +120,7 @@ export type GatorPermissionsControllerEvents = GatorPermissionsControllerStateCh
|
|
|
120
120
|
/**
|
|
121
121
|
* Events that {@link GatorPermissionsController} is allowed to subscribe to internally.
|
|
122
122
|
*/
|
|
123
|
-
type AllowedEvents = GatorPermissionsControllerStateChangeEvent | TransactionControllerTransactionConfirmedEvent | TransactionControllerTransactionFailedEvent | TransactionControllerTransactionDroppedEvent;
|
|
123
|
+
type AllowedEvents = GatorPermissionsControllerStateChangeEvent | TransactionControllerTransactionApprovedEvent | TransactionControllerTransactionRejectedEvent | TransactionControllerTransactionConfirmedEvent | TransactionControllerTransactionFailedEvent | TransactionControllerTransactionDroppedEvent;
|
|
124
124
|
/**
|
|
125
125
|
* Messenger type for the GatorPermissionsController.
|
|
126
126
|
*/
|
|
@@ -219,8 +219,15 @@ export default class GatorPermissionsController extends BaseController<typeof co
|
|
|
219
219
|
/**
|
|
220
220
|
* Adds a pending revocation that will be submitted once the transaction is confirmed.
|
|
221
221
|
*
|
|
222
|
-
* This method sets up listeners for
|
|
223
|
-
*
|
|
222
|
+
* This method sets up listeners for the user's approval/rejection decision and
|
|
223
|
+
* terminal transaction states (confirmed, failed, dropped). The flow is:
|
|
224
|
+
* 1. Wait for user to approve or reject the transaction
|
|
225
|
+
* 2. If approved, add to pending revocations state
|
|
226
|
+
* 3. If rejected, cleanup without adding to state
|
|
227
|
+
* 4. If confirmed, submit the revocation
|
|
228
|
+
* 5. If failed or dropped, cleanup
|
|
229
|
+
*
|
|
230
|
+
* Includes a timeout safety net to prevent memory leaks if the transaction never
|
|
224
231
|
* reaches a terminal state.
|
|
225
232
|
*
|
|
226
233
|
* @param params - The pending revocation parameters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatorPermissionsController.d.cts","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,oCAAoC;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAElD,OAAO,KAAK,EACV,8CAA8C,EAC9C,4CAA4C,EAC5C,2CAA2C,
|
|
1
|
+
{"version":3,"file":"GatorPermissionsController.d.cts","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { BaseController } from "@metamask/base-controller";
|
|
|
3
3
|
import type { Messenger } from "@metamask/messenger";
|
|
4
4
|
import type { HandleSnapRequest, HasSnap } from "@metamask/snaps-controllers";
|
|
5
5
|
import type { SnapId } from "@metamask/snaps-sdk";
|
|
6
|
-
import type { TransactionControllerTransactionConfirmedEvent, TransactionControllerTransactionDroppedEvent, TransactionControllerTransactionFailedEvent } from "@metamask/transaction-controller";
|
|
6
|
+
import type { TransactionControllerTransactionApprovedEvent, TransactionControllerTransactionConfirmedEvent, TransactionControllerTransactionDroppedEvent, TransactionControllerTransactionFailedEvent, TransactionControllerTransactionRejectedEvent } from "@metamask/transaction-controller";
|
|
7
7
|
import type { Hex, Json } from "@metamask/utils";
|
|
8
8
|
import type { DecodedPermission } from "./decodePermission/index.mjs";
|
|
9
9
|
import { type GatorPermissionsMap, type DelegationDetails, type RevocationParams, type PendingRevocationParams } from "./types.mjs";
|
|
@@ -120,7 +120,7 @@ export type GatorPermissionsControllerEvents = GatorPermissionsControllerStateCh
|
|
|
120
120
|
/**
|
|
121
121
|
* Events that {@link GatorPermissionsController} is allowed to subscribe to internally.
|
|
122
122
|
*/
|
|
123
|
-
type AllowedEvents = GatorPermissionsControllerStateChangeEvent | TransactionControllerTransactionConfirmedEvent | TransactionControllerTransactionFailedEvent | TransactionControllerTransactionDroppedEvent;
|
|
123
|
+
type AllowedEvents = GatorPermissionsControllerStateChangeEvent | TransactionControllerTransactionApprovedEvent | TransactionControllerTransactionRejectedEvent | TransactionControllerTransactionConfirmedEvent | TransactionControllerTransactionFailedEvent | TransactionControllerTransactionDroppedEvent;
|
|
124
124
|
/**
|
|
125
125
|
* Messenger type for the GatorPermissionsController.
|
|
126
126
|
*/
|
|
@@ -219,8 +219,15 @@ export default class GatorPermissionsController extends BaseController<typeof co
|
|
|
219
219
|
/**
|
|
220
220
|
* Adds a pending revocation that will be submitted once the transaction is confirmed.
|
|
221
221
|
*
|
|
222
|
-
* This method sets up listeners for
|
|
223
|
-
*
|
|
222
|
+
* This method sets up listeners for the user's approval/rejection decision and
|
|
223
|
+
* terminal transaction states (confirmed, failed, dropped). The flow is:
|
|
224
|
+
* 1. Wait for user to approve or reject the transaction
|
|
225
|
+
* 2. If approved, add to pending revocations state
|
|
226
|
+
* 3. If rejected, cleanup without adding to state
|
|
227
|
+
* 4. If confirmed, submit the revocation
|
|
228
|
+
* 5. If failed or dropped, cleanup
|
|
229
|
+
*
|
|
230
|
+
* Includes a timeout safety net to prevent memory leaks if the transaction never
|
|
224
231
|
* reaches a terminal state.
|
|
225
232
|
*
|
|
226
233
|
* @param params - The pending revocation parameters.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatorPermissionsController.d.mts","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,wBAAwB,EACxB,0BAA0B,EAE3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAE,4BAA4B;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,oCAAoC;AAC9E,OAAO,KAAK,EAAE,MAAM,EAAE,4BAA4B;AAElD,OAAO,KAAK,EACV,8CAA8C,EAC9C,4CAA4C,EAC5C,2CAA2C,
|
|
1
|
+
{"version":3,"file":"GatorPermissionsController.d.mts","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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"}
|
|
@@ -284,8 +284,15 @@ class GatorPermissionsController extends BaseController {
|
|
|
284
284
|
/**
|
|
285
285
|
* Adds a pending revocation that will be submitted once the transaction is confirmed.
|
|
286
286
|
*
|
|
287
|
-
* This method sets up listeners for
|
|
288
|
-
*
|
|
287
|
+
* This method sets up listeners for the user's approval/rejection decision and
|
|
288
|
+
* terminal transaction states (confirmed, failed, dropped). The flow is:
|
|
289
|
+
* 1. Wait for user to approve or reject the transaction
|
|
290
|
+
* 2. If approved, add to pending revocations state
|
|
291
|
+
* 3. If rejected, cleanup without adding to state
|
|
292
|
+
* 4. If confirmed, submit the revocation
|
|
293
|
+
* 5. If failed or dropped, cleanup
|
|
294
|
+
*
|
|
295
|
+
* Includes a timeout safety net to prevent memory leaks if the transaction never
|
|
289
296
|
* reaches a terminal state.
|
|
290
297
|
*
|
|
291
298
|
* @param params - The pending revocation parameters.
|
|
@@ -298,16 +305,29 @@ class GatorPermissionsController extends BaseController {
|
|
|
298
305
|
permissionContext,
|
|
299
306
|
});
|
|
300
307
|
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_assertGatorPermissionsEnabled).call(this);
|
|
301
|
-
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_addPendingRevocationToState).call(this, txId, permissionContext);
|
|
302
308
|
// Track handlers and timeout for cleanup
|
|
303
309
|
const handlers = {
|
|
310
|
+
approved: undefined,
|
|
311
|
+
rejected: undefined,
|
|
304
312
|
confirmed: undefined,
|
|
305
313
|
failed: undefined,
|
|
306
314
|
dropped: undefined,
|
|
307
315
|
timeoutId: undefined,
|
|
308
316
|
};
|
|
317
|
+
// Helper to unsubscribe from approval/rejection events after decision is made
|
|
318
|
+
const cleanupApprovalHandlers = () => {
|
|
319
|
+
if (handlers.approved) {
|
|
320
|
+
this.messenger.unsubscribe('TransactionController:transactionApproved', handlers.approved);
|
|
321
|
+
handlers.approved = undefined;
|
|
322
|
+
}
|
|
323
|
+
if (handlers.rejected) {
|
|
324
|
+
this.messenger.unsubscribe('TransactionController:transactionRejected', handlers.rejected);
|
|
325
|
+
handlers.rejected = undefined;
|
|
326
|
+
}
|
|
327
|
+
};
|
|
309
328
|
// Cleanup function to unsubscribe from all events and clear timeout
|
|
310
|
-
const cleanup = (txIdToRemove) => {
|
|
329
|
+
const cleanup = (txIdToRemove, removeFromState = true) => {
|
|
330
|
+
cleanupApprovalHandlers();
|
|
311
331
|
if (handlers.confirmed) {
|
|
312
332
|
this.messenger.unsubscribe('TransactionController:transactionConfirmed', handlers.confirmed);
|
|
313
333
|
}
|
|
@@ -320,8 +340,33 @@ class GatorPermissionsController extends BaseController {
|
|
|
320
340
|
if (handlers.timeoutId !== undefined) {
|
|
321
341
|
clearTimeout(handlers.timeoutId);
|
|
322
342
|
}
|
|
323
|
-
// Remove the pending revocation from the state
|
|
324
|
-
|
|
343
|
+
// Remove the pending revocation from the state (only if it was added)
|
|
344
|
+
if (removeFromState) {
|
|
345
|
+
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_removePendingRevocationFromStateByTxId).call(this, txIdToRemove);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
// Handle approved transaction - add to pending revocations state
|
|
349
|
+
handlers.approved = (payload) => {
|
|
350
|
+
if (payload.transactionMeta.id === txId) {
|
|
351
|
+
controllerLog('Transaction approved by user, adding to pending revocations', {
|
|
352
|
+
txId,
|
|
353
|
+
permissionContext,
|
|
354
|
+
});
|
|
355
|
+
__classPrivateFieldGet(this, _GatorPermissionsController_instances, "m", _GatorPermissionsController_addPendingRevocationToState).call(this, txId, permissionContext);
|
|
356
|
+
// Unsubscribe from approval/rejection events since decision is made
|
|
357
|
+
cleanupApprovalHandlers();
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
// Handle rejected transaction - cleanup without adding to state
|
|
361
|
+
handlers.rejected = (payload) => {
|
|
362
|
+
if (payload.transactionMeta.id === txId) {
|
|
363
|
+
controllerLog('Transaction rejected by user, cleaning up listeners', {
|
|
364
|
+
txId,
|
|
365
|
+
permissionContext,
|
|
366
|
+
});
|
|
367
|
+
// Don't remove from state since it was never added
|
|
368
|
+
cleanup(payload.transactionMeta.id, false);
|
|
369
|
+
}
|
|
325
370
|
};
|
|
326
371
|
// Handle confirmed transaction - submit revocation
|
|
327
372
|
handlers.confirmed = (transactionMeta) => {
|
|
@@ -361,6 +406,9 @@ class GatorPermissionsController extends BaseController {
|
|
|
361
406
|
cleanup(payload.transactionMeta.id);
|
|
362
407
|
}
|
|
363
408
|
};
|
|
409
|
+
// Subscribe to user approval/rejection events
|
|
410
|
+
this.messenger.subscribe('TransactionController:transactionApproved', handlers.approved);
|
|
411
|
+
this.messenger.subscribe('TransactionController:transactionRejected', handlers.rejected);
|
|
364
412
|
// Subscribe to terminal transaction events
|
|
365
413
|
this.messenger.subscribe('TransactionController:transactionConfirmed', handlers.confirmed);
|
|
366
414
|
this.messenger.subscribe('TransactionController:transactionFailed', handlers.failed);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GatorPermissionsController.mjs","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Signer } from '@metamask/7715-permission-types';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest, HasSnap } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n TransactionControllerTransactionConfirmedEvent,\n TransactionControllerTransactionDroppedEvent,\n TransactionControllerTransactionFailedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport type { DecodedPermission } from './decodePermission';\nimport {\n getPermissionDataAndExpiry,\n identifyPermissionByEnforcers,\n reconstructDecodedPermission,\n} from './decodePermission';\nimport {\n GatorPermissionsFetchError,\n GatorPermissionsNotEnabledError,\n GatorPermissionsProviderError,\n OriginNotAllowedError,\n PermissionDecodingError,\n} from './errors';\nimport { controllerLog } from './logger';\nimport type { StoredGatorPermissionSanitized } from './types';\nimport {\n GatorPermissionsSnapRpcMethod,\n type GatorPermissionsMap,\n type PermissionTypesWithCustom,\n type StoredGatorPermission,\n type DelegationDetails,\n type RevocationParams,\n type PendingRevocationParams,\n} from './types';\nimport {\n deserializeGatorPermissionsMap,\n serializeGatorPermissionsMap,\n} from './utils';\n\n// === GENERAL ===\n\n// Unique name for the controller\nconst controllerName = 'GatorPermissionsController';\n\n// Default value for the gator permissions provider snap id\nconst defaultGatorPermissionsProviderSnapId =\n 'npm:@metamask/gator-permissions-snap' as SnapId;\n\nconst defaultGatorPermissionsMap: GatorPermissionsMap = {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n};\n\n/**\n * Delegation framework version used to select the correct deployed enforcer\n * contract addresses from `@metamask/delegation-deployments`.\n */\nexport const DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\n/**\n * Timeout duration for pending revocations (2 hours in milliseconds).\n * After this time, event listeners will be cleaned up to prevent memory leaks.\n */\nconst PENDING_REVOCATION_TIMEOUT = 2 * 60 * 60 * 1000;\n\nconst contractsByChainId = DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION];\n\n// === STATE ===\n\n/**\n * State shape for GatorPermissionsController\n */\nexport type GatorPermissionsControllerState = {\n /**\n * Flag that indicates if the gator permissions feature is enabled\n */\n isGatorPermissionsEnabled: boolean;\n\n /**\n * JSON serialized object containing gator permissions fetched from profile sync\n */\n gatorPermissionsMapSerialized: string;\n\n /**\n * Flag that indicates that fetching permissions is in progress\n * This is used to show a loading spinner in the UI\n */\n isFetchingGatorPermissions: boolean;\n\n /**\n * The ID of the Snap of the gator permissions provider snap\n * Default value is `@metamask/gator-permissions-snap`\n */\n gatorPermissionsProviderSnapId: SnapId;\n\n /**\n * List of gator permission pending a revocation transaction\n */\n pendingRevocations: {\n txId: string;\n permissionContext: Hex;\n }[];\n};\n\nconst gatorPermissionsControllerMetadata: StateMetadata<GatorPermissionsControllerState> =\n {\n isGatorPermissionsEnabled: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsMapSerialized: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isFetchingGatorPermissions: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsProviderSnapId: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n pendingRevocations: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n } satisfies StateMetadata<GatorPermissionsControllerState>;\n\n/**\n * Constructs the default {@link GatorPermissionsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link GatorPermissionsController} state.\n */\nexport function getDefaultGatorPermissionsControllerState(): GatorPermissionsControllerState {\n return {\n isGatorPermissionsEnabled: false,\n gatorPermissionsMapSerialized: serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n ),\n isFetchingGatorPermissions: false,\n gatorPermissionsProviderSnapId: defaultGatorPermissionsProviderSnapId,\n pendingRevocations: [],\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the\n * {@link GatorPermissionsController}.\n */\nexport type GatorPermissionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n GatorPermissionsControllerState\n>;\n\n/**\n * The action which can be used to fetch and update gator permissions.\n */\nexport type GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction = {\n type: `${typeof controllerName}:fetchAndUpdateGatorPermissions`;\n handler: GatorPermissionsController['fetchAndUpdateGatorPermissions'];\n};\n\n/**\n * The action which can be used to enable gator permissions.\n */\nexport type GatorPermissionsControllerEnableGatorPermissionsAction = {\n type: `${typeof controllerName}:enableGatorPermissions`;\n handler: GatorPermissionsController['enableGatorPermissions'];\n};\n\n/**\n * The action which can be used to disable gator permissions.\n */\nexport type GatorPermissionsControllerDisableGatorPermissionsAction = {\n type: `${typeof controllerName}:disableGatorPermissions`;\n handler: GatorPermissionsController['disableGatorPermissions'];\n};\n\nexport type GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction =\n {\n type: `${typeof controllerName}:decodePermissionFromPermissionContextForOrigin`;\n handler: GatorPermissionsController['decodePermissionFromPermissionContextForOrigin'];\n };\n\n/**\n * The action which can be used to submit a revocation.\n */\nexport type GatorPermissionsControllerSubmitRevocationAction = {\n type: `${typeof controllerName}:submitRevocation`;\n handler: GatorPermissionsController['submitRevocation'];\n};\n\n/**\n * The action which can be used to add a pending revocation.\n */\nexport type GatorPermissionsControllerAddPendingRevocationAction = {\n type: `${typeof controllerName}:addPendingRevocation`;\n handler: GatorPermissionsController['addPendingRevocation'];\n};\n\n/**\n * All actions that {@link GatorPermissionsController} registers, to be called\n * externally.\n */\nexport type GatorPermissionsControllerActions =\n | GatorPermissionsControllerGetStateAction\n | GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction\n | GatorPermissionsControllerEnableGatorPermissionsAction\n | GatorPermissionsControllerDisableGatorPermissionsAction\n | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction\n | GatorPermissionsControllerSubmitRevocationAction\n | GatorPermissionsControllerAddPendingRevocationAction;\n\n/**\n * All actions that {@link GatorPermissionsController} calls internally.\n *\n * SnapsController:handleRequest and SnapsController:has are allowed to be called\n * internally because they are used to fetch gator permissions from the Snap.\n */\ntype AllowedActions = HandleSnapRequest | HasSnap;\n\n/**\n * The event that {@link GatorPermissionsController} publishes when updating state.\n */\nexport type GatorPermissionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n GatorPermissionsControllerState\n >;\n\n/**\n * All events that {@link GatorPermissionsController} publishes, to be subscribed to\n * externally.\n */\nexport type GatorPermissionsControllerEvents =\n GatorPermissionsControllerStateChangeEvent;\n\n/**\n * Events that {@link GatorPermissionsController} is allowed to subscribe to internally.\n */\ntype AllowedEvents =\n | GatorPermissionsControllerStateChangeEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionDroppedEvent;\n\n/**\n * Messenger type for the GatorPermissionsController.\n */\nexport type GatorPermissionsControllerMessenger = Messenger<\n typeof controllerName,\n GatorPermissionsControllerActions | AllowedActions,\n GatorPermissionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller that manages gator permissions by reading from profile sync\n */\nexport default class GatorPermissionsController extends BaseController<\n typeof controllerName,\n GatorPermissionsControllerState,\n GatorPermissionsControllerMessenger\n> {\n /**\n * Creates a GatorPermissionsController instance.\n *\n * @param args - The arguments to this function.\n * @param args.messenger - Messenger used to communicate with BaseV2 controller.\n * @param args.state - Initial state to set on this controller.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: GatorPermissionsControllerMessenger;\n state?: Partial<GatorPermissionsControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: gatorPermissionsControllerMetadata,\n messenger,\n state: {\n ...getDefaultGatorPermissionsControllerState(),\n ...state,\n isFetchingGatorPermissions: false,\n },\n });\n\n this.#registerMessageHandlers();\n }\n\n #setIsFetchingGatorPermissions(isFetchingGatorPermissions: boolean) {\n this.update((state) => {\n state.isFetchingGatorPermissions = isFetchingGatorPermissions;\n });\n }\n\n #setIsGatorPermissionsEnabled(isGatorPermissionsEnabled: boolean) {\n this.update((state) => {\n state.isGatorPermissionsEnabled = isGatorPermissionsEnabled;\n });\n }\n\n #addPendingRevocationToState(txId: string, permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = [\n ...state.pendingRevocations,\n { txId, permissionContext },\n ];\n });\n }\n\n #removePendingRevocationFromStateByTxId(txId: string) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) => pendingRevocations.txId !== txId,\n );\n });\n }\n\n #removePendingRevocationFromStateByPermissionContext(permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) =>\n pendingRevocations.permissionContext !== permissionContext,\n );\n });\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchAndUpdateGatorPermissions`,\n this.fetchAndUpdateGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:enableGatorPermissions`,\n this.enableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:disableGatorPermissions`,\n this.disableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:decodePermissionFromPermissionContextForOrigin`,\n this.decodePermissionFromPermissionContextForOrigin.bind(this),\n );\n\n const submitRevocationAction = `${controllerName}:submitRevocation`;\n\n this.messenger.registerActionHandler(\n submitRevocationAction,\n this.submitRevocation.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addPendingRevocation`,\n this.addPendingRevocation.bind(this),\n );\n }\n\n /**\n * Asserts that the gator permissions are enabled.\n *\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n */\n #assertGatorPermissionsEnabled() {\n if (!this.state.isGatorPermissionsEnabled) {\n throw new GatorPermissionsNotEnabledError();\n }\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap of the gator permissions provider snap.\n * @param args.params - Optional parameters to pass to the snap method.\n * @returns A promise that resolves with the gator permissions.\n */\n async #handleSnapRequestToGatorPermissionsProvider({\n snapId,\n params,\n }: {\n snapId: SnapId;\n params?: Json;\n }): Promise<\n StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null\n > {\n try {\n const response = (await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n ...(params !== undefined && { params }),\n },\n },\n )) as StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null;\n\n return response;\n } catch (error) {\n controllerLog(\n 'Failed to handle snap request to gator permissions provider',\n error,\n );\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Sanitizes a stored gator permission by removing the fields that are not expose to MetaMask client.\n *\n * @param storedGatorPermission - The stored gator permission to sanitize.\n * @returns The sanitized stored gator permission.\n */\n #sanitizeStoredGatorPermission(\n storedGatorPermission: StoredGatorPermission<\n Signer,\n PermissionTypesWithCustom\n >,\n ): StoredGatorPermissionSanitized<Signer, PermissionTypesWithCustom> {\n const { permissionResponse } = storedGatorPermission;\n const { rules, dependencyInfo, signer, ...rest } = permissionResponse;\n return {\n ...storedGatorPermission,\n permissionResponse: {\n ...rest,\n },\n };\n }\n\n /**\n * Categorizes stored gator permissions by type and chainId.\n *\n * @param storedGatorPermissions - An array of stored gator permissions.\n * @returns The gator permissions map.\n */\n #categorizePermissionsDataByTypeAndChainId(\n storedGatorPermissions:\n | StoredGatorPermission<Signer, PermissionTypesWithCustom>[]\n | null,\n ): GatorPermissionsMap {\n if (!storedGatorPermissions) {\n return defaultGatorPermissionsMap;\n }\n\n return storedGatorPermissions.reduce(\n (gatorPermissionsMap, storedGatorPermission) => {\n const { permissionResponse } = storedGatorPermission;\n const permissionType = permissionResponse.permission.type;\n const { chainId } = permissionResponse;\n\n const sanitizedStoredGatorPermission =\n this.#sanitizeStoredGatorPermission(storedGatorPermission);\n\n switch (permissionType) {\n case 'native-token-stream':\n case 'native-token-periodic':\n case 'erc20-token-stream':\n case 'erc20-token-periodic':\n if (!gatorPermissionsMap[permissionType][chainId]) {\n gatorPermissionsMap[permissionType][chainId] = [];\n }\n\n (\n gatorPermissionsMap[permissionType][\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n default:\n if (!gatorPermissionsMap.other[chainId]) {\n gatorPermissionsMap.other[chainId] = [];\n }\n\n (\n gatorPermissionsMap.other[\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n }\n\n return gatorPermissionsMap;\n },\n {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n } as GatorPermissionsMap,\n );\n }\n\n /**\n * Gets the gator permissions map from the state.\n *\n * @returns The gator permissions map.\n */\n get gatorPermissionsMap(): GatorPermissionsMap {\n return deserializeGatorPermissionsMap(\n this.state.gatorPermissionsMapSerialized,\n );\n }\n\n /**\n * Gets the gator permissions provider snap id that is used to fetch gator permissions.\n *\n * @returns The gator permissions provider snap id.\n */\n get permissionsProviderSnapId(): SnapId {\n return this.state.gatorPermissionsProviderSnapId;\n }\n\n /**\n * Enables gator permissions for the user.\n */\n public async enableGatorPermissions() {\n this.#setIsGatorPermissionsEnabled(true);\n }\n\n /**\n * Clears the gator permissions map and disables the feature.\n */\n public async disableGatorPermissions() {\n this.update((state) => {\n state.isGatorPermissionsEnabled = false;\n state.gatorPermissionsMapSerialized = serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n );\n });\n }\n\n /**\n * Gets the pending revocations list.\n *\n * @returns The pending revocations list.\n */\n get pendingRevocations(): { txId: string; permissionContext: Hex }[] {\n return this.state.pendingRevocations;\n }\n\n /**\n * Fetches the gator permissions from profile sync and updates the state.\n *\n * @param params - Optional parameters to pass to the snap's getGrantedPermissions method.\n * @returns A promise that resolves to the gator permissions map.\n * @throws {GatorPermissionsFetchError} If the gator permissions fetch fails.\n */\n public async fetchAndUpdateGatorPermissions(\n params?: Json,\n ): Promise<GatorPermissionsMap> {\n try {\n this.#setIsFetchingGatorPermissions(true);\n this.#assertGatorPermissionsEnabled();\n\n const permissionsData =\n await this.#handleSnapRequestToGatorPermissionsProvider({\n snapId: this.state.gatorPermissionsProviderSnapId,\n params,\n });\n\n const gatorPermissionsMap =\n this.#categorizePermissionsDataByTypeAndChainId(permissionsData);\n\n this.update((state) => {\n state.gatorPermissionsMapSerialized =\n serializeGatorPermissionsMap(gatorPermissionsMap);\n });\n\n return gatorPermissionsMap;\n } catch (error) {\n controllerLog('Failed to fetch gator permissions', error);\n throw new GatorPermissionsFetchError({\n message: 'Failed to fetch gator permissions',\n cause: error as Error,\n });\n } finally {\n this.#setIsFetchingGatorPermissions(false);\n }\n }\n\n /**\n * Decodes a permission context into a structured permission for a specific origin.\n *\n * This method validates the caller origin, decodes the provided `permissionContext`\n * into delegations, identifies the permission type from the caveat enforcers,\n * extracts the permission-specific data and expiry, and reconstructs a\n * {@link DecodedPermission} containing chainId, account addresses, signer, type and data.\n *\n * @param args - The arguments to this function.\n * @param args.origin - The caller's origin; must match the configured permissions provider Snap id.\n * @param args.chainId - Numeric EIP-155 chain id used for resolving enforcer contracts and encoding.\n * @param args.delegation - delegation representing the permission.\n * @param args.metadata - metadata included in the request.\n * @param args.metadata.justification - the justification as specified in the request metadata.\n * @param args.metadata.origin - the origin as specified in the request metadata.\n *\n * @returns A decoded permission object suitable for UI consumption and follow-up actions.\n * @throws If the origin is not allowed, the context cannot be decoded into exactly one delegation,\n * or the enforcers/terms do not match a supported permission type.\n */\n public decodePermissionFromPermissionContextForOrigin({\n origin,\n chainId,\n delegation: { caveats, delegator, delegate, authority },\n metadata: { justification, origin: specifiedOrigin },\n }: {\n origin: string;\n chainId: number;\n metadata: {\n justification: string;\n origin: string;\n };\n delegation: DelegationDetails;\n }): DecodedPermission {\n if (origin !== this.permissionsProviderSnapId) {\n throw new OriginNotAllowedError({ origin });\n }\n\n const contracts = contractsByChainId[chainId];\n\n if (!contracts) {\n throw new Error(`Contracts not found for chainId: ${chainId}`);\n }\n\n try {\n const enforcers = caveats.map((caveat) => caveat.enforcer);\n\n const permissionType = identifyPermissionByEnforcers({\n enforcers,\n contracts,\n });\n\n const { expiry, data } = getPermissionDataAndExpiry({\n contracts,\n caveats,\n permissionType,\n });\n\n const permission = reconstructDecodedPermission({\n chainId,\n permissionType,\n delegator,\n delegate,\n authority,\n expiry,\n data,\n justification,\n specifiedOrigin,\n });\n\n return permission;\n } catch (error) {\n throw new PermissionDecodingError({\n cause: error as Error,\n });\n }\n }\n\n /**\n * Submits a revocation to the gator permissions provider snap.\n *\n * @param revocationParams - The revocation parameters containing the permission context.\n * @returns A promise that resolves when the revocation is submitted successfully.\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n * @throws {GatorPermissionsProviderError} If the snap request fails.\n */\n public async submitRevocation(\n revocationParams: RevocationParams,\n ): Promise<void> {\n controllerLog('submitRevocation method called', {\n permissionContext: revocationParams.permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n try {\n const snapRequest = {\n snapId: this.state.gatorPermissionsProviderSnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n params: revocationParams,\n },\n };\n\n const result = await this.messenger.call(\n 'SnapController:handleRequest',\n snapRequest,\n );\n\n this.#removePendingRevocationFromStateByPermissionContext(\n revocationParams.permissionContext,\n );\n\n controllerLog('Successfully submitted revocation', {\n permissionContext: revocationParams.permissionContext,\n result,\n });\n } catch (error) {\n controllerLog('Failed to submit revocation', {\n error,\n permissionContext: revocationParams.permissionContext,\n });\n\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Adds a pending revocation that will be submitted once the transaction is confirmed.\n *\n * This method sets up listeners for terminal transaction states (confirmed, failed, dropped)\n * and includes a timeout safety net to prevent memory leaks if the transaction never\n * reaches a terminal state.\n *\n * @param params - The pending revocation parameters.\n * @returns A promise that resolves when the listener is set up.\n */\n public async addPendingRevocation(\n params: PendingRevocationParams,\n ): Promise<void> {\n const { txId, permissionContext } = params;\n\n controllerLog('addPendingRevocation method called', {\n txId,\n permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n this.#addPendingRevocationToState(txId, permissionContext);\n\n type PendingRevocationHandlers = {\n confirmed?: (\n ...args: TransactionControllerTransactionConfirmedEvent['payload']\n ) => void;\n failed?: (\n ...args: TransactionControllerTransactionFailedEvent['payload']\n ) => void;\n dropped?: (\n ...args: TransactionControllerTransactionDroppedEvent['payload']\n ) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n };\n\n // Track handlers and timeout for cleanup\n const handlers: PendingRevocationHandlers = {\n confirmed: undefined,\n failed: undefined,\n dropped: undefined,\n timeoutId: undefined,\n };\n\n // Cleanup function to unsubscribe from all events and clear timeout\n const cleanup = (txIdToRemove: string) => {\n if (handlers.confirmed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n }\n if (handlers.failed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n }\n if (handlers.dropped) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n }\n if (handlers.timeoutId !== undefined) {\n clearTimeout(handlers.timeoutId);\n }\n\n // Remove the pending revocation from the state\n this.#removePendingRevocationFromStateByTxId(txIdToRemove);\n };\n\n // Handle confirmed transaction - submit revocation\n handlers.confirmed = (transactionMeta) => {\n if (transactionMeta.id === txId) {\n controllerLog('Transaction confirmed, submitting revocation', {\n txId,\n permissionContext,\n });\n\n this.submitRevocation({ permissionContext }).catch((error) => {\n controllerLog(\n 'Failed to submit revocation after transaction confirmed',\n {\n txId,\n permissionContext,\n error,\n },\n );\n });\n\n cleanup(transactionMeta.id);\n }\n };\n\n // Handle failed transaction - cleanup without submitting revocation\n handlers.failed = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction failed, cleaning up revocation listener', {\n txId,\n permissionContext,\n error: payload.error,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Handle dropped transaction - cleanup without submitting revocation\n handlers.dropped = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction dropped, cleaning up revocation listener', {\n txId,\n permissionContext,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Subscribe to terminal transaction events\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n\n // Set timeout as safety net to prevent memory leaks\n handlers.timeoutId = setTimeout(() => {\n controllerLog('Pending revocation timed out, cleaning up listeners', {\n txId,\n permissionContext,\n });\n cleanup(txId);\n }, PENDING_REVOCATION_TIMEOUT);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"GatorPermissionsController.mjs","sourceRoot":"","sources":["../src/GatorPermissionsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Signer } from '@metamask/7715-permission-types';\nimport type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport { DELEGATOR_CONTRACTS } from '@metamask/delegation-deployments';\nimport type { Messenger } from '@metamask/messenger';\nimport type { HandleSnapRequest, HasSnap } from '@metamask/snaps-controllers';\nimport type { SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type {\n TransactionControllerTransactionApprovedEvent,\n TransactionControllerTransactionConfirmedEvent,\n TransactionControllerTransactionDroppedEvent,\n TransactionControllerTransactionFailedEvent,\n TransactionControllerTransactionRejectedEvent,\n} from '@metamask/transaction-controller';\nimport type { Hex, Json } from '@metamask/utils';\n\nimport type { DecodedPermission } from './decodePermission';\nimport {\n getPermissionDataAndExpiry,\n identifyPermissionByEnforcers,\n reconstructDecodedPermission,\n} from './decodePermission';\nimport {\n GatorPermissionsFetchError,\n GatorPermissionsNotEnabledError,\n GatorPermissionsProviderError,\n OriginNotAllowedError,\n PermissionDecodingError,\n} from './errors';\nimport { controllerLog } from './logger';\nimport type { StoredGatorPermissionSanitized } from './types';\nimport {\n GatorPermissionsSnapRpcMethod,\n type GatorPermissionsMap,\n type PermissionTypesWithCustom,\n type StoredGatorPermission,\n type DelegationDetails,\n type RevocationParams,\n type PendingRevocationParams,\n} from './types';\nimport {\n deserializeGatorPermissionsMap,\n serializeGatorPermissionsMap,\n} from './utils';\n\n// === GENERAL ===\n\n// Unique name for the controller\nconst controllerName = 'GatorPermissionsController';\n\n// Default value for the gator permissions provider snap id\nconst defaultGatorPermissionsProviderSnapId =\n 'npm:@metamask/gator-permissions-snap' as SnapId;\n\nconst defaultGatorPermissionsMap: GatorPermissionsMap = {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n};\n\n/**\n * Delegation framework version used to select the correct deployed enforcer\n * contract addresses from `@metamask/delegation-deployments`.\n */\nexport const DELEGATION_FRAMEWORK_VERSION = '1.3.0';\n\n/**\n * Timeout duration for pending revocations (2 hours in milliseconds).\n * After this time, event listeners will be cleaned up to prevent memory leaks.\n */\nconst PENDING_REVOCATION_TIMEOUT = 2 * 60 * 60 * 1000;\n\nconst contractsByChainId = DELEGATOR_CONTRACTS[DELEGATION_FRAMEWORK_VERSION];\n\n// === STATE ===\n\n/**\n * State shape for GatorPermissionsController\n */\nexport type GatorPermissionsControllerState = {\n /**\n * Flag that indicates if the gator permissions feature is enabled\n */\n isGatorPermissionsEnabled: boolean;\n\n /**\n * JSON serialized object containing gator permissions fetched from profile sync\n */\n gatorPermissionsMapSerialized: string;\n\n /**\n * Flag that indicates that fetching permissions is in progress\n * This is used to show a loading spinner in the UI\n */\n isFetchingGatorPermissions: boolean;\n\n /**\n * The ID of the Snap of the gator permissions provider snap\n * Default value is `@metamask/gator-permissions-snap`\n */\n gatorPermissionsProviderSnapId: SnapId;\n\n /**\n * List of gator permission pending a revocation transaction\n */\n pendingRevocations: {\n txId: string;\n permissionContext: Hex;\n }[];\n};\n\nconst gatorPermissionsControllerMetadata: StateMetadata<GatorPermissionsControllerState> =\n {\n isGatorPermissionsEnabled: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsMapSerialized: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n isFetchingGatorPermissions: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n gatorPermissionsProviderSnapId: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n pendingRevocations: {\n includeInStateLogs: true,\n persist: false,\n includeInDebugSnapshot: false,\n usedInUi: true,\n },\n } satisfies StateMetadata<GatorPermissionsControllerState>;\n\n/**\n * Constructs the default {@link GatorPermissionsController} state. This allows\n * consumers to provide a partial state object when initializing the controller\n * and also helps in constructing complete state objects for this controller in\n * tests.\n *\n * @returns The default {@link GatorPermissionsController} state.\n */\nexport function getDefaultGatorPermissionsControllerState(): GatorPermissionsControllerState {\n return {\n isGatorPermissionsEnabled: false,\n gatorPermissionsMapSerialized: serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n ),\n isFetchingGatorPermissions: false,\n gatorPermissionsProviderSnapId: defaultGatorPermissionsProviderSnapId,\n pendingRevocations: [],\n };\n}\n\n// === MESSENGER ===\n\n/**\n * The action which can be used to retrieve the state of the\n * {@link GatorPermissionsController}.\n */\nexport type GatorPermissionsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n GatorPermissionsControllerState\n>;\n\n/**\n * The action which can be used to fetch and update gator permissions.\n */\nexport type GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction = {\n type: `${typeof controllerName}:fetchAndUpdateGatorPermissions`;\n handler: GatorPermissionsController['fetchAndUpdateGatorPermissions'];\n};\n\n/**\n * The action which can be used to enable gator permissions.\n */\nexport type GatorPermissionsControllerEnableGatorPermissionsAction = {\n type: `${typeof controllerName}:enableGatorPermissions`;\n handler: GatorPermissionsController['enableGatorPermissions'];\n};\n\n/**\n * The action which can be used to disable gator permissions.\n */\nexport type GatorPermissionsControllerDisableGatorPermissionsAction = {\n type: `${typeof controllerName}:disableGatorPermissions`;\n handler: GatorPermissionsController['disableGatorPermissions'];\n};\n\nexport type GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction =\n {\n type: `${typeof controllerName}:decodePermissionFromPermissionContextForOrigin`;\n handler: GatorPermissionsController['decodePermissionFromPermissionContextForOrigin'];\n };\n\n/**\n * The action which can be used to submit a revocation.\n */\nexport type GatorPermissionsControllerSubmitRevocationAction = {\n type: `${typeof controllerName}:submitRevocation`;\n handler: GatorPermissionsController['submitRevocation'];\n};\n\n/**\n * The action which can be used to add a pending revocation.\n */\nexport type GatorPermissionsControllerAddPendingRevocationAction = {\n type: `${typeof controllerName}:addPendingRevocation`;\n handler: GatorPermissionsController['addPendingRevocation'];\n};\n\n/**\n * All actions that {@link GatorPermissionsController} registers, to be called\n * externally.\n */\nexport type GatorPermissionsControllerActions =\n | GatorPermissionsControllerGetStateAction\n | GatorPermissionsControllerFetchAndUpdateGatorPermissionsAction\n | GatorPermissionsControllerEnableGatorPermissionsAction\n | GatorPermissionsControllerDisableGatorPermissionsAction\n | GatorPermissionsControllerDecodePermissionFromPermissionContextForOriginAction\n | GatorPermissionsControllerSubmitRevocationAction\n | GatorPermissionsControllerAddPendingRevocationAction;\n\n/**\n * All actions that {@link GatorPermissionsController} calls internally.\n *\n * SnapsController:handleRequest and SnapsController:has are allowed to be called\n * internally because they are used to fetch gator permissions from the Snap.\n */\ntype AllowedActions = HandleSnapRequest | HasSnap;\n\n/**\n * The event that {@link GatorPermissionsController} publishes when updating state.\n */\nexport type GatorPermissionsControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n GatorPermissionsControllerState\n >;\n\n/**\n * All events that {@link GatorPermissionsController} publishes, to be subscribed to\n * externally.\n */\nexport type GatorPermissionsControllerEvents =\n GatorPermissionsControllerStateChangeEvent;\n\n/**\n * Events that {@link GatorPermissionsController} is allowed to subscribe to internally.\n */\ntype AllowedEvents =\n | GatorPermissionsControllerStateChangeEvent\n | TransactionControllerTransactionApprovedEvent\n | TransactionControllerTransactionRejectedEvent\n | TransactionControllerTransactionConfirmedEvent\n | TransactionControllerTransactionFailedEvent\n | TransactionControllerTransactionDroppedEvent;\n\n/**\n * Messenger type for the GatorPermissionsController.\n */\nexport type GatorPermissionsControllerMessenger = Messenger<\n typeof controllerName,\n GatorPermissionsControllerActions | AllowedActions,\n GatorPermissionsControllerEvents | AllowedEvents\n>;\n\n/**\n * Controller that manages gator permissions by reading from profile sync\n */\nexport default class GatorPermissionsController extends BaseController<\n typeof controllerName,\n GatorPermissionsControllerState,\n GatorPermissionsControllerMessenger\n> {\n /**\n * Creates a GatorPermissionsController instance.\n *\n * @param args - The arguments to this function.\n * @param args.messenger - Messenger used to communicate with BaseV2 controller.\n * @param args.state - Initial state to set on this controller.\n */\n constructor({\n messenger,\n state,\n }: {\n messenger: GatorPermissionsControllerMessenger;\n state?: Partial<GatorPermissionsControllerState>;\n }) {\n super({\n name: controllerName,\n metadata: gatorPermissionsControllerMetadata,\n messenger,\n state: {\n ...getDefaultGatorPermissionsControllerState(),\n ...state,\n isFetchingGatorPermissions: false,\n },\n });\n\n this.#registerMessageHandlers();\n }\n\n #setIsFetchingGatorPermissions(isFetchingGatorPermissions: boolean) {\n this.update((state) => {\n state.isFetchingGatorPermissions = isFetchingGatorPermissions;\n });\n }\n\n #setIsGatorPermissionsEnabled(isGatorPermissionsEnabled: boolean) {\n this.update((state) => {\n state.isGatorPermissionsEnabled = isGatorPermissionsEnabled;\n });\n }\n\n #addPendingRevocationToState(txId: string, permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = [\n ...state.pendingRevocations,\n { txId, permissionContext },\n ];\n });\n }\n\n #removePendingRevocationFromStateByTxId(txId: string) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) => pendingRevocations.txId !== txId,\n );\n });\n }\n\n #removePendingRevocationFromStateByPermissionContext(permissionContext: Hex) {\n this.update((state) => {\n state.pendingRevocations = state.pendingRevocations.filter(\n (pendingRevocations) =>\n pendingRevocations.permissionContext !== permissionContext,\n );\n });\n }\n\n #registerMessageHandlers(): void {\n this.messenger.registerActionHandler(\n `${controllerName}:fetchAndUpdateGatorPermissions`,\n this.fetchAndUpdateGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:enableGatorPermissions`,\n this.enableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:disableGatorPermissions`,\n this.disableGatorPermissions.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:decodePermissionFromPermissionContextForOrigin`,\n this.decodePermissionFromPermissionContextForOrigin.bind(this),\n );\n\n const submitRevocationAction = `${controllerName}:submitRevocation`;\n\n this.messenger.registerActionHandler(\n submitRevocationAction,\n this.submitRevocation.bind(this),\n );\n\n this.messenger.registerActionHandler(\n `${controllerName}:addPendingRevocation`,\n this.addPendingRevocation.bind(this),\n );\n }\n\n /**\n * Asserts that the gator permissions are enabled.\n *\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n */\n #assertGatorPermissionsEnabled() {\n if (!this.state.isGatorPermissionsEnabled) {\n throw new GatorPermissionsNotEnabledError();\n }\n }\n\n /**\n * Forwards a Snap request to the SnapController.\n *\n * @param args - The request parameters.\n * @param args.snapId - The ID of the Snap of the gator permissions provider snap.\n * @param args.params - Optional parameters to pass to the snap method.\n * @returns A promise that resolves with the gator permissions.\n */\n async #handleSnapRequestToGatorPermissionsProvider({\n snapId,\n params,\n }: {\n snapId: SnapId;\n params?: Json;\n }): Promise<\n StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null\n > {\n try {\n const response = (await this.messenger.call(\n 'SnapController:handleRequest',\n {\n snapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n ...(params !== undefined && { params }),\n },\n },\n )) as StoredGatorPermission<Signer, PermissionTypesWithCustom>[] | null;\n\n return response;\n } catch (error) {\n controllerLog(\n 'Failed to handle snap request to gator permissions provider',\n error,\n );\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderGetGrantedPermissions,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Sanitizes a stored gator permission by removing the fields that are not expose to MetaMask client.\n *\n * @param storedGatorPermission - The stored gator permission to sanitize.\n * @returns The sanitized stored gator permission.\n */\n #sanitizeStoredGatorPermission(\n storedGatorPermission: StoredGatorPermission<\n Signer,\n PermissionTypesWithCustom\n >,\n ): StoredGatorPermissionSanitized<Signer, PermissionTypesWithCustom> {\n const { permissionResponse } = storedGatorPermission;\n const { rules, dependencyInfo, signer, ...rest } = permissionResponse;\n return {\n ...storedGatorPermission,\n permissionResponse: {\n ...rest,\n },\n };\n }\n\n /**\n * Categorizes stored gator permissions by type and chainId.\n *\n * @param storedGatorPermissions - An array of stored gator permissions.\n * @returns The gator permissions map.\n */\n #categorizePermissionsDataByTypeAndChainId(\n storedGatorPermissions:\n | StoredGatorPermission<Signer, PermissionTypesWithCustom>[]\n | null,\n ): GatorPermissionsMap {\n if (!storedGatorPermissions) {\n return defaultGatorPermissionsMap;\n }\n\n return storedGatorPermissions.reduce(\n (gatorPermissionsMap, storedGatorPermission) => {\n const { permissionResponse } = storedGatorPermission;\n const permissionType = permissionResponse.permission.type;\n const { chainId } = permissionResponse;\n\n const sanitizedStoredGatorPermission =\n this.#sanitizeStoredGatorPermission(storedGatorPermission);\n\n switch (permissionType) {\n case 'native-token-stream':\n case 'native-token-periodic':\n case 'erc20-token-stream':\n case 'erc20-token-periodic':\n if (!gatorPermissionsMap[permissionType][chainId]) {\n gatorPermissionsMap[permissionType][chainId] = [];\n }\n\n (\n gatorPermissionsMap[permissionType][\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n default:\n if (!gatorPermissionsMap.other[chainId]) {\n gatorPermissionsMap.other[chainId] = [];\n }\n\n (\n gatorPermissionsMap.other[\n chainId\n ] as StoredGatorPermissionSanitized<\n Signer,\n PermissionTypesWithCustom\n >[]\n ).push(sanitizedStoredGatorPermission);\n break;\n }\n\n return gatorPermissionsMap;\n },\n {\n 'native-token-stream': {},\n 'native-token-periodic': {},\n 'erc20-token-stream': {},\n 'erc20-token-periodic': {},\n other: {},\n } as GatorPermissionsMap,\n );\n }\n\n /**\n * Gets the gator permissions map from the state.\n *\n * @returns The gator permissions map.\n */\n get gatorPermissionsMap(): GatorPermissionsMap {\n return deserializeGatorPermissionsMap(\n this.state.gatorPermissionsMapSerialized,\n );\n }\n\n /**\n * Gets the gator permissions provider snap id that is used to fetch gator permissions.\n *\n * @returns The gator permissions provider snap id.\n */\n get permissionsProviderSnapId(): SnapId {\n return this.state.gatorPermissionsProviderSnapId;\n }\n\n /**\n * Enables gator permissions for the user.\n */\n public async enableGatorPermissions() {\n this.#setIsGatorPermissionsEnabled(true);\n }\n\n /**\n * Clears the gator permissions map and disables the feature.\n */\n public async disableGatorPermissions() {\n this.update((state) => {\n state.isGatorPermissionsEnabled = false;\n state.gatorPermissionsMapSerialized = serializeGatorPermissionsMap(\n defaultGatorPermissionsMap,\n );\n });\n }\n\n /**\n * Gets the pending revocations list.\n *\n * @returns The pending revocations list.\n */\n get pendingRevocations(): { txId: string; permissionContext: Hex }[] {\n return this.state.pendingRevocations;\n }\n\n /**\n * Fetches the gator permissions from profile sync and updates the state.\n *\n * @param params - Optional parameters to pass to the snap's getGrantedPermissions method.\n * @returns A promise that resolves to the gator permissions map.\n * @throws {GatorPermissionsFetchError} If the gator permissions fetch fails.\n */\n public async fetchAndUpdateGatorPermissions(\n params?: Json,\n ): Promise<GatorPermissionsMap> {\n try {\n this.#setIsFetchingGatorPermissions(true);\n this.#assertGatorPermissionsEnabled();\n\n const permissionsData =\n await this.#handleSnapRequestToGatorPermissionsProvider({\n snapId: this.state.gatorPermissionsProviderSnapId,\n params,\n });\n\n const gatorPermissionsMap =\n this.#categorizePermissionsDataByTypeAndChainId(permissionsData);\n\n this.update((state) => {\n state.gatorPermissionsMapSerialized =\n serializeGatorPermissionsMap(gatorPermissionsMap);\n });\n\n return gatorPermissionsMap;\n } catch (error) {\n controllerLog('Failed to fetch gator permissions', error);\n throw new GatorPermissionsFetchError({\n message: 'Failed to fetch gator permissions',\n cause: error as Error,\n });\n } finally {\n this.#setIsFetchingGatorPermissions(false);\n }\n }\n\n /**\n * Decodes a permission context into a structured permission for a specific origin.\n *\n * This method validates the caller origin, decodes the provided `permissionContext`\n * into delegations, identifies the permission type from the caveat enforcers,\n * extracts the permission-specific data and expiry, and reconstructs a\n * {@link DecodedPermission} containing chainId, account addresses, signer, type and data.\n *\n * @param args - The arguments to this function.\n * @param args.origin - The caller's origin; must match the configured permissions provider Snap id.\n * @param args.chainId - Numeric EIP-155 chain id used for resolving enforcer contracts and encoding.\n * @param args.delegation - delegation representing the permission.\n * @param args.metadata - metadata included in the request.\n * @param args.metadata.justification - the justification as specified in the request metadata.\n * @param args.metadata.origin - the origin as specified in the request metadata.\n *\n * @returns A decoded permission object suitable for UI consumption and follow-up actions.\n * @throws If the origin is not allowed, the context cannot be decoded into exactly one delegation,\n * or the enforcers/terms do not match a supported permission type.\n */\n public decodePermissionFromPermissionContextForOrigin({\n origin,\n chainId,\n delegation: { caveats, delegator, delegate, authority },\n metadata: { justification, origin: specifiedOrigin },\n }: {\n origin: string;\n chainId: number;\n metadata: {\n justification: string;\n origin: string;\n };\n delegation: DelegationDetails;\n }): DecodedPermission {\n if (origin !== this.permissionsProviderSnapId) {\n throw new OriginNotAllowedError({ origin });\n }\n\n const contracts = contractsByChainId[chainId];\n\n if (!contracts) {\n throw new Error(`Contracts not found for chainId: ${chainId}`);\n }\n\n try {\n const enforcers = caveats.map((caveat) => caveat.enforcer);\n\n const permissionType = identifyPermissionByEnforcers({\n enforcers,\n contracts,\n });\n\n const { expiry, data } = getPermissionDataAndExpiry({\n contracts,\n caveats,\n permissionType,\n });\n\n const permission = reconstructDecodedPermission({\n chainId,\n permissionType,\n delegator,\n delegate,\n authority,\n expiry,\n data,\n justification,\n specifiedOrigin,\n });\n\n return permission;\n } catch (error) {\n throw new PermissionDecodingError({\n cause: error as Error,\n });\n }\n }\n\n /**\n * Submits a revocation to the gator permissions provider snap.\n *\n * @param revocationParams - The revocation parameters containing the permission context.\n * @returns A promise that resolves when the revocation is submitted successfully.\n * @throws {GatorPermissionsNotEnabledError} If the gator permissions are not enabled.\n * @throws {GatorPermissionsProviderError} If the snap request fails.\n */\n public async submitRevocation(\n revocationParams: RevocationParams,\n ): Promise<void> {\n controllerLog('submitRevocation method called', {\n permissionContext: revocationParams.permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n try {\n const snapRequest = {\n snapId: this.state.gatorPermissionsProviderSnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n jsonrpc: '2.0',\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n params: revocationParams,\n },\n };\n\n const result = await this.messenger.call(\n 'SnapController:handleRequest',\n snapRequest,\n );\n\n this.#removePendingRevocationFromStateByPermissionContext(\n revocationParams.permissionContext,\n );\n\n controllerLog('Successfully submitted revocation', {\n permissionContext: revocationParams.permissionContext,\n result,\n });\n } catch (error) {\n controllerLog('Failed to submit revocation', {\n error,\n permissionContext: revocationParams.permissionContext,\n });\n\n throw new GatorPermissionsProviderError({\n method:\n GatorPermissionsSnapRpcMethod.PermissionProviderSubmitRevocation,\n cause: error as Error,\n });\n }\n }\n\n /**\n * Adds a pending revocation that will be submitted once the transaction is confirmed.\n *\n * This method sets up listeners for the user's approval/rejection decision and\n * terminal transaction states (confirmed, failed, dropped). The flow is:\n * 1. Wait for user to approve or reject the transaction\n * 2. If approved, add to pending revocations state\n * 3. If rejected, cleanup without adding to state\n * 4. If confirmed, submit the revocation\n * 5. If failed or dropped, cleanup\n *\n * Includes a timeout safety net to prevent memory leaks if the transaction never\n * reaches a terminal state.\n *\n * @param params - The pending revocation parameters.\n * @returns A promise that resolves when the listener is set up.\n */\n public async addPendingRevocation(\n params: PendingRevocationParams,\n ): Promise<void> {\n const { txId, permissionContext } = params;\n\n controllerLog('addPendingRevocation method called', {\n txId,\n permissionContext,\n });\n\n this.#assertGatorPermissionsEnabled();\n\n type PendingRevocationHandlers = {\n approved?: (\n ...args: TransactionControllerTransactionApprovedEvent['payload']\n ) => void;\n rejected?: (\n ...args: TransactionControllerTransactionRejectedEvent['payload']\n ) => void;\n confirmed?: (\n ...args: TransactionControllerTransactionConfirmedEvent['payload']\n ) => void;\n failed?: (\n ...args: TransactionControllerTransactionFailedEvent['payload']\n ) => void;\n dropped?: (\n ...args: TransactionControllerTransactionDroppedEvent['payload']\n ) => void;\n timeoutId?: ReturnType<typeof setTimeout>;\n };\n\n // Track handlers and timeout for cleanup\n const handlers: PendingRevocationHandlers = {\n approved: undefined,\n rejected: undefined,\n confirmed: undefined,\n failed: undefined,\n dropped: undefined,\n timeoutId: undefined,\n };\n\n // Helper to unsubscribe from approval/rejection events after decision is made\n const cleanupApprovalHandlers = () => {\n if (handlers.approved) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionApproved',\n handlers.approved,\n );\n handlers.approved = undefined;\n }\n if (handlers.rejected) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionRejected',\n handlers.rejected,\n );\n handlers.rejected = undefined;\n }\n };\n\n // Cleanup function to unsubscribe from all events and clear timeout\n const cleanup = (txIdToRemove: string, removeFromState = true) => {\n cleanupApprovalHandlers();\n if (handlers.confirmed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n }\n if (handlers.failed) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n }\n if (handlers.dropped) {\n this.messenger.unsubscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n }\n if (handlers.timeoutId !== undefined) {\n clearTimeout(handlers.timeoutId);\n }\n\n // Remove the pending revocation from the state (only if it was added)\n if (removeFromState) {\n this.#removePendingRevocationFromStateByTxId(txIdToRemove);\n }\n };\n\n // Handle approved transaction - add to pending revocations state\n handlers.approved = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog(\n 'Transaction approved by user, adding to pending revocations',\n {\n txId,\n permissionContext,\n },\n );\n\n this.#addPendingRevocationToState(txId, permissionContext);\n\n // Unsubscribe from approval/rejection events since decision is made\n cleanupApprovalHandlers();\n }\n };\n\n // Handle rejected transaction - cleanup without adding to state\n handlers.rejected = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction rejected by user, cleaning up listeners', {\n txId,\n permissionContext,\n });\n\n // Don't remove from state since it was never added\n cleanup(payload.transactionMeta.id, false);\n }\n };\n\n // Handle confirmed transaction - submit revocation\n handlers.confirmed = (transactionMeta) => {\n if (transactionMeta.id === txId) {\n controllerLog('Transaction confirmed, submitting revocation', {\n txId,\n permissionContext,\n });\n\n this.submitRevocation({ permissionContext }).catch((error) => {\n controllerLog(\n 'Failed to submit revocation after transaction confirmed',\n {\n txId,\n permissionContext,\n error,\n },\n );\n });\n\n cleanup(transactionMeta.id);\n }\n };\n\n // Handle failed transaction - cleanup without submitting revocation\n handlers.failed = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction failed, cleaning up revocation listener', {\n txId,\n permissionContext,\n error: payload.error,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Handle dropped transaction - cleanup without submitting revocation\n handlers.dropped = (payload) => {\n if (payload.transactionMeta.id === txId) {\n controllerLog('Transaction dropped, cleaning up revocation listener', {\n txId,\n permissionContext,\n });\n\n cleanup(payload.transactionMeta.id);\n }\n };\n\n // Subscribe to user approval/rejection events\n this.messenger.subscribe(\n 'TransactionController:transactionApproved',\n handlers.approved,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionRejected',\n handlers.rejected,\n );\n\n // Subscribe to terminal transaction events\n this.messenger.subscribe(\n 'TransactionController:transactionConfirmed',\n handlers.confirmed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionFailed',\n handlers.failed,\n );\n this.messenger.subscribe(\n 'TransactionController:transactionDropped',\n handlers.dropped,\n );\n\n // Set timeout as safety net to prevent memory leaks\n handlers.timeoutId = setTimeout(() => {\n controllerLog('Pending revocation timed out, cleaning up listeners', {\n txId,\n permissionContext,\n });\n cleanup(txId);\n }, PENDING_REVOCATION_TIMEOUT);\n }\n}\n"]}
|
package/package.json
CHANGED