@metamask/snaps-controllers 0.29.0 → 0.31.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/dist/cronjob/CronjobController.js +11 -8
- package/dist/cronjob/CronjobController.js.map +1 -1
- package/dist/fsm.js +5 -5
- package/dist/fsm.js.map +1 -1
- package/dist/multichain/MultiChainController.js +12 -20
- package/dist/multichain/MultiChainController.js.map +1 -1
- package/dist/multichain/matching.js +3 -4
- package/dist/multichain/matching.js.map +1 -1
- package/dist/services/iframe/IframeExecutionService.js +1 -2
- package/dist/services/iframe/IframeExecutionService.js.map +1 -1
- package/dist/snaps/RequestQueue.js +3 -6
- package/dist/snaps/RequestQueue.js.map +1 -1
- package/dist/snaps/SnapController.d.ts +7 -5
- package/dist/snaps/SnapController.js +253 -171
- package/dist/snaps/SnapController.js.map +1 -1
- package/dist/snaps/endowments/cronjob.js +2 -3
- package/dist/snaps/endowments/cronjob.js.map +1 -1
- package/dist/snaps/endowments/enum.d.ts +2 -1
- package/dist/snaps/endowments/enum.js +1 -0
- package/dist/snaps/endowments/enum.js.map +1 -1
- package/dist/snaps/endowments/index.d.ts +9 -0
- package/dist/snaps/endowments/index.js +8 -1
- package/dist/snaps/endowments/index.js.map +1 -1
- package/dist/snaps/endowments/keyring.js +3 -4
- package/dist/snaps/endowments/keyring.js.map +1 -1
- package/dist/snaps/endowments/rpc.js +2 -2
- package/dist/snaps/endowments/rpc.js.map +1 -1
- package/dist/snaps/endowments/transaction-insight.js +4 -5
- package/dist/snaps/endowments/transaction-insight.js.map +1 -1
- package/dist/snaps/endowments/web-assembly.d.ts +13 -0
- package/dist/snaps/endowments/web-assembly.js +30 -0
- package/dist/snaps/endowments/web-assembly.js.map +1 -0
- package/dist/snaps/location/http.js +9 -3
- package/dist/snaps/location/http.js.map +1 -1
- package/dist/snaps/location/local.js +1 -1
- package/dist/snaps/location/local.js.map +1 -1
- package/dist/snaps/location/location.js +2 -3
- package/dist/snaps/location/location.js.map +1 -1
- package/dist/snaps/location/npm.js +11 -8
- package/dist/snaps/location/npm.js.map +1 -1
- package/dist/snaps/registry/json.js +5 -7
- package/dist/snaps/registry/json.js.map +1 -1
- package/package.json +35 -15
- package/dist/services/iframe/test/fixJSDOMPostMessageEventSource.d.ts +0 -3
- package/dist/services/iframe/test/fixJSDOMPostMessageEventSource.js +0 -34
- package/dist/services/iframe/test/fixJSDOMPostMessageEventSource.js.map +0 -1
|
@@ -10,20 +10,9 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
11
11
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
12
12
|
};
|
|
13
|
-
var
|
|
14
|
-
var t = {};
|
|
15
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
16
|
-
t[p] = s[p];
|
|
17
|
-
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
18
|
-
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
19
|
-
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
20
|
-
t[p[i]] = s[p[i]];
|
|
21
|
-
}
|
|
22
|
-
return t;
|
|
23
|
-
};
|
|
24
|
-
var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_excludedPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_registry, _SnapController_maxIdleTime, _SnapController_detectSnapLocation, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsInstallAllowed, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_removeSnapFromSubjects, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchSnap, _SnapController_processSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isValidUpdate;
|
|
13
|
+
var _SnapController_instances, _SnapController_closeAllConnections, _SnapController_environmentEndowmentPermissions, _SnapController_excludedPermissions, _SnapController_featureFlags, _SnapController_fetchFunction, _SnapController_idleTimeCheckInterval, _SnapController_registry, _SnapController_maxIdleTime, _SnapController_detectSnapLocation, _SnapController_rollbackSnapshots, _SnapController_timeoutForLastRequestStatus, _SnapController_statusMachine, _SnapController_initializeStateMachine, _SnapController_registerMessageHandlers, _SnapController_pollForLastRequestStatus, _SnapController_blockSnap, _SnapController_unblockSnap, _SnapController_assertIsInstallAllowed, _SnapController_stopSnapsLastRequestPastMax, _SnapController_transition, _SnapController_terminateSnap, _SnapController_removeSnapFromSubjects, _SnapController_createApproval, _SnapController_updateApproval, _SnapController_add, _SnapController_startSnap, _SnapController_getEndowments, _SnapController_set, _SnapController_fetchSnap, _SnapController_processSnapPermissions, _SnapController_validateSnapPermissions, _SnapController_getRpcRequestHandler, _SnapController_executeWithTimeout, _SnapController_recordSnapRpcRequestStart, _SnapController_recordSnapRpcRequestFinish, _SnapController_getRollbackSnapshot, _SnapController_createRollbackSnapshot, _SnapController_rollbackSnap, _SnapController_rollbackSnaps, _SnapController_getRuntime, _SnapController_getRuntimeExpect, _SnapController_setupRuntime, _SnapController_calculatePermissionsChange, _SnapController_isValidUpdate;
|
|
25
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.SnapController = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
|
|
15
|
+
exports.SnapController = exports.SNAP_APPROVAL_RESULT = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
|
|
27
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
28
17
|
const rpc_methods_1 = require("@metamask/rpc-methods");
|
|
29
18
|
const snaps_utils_1 = require("@metamask/snaps-utils");
|
|
@@ -45,6 +34,7 @@ exports.controllerName = 'SnapController';
|
|
|
45
34
|
// TODO: Figure out how to name these
|
|
46
35
|
exports.SNAP_APPROVAL_INSTALL = 'wallet_installSnap';
|
|
47
36
|
exports.SNAP_APPROVAL_UPDATE = 'wallet_updateSnap';
|
|
37
|
+
exports.SNAP_APPROVAL_RESULT = 'wallet_installSnapResult';
|
|
48
38
|
const TRUNCATED_SNAP_PROPERTIES = new Set([
|
|
49
39
|
'initialPermissions',
|
|
50
40
|
'id',
|
|
@@ -82,7 +72,6 @@ const name = 'SnapController';
|
|
|
82
72
|
*/
|
|
83
73
|
class SnapController extends base_controller_1.BaseControllerV2 {
|
|
84
74
|
constructor({ closeAllConnections, messenger, state, environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), registry = new registry_1.JsonSnapsRegistry(), maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(globalThis), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, }) {
|
|
85
|
-
var _a, _b;
|
|
86
75
|
super({
|
|
87
76
|
messenger,
|
|
88
77
|
metadata: {
|
|
@@ -103,9 +92,12 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
103
92
|
persist: (snaps) => {
|
|
104
93
|
return Object.values(snaps)
|
|
105
94
|
.map((snap) => {
|
|
106
|
-
return
|
|
95
|
+
return {
|
|
96
|
+
...snap,
|
|
97
|
+
sourceCode: __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snap.id).sourceCode,
|
|
107
98
|
// At the time state is rehydrated, no snap will be running.
|
|
108
|
-
status: snaps_utils_1.SnapStatus.Stopped
|
|
99
|
+
status: snaps_utils_1.SnapStatus.Stopped,
|
|
100
|
+
};
|
|
109
101
|
})
|
|
110
102
|
.reduce((memo, snap) => {
|
|
111
103
|
memo[snap.id] = snap;
|
|
@@ -116,12 +108,18 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
116
108
|
},
|
|
117
109
|
},
|
|
118
110
|
name,
|
|
119
|
-
state:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
111
|
+
state: {
|
|
112
|
+
...defaultState,
|
|
113
|
+
...{
|
|
114
|
+
...state,
|
|
115
|
+
snaps: Object.values(state?.snaps ?? {}).reduce((memo, snap) => {
|
|
116
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
117
|
+
const { sourceCode, ...rest } = snap;
|
|
118
|
+
memo[snap.id] = rest;
|
|
119
|
+
return memo;
|
|
120
|
+
}, {}),
|
|
121
|
+
},
|
|
122
|
+
},
|
|
125
123
|
});
|
|
126
124
|
_SnapController_instances.add(this);
|
|
127
125
|
_SnapController_closeAllConnections.set(this, void 0);
|
|
@@ -159,13 +157,10 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
159
157
|
/* eslint-enable @typescript-eslint/unbound-method */
|
|
160
158
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_initializeStateMachine).call(this);
|
|
161
159
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_registerMessageHandlers).call(this);
|
|
162
|
-
Object.values(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
state: (_b = (_a = state === null || state === void 0 ? void 0 : state.snapStates) === null || _a === void 0 ? void 0 : _a[snap.id]) !== null && _b !== void 0 ? _b : null,
|
|
167
|
-
});
|
|
168
|
-
});
|
|
160
|
+
Object.values(state?.snaps ?? {}).forEach((snap) => __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_setupRuntime).call(this, snap.id, {
|
|
161
|
+
sourceCode: snap.sourceCode,
|
|
162
|
+
state: state?.snapStates?.[snap.id] ?? null,
|
|
163
|
+
}));
|
|
169
164
|
}
|
|
170
165
|
/**
|
|
171
166
|
* Checks all installed snaps against the block list and
|
|
@@ -388,7 +383,10 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
388
383
|
addSnapError(snapError) {
|
|
389
384
|
this.update((state) => {
|
|
390
385
|
const id = (0, nanoid_1.nanoid)();
|
|
391
|
-
state.snapErrors[id] =
|
|
386
|
+
state.snapErrors[id] = {
|
|
387
|
+
...snapError,
|
|
388
|
+
internalID: id,
|
|
389
|
+
};
|
|
392
390
|
});
|
|
393
391
|
}
|
|
394
392
|
/**
|
|
@@ -419,7 +417,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
419
417
|
*/
|
|
420
418
|
async getSnapState(snapId) {
|
|
421
419
|
const { state } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
422
|
-
return state
|
|
420
|
+
return state ?? null;
|
|
423
421
|
}
|
|
424
422
|
/**
|
|
425
423
|
* Completely clear the controller's state: delete all associated data,
|
|
@@ -517,13 +515,12 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
517
515
|
* @returns The serialized permitted snaps for the origin.
|
|
518
516
|
*/
|
|
519
517
|
getPermittedSnaps(origin) {
|
|
520
|
-
|
|
521
|
-
const
|
|
522
|
-
const snaps = (_e = (_d = (_c = (_b = permissions[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]) === null || _b === void 0 ? void 0 : _b.caveats) === null || _c === void 0 ? void 0 : _c.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds)) === null || _d === void 0 ? void 0 : _d.value) !== null && _e !== void 0 ? _e : {};
|
|
518
|
+
const permissions = this.messagingSystem.call('PermissionController:getPermissions', origin) ?? {};
|
|
519
|
+
const snaps = permissions[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds)?.value ?? {};
|
|
523
520
|
return Object.keys(snaps).reduce((permittedSnaps, snapId) => {
|
|
524
521
|
const snap = this.get(snapId);
|
|
525
522
|
const truncatedSnap = this.getTruncated(snapId);
|
|
526
|
-
if (truncatedSnap &&
|
|
523
|
+
if (truncatedSnap && snap?.status !== snaps_utils_1.SnapStatus.Installing) {
|
|
527
524
|
permittedSnaps[snapId] = truncatedSnap;
|
|
528
525
|
}
|
|
529
526
|
return permittedSnaps;
|
|
@@ -542,12 +539,11 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
542
539
|
async installSnaps(origin, requestedSnaps) {
|
|
543
540
|
const result = {};
|
|
544
541
|
const snapIds = Object.keys(requestedSnaps);
|
|
545
|
-
|
|
546
|
-
const
|
|
547
|
-
// Non-existing snaps will need to be installed
|
|
548
|
-
const pendingInstalls = snapIds.filter((snapId) => !pendingUpdates.includes(snapId));
|
|
542
|
+
const pendingUpdates = [];
|
|
543
|
+
const pendingInstalls = [];
|
|
549
544
|
try {
|
|
550
545
|
for (const [snapId, { version: rawVersion }] of Object.entries(requestedSnaps)) {
|
|
546
|
+
(0, snaps_utils_1.assertIsValidSnapId)(snapId);
|
|
551
547
|
const [error, version] = (0, snaps_utils_1.resolveVersionRange)(rawVersion);
|
|
552
548
|
if (error) {
|
|
553
549
|
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`The "version" field must be a valid SemVer version range if specified. Received: "${rawVersion}".`);
|
|
@@ -556,8 +552,16 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
556
552
|
if (!(0, snaps_utils_1.isSnapPermitted)(permissions, snapId)) {
|
|
557
553
|
throw eth_rpc_errors_1.ethErrors.provider.unauthorized(`Not authorized to install snap "${snapId}". Request the permission for the snap before attempting to install it.`);
|
|
558
554
|
}
|
|
559
|
-
const
|
|
555
|
+
const location = __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, {
|
|
556
|
+
versionRange: version,
|
|
557
|
+
fetch: __classPrivateFieldGet(this, _SnapController_fetchFunction, "f"),
|
|
558
|
+
allowLocal: __classPrivateFieldGet(this, _SnapController_featureFlags, "f").allowLocalSnaps,
|
|
559
|
+
});
|
|
560
|
+
// Existing snaps may need to be updated, unless they should be re-installed (e.g. local snaps)
|
|
561
|
+
// Everything else is treated as an install
|
|
562
|
+
const isUpdate = this.has(snapId) && !location.shouldAlwaysReload;
|
|
560
563
|
if (isUpdate && __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_isValidUpdate).call(this, snapId, version)) {
|
|
564
|
+
pendingUpdates.push(snapId);
|
|
561
565
|
let rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
562
566
|
if (rollbackSnapshot === undefined) {
|
|
563
567
|
const prevSourceCode = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId).sourceCode;
|
|
@@ -569,7 +573,10 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
569
573
|
throw new Error('This snap is already being updated.');
|
|
570
574
|
}
|
|
571
575
|
}
|
|
572
|
-
|
|
576
|
+
else if (!isUpdate) {
|
|
577
|
+
pendingInstalls.push(snapId);
|
|
578
|
+
}
|
|
579
|
+
result[snapId] = await this.processRequestedSnap(origin, snapId, location, version);
|
|
573
580
|
}
|
|
574
581
|
snapIds.forEach((snapId) => __classPrivateFieldGet(this, _SnapController_rollbackSnapshots, "f").delete(snapId));
|
|
575
582
|
}
|
|
@@ -589,16 +596,11 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
589
596
|
*
|
|
590
597
|
* @param origin - The origin requesting the snap.
|
|
591
598
|
* @param snapId - The id of the snap.
|
|
599
|
+
* @param location - The location implementation of the snap.
|
|
592
600
|
* @param versionRange - The semver range of the snap to install.
|
|
593
601
|
* @returns The resulting snap object, or an error if something went wrong.
|
|
594
602
|
*/
|
|
595
|
-
async processRequestedSnap(origin, snapId, versionRange) {
|
|
596
|
-
(0, snaps_utils_1.validateSnapId)(snapId);
|
|
597
|
-
const location = __classPrivateFieldGet(this, _SnapController_detectSnapLocation, "f").call(this, snapId, {
|
|
598
|
-
versionRange,
|
|
599
|
-
fetch: __classPrivateFieldGet(this, _SnapController_fetchFunction, "f"),
|
|
600
|
-
allowLocal: __classPrivateFieldGet(this, _SnapController_featureFlags, "f").allowLocalSnaps,
|
|
601
|
-
});
|
|
603
|
+
async processRequestedSnap(origin, snapId, location, versionRange) {
|
|
602
604
|
const existingSnap = this.getTruncated(snapId);
|
|
603
605
|
// For devX we always re-install local snaps.
|
|
604
606
|
if (existingSnap && !location.shouldAlwaysReload) {
|
|
@@ -606,35 +608,50 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
606
608
|
return existingSnap;
|
|
607
609
|
}
|
|
608
610
|
if (__classPrivateFieldGet(this, _SnapController_featureFlags, "f").dappsCanUpdateSnaps === true) {
|
|
609
|
-
|
|
610
|
-
if (updateResult === null) {
|
|
611
|
-
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Snap "${snapId}@${existingSnap.version}" is already installed. Couldn't update to a version inside requested "${versionRange}" range.`);
|
|
612
|
-
}
|
|
613
|
-
return updateResult;
|
|
611
|
+
return await this.updateSnap(origin, snapId, location, versionRange);
|
|
614
612
|
}
|
|
615
613
|
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Version mismatch with already installed snap. ${snapId}@${existingSnap.version} doesn't satisfy requested version ${versionRange}.`);
|
|
616
614
|
}
|
|
615
|
+
let pendingApproval = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_createApproval).call(this, {
|
|
616
|
+
origin,
|
|
617
|
+
snapId,
|
|
618
|
+
type: exports.SNAP_APPROVAL_INSTALL,
|
|
619
|
+
});
|
|
617
620
|
// Existing snaps must be stopped before overwriting
|
|
618
621
|
if (existingSnap && this.isRunning(snapId)) {
|
|
619
622
|
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
620
623
|
}
|
|
624
|
+
// Existing snaps that should be re-installed should not maintain their existing permissions
|
|
625
|
+
if (existingSnap && location.shouldAlwaysReload) {
|
|
626
|
+
this.revokeAllSnapPermissions(snapId);
|
|
627
|
+
}
|
|
621
628
|
try {
|
|
622
629
|
const { sourceCode } = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_add).call(this, {
|
|
623
630
|
origin,
|
|
624
631
|
id: snapId,
|
|
625
632
|
location,
|
|
626
633
|
});
|
|
627
|
-
await this.authorize(
|
|
634
|
+
await this.authorize(snapId, pendingApproval);
|
|
635
|
+
pendingApproval = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_createApproval).call(this, {
|
|
636
|
+
origin,
|
|
637
|
+
snapId,
|
|
638
|
+
type: exports.SNAP_APPROVAL_RESULT,
|
|
639
|
+
});
|
|
628
640
|
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, {
|
|
629
641
|
snapId,
|
|
630
642
|
sourceCode,
|
|
631
643
|
});
|
|
632
644
|
const truncated = this.getTruncatedExpect(snapId);
|
|
645
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, { loading: false });
|
|
633
646
|
this.messagingSystem.publish(`SnapController:snapInstalled`, truncated);
|
|
634
647
|
return truncated;
|
|
635
648
|
}
|
|
636
649
|
catch (error) {
|
|
637
650
|
(0, snaps_utils_1.logError)(`Error when adding snap.`, error);
|
|
651
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
|
|
652
|
+
loading: false,
|
|
653
|
+
error: error instanceof Error ? error.message : error.toString(),
|
|
654
|
+
});
|
|
638
655
|
throw error;
|
|
639
656
|
}
|
|
640
657
|
}
|
|
@@ -652,88 +669,102 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
652
669
|
*
|
|
653
670
|
* @param origin - The origin requesting the snap update.
|
|
654
671
|
* @param snapId - The id of the Snap to be updated.
|
|
655
|
-
* @param location -
|
|
672
|
+
* @param location - The location implementation of the snap.
|
|
656
673
|
* @param newVersionRange - A semver version range in which the maximum version will be chosen.
|
|
657
674
|
* @returns The snap metadata if updated, `null` otherwise.
|
|
658
675
|
*/
|
|
659
676
|
async updateSnap(origin, snapId, location, newVersionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION) {
|
|
660
|
-
var _a;
|
|
661
|
-
const snap = this.getExpect(snapId);
|
|
662
677
|
if (!(0, utils_1.isValidSemVerRange)(newVersionRange)) {
|
|
663
678
|
throw new Error(`Received invalid snap version range: "${newVersionRange}".`);
|
|
664
679
|
}
|
|
665
|
-
|
|
666
|
-
const newVersion = newSnap.manifest.result.version;
|
|
667
|
-
if (!(0, utils_1.gtVersion)(newVersion, snap.version)) {
|
|
668
|
-
(0, snaps_utils_1.logWarning)(`Tried updating snap "${snapId}" within "${newVersionRange}" version range, but newer version "${snap.version}" is already installed`);
|
|
669
|
-
return null;
|
|
670
|
-
}
|
|
671
|
-
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsInstallAllowed).call(this, snapId, {
|
|
672
|
-
version: newVersion,
|
|
673
|
-
checksum: newSnap.manifest.result.source.shasum,
|
|
674
|
-
});
|
|
675
|
-
const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.result.initialPermissions);
|
|
676
|
-
const { newPermissions, unusedPermissions, approvedPermissions } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
|
|
677
|
-
const id = (0, nanoid_1.nanoid)();
|
|
678
|
-
const _b = (await this.messagingSystem.call('ApprovalController:addRequest', {
|
|
680
|
+
let pendingApproval = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_createApproval).call(this, {
|
|
679
681
|
origin,
|
|
680
|
-
|
|
682
|
+
snapId,
|
|
681
683
|
type: exports.SNAP_APPROVAL_UPDATE,
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
684
|
+
});
|
|
685
|
+
try {
|
|
686
|
+
const snap = this.getExpect(snapId);
|
|
687
|
+
const newSnap = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_fetchSnap).call(this, snapId, location);
|
|
688
|
+
const newVersion = newSnap.manifest.result.version;
|
|
689
|
+
if (!(0, utils_1.gtVersion)(newVersion, snap.version)) {
|
|
690
|
+
throw eth_rpc_errors_1.ethErrors.rpc.invalidParams(`Snap "${snapId}@${snap.version}" is already installed. Couldn't update to a version inside requested "${newVersionRange}" range.`);
|
|
691
|
+
}
|
|
692
|
+
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_assertIsInstallAllowed).call(this, snapId, {
|
|
693
|
+
version: newVersion,
|
|
694
|
+
checksum: newSnap.manifest.result.source.shasum,
|
|
695
|
+
});
|
|
696
|
+
const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, newSnap.manifest.result.initialPermissions);
|
|
697
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_validateSnapPermissions).call(this, processedPermissions);
|
|
698
|
+
const { newPermissions, unusedPermissions, approvedPermissions } = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_calculatePermissionsChange).call(this, snapId, processedPermissions);
|
|
699
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
|
|
685
700
|
permissions: newPermissions,
|
|
686
|
-
snapId,
|
|
687
701
|
newVersion: newSnap.manifest.result.version,
|
|
688
702
|
newPermissions,
|
|
689
703
|
approvedPermissions,
|
|
690
704
|
unusedPermissions,
|
|
691
|
-
|
|
692
|
-
}, true)), { permissions: approvedNewPermissions } = _b, requestData = __rest(_b, ["permissions"]);
|
|
693
|
-
if (this.isRunning(snapId)) {
|
|
694
|
-
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
695
|
-
}
|
|
696
|
-
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transition).call(this, snapId, snaps_utils_1.SnapStatusEvents.Update);
|
|
697
|
-
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, {
|
|
698
|
-
origin,
|
|
699
|
-
id: snapId,
|
|
700
|
-
manifest: newSnap.manifest,
|
|
701
|
-
files: newSnap.files,
|
|
702
|
-
versionRange: newVersionRange,
|
|
703
|
-
isUpdate: true,
|
|
704
|
-
});
|
|
705
|
-
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
706
|
-
if ((0, utils_1.isNonEmptyArray)(unusedPermissionsKeys)) {
|
|
707
|
-
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
708
|
-
[snapId]: unusedPermissionsKeys,
|
|
705
|
+
loading: false,
|
|
709
706
|
});
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
requestData,
|
|
707
|
+
const { permissions: approvedNewPermissions, ...requestData } = (await pendingApproval.promise);
|
|
708
|
+
pendingApproval = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_createApproval).call(this, {
|
|
709
|
+
origin,
|
|
710
|
+
snapId,
|
|
711
|
+
type: exports.SNAP_APPROVAL_RESULT,
|
|
716
712
|
});
|
|
713
|
+
if (this.isRunning(snapId)) {
|
|
714
|
+
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
715
|
+
}
|
|
716
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transition).call(this, snapId, snaps_utils_1.SnapStatusEvents.Update);
|
|
717
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, {
|
|
718
|
+
origin,
|
|
719
|
+
id: snapId,
|
|
720
|
+
manifest: newSnap.manifest,
|
|
721
|
+
files: newSnap.files,
|
|
722
|
+
versionRange: newVersionRange,
|
|
723
|
+
isUpdate: true,
|
|
724
|
+
});
|
|
725
|
+
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
726
|
+
if ((0, utils_1.isNonEmptyArray)(unusedPermissionsKeys)) {
|
|
727
|
+
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
728
|
+
[snapId]: unusedPermissionsKeys,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedNewPermissions))) {
|
|
732
|
+
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
733
|
+
approvedPermissions: approvedNewPermissions,
|
|
734
|
+
subject: { origin: snapId },
|
|
735
|
+
requestData,
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
const rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
739
|
+
if (rollbackSnapshot !== undefined) {
|
|
740
|
+
rollbackSnapshot.permissions.revoked = unusedPermissions;
|
|
741
|
+
rollbackSnapshot.permissions.granted = Object.keys(approvedNewPermissions);
|
|
742
|
+
rollbackSnapshot.permissions.requestData = requestData;
|
|
743
|
+
}
|
|
744
|
+
const normalizedSourcePath = (0, snaps_utils_1.normalizeRelative)(newSnap.manifest.result.source.location.npm.filePath);
|
|
745
|
+
const sourceCode = newSnap.files
|
|
746
|
+
.find((file) => file.path === normalizedSourcePath)
|
|
747
|
+
?.toString();
|
|
748
|
+
(0, utils_1.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
749
|
+
try {
|
|
750
|
+
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, { snapId, sourceCode });
|
|
751
|
+
}
|
|
752
|
+
catch {
|
|
753
|
+
throw new Error(`Snap ${snapId} crashed with updated source code.`);
|
|
754
|
+
}
|
|
755
|
+
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
756
|
+
this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version);
|
|
757
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, { loading: false });
|
|
758
|
+
return truncatedSnap;
|
|
717
759
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
const sourceCode = (_a = newSnap.files
|
|
726
|
-
.find((file) => file.path === normalizedSourcePath)) === null || _a === void 0 ? void 0 : _a.toString();
|
|
727
|
-
(0, utils_1.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
728
|
-
try {
|
|
729
|
-
await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_startSnap).call(this, { snapId, sourceCode });
|
|
730
|
-
}
|
|
731
|
-
catch (_c) {
|
|
732
|
-
throw new Error(`Snap ${snapId} crashed with updated source code.`);
|
|
760
|
+
catch (error) {
|
|
761
|
+
(0, snaps_utils_1.logError)(`Error when updating snap,`, error);
|
|
762
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
|
|
763
|
+
loading: false,
|
|
764
|
+
error: error instanceof Error ? error.message : error.toString(),
|
|
765
|
+
});
|
|
766
|
+
throw error;
|
|
733
767
|
}
|
|
734
|
-
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
735
|
-
this.messagingSystem.publish('SnapController:snapUpdated', truncatedSnap, snap.version);
|
|
736
|
-
return truncatedSnap;
|
|
737
768
|
}
|
|
738
769
|
/**
|
|
739
770
|
* Get metadata for the given snap ID.
|
|
@@ -751,36 +782,23 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
751
782
|
*
|
|
752
783
|
* This function is not hash private yet because of tests.
|
|
753
784
|
*
|
|
754
|
-
* @param origin - The origin of the install request.
|
|
755
785
|
* @param snapId - The id of the Snap.
|
|
786
|
+
* @param pendingApproval - Pending approval to update.
|
|
756
787
|
* @returns The snap's approvedPermissions.
|
|
757
788
|
*/
|
|
758
|
-
async authorize(
|
|
789
|
+
async authorize(snapId, pendingApproval) {
|
|
759
790
|
(0, logging_1.log)(`Authorizing snap: ${snapId}`);
|
|
760
791
|
const snapsState = this.state.snaps;
|
|
761
792
|
const snap = snapsState[snapId];
|
|
762
793
|
const { initialPermissions } = snap;
|
|
763
794
|
try {
|
|
764
795
|
const processedPermissions = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_processSnapPermissions).call(this, initialPermissions);
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
(0, utils_1.assert)(excludedPermissionErrors.length === 0, `One or more permissions are not allowed:\n${excludedPermissionErrors.join('\n')}`);
|
|
772
|
-
const id = (0, nanoid_1.nanoid)();
|
|
773
|
-
const _a = (await this.messagingSystem.call('ApprovalController:addRequest', {
|
|
774
|
-
origin,
|
|
775
|
-
id,
|
|
776
|
-
type: exports.SNAP_APPROVAL_INSTALL,
|
|
777
|
-
requestData: {
|
|
778
|
-
// Mirror previous installation metadata
|
|
779
|
-
metadata: { id, origin: snapId, dappOrigin: origin },
|
|
780
|
-
permissions: processedPermissions,
|
|
781
|
-
snapId,
|
|
782
|
-
},
|
|
783
|
-
}, true)), { permissions: approvedPermissions } = _a, requestData = __rest(_a, ["permissions"]);
|
|
796
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_validateSnapPermissions).call(this, processedPermissions);
|
|
797
|
+
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
|
|
798
|
+
loading: false,
|
|
799
|
+
permissions: processedPermissions,
|
|
800
|
+
});
|
|
801
|
+
const { permissions: approvedPermissions, ...requestData } = (await pendingApproval.promise);
|
|
784
802
|
if ((0, utils_1.isNonEmptyArray)(Object.keys(approvedPermissions))) {
|
|
785
803
|
this.messagingSystem.call('PermissionController:grantPermissions', {
|
|
786
804
|
approvedPermissions,
|
|
@@ -823,9 +841,9 @@ class SnapController extends base_controller_1.BaseControllerV2 {
|
|
|
823
841
|
}
|
|
824
842
|
if (permissionName === endowments_1.SnapEndowments.Rpc) {
|
|
825
843
|
const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
826
|
-
const isSnap =
|
|
844
|
+
const isSnap = subject?.subjectType === subject_metadata_controller_1.SubjectType.Snap;
|
|
827
845
|
const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
|
|
828
|
-
const rpcPermission = permissions
|
|
846
|
+
const rpcPermission = permissions?.[endowments_1.SnapEndowments.Rpc];
|
|
829
847
|
(0, utils_1.assert)(rpcPermission);
|
|
830
848
|
const origins = (0, rpc_1.getRpcCaveatOrigins)(rpcPermission);
|
|
831
849
|
(0, utils_1.assert)(origins);
|
|
@@ -951,13 +969,12 @@ async function _SnapController_blockSnap(snapId, blockedSnapInfo) {
|
|
|
951
969
|
});
|
|
952
970
|
this.messagingSystem.publish(`${exports.controllerName}:snapUnblocked`, snapId);
|
|
953
971
|
}, _SnapController_assertIsInstallAllowed = async function _SnapController_assertIsInstallAllowed(snapId, snapInfo) {
|
|
954
|
-
var _a, _b;
|
|
955
972
|
const results = await __classPrivateFieldGet(this, _SnapController_registry, "f").get({
|
|
956
973
|
[snapId]: snapInfo,
|
|
957
974
|
});
|
|
958
975
|
const result = results[snapId];
|
|
959
976
|
if (result.status === registry_1.SnapsRegistryStatus.Blocked) {
|
|
960
|
-
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The version is blocked. ${
|
|
977
|
+
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The version is blocked. ${result.reason?.explanation ?? ''}`);
|
|
961
978
|
}
|
|
962
979
|
else if (__classPrivateFieldGet(this, _SnapController_featureFlags, "f").requireAllowlist &&
|
|
963
980
|
result.status !== registry_1.SnapsRegistryStatus.Verified) {
|
|
@@ -989,18 +1006,53 @@ async function _SnapController_terminateSnap(snapId) {
|
|
|
989
1006
|
await this.messagingSystem.call('ExecutionService:terminateSnap', snapId);
|
|
990
1007
|
this.messagingSystem.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
991
1008
|
}, _SnapController_removeSnapFromSubjects = function _SnapController_removeSnapFromSubjects(snapId) {
|
|
992
|
-
var _a, _b, _c, _d;
|
|
993
1009
|
const subjects = this.messagingSystem.call('PermissionController:getSubjectNames');
|
|
994
1010
|
for (const subject of subjects) {
|
|
995
1011
|
const subjectPermissions = this.messagingSystem.call('PermissionController:getPermissions', subject);
|
|
996
|
-
const snapIdsCaveat = (
|
|
997
|
-
|
|
1012
|
+
const snapIdsCaveat = (subjectPermissions?.[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds) ??
|
|
1013
|
+
{});
|
|
1014
|
+
const caveatHasSnap = Boolean(snapIdsCaveat.value?.[snapId]);
|
|
998
1015
|
if (caveatHasSnap) {
|
|
999
|
-
const newCaveatValue =
|
|
1016
|
+
const newCaveatValue = {
|
|
1017
|
+
...snapIdsCaveat.value,
|
|
1018
|
+
};
|
|
1000
1019
|
delete newCaveatValue[snapId];
|
|
1001
|
-
|
|
1020
|
+
if (Object.keys(newCaveatValue).length > 0) {
|
|
1021
|
+
this.messagingSystem.call('PermissionController:updateCaveat', subject, rpc_methods_1.WALLET_SNAP_PERMISSION_KEY, snaps_utils_1.SnapCaveatType.SnapIds, newCaveatValue);
|
|
1022
|
+
}
|
|
1023
|
+
else {
|
|
1024
|
+
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1025
|
+
[subject]: [rpc_methods_1.WALLET_SNAP_PERMISSION_KEY],
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1002
1028
|
}
|
|
1003
1029
|
}
|
|
1030
|
+
}, _SnapController_createApproval = function _SnapController_createApproval({ origin, snapId, type, }) {
|
|
1031
|
+
const id = (0, nanoid_1.nanoid)();
|
|
1032
|
+
const promise = this.messagingSystem.call('ApprovalController:addRequest', {
|
|
1033
|
+
origin,
|
|
1034
|
+
id,
|
|
1035
|
+
type,
|
|
1036
|
+
requestData: {
|
|
1037
|
+
// Mirror previous installation metadata
|
|
1038
|
+
metadata: { id, origin: snapId, dappOrigin: origin },
|
|
1039
|
+
snapId,
|
|
1040
|
+
},
|
|
1041
|
+
requestState: {
|
|
1042
|
+
loading: true,
|
|
1043
|
+
},
|
|
1044
|
+
}, true);
|
|
1045
|
+
return { id, promise };
|
|
1046
|
+
}, _SnapController_updateApproval = function _SnapController_updateApproval(id, requestState) {
|
|
1047
|
+
try {
|
|
1048
|
+
this.messagingSystem.call('ApprovalController:updateRequestState', {
|
|
1049
|
+
id,
|
|
1050
|
+
requestState,
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
1053
|
+
catch {
|
|
1054
|
+
// Do nothing
|
|
1055
|
+
}
|
|
1004
1056
|
}, _SnapController_add =
|
|
1005
1057
|
/**
|
|
1006
1058
|
* Returns a promise representing the complete installation of the requested snap.
|
|
@@ -1013,7 +1065,6 @@ async function _SnapController_terminateSnap(snapId) {
|
|
|
1013
1065
|
*/
|
|
1014
1066
|
async function _SnapController_add(args) {
|
|
1015
1067
|
const { id: snapId, location } = args;
|
|
1016
|
-
(0, snaps_utils_1.validateSnapId)(snapId);
|
|
1017
1068
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_setupRuntime).call(this, snapId, { sourceCode: null, state: null });
|
|
1018
1069
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1019
1070
|
if (!runtime.installPromise) {
|
|
@@ -1026,7 +1077,11 @@ async function _SnapController_add(args) {
|
|
|
1026
1077
|
version: fetchedSnap.manifest.result.version,
|
|
1027
1078
|
checksum: fetchedSnap.manifest.result.source.shasum,
|
|
1028
1079
|
});
|
|
1029
|
-
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this,
|
|
1080
|
+
return __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_set).call(this, {
|
|
1081
|
+
...args,
|
|
1082
|
+
...fetchedSnap,
|
|
1083
|
+
id: snapId,
|
|
1084
|
+
});
|
|
1030
1085
|
})();
|
|
1031
1086
|
}
|
|
1032
1087
|
try {
|
|
@@ -1044,7 +1099,10 @@ async function _SnapController_add(args) {
|
|
|
1044
1099
|
throw new Error(`Snap "${snapId}" is already started.`);
|
|
1045
1100
|
}
|
|
1046
1101
|
try {
|
|
1047
|
-
const result = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_executeWithTimeout).call(this, snapId, this.messagingSystem.call('ExecutionService:executeSnap',
|
|
1102
|
+
const result = await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_executeWithTimeout).call(this, snapId, this.messagingSystem.call('ExecutionService:executeSnap', {
|
|
1103
|
+
...snapData,
|
|
1104
|
+
endowments: await __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getEndowments).call(this, snapId),
|
|
1105
|
+
}));
|
|
1048
1106
|
__classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_transition).call(this, snapId, snaps_utils_1.SnapStatusEvents.Start);
|
|
1049
1107
|
return result;
|
|
1050
1108
|
}
|
|
@@ -1091,7 +1149,6 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1091
1149
|
}
|
|
1092
1150
|
return dedupedEndowments;
|
|
1093
1151
|
}, _SnapController_set = function _SnapController_set(args) {
|
|
1094
|
-
var _a, _b;
|
|
1095
1152
|
const { id: snapId, origin, manifest, files, versionRange = snaps_utils_1.DEFAULT_REQUESTED_SNAP_VERSION, isUpdate = false, } = args;
|
|
1096
1153
|
(0, snaps_utils_1.assertIsSnapManifest)(manifest.result);
|
|
1097
1154
|
const { version } = manifest.result;
|
|
@@ -1101,15 +1158,16 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1101
1158
|
const normalizedSourcePath = (0, snaps_utils_1.normalizeRelative)(manifest.result.source.location.npm.filePath);
|
|
1102
1159
|
const { iconPath } = manifest.result.source.location.npm;
|
|
1103
1160
|
const normalizedIconPath = iconPath && (0, snaps_utils_1.normalizeRelative)(iconPath);
|
|
1104
|
-
const sourceCode =
|
|
1105
|
-
.find((file) => file.path === normalizedSourcePath)
|
|
1161
|
+
const sourceCode = files
|
|
1162
|
+
.find((file) => file.path === normalizedSourcePath)
|
|
1163
|
+
?.toString();
|
|
1106
1164
|
const svgIcon = normalizedIconPath
|
|
1107
1165
|
? files.find((file) => file.path === normalizedIconPath)
|
|
1108
1166
|
: undefined;
|
|
1109
1167
|
(0, utils_1.assert)(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
1110
1168
|
const snapsState = this.state.snaps;
|
|
1111
1169
|
const existingSnap = snapsState[snapId];
|
|
1112
|
-
const previousVersionHistory =
|
|
1170
|
+
const previousVersionHistory = existingSnap?.versionHistory ?? [];
|
|
1113
1171
|
const versionHistory = [
|
|
1114
1172
|
...previousVersionHistory,
|
|
1115
1173
|
{
|
|
@@ -1118,11 +1176,20 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1118
1176
|
origin,
|
|
1119
1177
|
},
|
|
1120
1178
|
];
|
|
1121
|
-
const snap =
|
|
1179
|
+
const snap = {
|
|
1180
|
+
// Restore relevant snap state if it exists
|
|
1181
|
+
...existingSnap,
|
|
1122
1182
|
// Note that the snap will be unblocked and enabled, regardless of its
|
|
1123
1183
|
// previous state.
|
|
1124
|
-
blocked: false,
|
|
1125
|
-
|
|
1184
|
+
blocked: false,
|
|
1185
|
+
enabled: true,
|
|
1186
|
+
id: snapId,
|
|
1187
|
+
initialPermissions: manifest.result.initialPermissions,
|
|
1188
|
+
manifest: manifest.result,
|
|
1189
|
+
status: __classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial,
|
|
1190
|
+
version,
|
|
1191
|
+
versionHistory,
|
|
1192
|
+
};
|
|
1126
1193
|
// If the snap was blocked, it isn't any longer
|
|
1127
1194
|
delete snap.blockInformation;
|
|
1128
1195
|
// store the snap back in state
|
|
@@ -1139,8 +1206,8 @@ async function _SnapController_getEndowments(snapId) {
|
|
|
1139
1206
|
}
|
|
1140
1207
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1141
1208
|
runtime.sourceCode = sourceCode;
|
|
1142
|
-
this.messagingSystem.publish(`SnapController:snapAdded`, snap, svgIcon
|
|
1143
|
-
return
|
|
1209
|
+
this.messagingSystem.publish(`SnapController:snapAdded`, snap, svgIcon?.toString());
|
|
1210
|
+
return { ...snap, sourceCode };
|
|
1144
1211
|
}, _SnapController_fetchSnap =
|
|
1145
1212
|
/**
|
|
1146
1213
|
* Fetches the manifest and source code of a snap.
|
|
@@ -1171,7 +1238,7 @@ async function _SnapController_fetchSnap(snapId, location) {
|
|
|
1171
1238
|
throw new Error(`Failed to fetch Snap "${snapId}": ${message}.`);
|
|
1172
1239
|
}
|
|
1173
1240
|
}, _SnapController_processSnapPermissions = function _SnapController_processSnapPermissions(initialPermissions) {
|
|
1174
|
-
return
|
|
1241
|
+
return Object.fromEntries(Object.entries(initialPermissions).map(([initialPermission, value]) => {
|
|
1175
1242
|
if ((0, utils_1.hasProperty)(rpc_methods_1.caveatMappers, initialPermission)) {
|
|
1176
1243
|
return [initialPermission, rpc_methods_1.caveatMappers[initialPermission](value)];
|
|
1177
1244
|
}
|
|
@@ -1187,6 +1254,14 @@ async function _SnapController_fetchSnap(snapId, location) {
|
|
|
1187
1254
|
value,
|
|
1188
1255
|
];
|
|
1189
1256
|
}));
|
|
1257
|
+
}, _SnapController_validateSnapPermissions = function _SnapController_validateSnapPermissions(processedPermissions) {
|
|
1258
|
+
const excludedPermissionErrors = Object.keys(processedPermissions).reduce((errors, permission) => {
|
|
1259
|
+
if ((0, utils_1.hasProperty)(__classPrivateFieldGet(this, _SnapController_excludedPermissions, "f"), permission)) {
|
|
1260
|
+
errors.push(__classPrivateFieldGet(this, _SnapController_excludedPermissions, "f")[permission]);
|
|
1261
|
+
}
|
|
1262
|
+
return errors;
|
|
1263
|
+
}, []);
|
|
1264
|
+
(0, utils_1.assert)(excludedPermissionErrors.length === 0, `One or more permissions are not allowed:\n${excludedPermissionErrors.join('\n')}`);
|
|
1190
1265
|
}, _SnapController_getRpcRequestHandler = function _SnapController_getRpcRequestHandler(snapId) {
|
|
1191
1266
|
const runtime = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRuntimeExpect).call(this, snapId);
|
|
1192
1267
|
const existingHandler = runtime.rpcHandler;
|
|
@@ -1227,7 +1302,7 @@ async function _SnapController_fetchSnap(snapId, location) {
|
|
|
1227
1302
|
}
|
|
1228
1303
|
let _request = request;
|
|
1229
1304
|
if (!(0, utils_1.hasProperty)(request, 'jsonrpc')) {
|
|
1230
|
-
_request =
|
|
1305
|
+
_request = { ...request, jsonrpc: '2.0' };
|
|
1231
1306
|
}
|
|
1232
1307
|
else if (request.jsonrpc !== '2.0') {
|
|
1233
1308
|
throw eth_rpc_errors_1.ethErrors.rpc.invalidRequest({
|
|
@@ -1269,7 +1344,7 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
|
1269
1344
|
(0, snaps_utils_1.logWarning)(`${endowments_1.SnapEndowments.LongRunning} will soon be deprecated. For more information please see https://github.com/MetaMask/snaps-monorepo/issues/945.`);
|
|
1270
1345
|
return promise;
|
|
1271
1346
|
}
|
|
1272
|
-
const result = await (0, utils_2.withTimeout)(promise, timer
|
|
1347
|
+
const result = await (0, utils_2.withTimeout)(promise, timer ?? this.maxRequestTime);
|
|
1273
1348
|
if (result === utils_2.hasTimedOut) {
|
|
1274
1349
|
throw new Error('The request timed out.');
|
|
1275
1350
|
}
|
|
@@ -1310,14 +1385,13 @@ async function _SnapController_executeWithTimeout(snapId, promise, timer) {
|
|
|
1310
1385
|
* @throws {@link Error}. If a snapshot does not exist.
|
|
1311
1386
|
*/
|
|
1312
1387
|
async function _SnapController_rollbackSnap(snapId) {
|
|
1313
|
-
var _a;
|
|
1314
1388
|
const rollbackSnapshot = __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_getRollbackSnapshot).call(this, snapId);
|
|
1315
1389
|
if (!rollbackSnapshot) {
|
|
1316
1390
|
throw new Error('A snapshot does not exist for this snap.');
|
|
1317
1391
|
}
|
|
1318
1392
|
await this.stopSnap(snapId, snaps_utils_1.SnapStatusEvents.Stop);
|
|
1319
1393
|
const { statePatches, sourceCode, permissions } = rollbackSnapshot;
|
|
1320
|
-
if (statePatches
|
|
1394
|
+
if (statePatches?.length) {
|
|
1321
1395
|
this.applyPatches(statePatches);
|
|
1322
1396
|
}
|
|
1323
1397
|
if (sourceCode) {
|
|
@@ -1331,7 +1405,7 @@ async function _SnapController_rollbackSnap(snapId) {
|
|
|
1331
1405
|
requestData: permissions.requestData,
|
|
1332
1406
|
});
|
|
1333
1407
|
}
|
|
1334
|
-
if (
|
|
1408
|
+
if (permissions.granted?.length) {
|
|
1335
1409
|
this.messagingSystem.call('PermissionController:revokePermissions', {
|
|
1336
1410
|
[snapId]: permissions.granted,
|
|
1337
1411
|
});
|
|
@@ -1357,7 +1431,6 @@ async function _SnapController_rollbackSnaps(snapIds) {
|
|
|
1357
1431
|
(0, utils_1.assert)(runtime !== undefined, new Error(`Snap "${snapId}" runtime data not found`));
|
|
1358
1432
|
return runtime;
|
|
1359
1433
|
}, _SnapController_setupRuntime = function _SnapController_setupRuntime(snapId, data) {
|
|
1360
|
-
var _a;
|
|
1361
1434
|
if (this.snapsRuntimeData.has(snapId)) {
|
|
1362
1435
|
return;
|
|
1363
1436
|
}
|
|
@@ -1365,13 +1438,22 @@ async function _SnapController_rollbackSnaps(snapIds) {
|
|
|
1365
1438
|
const interpreter = (0, fsm_1.interpret)(__classPrivateFieldGet(this, _SnapController_statusMachine, "f"));
|
|
1366
1439
|
interpreter.start({
|
|
1367
1440
|
context: { snapId },
|
|
1368
|
-
value:
|
|
1441
|
+
value: snap?.status ??
|
|
1442
|
+
__classPrivateFieldGet(this, _SnapController_statusMachine, "f").config.initial,
|
|
1369
1443
|
});
|
|
1370
1444
|
(0, fsm_2.forceStrict)(interpreter);
|
|
1371
|
-
this.snapsRuntimeData.set(snapId,
|
|
1445
|
+
this.snapsRuntimeData.set(snapId, {
|
|
1446
|
+
lastRequest: null,
|
|
1447
|
+
rpcHandler: null,
|
|
1448
|
+
installPromise: null,
|
|
1449
|
+
activeReferences: 0,
|
|
1450
|
+
pendingInboundRequests: [],
|
|
1451
|
+
pendingOutboundRequests: 0,
|
|
1452
|
+
interpreter,
|
|
1453
|
+
...data,
|
|
1454
|
+
});
|
|
1372
1455
|
}, _SnapController_calculatePermissionsChange = function _SnapController_calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
1373
|
-
|
|
1374
|
-
const oldPermissions = (_a = this.messagingSystem.call('PermissionController:getPermissions', snapId)) !== null && _a !== void 0 ? _a : {};
|
|
1456
|
+
const oldPermissions = this.messagingSystem.call('PermissionController:getPermissions', snapId) ?? {};
|
|
1375
1457
|
const newPermissions = (0, utils_2.setDiff)(desiredPermissionsSet, oldPermissions);
|
|
1376
1458
|
// TODO(ritave): The assumption that these are unused only holds so long as we do not
|
|
1377
1459
|
// permit dynamic permission requests.
|