Skip to content

Commit 738fb9e

Browse files
authored
Merge pull request #89 from MetaMask/feat/native-token-periodic
Add `native-token-periodic` permission
2 parents 183f5e0 + b16d5de commit 738fb9e

30 files changed

Lines changed: 3404 additions & 212 deletions

packages/gator-permissions-snap/snap.manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"url": "https://github.com/MetaMask/snap-7715-permissions.git"
88
},
99
"source": {
10-
"shasum": "v1B05D89zwDAj6nm4a1UG2nA1s5h/k6sFLYGUPJliGc=",
10+
"shasum": "D1xZgkqOmv2yug3z6/YsbDkUWAzgxWujvWgz+W5bWH8=",
1111
"location": {
1212
"npm": {
1313
"filePath": "dist/bundle.js",

packages/gator-permissions-snap/src/core/permissionHandler.ts

Lines changed: 5 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { PermissionRequest } from '@metamask/7715-permissions-shared/types';
22
import { UserInputEventType } from '@metamask/snaps-sdk';
3-
import { type GenericSnapElement } from '@metamask/snaps-sdk/jsx';
43

54
import type { AccountController } from '../accountController';
65
import type { TokenPricesService } from '../services/tokenPricesService';
@@ -19,68 +18,12 @@ import type {
1918
PermissionRequestResult,
2019
RuleDefinition,
2120
PermissionHandlerType,
21+
PermissionHandlerDependencies,
22+
PermissionHandlerParams,
2223
} from './types';
2324

2425
export const JUSTIFICATION_SHOW_MORE_BUTTON_NAME = 'show-more-justification';
2526

26-
export type PermissionHandlerDependencies<
27-
TRequest extends PermissionRequest,
28-
TContext extends BaseContext,
29-
TMetadata extends object,
30-
TPermission extends TRequest['permission'],
31-
TPopulatedPermission extends DeepRequired<TPermission>,
32-
> = {
33-
validateRequest: (permissionRequest: TRequest) => TRequest;
34-
buildContext: (args: {
35-
permissionRequest: TRequest;
36-
tokenPricesService: any;
37-
accountController: AccountController;
38-
}) => Promise<TContext>;
39-
deriveMetadata: (args: { context: TContext }) => Promise<TMetadata>;
40-
createConfirmationContent: (args: {
41-
context: TContext;
42-
metadata: TMetadata;
43-
origin: string;
44-
chainId: number;
45-
isJustificationCollapsed: boolean;
46-
showAddMoreRulesButton: boolean;
47-
}) => Promise<GenericSnapElement>;
48-
applyContext: (args: {
49-
context: TContext;
50-
originalRequest: TRequest;
51-
}) => Promise<TRequest>;
52-
populatePermission: (args: {
53-
permission: TPermission;
54-
}) => Promise<TPopulatedPermission>;
55-
appendCaveats: (args: {
56-
permission: TPopulatedPermission;
57-
caveatBuilder: any;
58-
}) => Promise<any>;
59-
};
60-
61-
export type PermissionHandlerParams<
62-
TRequest extends PermissionRequest,
63-
TContext extends BaseContext,
64-
TMetadata extends object,
65-
TPermission extends TRequest['permission'],
66-
TPopulatedPermission extends DeepRequired<TPermission>,
67-
> = {
68-
accountController: AccountController;
69-
userEventDispatcher: UserEventDispatcher;
70-
orchestrator: PermissionRequestLifecycleOrchestrator;
71-
permissionRequest: TRequest;
72-
dependencies: PermissionHandlerDependencies<
73-
TRequest,
74-
TContext,
75-
TMetadata,
76-
TPermission,
77-
TPopulatedPermission
78-
>;
79-
tokenPricesService: any;
80-
rules: RuleDefinition<TContext, TMetadata>[];
81-
title: string;
82-
};
83-
8427
/**
8528
* Handler for permission requests.
8629
* Coordinates the permission-specific validation, UI, and caveat logic.
@@ -99,7 +42,7 @@ export class PermissionHandler<
9942

10043
readonly #orchestrator: PermissionRequestLifecycleOrchestrator;
10144

102-
readonly #permissionRequest: TRequest;
45+
readonly #permissionRequest: PermissionRequest;
10346

10447
readonly #dependencies: PermissionHandlerDependencies<
10548
TRequest,
@@ -290,15 +233,15 @@ export class PermissionHandler<
290233
};
291234

292235
const {
293-
validateRequest,
236+
parseAndValidatePermission,
294237
applyContext,
295238
populatePermission,
296239
appendCaveats,
297240
deriveMetadata,
298241
} = this.#dependencies;
299242

300243
return {
301-
validateRequest,
244+
parseAndValidatePermission,
302245
applyContext,
303246
populatePermission,
304247
appendCaveats,

packages/gator-permissions-snap/src/core/permissionHandlerFactory.ts

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ import type { PermissionRequest } from '@metamask/7715-permissions-shared/types'
22
import { extractPermissionName } from '@metamask/7715-permissions-shared/utils';
33

44
import type { AccountController } from '../accountController';
5-
import { createNativeTokenStreamHandler } from '../permissions/nativeTokenStream/createHandler';
6-
import type { NativeTokenStreamPermissionRequest } from '../permissions/nativeTokenStream/types';
5+
import { nativeTokenPeriodicPermissionDefinition } from '../permissions/nativeTokenPeriodic';
6+
import { nativeTokenStreamPermissionDefinition } from '../permissions/nativeTokenStream';
77
import type { TokenPricesService } from '../services/tokenPricesService';
88
import type { UserEventDispatcher } from '../userEventDispatcher';
9-
import type { ConfirmationDialogFactory } from './confirmationFactory';
9+
import { PermissionHandler } from './permissionHandler';
1010
import type { PermissionRequestLifecycleOrchestrator } from './permissionRequestLifecycleOrchestrator';
11-
import type { PermissionHandlerType } from './types';
11+
import type {
12+
BaseContext,
13+
DeepRequired,
14+
PermissionDefinition,
15+
PermissionHandlerType,
16+
} from './types';
1217

1318
/**
1419
* Factory for creating permission-specific orchestrators.
@@ -19,28 +24,23 @@ export class PermissionHandlerFactory {
1924

2025
readonly #tokenPricesService: TokenPricesService;
2126

22-
readonly #confirmationDialogFactory: ConfirmationDialogFactory;
23-
2427
readonly #userEventDispatcher: UserEventDispatcher;
2528

2629
readonly #orchestrator: PermissionRequestLifecycleOrchestrator;
2730

2831
constructor({
2932
accountController,
3033
tokenPricesService,
31-
confirmationDialogFactory,
3234
userEventDispatcher,
3335
orchestrator,
3436
}: {
3537
accountController: AccountController;
3638
tokenPricesService: TokenPricesService;
37-
confirmationDialogFactory: ConfirmationDialogFactory;
3839
userEventDispatcher: UserEventDispatcher;
3940
orchestrator: PermissionRequestLifecycleOrchestrator;
4041
}) {
4142
this.#accountController = accountController;
4243
this.#tokenPricesService = tokenPricesService;
43-
this.#confirmationDialogFactory = confirmationDialogFactory;
4444
this.#userEventDispatcher = userEventDispatcher;
4545
this.#orchestrator = orchestrator;
4646
}
@@ -56,23 +56,47 @@ export class PermissionHandlerFactory {
5656
): PermissionHandlerType {
5757
const type = extractPermissionName(permissionRequest.permission.type);
5858

59-
const baseDependencies = {
60-
permissionRequest:
61-
permissionRequest as NativeTokenStreamPermissionRequest,
62-
accountController: this.#accountController,
63-
confirmationDialogFactory: this.#confirmationDialogFactory,
64-
userEventDispatcher: this.#userEventDispatcher,
65-
orchestrator: this.#orchestrator,
59+
const createPermissionHandler = <
60+
TRequest extends PermissionRequest,
61+
TContext extends BaseContext,
62+
TMetadata extends object,
63+
TPermission extends TRequest['permission'],
64+
TPopulatedPermission extends DeepRequired<TPermission>,
65+
>(
66+
permissionDefinition: PermissionDefinition<
67+
TRequest,
68+
TContext,
69+
TMetadata,
70+
TPermission,
71+
TPopulatedPermission
72+
>,
73+
): PermissionHandlerType => {
74+
return new PermissionHandler({
75+
...permissionDefinition,
76+
accountController: this.#accountController,
77+
userEventDispatcher: this.#userEventDispatcher,
78+
orchestrator: this.#orchestrator,
79+
permissionRequest,
80+
tokenPricesService: this.#tokenPricesService,
81+
});
6682
};
83+
let handler: PermissionHandlerType;
6784

6885
switch (type) {
6986
case 'native-token-stream':
70-
return createNativeTokenStreamHandler({
71-
...baseDependencies,
72-
tokenPricesService: this.#tokenPricesService,
73-
});
87+
handler = createPermissionHandler(
88+
nativeTokenStreamPermissionDefinition,
89+
);
90+
break;
91+
case 'native-token-periodic':
92+
handler = createPermissionHandler(
93+
nativeTokenPeriodicPermissionDefinition,
94+
);
95+
break;
7496
default:
7597
throw new Error(`Unsupported permission type: ${type}`);
7698
}
99+
100+
return handler;
77101
}
78102
}

packages/gator-permissions-snap/src/core/permissionRequestLifecycleOrchestrator.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export class PermissionRequestLifecycleOrchestrator {
5454
TPopulatedPermission extends DeepRequired<TPermission>,
5555
>(
5656
origin: string,
57-
permissionRequest: TRequest,
57+
permissionRequest: PermissionRequest,
5858
lifecycleHandlers: LifecycleOrchestrationHandlers<
5959
TRequest,
6060
TContext,
@@ -66,7 +66,7 @@ export class PermissionRequestLifecycleOrchestrator {
6666
const isAdjustmentAllowed = permissionRequest.isAdjustmentAllowed ?? true;
6767

6868
const validatedPermissionRequest =
69-
lifecycleHandlers.validateRequest(permissionRequest);
69+
lifecycleHandlers.parseAndValidatePermission(permissionRequest);
7070

7171
const chainId = parseInt(permissionRequest.chainId, 16);
7272

packages/gator-permissions-snap/src/core/ruleModalManager.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class RuleModalManager<
8484
}
8585

8686
hasRulesToAdd(args: { context: TContext }) {
87-
return this.#getRulesToAdd(args).length > 0;
87+
return this.#getRulesToAdd({ context: args.context }).length > 0;
8888
}
8989

9090
async renderModal() {

packages/gator-permissions-snap/src/core/rules.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export function renderRule<
3232
}): GenericSnapElement | null {
3333
const value = rule.value(context);
3434

35-
if (value === undefined) {
35+
const isVisible = rule.isVisible?.(context) ?? true;
36+
37+
if (value === undefined || !isVisible) {
3638
// If the value is not set, don't render the rule
3739
return null;
3840
}

0 commit comments

Comments
 (0)