@metamask/snaps-controllers 9.12.0 → 9.14.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 +21 -1
- package/dist/interface/SnapInterfaceController.cjs +35 -3
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +36 -2
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +36 -2
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +36 -4
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +17 -6
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +7 -2
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +7 -2
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +17 -6
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/location/http.cjs +4 -14
- package/dist/snaps/location/http.cjs.map +1 -1
- package/dist/snaps/location/http.d.cts.map +1 -1
- package/dist/snaps/location/http.d.mts.map +1 -1
- package/dist/snaps/location/http.mjs +4 -14
- package/dist/snaps/location/http.mjs.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [9.14.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Emit `snapInstalled` and `snapUpdated` events for preinstalled Snaps ([#2900](https://github.com/MetaMask/snaps/pull/2900))
|
|
15
|
+
- This indirectly makes preinstalled Snaps trigger cronjobs and lifecycle hooks more reliably.
|
|
16
|
+
|
|
17
|
+
## [9.13.0]
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Add interface persistence ([#2856](https://github.com/MetaMask/snaps/pull/2856))
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Use `arrayBuffer` for fetching local Snaps ([#2884](https://github.com/MetaMask/snaps/pull/2884))
|
|
26
|
+
- This fixes some incompatiblities with React Native.
|
|
27
|
+
|
|
10
28
|
## [9.12.0]
|
|
11
29
|
|
|
12
30
|
### Added
|
|
@@ -556,7 +574,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
556
574
|
- The version of the package no longer needs to match the version of all other
|
|
557
575
|
MetaMask Snaps packages.
|
|
558
576
|
|
|
559
|
-
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.
|
|
577
|
+
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.14.0...HEAD
|
|
578
|
+
[9.14.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.13.0...@metamask/snaps-controllers@9.14.0
|
|
579
|
+
[9.13.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.12.0...@metamask/snaps-controllers@9.13.0
|
|
560
580
|
[9.12.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.11.1...@metamask/snaps-controllers@9.12.0
|
|
561
581
|
[9.11.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.11.0...@metamask/snaps-controllers@9.11.1
|
|
562
582
|
[9.11.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@9.10.0...@metamask/snaps-controllers@9.11.0
|
|
@@ -4,10 +4,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
4
4
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
5
5
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
6
6
|
};
|
|
7
|
-
var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_triggerPhishingListUpdate, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_validateContent;
|
|
7
|
+
var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_triggerPhishingListUpdate, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_validateContent, _SnapInterfaceController_onNotificationsListUpdated;
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.SnapInterfaceController = void 0;
|
|
10
10
|
const base_controller_1 = require("@metamask/base-controller");
|
|
11
|
+
const snaps_sdk_1 = require("@metamask/snaps-sdk");
|
|
11
12
|
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
12
13
|
const utils_1 = require("@metamask/utils");
|
|
13
14
|
const immer_1 = require("immer");
|
|
@@ -23,12 +24,26 @@ class SnapInterfaceController extends base_controller_1.BaseController {
|
|
|
23
24
|
super({
|
|
24
25
|
messenger,
|
|
25
26
|
metadata: {
|
|
26
|
-
interfaces: {
|
|
27
|
+
interfaces: {
|
|
28
|
+
persist: (interfaces) => {
|
|
29
|
+
return Object.entries(interfaces).reduce((persistedInterfaces, [id, snapInterface]) => {
|
|
30
|
+
switch (snapInterface.contentType) {
|
|
31
|
+
case snaps_sdk_1.ContentType.Notification:
|
|
32
|
+
persistedInterfaces[id] = snapInterface;
|
|
33
|
+
return persistedInterfaces;
|
|
34
|
+
default:
|
|
35
|
+
return persistedInterfaces;
|
|
36
|
+
}
|
|
37
|
+
}, {});
|
|
38
|
+
},
|
|
39
|
+
anonymous: false,
|
|
40
|
+
},
|
|
27
41
|
},
|
|
28
42
|
name: controllerName,
|
|
29
43
|
state: { interfaces: {}, ...state },
|
|
30
44
|
});
|
|
31
45
|
_SnapInterfaceController_instances.add(this);
|
|
46
|
+
this.messagingSystem.subscribe('NotificationServicesController:notificationsListUpdated', __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_onNotificationsListUpdated).bind(this));
|
|
32
47
|
__classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_registerMessageHandlers).call(this);
|
|
33
48
|
}
|
|
34
49
|
/**
|
|
@@ -37,9 +52,10 @@ class SnapInterfaceController extends base_controller_1.BaseController {
|
|
|
37
52
|
* @param snapId - The snap id that created the interface.
|
|
38
53
|
* @param content - The interface content.
|
|
39
54
|
* @param context - An optional interface context object.
|
|
55
|
+
* @param contentType - The type of content.
|
|
40
56
|
* @returns The newly interface id.
|
|
41
57
|
*/
|
|
42
|
-
async createInterface(snapId, content, context) {
|
|
58
|
+
async createInterface(snapId, content, context, contentType) {
|
|
43
59
|
const element = (0, utils_2.getJsxInterface)(content);
|
|
44
60
|
await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateContent).call(this, element);
|
|
45
61
|
(0, utils_2.validateInterfaceContext)(context);
|
|
@@ -53,6 +69,7 @@ class SnapInterfaceController extends base_controller_1.BaseController {
|
|
|
53
69
|
content: (0, immer_1.castDraft)(element),
|
|
54
70
|
state: componentState,
|
|
55
71
|
context: context ?? null,
|
|
72
|
+
contentType: contentType ?? null,
|
|
56
73
|
};
|
|
57
74
|
});
|
|
58
75
|
return id;
|
|
@@ -177,5 +194,20 @@ async function _SnapInterfaceController_validateContent(element) {
|
|
|
177
194
|
(0, utils_1.assert)(size <= MAX_UI_CONTENT_SIZE, `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`);
|
|
178
195
|
await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_triggerPhishingListUpdate).call(this);
|
|
179
196
|
(0, snaps_utils_1.validateJsxLinks)(element, __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_checkPhishingList).bind(this), (id) => this.messagingSystem.call('SnapController:get', id));
|
|
197
|
+
}, _SnapInterfaceController_onNotificationsListUpdated = function _SnapInterfaceController_onNotificationsListUpdated(notificationsList) {
|
|
198
|
+
const snapNotificationsWithInterface = notificationsList.filter((notification) => {
|
|
199
|
+
return (notification.type === 'snap' &&
|
|
200
|
+
(0, utils_1.hasProperty)(notification.data, 'detailedView'));
|
|
201
|
+
});
|
|
202
|
+
const interfaceIdSet = new Set(snapNotificationsWithInterface.map((notification) => notification
|
|
203
|
+
.data.detailedView.interfaceId));
|
|
204
|
+
this.update((state) => {
|
|
205
|
+
Object.entries(state.interfaces).forEach(([id, snapInterface]) => {
|
|
206
|
+
if (snapInterface.contentType === snaps_sdk_1.ContentType.Notification &&
|
|
207
|
+
!interfaceIdSet.has(id)) {
|
|
208
|
+
delete state.interfaces[id];
|
|
209
|
+
}
|
|
210
|
+
});
|
|
211
|
+
});
|
|
180
212
|
};
|
|
181
213
|
//# sourceMappingURL=SnapInterfaceController.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MaybeUpdateState,\n TestOrigin,\n} from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n} from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport { getJsonSizeUnsafe, validateJsxLinks } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { assert } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport type { GetSnap } from '../snaps';\nimport {\n constructState,\n getJsxInterface,\n validateInterfaceContext,\n} from './utils';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | MaybeUpdateState\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\nexport type SnapInterfaceControllerEvents =\n SnapInterfaceControllerStateChangeEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: { persist: false, anonymous: false },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element);\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element);\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Trigger a Phishing list update if needed.\n */\n async #triggerPhishingListUpdate() {\n await this.messagingSystem.call('PhishingController:maybeUpdateState');\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n await this.#triggerPhishingListUpdate();\n validateJsxLinks(\n element,\n this.#checkPhishingList.bind(this),\n (id: string) => this.messagingSystem.call('SnapController:get', id),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MaybeUpdateState,\n TestOrigin,\n} from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport { getJsonSizeUnsafe, validateJsxLinks } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { assert, hasProperty } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport type { GetSnap } from '../snaps';\nimport {\n constructState,\n getJsxInterface,\n validateInterfaceContext,\n} from './utils';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | MaybeUpdateState\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element);\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element);\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Trigger a Phishing list update if needed.\n */\n async #triggerPhishingListUpdate() {\n await this.messagingSystem.call('PhishingController:maybeUpdateState');\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n await this.#triggerPhishingListUpdate();\n validateJsxLinks(\n element,\n this.#checkPhishingList.bind(this),\n (id: string) => this.messagingSystem.call('SnapController:get', id),\n );\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import type { RestrictedControllerMessenger, ControllerGetStateAction, Controlle
|
|
|
3
3
|
import { BaseController } from "@metamask/base-controller";
|
|
4
4
|
import type { MaybeUpdateState, TestOrigin } from "@metamask/phishing-controller";
|
|
5
5
|
import type { InterfaceState, SnapId, ComponentOrElement, InterfaceContext } from "@metamask/snaps-sdk";
|
|
6
|
+
import { ContentType } from "@metamask/snaps-sdk";
|
|
6
7
|
import type { JSXElement } from "@metamask/snaps-sdk/jsx";
|
|
7
8
|
import type { Json } from "@metamask/utils";
|
|
8
9
|
import type { GetSnap } from "../snaps/index.cjs";
|
|
@@ -35,13 +36,45 @@ export type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<typ
|
|
|
35
36
|
export type SnapInterfaceControllerAllowedActions = TestOrigin | MaybeUpdateState | HasApprovalRequest | AcceptRequest | GetSnap;
|
|
36
37
|
export type SnapInterfaceControllerActions = CreateInterface | GetInterface | UpdateInterface | DeleteInterface | UpdateInterfaceState | ResolveInterface | SnapInterfaceControllerGetStateAction;
|
|
37
38
|
export type SnapInterfaceControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, SnapInterfaceControllerState>;
|
|
38
|
-
|
|
39
|
+
type OtherNotification = {
|
|
40
|
+
type: string;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
};
|
|
43
|
+
export type ExpandedView = {
|
|
44
|
+
title: string;
|
|
45
|
+
interfaceId: string;
|
|
46
|
+
footerLink?: {
|
|
47
|
+
href: string;
|
|
48
|
+
text: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
type NormalSnapNotificationData = {
|
|
52
|
+
message: string;
|
|
53
|
+
origin: string;
|
|
54
|
+
};
|
|
55
|
+
type ExpandedSnapNotificationData = {
|
|
56
|
+
message: string;
|
|
57
|
+
origin: string;
|
|
58
|
+
detailedView: ExpandedView;
|
|
59
|
+
};
|
|
60
|
+
type SnapNotification = {
|
|
61
|
+
type: 'snap';
|
|
62
|
+
data: NormalSnapNotificationData | ExpandedSnapNotificationData;
|
|
63
|
+
readDate: string | null;
|
|
64
|
+
};
|
|
65
|
+
type Notification = OtherNotification | SnapNotification;
|
|
66
|
+
type NotificationListUpdatedEvent = {
|
|
67
|
+
type: 'NotificationServicesController:notificationsListUpdated';
|
|
68
|
+
payload: [Notification[]];
|
|
69
|
+
};
|
|
70
|
+
export type SnapInterfaceControllerEvents = SnapInterfaceControllerStateChangeEvent | NotificationListUpdatedEvent;
|
|
39
71
|
export type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<typeof controllerName, SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions, SnapInterfaceControllerEvents, SnapInterfaceControllerAllowedActions['type'], SnapInterfaceControllerEvents['type']>;
|
|
40
72
|
export type StoredInterface = {
|
|
41
73
|
snapId: SnapId;
|
|
42
74
|
content: JSXElement;
|
|
43
75
|
state: InterfaceState;
|
|
44
76
|
context: InterfaceContext | null;
|
|
77
|
+
contentType: ContentType | null;
|
|
45
78
|
};
|
|
46
79
|
export type SnapInterfaceControllerState = {
|
|
47
80
|
interfaces: Record<string, StoredInterface>;
|
|
@@ -62,9 +95,10 @@ export declare class SnapInterfaceController extends BaseController<typeof contr
|
|
|
62
95
|
* @param snapId - The snap id that created the interface.
|
|
63
96
|
* @param content - The interface content.
|
|
64
97
|
* @param context - An optional interface context object.
|
|
98
|
+
* @param contentType - The type of content.
|
|
65
99
|
* @returns The newly interface id.
|
|
66
100
|
*/
|
|
67
|
-
createInterface(snapId: SnapId, content: ComponentOrElement, context?: InterfaceContext): Promise<string>;
|
|
101
|
+
createInterface(snapId: SnapId, content: ComponentOrElement, context?: InterfaceContext, contentType?: ContentType): Promise<string>;
|
|
68
102
|
/**
|
|
69
103
|
* Get the data of a given interface id.
|
|
70
104
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapInterfaceController.d.cts","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EACnB,sCAAsC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,sCAAsC;AACvC,OAAO,KAAK,EACV,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAgC;AAE1D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAK5C,OAAO,KAAK,EAAE,OAAO,EAAE,2BAAiB;AASxC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,GAAG,OAAO,cAAc,eAAe,CAAC;IAC9C,OAAO,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,uBAAuB,CAAC,sBAAsB,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,GAAG,OAAO,cAAc,mBAAmB,CAAC;IAClD,OAAO,EAAE,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAC7C,UAAU,GACV,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,MAAM,8BAA8B,GACtC,eAAe,GACf,YAAY,GACZ,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,gBAAgB,GAChB,qCAAqC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ,MAAM,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"SnapInterfaceController.d.cts","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EACnB,sCAAsC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,sCAAsC;AACvC,OAAO,KAAK,EACV,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAC7B,OAAO,EAAE,WAAW,EAAE,4BAA4B;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAgC;AAE1D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAK5C,OAAO,KAAK,EAAE,OAAO,EAAE,2BAAiB;AASxC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,GAAG,OAAO,cAAc,eAAe,CAAC;IAC9C,OAAO,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,uBAAuB,CAAC,sBAAsB,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,GAAG,OAAO,cAAc,mBAAmB,CAAC;IAClD,OAAO,EAAE,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAC7C,UAAU,GACV,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,MAAM,8BAA8B,GACtC,eAAe,GACf,YAAY,GACZ,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,gBAAgB,GAChB,qCAAqC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ,KAAK,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAElE,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C,CAAC;AAEF,KAAK,0BAA0B,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtE,KAAK,4BAA4B,GAAG;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,0BAA0B,GAAG,4BAA4B,CAAC;IAChE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB,CAAC;AAEF,KAAK,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEzD,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,yDAAyD,CAAC;IAChE,OAAO,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC;CAC3B,CAAC;AAEF,MAAM,MAAM,6BAA6B,GACrC,uCAAuC,GACvC,4BAA4B,CAAC;AAEjC,MAAM,MAAM,gCAAgC,GAAG,6BAA6B,CAC1E,OAAO,cAAc,EACrB,8BAA8B,GAAG,qCAAqC,EACtE,6BAA6B,EAC7B,qCAAqC,CAAC,MAAM,CAAC,EAC7C,6BAA6B,CAAC,MAAM,CAAC,CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC;IACpB,KAAK,EAAE,cAAc,CAAC;IACtB,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACjC,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC7C,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,SAAS,EAAE,gCAAgC,CAAC;IAC5C,KAAK,CAAC,EAAE,4BAA4B,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,cAAc,CACzD,OAAO,cAAc,EACrB,4BAA4B,EAC5B,gCAAgC,CACjC;;gBACa,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,2BAA2B;IAqE7D;;;;;;;;OAQG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,EAC1B,WAAW,CAAC,EAAE,WAAW;IAwB3B;;;;;;OAMG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAMvC;;;;;;;OAOG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,gBAAgB;IAmB5B;;;;OAIG;IACH,eAAe,CAAC,EAAE,EAAE,MAAM;IAM1B;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc;IAMtD;;;;;;;OAOG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI;CA2I/D"}
|
|
@@ -3,6 +3,7 @@ import type { RestrictedControllerMessenger, ControllerGetStateAction, Controlle
|
|
|
3
3
|
import { BaseController } from "@metamask/base-controller";
|
|
4
4
|
import type { MaybeUpdateState, TestOrigin } from "@metamask/phishing-controller";
|
|
5
5
|
import type { InterfaceState, SnapId, ComponentOrElement, InterfaceContext } from "@metamask/snaps-sdk";
|
|
6
|
+
import { ContentType } from "@metamask/snaps-sdk";
|
|
6
7
|
import type { JSXElement } from "@metamask/snaps-sdk/jsx";
|
|
7
8
|
import type { Json } from "@metamask/utils";
|
|
8
9
|
import type { GetSnap } from "../snaps/index.mjs";
|
|
@@ -35,13 +36,45 @@ export type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<typ
|
|
|
35
36
|
export type SnapInterfaceControllerAllowedActions = TestOrigin | MaybeUpdateState | HasApprovalRequest | AcceptRequest | GetSnap;
|
|
36
37
|
export type SnapInterfaceControllerActions = CreateInterface | GetInterface | UpdateInterface | DeleteInterface | UpdateInterfaceState | ResolveInterface | SnapInterfaceControllerGetStateAction;
|
|
37
38
|
export type SnapInterfaceControllerStateChangeEvent = ControllerStateChangeEvent<typeof controllerName, SnapInterfaceControllerState>;
|
|
38
|
-
|
|
39
|
+
type OtherNotification = {
|
|
40
|
+
type: string;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
};
|
|
43
|
+
export type ExpandedView = {
|
|
44
|
+
title: string;
|
|
45
|
+
interfaceId: string;
|
|
46
|
+
footerLink?: {
|
|
47
|
+
href: string;
|
|
48
|
+
text: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
type NormalSnapNotificationData = {
|
|
52
|
+
message: string;
|
|
53
|
+
origin: string;
|
|
54
|
+
};
|
|
55
|
+
type ExpandedSnapNotificationData = {
|
|
56
|
+
message: string;
|
|
57
|
+
origin: string;
|
|
58
|
+
detailedView: ExpandedView;
|
|
59
|
+
};
|
|
60
|
+
type SnapNotification = {
|
|
61
|
+
type: 'snap';
|
|
62
|
+
data: NormalSnapNotificationData | ExpandedSnapNotificationData;
|
|
63
|
+
readDate: string | null;
|
|
64
|
+
};
|
|
65
|
+
type Notification = OtherNotification | SnapNotification;
|
|
66
|
+
type NotificationListUpdatedEvent = {
|
|
67
|
+
type: 'NotificationServicesController:notificationsListUpdated';
|
|
68
|
+
payload: [Notification[]];
|
|
69
|
+
};
|
|
70
|
+
export type SnapInterfaceControllerEvents = SnapInterfaceControllerStateChangeEvent | NotificationListUpdatedEvent;
|
|
39
71
|
export type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<typeof controllerName, SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions, SnapInterfaceControllerEvents, SnapInterfaceControllerAllowedActions['type'], SnapInterfaceControllerEvents['type']>;
|
|
40
72
|
export type StoredInterface = {
|
|
41
73
|
snapId: SnapId;
|
|
42
74
|
content: JSXElement;
|
|
43
75
|
state: InterfaceState;
|
|
44
76
|
context: InterfaceContext | null;
|
|
77
|
+
contentType: ContentType | null;
|
|
45
78
|
};
|
|
46
79
|
export type SnapInterfaceControllerState = {
|
|
47
80
|
interfaces: Record<string, StoredInterface>;
|
|
@@ -62,9 +95,10 @@ export declare class SnapInterfaceController extends BaseController<typeof contr
|
|
|
62
95
|
* @param snapId - The snap id that created the interface.
|
|
63
96
|
* @param content - The interface content.
|
|
64
97
|
* @param context - An optional interface context object.
|
|
98
|
+
* @param contentType - The type of content.
|
|
65
99
|
* @returns The newly interface id.
|
|
66
100
|
*/
|
|
67
|
-
createInterface(snapId: SnapId, content: ComponentOrElement, context?: InterfaceContext): Promise<string>;
|
|
101
|
+
createInterface(snapId: SnapId, content: ComponentOrElement, context?: InterfaceContext, contentType?: ContentType): Promise<string>;
|
|
68
102
|
/**
|
|
69
103
|
* Get the data of a given interface id.
|
|
70
104
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapInterfaceController.d.mts","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,kBAAkB,EACnB,sCAAsC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,wBAAwB,EACxB,0BAA0B,EAC3B,kCAAkC;AACnC,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAC3D,OAAO,KAAK,EACV,gBAAgB,EAChB,UAAU,EACX,sCAAsC;AACvC,OAAO,KAAK,EACV,cAAc,EACd,MAAM,EACN,kBAAkB,EAClB,gBAAgB,EACjB,4BAA4B;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,gCAAgC;AAE1D,OAAO,KAAK,EAAE,IAAI,EAAE,wBAAwB;AAK5C,OAAO,KAAK,EAAE,OAAO,EAAE,2BAAiB;AASxC,QAAA,MAAM,cAAc,4BAA4B,CAAC;AAEjD,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,GAAG,OAAO,cAAc,eAAe,CAAC;IAC9C,OAAO,EAAE,uBAAuB,CAAC,cAAc,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,GAAG,OAAO,cAAc,kBAAkB,CAAC;IACjD,OAAO,EAAE,uBAAuB,CAAC,iBAAiB,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,GAAG,OAAO,cAAc,uBAAuB,CAAC;IACtD,OAAO,EAAE,uBAAuB,CAAC,sBAAsB,CAAC,CAAC;CAC1D,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,GAAG,OAAO,cAAc,mBAAmB,CAAC;IAClD,OAAO,EAAE,uBAAuB,CAAC,kBAAkB,CAAC,CAAC;CACtD,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG,wBAAwB,CAC1E,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAC7C,UAAU,GACV,gBAAgB,GAChB,kBAAkB,GAClB,aAAa,GACb,OAAO,CAAC;AAEZ,MAAM,MAAM,8BAA8B,GACtC,eAAe,GACf,YAAY,GACZ,eAAe,GACf,eAAe,GACf,oBAAoB,GACpB,gBAAgB,GAChB,qCAAqC,CAAC;AAE1C,MAAM,MAAM,uCAAuC,GACjD,0BAA0B,CACxB,OAAO,cAAc,EACrB,4BAA4B,CAC7B,CAAC;AAEJ,MAAM,MAAM,6BAA6B,
|
|
1
|
+
{"version":3,"file":"SnapInterfaceController.d.mts","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,10 +3,11 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
3
3
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
4
4
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
5
5
|
};
|
|
6
|
-
var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_triggerPhishingListUpdate, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_validateContent;
|
|
6
|
+
var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_triggerPhishingListUpdate, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_validateContent, _SnapInterfaceController_onNotificationsListUpdated;
|
|
7
7
|
import { BaseController } from "@metamask/base-controller";
|
|
8
|
+
import { ContentType } from "@metamask/snaps-sdk";
|
|
8
9
|
import { getJsonSizeUnsafe, validateJsxLinks } from "@metamask/snaps-utils";
|
|
9
|
-
import { assert } from "@metamask/utils";
|
|
10
|
+
import { assert, hasProperty } from "@metamask/utils";
|
|
10
11
|
import { castDraft } from "immer";
|
|
11
12
|
import { nanoid } from "nanoid";
|
|
12
13
|
import { constructState, getJsxInterface, validateInterfaceContext } from "./utils.mjs";
|
|
@@ -20,12 +21,26 @@ export class SnapInterfaceController extends BaseController {
|
|
|
20
21
|
super({
|
|
21
22
|
messenger,
|
|
22
23
|
metadata: {
|
|
23
|
-
interfaces: {
|
|
24
|
+
interfaces: {
|
|
25
|
+
persist: (interfaces) => {
|
|
26
|
+
return Object.entries(interfaces).reduce((persistedInterfaces, [id, snapInterface]) => {
|
|
27
|
+
switch (snapInterface.contentType) {
|
|
28
|
+
case ContentType.Notification:
|
|
29
|
+
persistedInterfaces[id] = snapInterface;
|
|
30
|
+
return persistedInterfaces;
|
|
31
|
+
default:
|
|
32
|
+
return persistedInterfaces;
|
|
33
|
+
}
|
|
34
|
+
}, {});
|
|
35
|
+
},
|
|
36
|
+
anonymous: false,
|
|
37
|
+
},
|
|
24
38
|
},
|
|
25
39
|
name: controllerName,
|
|
26
40
|
state: { interfaces: {}, ...state },
|
|
27
41
|
});
|
|
28
42
|
_SnapInterfaceController_instances.add(this);
|
|
43
|
+
this.messagingSystem.subscribe('NotificationServicesController:notificationsListUpdated', __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_onNotificationsListUpdated).bind(this));
|
|
29
44
|
__classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_registerMessageHandlers).call(this);
|
|
30
45
|
}
|
|
31
46
|
/**
|
|
@@ -34,9 +49,10 @@ export class SnapInterfaceController extends BaseController {
|
|
|
34
49
|
* @param snapId - The snap id that created the interface.
|
|
35
50
|
* @param content - The interface content.
|
|
36
51
|
* @param context - An optional interface context object.
|
|
52
|
+
* @param contentType - The type of content.
|
|
37
53
|
* @returns The newly interface id.
|
|
38
54
|
*/
|
|
39
|
-
async createInterface(snapId, content, context) {
|
|
55
|
+
async createInterface(snapId, content, context, contentType) {
|
|
40
56
|
const element = getJsxInterface(content);
|
|
41
57
|
await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_validateContent).call(this, element);
|
|
42
58
|
validateInterfaceContext(context);
|
|
@@ -50,6 +66,7 @@ export class SnapInterfaceController extends BaseController {
|
|
|
50
66
|
content: castDraft(element),
|
|
51
67
|
state: componentState,
|
|
52
68
|
context: context ?? null,
|
|
69
|
+
contentType: contentType ?? null,
|
|
53
70
|
};
|
|
54
71
|
});
|
|
55
72
|
return id;
|
|
@@ -173,5 +190,20 @@ async function _SnapInterfaceController_validateContent(element) {
|
|
|
173
190
|
assert(size <= MAX_UI_CONTENT_SIZE, `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`);
|
|
174
191
|
await __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_triggerPhishingListUpdate).call(this);
|
|
175
192
|
validateJsxLinks(element, __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_checkPhishingList).bind(this), (id) => this.messagingSystem.call('SnapController:get', id));
|
|
193
|
+
}, _SnapInterfaceController_onNotificationsListUpdated = function _SnapInterfaceController_onNotificationsListUpdated(notificationsList) {
|
|
194
|
+
const snapNotificationsWithInterface = notificationsList.filter((notification) => {
|
|
195
|
+
return (notification.type === 'snap' &&
|
|
196
|
+
hasProperty(notification.data, 'detailedView'));
|
|
197
|
+
});
|
|
198
|
+
const interfaceIdSet = new Set(snapNotificationsWithInterface.map((notification) => notification
|
|
199
|
+
.data.detailedView.interfaceId));
|
|
200
|
+
this.update((state) => {
|
|
201
|
+
Object.entries(state.interfaces).forEach(([id, snapInterface]) => {
|
|
202
|
+
if (snapInterface.contentType === ContentType.Notification &&
|
|
203
|
+
!interfaceIdSet.has(id)) {
|
|
204
|
+
delete state.interfaces[id];
|
|
205
|
+
}
|
|
206
|
+
});
|
|
207
|
+
});
|
|
176
208
|
};
|
|
177
209
|
//# sourceMappingURL=SnapInterfaceController.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SnapInterfaceController.mjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":";;;;;;AASA,OAAO,EAAE,cAAc,EAAE,kCAAkC;AAY3D,OAAO,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,8BAA8B;AAE5E,OAAO,EAAE,MAAM,EAAE,wBAAwB;AACzC,OAAO,EAAE,SAAS,EAAE,cAAc;AAClC,OAAO,EAAE,MAAM,EAAE,eAAe;AAGhC,OAAO,EACL,cAAc,EACd,eAAe,EACf,wBAAwB,EACzB,oBAAgB;AAEjB,MAAM,mBAAmB,GAAG,QAAU,CAAC,CAAC,QAAQ;AAEhD,MAAM,cAAc,GAAG,yBAAyB,CAAC;AAsFjD;;GAEG;AACH,MAAM,OAAO,uBAAwB,SAAQ,cAI5C;IACC,YAAY,EAAE,SAAS,EAAE,KAAK,EAA+B;QAC3D,KAAK,CAAC;YACJ,SAAS;YACT,QAAQ,EAAE;gBACR,UAAU,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE;aACjD;YACD,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,KAAK,EAAE;SACpC,CAAC,CAAC;;QAEH,uBAAA,IAAI,4FAAyB,MAA7B,IAAI,CAA2B,CAAC;IAClC,CAAC;IAsCD;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CACnB,MAAc,EACd,OAA2B,EAC3B,OAA0B;QAE1B,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,uBAAA,IAAI,oFAAiB,MAArB,IAAI,EAAkB,OAAO,CAAC,CAAC;QACrC,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAElC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,cAAc,GAAG,cAAc,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE;YACzB,wEAAwE;YACxE,qBAAqB;YACrB,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG;gBAC1B,MAAM;gBACN,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC;gBAC3B,KAAK,EAAE,cAAc;gBACrB,OAAO,EAAE,OAAO,IAAI,IAAI;aACzB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;;;;;OAMG;IACH,YAAY,CAAC,MAAc,EAAE,EAAU;QACrC,uBAAA,IAAI,iFAAc,MAAlB,IAAI,EAAe,MAAM,EAAE,EAAE,CAAC,CAAC;QAE/B,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CACnB,MAAc,EACd,EAAU,EACV,OAA2B,EAC3B,OAA0B;QAE1B,uBAAA,IAAI,iFAAc,MAAlB,IAAI,EAAe,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,uBAAA,IAAI,oFAAiB,MAArB,IAAI,EAAkB,OAAO,CAAC,CAAC;QACrC,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;QACjD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAEnD,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE;YACzB,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC;YAC3C,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;YACvD,IAAI,OAAO,EAAE,CAAC;gBACZ,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC;YAC9C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,eAAe,CAAC,EAAU;QACxB,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE;YACzB,OAAO,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACH,oBAAoB,CAAC,EAAU,EAAE,KAAqB;QACpD,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE;YACzB,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;QAC1C,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,EAAU,EAAE,KAAW;QAC5D,uBAAA,IAAI,iFAAc,MAAlB,IAAI,EAAe,MAAM,EAAE,EAAE,CAAC,CAAC;QAC/B,uBAAA,IAAI,qFAAkB,MAAtB,IAAI,EAAmB,EAAE,CAAC,CAAC;QAE3B,MAAM,uBAAA,IAAI,0FAAuB,MAA3B,IAAI,EAAwB,EAAE,EAAE,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IAC3B,CAAC;CAoGF;;IAvPG,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,kBAAkB,EACnC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAChC,CAAC;IAEF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,eAAe,EAChC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAC7B,CAAC;IAEF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,kBAAkB,EACnC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAChC,CAAC;IAEF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,kBAAkB,EACnC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAChC,CAAC;IAEF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,uBAAuB,EACxC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CACrC,CAAC;IAEF,IAAI,CAAC,eAAe,CAAC,qBAAqB,CACxC,GAAG,cAAc,mBAAmB,EACpC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CACjC,CAAC;AACJ,CAAC,yFA8Ha,MAAc,EAAE,EAAU;IACtC,MAAM,iBAAiB,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAEpD,MAAM,CACJ,iBAAiB,KAAK,SAAS,EAC/B,sBAAsB,EAAE,cAAc,CACvC,CAAC;IACF,MAAM,CACJ,iBAAiB,CAAC,MAAM,KAAK,MAAM,EACnC,4BAA4B,MAAM,GAAG,CACtC,CAAC;AACJ,CAAC,iGAOiB,EAAU;IAC1B,MAAM,CACJ,uBAAA,IAAI,uFAAoB,MAAxB,IAAI,EAAqB,EAAE,CAAC,EAC5B,6BAA6B,EAAE,cAAc,CAC9C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,KAAK;IACH,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;AACzE,CAAC,mGAQkB,MAAc;IAC/B,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,+BAA+B,EAAE,MAAM,CAAC;SACtE,MAAM,CAAC;AACZ,CAAC,qGASmB,EAAU;IAC5B,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,+BAA+B,EAAE;QAChE,EAAE;KACH,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,KAAK,yDAAwB,EAAU,EAAE,KAAW;IAClD,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAC7B,kCAAkC,EAClC,EAAE,EACF,KAAK,CACN,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,KAAK,mDAAkB,OAAmB;IACxC,qEAAqE;IACrE,0CAA0C;IAC1C,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,CACJ,IAAI,IAAI,mBAAmB,EAC3B,oCAAoC,mBAAmB,GAAG,OAAO,MAAM,CACxE,CAAC;IAEF,MAAM,uBAAA,IAAI,8FAA2B,MAA/B,IAAI,CAA6B,CAAC;IACxC,gBAAgB,CACd,OAAO,EACP,uBAAA,IAAI,sFAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,EAClC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC,CACpE,CAAC;AACJ,CAAC","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MaybeUpdateState,\n TestOrigin,\n} from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n} from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport { getJsonSizeUnsafe, validateJsxLinks } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { assert } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport type { GetSnap } from '../snaps';\nimport {\n constructState,\n getJsxInterface,\n validateInterfaceContext,\n} from './utils';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | MaybeUpdateState\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\nexport type SnapInterfaceControllerEvents =\n SnapInterfaceControllerStateChangeEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: { persist: false, anonymous: false },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element);\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element);\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Trigger a Phishing list update if needed.\n */\n async #triggerPhishingListUpdate() {\n await this.messagingSystem.call('PhishingController:maybeUpdateState');\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n await this.#triggerPhishingListUpdate();\n validateJsxLinks(\n element,\n this.#checkPhishingList.bind(this),\n (id: string) => this.messagingSystem.call('SnapController:get', id),\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SnapInterfaceController.mjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedControllerMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type {\n MaybeUpdateState,\n TestOrigin,\n} from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport { getJsonSizeUnsafe, validateJsxLinks } from '@metamask/snaps-utils';\nimport type { Json } from '@metamask/utils';\nimport { assert, hasProperty } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport type { GetSnap } from '../snaps';\nimport {\n constructState,\n getJsxInterface,\n validateInterfaceContext,\n} from './utils';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | MaybeUpdateState\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedControllerMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element);\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element);\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Trigger a Phishing list update if needed.\n */\n async #triggerPhishingListUpdate() {\n await this.messagingSystem.call('PhishingController:maybeUpdateState');\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n await this.#triggerPhishingListUpdate();\n validateJsxLinks(\n element,\n this.#checkPhishingList.bind(this),\n (id: string) => this.messagingSystem.call('SnapController:get', id),\n );\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}
|
|
@@ -673,8 +673,8 @@ class SnapController extends base_controller_1.BaseController {
|
|
|
673
673
|
result[snapId] = await this.processRequestedSnap(origin, snapId, location, version);
|
|
674
674
|
}
|
|
675
675
|
// Once we finish all installs / updates, emit events.
|
|
676
|
-
pendingInstalls.forEach((snapId) => this.messagingSystem.publish(`SnapController:snapInstalled`, this.getTruncatedExpect(snapId), origin));
|
|
677
|
-
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messagingSystem.publish(`SnapController:snapUpdated`, this.getTruncatedExpect(snapId), oldVersion, origin));
|
|
676
|
+
pendingInstalls.forEach((snapId) => this.messagingSystem.publish(`SnapController:snapInstalled`, this.getTruncatedExpect(snapId), origin, false));
|
|
677
|
+
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messagingSystem.publish(`SnapController:snapUpdated`, this.getTruncatedExpect(snapId), oldVersion, origin, false));
|
|
678
678
|
snapIds.forEach((snapId) => __classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").delete(snapId));
|
|
679
679
|
}
|
|
680
680
|
catch (error) {
|
|
@@ -787,6 +787,10 @@ class SnapController extends base_controller_1.BaseController {
|
|
|
787
787
|
async updateSnap(origin, snapId, location, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, emitEvent = true) {
|
|
788
788
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertCanInstallSnaps).call(this);
|
|
789
789
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertCanUsePlatform).call(this);
|
|
790
|
+
const snap = this.getExpect(snapId);
|
|
791
|
+
if (snap.preinstalled) {
|
|
792
|
+
throw new Error('Preinstalled Snaps cannot be manually updated.');
|
|
793
|
+
}
|
|
790
794
|
if (!(0, utils_1.isValidSemVerRange)(newVersionRange)) {
|
|
791
795
|
throw new Error(`Received invalid snap version range: "${newVersionRange}".`);
|
|
792
796
|
}
|
|
@@ -797,7 +801,6 @@ class SnapController extends base_controller_1.BaseController {
|
|
|
797
801
|
});
|
|
798
802
|
try {
|
|
799
803
|
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
800
|
-
const snap = this.getExpect(snapId);
|
|
801
804
|
const oldManifest = snap.manifest;
|
|
802
805
|
const newSnap = await (0, utils_2.fetchSnap)(snapId, location);
|
|
803
806
|
const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
|
|
@@ -871,7 +874,7 @@ class SnapController extends base_controller_1.BaseController {
|
|
|
871
874
|
}
|
|
872
875
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
873
876
|
if (emitEvent) {
|
|
874
|
-
this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version, origin);
|
|
877
|
+
this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version, origin, false);
|
|
875
878
|
}
|
|
876
879
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
|
|
877
880
|
loading: false,
|
|
@@ -1132,6 +1135,13 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_dynamicPerm
|
|
|
1132
1135
|
this.update((state) => {
|
|
1133
1136
|
state.snaps[snapId].status = snaps_utils_1.SnapStatus.Stopped;
|
|
1134
1137
|
});
|
|
1138
|
+
// Emit events
|
|
1139
|
+
if (isUpdate) {
|
|
1140
|
+
this.messagingSystem.publish('SnapController:snapUpdated', this.getTruncatedExpect(snapId), existingSnap.version, 'metamask', true);
|
|
1141
|
+
}
|
|
1142
|
+
else {
|
|
1143
|
+
this.messagingSystem.publish('SnapController:snapInstalled', this.getTruncatedExpect(snapId), 'metamask', true);
|
|
1144
|
+
}
|
|
1135
1145
|
}
|
|
1136
1146
|
}, _SnapController_pollForLastRequestStatus = function _SnapController_pollForLastRequestStatus() {
|
|
1137
1147
|
__classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(() => {
|
|
@@ -1664,10 +1674,11 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1664
1674
|
*
|
|
1665
1675
|
* @param snapId - The snap ID.
|
|
1666
1676
|
* @param content - The initial interface content.
|
|
1677
|
+
* @param contentType - The type of content.
|
|
1667
1678
|
* @returns An identifier that can be used to identify the interface.
|
|
1668
1679
|
*/
|
|
1669
|
-
async function _SnapController_createInterface(snapId, content) {
|
|
1670
|
-
return this.messagingSystem.call('SnapInterfaceController:createInterface', snapId, content);
|
|
1680
|
+
async function _SnapController_createInterface(snapId, content, contentType) {
|
|
1681
|
+
return this.messagingSystem.call('SnapInterfaceController:createInterface', snapId, content, undefined, contentType);
|
|
1671
1682
|
}, _SnapController_assertInterfaceExists = function _SnapController_assertInterfaceExists(snapId, id) {
|
|
1672
1683
|
// This will throw if the interface isn't accessible, but we assert nevertheless.
|
|
1673
1684
|
(0, utils_1.assert)(this.messagingSystem.call('SnapInterfaceController:getInterface', snapId, id));
|