@metamask/snaps-controllers 3.4.0 → 3.5.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/cjs/cronjob/CronjobController.js +1 -1
- package/dist/cjs/cronjob/CronjobController.js.map +1 -1
- package/dist/cjs/services/AbstractExecutionService.js +4 -6
- package/dist/cjs/services/AbstractExecutionService.js.map +1 -1
- package/dist/cjs/snaps/SnapController.js +22 -19
- package/dist/cjs/snaps/SnapController.js.map +1 -1
- package/dist/cjs/snaps/location/npm.js +30 -7
- package/dist/cjs/snaps/location/npm.js.map +1 -1
- package/dist/cjs/snaps/registry/json.js +1 -1
- package/dist/cjs/snaps/registry/json.js.map +1 -1
- package/dist/esm/cronjob/CronjobController.js +1 -1
- package/dist/esm/cronjob/CronjobController.js.map +1 -1
- package/dist/esm/services/AbstractExecutionService.js +3 -5
- package/dist/esm/services/AbstractExecutionService.js.map +1 -1
- package/dist/esm/snaps/SnapController.js +23 -20
- package/dist/esm/snaps/SnapController.js.map +1 -1
- package/dist/esm/snaps/location/npm.js +30 -7
- package/dist/esm/snaps/location/npm.js.map +1 -1
- package/dist/esm/snaps/registry/json.js +1 -1
- package/dist/esm/snaps/registry/json.js.map +1 -1
- package/dist/types/cronjob/CronjobController.d.ts +1 -1
- package/dist/types/services/AbstractExecutionService.d.ts +1 -1
- package/dist/types/snaps/SnapController.d.ts +2 -2
- package/dist/types/snaps/location/npm.d.ts +1 -1
- package/dist/types/snaps/registry/json.d.ts +1 -1
- package/package.json +15 -14
|
@@ -61,12 +61,12 @@ function _define_property(obj, key, value) {
|
|
|
61
61
|
}
|
|
62
62
|
return obj;
|
|
63
63
|
}
|
|
64
|
-
import {
|
|
64
|
+
import { BaseController } from '@metamask/base-controller';
|
|
65
65
|
import { SubjectType } from '@metamask/permission-controller';
|
|
66
66
|
import { rpcErrors } from '@metamask/rpc-errors';
|
|
67
67
|
import { WALLET_SNAP_PERMISSION_KEY } from '@metamask/snaps-rpc-methods';
|
|
68
68
|
import { AuxiliaryFileEncoding, getErrorMessage } from '@metamask/snaps-sdk';
|
|
69
|
-
import { validateComponentLinks, assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS, DEFAULT_REQUESTED_SNAP_VERSION, encodeAuxiliaryFile, HandlerType, isOriginAllowed, logError, normalizeRelative, OnTransactionResponseStruct, resolveVersionRange, SnapCaveatType, SnapStatus, SnapStatusEvents, validateFetchedSnap, unwrapError, OnHomePageResponseStruct, getValidatedLocalizationFiles } from '@metamask/snaps-utils';
|
|
69
|
+
import { validateComponentLinks, assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS, DEFAULT_REQUESTED_SNAP_VERSION, encodeAuxiliaryFile, HandlerType, isOriginAllowed, logError, normalizeRelative, OnTransactionResponseStruct, resolveVersionRange, SnapCaveatType, SnapStatus, SnapStatusEvents, validateFetchedSnap, unwrapError, OnHomePageResponseStruct, getValidatedLocalizationFiles, encodeBase64 } from '@metamask/snaps-utils';
|
|
70
70
|
import { assert, assertIsJsonRpcRequest, assertStruct, Duration, gtRange, gtVersion, hasProperty, inMilliseconds, isNonEmptyArray, isValidSemVerRange, satisfiesVersionRange, timeSince } from '@metamask/utils';
|
|
71
71
|
import { createMachine, interpret } from '@xstate/fsm';
|
|
72
72
|
import { nanoid } from 'nanoid';
|
|
@@ -425,7 +425,7 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
425
425
|
* @param path - The path to the requested file.
|
|
426
426
|
* @param encoding - An optional requested file encoding.
|
|
427
427
|
* @returns The file requested in the chosen file encoding or null if the file is not found.
|
|
428
|
-
*/ getSnapFile(snapId, path, encoding = AuxiliaryFileEncoding.Base64) {
|
|
428
|
+
*/ async getSnapFile(snapId, path, encoding = AuxiliaryFileEncoding.Base64) {
|
|
429
429
|
const snap = this.getExpect(snapId);
|
|
430
430
|
const normalizedPath = normalizeRelative(path);
|
|
431
431
|
const value = snap.auxiliaryFiles?.find((file)=>file.path === normalizedPath)?.value;
|
|
@@ -1153,10 +1153,7 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
1153
1153
|
});
|
|
1154
1154
|
_class_private_method_get(this, _initializeStateMachine, initializeStateMachine).call(this);
|
|
1155
1155
|
_class_private_method_get(this, _registerMessageHandlers, registerMessageHandlers).call(this);
|
|
1156
|
-
Object.values(state?.snaps ?? {}).forEach((snap)=>_class_private_method_get(this, _setupRuntime, setupRuntime).call(this, snap.id
|
|
1157
|
-
sourceCode: snap.sourceCode,
|
|
1158
|
-
state: state?.snapStates?.[snap.id] ?? null
|
|
1159
|
-
}));
|
|
1156
|
+
Object.values(state?.snaps ?? {}).forEach((snap)=>_class_private_method_get(this, _setupRuntime, setupRuntime).call(this, snap.id));
|
|
1160
1157
|
}
|
|
1161
1158
|
}
|
|
1162
1159
|
function initializeStateMachine() {
|
|
@@ -1231,7 +1228,7 @@ function registerMessageHandlers() {
|
|
|
1231
1228
|
this.messagingSystem.registerActionHandler(`${controllerName}:getRegistryMetadata`, async (...args)=>this.getRegistryMetadata(...args));
|
|
1232
1229
|
this.messagingSystem.registerActionHandler(`${controllerName}:disconnectOrigin`, (...args)=>this.removeSnapFromSubject(...args));
|
|
1233
1230
|
this.messagingSystem.registerActionHandler(`${controllerName}:revokeDynamicPermissions`, (...args)=>this.revokeDynamicSnapPermissions(...args));
|
|
1234
|
-
this.messagingSystem.registerActionHandler(`${controllerName}:getFile`, (...args)=>this.getSnapFile(...args));
|
|
1231
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:getFile`, async (...args)=>this.getSnapFile(...args));
|
|
1235
1232
|
}
|
|
1236
1233
|
function pollForLastRequestStatus() {
|
|
1237
1234
|
_class_private_field_set(this, _timeoutForLastRequestStatus, setTimeout(()=>{
|
|
@@ -1282,8 +1279,7 @@ async function stopSnapsLastRequestPastMax() {
|
|
|
1282
1279
|
const entries = [
|
|
1283
1280
|
..._class_private_field_get(this, _snapsRuntimeData).entries()
|
|
1284
1281
|
];
|
|
1285
|
-
return Promise.all(entries.filter(([_snapId, runtime])=>runtime.activeReferences === 0 && runtime.pendingInboundRequests.length === 0 &&
|
|
1286
|
-
runtime.lastRequest && _class_private_field_get(this, _maxIdleTime) && timeSince(runtime.lastRequest) > _class_private_field_get(this, _maxIdleTime)).map(async ([snapId])=>this.stopSnap(snapId, SnapStatusEvents.Stop)));
|
|
1282
|
+
return Promise.all(entries.filter(([_snapId, runtime])=>runtime.activeReferences === 0 && runtime.pendingInboundRequests.length === 0 && runtime.lastRequest && _class_private_field_get(this, _maxIdleTime) && timeSince(runtime.lastRequest) > _class_private_field_get(this, _maxIdleTime)).map(async ([snapId])=>this.stopSnap(snapId, SnapStatusEvents.Stop)));
|
|
1287
1283
|
}
|
|
1288
1284
|
function transition(snapId, event) {
|
|
1289
1285
|
const { interpreter } = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
@@ -1346,10 +1342,7 @@ async function resolveAllowlistVersion(snapId, versionRange) {
|
|
|
1346
1342
|
}
|
|
1347
1343
|
async function add(args) {
|
|
1348
1344
|
const { id: snapId, location, versionRange } = args;
|
|
1349
|
-
_class_private_method_get(this, _setupRuntime, setupRuntime).call(this, snapId
|
|
1350
|
-
sourceCode: null,
|
|
1351
|
-
state: null
|
|
1352
|
-
});
|
|
1345
|
+
_class_private_method_get(this, _setupRuntime, setupRuntime).call(this, snapId);
|
|
1353
1346
|
const runtime = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
1354
1347
|
if (!runtime.installPromise) {
|
|
1355
1348
|
log(`Adding snap: ${snapId}`);
|
|
@@ -1387,11 +1380,14 @@ async function startSnap(snapData) {
|
|
|
1387
1380
|
throw new Error(`Snap "${snapId}" is already started.`);
|
|
1388
1381
|
}
|
|
1389
1382
|
try {
|
|
1383
|
+
const runtime = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
1390
1384
|
const result = await _class_private_method_get(this, _executeWithTimeout, executeWithTimeout).call(this, this.messagingSystem.call('ExecutionService:executeSnap', {
|
|
1391
1385
|
...snapData,
|
|
1392
1386
|
endowments: await _class_private_method_get(this, _getEndowments, getEndowments).call(this, snapId)
|
|
1393
1387
|
}));
|
|
1394
1388
|
_class_private_method_get(this, _transition, transition).call(this, snapId, SnapStatusEvents.Start);
|
|
1389
|
+
// We treat the initialization of the snap as the first request, for idle timing purposes.
|
|
1390
|
+
runtime.lastRequest = Date.now();
|
|
1395
1391
|
return result;
|
|
1396
1392
|
} catch (error) {
|
|
1397
1393
|
await _class_private_method_get(this, _terminateSnap, terminateSnap).call(this, snapId);
|
|
@@ -1433,10 +1429,13 @@ function set(args) {
|
|
|
1433
1429
|
const { version } = manifest.result;
|
|
1434
1430
|
const sourceCode = sourceCodeFile.toString();
|
|
1435
1431
|
assert(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
1436
|
-
const auxiliaryFiles = rawAuxiliaryFiles.map((file)=>
|
|
1432
|
+
const auxiliaryFiles = rawAuxiliaryFiles.map((file)=>{
|
|
1433
|
+
assert(typeof file.data.base64 === 'string');
|
|
1434
|
+
return {
|
|
1437
1435
|
path: file.path,
|
|
1438
|
-
value: file.
|
|
1439
|
-
}
|
|
1436
|
+
value: file.data.base64
|
|
1437
|
+
};
|
|
1438
|
+
});
|
|
1440
1439
|
const snapsState = this.state.snaps;
|
|
1441
1440
|
const existingSnap = snapsState[snapId];
|
|
1442
1441
|
const previousVersionHistory = existingSnap?.versionHistory ?? [];
|
|
@@ -1492,6 +1491,11 @@ async function fetchSnap(snapId, location) {
|
|
|
1492
1491
|
const { iconPath } = manifest.result.source.location.npm;
|
|
1493
1492
|
const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;
|
|
1494
1493
|
const auxiliaryFiles = await getSnapFiles(location, manifest.result.source.files);
|
|
1494
|
+
await Promise.all(auxiliaryFiles.map(async (file)=>{
|
|
1495
|
+
// This should still be safe
|
|
1496
|
+
// eslint-disable-next-line require-atomic-updates
|
|
1497
|
+
file.data.base64 = await encodeBase64(file);
|
|
1498
|
+
}));
|
|
1495
1499
|
const localizationFiles = await getSnapFiles(location, manifest.result.source.locales);
|
|
1496
1500
|
const validatedLocalizationFiles = getValidatedLocalizationFiles(localizationFiles);
|
|
1497
1501
|
const files = {
|
|
@@ -1703,7 +1707,7 @@ function getRuntimeExpect(snapId) {
|
|
|
1703
1707
|
assert(runtime !== undefined, new Error(`Snap "${snapId}" runtime data not found`));
|
|
1704
1708
|
return runtime;
|
|
1705
1709
|
}
|
|
1706
|
-
function setupRuntime(snapId
|
|
1710
|
+
function setupRuntime(snapId) {
|
|
1707
1711
|
if (_class_private_field_get(this, _snapsRuntimeData).has(snapId)) {
|
|
1708
1712
|
return;
|
|
1709
1713
|
}
|
|
@@ -1723,8 +1727,7 @@ function setupRuntime(snapId, data) {
|
|
|
1723
1727
|
activeReferences: 0,
|
|
1724
1728
|
pendingInboundRequests: [],
|
|
1725
1729
|
pendingOutboundRequests: 0,
|
|
1726
|
-
interpreter
|
|
1727
|
-
...data
|
|
1730
|
+
interpreter
|
|
1728
1731
|
});
|
|
1729
1732
|
}
|
|
1730
1733
|
function calculatePermissionsChange(snapId, desiredPermissionsSet) {
|