@metamask/snaps-controllers 15.0.1 → 16.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 +20 -1
- package/dist/cronjob/CronjobController.cjs +17 -17
- package/dist/cronjob/CronjobController.cjs.map +1 -1
- package/dist/cronjob/CronjobController.d.cts +3 -2
- package/dist/cronjob/CronjobController.d.cts.map +1 -1
- package/dist/cronjob/CronjobController.d.mts +3 -2
- package/dist/cronjob/CronjobController.d.mts.map +1 -1
- package/dist/cronjob/CronjobController.mjs +17 -17
- package/dist/cronjob/CronjobController.mjs.map +1 -1
- package/dist/insights/SnapInsightsController.cjs +8 -8
- package/dist/insights/SnapInsightsController.cjs.map +1 -1
- package/dist/insights/SnapInsightsController.d.cts +3 -2
- package/dist/insights/SnapInsightsController.d.cts.map +1 -1
- package/dist/insights/SnapInsightsController.d.mts +3 -2
- package/dist/insights/SnapInsightsController.d.mts.map +1 -1
- package/dist/insights/SnapInsightsController.mjs +8 -8
- package/dist/insights/SnapInsightsController.mjs.map +1 -1
- package/dist/interface/SnapInterfaceController.cjs +16 -17
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +3 -2
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +3 -2
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +16 -17
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/multichain/MultichainRouter.cjs.map +1 -1
- package/dist/multichain/MultichainRouter.d.cts +3 -3
- package/dist/multichain/MultichainRouter.d.cts.map +1 -1
- package/dist/multichain/MultichainRouter.d.mts +3 -3
- package/dist/multichain/MultichainRouter.d.mts.map +1 -1
- package/dist/multichain/MultichainRouter.mjs.map +1 -1
- package/dist/services/ExecutionService.cjs.map +1 -1
- package/dist/services/ExecutionService.d.cts +2 -2
- package/dist/services/ExecutionService.d.cts.map +1 -1
- package/dist/services/ExecutionService.d.mts +2 -2
- package/dist/services/ExecutionService.d.mts.map +1 -1
- package/dist/services/ExecutionService.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +94 -92
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +3 -2
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +3 -2
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +94 -92
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/registry/json.cjs +7 -7
- package/dist/snaps/registry/json.cjs.map +1 -1
- package/dist/snaps/registry/json.d.cts +3 -2
- package/dist/snaps/registry/json.d.cts.map +1 -1
- package/dist/snaps/registry/json.d.mts +3 -2
- package/dist/snaps/registry/json.d.mts.map +1 -1
- package/dist/snaps/registry/json.mjs +7 -7
- package/dist/snaps/registry/json.mjs.map +1 -1
- package/dist/websocket/WebSocketService.cjs.map +1 -1
- package/dist/websocket/WebSocketService.d.cts +2 -2
- package/dist/websocket/WebSocketService.d.cts.map +1 -1
- package/dist/websocket/WebSocketService.d.mts +2 -2
- package/dist/websocket/WebSocketService.d.mts.map +1 -1
- package/dist/websocket/WebSocketService.mjs.map +1 -1
- package/package.json +8 -7
|
@@ -87,13 +87,13 @@ export class SnapController extends BaseController {
|
|
|
87
87
|
snapStates: {
|
|
88
88
|
includeInStateLogs: false,
|
|
89
89
|
persist: true,
|
|
90
|
-
|
|
90
|
+
includeInDebugSnapshot: false,
|
|
91
91
|
usedInUi: false,
|
|
92
92
|
},
|
|
93
93
|
unencryptedSnapStates: {
|
|
94
94
|
includeInStateLogs: false,
|
|
95
95
|
persist: true,
|
|
96
|
-
|
|
96
|
+
includeInDebugSnapshot: false,
|
|
97
97
|
usedInUi: false,
|
|
98
98
|
},
|
|
99
99
|
snaps: {
|
|
@@ -124,7 +124,7 @@ export class SnapController extends BaseController {
|
|
|
124
124
|
return memo;
|
|
125
125
|
}, {}));
|
|
126
126
|
},
|
|
127
|
-
|
|
127
|
+
includeInDebugSnapshot: false,
|
|
128
128
|
// TODO: Ensure larger snap properties are not sent to the UI
|
|
129
129
|
// Currently these are stripped out manually in the extension
|
|
130
130
|
usedInUi: true,
|
|
@@ -159,21 +159,21 @@ export class SnapController extends BaseController {
|
|
|
159
159
|
this.#trackEvent = trackEvent;
|
|
160
160
|
this.#pollForLastRequestStatus();
|
|
161
161
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
162
|
-
this.
|
|
163
|
-
this.
|
|
164
|
-
this.
|
|
162
|
+
this.messenger.subscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
163
|
+
this.messenger.subscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
164
|
+
this.messenger.subscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
165
165
|
/* eslint-enable @typescript-eslint/unbound-method */
|
|
166
|
-
this.
|
|
166
|
+
this.messenger.subscribe('SnapController:snapInstalled', ({ id }, origin) => {
|
|
167
167
|
this.#callLifecycleHook(origin, id, HandlerType.OnInstall).catch((error) => {
|
|
168
168
|
logError(`Error when calling \`onInstall\` lifecycle hook for snap "${id}": ${getErrorMessage(error)}`);
|
|
169
169
|
});
|
|
170
170
|
});
|
|
171
|
-
this.
|
|
171
|
+
this.messenger.subscribe('SnapController:snapUpdated', ({ id }, _oldVersion, origin) => {
|
|
172
172
|
this.#callLifecycleHook(origin, id, HandlerType.OnUpdate).catch((error) => {
|
|
173
173
|
logError(`Error when calling \`onUpdate\` lifecycle hook for snap "${id}": ${getErrorMessage(error)}`);
|
|
174
174
|
});
|
|
175
175
|
});
|
|
176
|
-
this.
|
|
176
|
+
this.messenger.subscribe('KeyringController:lock', this.#handleLock.bind(this));
|
|
177
177
|
this.#initializeStateMachine();
|
|
178
178
|
this.#registerMessageHandlers();
|
|
179
179
|
Object.values(this.state?.snaps ?? {}).forEach((snap) => this.#setupRuntime(snap.id));
|
|
@@ -181,7 +181,7 @@ export class SnapController extends BaseController {
|
|
|
181
181
|
this.#handlePreinstalledSnaps(this.#preinstalledSnaps);
|
|
182
182
|
}
|
|
183
183
|
this.#trackSnapExport = throttleTracking((snapId, handler, success, origin) => {
|
|
184
|
-
const snapMetadata = this.
|
|
184
|
+
const snapMetadata = this.messenger.call('SnapsRegistry:getMetadata', snapId);
|
|
185
185
|
this.#trackEvent({
|
|
186
186
|
event: 'Snap Export Used',
|
|
187
187
|
category: 'Snaps',
|
|
@@ -264,29 +264,29 @@ export class SnapController extends BaseController {
|
|
|
264
264
|
* actions.
|
|
265
265
|
*/
|
|
266
266
|
#registerMessageHandlers() {
|
|
267
|
-
this.
|
|
268
|
-
this.
|
|
269
|
-
this.
|
|
270
|
-
this.
|
|
271
|
-
this.
|
|
272
|
-
this.
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
275
|
-
this.
|
|
276
|
-
this.
|
|
277
|
-
this.
|
|
278
|
-
this.
|
|
279
|
-
this.
|
|
280
|
-
this.
|
|
281
|
-
this.
|
|
282
|
-
this.
|
|
283
|
-
this.
|
|
284
|
-
this.
|
|
285
|
-
this.
|
|
286
|
-
this.
|
|
287
|
-
this.
|
|
288
|
-
this.
|
|
289
|
-
this.
|
|
267
|
+
this.messenger.registerActionHandler(`${controllerName}:init`, (...args) => this.init(...args));
|
|
268
|
+
this.messenger.registerActionHandler(`${controllerName}:clearSnapState`, (...args) => this.clearSnapState(...args));
|
|
269
|
+
this.messenger.registerActionHandler(`${controllerName}:get`, (...args) => this.get(...args));
|
|
270
|
+
this.messenger.registerActionHandler(`${controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
|
|
271
|
+
this.messenger.registerActionHandler(`${controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
|
|
272
|
+
this.messenger.registerActionHandler(`${controllerName}:has`, (...args) => this.has(...args));
|
|
273
|
+
this.messenger.registerActionHandler(`${controllerName}:updateRegistry`, async () => this.updateRegistry());
|
|
274
|
+
this.messenger.registerActionHandler(`${controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
|
|
275
|
+
this.messenger.registerActionHandler(`${controllerName}:enable`, (...args) => this.enableSnap(...args));
|
|
276
|
+
this.messenger.registerActionHandler(`${controllerName}:disable`, async (...args) => this.disableSnap(...args));
|
|
277
|
+
this.messenger.registerActionHandler(`${controllerName}:remove`, async (...args) => this.removeSnap(...args));
|
|
278
|
+
this.messenger.registerActionHandler(`${controllerName}:getPermitted`, (...args) => this.getPermittedSnaps(...args));
|
|
279
|
+
this.messenger.registerActionHandler(`${controllerName}:install`, async (...args) => this.installSnaps(...args));
|
|
280
|
+
this.messenger.registerActionHandler(`${controllerName}:getAll`, (...args) => this.getAllSnaps(...args));
|
|
281
|
+
this.messenger.registerActionHandler(`${controllerName}:getRunnableSnaps`, (...args) => this.getRunnableSnaps(...args));
|
|
282
|
+
this.messenger.registerActionHandler(`${controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
|
|
283
|
+
this.messenger.registerActionHandler(`${controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
|
|
284
|
+
this.messenger.registerActionHandler(`${controllerName}:disconnectOrigin`, (...args) => this.removeSnapFromSubject(...args));
|
|
285
|
+
this.messenger.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args) => this.revokeDynamicSnapPermissions(...args));
|
|
286
|
+
this.messenger.registerActionHandler(`${controllerName}:getFile`, async (...args) => this.getSnapFile(...args));
|
|
287
|
+
this.messenger.registerActionHandler(`${controllerName}:stopAllSnaps`, async (...args) => this.stopAllSnaps(...args));
|
|
288
|
+
this.messenger.registerActionHandler(`${controllerName}:isMinimumPlatformVersion`, (...args) => this.isMinimumPlatformVersion(...args));
|
|
289
|
+
this.messenger.registerActionHandler(`${controllerName}:setClientActive`, (...args) => this.setClientActive(...args));
|
|
290
290
|
}
|
|
291
291
|
/**
|
|
292
292
|
* Initialise the SnapController.
|
|
@@ -356,10 +356,10 @@ export class SnapController extends BaseController {
|
|
|
356
356
|
this.#setupRuntime(snapId);
|
|
357
357
|
// Emit events
|
|
358
358
|
if (isUpdate) {
|
|
359
|
-
this.
|
|
359
|
+
this.messenger.publish('SnapController:snapUpdated', this.getTruncatedExpect(snapId), existingSnap.version, METAMASK_ORIGIN, true);
|
|
360
360
|
}
|
|
361
361
|
else {
|
|
362
|
-
this.
|
|
362
|
+
this.messenger.publish('SnapController:snapInstalled', this.getTruncatedExpect(snapId), METAMASK_ORIGIN, true);
|
|
363
363
|
}
|
|
364
364
|
}
|
|
365
365
|
}
|
|
@@ -381,8 +381,8 @@ export class SnapController extends BaseController {
|
|
|
381
381
|
*/
|
|
382
382
|
async updateRegistry() {
|
|
383
383
|
this.#assertCanUsePlatform();
|
|
384
|
-
await this.
|
|
385
|
-
const blockedSnaps = await this.
|
|
384
|
+
await this.messenger.call('SnapsRegistry:update');
|
|
385
|
+
const blockedSnaps = await this.messenger.call('SnapsRegistry:get', Object.values(this.state.snaps).reduce((blockListArg, snap) => {
|
|
386
386
|
blockListArg[snap.id] = {
|
|
387
387
|
version: snap.version,
|
|
388
388
|
checksum: snap.manifest.source.shasum,
|
|
@@ -441,7 +441,7 @@ export class SnapController extends BaseController {
|
|
|
441
441
|
catch (error) {
|
|
442
442
|
logError(`Encountered error when stopping blocked snap "${snapId}".`, error);
|
|
443
443
|
}
|
|
444
|
-
this.
|
|
444
|
+
this.messenger.publish(`${controllerName}:snapBlocked`, snapId, blockedSnapInfo);
|
|
445
445
|
}
|
|
446
446
|
/**
|
|
447
447
|
* Unblocks a snap so that it can be enabled and started again. Emits
|
|
@@ -458,10 +458,10 @@ export class SnapController extends BaseController {
|
|
|
458
458
|
state.snaps[snapId].blocked = false;
|
|
459
459
|
delete state.snaps[snapId].blockInformation;
|
|
460
460
|
});
|
|
461
|
-
this.
|
|
461
|
+
this.messenger.publish(`${controllerName}:snapUnblocked`, snapId);
|
|
462
462
|
}
|
|
463
463
|
async #assertIsInstallAllowed(snapId, { platformVersion, ...snapInfo }) {
|
|
464
|
-
const results = await this.
|
|
464
|
+
const results = await this.messenger.call('SnapsRegistry:get', {
|
|
465
465
|
[snapId]: snapInfo,
|
|
466
466
|
});
|
|
467
467
|
const result = results[snapId];
|
|
@@ -578,7 +578,7 @@ export class SnapController extends BaseController {
|
|
|
578
578
|
this.update((state) => {
|
|
579
579
|
state.snaps[snapId].enabled = true;
|
|
580
580
|
});
|
|
581
|
-
this.
|
|
581
|
+
this.messenger.publish('SnapController:snapEnabled', this.getTruncatedExpect(snapId));
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
584
|
* Disables the given snap. A snap can only be started if it is enabled.
|
|
@@ -596,7 +596,7 @@ export class SnapController extends BaseController {
|
|
|
596
596
|
if (this.isRunning(snapId)) {
|
|
597
597
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
598
598
|
}
|
|
599
|
-
this.
|
|
599
|
+
this.messenger.publish('SnapController:snapDisabled', this.getTruncatedExpect(snapId));
|
|
600
600
|
}
|
|
601
601
|
/**
|
|
602
602
|
* Stops the given snap, removes all hooks, closes all connections, and
|
|
@@ -656,7 +656,7 @@ export class SnapController extends BaseController {
|
|
|
656
656
|
* @param snapId - The snap to terminate.
|
|
657
657
|
*/
|
|
658
658
|
async #terminateSnap(snapId) {
|
|
659
|
-
await this.
|
|
659
|
+
await this.messenger.call('ExecutionService:terminateSnap', snapId);
|
|
660
660
|
// Hack to give up execution for a bit to let gracefully terminating Snaps return.
|
|
661
661
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
662
662
|
const runtime = this.#getRuntimeExpect(snapId);
|
|
@@ -666,7 +666,7 @@ export class SnapController extends BaseController {
|
|
|
666
666
|
.forEach((pendingRequest) => pendingRequest.timer.finish());
|
|
667
667
|
// Hack to give up execution for a bit to let timed out requests return.
|
|
668
668
|
await new Promise((resolve) => setTimeout(resolve, 1));
|
|
669
|
-
this.
|
|
669
|
+
this.messenger.publish('SnapController:snapTerminated', this.getTruncatedExpect(snapId));
|
|
670
670
|
}
|
|
671
671
|
/**
|
|
672
672
|
* Returns whether the given snap is running.
|
|
@@ -1051,7 +1051,7 @@ export class SnapController extends BaseController {
|
|
|
1051
1051
|
});
|
|
1052
1052
|
// If the snap has been fully installed before, also emit snapUninstalled.
|
|
1053
1053
|
if (snap.status !== SnapStatus.Installing) {
|
|
1054
|
-
this.
|
|
1054
|
+
this.messenger.publish(`SnapController:snapUninstalled`, truncated);
|
|
1055
1055
|
}
|
|
1056
1056
|
}));
|
|
1057
1057
|
}
|
|
@@ -1067,7 +1067,7 @@ export class SnapController extends BaseController {
|
|
|
1067
1067
|
}
|
|
1068
1068
|
}
|
|
1069
1069
|
#addSnapToSubject(origin, snapId) {
|
|
1070
|
-
const subjectPermissions = this.
|
|
1070
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
1071
1071
|
const existingCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
1072
1072
|
const subjectHasSnap = Boolean(existingCaveat?.value?.[snapId]);
|
|
1073
1073
|
// If the subject is already connected to the snap, this is a no-op.
|
|
@@ -1076,7 +1076,7 @@ export class SnapController extends BaseController {
|
|
|
1076
1076
|
}
|
|
1077
1077
|
// If an existing caveat exists, we add the snap to that.
|
|
1078
1078
|
if (existingCaveat) {
|
|
1079
|
-
this.
|
|
1079
|
+
this.messenger.call('PermissionController:updateCaveat', origin, WALLET_SNAP_PERMISSION_KEY, SnapCaveatType.SnapIds, { ...existingCaveat.value, [snapId]: {} });
|
|
1080
1080
|
return;
|
|
1081
1081
|
}
|
|
1082
1082
|
const approvedPermissions = {
|
|
@@ -1091,7 +1091,7 @@ export class SnapController extends BaseController {
|
|
|
1091
1091
|
],
|
|
1092
1092
|
},
|
|
1093
1093
|
};
|
|
1094
|
-
this.
|
|
1094
|
+
this.messenger.call('PermissionController:grantPermissions', {
|
|
1095
1095
|
approvedPermissions,
|
|
1096
1096
|
subject: { origin },
|
|
1097
1097
|
});
|
|
@@ -1103,7 +1103,7 @@ export class SnapController extends BaseController {
|
|
|
1103
1103
|
* @param snapId - The id of the snap to remove.
|
|
1104
1104
|
*/
|
|
1105
1105
|
removeSnapFromSubject(origin, snapId) {
|
|
1106
|
-
const subjectPermissions = this.
|
|
1106
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
1107
1107
|
const snapIdsCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
1108
1108
|
if (!snapIdsCaveat) {
|
|
1109
1109
|
return;
|
|
@@ -1115,10 +1115,10 @@ export class SnapController extends BaseController {
|
|
|
1115
1115
|
};
|
|
1116
1116
|
delete newCaveatValue[snapId];
|
|
1117
1117
|
if (Object.keys(newCaveatValue).length > 0) {
|
|
1118
|
-
this.
|
|
1118
|
+
this.messenger.call('PermissionController:updateCaveat', origin, WALLET_SNAP_PERMISSION_KEY, SnapCaveatType.SnapIds, newCaveatValue);
|
|
1119
1119
|
}
|
|
1120
1120
|
else {
|
|
1121
|
-
this.
|
|
1121
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
1122
1122
|
[origin]: [WALLET_SNAP_PERMISSION_KEY],
|
|
1123
1123
|
});
|
|
1124
1124
|
}
|
|
@@ -1133,7 +1133,7 @@ export class SnapController extends BaseController {
|
|
|
1133
1133
|
*/
|
|
1134
1134
|
revokeDynamicSnapPermissions(snapId, permissionNames) {
|
|
1135
1135
|
assert(permissionNames.every((permissionName) => this.#dynamicPermissions.includes(permissionName)), 'Non-dynamic permissions cannot be revoked');
|
|
1136
|
-
this.
|
|
1136
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
1137
1137
|
[snapId]: permissionNames,
|
|
1138
1138
|
});
|
|
1139
1139
|
}
|
|
@@ -1143,7 +1143,7 @@ export class SnapController extends BaseController {
|
|
|
1143
1143
|
* @param snapId - The id of the Snap.
|
|
1144
1144
|
*/
|
|
1145
1145
|
#removeSnapFromSubjects(snapId) {
|
|
1146
|
-
const subjects = this.
|
|
1146
|
+
const subjects = this.messenger.call('PermissionController:getSubjectNames');
|
|
1147
1147
|
for (const subject of subjects) {
|
|
1148
1148
|
this.removeSnapFromSubject(subject, snapId);
|
|
1149
1149
|
}
|
|
@@ -1154,8 +1154,8 @@ export class SnapController extends BaseController {
|
|
|
1154
1154
|
* @param snapId - The snap ID.
|
|
1155
1155
|
*/
|
|
1156
1156
|
#revokeAllSnapPermissions(snapId) {
|
|
1157
|
-
if (this.
|
|
1158
|
-
this.
|
|
1157
|
+
if (this.messenger.call('PermissionController:hasPermissions', snapId)) {
|
|
1158
|
+
this.messenger.call('PermissionController:revokeAllPermissions', snapId);
|
|
1159
1159
|
}
|
|
1160
1160
|
}
|
|
1161
1161
|
/**
|
|
@@ -1200,7 +1200,7 @@ export class SnapController extends BaseController {
|
|
|
1200
1200
|
* @returns The serialized permitted snaps for the origin.
|
|
1201
1201
|
*/
|
|
1202
1202
|
getPermittedSnaps(origin) {
|
|
1203
|
-
const permissions = this.
|
|
1203
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', origin) ?? {};
|
|
1204
1204
|
const snaps = permissions[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds)?.value ?? {};
|
|
1205
1205
|
return Object.keys(snaps).reduce((permittedSnaps, snapId) => {
|
|
1206
1206
|
const snap = this.get(snapId);
|
|
@@ -1263,8 +1263,8 @@ export class SnapController extends BaseController {
|
|
|
1263
1263
|
result[snapId] = await this.#processRequestedSnap(origin, snapId, location, version);
|
|
1264
1264
|
}
|
|
1265
1265
|
// Once we finish all installs / updates, emit events.
|
|
1266
|
-
pendingInstalls.forEach((snapId) => this.
|
|
1267
|
-
pendingUpdates.forEach(({ snapId, oldVersion }) => this.
|
|
1266
|
+
pendingInstalls.forEach((snapId) => this.messenger.publish(`SnapController:snapInstalled`, this.getTruncatedExpect(snapId), origin, false));
|
|
1267
|
+
pendingUpdates.forEach(({ snapId, oldVersion }) => this.messenger.publish(`SnapController:snapUpdated`, this.getTruncatedExpect(snapId), oldVersion, origin, false));
|
|
1268
1268
|
snapIds.forEach((snapId) => this.#rollbackSnapshots.delete(snapId));
|
|
1269
1269
|
}
|
|
1270
1270
|
catch (error) {
|
|
@@ -1309,7 +1309,7 @@ export class SnapController extends BaseController {
|
|
|
1309
1309
|
snapId,
|
|
1310
1310
|
type: SNAP_APPROVAL_INSTALL,
|
|
1311
1311
|
});
|
|
1312
|
-
this.
|
|
1312
|
+
this.messenger.publish('SnapController:snapInstallStarted', snapId, origin, false);
|
|
1313
1313
|
// Existing snaps must be stopped before overwriting
|
|
1314
1314
|
if (existingSnap && this.isRunning(snapId)) {
|
|
1315
1315
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
@@ -1350,13 +1350,13 @@ export class SnapController extends BaseController {
|
|
|
1350
1350
|
type: SNAP_APPROVAL_INSTALL,
|
|
1351
1351
|
error: errorString,
|
|
1352
1352
|
});
|
|
1353
|
-
this.
|
|
1353
|
+
this.messenger.publish('SnapController:snapInstallFailed', snapId, origin, false, errorString);
|
|
1354
1354
|
throw error;
|
|
1355
1355
|
}
|
|
1356
1356
|
}
|
|
1357
1357
|
#createApproval({ origin, snapId, type, }) {
|
|
1358
1358
|
const id = nanoid();
|
|
1359
|
-
const promise = this.
|
|
1359
|
+
const promise = this.messenger.call('ApprovalController:addRequest', {
|
|
1360
1360
|
origin,
|
|
1361
1361
|
id,
|
|
1362
1362
|
type,
|
|
@@ -1373,7 +1373,7 @@ export class SnapController extends BaseController {
|
|
|
1373
1373
|
}
|
|
1374
1374
|
#updateApproval(id, requestState) {
|
|
1375
1375
|
try {
|
|
1376
|
-
this.
|
|
1376
|
+
this.messenger.call('ApprovalController:updateRequestState', {
|
|
1377
1377
|
id,
|
|
1378
1378
|
requestState,
|
|
1379
1379
|
});
|
|
@@ -1419,7 +1419,7 @@ export class SnapController extends BaseController {
|
|
|
1419
1419
|
type: SNAP_APPROVAL_UPDATE,
|
|
1420
1420
|
});
|
|
1421
1421
|
try {
|
|
1422
|
-
this.
|
|
1422
|
+
this.messenger.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
1423
1423
|
const oldManifest = snap.manifest;
|
|
1424
1424
|
const newSnap = await fetchSnap(snapId, location);
|
|
1425
1425
|
const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;
|
|
@@ -1527,12 +1527,12 @@ export class SnapController extends BaseController {
|
|
|
1527
1527
|
type: SNAP_APPROVAL_UPDATE,
|
|
1528
1528
|
});
|
|
1529
1529
|
}
|
|
1530
|
-
this.
|
|
1530
|
+
this.messenger.publish('SnapController:snapInstallFailed', snapId, origin, true, errorString);
|
|
1531
1531
|
throw error;
|
|
1532
1532
|
}
|
|
1533
1533
|
}
|
|
1534
1534
|
async #resolveAllowlistVersion(snapId, versionRange) {
|
|
1535
|
-
return await this.
|
|
1535
|
+
return await this.messenger.call('SnapsRegistry:resolveVersion', snapId, versionRange);
|
|
1536
1536
|
}
|
|
1537
1537
|
/**
|
|
1538
1538
|
* Returns a promise representing the complete installation of the requested snap.
|
|
@@ -1595,7 +1595,7 @@ export class SnapController extends BaseController {
|
|
|
1595
1595
|
}
|
|
1596
1596
|
try {
|
|
1597
1597
|
const runtime = this.#getRuntimeExpect(snapId);
|
|
1598
|
-
const result = await this.
|
|
1598
|
+
const result = await this.messenger.call('ExecutionService:executeSnap', {
|
|
1599
1599
|
...snapData,
|
|
1600
1600
|
endowments: await this.#getEndowments(snapId),
|
|
1601
1601
|
});
|
|
@@ -1623,8 +1623,8 @@ export class SnapController extends BaseController {
|
|
|
1623
1623
|
async #getEndowments(snapId) {
|
|
1624
1624
|
let allEndowments = [];
|
|
1625
1625
|
for (const permissionName of this.#environmentEndowmentPermissions) {
|
|
1626
|
-
if (this.
|
|
1627
|
-
const endowments = await this.
|
|
1626
|
+
if (this.messenger.call('PermissionController:hasPermission', snapId, permissionName)) {
|
|
1627
|
+
const endowments = await this.messenger.call('PermissionController:getEndowments', snapId, permissionName);
|
|
1628
1628
|
if (endowments) {
|
|
1629
1629
|
// We don't have any guarantees about the type of the endowments
|
|
1630
1630
|
// value, so we have to guard at runtime.
|
|
@@ -1724,7 +1724,7 @@ export class SnapController extends BaseController {
|
|
|
1724
1724
|
// In case the Snap uses a localized manifest, we need to get the
|
|
1725
1725
|
// proposed name from the localized manifest.
|
|
1726
1726
|
const { proposedName } = getLocalizedSnapManifest(manifest.result, 'en', localizedFiles);
|
|
1727
|
-
this.
|
|
1727
|
+
this.messenger.call('SubjectMetadataController:addSubjectMetadata', {
|
|
1728
1728
|
subjectType: SubjectType.Snap,
|
|
1729
1729
|
name: proposedName,
|
|
1730
1730
|
origin: snap.id,
|
|
@@ -1810,11 +1810,11 @@ export class SnapController extends BaseController {
|
|
|
1810
1810
|
clearTimeout(this.#timeoutForLastRequestStatus);
|
|
1811
1811
|
}
|
|
1812
1812
|
/* eslint-disable @typescript-eslint/unbound-method */
|
|
1813
|
-
this.
|
|
1814
|
-
this.
|
|
1815
|
-
this.
|
|
1816
|
-
this.
|
|
1817
|
-
this.
|
|
1813
|
+
this.messenger.unsubscribe('ExecutionService:unhandledError', this._onUnhandledSnapError);
|
|
1814
|
+
this.messenger.unsubscribe('ExecutionService:outboundRequest', this._onOutboundRequest);
|
|
1815
|
+
this.messenger.unsubscribe('ExecutionService:outboundResponse', this._onOutboundResponse);
|
|
1816
|
+
this.messenger.clearEventSubscriptions('SnapController:snapInstalled');
|
|
1817
|
+
this.messenger.clearEventSubscriptions('SnapController:snapUpdated');
|
|
1818
1818
|
/* eslint-enable @typescript-eslint/unbound-method */
|
|
1819
1819
|
}
|
|
1820
1820
|
/**
|
|
@@ -1829,6 +1829,8 @@ export class SnapController extends BaseController {
|
|
|
1829
1829
|
*/
|
|
1830
1830
|
async handleRequest({ snapId, origin, handler: handlerType, request: rawRequest, }) {
|
|
1831
1831
|
this.#assertCanUsePlatform();
|
|
1832
|
+
const snap = this.get(snapId);
|
|
1833
|
+
assert(snap, `The Snap "${snapId}" is not installed. Please install it before invoking it.`);
|
|
1832
1834
|
assert(origin === METAMASK_ORIGIN || isValidUrl(origin), "'origin' must be a valid URL or 'metamask'.");
|
|
1833
1835
|
const request = {
|
|
1834
1836
|
jsonrpc: '2.0',
|
|
@@ -1838,7 +1840,7 @@ export class SnapController extends BaseController {
|
|
|
1838
1840
|
assertIsJsonRpcRequest(request);
|
|
1839
1841
|
const permissionName = handlerEndowments[handlerType];
|
|
1840
1842
|
assert(typeof permissionName === 'string' || permissionName === null, "'permissionName' must be either a string or null.");
|
|
1841
|
-
const permissions = this.
|
|
1843
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', snapId);
|
|
1842
1844
|
// If permissionName is null, the handler does not require a permission.
|
|
1843
1845
|
if (permissionName !== null &&
|
|
1844
1846
|
(!permissions || !hasProperty(permissions, permissionName))) {
|
|
@@ -1850,7 +1852,7 @@ export class SnapController extends BaseController {
|
|
|
1850
1852
|
if (permissionName === SnapEndowments.Rpc ||
|
|
1851
1853
|
permissionName === SnapEndowments.Keyring) {
|
|
1852
1854
|
assert(handlerPermissions);
|
|
1853
|
-
const subject = this.
|
|
1855
|
+
const subject = this.messenger.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
1854
1856
|
const origins = permissionName === SnapEndowments.Rpc
|
|
1855
1857
|
? getRpcCaveatOrigins(handlerPermissions)
|
|
1856
1858
|
: getKeyringCaveatOrigins(handlerPermissions);
|
|
@@ -1863,10 +1865,10 @@ export class SnapController extends BaseController {
|
|
|
1863
1865
|
CLIENT_ONLY_HANDLERS.includes(handlerType)) {
|
|
1864
1866
|
throw new Error(`"${handlerType}" can only be invoked by MetaMask.`);
|
|
1865
1867
|
}
|
|
1866
|
-
if (!
|
|
1868
|
+
if (!snap.enabled) {
|
|
1867
1869
|
throw new Error(`Snap "${snapId}" is disabled.`);
|
|
1868
1870
|
}
|
|
1869
|
-
if (
|
|
1871
|
+
if (snap.status === SnapStatus.Installing) {
|
|
1870
1872
|
throw new Error(`Snap "${snapId}" is currently being installed. Please try again later.`);
|
|
1871
1873
|
}
|
|
1872
1874
|
const timeout = this.#getExecutionTimeout(handlerPermissions);
|
|
@@ -1888,7 +1890,7 @@ export class SnapController extends BaseController {
|
|
|
1888
1890
|
const transformedRequest = this.#transformSnapRpcRequest(snapId, handlerType, request);
|
|
1889
1891
|
const timer = new Timer(timeout);
|
|
1890
1892
|
this.#recordSnapRpcRequestStart(snapId, transformedRequest.id, timer);
|
|
1891
|
-
const handleRpcRequestPromise = this.
|
|
1893
|
+
const handleRpcRequestPromise = this.messenger.call('ExecutionService:handleRpcRequest', snapId, { origin, handler: handlerType, request: transformedRequest });
|
|
1892
1894
|
// This will either get the result or reject due to the timeout.
|
|
1893
1895
|
try {
|
|
1894
1896
|
const result = await withTimeout(handleRpcRequestPromise, timer);
|
|
@@ -1952,11 +1954,11 @@ export class SnapController extends BaseController {
|
|
|
1952
1954
|
* @returns An identifier that can be used to identify the interface.
|
|
1953
1955
|
*/
|
|
1954
1956
|
async #createInterface(snapId, content, contentType) {
|
|
1955
|
-
return this.
|
|
1957
|
+
return this.messenger.call('SnapInterfaceController:createInterface', snapId, content, undefined, contentType);
|
|
1956
1958
|
}
|
|
1957
1959
|
#assertInterfaceExists(snapId, id) {
|
|
1958
1960
|
// This will throw if the interface isn't accessible, but we assert nevertheless.
|
|
1959
|
-
assert(this.
|
|
1961
|
+
assert(this.messenger.call('SnapInterfaceController:getInterface', snapId, id));
|
|
1960
1962
|
}
|
|
1961
1963
|
/**
|
|
1962
1964
|
* Transform a RPC response if necessary.
|
|
@@ -2010,7 +2012,7 @@ export class SnapController extends BaseController {
|
|
|
2010
2012
|
* @returns The transformed result.
|
|
2011
2013
|
*/
|
|
2012
2014
|
#transformOnAssetsLookupResult(snapId, { params: requestedParams }, { assets }) {
|
|
2013
|
-
const permissions = this.
|
|
2015
|
+
const permissions = this.messenger.call('PermissionController:getPermissions', snapId);
|
|
2014
2016
|
// We know the permissions are guaranteed to be set here.
|
|
2015
2017
|
assert(permissions);
|
|
2016
2018
|
const permission = permissions[SnapEndowments.Assets];
|
|
@@ -2093,7 +2095,7 @@ export class SnapController extends BaseController {
|
|
|
2093
2095
|
case HandlerType.OnUserInput: {
|
|
2094
2096
|
assert(request.params && hasProperty(request.params, 'id'));
|
|
2095
2097
|
const interfaceId = request.params.id;
|
|
2096
|
-
const { context } = this.
|
|
2098
|
+
const { context } = this.messenger.call('SnapInterfaceController:getInterface', snapId, interfaceId);
|
|
2097
2099
|
return {
|
|
2098
2100
|
...request,
|
|
2099
2101
|
params: { ...request.params, context },
|
|
@@ -2249,7 +2251,7 @@ export class SnapController extends BaseController {
|
|
|
2249
2251
|
// Calling this in reverse order to undo the changes
|
|
2250
2252
|
this.#handleInitialConnections(snapId, newInitialConnections ?? null, previousInitialConnections ?? {});
|
|
2251
2253
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
2252
|
-
this.
|
|
2254
|
+
this.messenger.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
2253
2255
|
this.#rollbackSnapshots.delete(snapId);
|
|
2254
2256
|
}
|
|
2255
2257
|
/**
|
|
@@ -2299,7 +2301,7 @@ export class SnapController extends BaseController {
|
|
|
2299
2301
|
});
|
|
2300
2302
|
}
|
|
2301
2303
|
#calculatePermissionsChange(snapId, desiredPermissionsSet) {
|
|
2302
|
-
const oldPermissions = this.
|
|
2304
|
+
const oldPermissions = this.messenger.call('PermissionController:getPermissions', snapId) ?? {};
|
|
2303
2305
|
const newPermissions = permissionsDiff(desiredPermissionsSet, oldPermissions);
|
|
2304
2306
|
// TODO(ritave): The assumption that these are unused only holds so long as we do not
|
|
2305
2307
|
// permit dynamic permission requests.
|
|
@@ -2310,7 +2312,7 @@ export class SnapController extends BaseController {
|
|
|
2310
2312
|
return { newPermissions, unusedPermissions, approvedPermissions };
|
|
2311
2313
|
}
|
|
2312
2314
|
#isSubjectConnectedToSnap(snapId, origin) {
|
|
2313
|
-
const subjectPermissions = this.
|
|
2315
|
+
const subjectPermissions = this.messenger.call('PermissionController:getPermissions', origin);
|
|
2314
2316
|
const existingCaveat = subjectPermissions?.[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);
|
|
2315
2317
|
return Boolean(existingCaveat?.value?.[snapId]);
|
|
2316
2318
|
}
|
|
@@ -2342,8 +2344,8 @@ export class SnapController extends BaseController {
|
|
|
2342
2344
|
if (Object.keys(newPermissions).includes(SnapEndowments.EthereumProvider)) {
|
|
2343
2345
|
// This will return the globally selected network if the Snap doesn't have
|
|
2344
2346
|
// one set.
|
|
2345
|
-
const networkClientId = this.
|
|
2346
|
-
const { configuration } = this.
|
|
2347
|
+
const networkClientId = this.messenger.call('SelectedNetworkController:getNetworkClientIdForDomain', snapId);
|
|
2348
|
+
const { configuration } = this.messenger.call('NetworkController:getNetworkClientById', networkClientId);
|
|
2347
2349
|
const chainId = hexToNumber(configuration.chainId);
|
|
2348
2350
|
// This needs to be assigned to have proper type inference.
|
|
2349
2351
|
const modifiedPermissions = {
|
|
@@ -2384,13 +2386,13 @@ export class SnapController extends BaseController {
|
|
|
2384
2386
|
#updatePermissions({ snapId, unusedPermissions = {}, newPermissions = {}, requestData, }) {
|
|
2385
2387
|
const unusedPermissionsKeys = Object.keys(unusedPermissions);
|
|
2386
2388
|
if (isNonEmptyArray(unusedPermissionsKeys)) {
|
|
2387
|
-
this.
|
|
2389
|
+
this.messenger.call('PermissionController:revokePermissions', {
|
|
2388
2390
|
[snapId]: unusedPermissionsKeys,
|
|
2389
2391
|
});
|
|
2390
2392
|
}
|
|
2391
2393
|
if (isNonEmptyArray(Object.keys(newPermissions))) {
|
|
2392
2394
|
const approvedPermissions = this.#getPermissionsToGrant(snapId, newPermissions);
|
|
2393
|
-
this.
|
|
2395
|
+
this.messenger.call('PermissionController:grantPermissions', {
|
|
2394
2396
|
approvedPermissions,
|
|
2395
2397
|
subject: { origin: snapId },
|
|
2396
2398
|
requestData,
|
|
@@ -2432,7 +2434,7 @@ export class SnapController extends BaseController {
|
|
|
2432
2434
|
#callLifecycleHooks(origin, handler) {
|
|
2433
2435
|
const snaps = this.getRunnableSnaps();
|
|
2434
2436
|
for (const { id } of snaps) {
|
|
2435
|
-
const hasLifecycleHooksEndowment = this.
|
|
2437
|
+
const hasLifecycleHooksEndowment = this.messenger.call('PermissionController:hasPermission', id, SnapEndowments.LifecycleHooks);
|
|
2436
2438
|
if (!hasLifecycleHooksEndowment) {
|
|
2437
2439
|
continue;
|
|
2438
2440
|
}
|
|
@@ -2455,7 +2457,7 @@ export class SnapController extends BaseController {
|
|
|
2455
2457
|
async #callLifecycleHook(origin, snapId, handler) {
|
|
2456
2458
|
const permissionName = handlerEndowments[handler];
|
|
2457
2459
|
assert(permissionName, 'Lifecycle hook must have an endowment.');
|
|
2458
|
-
const hasPermission = this.
|
|
2460
|
+
const hasPermission = this.messenger.call('PermissionController:hasPermission', snapId, permissionName);
|
|
2459
2461
|
if (!hasPermission) {
|
|
2460
2462
|
return;
|
|
2461
2463
|
}
|