@metamask/snaps-rpc-methods 11.1.1 → 11.2.0

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 CHANGED
@@ -1,4 +1,5 @@
1
1
  # Changelog
2
+
2
3
  All notable changes to this project will be documented in this file.
3
4
 
4
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
@@ -6,16 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
7
 
7
8
  ## [Unreleased]
8
9
 
10
+ ## [11.2.0]
11
+
12
+ ### Added
13
+
14
+ - Add support for `metamask:` schemed URLs ([#2719](https://github.com/MetaMask/snaps/pull/2719))
15
+ - Add support for JSX in `snap_notify` notifications ([#2706](https://github.com/MetaMask/snaps/pull/2706))
16
+
9
17
  ## [11.1.1]
18
+
10
19
  ### Fixed
20
+
11
21
  - Fix invalid types in type declaration in some cases ([#2714](https://github.com/MetaMask/snaps/pull/2714))
12
22
 
13
23
  ## [11.1.0]
24
+
14
25
  ### Changed
26
+
15
27
  - Improve error messaging ([#2696](https://github.com/MetaMask/snaps/pull/2696))
16
28
  - Increase character limit for in-app notification messages ([#2684](https://github.com/MetaMask/snaps/pull/2684))
17
29
 
18
30
  ### Fixed
31
+
19
32
  - Fix ESM version of the package ([#2682](https://github.com/MetaMask/snaps/pull/2682))
20
33
  - This fixes the ESM version of the package to be fully compliant with the ESM
21
34
  standard.
@@ -23,85 +36,118 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
23
36
  - Bump other MetaMask dependencies ([#2703](https://github.com/MetaMask/snaps/pull/2703))
24
37
 
25
38
  ## [11.0.0]
39
+
26
40
  ### Added
41
+
27
42
  - **BREAKING:** Add `snap_getPreferences` ([#2607](https://github.com/MetaMask/snaps/pull/2607))
28
43
  - This is breaking because a `getPreferences` method hook is now required.
29
44
 
30
45
  ## [10.0.1]
46
+
31
47
  ### Changed
48
+
32
49
  - Bump `@metamask/json-rpc-engine` from `^9.0.0` to `^9.0.2` ([#2593](https://github.com/metamask/snaps/pull/2593))
33
50
  - Bump `@metamask/permission-controller` from `^10.0.1` to `^11.0.0` ([#2593](https://github.com/metamask/snaps/pull/2593))
34
51
  - Bump `@metamask/snaps-utils` from `^7.8.0` to `^7.8.1` ([#2595](https://github.com/MetaMask/snaps/pull/2595))
35
52
 
36
53
  ## [10.0.0]
54
+
37
55
  ### Added
56
+
38
57
  - **BREAKING:** `snap_dialog` now takes the `requestUserApproval` hook ([#2509](https://github.com/metamask/snaps/pull/2509))
39
58
  - It should bind to the `addAndShowRequest` method of the `ApprovalController`.
40
59
  - Add type `DialogApprovalTypes` and object `DIALOG_APPROVAL_TYPES`.
41
60
 
42
61
  ### Changed
62
+
43
63
  - Bump `@metamask/key-tree` from `^9.1.1` to `^9.1.2` ([#2445](https://github.com/MetaMask/snaps/pull/2445))
44
64
  - Bump `@metamask/permission-controller` from `^10.0.0` to `^10.0.1` ([#2445](https://github.com/MetaMask/snaps/pull/2445))
45
65
  - Bump `@metamask/rpc-errors` from `^6.2.1` to `^6.3.1` ([#2445](https://github.com/MetaMask/snaps/pull/2445))
46
66
  - Bump `@metamask/utils` from `^8.3.0` to `^9.1.0` ([#2445](https://github.com/MetaMask/snaps/pull/2445))
47
67
 
48
68
  ### Fixed
69
+
49
70
  - Replace `superstruct` with ESM-compatible `@metamask/superstruct` `^3.1.0` ([#2445](https://github.com/MetaMask/snaps/pull/2445))
50
71
  - This fixes the issue of this package being unusable by any TypeScript project that uses `Node16` or `NodeNext` as its `moduleResolution` option.
51
72
 
52
73
  ## [9.1.4]
74
+
53
75
  ### Changed
76
+
54
77
  - Bump MetaMask dependencies ([#2516](https://github.com/MetaMask/snaps/pull/2516))
55
78
 
56
79
  ## [9.1.3]
80
+
57
81
  ### Changed
82
+
58
83
  - Bump MetaMask dependencies ([#2460](https://github.com/MetaMask/snaps/pull/2460))
59
84
 
60
85
  ## [9.1.2]
86
+
61
87
  ### Fixed
88
+
62
89
  - Fix invalid `@metamask/snaps-sdk` imports ([#2452](https://github.com/MetaMask/snaps/pull/2452))
63
90
 
64
91
  ## [9.1.1]
92
+
65
93
  ### Changed
94
+
66
95
  - Bump `@metamask/key-tree` from `9.1.0` to `9.1.1` ([#2431](https://github.com/MetaMask/snaps/pull/2431))
67
96
 
68
97
  ## [9.1.0]
98
+
69
99
  ### Added
100
+
70
101
  - Add `context` field to `snap_createInterface` ([#2413](https://github.com/MetaMask/snaps/pull/2413))
71
102
 
72
103
  ## [9.0.0]
104
+
73
105
  ### Added
106
+
74
107
  - Add support for BIP-32-Ed25519 / CIP-3 key derivation ([#2408](https://github.com/MetaMask/snaps/pull/2408))
75
108
  - The `ed25519Bip32` curve is now supported for `snap_getBip32Entropy` and `snap_getBip32PublicKey`
76
109
 
77
110
  ### Changed
111
+
78
112
  - **BREAKING:** Use hooks in `wallet_invokeSnap` instead of remapping the request to `wallet_snap` ([#2406](https://github.com/MetaMask/snaps/pull/2406))
79
113
 
80
114
  ## [8.1.0]
115
+
81
116
  ### Added
117
+
82
118
  - Add JSX support for custom UI ([#2258](https://github.com/MetaMask/snaps/pull/2258))
83
119
 
84
120
  ## [8.0.0]
121
+
85
122
  ### Changed
123
+
86
124
  - **BREAKING:** Refactor to support changes to encryption ([#2316](https://github.com/MetaMask/snaps/pull/2316))
87
125
  - No longer expects `encrypt` or `decrypt`, instead expects `updateSnapState` and `getSnapState` to be asynchronous
88
126
 
89
127
  ## [7.0.2]
128
+
90
129
  ### Changed
130
+
91
131
  - Bump MetaMask dependencies ([#2270](https://github.com/MetaMask/snaps/pull/2270))
92
132
  - Bump @metamask/json-rpc-engine from 7.3.2 to 7.3.3 ([#2247](https://github.com/MetaMask/snaps/pull/2247))
93
133
 
94
134
  ## [7.0.1]
135
+
95
136
  ### Fixed
137
+
96
138
  - Fix minor build configuration problems ([#2220](https://github.com/MetaMask/snaps/pull/2220))
97
139
 
98
140
  ## [7.0.0]
141
+
99
142
  ### Changed
143
+
100
144
  - **BREAKING:** Update ESM build to be fully compliant with the ESM standard ([#2210](https://github.com/MetaMask/snaps/pull/2210))
101
145
  - Bump `@metamask/rpc-errors` to `^6.2.1` ([#2209](https://github.com/MetaMask/snaps/pull/2209))
102
146
 
103
147
  ## [6.0.0]
148
+
104
149
  ### Added
150
+
105
151
  - **BREAKING:** Add support for dynamic user interfaces ([#1465](https://github.com/MetaMask/snaps/pull/1465), [#2144](https://github.com/MetaMask/snaps/pull/2144), [#2143](https://github.com/MetaMask/snaps/pull/2143))
106
152
  - This adds the `snap_createInterface`, `snap_updateInterface`, and `snap_getInterfaceState` methods.
107
153
  - This is breaking because it changes the expected type of the `showDialog` RPC method hook.
@@ -110,102 +156,143 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
110
156
  - Add endowment permission specifications to this package ([#2155](https://github.com/MetaMask/snaps/pull/2155))
111
157
 
112
158
  ### Changed
159
+
113
160
  - Bump MetaMask dependencies ([#2129](https://github.com/MetaMask/snaps/pull/2129), [#2142](https://github.com/MetaMask/snaps/pull/2142))
114
161
 
115
162
  ## [5.0.0]
163
+
116
164
  ### Added
165
+
117
166
  - Add `snap_getClientStatus` ([#2051](https://github.com/MetaMask/snaps/pull/2051))
118
167
 
119
168
  ### Changed
169
+
120
170
  - **BREAKING:** Use origin bound hooks for `invokeKeyring` ([#2090](https://github.com/MetaMask/snaps/pull/2090))
121
171
  - Bump several MetaMask dependencies ([#2069](https://github.com/MetaMask/snaps/pull/2069), [#2100](https://github.com/MetaMask/snaps/pull/2100))
122
172
 
123
173
  ## [4.1.0]
174
+
124
175
  ### Added
176
+
125
177
  - Add `wallet_getAllSnaps` method to get all installed Snaps ([#2047](https://github.com/MetaMask/snaps/pull/2047))
126
178
 
127
179
  ### Changed
180
+
128
181
  - Bump several MetaMask dependencies ([#2064](https://github.com/MetaMask/snaps/pull/2064), [#2065](https://github.com/MetaMask/snaps/pull/2065))
129
182
 
130
183
  ## [4.0.3]
184
+
131
185
  ### Changed
186
+
132
187
  - Use prototype `startsWith` for RPC method middleware ([#2035](https://github.com/MetaMask/snaps/pull/2035))
133
188
 
134
189
  ## [4.0.2]
190
+
135
191
  ### Changed
192
+
136
193
  - Bump several MetaMask dependencies ([#1989](https://github.com/MetaMask/snaps/pull/1989))
137
194
 
138
195
  ## [4.0.1]
196
+
139
197
  ### Changed
198
+
140
199
  - Bump several MetaMask dependencies ([#1964](https://github.com/MetaMask/snaps/pull/1964), [#1968](https://github.com/MetaMask/snaps/pull/1968))
141
200
 
142
201
  ## [4.0.0]
202
+
143
203
  ### Changed
204
+
144
205
  - Use `@metamask/snaps-sdk` package ([#1930](https://github.com/MetaMask/snaps/pull/1930),
145
206
  [#1950](https://github.com/MetaMask/snaps/pull/1950), [#1954](https://github.com/MetaMask/snaps/pull/1954))
146
207
  - This package replaces the `@metamask/snaps-types` and
147
208
  - `@metamask/snaps-ui` packages.
148
209
 
149
210
  ### Removed
211
+
150
212
  - **BREAKING**: Remove `DialogType`, `ManageStateOperation`, and `NotificationType` enums ([#1930](https://github.com/MetaMask/snaps/pull/1930))
151
213
  - These are now defined in the `@metamask/snaps-sdk` package.
152
214
 
153
215
  ## [3.3.0]
216
+
154
217
  ### Added
218
+
155
219
  - Add support for unencrypted storage using `snap_manageState` ([#1902](https://github.com/MetaMask/snaps/pull/1902))
156
220
 
157
221
  ## [3.2.1]
222
+
158
223
  ### Fixed
224
+
159
225
  - Fix `assertLinksAreSafe` import ([#1908](https://github.com/MetaMask/snaps/pull/1908))
160
226
 
161
227
  ## [3.2.0]
228
+
162
229
  ### Added
230
+
163
231
  - Add support for links in custom UI and notifications ([#1814](https://github.com/MetaMask/snaps/pull/1814))
164
232
 
165
233
  ## [3.1.0]
234
+
166
235
  ### Changed
236
+
167
237
  - Rename package to `@metamask/snaps-rpc-methods` ([#1864](https://github.com/MetaMask/snaps/pull/1864))
168
238
  - Update multiple MetaMask dependencies ([#1841](https://github.com/MetaMask/snaps/pull/1841))
169
239
 
170
240
  ## [3.0.0]
241
+
171
242
  ### Added
243
+
172
244
  - Add keyring export and endowment ([#1787](https://github.com/MetaMask/snaps/pull/1787))
173
245
 
174
246
  ### Changed
247
+
175
248
  - **BREAKING:** Bump minimum Node.js version to `^18.16.0` ([#1741](https://github.com/MetaMask/snaps/pull/1741))
176
249
 
177
250
  ## [2.0.0]
251
+
178
252
  ### Changed
253
+
179
254
  - Initial stable release from main branch ([#1757](https://github.com/MetaMask/snaps/pull/1757))
180
255
 
181
256
  ## [0.38.3-flask.1]
257
+
182
258
  ### Changed
259
+
183
260
  - Bump `metamask/utils` and `metamask/snaps-registry` ([#1738](https://github.com/MetaMask/snaps/pull/1738))
184
261
 
185
262
  ## [0.38.2-flask.1]
263
+
186
264
  ### Changed
265
+
187
266
  - Remove business-logic callbacks from `manageAccounts` ([#1725](https://github.com/MetaMask/snaps/pull/1725))
188
267
  - Bump `@metamask/utils` and `@metamask/snaps-registry` ([#1694](https://github.com/MetaMask/snaps/pull/1694))
189
268
 
190
269
  ## [0.38.1-flask.1]
270
+
191
271
  ### Fixed
272
+
192
273
  - Make `manageAccounts` arguments extend `RestrictedMethodParameters` ([#1687](https://github.com/MetaMask/snaps/pull/1687))
193
274
 
194
275
  ## [0.38.0-flask.1]
276
+
195
277
  ### Added
278
+
196
279
  - Add `snap_getLocale` JSON-RPC method ([#1557](https://github.com/MetaMask/snaps/pull/1557))
197
280
  - This will let snaps get the user locale from the client.
198
281
 
199
282
  ### Fixed
283
+
200
284
  - Fix ed25519 public key derivation ([#1678](https://github.com/MetaMask/snaps/pull/1678))
201
285
 
202
286
  ## [0.37.2-flask.1]
287
+
203
288
  ### Changed
289
+
204
290
  - Release package independently ([#1600](https://github.com/MetaMask/snaps/pull/1600))
205
291
  - The version of the package no longer needs to match the version of all other
206
292
  MetaMask Snaps packages.
207
293
 
208
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@11.1.1...HEAD
294
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@11.2.0...HEAD
295
+ [11.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@11.1.1...@metamask/snaps-rpc-methods@11.2.0
209
296
  [11.1.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@11.1.0...@metamask/snaps-rpc-methods@11.1.1
210
297
  [11.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@11.0.0...@metamask/snaps-rpc-methods@11.1.0
211
298
  [11.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-rpc-methods@10.0.1...@metamask/snaps-rpc-methods@11.0.0
@@ -4,9 +4,41 @@ exports.getValidatedParams = exports.getImplementation = exports.notifyBuilder =
4
4
  const permission_controller_1 = require("@metamask/permission-controller");
5
5
  const rpc_errors_1 = require("@metamask/rpc-errors");
6
6
  const snaps_sdk_1 = require("@metamask/snaps-sdk");
7
+ const jsx_1 = require("@metamask/snaps-sdk/jsx");
7
8
  const snaps_utils_1 = require("@metamask/snaps-utils");
9
+ const superstruct_1 = require("@metamask/superstruct");
8
10
  const utils_1 = require("@metamask/utils");
9
11
  const methodName = 'snap_notify';
12
+ const NativeNotificationStruct = (0, superstruct_1.object)({
13
+ type: (0, snaps_sdk_1.enumValue)(snaps_sdk_1.NotificationType.Native),
14
+ message: (0, superstruct_1.string)(),
15
+ });
16
+ const InAppNotificationStruct = (0, superstruct_1.object)({
17
+ type: (0, snaps_sdk_1.enumValue)(snaps_sdk_1.NotificationType.InApp),
18
+ message: (0, superstruct_1.string)(),
19
+ });
20
+ const InAppNotificationWithDetailsStruct = (0, superstruct_1.object)({
21
+ type: (0, snaps_sdk_1.enumValue)(snaps_sdk_1.NotificationType.InApp),
22
+ message: (0, superstruct_1.string)(),
23
+ content: jsx_1.NotificationComponentsStruct,
24
+ title: (0, superstruct_1.string)(),
25
+ });
26
+ const InAppNotificationWithDetailsAndFooterStruct = (0, superstruct_1.object)({
27
+ type: (0, snaps_sdk_1.enumValue)(snaps_sdk_1.NotificationType.InApp),
28
+ message: (0, superstruct_1.string)(),
29
+ content: jsx_1.NotificationComponentsStruct,
30
+ title: (0, superstruct_1.string)(),
31
+ footerLink: (0, superstruct_1.object)({
32
+ href: (0, superstruct_1.string)(),
33
+ text: (0, superstruct_1.string)(),
34
+ }),
35
+ });
36
+ const NotificationParametersStruct = (0, snaps_sdk_1.union)([
37
+ InAppNotificationStruct,
38
+ InAppNotificationWithDetailsStruct,
39
+ InAppNotificationWithDetailsAndFooterStruct,
40
+ NativeNotificationStruct,
41
+ ]);
10
42
  /**
11
43
  * The specification builder for the `snap_notify` permission.
12
44
  * `snap_notify` allows snaps to send multiple types of notifications to its users.
@@ -31,6 +63,8 @@ const methodHooks = {
31
63
  showInAppNotification: true,
32
64
  isOnPhishingList: true,
33
65
  maybeUpdatePhishingList: true,
66
+ createInterface: true,
67
+ getSnap: true,
34
68
  };
35
69
  exports.notifyBuilder = Object.freeze({
36
70
  targetName: methodName,
@@ -45,15 +79,21 @@ exports.notifyBuilder = Object.freeze({
45
79
  * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.
46
80
  * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.
47
81
  * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.
82
+ * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.
83
+ * @param hooks.getSnap - A function that checks if a snap is installed.
48
84
  * @returns The method implementation which returns `null` on success.
49
85
  * @throws If the params are invalid.
50
86
  */
51
- function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, }) {
87
+ function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, createInterface, getSnap, }) {
52
88
  return async function implementation(args) {
53
89
  const { params, context: { origin }, } = args;
54
- const validatedParams = getValidatedParams(params);
55
90
  await maybeUpdatePhishingList();
56
- (0, snaps_utils_1.validateTextLinks)(validatedParams.message, isOnPhishingList);
91
+ const validatedParams = getValidatedParams(params, isOnPhishingList, getSnap);
92
+ let id;
93
+ if ((0, utils_1.hasProperty)(validatedParams, 'content')) {
94
+ id = await createInterface(origin, validatedParams.content);
95
+ validatedParams.content = id;
96
+ }
57
97
  switch (validatedParams.type) {
58
98
  case snaps_sdk_1.NotificationType.Native:
59
99
  return await showNativeNotification(origin, validatedParams);
@@ -72,9 +112,12 @@ exports.getImplementation = getImplementation;
72
112
  * type. Throws if validation fails.
73
113
  *
74
114
  * @param params - The unvalidated params object from the method request.
115
+ * @param isOnPhishingList - The function that checks for links against the phishing list.
116
+ * @param getSnap - A function that checks if a snap is installed.
75
117
  * @returns The validated method parameter object.
118
+ * @throws If the params are invalid.
76
119
  */
77
- function getValidatedParams(params) {
120
+ function getValidatedParams(params, isOnPhishingList, getSnap) {
78
121
  if (!(0, utils_1.isObject)(params)) {
79
122
  throw rpc_errors_1.rpcErrors.invalidParams({
80
123
  message: 'Expected params to be a single object.',
@@ -102,7 +145,20 @@ function getValidatedParams(params) {
102
145
  message: 'Must specify a non-empty string "message" less than 500 characters long.',
103
146
  });
104
147
  }
105
- return params;
148
+ try {
149
+ const validatedParams = (0, snaps_utils_1.createUnion)(params, NotificationParametersStruct, 'type');
150
+ (0, snaps_utils_1.validateTextLinks)(validatedParams.message, isOnPhishingList, getSnap);
151
+ if ((0, utils_1.hasProperty)(validatedParams, 'footerLink')) {
152
+ (0, snaps_utils_1.validateTextLinks)(validatedParams.footerLink.text, isOnPhishingList, getSnap);
153
+ (0, snaps_utils_1.validateLink)(validatedParams.footerLink.href, isOnPhishingList, getSnap);
154
+ }
155
+ return validatedParams;
156
+ }
157
+ catch (error) {
158
+ throw rpc_errors_1.rpcErrors.invalidParams({
159
+ message: `Invalid params: ${error.message}`,
160
+ });
161
+ }
106
162
  }
107
163
  exports.getValidatedParams = getValidatedParams;
108
164
  //# sourceMappingURL=notify.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"notify.cjs","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PermissionSpecificationBuilder,\n RestrictedMethodOptions,\n ValidPermissionSpecification,\n} from '@metamask/permission-controller';\nimport { PermissionType, SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { NotificationType } from '@metamask/snaps-sdk';\nimport type {\n NotifyParams,\n NotifyResult,\n EnumToUnion,\n} from '@metamask/snaps-sdk';\nimport { validateTextLinks } from '@metamask/snaps-utils';\nimport type { NonEmptyArray } from '@metamask/utils';\nimport { isObject } from '@metamask/utils';\n\nimport { type MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_notify';\n\nexport type NotificationArgs = {\n /**\n * Enum type to determine notification type.\n */\n type: EnumToUnion<NotificationType>;\n\n /**\n * A message to show on the notification.\n */\n message: string;\n};\n\nexport type NotifyMethodHooks = {\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showNativeNotification: (\n snapId: string,\n args: NotificationArgs,\n ) => Promise<null>;\n\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showInAppNotification: (\n snapId: string,\n args: NotificationArgs,\n ) => Promise<null>;\n\n isOnPhishingList: (url: string) => boolean;\n\n maybeUpdatePhishingList: () => Promise<void>;\n};\n\ntype SpecificationBuilderOptions = {\n allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n methodHooks: NotifyMethodHooks;\n};\n\ntype Specification = ValidPermissionSpecification<{\n permissionType: PermissionType.RestrictedMethod;\n targetName: typeof methodName;\n methodImplementation: ReturnType<typeof getImplementation>;\n allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n}>;\n\n/**\n * The specification builder for the `snap_notify` permission.\n * `snap_notify` allows snaps to send multiple types of notifications to its users.\n *\n * @param options - The specification builder options.\n * @param options.allowedCaveats - The optional allowed caveats for the permission.\n * @param options.methodHooks - The RPC method hooks needed by the method implementation.\n * @returns The specification for the `snap_notify` permission.\n */\nexport const specificationBuilder: PermissionSpecificationBuilder<\n PermissionType.RestrictedMethod,\n SpecificationBuilderOptions,\n Specification\n> = ({ allowedCaveats = null, methodHooks }: SpecificationBuilderOptions) => {\n return {\n permissionType: PermissionType.RestrictedMethod,\n targetName: methodName,\n allowedCaveats,\n methodImplementation: getImplementation(methodHooks),\n subjectTypes: [SubjectType.Snap],\n };\n};\n\nconst methodHooks: MethodHooksObject<NotifyMethodHooks> = {\n showNativeNotification: true,\n showInAppNotification: true,\n isOnPhishingList: true,\n maybeUpdatePhishingList: true,\n};\n\nexport const notifyBuilder = Object.freeze({\n targetName: methodName,\n specificationBuilder,\n methodHooks,\n} as const);\n\n/**\n * Builds the method implementation for `snap_notify`.\n *\n * @param hooks - The RPC method hooks.\n * @param hooks.showNativeNotification - A function that shows a native browser notification.\n * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.\n * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.\n * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.\n * @returns The method implementation which returns `null` on success.\n * @throws If the params are invalid.\n */\nexport function getImplementation({\n showNativeNotification,\n showInAppNotification,\n isOnPhishingList,\n maybeUpdatePhishingList,\n}: NotifyMethodHooks) {\n return async function implementation(\n args: RestrictedMethodOptions<NotifyParams>,\n ): Promise<NotifyResult> {\n const {\n params,\n context: { origin },\n } = args;\n\n const validatedParams = getValidatedParams(params);\n\n await maybeUpdatePhishingList();\n\n validateTextLinks(validatedParams.message, isOnPhishingList);\n\n switch (validatedParams.type) {\n case NotificationType.Native:\n return await showNativeNotification(origin, validatedParams);\n case NotificationType.InApp:\n return await showInAppNotification(origin, validatedParams);\n default:\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n };\n}\n\n/**\n * Validates the notify method `params` and returns them cast to the correct\n * type. Throws if validation fails.\n *\n * @param params - The unvalidated params object from the method request.\n * @returns The validated method parameter object.\n */\nexport function getValidatedParams(params: unknown): NotifyParams {\n if (!isObject(params)) {\n throw rpcErrors.invalidParams({\n message: 'Expected params to be a single object.',\n });\n }\n\n const { type, message } = params;\n\n if (\n !type ||\n typeof type !== 'string' ||\n !Object.values(NotificationType).includes(type as NotificationType)\n ) {\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n\n const isNotString = !message || typeof message !== 'string';\n // Set to the max message length on a Mac notification for now.\n if (\n type === NotificationType.Native &&\n (isNotString || message.length >= 50)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 50 characters long.',\n });\n }\n\n if (\n type === NotificationType.InApp &&\n (isNotString || message.length >= 500)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 500 characters long.',\n });\n }\n\n return params as NotificationArgs;\n}\n"]}
1
+ {"version":3,"file":"notify.cjs","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PermissionSpecificationBuilder,\n RestrictedMethodOptions,\n ValidPermissionSpecification,\n} from '@metamask/permission-controller';\nimport { PermissionType, SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { enumValue, NotificationType, union } from '@metamask/snaps-sdk';\nimport type {\n NotifyParams,\n NotifyResult,\n NotificationComponent,\n} from '@metamask/snaps-sdk';\nimport { NotificationComponentsStruct } from '@metamask/snaps-sdk/jsx';\nimport {\n createUnion,\n validateLink,\n validateTextLinks,\n type Snap,\n} from '@metamask/snaps-utils';\nimport type { InferMatching } from '@metamask/snaps-utils';\nimport { object, string } from '@metamask/superstruct';\nimport type { NonEmptyArray } from '@metamask/utils';\nimport { hasProperty, isObject } from '@metamask/utils';\n\nimport { type MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_notify';\n\nconst NativeNotificationStruct = object({\n type: enumValue(NotificationType.Native),\n message: string(),\n});\n\nconst InAppNotificationStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n});\n\nconst InAppNotificationWithDetailsStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n content: NotificationComponentsStruct,\n title: string(),\n});\n\nconst InAppNotificationWithDetailsAndFooterStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n content: NotificationComponentsStruct,\n title: string(),\n footerLink: object({\n href: string(),\n text: string(),\n }),\n});\n\nconst NotificationParametersStruct = union([\n InAppNotificationStruct,\n InAppNotificationWithDetailsStruct,\n InAppNotificationWithDetailsAndFooterStruct,\n NativeNotificationStruct,\n]);\n\nexport type NotificationParameters = InferMatching<\n typeof NotificationParametersStruct,\n NotifyParams\n>;\n\nexport type NotifyMethodHooks = {\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showNativeNotification: (\n snapId: string,\n args: NotificationParameters,\n ) => Promise<null>;\n\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showInAppNotification: (\n snapId: string,\n args: NotificationParameters,\n ) => Promise<null>;\n\n isOnPhishingList: (url: string) => boolean;\n\n maybeUpdatePhishingList: () => Promise<void>;\n\n createInterface: (\n origin: string,\n content: NotificationComponent,\n ) => Promise<string>;\n getSnap: (snapId: string) => Snap | undefined;\n};\n\ntype SpecificationBuilderOptions = {\n allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n methodHooks: NotifyMethodHooks;\n};\n\ntype Specification = ValidPermissionSpecification<{\n permissionType: PermissionType.RestrictedMethod;\n targetName: typeof methodName;\n methodImplementation: ReturnType<typeof getImplementation>;\n allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n}>;\n\n/**\n * The specification builder for the `snap_notify` permission.\n * `snap_notify` allows snaps to send multiple types of notifications to its users.\n *\n * @param options - The specification builder options.\n * @param options.allowedCaveats - The optional allowed caveats for the permission.\n * @param options.methodHooks - The RPC method hooks needed by the method implementation.\n * @returns The specification for the `snap_notify` permission.\n */\nexport const specificationBuilder: PermissionSpecificationBuilder<\n PermissionType.RestrictedMethod,\n SpecificationBuilderOptions,\n Specification\n> = ({ allowedCaveats = null, methodHooks }: SpecificationBuilderOptions) => {\n return {\n permissionType: PermissionType.RestrictedMethod,\n targetName: methodName,\n allowedCaveats,\n methodImplementation: getImplementation(methodHooks),\n subjectTypes: [SubjectType.Snap],\n };\n};\n\nconst methodHooks: MethodHooksObject<NotifyMethodHooks> = {\n showNativeNotification: true,\n showInAppNotification: true,\n isOnPhishingList: true,\n maybeUpdatePhishingList: true,\n createInterface: true,\n getSnap: true,\n};\n\nexport const notifyBuilder = Object.freeze({\n targetName: methodName,\n specificationBuilder,\n methodHooks,\n} as const);\n\n/**\n * Builds the method implementation for `snap_notify`.\n *\n * @param hooks - The RPC method hooks.\n * @param hooks.showNativeNotification - A function that shows a native browser notification.\n * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.\n * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.\n * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.\n * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.\n * @param hooks.getSnap - A function that checks if a snap is installed.\n * @returns The method implementation which returns `null` on success.\n * @throws If the params are invalid.\n */\nexport function getImplementation({\n showNativeNotification,\n showInAppNotification,\n isOnPhishingList,\n maybeUpdatePhishingList,\n createInterface,\n getSnap,\n}: NotifyMethodHooks) {\n return async function implementation(\n args: RestrictedMethodOptions<NotifyParams>,\n ): Promise<NotifyResult> {\n const {\n params,\n context: { origin },\n } = args;\n\n await maybeUpdatePhishingList();\n\n const validatedParams = getValidatedParams(\n params,\n isOnPhishingList,\n getSnap,\n );\n\n let id;\n if (hasProperty(validatedParams, 'content')) {\n id = await createInterface(\n origin,\n validatedParams.content as NotificationComponent,\n );\n validatedParams.content = id;\n }\n\n switch (validatedParams.type) {\n case NotificationType.Native:\n return await showNativeNotification(origin, validatedParams);\n case NotificationType.InApp:\n return await showInAppNotification(origin, validatedParams);\n default:\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n };\n}\n\n/**\n * Validates the notify method `params` and returns them cast to the correct\n * type. Throws if validation fails.\n *\n * @param params - The unvalidated params object from the method request.\n * @param isOnPhishingList - The function that checks for links against the phishing list.\n * @param getSnap - A function that checks if a snap is installed.\n * @returns The validated method parameter object.\n * @throws If the params are invalid.\n */\nexport function getValidatedParams(\n params: unknown,\n isOnPhishingList: NotifyMethodHooks['isOnPhishingList'],\n getSnap: NotifyMethodHooks['getSnap'],\n): NotifyParams {\n if (!isObject(params)) {\n throw rpcErrors.invalidParams({\n message: 'Expected params to be a single object.',\n });\n }\n\n const { type, message } = params;\n\n if (\n !type ||\n typeof type !== 'string' ||\n !Object.values(NotificationType).includes(type as NotificationType)\n ) {\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n\n const isNotString = !message || typeof message !== 'string';\n // Set to the max message length on a Mac notification for now.\n if (\n type === NotificationType.Native &&\n (isNotString || message.length >= 50)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 50 characters long.',\n });\n }\n\n if (\n type === NotificationType.InApp &&\n (isNotString || message.length >= 500)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 500 characters long.',\n });\n }\n\n try {\n const validatedParams = createUnion(\n params,\n NotificationParametersStruct,\n 'type',\n );\n\n validateTextLinks(validatedParams.message, isOnPhishingList, getSnap);\n\n if (hasProperty(validatedParams, 'footerLink')) {\n validateTextLinks(\n validatedParams.footerLink.text,\n isOnPhishingList,\n getSnap,\n );\n validateLink(validatedParams.footerLink.href, isOnPhishingList, getSnap);\n }\n\n return validatedParams;\n } catch (error) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: ${error.message}`,\n });\n }\n}\n"]}
@@ -1,33 +1,109 @@
1
1
  import type { PermissionSpecificationBuilder, RestrictedMethodOptions, ValidPermissionSpecification } from "@metamask/permission-controller";
2
2
  import { PermissionType } from "@metamask/permission-controller";
3
- import { NotificationType } from "@metamask/snaps-sdk";
4
- import type { NotifyParams, NotifyResult, EnumToUnion } from "@metamask/snaps-sdk";
3
+ import type { NotifyParams, NotifyResult, NotificationComponent } from "@metamask/snaps-sdk";
4
+ import { type Snap } from "@metamask/snaps-utils";
5
+ import type { InferMatching } from "@metamask/snaps-utils";
5
6
  import type { NonEmptyArray } from "@metamask/utils";
6
7
  import { type MethodHooksObject } from "../utils.cjs";
7
8
  declare const methodName = "snap_notify";
8
- export type NotificationArgs = {
9
- /**
10
- * Enum type to determine notification type.
11
- */
12
- type: EnumToUnion<NotificationType>;
13
- /**
14
- * A message to show on the notification.
15
- */
9
+ declare const NotificationParametersStruct: import("@metamask/superstruct").Struct<{
10
+ type: "native";
16
11
  message: string;
17
- };
12
+ } | {
13
+ type: "inApp";
14
+ message: string;
15
+ } | {
16
+ type: "inApp";
17
+ message: string;
18
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
19
+ src: string;
20
+ alt?: string | undefined;
21
+ }, "Image">;
22
+ title: string;
23
+ } | {
24
+ type: "inApp";
25
+ message: string;
26
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
27
+ src: string;
28
+ alt?: string | undefined;
29
+ }, "Image">;
30
+ title: string;
31
+ footerLink: {
32
+ text: string;
33
+ href: string;
34
+ };
35
+ }, [head: import("@metamask/superstruct").Struct<{
36
+ type: "inApp";
37
+ message: string;
38
+ }, {
39
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
40
+ message: import("@metamask/superstruct").Struct<string, null>;
41
+ }>, import("@metamask/superstruct").Struct<{
42
+ type: "inApp";
43
+ message: string;
44
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
45
+ src: string;
46
+ alt?: string | undefined;
47
+ }, "Image">;
48
+ title: string;
49
+ }, {
50
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
51
+ message: import("@metamask/superstruct").Struct<string, null>;
52
+ content: import("@metamask/superstruct").Struct<import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
53
+ src: string;
54
+ alt?: string | undefined;
55
+ }, "Image">, null>;
56
+ title: import("@metamask/superstruct").Struct<string, null>;
57
+ }>, import("@metamask/superstruct").Struct<{
58
+ type: "inApp";
59
+ message: string;
60
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
61
+ src: string;
62
+ alt?: string | undefined;
63
+ }, "Image">;
64
+ title: string;
65
+ footerLink: {
66
+ text: string;
67
+ href: string;
68
+ };
69
+ }, {
70
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
71
+ message: import("@metamask/superstruct").Struct<string, null>;
72
+ content: import("@metamask/superstruct").Struct<import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
73
+ src: string;
74
+ alt?: string | undefined;
75
+ }, "Image">, null>;
76
+ title: import("@metamask/superstruct").Struct<string, null>;
77
+ footerLink: import("@metamask/superstruct").Struct<{
78
+ text: string;
79
+ href: string;
80
+ }, {
81
+ href: import("@metamask/superstruct").Struct<string, null>;
82
+ text: import("@metamask/superstruct").Struct<string, null>;
83
+ }>;
84
+ }>, import("@metamask/superstruct").Struct<{
85
+ type: "native";
86
+ message: string;
87
+ }, {
88
+ type: import("@metamask/superstruct").Struct<"native", null>;
89
+ message: import("@metamask/superstruct").Struct<string, null>;
90
+ }>]>;
91
+ export type NotificationParameters = InferMatching<typeof NotificationParametersStruct, NotifyParams>;
18
92
  export type NotifyMethodHooks = {
19
93
  /**
20
94
  * @param snapId - The ID of the Snap that created the notification.
21
95
  * @param args - The notification arguments.
22
96
  */
23
- showNativeNotification: (snapId: string, args: NotificationArgs) => Promise<null>;
97
+ showNativeNotification: (snapId: string, args: NotificationParameters) => Promise<null>;
24
98
  /**
25
99
  * @param snapId - The ID of the Snap that created the notification.
26
100
  * @param args - The notification arguments.
27
101
  */
28
- showInAppNotification: (snapId: string, args: NotificationArgs) => Promise<null>;
102
+ showInAppNotification: (snapId: string, args: NotificationParameters) => Promise<null>;
29
103
  isOnPhishingList: (url: string) => boolean;
30
104
  maybeUpdatePhishingList: () => Promise<void>;
105
+ createInterface: (origin: string, content: NotificationComponent) => Promise<string>;
106
+ getSnap: (snapId: string) => Snap | undefined;
31
107
  };
32
108
  type SpecificationBuilderOptions = {
33
109
  allowedCaveats?: Readonly<NonEmptyArray<string>> | null;
@@ -67,17 +143,22 @@ export declare const notifyBuilder: Readonly<{
67
143
  * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.
68
144
  * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.
69
145
  * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.
146
+ * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.
147
+ * @param hooks.getSnap - A function that checks if a snap is installed.
70
148
  * @returns The method implementation which returns `null` on success.
71
149
  * @throws If the params are invalid.
72
150
  */
73
- export declare function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, }: NotifyMethodHooks): (args: RestrictedMethodOptions<NotifyParams>) => Promise<NotifyResult>;
151
+ export declare function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, createInterface, getSnap, }: NotifyMethodHooks): (args: RestrictedMethodOptions<NotifyParams>) => Promise<NotifyResult>;
74
152
  /**
75
153
  * Validates the notify method `params` and returns them cast to the correct
76
154
  * type. Throws if validation fails.
77
155
  *
78
156
  * @param params - The unvalidated params object from the method request.
157
+ * @param isOnPhishingList - The function that checks for links against the phishing list.
158
+ * @param getSnap - A function that checks if a snap is installed.
79
159
  * @returns The validated method parameter object.
160
+ * @throws If the params are invalid.
80
161
  */
81
- export declare function getValidatedParams(params: unknown): NotifyParams;
162
+ export declare function getValidatedParams(params: unknown, isOnPhishingList: NotifyMethodHooks['isOnPhishingList'], getSnap: NotifyMethodHooks['getSnap']): NotifyParams;
82
163
  export {};
83
164
  //# sourceMappingURL=notify.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notify.d.cts","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,EAC7B,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAE9E,OAAO,EAAE,gBAAgB,EAAE,4BAA4B;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,4BAA4B;AAE7B,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AAEjC,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAEpC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,sBAAsB,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAE3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,KAAK,aAAa,GAAG,4BAA4B,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC;IAChD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,oBAAoB,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC3D,cAAc,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CACxD,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,8BAA8B,CAC/D,cAAc,CAAC,gBAAgB,EAC/B,2BAA2B,EAC3B,aAAa,CASd,CAAC;AASF,eAAO,MAAM,aAAa;;;wBApCR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,wBAAwB,CAAC;wBAC1C,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EAqC7C,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,GACxB,EAAE,iBAAiB,UAEV,wBAAwB,YAAY,CAAC,KAC1C,QAAQ,YAAY,CAAC,CAuBzB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,CA0ChE"}
1
+ {"version":3,"file":"notify.d.cts","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,EAC7B,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAG9E,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACtB,4BAA4B;AAE7B,OAAO,EAIL,KAAK,IAAI,EACV,8BAA8B;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA8B;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AA8BjC,QAAA,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKhC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,aAAa,CAChD,OAAO,4BAA4B,EACnC,YAAY,CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,sBAAsB,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,sBAAsB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,sBAAsB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAE3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,eAAe,EAAE,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,KAAK,aAAa,GAAG,4BAA4B,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC;IAChD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,oBAAoB,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC3D,cAAc,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CACxD,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,8BAA8B,CAC/D,cAAc,CAAC,gBAAgB,EAC/B,2BAA2B,EAC3B,aAAa,CASd,CAAC;AAWF,eAAO,MAAM,aAAa;;;wBAtCR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,wBAAwB,CAAC;wBAC1C,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EAuC7C,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,OAAO,GACR,EAAE,iBAAiB,UAEV,wBAAwB,YAAY,CAAC,KAC1C,QAAQ,YAAY,CAAC,CAkCzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EACf,gBAAgB,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,EACvD,OAAO,EAAE,iBAAiB,CAAC,SAAS,CAAC,GACpC,YAAY,CAiEd"}
@@ -1,33 +1,109 @@
1
1
  import type { PermissionSpecificationBuilder, RestrictedMethodOptions, ValidPermissionSpecification } from "@metamask/permission-controller";
2
2
  import { PermissionType } from "@metamask/permission-controller";
3
- import { NotificationType } from "@metamask/snaps-sdk";
4
- import type { NotifyParams, NotifyResult, EnumToUnion } from "@metamask/snaps-sdk";
3
+ import type { NotifyParams, NotifyResult, NotificationComponent } from "@metamask/snaps-sdk";
4
+ import { type Snap } from "@metamask/snaps-utils";
5
+ import type { InferMatching } from "@metamask/snaps-utils";
5
6
  import type { NonEmptyArray } from "@metamask/utils";
6
7
  import { type MethodHooksObject } from "../utils.mjs";
7
8
  declare const methodName = "snap_notify";
8
- export type NotificationArgs = {
9
- /**
10
- * Enum type to determine notification type.
11
- */
12
- type: EnumToUnion<NotificationType>;
13
- /**
14
- * A message to show on the notification.
15
- */
9
+ declare const NotificationParametersStruct: import("@metamask/superstruct").Struct<{
10
+ type: "native";
16
11
  message: string;
17
- };
12
+ } | {
13
+ type: "inApp";
14
+ message: string;
15
+ } | {
16
+ type: "inApp";
17
+ message: string;
18
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
19
+ src: string;
20
+ alt?: string | undefined;
21
+ }, "Image">;
22
+ title: string;
23
+ } | {
24
+ type: "inApp";
25
+ message: string;
26
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
27
+ src: string;
28
+ alt?: string | undefined;
29
+ }, "Image">;
30
+ title: string;
31
+ footerLink: {
32
+ text: string;
33
+ href: string;
34
+ };
35
+ }, [head: import("@metamask/superstruct").Struct<{
36
+ type: "inApp";
37
+ message: string;
38
+ }, {
39
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
40
+ message: import("@metamask/superstruct").Struct<string, null>;
41
+ }>, import("@metamask/superstruct").Struct<{
42
+ type: "inApp";
43
+ message: string;
44
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
45
+ src: string;
46
+ alt?: string | undefined;
47
+ }, "Image">;
48
+ title: string;
49
+ }, {
50
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
51
+ message: import("@metamask/superstruct").Struct<string, null>;
52
+ content: import("@metamask/superstruct").Struct<import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
53
+ src: string;
54
+ alt?: string | undefined;
55
+ }, "Image">, null>;
56
+ title: import("@metamask/superstruct").Struct<string, null>;
57
+ }>, import("@metamask/superstruct").Struct<{
58
+ type: "inApp";
59
+ message: string;
60
+ content: import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
61
+ src: string;
62
+ alt?: string | undefined;
63
+ }, "Image">;
64
+ title: string;
65
+ footerLink: {
66
+ text: string;
67
+ href: string;
68
+ };
69
+ }, {
70
+ type: import("@metamask/superstruct").Struct<"inApp", null>;
71
+ message: import("@metamask/superstruct").Struct<string, null>;
72
+ content: import("@metamask/superstruct").Struct<import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoldProps, "Bold"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").ItalicProps, "Italic"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").AddressProps, "Address"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").BoxProps, "Box"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").CopyableProps, "Copyable"> | import("@metamask/snaps-sdk/jsx").SnapElement<Record<string, never>, "Divider"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").IconProps, "Icon"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").LinkProps, "Link"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").RowProps, "Row"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TextProps, "Text"> | import("@metamask/snaps-sdk/jsx").SnapElement<import("@metamask/snaps-sdk/jsx").TooltipProps, "Tooltip"> | import("@metamask/snaps-sdk/jsx").SnapElement<{
73
+ src: string;
74
+ alt?: string | undefined;
75
+ }, "Image">, null>;
76
+ title: import("@metamask/superstruct").Struct<string, null>;
77
+ footerLink: import("@metamask/superstruct").Struct<{
78
+ text: string;
79
+ href: string;
80
+ }, {
81
+ href: import("@metamask/superstruct").Struct<string, null>;
82
+ text: import("@metamask/superstruct").Struct<string, null>;
83
+ }>;
84
+ }>, import("@metamask/superstruct").Struct<{
85
+ type: "native";
86
+ message: string;
87
+ }, {
88
+ type: import("@metamask/superstruct").Struct<"native", null>;
89
+ message: import("@metamask/superstruct").Struct<string, null>;
90
+ }>]>;
91
+ export type NotificationParameters = InferMatching<typeof NotificationParametersStruct, NotifyParams>;
18
92
  export type NotifyMethodHooks = {
19
93
  /**
20
94
  * @param snapId - The ID of the Snap that created the notification.
21
95
  * @param args - The notification arguments.
22
96
  */
23
- showNativeNotification: (snapId: string, args: NotificationArgs) => Promise<null>;
97
+ showNativeNotification: (snapId: string, args: NotificationParameters) => Promise<null>;
24
98
  /**
25
99
  * @param snapId - The ID of the Snap that created the notification.
26
100
  * @param args - The notification arguments.
27
101
  */
28
- showInAppNotification: (snapId: string, args: NotificationArgs) => Promise<null>;
102
+ showInAppNotification: (snapId: string, args: NotificationParameters) => Promise<null>;
29
103
  isOnPhishingList: (url: string) => boolean;
30
104
  maybeUpdatePhishingList: () => Promise<void>;
105
+ createInterface: (origin: string, content: NotificationComponent) => Promise<string>;
106
+ getSnap: (snapId: string) => Snap | undefined;
31
107
  };
32
108
  type SpecificationBuilderOptions = {
33
109
  allowedCaveats?: Readonly<NonEmptyArray<string>> | null;
@@ -67,17 +143,22 @@ export declare const notifyBuilder: Readonly<{
67
143
  * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.
68
144
  * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.
69
145
  * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.
146
+ * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.
147
+ * @param hooks.getSnap - A function that checks if a snap is installed.
70
148
  * @returns The method implementation which returns `null` on success.
71
149
  * @throws If the params are invalid.
72
150
  */
73
- export declare function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, }: NotifyMethodHooks): (args: RestrictedMethodOptions<NotifyParams>) => Promise<NotifyResult>;
151
+ export declare function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, createInterface, getSnap, }: NotifyMethodHooks): (args: RestrictedMethodOptions<NotifyParams>) => Promise<NotifyResult>;
74
152
  /**
75
153
  * Validates the notify method `params` and returns them cast to the correct
76
154
  * type. Throws if validation fails.
77
155
  *
78
156
  * @param params - The unvalidated params object from the method request.
157
+ * @param isOnPhishingList - The function that checks for links against the phishing list.
158
+ * @param getSnap - A function that checks if a snap is installed.
79
159
  * @returns The validated method parameter object.
160
+ * @throws If the params are invalid.
80
161
  */
81
- export declare function getValidatedParams(params: unknown): NotifyParams;
162
+ export declare function getValidatedParams(params: unknown, isOnPhishingList: NotifyMethodHooks['isOnPhishingList'], getSnap: NotifyMethodHooks['getSnap']): NotifyParams;
82
163
  export {};
83
164
  //# sourceMappingURL=notify.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"notify.d.mts","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,EAC7B,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAE9E,OAAO,EAAE,gBAAgB,EAAE,4BAA4B;AACvD,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,WAAW,EACZ,4BAA4B;AAE7B,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AAEjC,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAEpC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,sBAAsB,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,gBAAgB,KACnB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAE3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,KAAK,aAAa,GAAG,4BAA4B,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC;IAChD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,oBAAoB,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC3D,cAAc,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CACxD,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,8BAA8B,CAC/D,cAAc,CAAC,gBAAgB,EAC/B,2BAA2B,EAC3B,aAAa,CASd,CAAC;AASF,eAAO,MAAM,aAAa;;;wBApCR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,wBAAwB,CAAC;wBAC1C,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EAqC7C,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,GACxB,EAAE,iBAAiB,UAEV,wBAAwB,YAAY,CAAC,KAC1C,QAAQ,YAAY,CAAC,CAuBzB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,YAAY,CA0ChE"}
1
+ {"version":3,"file":"notify.d.mts","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,EAC7B,wCAAwC;AACzC,OAAO,EAAE,cAAc,EAAe,wCAAwC;AAG9E,OAAO,KAAK,EACV,YAAY,EACZ,YAAY,EACZ,qBAAqB,EACtB,4BAA4B;AAE7B,OAAO,EAIL,KAAK,IAAI,EACV,8BAA8B;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,8BAA8B;AAE3D,OAAO,KAAK,EAAE,aAAa,EAAE,wBAAwB;AAGrD,OAAO,EAAE,KAAK,iBAAiB,EAAE,qBAAiB;AAElD,QAAA,MAAM,UAAU,gBAAgB,CAAC;AA8BjC,QAAA,MAAM,4BAA4B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAKhC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,aAAa,CAChD,OAAO,4BAA4B,EACnC,YAAY,CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,sBAAsB,EAAE,CACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,sBAAsB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,sBAAsB,KACzB,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnB,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IAE3C,uBAAuB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C,eAAe,EAAE,CACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,KAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;IACrB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,GAAG,SAAS,CAAC;CAC/C,CAAC;AAEF,KAAK,2BAA2B,GAAG;IACjC,cAAc,CAAC,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;IACxD,WAAW,EAAE,iBAAiB,CAAC;CAChC,CAAC;AAEF,KAAK,aAAa,GAAG,4BAA4B,CAAC;IAChD,cAAc,EAAE,cAAc,CAAC,gBAAgB,CAAC;IAChD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,oBAAoB,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,CAAC;IAC3D,cAAc,EAAE,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;CACxD,CAAC,CAAC;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,EAAE,8BAA8B,CAC/D,cAAc,CAAC,gBAAgB,EAC/B,2BAA2B,EAC3B,aAAa,CASd,CAAC;AAWF,eAAO,MAAM,aAAa;;;wBAtCR,eAAe,gBAAgB;oBACnC,iBAAiB;8BACP,WAAW,wBAAwB,CAAC;wBAC1C,SAAS,cAAc,MAAM,CAAC,CAAC,GAAG,IAAI;;;EAuC7C,CAAC;AAEZ;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,sBAAsB,EACtB,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,OAAO,GACR,EAAE,iBAAiB,UAEV,wBAAwB,YAAY,CAAC,KAC1C,QAAQ,YAAY,CAAC,CAkCzB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,OAAO,EACf,gBAAgB,EAAE,iBAAiB,CAAC,kBAAkB,CAAC,EACvD,OAAO,EAAE,iBAAiB,CAAC,SAAS,CAAC,GACpC,YAAY,CAiEd"}
@@ -1,9 +1,41 @@
1
1
  import { PermissionType, SubjectType } from "@metamask/permission-controller";
2
2
  import { rpcErrors } from "@metamask/rpc-errors";
3
- import { NotificationType } from "@metamask/snaps-sdk";
4
- import { validateTextLinks } from "@metamask/snaps-utils";
5
- import { isObject } from "@metamask/utils";
3
+ import { enumValue, NotificationType, union } from "@metamask/snaps-sdk";
4
+ import { NotificationComponentsStruct } from "@metamask/snaps-sdk/jsx";
5
+ import { createUnion, validateLink, validateTextLinks } from "@metamask/snaps-utils";
6
+ import { object, string } from "@metamask/superstruct";
7
+ import { hasProperty, isObject } from "@metamask/utils";
6
8
  const methodName = 'snap_notify';
9
+ const NativeNotificationStruct = object({
10
+ type: enumValue(NotificationType.Native),
11
+ message: string(),
12
+ });
13
+ const InAppNotificationStruct = object({
14
+ type: enumValue(NotificationType.InApp),
15
+ message: string(),
16
+ });
17
+ const InAppNotificationWithDetailsStruct = object({
18
+ type: enumValue(NotificationType.InApp),
19
+ message: string(),
20
+ content: NotificationComponentsStruct,
21
+ title: string(),
22
+ });
23
+ const InAppNotificationWithDetailsAndFooterStruct = object({
24
+ type: enumValue(NotificationType.InApp),
25
+ message: string(),
26
+ content: NotificationComponentsStruct,
27
+ title: string(),
28
+ footerLink: object({
29
+ href: string(),
30
+ text: string(),
31
+ }),
32
+ });
33
+ const NotificationParametersStruct = union([
34
+ InAppNotificationStruct,
35
+ InAppNotificationWithDetailsStruct,
36
+ InAppNotificationWithDetailsAndFooterStruct,
37
+ NativeNotificationStruct,
38
+ ]);
7
39
  /**
8
40
  * The specification builder for the `snap_notify` permission.
9
41
  * `snap_notify` allows snaps to send multiple types of notifications to its users.
@@ -27,6 +59,8 @@ const methodHooks = {
27
59
  showInAppNotification: true,
28
60
  isOnPhishingList: true,
29
61
  maybeUpdatePhishingList: true,
62
+ createInterface: true,
63
+ getSnap: true,
30
64
  };
31
65
  export const notifyBuilder = Object.freeze({
32
66
  targetName: methodName,
@@ -41,15 +75,21 @@ export const notifyBuilder = Object.freeze({
41
75
  * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.
42
76
  * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.
43
77
  * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.
78
+ * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.
79
+ * @param hooks.getSnap - A function that checks if a snap is installed.
44
80
  * @returns The method implementation which returns `null` on success.
45
81
  * @throws If the params are invalid.
46
82
  */
47
- export function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, }) {
83
+ export function getImplementation({ showNativeNotification, showInAppNotification, isOnPhishingList, maybeUpdatePhishingList, createInterface, getSnap, }) {
48
84
  return async function implementation(args) {
49
85
  const { params, context: { origin }, } = args;
50
- const validatedParams = getValidatedParams(params);
51
86
  await maybeUpdatePhishingList();
52
- validateTextLinks(validatedParams.message, isOnPhishingList);
87
+ const validatedParams = getValidatedParams(params, isOnPhishingList, getSnap);
88
+ let id;
89
+ if (hasProperty(validatedParams, 'content')) {
90
+ id = await createInterface(origin, validatedParams.content);
91
+ validatedParams.content = id;
92
+ }
53
93
  switch (validatedParams.type) {
54
94
  case NotificationType.Native:
55
95
  return await showNativeNotification(origin, validatedParams);
@@ -67,9 +107,12 @@ export function getImplementation({ showNativeNotification, showInAppNotificatio
67
107
  * type. Throws if validation fails.
68
108
  *
69
109
  * @param params - The unvalidated params object from the method request.
110
+ * @param isOnPhishingList - The function that checks for links against the phishing list.
111
+ * @param getSnap - A function that checks if a snap is installed.
70
112
  * @returns The validated method parameter object.
113
+ * @throws If the params are invalid.
71
114
  */
72
- export function getValidatedParams(params) {
115
+ export function getValidatedParams(params, isOnPhishingList, getSnap) {
73
116
  if (!isObject(params)) {
74
117
  throw rpcErrors.invalidParams({
75
118
  message: 'Expected params to be a single object.',
@@ -97,6 +140,19 @@ export function getValidatedParams(params) {
97
140
  message: 'Must specify a non-empty string "message" less than 500 characters long.',
98
141
  });
99
142
  }
100
- return params;
143
+ try {
144
+ const validatedParams = createUnion(params, NotificationParametersStruct, 'type');
145
+ validateTextLinks(validatedParams.message, isOnPhishingList, getSnap);
146
+ if (hasProperty(validatedParams, 'footerLink')) {
147
+ validateTextLinks(validatedParams.footerLink.text, isOnPhishingList, getSnap);
148
+ validateLink(validatedParams.footerLink.href, isOnPhishingList, getSnap);
149
+ }
150
+ return validatedParams;
151
+ }
152
+ catch (error) {
153
+ throw rpcErrors.invalidParams({
154
+ message: `Invalid params: ${error.message}`,
155
+ });
156
+ }
101
157
  }
102
158
  //# sourceMappingURL=notify.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"notify.mjs","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PermissionSpecificationBuilder,\n RestrictedMethodOptions,\n ValidPermissionSpecification,\n} from '@metamask/permission-controller';\nimport { PermissionType, SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { NotificationType } from '@metamask/snaps-sdk';\nimport type {\n NotifyParams,\n NotifyResult,\n EnumToUnion,\n} from '@metamask/snaps-sdk';\nimport { validateTextLinks } from '@metamask/snaps-utils';\nimport type { NonEmptyArray } from '@metamask/utils';\nimport { isObject } from '@metamask/utils';\n\nimport { type MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_notify';\n\nexport type NotificationArgs = {\n /**\n * Enum type to determine notification type.\n */\n type: EnumToUnion<NotificationType>;\n\n /**\n * A message to show on the notification.\n */\n message: string;\n};\n\nexport type NotifyMethodHooks = {\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showNativeNotification: (\n snapId: string,\n args: NotificationArgs,\n ) => Promise<null>;\n\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showInAppNotification: (\n snapId: string,\n args: NotificationArgs,\n ) => Promise<null>;\n\n isOnPhishingList: (url: string) => boolean;\n\n maybeUpdatePhishingList: () => Promise<void>;\n};\n\ntype SpecificationBuilderOptions = {\n allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n methodHooks: NotifyMethodHooks;\n};\n\ntype Specification = ValidPermissionSpecification<{\n permissionType: PermissionType.RestrictedMethod;\n targetName: typeof methodName;\n methodImplementation: ReturnType<typeof getImplementation>;\n allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n}>;\n\n/**\n * The specification builder for the `snap_notify` permission.\n * `snap_notify` allows snaps to send multiple types of notifications to its users.\n *\n * @param options - The specification builder options.\n * @param options.allowedCaveats - The optional allowed caveats for the permission.\n * @param options.methodHooks - The RPC method hooks needed by the method implementation.\n * @returns The specification for the `snap_notify` permission.\n */\nexport const specificationBuilder: PermissionSpecificationBuilder<\n PermissionType.RestrictedMethod,\n SpecificationBuilderOptions,\n Specification\n> = ({ allowedCaveats = null, methodHooks }: SpecificationBuilderOptions) => {\n return {\n permissionType: PermissionType.RestrictedMethod,\n targetName: methodName,\n allowedCaveats,\n methodImplementation: getImplementation(methodHooks),\n subjectTypes: [SubjectType.Snap],\n };\n};\n\nconst methodHooks: MethodHooksObject<NotifyMethodHooks> = {\n showNativeNotification: true,\n showInAppNotification: true,\n isOnPhishingList: true,\n maybeUpdatePhishingList: true,\n};\n\nexport const notifyBuilder = Object.freeze({\n targetName: methodName,\n specificationBuilder,\n methodHooks,\n} as const);\n\n/**\n * Builds the method implementation for `snap_notify`.\n *\n * @param hooks - The RPC method hooks.\n * @param hooks.showNativeNotification - A function that shows a native browser notification.\n * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.\n * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.\n * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.\n * @returns The method implementation which returns `null` on success.\n * @throws If the params are invalid.\n */\nexport function getImplementation({\n showNativeNotification,\n showInAppNotification,\n isOnPhishingList,\n maybeUpdatePhishingList,\n}: NotifyMethodHooks) {\n return async function implementation(\n args: RestrictedMethodOptions<NotifyParams>,\n ): Promise<NotifyResult> {\n const {\n params,\n context: { origin },\n } = args;\n\n const validatedParams = getValidatedParams(params);\n\n await maybeUpdatePhishingList();\n\n validateTextLinks(validatedParams.message, isOnPhishingList);\n\n switch (validatedParams.type) {\n case NotificationType.Native:\n return await showNativeNotification(origin, validatedParams);\n case NotificationType.InApp:\n return await showInAppNotification(origin, validatedParams);\n default:\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n };\n}\n\n/**\n * Validates the notify method `params` and returns them cast to the correct\n * type. Throws if validation fails.\n *\n * @param params - The unvalidated params object from the method request.\n * @returns The validated method parameter object.\n */\nexport function getValidatedParams(params: unknown): NotifyParams {\n if (!isObject(params)) {\n throw rpcErrors.invalidParams({\n message: 'Expected params to be a single object.',\n });\n }\n\n const { type, message } = params;\n\n if (\n !type ||\n typeof type !== 'string' ||\n !Object.values(NotificationType).includes(type as NotificationType)\n ) {\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n\n const isNotString = !message || typeof message !== 'string';\n // Set to the max message length on a Mac notification for now.\n if (\n type === NotificationType.Native &&\n (isNotString || message.length >= 50)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 50 characters long.',\n });\n }\n\n if (\n type === NotificationType.InApp &&\n (isNotString || message.length >= 500)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 500 characters long.',\n });\n }\n\n return params as NotificationArgs;\n}\n"]}
1
+ {"version":3,"file":"notify.mjs","sourceRoot":"","sources":["../../src/restricted/notify.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PermissionSpecificationBuilder,\n RestrictedMethodOptions,\n ValidPermissionSpecification,\n} from '@metamask/permission-controller';\nimport { PermissionType, SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport { enumValue, NotificationType, union } from '@metamask/snaps-sdk';\nimport type {\n NotifyParams,\n NotifyResult,\n NotificationComponent,\n} from '@metamask/snaps-sdk';\nimport { NotificationComponentsStruct } from '@metamask/snaps-sdk/jsx';\nimport {\n createUnion,\n validateLink,\n validateTextLinks,\n type Snap,\n} from '@metamask/snaps-utils';\nimport type { InferMatching } from '@metamask/snaps-utils';\nimport { object, string } from '@metamask/superstruct';\nimport type { NonEmptyArray } from '@metamask/utils';\nimport { hasProperty, isObject } from '@metamask/utils';\n\nimport { type MethodHooksObject } from '../utils';\n\nconst methodName = 'snap_notify';\n\nconst NativeNotificationStruct = object({\n type: enumValue(NotificationType.Native),\n message: string(),\n});\n\nconst InAppNotificationStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n});\n\nconst InAppNotificationWithDetailsStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n content: NotificationComponentsStruct,\n title: string(),\n});\n\nconst InAppNotificationWithDetailsAndFooterStruct = object({\n type: enumValue(NotificationType.InApp),\n message: string(),\n content: NotificationComponentsStruct,\n title: string(),\n footerLink: object({\n href: string(),\n text: string(),\n }),\n});\n\nconst NotificationParametersStruct = union([\n InAppNotificationStruct,\n InAppNotificationWithDetailsStruct,\n InAppNotificationWithDetailsAndFooterStruct,\n NativeNotificationStruct,\n]);\n\nexport type NotificationParameters = InferMatching<\n typeof NotificationParametersStruct,\n NotifyParams\n>;\n\nexport type NotifyMethodHooks = {\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showNativeNotification: (\n snapId: string,\n args: NotificationParameters,\n ) => Promise<null>;\n\n /**\n * @param snapId - The ID of the Snap that created the notification.\n * @param args - The notification arguments.\n */\n showInAppNotification: (\n snapId: string,\n args: NotificationParameters,\n ) => Promise<null>;\n\n isOnPhishingList: (url: string) => boolean;\n\n maybeUpdatePhishingList: () => Promise<void>;\n\n createInterface: (\n origin: string,\n content: NotificationComponent,\n ) => Promise<string>;\n getSnap: (snapId: string) => Snap | undefined;\n};\n\ntype SpecificationBuilderOptions = {\n allowedCaveats?: Readonly<NonEmptyArray<string>> | null;\n methodHooks: NotifyMethodHooks;\n};\n\ntype Specification = ValidPermissionSpecification<{\n permissionType: PermissionType.RestrictedMethod;\n targetName: typeof methodName;\n methodImplementation: ReturnType<typeof getImplementation>;\n allowedCaveats: Readonly<NonEmptyArray<string>> | null;\n}>;\n\n/**\n * The specification builder for the `snap_notify` permission.\n * `snap_notify` allows snaps to send multiple types of notifications to its users.\n *\n * @param options - The specification builder options.\n * @param options.allowedCaveats - The optional allowed caveats for the permission.\n * @param options.methodHooks - The RPC method hooks needed by the method implementation.\n * @returns The specification for the `snap_notify` permission.\n */\nexport const specificationBuilder: PermissionSpecificationBuilder<\n PermissionType.RestrictedMethod,\n SpecificationBuilderOptions,\n Specification\n> = ({ allowedCaveats = null, methodHooks }: SpecificationBuilderOptions) => {\n return {\n permissionType: PermissionType.RestrictedMethod,\n targetName: methodName,\n allowedCaveats,\n methodImplementation: getImplementation(methodHooks),\n subjectTypes: [SubjectType.Snap],\n };\n};\n\nconst methodHooks: MethodHooksObject<NotifyMethodHooks> = {\n showNativeNotification: true,\n showInAppNotification: true,\n isOnPhishingList: true,\n maybeUpdatePhishingList: true,\n createInterface: true,\n getSnap: true,\n};\n\nexport const notifyBuilder = Object.freeze({\n targetName: methodName,\n specificationBuilder,\n methodHooks,\n} as const);\n\n/**\n * Builds the method implementation for `snap_notify`.\n *\n * @param hooks - The RPC method hooks.\n * @param hooks.showNativeNotification - A function that shows a native browser notification.\n * @param hooks.showInAppNotification - A function that shows a notification in the MetaMask UI.\n * @param hooks.isOnPhishingList - A function that checks for links against the phishing list.\n * @param hooks.maybeUpdatePhishingList - A function that updates the phishing list if needed.\n * @param hooks.createInterface - A function that creates the interface in SnapInterfaceController.\n * @param hooks.getSnap - A function that checks if a snap is installed.\n * @returns The method implementation which returns `null` on success.\n * @throws If the params are invalid.\n */\nexport function getImplementation({\n showNativeNotification,\n showInAppNotification,\n isOnPhishingList,\n maybeUpdatePhishingList,\n createInterface,\n getSnap,\n}: NotifyMethodHooks) {\n return async function implementation(\n args: RestrictedMethodOptions<NotifyParams>,\n ): Promise<NotifyResult> {\n const {\n params,\n context: { origin },\n } = args;\n\n await maybeUpdatePhishingList();\n\n const validatedParams = getValidatedParams(\n params,\n isOnPhishingList,\n getSnap,\n );\n\n let id;\n if (hasProperty(validatedParams, 'content')) {\n id = await createInterface(\n origin,\n validatedParams.content as NotificationComponent,\n );\n validatedParams.content = id;\n }\n\n switch (validatedParams.type) {\n case NotificationType.Native:\n return await showNativeNotification(origin, validatedParams);\n case NotificationType.InApp:\n return await showInAppNotification(origin, validatedParams);\n default:\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n };\n}\n\n/**\n * Validates the notify method `params` and returns them cast to the correct\n * type. Throws if validation fails.\n *\n * @param params - The unvalidated params object from the method request.\n * @param isOnPhishingList - The function that checks for links against the phishing list.\n * @param getSnap - A function that checks if a snap is installed.\n * @returns The validated method parameter object.\n * @throws If the params are invalid.\n */\nexport function getValidatedParams(\n params: unknown,\n isOnPhishingList: NotifyMethodHooks['isOnPhishingList'],\n getSnap: NotifyMethodHooks['getSnap'],\n): NotifyParams {\n if (!isObject(params)) {\n throw rpcErrors.invalidParams({\n message: 'Expected params to be a single object.',\n });\n }\n\n const { type, message } = params;\n\n if (\n !type ||\n typeof type !== 'string' ||\n !Object.values(NotificationType).includes(type as NotificationType)\n ) {\n throw rpcErrors.invalidParams({\n message: 'Must specify a valid notification \"type\".',\n });\n }\n\n const isNotString = !message || typeof message !== 'string';\n // Set to the max message length on a Mac notification for now.\n if (\n type === NotificationType.Native &&\n (isNotString || message.length >= 50)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 50 characters long.',\n });\n }\n\n if (\n type === NotificationType.InApp &&\n (isNotString || message.length >= 500)\n ) {\n throw rpcErrors.invalidParams({\n message:\n 'Must specify a non-empty string \"message\" less than 500 characters long.',\n });\n }\n\n try {\n const validatedParams = createUnion(\n params,\n NotificationParametersStruct,\n 'type',\n );\n\n validateTextLinks(validatedParams.message, isOnPhishingList, getSnap);\n\n if (hasProperty(validatedParams, 'footerLink')) {\n validateTextLinks(\n validatedParams.footerLink.text,\n isOnPhishingList,\n getSnap,\n );\n validateLink(validatedParams.footerLink.href, isOnPhishingList, getSnap);\n }\n\n return validatedParams;\n } catch (error) {\n throw rpcErrors.invalidParams({\n message: `Invalid params: ${error.message}`,\n });\n }\n}\n"]}
package/package.json CHANGED
@@ -1,11 +1,21 @@
1
1
  {
2
2
  "name": "@metamask/snaps-rpc-methods",
3
- "version": "11.1.1",
4
- "description": "MetaMask Snaps JSON-RPC method implementations.",
3
+ "version": "11.2.0",
4
+ "description": "MetaMask Snaps JSON-RPC method implementations",
5
+ "keywords": [
6
+ "MetaMask",
7
+ "Snaps",
8
+ "Ethereum"
9
+ ],
10
+ "homepage": "https://github.com/MetaMask/snaps/tree/main/packages/snaps-rpc-methods#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/MetaMask/snaps/issues"
13
+ },
5
14
  "repository": {
6
15
  "type": "git",
7
16
  "url": "https://github.com/MetaMask/snaps.git"
8
17
  },
18
+ "license": "SEE LICENSE IN LICENSE",
9
19
  "sideEffects": false,
10
20
  "exports": {
11
21
  ".": {
@@ -27,25 +37,29 @@
27
37
  "dist"
28
38
  ],
29
39
  "scripts": {
30
- "test": "jest && yarn posttest",
31
- "posttest": "jest-it-up --margin 0.25",
32
- "test:ci": "yarn test",
40
+ "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references",
41
+ "changelog:update": "../../scripts/update-changelog.sh @metamask/snaps-rpc-methods",
42
+ "changelog:validate": "../../scripts/validate-changelog.sh @metamask/snaps-rpc-methods",
43
+ "lint": "yarn lint:eslint && yarn lint:misc --check && yarn changelog:validate && yarn lint:dependencies",
44
+ "lint:ci": "yarn lint",
45
+ "lint:dependencies": "depcheck",
33
46
  "lint:eslint": "eslint . --cache --ext js,ts,jsx,tsx",
34
- "lint:misc": "prettier --no-error-on-unmatched-pattern --loglevel warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" --ignore-path ../../.gitignore",
35
- "lint": "yarn lint:eslint && yarn lint:misc --check && yarn lint:changelog && yarn lint:dependencies",
36
47
  "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write",
37
- "lint:changelog": "../../scripts/validate-changelog.sh @metamask/snaps-rpc-methods",
38
- "build": "ts-bridge --project tsconfig.build.json --verbose --no-references",
48
+ "lint:misc": "prettier --no-error-on-unmatched-pattern --loglevel warn \"**/*.json\" \"**/*.md\" \"**/*.html\" \"!CHANGELOG.md\" --ignore-path ../../.gitignore",
39
49
  "publish:preview": "yarn npm publish --tag preview",
40
- "lint:ci": "yarn lint",
41
- "lint:dependencies": "depcheck"
50
+ "since-latest-release": "../../scripts/since-latest-release.sh",
51
+ "test": "jest --reporters=jest-silent-reporter",
52
+ "test:clean": "jest --clearCache",
53
+ "test:post": "jest-it-up",
54
+ "test:verbose": "jest --verbose",
55
+ "test:watch": "jest --watch"
42
56
  },
43
57
  "dependencies": {
44
58
  "@metamask/key-tree": "^9.1.2",
45
59
  "@metamask/permission-controller": "^11.0.0",
46
60
  "@metamask/rpc-errors": "^6.3.1",
47
- "@metamask/snaps-sdk": "^6.5.0",
48
- "@metamask/snaps-utils": "^8.1.1",
61
+ "@metamask/snaps-sdk": "^6.6.0",
62
+ "@metamask/snaps-utils": "^8.2.0",
49
63
  "@metamask/superstruct": "^3.1.0",
50
64
  "@metamask/utils": "^9.2.1",
51
65
  "@noble/hashes": "^1.3.1"
@@ -76,8 +90,9 @@
76
90
  "eslint-plugin-promise": "^6.1.1",
77
91
  "jest": "^29.0.2",
78
92
  "jest-it-up": "^2.0.0",
79
- "prettier": "^2.7.1",
80
- "prettier-plugin-packagejson": "^2.2.11",
93
+ "jest-silent-reporter": "^0.6.0",
94
+ "prettier": "^2.8.8",
95
+ "prettier-plugin-packagejson": "^2.5.2",
81
96
  "typescript": "~5.3.3"
82
97
  },
83
98
  "engines": {