@metamask/snaps-controllers 18.0.3 → 19.0.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 +103 -1
- package/dist/cronjob/CronjobController-method-action-types.cjs +7 -0
- package/dist/cronjob/CronjobController-method-action-types.cjs.map +1 -0
- package/dist/cronjob/CronjobController-method-action-types.d.cts +51 -0
- package/dist/cronjob/CronjobController-method-action-types.d.cts.map +1 -0
- package/dist/cronjob/CronjobController-method-action-types.d.mts +51 -0
- package/dist/cronjob/CronjobController-method-action-types.d.mts.map +1 -0
- package/dist/cronjob/CronjobController-method-action-types.mjs +6 -0
- package/dist/cronjob/CronjobController-method-action-types.mjs.map +1 -0
- package/dist/cronjob/CronjobController.cjs +7 -4
- package/dist/cronjob/CronjobController.cjs.map +1 -1
- package/dist/cronjob/CronjobController.d.cts +7 -24
- package/dist/cronjob/CronjobController.d.cts.map +1 -1
- package/dist/cronjob/CronjobController.d.mts +7 -24
- package/dist/cronjob/CronjobController.d.mts.map +1 -1
- package/dist/cronjob/CronjobController.mjs +7 -4
- package/dist/cronjob/CronjobController.mjs.map +1 -1
- package/dist/cronjob/index.cjs +3 -15
- package/dist/cronjob/index.cjs.map +1 -1
- package/dist/cronjob/index.d.cts +3 -1
- package/dist/cronjob/index.d.cts.map +1 -1
- package/dist/cronjob/index.d.mts +3 -1
- package/dist/cronjob/index.d.mts.map +1 -1
- package/dist/cronjob/index.mjs +1 -1
- package/dist/cronjob/index.mjs.map +1 -1
- package/dist/insights/SnapInsightsController.cjs +1 -3
- package/dist/insights/SnapInsightsController.cjs.map +1 -1
- package/dist/insights/SnapInsightsController.d.cts +8 -8
- package/dist/insights/SnapInsightsController.d.cts.map +1 -1
- package/dist/insights/SnapInsightsController.d.mts +8 -8
- package/dist/insights/SnapInsightsController.d.mts.map +1 -1
- package/dist/insights/SnapInsightsController.mjs +1 -3
- package/dist/insights/SnapInsightsController.mjs.map +1 -1
- package/dist/insights/index.cjs +3 -15
- package/dist/insights/index.cjs.map +1 -1
- package/dist/insights/index.d.cts +2 -1
- package/dist/insights/index.d.cts.map +1 -1
- package/dist/insights/index.d.mts +2 -1
- package/dist/insights/index.d.mts.map +1 -1
- package/dist/insights/index.mjs +1 -1
- package/dist/insights/index.mjs.map +1 -1
- package/dist/interface/SnapInterfaceController-method-action-types.cjs +7 -0
- package/dist/interface/SnapInterfaceController-method-action-types.cjs.map +1 -0
- package/dist/interface/SnapInterfaceController-method-action-types.d.cts +99 -0
- package/dist/interface/SnapInterfaceController-method-action-types.d.cts.map +1 -0
- package/dist/interface/SnapInterfaceController-method-action-types.d.mts +99 -0
- package/dist/interface/SnapInterfaceController-method-action-types.d.mts.map +1 -0
- package/dist/interface/SnapInterfaceController-method-action-types.mjs +6 -0
- package/dist/interface/SnapInterfaceController-method-action-types.mjs.map +1 -0
- package/dist/interface/SnapInterfaceController.cjs +12 -16
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +9 -39
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +9 -39
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +12 -16
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/interface/index.cjs +3 -15
- package/dist/interface/index.cjs.map +1 -1
- package/dist/interface/index.d.cts +3 -1
- package/dist/interface/index.d.cts.map +1 -1
- package/dist/interface/index.d.mts +3 -1
- package/dist/interface/index.d.mts.map +1 -1
- package/dist/interface/index.mjs +1 -1
- package/dist/interface/index.mjs.map +1 -1
- package/dist/multichain/MultichainRoutingService-method-action-types.cjs +7 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.cjs.map +1 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.d.cts +61 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.d.cts.map +1 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.d.mts +61 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.d.mts.map +1 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.mjs +6 -0
- package/dist/multichain/MultichainRoutingService-method-action-types.mjs.map +1 -0
- package/dist/multichain/{MultichainRouter.cjs → MultichainRoutingService.cjs} +14 -13
- package/dist/multichain/MultichainRoutingService.cjs.map +1 -0
- package/dist/multichain/{MultichainRouter.d.mts → MultichainRoutingService.d.cts} +13 -28
- package/dist/multichain/MultichainRoutingService.d.cts.map +1 -0
- package/dist/multichain/{MultichainRouter.d.cts → MultichainRoutingService.d.mts} +13 -28
- package/dist/multichain/MultichainRoutingService.d.mts.map +1 -0
- package/dist/multichain/{MultichainRouter.mjs → MultichainRoutingService.mjs} +12 -11
- package/dist/multichain/MultichainRoutingService.mjs.map +1 -0
- package/dist/multichain/index.cjs +3 -15
- package/dist/multichain/index.cjs.map +1 -1
- package/dist/multichain/index.d.cts +3 -1
- package/dist/multichain/index.d.cts.map +1 -1
- package/dist/multichain/index.d.mts +3 -1
- package/dist/multichain/index.d.mts.map +1 -1
- package/dist/multichain/index.mjs +1 -1
- package/dist/multichain/index.mjs.map +1 -1
- package/dist/services/ExecutionService-method-action-types.cjs +7 -0
- package/dist/services/ExecutionService-method-action-types.cjs.map +1 -0
- package/dist/services/ExecutionService-method-action-types.d.cts +50 -0
- package/dist/services/ExecutionService-method-action-types.d.cts.map +1 -0
- package/dist/services/ExecutionService-method-action-types.d.mts +50 -0
- package/dist/services/ExecutionService-method-action-types.d.mts.map +1 -0
- package/dist/services/ExecutionService-method-action-types.mjs +6 -0
- package/dist/services/ExecutionService-method-action-types.mjs.map +1 -0
- package/dist/services/ExecutionService.cjs +287 -0
- package/dist/services/ExecutionService.cjs.map +1 -1
- package/dist/services/ExecutionService.d.cts +100 -46
- package/dist/services/ExecutionService.d.cts.map +1 -1
- package/dist/services/ExecutionService.d.mts +100 -46
- package/dist/services/ExecutionService.d.mts.map +1 -1
- package/dist/services/ExecutionService.mjs +285 -1
- package/dist/services/ExecutionService.mjs.map +1 -1
- package/dist/services/browser.cjs +5 -2
- package/dist/services/browser.cjs.map +1 -1
- package/dist/services/browser.d.cts +4 -2
- package/dist/services/browser.d.cts.map +1 -1
- package/dist/services/browser.d.mts +4 -2
- package/dist/services/browser.d.mts.map +1 -1
- package/dist/services/browser.mjs +2 -2
- package/dist/services/browser.mjs.map +1 -1
- package/dist/services/iframe/IframeExecutionService.cjs +2 -2
- package/dist/services/iframe/IframeExecutionService.cjs.map +1 -1
- package/dist/services/iframe/IframeExecutionService.d.cts +3 -3
- package/dist/services/iframe/IframeExecutionService.d.cts.map +1 -1
- package/dist/services/iframe/IframeExecutionService.d.mts +3 -3
- package/dist/services/iframe/IframeExecutionService.d.mts.map +1 -1
- package/dist/services/iframe/IframeExecutionService.mjs +2 -2
- package/dist/services/iframe/IframeExecutionService.mjs.map +1 -1
- package/dist/services/index.cjs +5 -1
- package/dist/services/index.cjs.map +1 -1
- package/dist/services/index.d.cts +4 -2
- package/dist/services/index.d.cts.map +1 -1
- package/dist/services/index.d.mts +4 -2
- package/dist/services/index.d.mts.map +1 -1
- package/dist/services/index.mjs +2 -1
- package/dist/services/index.mjs.map +1 -1
- package/dist/services/multiplex.cjs +27 -0
- package/dist/services/multiplex.cjs.map +1 -0
- package/dist/services/multiplex.d.cts +11 -0
- package/dist/services/multiplex.d.cts.map +1 -0
- package/dist/services/multiplex.d.mts +11 -0
- package/dist/services/multiplex.d.mts.map +1 -0
- package/dist/services/multiplex.mjs +27 -0
- package/dist/services/multiplex.mjs.map +1 -0
- package/dist/services/node-js/NodeProcessExecutionService.cjs +2 -2
- package/dist/services/node-js/NodeProcessExecutionService.cjs.map +1 -1
- package/dist/services/node-js/NodeProcessExecutionService.d.cts +3 -3
- package/dist/services/node-js/NodeProcessExecutionService.d.cts.map +1 -1
- package/dist/services/node-js/NodeProcessExecutionService.d.mts +3 -3
- package/dist/services/node-js/NodeProcessExecutionService.d.mts.map +1 -1
- package/dist/services/node-js/NodeProcessExecutionService.mjs +2 -2
- package/dist/services/node-js/NodeProcessExecutionService.mjs.map +1 -1
- package/dist/services/node-js/NodeThreadExecutionService.cjs +2 -5
- package/dist/services/node-js/NodeThreadExecutionService.cjs.map +1 -1
- package/dist/services/node-js/NodeThreadExecutionService.d.cts +3 -3
- package/dist/services/node-js/NodeThreadExecutionService.d.cts.map +1 -1
- package/dist/services/node-js/NodeThreadExecutionService.d.mts +3 -3
- package/dist/services/node-js/NodeThreadExecutionService.d.mts.map +1 -1
- package/dist/services/node-js/NodeThreadExecutionService.mjs +2 -5
- package/dist/services/node-js/NodeThreadExecutionService.mjs.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.cjs.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.cts +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.cts.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.mts +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.d.mts.map +1 -1
- package/dist/services/offscreen/OffscreenExecutionService.mjs.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.cjs +2 -5
- package/dist/services/proxy/ProxyExecutionService.cjs.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.d.cts +3 -3
- package/dist/services/proxy/ProxyExecutionService.d.cts.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.d.mts +3 -3
- package/dist/services/proxy/ProxyExecutionService.d.mts.map +1 -1
- package/dist/services/proxy/ProxyExecutionService.mjs +2 -5
- package/dist/services/proxy/ProxyExecutionService.mjs.map +1 -1
- package/dist/services/webview/WebViewExecutionService.cjs +2 -2
- package/dist/services/webview/WebViewExecutionService.cjs.map +1 -1
- package/dist/services/webview/WebViewExecutionService.d.cts +3 -3
- package/dist/services/webview/WebViewExecutionService.d.cts.map +1 -1
- package/dist/services/webview/WebViewExecutionService.d.mts +3 -3
- package/dist/services/webview/WebViewExecutionService.d.mts.map +1 -1
- package/dist/services/webview/WebViewExecutionService.mjs +2 -2
- package/dist/services/webview/WebViewExecutionService.mjs.map +1 -1
- package/dist/snaps/SnapController-method-action-types.cjs +7 -0
- package/dist/snaps/SnapController-method-action-types.cjs.map +1 -0
- package/dist/snaps/SnapController-method-action-types.d.cts +284 -0
- package/dist/snaps/SnapController-method-action-types.d.cts.map +1 -0
- package/dist/snaps/SnapController-method-action-types.d.mts +284 -0
- package/dist/snaps/SnapController-method-action-types.d.mts.map +1 -0
- package/dist/snaps/SnapController-method-action-types.mjs +6 -0
- package/dist/snaps/SnapController-method-action-types.mjs.map +1 -0
- package/dist/snaps/SnapController.cjs +118 -113
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +32 -189
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +32 -189
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +119 -114
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/index.cjs +3 -1
- package/dist/snaps/index.cjs.map +1 -1
- package/dist/snaps/index.d.cts +3 -1
- package/dist/snaps/index.d.cts.map +1 -1
- package/dist/snaps/index.d.mts +3 -1
- package/dist/snaps/index.d.mts.map +1 -1
- package/dist/snaps/index.mjs +1 -1
- package/dist/snaps/index.mjs.map +1 -1
- package/dist/snaps/registry/SnapRegistryController-method-action-types.cjs +7 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.cjs.map +1 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.d.cts +46 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.d.cts.map +1 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.d.mts +46 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.d.mts.map +1 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.mjs +6 -0
- package/dist/snaps/registry/SnapRegistryController-method-action-types.mjs.map +1 -0
- package/dist/snaps/registry/{json.cjs → SnapRegistryController.cjs} +27 -24
- package/dist/snaps/registry/SnapRegistryController.cjs.map +1 -0
- package/dist/snaps/registry/SnapRegistryController.d.cts +67 -0
- package/dist/snaps/registry/SnapRegistryController.d.cts.map +1 -0
- package/dist/snaps/registry/SnapRegistryController.d.mts +67 -0
- package/dist/snaps/registry/SnapRegistryController.d.mts.map +1 -0
- package/dist/snaps/registry/{json.mjs → SnapRegistryController.mjs} +25 -22
- package/dist/snaps/registry/SnapRegistryController.mjs.map +1 -0
- package/dist/snaps/registry/index.cjs +5 -16
- package/dist/snaps/registry/index.cjs.map +1 -1
- package/dist/snaps/registry/index.d.cts +5 -2
- package/dist/snaps/registry/index.d.cts.map +1 -1
- package/dist/snaps/registry/index.d.mts +5 -2
- package/dist/snaps/registry/index.d.mts.map +1 -1
- package/dist/snaps/registry/index.mjs +2 -2
- package/dist/snaps/registry/index.mjs.map +1 -1
- package/dist/snaps/registry/types.cjs +11 -0
- package/dist/snaps/registry/types.cjs.map +1 -0
- package/dist/snaps/registry/types.d.cts +20 -0
- package/dist/snaps/registry/types.d.cts.map +1 -0
- package/dist/snaps/registry/types.d.mts +20 -0
- package/dist/snaps/registry/types.d.mts.map +1 -0
- package/dist/snaps/registry/types.mjs +8 -0
- package/dist/snaps/registry/types.mjs.map +1 -0
- package/dist/types/controllers.cjs.map +1 -1
- package/dist/types/controllers.d.cts +1 -1
- package/dist/types/controllers.d.cts.map +1 -1
- package/dist/types/controllers.d.mts +1 -1
- package/dist/types/controllers.d.mts.map +1 -1
- package/dist/types/controllers.mjs.map +1 -1
- package/dist/websocket/WebSocketService-method-action-types.cjs +7 -0
- package/dist/websocket/WebSocketService-method-action-types.cjs.map +1 -0
- package/dist/websocket/WebSocketService-method-action-types.d.cts +54 -0
- package/dist/websocket/WebSocketService-method-action-types.d.cts.map +1 -0
- package/dist/websocket/WebSocketService-method-action-types.d.mts +54 -0
- package/dist/websocket/WebSocketService-method-action-types.d.mts.map +1 -0
- package/dist/websocket/WebSocketService-method-action-types.mjs +6 -0
- package/dist/websocket/WebSocketService-method-action-types.mjs.map +1 -0
- package/dist/websocket/WebSocketService.cjs +14 -11
- package/dist/websocket/WebSocketService.cjs.map +1 -1
- package/dist/websocket/WebSocketService.d.cts +43 -22
- package/dist/websocket/WebSocketService.d.cts.map +1 -1
- package/dist/websocket/WebSocketService.d.mts +43 -22
- package/dist/websocket/WebSocketService.d.mts.map +1 -1
- package/dist/websocket/WebSocketService.mjs +14 -11
- package/dist/websocket/WebSocketService.mjs.map +1 -1
- package/dist/websocket/index.cjs +3 -15
- package/dist/websocket/index.cjs.map +1 -1
- package/dist/websocket/index.d.cts +3 -1
- package/dist/websocket/index.d.cts.map +1 -1
- package/dist/websocket/index.d.mts +3 -1
- package/dist/websocket/index.d.mts.map +1 -1
- package/dist/websocket/index.mjs +1 -1
- package/dist/websocket/index.mjs.map +1 -1
- package/package.json +8 -7
- package/dist/multichain/MultichainRouter.cjs.map +0 -1
- package/dist/multichain/MultichainRouter.d.cts.map +0 -1
- package/dist/multichain/MultichainRouter.d.mts.map +0 -1
- package/dist/multichain/MultichainRouter.mjs.map +0 -1
- package/dist/services/AbstractExecutionService.cjs +0 -307
- package/dist/services/AbstractExecutionService.cjs.map +0 -1
- package/dist/services/AbstractExecutionService.d.cts +0 -107
- package/dist/services/AbstractExecutionService.d.cts.map +0 -1
- package/dist/services/AbstractExecutionService.d.mts +0 -107
- package/dist/services/AbstractExecutionService.d.mts.map +0 -1
- package/dist/services/AbstractExecutionService.mjs +0 -306
- package/dist/services/AbstractExecutionService.mjs.map +0 -1
- package/dist/snaps/registry/json.cjs.map +0 -1
- package/dist/snaps/registry/json.d.cts +0 -58
- package/dist/snaps/registry/json.d.cts.map +0 -1
- package/dist/snaps/registry/json.d.mts +0 -58
- package/dist/snaps/registry/json.d.mts.map +0 -1
- package/dist/snaps/registry/json.mjs.map +0 -1
- package/dist/snaps/registry/registry.cjs +0 -11
- package/dist/snaps/registry/registry.cjs.map +0 -1
- package/dist/snaps/registry/registry.d.cts +0 -41
- package/dist/snaps/registry/registry.d.cts.map +0 -1
- package/dist/snaps/registry/registry.d.mts +0 -41
- package/dist/snaps/registry/registry.d.mts.map +0 -1
- package/dist/snaps/registry/registry.mjs +0 -8
- package/dist/snaps/registry/registry.mjs.map +0 -1
|
@@ -12,14 +12,42 @@ import { nanoid } from "nanoid";
|
|
|
12
12
|
import { gt, gte } from "semver";
|
|
13
13
|
import { ALLOWED_PERMISSIONS, CLIENT_ONLY_HANDLERS, DYNAMIC_PERMISSION_DEPENDENCIES, INTERFACE_HANDLERS, LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS, METAMASK_ORIGIN, STATE_DEBOUNCE_TIMEOUT } from "./constants.mjs";
|
|
14
14
|
import { detectSnapLocation } from "./location/index.mjs";
|
|
15
|
-
import {
|
|
15
|
+
import { SnapRegistryStatus } from "./registry/index.mjs";
|
|
16
16
|
import { getRunnableSnaps } from "./selectors.mjs";
|
|
17
17
|
import { Timer } from "./Timer.mjs";
|
|
18
18
|
import { forceStrict, validateMachine } from "../fsm.mjs";
|
|
19
19
|
import { log } from "../logging.mjs";
|
|
20
20
|
import { debouncePersistState, fetchSnap, hasTimedOut, permissionsDiff, setDiff, throttleTracking, withTimeout, isTrackableHandler, isLocalSnapId } from "../utils.mjs";
|
|
21
21
|
export const controllerName = 'SnapController';
|
|
22
|
-
//
|
|
22
|
+
// This is used by the `generate-method-action-types` script.
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
24
|
+
const MESSENGER_EXPOSED_METHODS = [
|
|
25
|
+
'init',
|
|
26
|
+
'updateRegistry',
|
|
27
|
+
'enableSnap',
|
|
28
|
+
'disableSnap',
|
|
29
|
+
'stopSnap',
|
|
30
|
+
'stopAllSnaps',
|
|
31
|
+
'isSnapRunning',
|
|
32
|
+
'hasSnap',
|
|
33
|
+
'getSnap',
|
|
34
|
+
'updateSnapState',
|
|
35
|
+
'clearSnapState',
|
|
36
|
+
'getSnapState',
|
|
37
|
+
'getSnapFile',
|
|
38
|
+
'isMinimumPlatformVersion',
|
|
39
|
+
'clearState',
|
|
40
|
+
'removeSnap',
|
|
41
|
+
'removeSnaps',
|
|
42
|
+
'disconnectOrigin',
|
|
43
|
+
'revokeDynamicSnapPermissions',
|
|
44
|
+
'getAllSnaps',
|
|
45
|
+
'getRunnableSnaps',
|
|
46
|
+
'getPermittedSnaps',
|
|
47
|
+
'installSnaps',
|
|
48
|
+
'handleRequest',
|
|
49
|
+
'setClientActive',
|
|
50
|
+
];
|
|
23
51
|
export const SNAP_APPROVAL_INSTALL = 'wallet_installSnap';
|
|
24
52
|
export const SNAP_APPROVAL_UPDATE = 'wallet_updateSnap';
|
|
25
53
|
export const SNAP_APPROVAL_RESULT = 'wallet_installSnapResult';
|
|
@@ -185,7 +213,7 @@ export class SnapController extends BaseController {
|
|
|
185
213
|
});
|
|
186
214
|
});
|
|
187
215
|
this.messenger.subscribe('KeyringController:lock', this.#handleLock.bind(this));
|
|
188
|
-
this.messenger.subscribe('
|
|
216
|
+
this.messenger.subscribe('SnapRegistryController:stateChange', () => {
|
|
189
217
|
this.#handleRegistryUpdate().catch((error) => {
|
|
190
218
|
logError(`Error when processing Snaps registry update: ${getErrorMessage(error)}`);
|
|
191
219
|
});
|
|
@@ -194,7 +222,7 @@ export class SnapController extends BaseController {
|
|
|
194
222
|
this.#registerMessageHandlers();
|
|
195
223
|
Object.values(this.state?.snaps ?? {}).forEach((snap) => this.#setupRuntime(snap.id));
|
|
196
224
|
this.#trackSnapExport = throttleTracking((snapId, handler, success, origin) => {
|
|
197
|
-
const snapMetadata = this.messenger.call('
|
|
225
|
+
const snapMetadata = this.messenger.call('SnapRegistryController:getMetadata', snapId);
|
|
198
226
|
this.#trackEvent({
|
|
199
227
|
event: 'Snap Export Used',
|
|
200
228
|
category: 'Snaps',
|
|
@@ -221,7 +249,7 @@ export class SnapController extends BaseController {
|
|
|
221
249
|
// In the future, side-effects could be added to the machine during transitions.
|
|
222
250
|
#initializeStateMachine() {
|
|
223
251
|
const disableGuard = ({ snapId }) => {
|
|
224
|
-
return this.
|
|
252
|
+
return this.getSnapExpect(snapId).enabled;
|
|
225
253
|
};
|
|
226
254
|
const statusConfig = {
|
|
227
255
|
initial: SnapStatus.Installing,
|
|
@@ -279,24 +307,22 @@ export class SnapController extends BaseController {
|
|
|
279
307
|
#registerMessageHandlers() {
|
|
280
308
|
this.messenger.registerActionHandler(`${controllerName}:init`, async (...args) => this.init(...args));
|
|
281
309
|
this.messenger.registerActionHandler(`${controllerName}:clearSnapState`, (...args) => this.clearSnapState(...args));
|
|
282
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
310
|
+
this.messenger.registerActionHandler(`${controllerName}:getSnap`, (...args) => this.getSnap(...args));
|
|
283
311
|
this.messenger.registerActionHandler(`${controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
|
|
284
312
|
this.messenger.registerActionHandler(`${controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
|
|
285
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
313
|
+
this.messenger.registerActionHandler(`${controllerName}:hasSnap`, (...args) => this.hasSnap(...args));
|
|
286
314
|
this.messenger.registerActionHandler(`${controllerName}:updateRegistry`, async () => this.updateRegistry());
|
|
287
315
|
this.messenger.registerActionHandler(`${controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
|
|
288
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
289
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
290
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
291
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
292
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
293
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
316
|
+
this.messenger.registerActionHandler(`${controllerName}:enableSnap`, (...args) => this.enableSnap(...args));
|
|
317
|
+
this.messenger.registerActionHandler(`${controllerName}:disableSnap`, async (...args) => this.disableSnap(...args));
|
|
318
|
+
this.messenger.registerActionHandler(`${controllerName}:removeSnap`, async (...args) => this.removeSnap(...args));
|
|
319
|
+
this.messenger.registerActionHandler(`${controllerName}:getPermittedSnaps`, (...args) => this.getPermittedSnaps(...args));
|
|
320
|
+
this.messenger.registerActionHandler(`${controllerName}:installSnaps`, async (...args) => this.installSnaps(...args));
|
|
321
|
+
this.messenger.registerActionHandler(`${controllerName}:getAllSnaps`, (...args) => this.getAllSnaps(...args));
|
|
294
322
|
this.messenger.registerActionHandler(`${controllerName}:getRunnableSnaps`, (...args) => this.getRunnableSnaps(...args));
|
|
295
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
296
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
297
|
-
this.messenger.registerActionHandler(`${controllerName}:
|
|
298
|
-
this.messenger.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args) => this.revokeDynamicSnapPermissions(...args));
|
|
299
|
-
this.messenger.registerActionHandler(`${controllerName}:getFile`, async (...args) => this.getSnapFile(...args));
|
|
323
|
+
this.messenger.registerActionHandler(`${controllerName}:disconnectOrigin`, (...args) => this.disconnectOrigin(...args));
|
|
324
|
+
this.messenger.registerActionHandler(`${controllerName}:revokeDynamicSnapPermissions`, (...args) => this.revokeDynamicSnapPermissions(...args));
|
|
325
|
+
this.messenger.registerActionHandler(`${controllerName}:getSnapFile`, async (...args) => this.getSnapFile(...args));
|
|
300
326
|
this.messenger.registerActionHandler(`${controllerName}:stopAllSnaps`, async (...args) => this.stopAllSnaps(...args));
|
|
301
327
|
this.messenger.registerActionHandler(`${controllerName}:isMinimumPlatformVersion`, (...args) => this.isMinimumPlatformVersion(...args));
|
|
302
328
|
this.messenger.registerActionHandler(`${controllerName}:setClientActive`, (...args) => this.setClientActive(...args));
|
|
@@ -331,8 +357,8 @@ export class SnapController extends BaseController {
|
|
|
331
357
|
}
|
|
332
358
|
async #handlePreinstalledSnaps(preinstalledSnaps) {
|
|
333
359
|
for (const { snapId, manifest, files, removable, hidden, hideSnapBranding, } of preinstalledSnaps) {
|
|
334
|
-
const existingSnap = this.
|
|
335
|
-
const isAlreadyInstalled = existingSnap !==
|
|
360
|
+
const existingSnap = this.getSnap(snapId);
|
|
361
|
+
const isAlreadyInstalled = existingSnap !== null;
|
|
336
362
|
const isUpdate = isAlreadyInstalled && gtVersion(manifest.version, existingSnap.version);
|
|
337
363
|
const isPreinstalled = existingSnap?.preinstalled === true;
|
|
338
364
|
const isMissingSource = isAlreadyInstalled &&
|
|
@@ -395,10 +421,10 @@ export class SnapController extends BaseController {
|
|
|
395
421
|
this.#setupRuntime(snapId);
|
|
396
422
|
// Emit events
|
|
397
423
|
if (isUpdate) {
|
|
398
|
-
this.messenger.publish('SnapController:snapUpdated', this
|
|
424
|
+
this.messenger.publish('SnapController:snapUpdated', this.#getTruncatedSnapExpect(snapId), existingSnap.version, METAMASK_ORIGIN, true);
|
|
399
425
|
}
|
|
400
426
|
else if (!isMissingSource) {
|
|
401
|
-
this.messenger.publish('SnapController:snapInstalled', this
|
|
427
|
+
this.messenger.publish('SnapController:snapInstalled', this.#getTruncatedSnapExpect(snapId), METAMASK_ORIGIN, true);
|
|
402
428
|
}
|
|
403
429
|
if (isMissingSource) {
|
|
404
430
|
logWarning(`The source code for "${snapId}" was missing and has been automatically restored. If you see this message, please file a bug report.`);
|
|
@@ -454,7 +480,7 @@ export class SnapController extends BaseController {
|
|
|
454
480
|
*/
|
|
455
481
|
async updateRegistry() {
|
|
456
482
|
await this.#ensureCanUsePlatform();
|
|
457
|
-
await this.messenger.call('
|
|
483
|
+
await this.messenger.call('SnapRegistryController:requestUpdate');
|
|
458
484
|
}
|
|
459
485
|
/**
|
|
460
486
|
* Checks all installed Snaps against the blocklist and
|
|
@@ -464,7 +490,7 @@ export class SnapController extends BaseController {
|
|
|
464
490
|
* Also updates any preinstalled Snaps to the latest allowlisted version.
|
|
465
491
|
*/
|
|
466
492
|
async #handleRegistryUpdate() {
|
|
467
|
-
const blockedSnaps = await this.messenger.call('
|
|
493
|
+
const blockedSnaps = await this.messenger.call('SnapRegistryController:get', Object.values(this.state.snaps).reduce((blockListArg, snap) => {
|
|
468
494
|
blockListArg[snap.id] = {
|
|
469
495
|
version: snap.version,
|
|
470
496
|
checksum: snap.manifest.source.shasum,
|
|
@@ -472,7 +498,7 @@ export class SnapController extends BaseController {
|
|
|
472
498
|
return blockListArg;
|
|
473
499
|
}, {}));
|
|
474
500
|
await Promise.all(Object.entries(blockedSnaps).map(async ([snapId, { status, reason }]) => {
|
|
475
|
-
if (status ===
|
|
501
|
+
if (status === SnapRegistryStatus.Blocked) {
|
|
476
502
|
return this.#blockSnap(snapId, reason);
|
|
477
503
|
}
|
|
478
504
|
return this.#unblockSnap(snapId);
|
|
@@ -505,13 +531,13 @@ export class SnapController extends BaseController {
|
|
|
505
531
|
}
|
|
506
532
|
/**
|
|
507
533
|
* Blocks an installed snap and prevents it from being started again. Emits
|
|
508
|
-
* {@link
|
|
534
|
+
* {@link SnapControllerSnapBlockedEvent}. Does nothing if the snap is not installed.
|
|
509
535
|
*
|
|
510
536
|
* @param snapId - The snap to block.
|
|
511
537
|
* @param blockedSnapInfo - Information detailing why the snap is blocked.
|
|
512
538
|
*/
|
|
513
539
|
async #blockSnap(snapId, blockedSnapInfo) {
|
|
514
|
-
if (!this.
|
|
540
|
+
if (!this.hasSnap(snapId)) {
|
|
515
541
|
return;
|
|
516
542
|
}
|
|
517
543
|
try {
|
|
@@ -528,13 +554,13 @@ export class SnapController extends BaseController {
|
|
|
528
554
|
}
|
|
529
555
|
/**
|
|
530
556
|
* Unblocks a snap so that it can be enabled and started again. Emits
|
|
531
|
-
* {@link
|
|
557
|
+
* {@link SnapControllerSnapUnblockedEvent}. Does nothing if the snap is not installed or already
|
|
532
558
|
* unblocked.
|
|
533
559
|
*
|
|
534
560
|
* @param snapId - The id of the snap to unblock.
|
|
535
561
|
*/
|
|
536
562
|
#unblockSnap(snapId) {
|
|
537
|
-
if (!this.
|
|
563
|
+
if (!this.hasSnap(snapId) || !this.state.snaps[snapId].blocked) {
|
|
538
564
|
return;
|
|
539
565
|
}
|
|
540
566
|
this.update((state) => {
|
|
@@ -544,18 +570,18 @@ export class SnapController extends BaseController {
|
|
|
544
570
|
this.messenger.publish(`${controllerName}:snapUnblocked`, snapId);
|
|
545
571
|
}
|
|
546
572
|
async #assertIsInstallAllowed(snapId, { platformVersion, ...snapInfo }) {
|
|
547
|
-
const results = await this.messenger.call('
|
|
573
|
+
const results = await this.messenger.call('SnapRegistryController:get', {
|
|
548
574
|
[snapId]: snapInfo,
|
|
549
575
|
});
|
|
550
576
|
const result = results[snapId];
|
|
551
|
-
if (result.status ===
|
|
577
|
+
if (result.status === SnapRegistryStatus.Blocked) {
|
|
552
578
|
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The version is blocked. ${result.reason?.explanation ?? ''}`);
|
|
553
579
|
}
|
|
554
580
|
const isAllowlistingRequired = Object.keys(snapInfo.permissions).some((permission) => !ALLOWED_PERMISSIONS.includes(permission));
|
|
555
581
|
if (this.#featureFlags.requireAllowlist &&
|
|
556
582
|
isAllowlistingRequired &&
|
|
557
|
-
result.status !==
|
|
558
|
-
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": ${result.status ===
|
|
583
|
+
result.status !== SnapRegistryStatus.Verified) {
|
|
584
|
+
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": ${result.status === SnapRegistryStatus.Unavailable
|
|
559
585
|
? 'The registry is temporarily unavailable.'
|
|
560
586
|
: 'The snap is not on the allowlist.'}`);
|
|
561
587
|
}
|
|
@@ -589,8 +615,7 @@ export class SnapController extends BaseController {
|
|
|
589
615
|
async #stopSnapsLastRequestPastMax() {
|
|
590
616
|
const entries = [...this.#snapsRuntimeData.entries()];
|
|
591
617
|
return Promise.all(entries
|
|
592
|
-
.filter(([_snapId, runtime]) => runtime.
|
|
593
|
-
runtime.pendingInboundRequests.length === 0 &&
|
|
618
|
+
.filter(([_snapId, runtime]) => runtime.pendingInboundRequests.length === 0 &&
|
|
594
619
|
runtime.lastRequest &&
|
|
595
620
|
this.#maxIdleTime &&
|
|
596
621
|
timeSince(runtime.lastRequest) > this.#maxIdleTime)
|
|
@@ -667,14 +692,14 @@ export class SnapController extends BaseController {
|
|
|
667
692
|
* @param snapId - The id of the Snap to enable.
|
|
668
693
|
*/
|
|
669
694
|
enableSnap(snapId) {
|
|
670
|
-
this.
|
|
695
|
+
this.getSnapExpect(snapId);
|
|
671
696
|
if (this.state.snaps[snapId].blocked) {
|
|
672
697
|
throw new Error(`Snap "${snapId}" is blocked and cannot be enabled.`);
|
|
673
698
|
}
|
|
674
699
|
this.update((state) => {
|
|
675
700
|
state.snaps[snapId].enabled = true;
|
|
676
701
|
});
|
|
677
|
-
this.messenger.publish('SnapController:snapEnabled', this
|
|
702
|
+
this.messenger.publish('SnapController:snapEnabled', this.#getTruncatedSnapExpect(snapId));
|
|
678
703
|
}
|
|
679
704
|
/**
|
|
680
705
|
* Disables the given snap. A snap can only be started if it is enabled.
|
|
@@ -683,16 +708,16 @@ export class SnapController extends BaseController {
|
|
|
683
708
|
* @returns A promise that resolves once the snap has been disabled.
|
|
684
709
|
*/
|
|
685
710
|
async disableSnap(snapId) {
|
|
686
|
-
if (!this.
|
|
711
|
+
if (!this.hasSnap(snapId)) {
|
|
687
712
|
throw new Error(`Snap "${snapId}" not found.`);
|
|
688
713
|
}
|
|
689
714
|
this.update((state) => {
|
|
690
715
|
state.snaps[snapId].enabled = false;
|
|
691
716
|
});
|
|
692
|
-
if (this.
|
|
717
|
+
if (this.isSnapRunning(snapId)) {
|
|
693
718
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
694
719
|
}
|
|
695
|
-
this.messenger.publish('SnapController:snapDisabled', this
|
|
720
|
+
this.messenger.publish('SnapController:snapDisabled', this.#getTruncatedSnapExpect(snapId));
|
|
696
721
|
}
|
|
697
722
|
/**
|
|
698
723
|
* Stops the given snap, removes all hooks, closes all connections, and
|
|
@@ -717,7 +742,7 @@ export class SnapController extends BaseController {
|
|
|
717
742
|
const { promise, resolve } = createDeferredPromise();
|
|
718
743
|
runtime.stopPromise = promise;
|
|
719
744
|
try {
|
|
720
|
-
if (this.
|
|
745
|
+
if (this.isSnapRunning(snapId)) {
|
|
721
746
|
await this.#terminateSnap(snapId);
|
|
722
747
|
}
|
|
723
748
|
}
|
|
@@ -727,7 +752,7 @@ export class SnapController extends BaseController {
|
|
|
727
752
|
runtime.pendingInboundRequests = [];
|
|
728
753
|
runtime.pendingOutboundRequests = 0;
|
|
729
754
|
runtime.stopPromise = null;
|
|
730
|
-
if (this.
|
|
755
|
+
if (this.isSnapRunning(snapId)) {
|
|
731
756
|
this.#transition(snapId, statusEvent);
|
|
732
757
|
}
|
|
733
758
|
resolve();
|
|
@@ -741,7 +766,7 @@ export class SnapController extends BaseController {
|
|
|
741
766
|
* stopped.
|
|
742
767
|
*/
|
|
743
768
|
async stopAllSnaps(statusEvent = SnapStatusEvents.Stop) {
|
|
744
|
-
const snaps = Object.values(this.state.snaps).filter((snap) => this.
|
|
769
|
+
const snaps = Object.values(this.state.snaps).filter((snap) => this.isSnapRunning(snap.id));
|
|
745
770
|
const promises = snaps.map(async (snap) => this.stopSnap(snap.id, statusEvent));
|
|
746
771
|
await Promise.allSettled(promises);
|
|
747
772
|
}
|
|
@@ -761,7 +786,7 @@ export class SnapController extends BaseController {
|
|
|
761
786
|
.forEach((pendingRequest) => pendingRequest.timer.finish());
|
|
762
787
|
// Hack to give up execution for a bit to let timed out requests return.
|
|
763
788
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
764
|
-
this.messenger.publish('SnapController:snapTerminated', this
|
|
789
|
+
this.messenger.publish('SnapController:snapTerminated', this.#getTruncatedSnapExpect(snapId));
|
|
765
790
|
}
|
|
766
791
|
/**
|
|
767
792
|
* Returns whether the given snap is running.
|
|
@@ -770,8 +795,8 @@ export class SnapController extends BaseController {
|
|
|
770
795
|
* @param snapId - The id of the Snap to check.
|
|
771
796
|
* @returns `true` if the snap is running, otherwise `false`.
|
|
772
797
|
*/
|
|
773
|
-
|
|
774
|
-
return this.
|
|
798
|
+
isSnapRunning(snapId) {
|
|
799
|
+
return this.getSnapExpect(snapId).status === 'running';
|
|
775
800
|
}
|
|
776
801
|
/**
|
|
777
802
|
* Returns whether the given snap has been added to state.
|
|
@@ -779,8 +804,8 @@ export class SnapController extends BaseController {
|
|
|
779
804
|
* @param snapId - The id of the Snap to check for.
|
|
780
805
|
* @returns `true` if the snap exists in the controller state, otherwise `false`.
|
|
781
806
|
*/
|
|
782
|
-
|
|
783
|
-
return Boolean(this.
|
|
807
|
+
hasSnap(snapId) {
|
|
808
|
+
return Boolean(this.getSnap(snapId));
|
|
784
809
|
}
|
|
785
810
|
/**
|
|
786
811
|
* Gets the snap with the given id if it exists, including all data.
|
|
@@ -790,22 +815,22 @@ export class SnapController extends BaseController {
|
|
|
790
815
|
* @param snapId - The id of the Snap to get.
|
|
791
816
|
* @returns The entire snap object from the controller state.
|
|
792
817
|
*/
|
|
793
|
-
|
|
794
|
-
return this.state.snaps[snapId];
|
|
818
|
+
getSnap(snapId) {
|
|
819
|
+
return this.state.snaps[snapId] ?? null;
|
|
795
820
|
}
|
|
796
821
|
/**
|
|
797
822
|
* Gets the snap with the given id, throws if doesn't.
|
|
798
823
|
* This should not be used if the snap is to be serializable, as e.g.
|
|
799
824
|
* the snap sourceCode may be quite large.
|
|
800
825
|
*
|
|
801
|
-
* @see {@link SnapController.
|
|
826
|
+
* @see {@link SnapController.getSnap}
|
|
802
827
|
* @throws {@link Error}. If the snap doesn't exist
|
|
803
828
|
* @param snapId - The id of the snap to get.
|
|
804
829
|
* @returns The entire snap object.
|
|
805
830
|
*/
|
|
806
|
-
|
|
807
|
-
const snap = this.
|
|
808
|
-
assert(snap !==
|
|
831
|
+
getSnapExpect(snapId) {
|
|
832
|
+
const snap = this.getSnap(snapId);
|
|
833
|
+
assert(snap !== null, `Snap "${snapId}" not found.`);
|
|
809
834
|
return snap;
|
|
810
835
|
}
|
|
811
836
|
/**
|
|
@@ -815,9 +840,8 @@ export class SnapController extends BaseController {
|
|
|
815
840
|
* @param snapId - The id of the Snap to get.
|
|
816
841
|
* @returns A truncated version of the snap state, that is less expensive to serialize.
|
|
817
842
|
*/
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
const snap = this.get(snapId);
|
|
843
|
+
#getTruncatedSnap(snapId) {
|
|
844
|
+
const snap = this.getSnap(snapId);
|
|
821
845
|
return snap ? truncateSnap(snap) : null;
|
|
822
846
|
}
|
|
823
847
|
/**
|
|
@@ -827,8 +851,8 @@ export class SnapController extends BaseController {
|
|
|
827
851
|
* @param snapId - The id of the snap to get.
|
|
828
852
|
* @returns A truncated version of the snap state, that is less expensive to serialize.
|
|
829
853
|
*/
|
|
830
|
-
|
|
831
|
-
return truncateSnap(this.
|
|
854
|
+
#getTruncatedSnapExpect(snapId) {
|
|
855
|
+
return truncateSnap(this.getSnapExpect(snapId));
|
|
832
856
|
}
|
|
833
857
|
/**
|
|
834
858
|
* Check if a given Snap has a cached encryption key stored in the runtime.
|
|
@@ -1059,7 +1083,7 @@ export class SnapController extends BaseController {
|
|
|
1059
1083
|
* @returns The file requested in the chosen file encoding or null if the file is not found.
|
|
1060
1084
|
*/
|
|
1061
1085
|
async getSnapFile(snapId, path, encoding = AuxiliaryFileEncoding.Base64) {
|
|
1062
|
-
const snap = this.
|
|
1086
|
+
const snap = this.getSnapExpect(snapId);
|
|
1063
1087
|
const normalizedPath = normalizeRelative(path);
|
|
1064
1088
|
const value = snap.auxiliaryFiles?.find((file) => file.path === normalizedPath)?.value;
|
|
1065
1089
|
if (!value) {
|
|
@@ -1078,7 +1102,7 @@ export class SnapController extends BaseController {
|
|
|
1078
1102
|
* @returns True if the platform version is equal or greater to the passed version, false otherwise.
|
|
1079
1103
|
*/
|
|
1080
1104
|
isMinimumPlatformVersion(snapId, version) {
|
|
1081
|
-
const snap = this.
|
|
1105
|
+
const snap = this.getSnapExpect(snapId);
|
|
1082
1106
|
const { platformVersion } = snap.manifest;
|
|
1083
1107
|
if (!platformVersion) {
|
|
1084
1108
|
return false;
|
|
@@ -1128,12 +1152,12 @@ export class SnapController extends BaseController {
|
|
|
1128
1152
|
throw new Error('Expected array of snap ids.');
|
|
1129
1153
|
}
|
|
1130
1154
|
snapIds.forEach((snapId) => {
|
|
1131
|
-
const snap = this.
|
|
1155
|
+
const snap = this.getSnapExpect(snapId);
|
|
1132
1156
|
assert(snap.removable !== false, `${snapId} is not removable.`);
|
|
1133
1157
|
});
|
|
1134
1158
|
await Promise.all(snapIds.map(async (snapId) => {
|
|
1135
|
-
const snap = this.
|
|
1136
|
-
const truncated = this
|
|
1159
|
+
const snap = this.getSnapExpect(snapId);
|
|
1160
|
+
const truncated = this.#getTruncatedSnapExpect(snapId);
|
|
1137
1161
|
// Disable the snap and revoke all of its permissions before deleting
|
|
1138
1162
|
// it. This ensures that the snap will not be restarted or otherwise
|
|
1139
1163
|
// affect the host environment while we are deleting it.
|
|
@@ -1157,7 +1181,7 @@ export class SnapController extends BaseController {
|
|
|
1157
1181
|
if (previousInitialConnections) {
|
|
1158
1182
|
const revokedInitialConnections = setDiff(previousInitialConnections, initialConnections);
|
|
1159
1183
|
for (const origin of Object.keys(revokedInitialConnections)) {
|
|
1160
|
-
this.
|
|
1184
|
+
this.disconnectOrigin(origin, snapId);
|
|
1161
1185
|
}
|
|
1162
1186
|
}
|
|
1163
1187
|
for (const origin of Object.keys(initialConnections)) {
|
|
@@ -1195,12 +1219,13 @@ export class SnapController extends BaseController {
|
|
|
1195
1219
|
});
|
|
1196
1220
|
}
|
|
1197
1221
|
/**
|
|
1198
|
-
*
|
|
1222
|
+
* Disconnect the Snap from the given origin, meaning the origin can no longer
|
|
1223
|
+
* interact with the Snap until it is reconnected.
|
|
1199
1224
|
*
|
|
1200
|
-
* @param origin - The origin from which to remove the
|
|
1225
|
+
* @param origin - The origin from which to remove the Snap.
|
|
1201
1226
|
* @param snapId - The id of the snap to remove.
|
|
1202
1227
|
*/
|
|
1203
|
-
|
|
1228
|
+
disconnectOrigin(origin, snapId) {
|
|
1204
1229
|
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
1205
1230
|
const snapIdsCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
1206
1231
|
if (!snapIdsCaveat) {
|
|
@@ -1243,7 +1268,7 @@ export class SnapController extends BaseController {
|
|
|
1243
1268
|
#removeSnapFromSubjects(snapId) {
|
|
1244
1269
|
const subjects = this.messenger.call('PermissionController:getSubjectNames');
|
|
1245
1270
|
for (const subject of subjects) {
|
|
1246
|
-
this.
|
|
1271
|
+
this.disconnectOrigin(subject, snapId);
|
|
1247
1272
|
}
|
|
1248
1273
|
}
|
|
1249
1274
|
/**
|
|
@@ -1256,25 +1281,6 @@ export class SnapController extends BaseController {
|
|
|
1256
1281
|
this.messenger.call('PermissionController:revokeAllPermissions', snapId);
|
|
1257
1282
|
}
|
|
1258
1283
|
}
|
|
1259
|
-
/**
|
|
1260
|
-
* Handles incrementing the activeReferences counter.
|
|
1261
|
-
*
|
|
1262
|
-
* @param snapId - The snap id of the snap that was referenced.
|
|
1263
|
-
*/
|
|
1264
|
-
incrementActiveReferences(snapId) {
|
|
1265
|
-
const runtime = this.#getRuntimeExpect(snapId);
|
|
1266
|
-
runtime.activeReferences += 1;
|
|
1267
|
-
}
|
|
1268
|
-
/**
|
|
1269
|
-
* Handles decrement the activeReferences counter.
|
|
1270
|
-
*
|
|
1271
|
-
* @param snapId - The snap id of the snap that was referenced..
|
|
1272
|
-
*/
|
|
1273
|
-
decrementActiveReferences(snapId) {
|
|
1274
|
-
const runtime = this.#getRuntimeExpect(snapId);
|
|
1275
|
-
assert(runtime.activeReferences > 0, 'SnapController reference management is in an invalid state.');
|
|
1276
|
-
runtime.activeReferences -= 1;
|
|
1277
|
-
}
|
|
1278
1284
|
/**
|
|
1279
1285
|
* Gets all snaps in their truncated format.
|
|
1280
1286
|
*
|
|
@@ -1301,8 +1307,8 @@ export class SnapController extends BaseController {
|
|
|
1301
1307
|
const permissions = this.messenger.call('PermissionController:getPermissions', origin) ?? {};
|
|
1302
1308
|
const snaps = permissions[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds)?.value ?? {};
|
|
1303
1309
|
return Object.keys(snaps).reduce((permittedSnaps, snapId) => {
|
|
1304
|
-
const snap = this.
|
|
1305
|
-
const truncatedSnap = this
|
|
1310
|
+
const snap = this.getSnap(snapId);
|
|
1311
|
+
const truncatedSnap = this.#getTruncatedSnap(snapId);
|
|
1306
1312
|
if (truncatedSnap && snap?.status !== SnapStatus.Installing) {
|
|
1307
1313
|
permittedSnaps[snapId] = truncatedSnap;
|
|
1308
1314
|
}
|
|
@@ -1342,9 +1348,9 @@ export class SnapController extends BaseController {
|
|
|
1342
1348
|
});
|
|
1343
1349
|
// Existing snaps may need to be updated, unless they should be re-installed (e.g. local snaps)
|
|
1344
1350
|
// Everything else is treated as an install
|
|
1345
|
-
const isUpdate = this.
|
|
1351
|
+
const isUpdate = this.hasSnap(snapId) && !location.shouldAlwaysReload;
|
|
1346
1352
|
if (isUpdate && this.#isValidUpdate(snapId, version)) {
|
|
1347
|
-
const existingSnap = this.
|
|
1353
|
+
const existingSnap = this.getSnapExpect(snapId);
|
|
1348
1354
|
pendingUpdates.push({ snapId, oldVersion: existingSnap.version });
|
|
1349
1355
|
let rollbackSnapshot = this.#getRollbackSnapshot(snapId);
|
|
1350
1356
|
if (rollbackSnapshot === undefined) {
|
|
@@ -1361,12 +1367,12 @@ export class SnapController extends BaseController {
|
|
|
1361
1367
|
result[snapId] = await this.#processRequestedSnap(origin, snapId, location, version);
|
|
1362
1368
|
}
|
|
1363
1369
|
// Once we finish all installs / updates, emit events.
|
|
1364
|
-
pendingInstalls.forEach((snapId) => this.messenger.publish(`SnapController:snapInstalled`, this
|
|
1365
|
-
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messenger.publish(`SnapController:snapUpdated`, this
|
|
1370
|
+
pendingInstalls.forEach((snapId) => this.messenger.publish(`SnapController:snapInstalled`, this.#getTruncatedSnapExpect(snapId), origin, false));
|
|
1371
|
+
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messenger.publish(`SnapController:snapUpdated`, this.#getTruncatedSnapExpect(snapId), oldVersion, origin, false));
|
|
1366
1372
|
snapIds.forEach((snapId) => this.#rollbackSnapshots.delete(snapId));
|
|
1367
1373
|
}
|
|
1368
1374
|
catch (error) {
|
|
1369
|
-
const installed = pendingInstalls.filter((snapId) => this.
|
|
1375
|
+
const installed = pendingInstalls.filter((snapId) => this.hasSnap(snapId));
|
|
1370
1376
|
await this.removeSnaps(installed);
|
|
1371
1377
|
const snapshottedSnaps = [...this.#rollbackSnapshots.keys()];
|
|
1372
1378
|
const snapsToRollback = pendingUpdates
|
|
@@ -1388,7 +1394,7 @@ export class SnapController extends BaseController {
|
|
|
1388
1394
|
* @returns The resulting snap object, or an error if something went wrong.
|
|
1389
1395
|
*/
|
|
1390
1396
|
async #processRequestedSnap(origin, snapId, location, versionRange) {
|
|
1391
|
-
const existingSnap = this
|
|
1397
|
+
const existingSnap = this.#getTruncatedSnap(snapId);
|
|
1392
1398
|
// For devX we always re-install local snaps.
|
|
1393
1399
|
if (existingSnap && !location.shouldAlwaysReload) {
|
|
1394
1400
|
if (satisfiesVersionRange(existingSnap.version, versionRange)) {
|
|
@@ -1409,7 +1415,7 @@ export class SnapController extends BaseController {
|
|
|
1409
1415
|
});
|
|
1410
1416
|
this.messenger.publish('SnapController:snapInstallStarted', snapId, origin, false);
|
|
1411
1417
|
// Existing snaps must be stopped before overwriting
|
|
1412
|
-
if (existingSnap && this.
|
|
1418
|
+
if (existingSnap && this.isSnapRunning(snapId)) {
|
|
1413
1419
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
1414
1420
|
}
|
|
1415
1421
|
// Existing snaps that should be re-installed should not maintain their existing permissions
|
|
@@ -1433,7 +1439,7 @@ export class SnapController extends BaseController {
|
|
|
1433
1439
|
snapId,
|
|
1434
1440
|
sourceCode,
|
|
1435
1441
|
});
|
|
1436
|
-
const truncated = this
|
|
1442
|
+
const truncated = this.#getTruncatedSnapExpect(snapId);
|
|
1437
1443
|
this.#updateApproval(pendingApproval.id, {
|
|
1438
1444
|
loading: false,
|
|
1439
1445
|
type: SNAP_APPROVAL_INSTALL,
|
|
@@ -1506,7 +1512,7 @@ export class SnapController extends BaseController {
|
|
|
1506
1512
|
this.#assertCanInstallSnaps();
|
|
1507
1513
|
}
|
|
1508
1514
|
await this.#ensureCanUsePlatform();
|
|
1509
|
-
const snap = this.
|
|
1515
|
+
const snap = this.getSnapExpect(snapId);
|
|
1510
1516
|
const { preinstalled, removable, hidden, hideSnapBranding } = snap;
|
|
1511
1517
|
if (preinstalled && !automaticUpdate) {
|
|
1512
1518
|
throw new Error('Preinstalled Snaps cannot be manually updated.');
|
|
@@ -1568,7 +1574,7 @@ export class SnapController extends BaseController {
|
|
|
1568
1574
|
assert(automaticUpdate);
|
|
1569
1575
|
approvedNewPermissions = newPermissions;
|
|
1570
1576
|
}
|
|
1571
|
-
if (this.
|
|
1577
|
+
if (this.isSnapRunning(snapId)) {
|
|
1572
1578
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
1573
1579
|
}
|
|
1574
1580
|
this.#transition(snapId, SnapStatusEvents.Update);
|
|
@@ -1608,7 +1614,7 @@ export class SnapController extends BaseController {
|
|
|
1608
1614
|
catch {
|
|
1609
1615
|
throw new Error(`Snap ${snapId} crashed with updated source code.`);
|
|
1610
1616
|
}
|
|
1611
|
-
const truncatedSnap = this
|
|
1617
|
+
const truncatedSnap = this.#getTruncatedSnapExpect(snapId);
|
|
1612
1618
|
if (pendingApproval) {
|
|
1613
1619
|
this.#updateApproval(pendingApproval.id, {
|
|
1614
1620
|
loading: false,
|
|
@@ -1632,7 +1638,7 @@ export class SnapController extends BaseController {
|
|
|
1632
1638
|
}
|
|
1633
1639
|
}
|
|
1634
1640
|
async #resolveAllowlistVersion(snapId, versionRange) {
|
|
1635
|
-
return await this.messenger.call('
|
|
1641
|
+
return await this.messenger.call('SnapRegistryController:resolveVersion', snapId, versionRange);
|
|
1636
1642
|
}
|
|
1637
1643
|
/**
|
|
1638
1644
|
* Returns a promise representing the complete installation of the requested snap.
|
|
@@ -1690,7 +1696,7 @@ export class SnapController extends BaseController {
|
|
|
1690
1696
|
}
|
|
1691
1697
|
async #startSnap(snapData) {
|
|
1692
1698
|
const { snapId } = snapData;
|
|
1693
|
-
if (this.
|
|
1699
|
+
if (this.isSnapRunning(snapId)) {
|
|
1694
1700
|
throw new Error(`Snap "${snapId}" is already started.`);
|
|
1695
1701
|
}
|
|
1696
1702
|
try {
|
|
@@ -1933,7 +1939,7 @@ export class SnapController extends BaseController {
|
|
|
1933
1939
|
*/
|
|
1934
1940
|
async handleRequest({ snapId, origin, handler: handlerType, request: rawRequest, }) {
|
|
1935
1941
|
await this.#ensureCanUsePlatform();
|
|
1936
|
-
const snap = this.
|
|
1942
|
+
const snap = this.getSnap(snapId);
|
|
1937
1943
|
assert(snap, `The Snap "${snapId}" is not installed. Please install it before invoking it.`);
|
|
1938
1944
|
assert(origin === METAMASK_ORIGIN || isValidUrl(origin), "'origin' must be a valid URL or 'metamask'.");
|
|
1939
1945
|
const request = {
|
|
@@ -1980,7 +1986,7 @@ export class SnapController extends BaseController {
|
|
|
1980
1986
|
if (runtime.stopPromise) {
|
|
1981
1987
|
await runtime.stopPromise;
|
|
1982
1988
|
}
|
|
1983
|
-
if (!this.
|
|
1989
|
+
if (!this.isSnapRunning(snapId)) {
|
|
1984
1990
|
if (!runtime.startPromise) {
|
|
1985
1991
|
runtime.startPromise = this.startSnap(snapId);
|
|
1986
1992
|
}
|
|
@@ -1999,7 +2005,7 @@ export class SnapController extends BaseController {
|
|
|
1999
2005
|
try {
|
|
2000
2006
|
const result = await withTimeout(handleRpcRequestPromise, timer);
|
|
2001
2007
|
if (result === hasTimedOut) {
|
|
2002
|
-
const stopping = runtime.stopPromise !== null || !this.
|
|
2008
|
+
const stopping = runtime.stopPromise !== null || !this.isSnapRunning(snapId);
|
|
2003
2009
|
throw new Error(stopping
|
|
2004
2010
|
? `${snapId} was stopped and the request was cancelled. This is likely because the Snap crashed.`
|
|
2005
2011
|
: `${snapId} failed to respond to the request in time.`);
|
|
@@ -2020,7 +2026,7 @@ export class SnapController extends BaseController {
|
|
|
2020
2026
|
// We flag the RPC request as finished early since termination may affect pending requests
|
|
2021
2027
|
this.#recordSnapRpcRequestFinish(snapId, transformedRequest.id, handlerType, origin, false);
|
|
2022
2028
|
const [jsonRpcError, handled] = unwrapError(error);
|
|
2023
|
-
const stopping = runtime.stopPromise !== null || !this.
|
|
2029
|
+
const stopping = runtime.stopPromise !== null || !this.isSnapRunning(snapId);
|
|
2024
2030
|
if (!handled) {
|
|
2025
2031
|
if (!stopping) {
|
|
2026
2032
|
logError(`"${snapId}" crashed due to an unhandled error:`, jsonRpcError);
|
|
@@ -2283,7 +2289,7 @@ export class SnapController extends BaseController {
|
|
|
2283
2289
|
if (runtime.pendingInboundRequests.length === 0) {
|
|
2284
2290
|
runtime.lastRequest = Date.now();
|
|
2285
2291
|
}
|
|
2286
|
-
const snap = this.
|
|
2292
|
+
const snap = this.getSnap(snapId);
|
|
2287
2293
|
if (isTrackableHandler(handlerType) && !snap?.preinstalled) {
|
|
2288
2294
|
try {
|
|
2289
2295
|
this.#trackSnapExport(snapId, handlerType, success, origin);
|
|
@@ -2339,7 +2345,7 @@ export class SnapController extends BaseController {
|
|
|
2339
2345
|
}
|
|
2340
2346
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
2341
2347
|
// Always set to stopped even if it wasn't running initially
|
|
2342
|
-
if (this.
|
|
2348
|
+
if (this.getSnap(snapId)?.status !== SnapStatus.Stopped) {
|
|
2343
2349
|
this.#transition(snapId, SnapStatusEvents.Stop);
|
|
2344
2350
|
}
|
|
2345
2351
|
const { statePatches, permissions, previousInitialConnections, newInitialConnections, previousSourceCode, } = rollbackSnapshot;
|
|
@@ -2353,7 +2359,7 @@ export class SnapController extends BaseController {
|
|
|
2353
2359
|
}
|
|
2354
2360
|
// Reset snap status, as we may have been in another state when we stored state patches
|
|
2355
2361
|
// But now we are 100% in a stopped state
|
|
2356
|
-
if (this.
|
|
2362
|
+
if (this.getSnap(snapId)?.status !== SnapStatus.Stopped) {
|
|
2357
2363
|
this.update((state) => {
|
|
2358
2364
|
state.snaps[snapId].status = SnapStatus.Stopped;
|
|
2359
2365
|
});
|
|
@@ -2366,7 +2372,7 @@ export class SnapController extends BaseController {
|
|
|
2366
2372
|
});
|
|
2367
2373
|
// Calling this in reverse order to undo the changes
|
|
2368
2374
|
this.#handleInitialConnections(snapId, newInitialConnections ?? null, previousInitialConnections ?? {});
|
|
2369
|
-
const truncatedSnap = this
|
|
2375
|
+
const truncatedSnap = this.#getTruncatedSnapExpect(snapId);
|
|
2370
2376
|
this.messenger.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
2371
2377
|
this.#rollbackSnapshots.delete(snapId);
|
|
2372
2378
|
}
|
|
@@ -2393,7 +2399,7 @@ export class SnapController extends BaseController {
|
|
|
2393
2399
|
if (this.#snapsRuntimeData.has(snapId)) {
|
|
2394
2400
|
return;
|
|
2395
2401
|
}
|
|
2396
|
-
const snap = this.
|
|
2402
|
+
const snap = this.getSnap(snapId);
|
|
2397
2403
|
const interpreter = interpret(this.#statusMachine);
|
|
2398
2404
|
interpreter.start({
|
|
2399
2405
|
context: { snapId },
|
|
@@ -2408,7 +2414,6 @@ export class SnapController extends BaseController {
|
|
|
2408
2414
|
installPromise: null,
|
|
2409
2415
|
encryptionKey: null,
|
|
2410
2416
|
encryptionSalt: null,
|
|
2411
|
-
activeReferences: 0,
|
|
2412
2417
|
pendingInboundRequests: [],
|
|
2413
2418
|
pendingOutboundRequests: 0,
|
|
2414
2419
|
interpreter,
|
|
@@ -2519,7 +2524,7 @@ export class SnapController extends BaseController {
|
|
|
2519
2524
|
* @returns `true` if validation checks pass and `false` if they do not.
|
|
2520
2525
|
*/
|
|
2521
2526
|
#isValidUpdate(snapId, newVersionRange) {
|
|
2522
|
-
const existingSnap = this.
|
|
2527
|
+
const existingSnap = this.getSnapExpect(snapId);
|
|
2523
2528
|
if (satisfiesVersionRange(existingSnap.version, newVersionRange)) {
|
|
2524
2529
|
return false;
|
|
2525
2530
|
}
|