@metamask/snaps-controllers 14.2.2 → 15.0.1
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 +32 -1
- package/dist/cronjob/CronjobController.cjs +6 -1
- package/dist/cronjob/CronjobController.cjs.map +1 -1
- package/dist/cronjob/CronjobController.d.cts.map +1 -1
- package/dist/cronjob/CronjobController.d.mts.map +1 -1
- package/dist/cronjob/CronjobController.mjs +6 -1
- package/dist/cronjob/CronjobController.mjs.map +1 -1
- package/dist/insights/SnapInsightsController.cjs +6 -1
- package/dist/insights/SnapInsightsController.cjs.map +1 -1
- package/dist/insights/SnapInsightsController.d.cts.map +1 -1
- package/dist/insights/SnapInsightsController.d.mts.map +1 -1
- package/dist/insights/SnapInsightsController.mjs +6 -1
- package/dist/insights/SnapInsightsController.mjs.map +1 -1
- package/dist/interface/SnapInterfaceController.cjs +7 -5
- package/dist/interface/SnapInterfaceController.cjs.map +1 -1
- package/dist/interface/SnapInterfaceController.d.cts +2 -2
- package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
- package/dist/interface/SnapInterfaceController.d.mts +2 -2
- package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
- package/dist/interface/SnapInterfaceController.mjs +7 -5
- package/dist/interface/SnapInterfaceController.mjs.map +1 -1
- package/dist/services/AbstractExecutionService.cjs +22 -8
- package/dist/services/AbstractExecutionService.cjs.map +1 -1
- package/dist/services/AbstractExecutionService.d.cts.map +1 -1
- package/dist/services/AbstractExecutionService.d.mts.map +1 -1
- package/dist/services/AbstractExecutionService.mjs +24 -10
- package/dist/services/AbstractExecutionService.mjs.map +1 -1
- package/dist/snaps/SnapController.cjs +133 -75
- package/dist/snaps/SnapController.cjs.map +1 -1
- package/dist/snaps/SnapController.d.cts +13 -50
- package/dist/snaps/SnapController.d.cts.map +1 -1
- package/dist/snaps/SnapController.d.mts +13 -50
- package/dist/snaps/SnapController.d.mts.map +1 -1
- package/dist/snaps/SnapController.mjs +135 -77
- package/dist/snaps/SnapController.mjs.map +1 -1
- package/dist/snaps/Timer.cjs +5 -5
- package/dist/snaps/Timer.cjs.map +1 -1
- package/dist/snaps/Timer.d.cts.map +1 -1
- package/dist/snaps/Timer.d.mts.map +1 -1
- package/dist/snaps/Timer.mjs +5 -5
- package/dist/snaps/Timer.mjs.map +1 -1
- package/dist/snaps/registry/json.cjs +18 -3
- package/dist/snaps/registry/json.cjs.map +1 -1
- package/dist/snaps/registry/json.d.cts.map +1 -1
- package/dist/snaps/registry/json.d.mts.map +1 -1
- package/dist/snaps/registry/json.mjs +18 -3
- package/dist/snaps/registry/json.mjs.map +1 -1
- package/package.json +11 -9
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { ORIGIN_METAMASK } from "@metamask/approval-controller";
|
|
1
2
|
import { BaseController } from "@metamask/base-controller";
|
|
2
3
|
import { SubjectType } from "@metamask/permission-controller";
|
|
3
4
|
import { rpcErrors } from "@metamask/rpc-errors";
|
|
4
5
|
import { WALLET_SNAP_PERMISSION_KEY, getMaxRequestTimeCaveat, handlerEndowments, SnapEndowments, getKeyringCaveatOrigins, getRpcCaveatOrigins, processSnapPermissions, getEncryptionEntropy, getChainIdsCaveat } from "@metamask/snaps-rpc-methods";
|
|
5
6
|
import { AuxiliaryFileEncoding, getErrorMessage, OnAssetsLookupResponseStruct } from "@metamask/snaps-sdk";
|
|
6
|
-
import { logWarning, getPlatformVersion, assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS,
|
|
7
|
-
import { hexToNumber, assert, assertIsJsonRpcRequest, assertStruct, Duration, gtRange, gtVersion, hasProperty, inMilliseconds, isNonEmptyArray,
|
|
7
|
+
import { logWarning, getPlatformVersion, assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS, encodeAuxiliaryFile, HandlerType, isOriginAllowed, logError, normalizeRelative, OnTransactionResponseStruct, OnSignatureResponseStruct, resolveVersionRange, SnapCaveatType, SnapStatus, SnapStatusEvents, unwrapError, OnHomePageResponseStruct, getValidatedLocalizationFiles, VirtualFile, NpmSnapFileNames, OnNameLookupResponseStruct, getLocalizedSnapManifest, MAX_FILE_SIZE, OnSettingsPageResponseStruct, isValidUrl, OnAssetHistoricalPriceResponseStruct, OnAssetsConversionResponseStruct, OnAssetsMarketDataResponseStruct } from "@metamask/snaps-utils";
|
|
8
|
+
import { hexToNumber, assert, assertIsJsonRpcRequest, assertStruct, Duration, gtRange, gtVersion, hasProperty, inMilliseconds, isNonEmptyArray, satisfiesVersionRange, timeSince, createDeferredPromise } from "@metamask/utils";
|
|
8
9
|
import { createMachine, interpret } from "@xstate/fsm";
|
|
9
10
|
import { Mutex } from "async-mutex";
|
|
10
11
|
import { nanoid } from "nanoid";
|
|
@@ -84,14 +85,28 @@ export class SnapController extends BaseController {
|
|
|
84
85
|
messenger,
|
|
85
86
|
metadata: {
|
|
86
87
|
snapStates: {
|
|
88
|
+
includeInStateLogs: false,
|
|
87
89
|
persist: true,
|
|
88
90
|
anonymous: false,
|
|
91
|
+
usedInUi: false,
|
|
89
92
|
},
|
|
90
93
|
unencryptedSnapStates: {
|
|
94
|
+
includeInStateLogs: false,
|
|
91
95
|
persist: true,
|
|
92
96
|
anonymous: false,
|
|
97
|
+
usedInUi: false,
|
|
93
98
|
},
|
|
94
99
|
snaps: {
|
|
100
|
+
includeInStateLogs: (snaps) => {
|
|
101
|
+
// Delete larger snap properties
|
|
102
|
+
return Object.values(snaps).reduce((acc, snap) => {
|
|
103
|
+
const snapCopy = { ...snap };
|
|
104
|
+
delete snapCopy.sourceCode;
|
|
105
|
+
delete snapCopy.auxiliaryFiles;
|
|
106
|
+
acc[snap.id] = snapCopy;
|
|
107
|
+
return acc;
|
|
108
|
+
}, {});
|
|
109
|
+
},
|
|
95
110
|
persist: (snaps) => {
|
|
96
111
|
return (Object.values(snaps)
|
|
97
112
|
// We should not persist snaps that are in the installing state,
|
|
@@ -110,6 +125,9 @@ export class SnapController extends BaseController {
|
|
|
110
125
|
}, {}));
|
|
111
126
|
},
|
|
112
127
|
anonymous: false,
|
|
128
|
+
// TODO: Ensure larger snap properties are not sent to the UI
|
|
129
|
+
// Currently these are stripped out manually in the extension
|
|
130
|
+
usedInUi: true,
|
|
113
131
|
},
|
|
114
132
|
},
|
|
115
133
|
name: controllerName,
|
|
@@ -252,7 +270,7 @@ export class SnapController extends BaseController {
|
|
|
252
270
|
this.messagingSystem.registerActionHandler(`${controllerName}:getSnapState`, async (...args) => this.getSnapState(...args));
|
|
253
271
|
this.messagingSystem.registerActionHandler(`${controllerName}:handleRequest`, async (...args) => this.handleRequest(...args));
|
|
254
272
|
this.messagingSystem.registerActionHandler(`${controllerName}:has`, (...args) => this.has(...args));
|
|
255
|
-
this.messagingSystem.registerActionHandler(`${controllerName}:
|
|
273
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:updateRegistry`, async () => this.updateRegistry());
|
|
256
274
|
this.messagingSystem.registerActionHandler(`${controllerName}:updateSnapState`, async (...args) => this.updateSnapState(...args));
|
|
257
275
|
this.messagingSystem.registerActionHandler(`${controllerName}:enable`, (...args) => this.enableSnap(...args));
|
|
258
276
|
this.messagingSystem.registerActionHandler(`${controllerName}:disable`, async (...args) => this.disableSnap(...args));
|
|
@@ -358,8 +376,10 @@ export class SnapController extends BaseController {
|
|
|
358
376
|
* Checks all installed snaps against the block list and
|
|
359
377
|
* blocks/unblocks snaps as appropriate. See {@link SnapController.blockSnap}
|
|
360
378
|
* for more information.
|
|
379
|
+
*
|
|
380
|
+
* Also updates any preinstalled Snaps to the latest allowlisted version.
|
|
361
381
|
*/
|
|
362
|
-
async
|
|
382
|
+
async updateRegistry() {
|
|
363
383
|
this.#assertCanUsePlatform();
|
|
364
384
|
await this.messagingSystem.call('SnapsRegistry:update');
|
|
365
385
|
const blockedSnaps = await this.messagingSystem.call('SnapsRegistry:get', Object.values(this.state.snaps).reduce((blockListArg, snap) => {
|
|
@@ -375,6 +395,30 @@ export class SnapController extends BaseController {
|
|
|
375
395
|
}
|
|
376
396
|
return this.#unblockSnap(snapId);
|
|
377
397
|
}));
|
|
398
|
+
if (!this.#featureFlags.autoUpdatePreinstalledSnaps) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
const preinstalledVersionRange = '*';
|
|
402
|
+
await Promise.allSettled(Object.values(this.state.snaps)
|
|
403
|
+
.filter((snap) => snap.preinstalled)
|
|
404
|
+
.map(async (snap) => {
|
|
405
|
+
const resolvedVersion = await this.#resolveAllowlistVersion(snap.id, preinstalledVersionRange);
|
|
406
|
+
if (resolvedVersion !== preinstalledVersionRange &&
|
|
407
|
+
gtVersion(resolvedVersion, snap.version)) {
|
|
408
|
+
const location = this.#detectSnapLocation(snap.id, {
|
|
409
|
+
versionRange: resolvedVersion,
|
|
410
|
+
fetch: this.#fetchFunction,
|
|
411
|
+
allowLocal: false,
|
|
412
|
+
});
|
|
413
|
+
await this.#updateSnap({
|
|
414
|
+
origin: ORIGIN_METAMASK,
|
|
415
|
+
snapId: snap.id,
|
|
416
|
+
location,
|
|
417
|
+
versionRange: resolvedVersion,
|
|
418
|
+
automaticUpdate: true,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
}));
|
|
378
422
|
}
|
|
379
423
|
/**
|
|
380
424
|
* Blocks an installed snap and prevents it from being started again. Emits
|
|
@@ -666,7 +710,7 @@ export class SnapController extends BaseController {
|
|
|
666
710
|
*/
|
|
667
711
|
getExpect(snapId) {
|
|
668
712
|
const snap = this.get(snapId);
|
|
669
|
-
assert(snap !== undefined,
|
|
713
|
+
assert(snap !== undefined, `Snap "${snapId}" not found.`);
|
|
670
714
|
return snap;
|
|
671
715
|
}
|
|
672
716
|
/**
|
|
@@ -1216,7 +1260,7 @@ export class SnapController extends BaseController {
|
|
|
1216
1260
|
else if (!isUpdate) {
|
|
1217
1261
|
pendingInstalls.push(snapId);
|
|
1218
1262
|
}
|
|
1219
|
-
result[snapId] = await this
|
|
1263
|
+
result[snapId] = await this.#processRequestedSnap(origin, snapId, location, version);
|
|
1220
1264
|
}
|
|
1221
1265
|
// Once we finish all installs / updates, emit events.
|
|
1222
1266
|
pendingInstalls.forEach((snapId) => this.messagingSystem.publish(`SnapController:snapInstalled`, this.getTruncatedExpect(snapId), origin, false));
|
|
@@ -1245,23 +1289,19 @@ export class SnapController extends BaseController {
|
|
|
1245
1289
|
* @param versionRange - The semver range of the snap to install.
|
|
1246
1290
|
* @returns The resulting snap object, or an error if something went wrong.
|
|
1247
1291
|
*/
|
|
1248
|
-
|
|
1249
|
-
// ignore.
|
|
1250
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
1251
|
-
async processRequestedSnap(origin, snapId, location, versionRange) {
|
|
1292
|
+
async #processRequestedSnap(origin, snapId, location, versionRange) {
|
|
1252
1293
|
const existingSnap = this.getTruncated(snapId);
|
|
1253
1294
|
// For devX we always re-install local snaps.
|
|
1254
1295
|
if (existingSnap && !location.shouldAlwaysReload) {
|
|
1255
1296
|
if (satisfiesVersionRange(existingSnap.version, versionRange)) {
|
|
1256
1297
|
return existingSnap;
|
|
1257
1298
|
}
|
|
1258
|
-
return await this
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
false);
|
|
1299
|
+
return await this.#updateSnap({
|
|
1300
|
+
origin,
|
|
1301
|
+
snapId,
|
|
1302
|
+
location,
|
|
1303
|
+
versionRange,
|
|
1304
|
+
});
|
|
1265
1305
|
}
|
|
1266
1306
|
this.#assertCanInstallSnaps();
|
|
1267
1307
|
let pendingApproval = this.#createApproval({
|
|
@@ -1285,7 +1325,7 @@ export class SnapController extends BaseController {
|
|
|
1285
1325
|
location,
|
|
1286
1326
|
versionRange,
|
|
1287
1327
|
});
|
|
1288
|
-
await this
|
|
1328
|
+
await this.#authorize(snapId, pendingApproval);
|
|
1289
1329
|
pendingApproval = this.#createApproval({
|
|
1290
1330
|
origin,
|
|
1291
1331
|
snapId,
|
|
@@ -1354,28 +1394,30 @@ export class SnapController extends BaseController {
|
|
|
1354
1394
|
* If the original version of the snap was blocked and the update succeeded,
|
|
1355
1395
|
* the snap will be unblocked and enabled before it is restarted.
|
|
1356
1396
|
*
|
|
1357
|
-
* @param
|
|
1358
|
-
* @param
|
|
1359
|
-
* @param
|
|
1360
|
-
* @param
|
|
1361
|
-
* @param
|
|
1397
|
+
* @param options - An options bag.
|
|
1398
|
+
* @param options.origin - The origin requesting the snap update.
|
|
1399
|
+
* @param options.snapId - The id of the Snap to be updated.
|
|
1400
|
+
* @param options.location - The location implementation of the snap.
|
|
1401
|
+
* @param options.versionRange - A semver version range in which the maximum version will be chosen.
|
|
1402
|
+
* @param options.automaticUpdate - An optional boolean flag to indicate whether this update should be done
|
|
1403
|
+
* automatically.
|
|
1362
1404
|
* @returns The snap metadata if updated, `null` otherwise.
|
|
1363
1405
|
*/
|
|
1364
|
-
async updateSnap(origin, snapId, location,
|
|
1406
|
+
async #updateSnap({ origin, snapId, location, versionRange, automaticUpdate = false, }) {
|
|
1365
1407
|
this.#assertCanInstallSnaps();
|
|
1366
1408
|
this.#assertCanUsePlatform();
|
|
1367
1409
|
const snap = this.getExpect(snapId);
|
|
1368
|
-
|
|
1410
|
+
const { preinstalled, removable, hidden, hideSnapBranding } = snap;
|
|
1411
|
+
if (preinstalled && !automaticUpdate) {
|
|
1369
1412
|
throw new Error('Preinstalled Snaps cannot be manually updated.');
|
|
1370
1413
|
}
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
});
|
|
1414
|
+
let pendingApproval = automaticUpdate
|
|
1415
|
+
? null
|
|
1416
|
+
: this.#createApproval({
|
|
1417
|
+
origin,
|
|
1418
|
+
snapId,
|
|
1419
|
+
type: SNAP_APPROVAL_UPDATE,
|
|
1420
|
+
});
|
|
1379
1421
|
try {
|
|
1380
1422
|
this.messagingSystem.publish('SnapController:snapInstallStarted', snapId, origin, true);
|
|
1381
1423
|
const oldManifest = snap.manifest;
|
|
@@ -1384,10 +1426,10 @@ export class SnapController extends BaseController {
|
|
|
1384
1426
|
const manifest = manifestFile.result;
|
|
1385
1427
|
const newVersion = manifest.version;
|
|
1386
1428
|
if (!gtVersion(newVersion, snap.version)) {
|
|
1387
|
-
throw rpcErrors.invalidParams(`Snap "${snapId}@${snap.version}" is already installed. Couldn't update to a version inside requested "${
|
|
1429
|
+
throw rpcErrors.invalidParams(`Snap "${snapId}@${snap.version}" is already installed. Couldn't update to a version inside requested "${versionRange}" range.`);
|
|
1388
1430
|
}
|
|
1389
|
-
if (!satisfiesVersionRange(newVersion,
|
|
1390
|
-
throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${newVersion}" which doesn't satisfy requested version range "${
|
|
1431
|
+
if (!satisfiesVersionRange(newVersion, versionRange)) {
|
|
1432
|
+
throw new Error(`Version mismatch. Manifest for "${snapId}" specifies version "${newVersion}" which doesn't satisfy requested version range "${versionRange}".`);
|
|
1391
1433
|
}
|
|
1392
1434
|
await this.#assertIsInstallAllowed(snapId, {
|
|
1393
1435
|
version: newVersion,
|
|
@@ -1399,23 +1441,33 @@ export class SnapController extends BaseController {
|
|
|
1399
1441
|
this.#validateSnapPermissions(processedPermissions);
|
|
1400
1442
|
const { newPermissions, unusedPermissions, approvedPermissions } = this.#calculatePermissionsChange(snapId, processedPermissions);
|
|
1401
1443
|
const { newConnections, unusedConnections, approvedConnections } = this.#calculateConnectionsChange(snapId, oldManifest.initialConnections ?? {}, manifest.initialConnections ?? {});
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1444
|
+
let approvedNewPermissions;
|
|
1445
|
+
let requestData;
|
|
1446
|
+
if (pendingApproval) {
|
|
1447
|
+
this.#updateApproval(pendingApproval.id, {
|
|
1448
|
+
permissions: newPermissions,
|
|
1449
|
+
newVersion: manifest.version,
|
|
1450
|
+
newPermissions,
|
|
1451
|
+
approvedPermissions,
|
|
1452
|
+
unusedPermissions,
|
|
1453
|
+
newConnections,
|
|
1454
|
+
unusedConnections,
|
|
1455
|
+
approvedConnections,
|
|
1456
|
+
loading: false,
|
|
1457
|
+
});
|
|
1458
|
+
const { permissions, ...rest } = (await pendingApproval.promise);
|
|
1459
|
+
approvedNewPermissions = permissions;
|
|
1460
|
+
requestData = rest;
|
|
1461
|
+
pendingApproval = this.#createApproval({
|
|
1462
|
+
origin,
|
|
1463
|
+
snapId,
|
|
1464
|
+
type: SNAP_APPROVAL_RESULT,
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
else {
|
|
1468
|
+
assert(automaticUpdate);
|
|
1469
|
+
approvedNewPermissions = newPermissions;
|
|
1470
|
+
}
|
|
1419
1471
|
if (this.isRunning(snapId)) {
|
|
1420
1472
|
await this.stopSnap(snapId, SnapStatusEvents.Stop);
|
|
1421
1473
|
}
|
|
@@ -1424,6 +1476,10 @@ export class SnapController extends BaseController {
|
|
|
1424
1476
|
origin,
|
|
1425
1477
|
id: snapId,
|
|
1426
1478
|
files: newSnap,
|
|
1479
|
+
removable,
|
|
1480
|
+
preinstalled,
|
|
1481
|
+
hidden,
|
|
1482
|
+
hideSnapBranding,
|
|
1427
1483
|
isUpdate: true,
|
|
1428
1484
|
});
|
|
1429
1485
|
this.#updatePermissions({
|
|
@@ -1432,14 +1488,17 @@ export class SnapController extends BaseController {
|
|
|
1432
1488
|
newPermissions: approvedNewPermissions,
|
|
1433
1489
|
requestData,
|
|
1434
1490
|
});
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1491
|
+
const previousInitialConnections = oldManifest.initialConnections ?? null;
|
|
1492
|
+
const newInitialConnections = manifest.initialConnections ?? {};
|
|
1493
|
+
this.#handleInitialConnections(snapId, previousInitialConnections, newInitialConnections);
|
|
1438
1494
|
const rollbackSnapshot = this.#getRollbackSnapshot(snapId);
|
|
1439
1495
|
if (rollbackSnapshot !== undefined) {
|
|
1440
1496
|
rollbackSnapshot.permissions.revoked = unusedPermissions;
|
|
1441
1497
|
rollbackSnapshot.permissions.granted = approvedNewPermissions;
|
|
1442
1498
|
rollbackSnapshot.permissions.requestData = requestData;
|
|
1499
|
+
rollbackSnapshot.previousInitialConnections =
|
|
1500
|
+
previousInitialConnections;
|
|
1501
|
+
rollbackSnapshot.newInitialConnections = newInitialConnections;
|
|
1443
1502
|
}
|
|
1444
1503
|
const sourceCode = sourceCodeFile.toString();
|
|
1445
1504
|
assert(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
@@ -1450,23 +1509,24 @@ export class SnapController extends BaseController {
|
|
|
1450
1509
|
throw new Error(`Snap ${snapId} crashed with updated source code.`);
|
|
1451
1510
|
}
|
|
1452
1511
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
1453
|
-
if (
|
|
1454
|
-
this
|
|
1512
|
+
if (pendingApproval) {
|
|
1513
|
+
this.#updateApproval(pendingApproval.id, {
|
|
1514
|
+
loading: false,
|
|
1515
|
+
type: SNAP_APPROVAL_UPDATE,
|
|
1516
|
+
});
|
|
1455
1517
|
}
|
|
1456
|
-
this.#updateApproval(pendingApproval.id, {
|
|
1457
|
-
loading: false,
|
|
1458
|
-
type: SNAP_APPROVAL_UPDATE,
|
|
1459
|
-
});
|
|
1460
1518
|
return truncatedSnap;
|
|
1461
1519
|
}
|
|
1462
1520
|
catch (error) {
|
|
1463
1521
|
logError(`Error when updating ${snapId},`, error);
|
|
1464
1522
|
const errorString = error instanceof Error ? error.message : error.toString();
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1523
|
+
if (pendingApproval) {
|
|
1524
|
+
this.#updateApproval(pendingApproval.id, {
|
|
1525
|
+
loading: false,
|
|
1526
|
+
error: errorString,
|
|
1527
|
+
type: SNAP_APPROVAL_UPDATE,
|
|
1528
|
+
});
|
|
1529
|
+
}
|
|
1470
1530
|
this.messagingSystem.publish('SnapController:snapInstallFailed', snapId, origin, true, errorString);
|
|
1471
1531
|
throw error;
|
|
1472
1532
|
}
|
|
@@ -1712,14 +1772,11 @@ export class SnapController extends BaseController {
|
|
|
1712
1772
|
* Initiates a request for the given snap's initial permissions.
|
|
1713
1773
|
* Must be called in order. See processRequestedSnap.
|
|
1714
1774
|
*
|
|
1715
|
-
* This function is not hash private yet because of tests.
|
|
1716
|
-
*
|
|
1717
1775
|
* @param snapId - The id of the Snap.
|
|
1718
1776
|
* @param pendingApproval - Pending approval to update.
|
|
1719
1777
|
* @returns The snap's approvedPermissions.
|
|
1720
1778
|
*/
|
|
1721
|
-
|
|
1722
|
-
async authorize(snapId, pendingApproval) {
|
|
1779
|
+
async #authorize(snapId, pendingApproval) {
|
|
1723
1780
|
log(`Authorizing snap: ${snapId}`);
|
|
1724
1781
|
const snapsState = this.state.snaps;
|
|
1725
1782
|
const snap = snapsState[snapId];
|
|
@@ -2141,14 +2198,14 @@ export class SnapController extends BaseController {
|
|
|
2141
2198
|
* @returns A `RollbackSnapshot`.
|
|
2142
2199
|
*/
|
|
2143
2200
|
#createRollbackSnapshot(snapId) {
|
|
2144
|
-
assert(this.#rollbackSnapshots.get(snapId) === undefined,
|
|
2201
|
+
assert(this.#rollbackSnapshots.get(snapId) === undefined, `Snap "${snapId}" rollback snapshot already exists.`);
|
|
2145
2202
|
this.#rollbackSnapshots.set(snapId, {
|
|
2146
2203
|
statePatches: [],
|
|
2147
2204
|
permissions: {},
|
|
2148
2205
|
newVersion: '',
|
|
2149
2206
|
});
|
|
2150
2207
|
const newRollbackSnapshot = this.#rollbackSnapshots.get(snapId);
|
|
2151
|
-
assert(newRollbackSnapshot !== undefined,
|
|
2208
|
+
assert(newRollbackSnapshot !== undefined, `Snapshot creation failed for ${snapId}.`);
|
|
2152
2209
|
return newRollbackSnapshot;
|
|
2153
2210
|
}
|
|
2154
2211
|
/**
|
|
@@ -2172,7 +2229,7 @@ export class SnapController extends BaseController {
|
|
|
2172
2229
|
if (this.get(snapId)?.status !== SnapStatus.Stopped) {
|
|
2173
2230
|
this.#transition(snapId, SnapStatusEvents.Stop);
|
|
2174
2231
|
}
|
|
2175
|
-
const { statePatches, permissions } = rollbackSnapshot;
|
|
2232
|
+
const { statePatches, permissions, previousInitialConnections, newInitialConnections, } = rollbackSnapshot;
|
|
2176
2233
|
if (statePatches?.length) {
|
|
2177
2234
|
this.applyPatches(statePatches);
|
|
2178
2235
|
}
|
|
@@ -2189,6 +2246,8 @@ export class SnapController extends BaseController {
|
|
|
2189
2246
|
newPermissions: permissions.revoked,
|
|
2190
2247
|
requestData: permissions.requestData,
|
|
2191
2248
|
});
|
|
2249
|
+
// Calling this in reverse order to undo the changes
|
|
2250
|
+
this.#handleInitialConnections(snapId, newInitialConnections ?? null, previousInitialConnections ?? {});
|
|
2192
2251
|
const truncatedSnap = this.getTruncatedExpect(snapId);
|
|
2193
2252
|
this.messagingSystem.publish('SnapController:snapRolledback', truncatedSnap, rollbackSnapshot.newVersion);
|
|
2194
2253
|
this.#rollbackSnapshots.delete(snapId);
|
|
@@ -2209,7 +2268,7 @@ export class SnapController extends BaseController {
|
|
|
2209
2268
|
}
|
|
2210
2269
|
#getRuntimeExpect(snapId) {
|
|
2211
2270
|
const runtime = this.#getRuntime(snapId);
|
|
2212
|
-
assert(runtime !== undefined,
|
|
2271
|
+
assert(runtime !== undefined, `Snap "${snapId}" runtime data not found`);
|
|
2213
2272
|
return runtime;
|
|
2214
2273
|
}
|
|
2215
2274
|
#setupRuntime(snapId) {
|
|
@@ -2280,8 +2339,7 @@ export class SnapController extends BaseController {
|
|
|
2280
2339
|
* @returns The permissions to grant to the Snap.
|
|
2281
2340
|
*/
|
|
2282
2341
|
#getPermissionsToGrant(snapId, newPermissions) {
|
|
2283
|
-
if (
|
|
2284
|
-
Object.keys(newPermissions).includes(SnapEndowments.EthereumProvider)) {
|
|
2342
|
+
if (Object.keys(newPermissions).includes(SnapEndowments.EthereumProvider)) {
|
|
2285
2343
|
// This will return the globally selected network if the Snap doesn't have
|
|
2286
2344
|
// one set.
|
|
2287
2345
|
const networkClientId = this.messagingSystem.call('SelectedNetworkController:getNetworkClientIdForDomain', snapId);
|