@metamask/snaps-controllers 4.1.0 → 5.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 +27 -1
- package/dist/cjs/cronjob/CronjobController.js +3 -3
- package/dist/cjs/cronjob/CronjobController.js.map +1 -1
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/interface/SnapInterfaceController.js +166 -0
- package/dist/cjs/interface/SnapInterfaceController.js.map +1 -0
- package/dist/cjs/interface/index.js +20 -0
- package/dist/cjs/interface/index.js.map +1 -0
- package/dist/cjs/interface/utils.js +59 -0
- package/dist/cjs/interface/utils.js.map +1 -0
- package/dist/cjs/services/browser.js +1 -0
- package/dist/cjs/services/browser.js.map +1 -1
- package/dist/cjs/services/index.js +1 -0
- package/dist/cjs/services/index.js.map +1 -1
- package/dist/cjs/services/webview/WebViewExecutionService.js +99 -0
- package/dist/cjs/services/webview/WebViewExecutionService.js.map +1 -0
- package/dist/cjs/services/webview/WebViewMessageStream.js +127 -0
- package/dist/cjs/services/webview/WebViewMessageStream.js.map +1 -0
- package/dist/cjs/services/webview/index.js +20 -0
- package/dist/cjs/services/webview/index.js.map +1 -0
- package/dist/cjs/snaps/SnapController.js +111 -51
- package/dist/cjs/snaps/SnapController.js.map +1 -1
- package/dist/cjs/snaps/constants.js +25 -0
- package/dist/cjs/snaps/constants.js.map +1 -0
- package/dist/cjs/snaps/index.js +0 -2
- package/dist/cjs/snaps/index.js.map +1 -1
- package/dist/cjs/snaps/location/npm.js +13 -2
- package/dist/cjs/snaps/location/npm.js.map +1 -1
- package/dist/cjs/snaps/registry/json.js +10 -5
- package/dist/cjs/snaps/registry/json.js.map +1 -1
- package/dist/esm/cronjob/CronjobController.js +2 -2
- package/dist/esm/cronjob/CronjobController.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/interface/SnapInterfaceController.js +158 -0
- package/dist/esm/interface/SnapInterfaceController.js.map +1 -0
- package/dist/esm/interface/index.js +3 -0
- package/dist/esm/interface/index.js.map +1 -0
- package/dist/esm/interface/utils.js +62 -0
- package/dist/esm/interface/utils.js.map +1 -0
- package/dist/esm/services/browser.js +1 -0
- package/dist/esm/services/browser.js.map +1 -1
- package/dist/esm/services/index.js +1 -0
- package/dist/esm/services/index.js.map +1 -1
- package/dist/esm/services/webview/WebViewExecutionService.js +89 -0
- package/dist/esm/services/webview/WebViewExecutionService.js.map +1 -0
- package/dist/esm/services/webview/WebViewMessageStream.js +119 -0
- package/dist/esm/services/webview/WebViewMessageStream.js.map +1 -0
- package/dist/esm/services/webview/index.js +3 -0
- package/dist/esm/services/webview/index.js.map +1 -0
- package/dist/esm/snaps/SnapController.js +105 -45
- package/dist/esm/snaps/SnapController.js.map +1 -1
- package/dist/esm/snaps/constants.js +16 -0
- package/dist/esm/snaps/constants.js.map +1 -0
- package/dist/esm/snaps/index.js +0 -2
- package/dist/esm/snaps/index.js.map +1 -1
- package/dist/esm/snaps/location/npm.js +13 -2
- package/dist/esm/snaps/location/npm.js.map +1 -1
- package/dist/esm/snaps/registry/json.js +10 -5
- package/dist/esm/snaps/registry/json.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/interface/SnapInterfaceController.d.ts +85 -0
- package/dist/types/interface/index.d.ts +1 -0
- package/dist/types/interface/utils.d.ts +36 -0
- package/dist/types/services/browser.d.ts +1 -0
- package/dist/types/services/index.d.ts +1 -0
- package/dist/types/services/webview/WebViewExecutionService.d.ts +20 -0
- package/dist/types/services/webview/WebViewMessageStream.d.ts +32 -0
- package/dist/types/services/webview/index.d.ts +1 -0
- package/dist/types/snaps/SnapController.d.ts +7 -4
- package/dist/types/snaps/constants.d.ts +1 -0
- package/dist/types/snaps/index.d.ts +0 -2
- package/dist/types/utils.d.ts +33 -13
- package/package.json +12 -12
- package/dist/cjs/snaps/endowments/cronjob.js +0 -100
- package/dist/cjs/snaps/endowments/cronjob.js.map +0 -1
- package/dist/cjs/snaps/endowments/enum.js +0 -26
- package/dist/cjs/snaps/endowments/enum.js.map +0 -1
- package/dist/cjs/snaps/endowments/ethereum-provider.js +0 -43
- package/dist/cjs/snaps/endowments/ethereum-provider.js.map +0 -1
- package/dist/cjs/snaps/endowments/home-page.js +0 -37
- package/dist/cjs/snaps/endowments/home-page.js.map +0 -1
- package/dist/cjs/snaps/endowments/index.js +0 -107
- package/dist/cjs/snaps/endowments/index.js.map +0 -1
- package/dist/cjs/snaps/endowments/keyring.js +0 -100
- package/dist/cjs/snaps/endowments/keyring.js.map +0 -1
- package/dist/cjs/snaps/endowments/lifecycle-hooks.js +0 -37
- package/dist/cjs/snaps/endowments/lifecycle-hooks.js.map +0 -1
- package/dist/cjs/snaps/endowments/name-lookup.js +0 -106
- package/dist/cjs/snaps/endowments/name-lookup.js.map +0 -1
- package/dist/cjs/snaps/endowments/network-access.js +0 -44
- package/dist/cjs/snaps/endowments/network-access.js.map +0 -1
- package/dist/cjs/snaps/endowments/rpc.js +0 -99
- package/dist/cjs/snaps/endowments/rpc.js.map +0 -1
- package/dist/cjs/snaps/endowments/signature-insight.js +0 -106
- package/dist/cjs/snaps/endowments/signature-insight.js.map +0 -1
- package/dist/cjs/snaps/endowments/transaction-insight.js +0 -106
- package/dist/cjs/snaps/endowments/transaction-insight.js.map +0 -1
- package/dist/cjs/snaps/endowments/web-assembly.js +0 -42
- package/dist/cjs/snaps/endowments/web-assembly.js.map +0 -1
- package/dist/cjs/snaps/permissions.js +0 -61
- package/dist/cjs/snaps/permissions.js.map +0 -1
- package/dist/esm/snaps/endowments/cronjob.js +0 -99
- package/dist/esm/snaps/endowments/cronjob.js.map +0 -1
- package/dist/esm/snaps/endowments/enum.js +0 -16
- package/dist/esm/snaps/endowments/enum.js.map +0 -1
- package/dist/esm/snaps/endowments/ethereum-provider.js +0 -33
- package/dist/esm/snaps/endowments/ethereum-provider.js.map +0 -1
- package/dist/esm/snaps/endowments/home-page.js +0 -27
- package/dist/esm/snaps/endowments/home-page.js.map +0 -1
- package/dist/esm/snaps/endowments/index.js +0 -60
- package/dist/esm/snaps/endowments/index.js.map +0 -1
- package/dist/esm/snaps/endowments/keyring.js +0 -91
- package/dist/esm/snaps/endowments/keyring.js.map +0 -1
- package/dist/esm/snaps/endowments/lifecycle-hooks.js +0 -27
- package/dist/esm/snaps/endowments/lifecycle-hooks.js.map +0 -1
- package/dist/esm/snaps/endowments/name-lookup.js +0 -98
- package/dist/esm/snaps/endowments/name-lookup.js.map +0 -1
- package/dist/esm/snaps/endowments/network-access.js +0 -34
- package/dist/esm/snaps/endowments/network-access.js.map +0 -1
- package/dist/esm/snaps/endowments/rpc.js +0 -88
- package/dist/esm/snaps/endowments/rpc.js.map +0 -1
- package/dist/esm/snaps/endowments/signature-insight.js +0 -99
- package/dist/esm/snaps/endowments/signature-insight.js.map +0 -1
- package/dist/esm/snaps/endowments/transaction-insight.js +0 -99
- package/dist/esm/snaps/endowments/transaction-insight.js.map +0 -1
- package/dist/esm/snaps/endowments/web-assembly.js +0 -32
- package/dist/esm/snaps/endowments/web-assembly.js.map +0 -1
- package/dist/esm/snaps/permissions.js +0 -50
- package/dist/esm/snaps/permissions.js.map +0 -1
- package/dist/types/snaps/endowments/cronjob.d.ts +0 -51
- package/dist/types/snaps/endowments/enum.d.ts +0 -13
- package/dist/types/snaps/endowments/ethereum-provider.d.ts +0 -14
- package/dist/types/snaps/endowments/home-page.d.ts +0 -15
- package/dist/types/snaps/endowments/index.d.ts +0 -127
- package/dist/types/snaps/endowments/keyring.d.ts +0 -39
- package/dist/types/snaps/endowments/lifecycle-hooks.d.ts +0 -15
- package/dist/types/snaps/endowments/name-lookup.d.ts +0 -38
- package/dist/types/snaps/endowments/network-access.d.ts +0 -14
- package/dist/types/snaps/endowments/rpc.d.ts +0 -38
- package/dist/types/snaps/endowments/signature-insight.d.ts +0 -39
- package/dist/types/snaps/endowments/transaction-insight.d.ts +0 -39
- package/dist/types/snaps/endowments/web-assembly.d.ts +0 -14
- package/dist/types/snaps/permissions.d.ts +0 -16
|
@@ -64,20 +64,17 @@ function _define_property(obj, key, value) {
|
|
|
64
64
|
import { BaseController } from '@metamask/base-controller';
|
|
65
65
|
import { SubjectType } from '@metamask/permission-controller';
|
|
66
66
|
import { rpcErrors } from '@metamask/rpc-errors';
|
|
67
|
-
import { WALLET_SNAP_PERMISSION_KEY } from '@metamask/snaps-rpc-methods';
|
|
67
|
+
import { WALLET_SNAP_PERMISSION_KEY, getMaxRequestTimeCaveat, handlerEndowments, SnapEndowments, getKeyringCaveatOrigins, getRpcCaveatOrigins, processSnapPermissions } from '@metamask/snaps-rpc-methods';
|
|
68
68
|
import { AuxiliaryFileEncoding, getErrorMessage } from '@metamask/snaps-sdk';
|
|
69
|
-
import {
|
|
69
|
+
import { assertIsSnapManifest, assertIsValidSnapId, DEFAULT_ENDOWMENTS, DEFAULT_REQUESTED_SNAP_VERSION, encodeAuxiliaryFile, HandlerType, isOriginAllowed, logError, normalizeRelative, OnTransactionResponseStruct, OnSignatureResponseStruct, resolveVersionRange, SnapCaveatType, SnapStatus, SnapStatusEvents, unwrapError, OnHomePageResponseStruct, getValidatedLocalizationFiles, VirtualFile, NpmSnapFileNames, OnNameLookupResponseStruct, getLocalizedSnapManifest } 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';
|
|
73
73
|
import { forceStrict, validateMachine } from '../fsm';
|
|
74
74
|
import { log } from '../logging';
|
|
75
75
|
import { fetchSnap, hasTimedOut, setDiff, withTimeout } from '../utils';
|
|
76
|
-
import {
|
|
77
|
-
import { getKeyringCaveatOrigins } from './endowments/keyring';
|
|
78
|
-
import { getRpcCaveatOrigins } from './endowments/rpc';
|
|
76
|
+
import { ALLOWED_PERMISSIONS } from './constants';
|
|
79
77
|
import { detectSnapLocation } from './location';
|
|
80
|
-
import { processSnapPermissions } from './permissions';
|
|
81
78
|
import { SnapsRegistryStatus } from './registry';
|
|
82
79
|
import { RequestQueue } from './RequestQueue';
|
|
83
80
|
import { Timer } from './Timer';
|
|
@@ -164,11 +161,19 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
164
161
|
* @param args - The add snap args.
|
|
165
162
|
* @returns The resulting snap object.
|
|
166
163
|
*/ _set = /*#__PURE__*/ new WeakSet(), _validateSnapPermissions = /*#__PURE__*/ new WeakSet(), /**
|
|
164
|
+
* Determine the execution timeout for a given handler permission.
|
|
165
|
+
*
|
|
166
|
+
* If no permission is specified or the permission itself has no execution timeout defined
|
|
167
|
+
* the constructor argument `maxRequestTime` will be used.
|
|
168
|
+
*
|
|
169
|
+
* @param permission - An optional permission constraint for the handler being called.
|
|
170
|
+
* @returns The execution timeout for the given handler.
|
|
171
|
+
*/ _getExecutionTimeout = /*#__PURE__*/ new WeakSet(), /**
|
|
167
172
|
* Gets the RPC message handler for the given snap.
|
|
168
173
|
*
|
|
169
174
|
* @param snapId - The id of the Snap whose message handler to get.
|
|
170
175
|
* @returns The RPC handler for the given snap.
|
|
171
|
-
*/ _getRpcRequestHandler = /*#__PURE__*/ new WeakSet(),
|
|
176
|
+
*/ _getRpcRequestHandler = /*#__PURE__*/ new WeakSet(), _createInterface = /*#__PURE__*/ new WeakSet(), _assertInterfaceExists = /*#__PURE__*/ new WeakSet(), _transformSnapRpcRequestResult = /*#__PURE__*/ new WeakSet(), _assertSnapRpcRequestResult = /*#__PURE__*/ new WeakSet(), _executeWithTimeout = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestStart = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestFinish = /*#__PURE__*/ new WeakSet(), /**
|
|
172
177
|
* Retrieves the rollback snapshot of a snap.
|
|
173
178
|
*
|
|
174
179
|
* @param snapId - The snap id.
|
|
@@ -765,7 +770,8 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
765
770
|
}
|
|
766
771
|
await _class_private_method_get(this, _assertIsInstallAllowed, assertIsInstallAllowed).call(this, snapId, {
|
|
767
772
|
version: newVersion,
|
|
768
|
-
checksum: manifest.source.shasum
|
|
773
|
+
checksum: manifest.source.shasum,
|
|
774
|
+
permissions: manifest.initialPermissions
|
|
769
775
|
});
|
|
770
776
|
const processedPermissions = processSnapPermissions(manifest.initialPermissions);
|
|
771
777
|
_class_private_method_get(this, _validateSnapPermissions, validateSnapPermissions).call(this, processedPermissions);
|
|
@@ -912,29 +918,32 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
912
918
|
};
|
|
913
919
|
assertIsJsonRpcRequest(request);
|
|
914
920
|
const permissionName = handlerEndowments[handlerType];
|
|
915
|
-
|
|
916
|
-
|
|
921
|
+
assert(typeof permissionName === 'string' || permissionName === null, "'permissionName' must be either a string or null.");
|
|
922
|
+
const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
|
|
923
|
+
// If permissionName is null, the handler does not require a permission.
|
|
924
|
+
if (permissionName !== null && (!permissions || !hasProperty(permissions, permissionName))) {
|
|
917
925
|
throw new Error(`Snap "${snapId}" is not permitted to use "${permissionName}".`);
|
|
918
926
|
}
|
|
927
|
+
const handlerPermissions = permissionName ? permissions[permissionName] : undefined;
|
|
919
928
|
if (permissionName === SnapEndowments.Rpc || permissionName === SnapEndowments.Keyring) {
|
|
920
|
-
const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
921
|
-
const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
|
|
922
|
-
const handlerPermissions = permissions?.[permissionName];
|
|
923
929
|
assert(handlerPermissions);
|
|
930
|
+
const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
|
|
924
931
|
const origins = permissionName === SnapEndowments.Rpc ? getRpcCaveatOrigins(handlerPermissions) : getKeyringCaveatOrigins(handlerPermissions);
|
|
925
932
|
assert(origins);
|
|
926
933
|
if (!isOriginAllowed(origins, subject?.subjectType ?? SubjectType.Website, origin)) {
|
|
927
934
|
throw new Error(`Snap "${snapId}" is not permitted to handle requests from "${origin}".`);
|
|
928
935
|
}
|
|
929
936
|
}
|
|
930
|
-
const handler =
|
|
937
|
+
const handler = _class_private_method_get(this, _getRpcRequestHandler, getRpcRequestHandler).call(this, snapId);
|
|
931
938
|
if (!handler) {
|
|
932
939
|
throw new Error(`Snap RPC message handler not found for snap "${snapId}".`);
|
|
933
940
|
}
|
|
941
|
+
const timeout = _class_private_method_get(this, _getExecutionTimeout, getExecutionTimeout).call(this, handlerPermissions);
|
|
934
942
|
return handler({
|
|
935
943
|
origin,
|
|
936
944
|
handler: handlerType,
|
|
937
|
-
request
|
|
945
|
+
request,
|
|
946
|
+
timeout
|
|
938
947
|
});
|
|
939
948
|
}
|
|
940
949
|
constructor({ closeAllConnections, messenger, state, dynamicPermissions = [
|
|
@@ -1025,12 +1034,28 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
1025
1034
|
*/ _class_private_method_init(this, _getEndowments);
|
|
1026
1035
|
_class_private_method_init(this, _set);
|
|
1027
1036
|
_class_private_method_init(this, _validateSnapPermissions);
|
|
1037
|
+
_class_private_method_init(this, _getExecutionTimeout);
|
|
1028
1038
|
_class_private_method_init(this, _getRpcRequestHandler);
|
|
1029
|
-
_class_private_method_init(this, _triggerPhishingListUpdate);
|
|
1030
|
-
_class_private_method_init(this, _checkPhishingList);
|
|
1031
1039
|
/**
|
|
1032
|
-
*
|
|
1040
|
+
* Create a dynamic interface in the SnapInterfaceController.
|
|
1041
|
+
*
|
|
1042
|
+
* @param snapId - The snap ID.
|
|
1043
|
+
* @param content - The initial interface content.
|
|
1044
|
+
* @returns An identifier that can be used to identify the interface.
|
|
1045
|
+
*/ _class_private_method_init(this, _createInterface);
|
|
1046
|
+
_class_private_method_init(this, _assertInterfaceExists);
|
|
1047
|
+
/**
|
|
1048
|
+
* Transform a RPC request result if necessary.
|
|
1033
1049
|
*
|
|
1050
|
+
* @param snapId - The snap ID of the snap that produced the result.
|
|
1051
|
+
* @param handlerType - The handler type that produced the result.
|
|
1052
|
+
* @param result - The result.
|
|
1053
|
+
* @returns The transformed result if applicable, otherwise the original result.
|
|
1054
|
+
*/ _class_private_method_init(this, _transformSnapRpcRequestResult);
|
|
1055
|
+
/**
|
|
1056
|
+
* Assert that the returned result of a Snap RPC call is the expected shape.
|
|
1057
|
+
*
|
|
1058
|
+
* @param snapId - The snap ID.
|
|
1034
1059
|
* @param handlerType - The handler type of the RPC Request.
|
|
1035
1060
|
* @param result - The result of the RPC request.
|
|
1036
1061
|
*/ _class_private_method_init(this, _assertSnapRpcRequestResult);
|
|
@@ -1343,7 +1368,9 @@ async function assertIsInstallAllowed(snapId, snapInfo) {
|
|
|
1343
1368
|
const result = results[snapId];
|
|
1344
1369
|
if (result.status === SnapsRegistryStatus.Blocked) {
|
|
1345
1370
|
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The version is blocked. ${result.reason?.explanation ?? ''}`);
|
|
1346
|
-
}
|
|
1371
|
+
}
|
|
1372
|
+
const isAllowlistingRequired = Object.keys(snapInfo.permissions).some((permission)=>!ALLOWED_PERMISSIONS.includes(permission));
|
|
1373
|
+
if (_class_private_field_get(this, _featureFlags).requireAllowlist && isAllowlistingRequired && result.status !== SnapsRegistryStatus.Verified) {
|
|
1347
1374
|
throw new Error(`Cannot install version "${snapInfo.version}" of snap "${snapId}": The snap is not on the allowlist.`);
|
|
1348
1375
|
}
|
|
1349
1376
|
}
|
|
@@ -1474,7 +1501,8 @@ async function add(args) {
|
|
|
1474
1501
|
}
|
|
1475
1502
|
await _class_private_method_get(this, _assertIsInstallAllowed, assertIsInstallAllowed).call(this, snapId, {
|
|
1476
1503
|
version: manifest.version,
|
|
1477
|
-
checksum: manifest.source.shasum
|
|
1504
|
+
checksum: manifest.source.shasum,
|
|
1505
|
+
permissions: manifest.initialPermissions
|
|
1478
1506
|
});
|
|
1479
1507
|
return _class_private_method_get(this, _set, set).call(this, {
|
|
1480
1508
|
...args,
|
|
@@ -1544,7 +1572,7 @@ function set(args) {
|
|
|
1544
1572
|
const { id: snapId, origin, files, isUpdate = false, removable, preinstalled } = args;
|
|
1545
1573
|
const { manifest, sourceCode: sourceCodeFile, svgIcon, auxiliaryFiles: rawAuxiliaryFiles, localizationFiles } = files;
|
|
1546
1574
|
assertIsSnapManifest(manifest.result);
|
|
1547
|
-
const { version
|
|
1575
|
+
const { version } = manifest.result;
|
|
1548
1576
|
const sourceCode = sourceCodeFile.toString();
|
|
1549
1577
|
assert(typeof sourceCode === 'string' && sourceCode.length > 0, `Invalid source code for snap "${snapId}".`);
|
|
1550
1578
|
const auxiliaryFiles = rawAuxiliaryFiles.map((file)=>{
|
|
@@ -1565,6 +1593,7 @@ function set(args) {
|
|
|
1565
1593
|
origin
|
|
1566
1594
|
}
|
|
1567
1595
|
];
|
|
1596
|
+
const localizedFiles = localizationFiles.map((file)=>file.result);
|
|
1568
1597
|
const snap = {
|
|
1569
1598
|
// Restore relevant snap state if it exists
|
|
1570
1599
|
...existingSnap,
|
|
@@ -1582,7 +1611,7 @@ function set(args) {
|
|
|
1582
1611
|
version,
|
|
1583
1612
|
versionHistory,
|
|
1584
1613
|
auxiliaryFiles,
|
|
1585
|
-
localizationFiles:
|
|
1614
|
+
localizationFiles: localizedFiles
|
|
1586
1615
|
};
|
|
1587
1616
|
// If the snap was blocked, it isn't any longer
|
|
1588
1617
|
delete snap.blockInformation;
|
|
@@ -1598,6 +1627,9 @@ function set(args) {
|
|
|
1598
1627
|
rollbackSnapshot.statePatches = inversePatches;
|
|
1599
1628
|
}
|
|
1600
1629
|
}
|
|
1630
|
+
// In case the Snap uses a localized manifest, we need to get the
|
|
1631
|
+
// proposed name from the localized manifest.
|
|
1632
|
+
const { proposedName } = getLocalizedSnapManifest(manifest.result, 'en', localizedFiles);
|
|
1601
1633
|
this.messagingSystem.call('SubjectMetadataController:addSubjectMetadata', {
|
|
1602
1634
|
subjectType: SubjectType.Snap,
|
|
1603
1635
|
name: proposedName,
|
|
@@ -1613,7 +1645,7 @@ function set(args) {
|
|
|
1613
1645
|
function validateSnapPermissions(processedPermissions) {
|
|
1614
1646
|
const permissionKeys = Object.keys(processedPermissions);
|
|
1615
1647
|
const handlerPermissions = Array.from(new Set(Object.values(handlerEndowments)));
|
|
1616
|
-
assert(permissionKeys.some((key)=>handlerPermissions.includes(key)), `A snap must request at least one of the following permissions: ${handlerPermissions.join(', ')}.`);
|
|
1648
|
+
assert(permissionKeys.some((key)=>handlerPermissions.includes(key)), `A snap must request at least one of the following permissions: ${handlerPermissions.filter((handler)=>handler !== null).join(', ')}.`);
|
|
1617
1649
|
const excludedPermissionErrors = permissionKeys.reduce((errors, permission)=>{
|
|
1618
1650
|
if (hasProperty(_class_private_field_get(this, _excludedPermissions), permission)) {
|
|
1619
1651
|
errors.push(_class_private_field_get(this, _excludedPermissions)[permission]);
|
|
@@ -1622,6 +1654,9 @@ function validateSnapPermissions(processedPermissions) {
|
|
|
1622
1654
|
}, []);
|
|
1623
1655
|
assert(excludedPermissionErrors.length === 0, `One or more permissions are not allowed:\n${excludedPermissionErrors.join('\n')}`);
|
|
1624
1656
|
}
|
|
1657
|
+
function getExecutionTimeout(permission) {
|
|
1658
|
+
return getMaxRequestTimeCaveat(permission) ?? this.maxRequestTime;
|
|
1659
|
+
}
|
|
1625
1660
|
function getRpcRequestHandler(snapId) {
|
|
1626
1661
|
const runtime = _class_private_method_get(this, _getRuntimeExpect, getRuntimeExpect).call(this, snapId);
|
|
1627
1662
|
const existingHandler = runtime.rpcHandler;
|
|
@@ -1632,7 +1667,7 @@ function getRpcRequestHandler(snapId) {
|
|
|
1632
1667
|
// We need to set up this promise map to map snapIds to their respective startPromises,
|
|
1633
1668
|
// because otherwise we would lose context on the correct startPromise.
|
|
1634
1669
|
const startPromises = new Map();
|
|
1635
|
-
const rpcHandler = async ({ origin, handler: handlerType, request })=>{
|
|
1670
|
+
const rpcHandler = async ({ origin, handler: handlerType, request, timeout })=>{
|
|
1636
1671
|
if (this.state.snaps[snapId].enabled === false) {
|
|
1637
1672
|
throw new Error(`Snap "${snapId}" is disabled.`);
|
|
1638
1673
|
}
|
|
@@ -1658,7 +1693,7 @@ function getRpcRequestHandler(snapId) {
|
|
|
1658
1693
|
}
|
|
1659
1694
|
}
|
|
1660
1695
|
}
|
|
1661
|
-
const timer = new Timer(
|
|
1696
|
+
const timer = new Timer(timeout);
|
|
1662
1697
|
_class_private_method_get(this, _recordSnapRpcRequestStart, recordSnapRpcRequestStart).call(this, snapId, request.id, timer);
|
|
1663
1698
|
const handleRpcRequestPromise = this.messagingSystem.call('ExecutionService:handleRpcRequest', snapId, {
|
|
1664
1699
|
origin,
|
|
@@ -1668,8 +1703,8 @@ function getRpcRequestHandler(snapId) {
|
|
|
1668
1703
|
// This will either get the result or reject due to the timeout.
|
|
1669
1704
|
try {
|
|
1670
1705
|
const result = await _class_private_method_get(this, _executeWithTimeout, executeWithTimeout).call(this, handleRpcRequestPromise, timer);
|
|
1671
|
-
await _class_private_method_get(this, _assertSnapRpcRequestResult, assertSnapRpcRequestResult).call(this, handlerType, result);
|
|
1672
|
-
return result;
|
|
1706
|
+
await _class_private_method_get(this, _assertSnapRpcRequestResult, assertSnapRpcRequestResult).call(this, snapId, handlerType, result);
|
|
1707
|
+
return _class_private_method_get(this, _transformSnapRpcRequestResult, transformSnapRpcRequestResult).call(this, snapId, handlerType, result);
|
|
1673
1708
|
} catch (error) {
|
|
1674
1709
|
const [jsonRpcError, handled] = unwrapError(error);
|
|
1675
1710
|
if (!handled) {
|
|
@@ -1683,40 +1718,64 @@ function getRpcRequestHandler(snapId) {
|
|
|
1683
1718
|
runtime.rpcHandler = rpcHandler;
|
|
1684
1719
|
return rpcHandler;
|
|
1685
1720
|
}
|
|
1686
|
-
async function
|
|
1687
|
-
return this.messagingSystem.call('
|
|
1721
|
+
async function createInterface(snapId, content) {
|
|
1722
|
+
return this.messagingSystem.call('SnapInterfaceController:createInterface', snapId, content);
|
|
1688
1723
|
}
|
|
1689
|
-
function
|
|
1690
|
-
|
|
1724
|
+
function assertInterfaceExists(snapId, id) {
|
|
1725
|
+
// This will throw if the interface isn't accessible, but we assert nevertheless.
|
|
1726
|
+
assert(this.messagingSystem.call('SnapInterfaceController:getInterface', snapId, id));
|
|
1691
1727
|
}
|
|
1692
|
-
async function
|
|
1728
|
+
async function transformSnapRpcRequestResult(snapId, handlerType, result) {
|
|
1729
|
+
switch(handlerType){
|
|
1730
|
+
case HandlerType.OnTransaction:
|
|
1731
|
+
case HandlerType.OnSignature:
|
|
1732
|
+
case HandlerType.OnHomePage:
|
|
1733
|
+
{
|
|
1734
|
+
// Since this type has been asserted earlier we can cast
|
|
1735
|
+
const castResult = result;
|
|
1736
|
+
// If a handler returns static content, we turn it into a dynamic UI
|
|
1737
|
+
if (castResult && hasProperty(castResult, 'content')) {
|
|
1738
|
+
const { content, ...rest } = castResult;
|
|
1739
|
+
const id = await _class_private_method_get(this, _createInterface, createInterface).call(this, snapId, content);
|
|
1740
|
+
return {
|
|
1741
|
+
...rest,
|
|
1742
|
+
id
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
return result;
|
|
1746
|
+
}
|
|
1747
|
+
default:
|
|
1748
|
+
return result;
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
async function assertSnapRpcRequestResult(snapId, handlerType, result) {
|
|
1693
1752
|
switch(handlerType){
|
|
1694
1753
|
case HandlerType.OnTransaction:
|
|
1695
1754
|
{
|
|
1696
1755
|
assertStruct(result, OnTransactionResponseStruct);
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
return;
|
|
1756
|
+
if (result && hasProperty(result, 'id')) {
|
|
1757
|
+
_class_private_method_get(this, _assertInterfaceExists, assertInterfaceExists).call(this, snapId, result.id);
|
|
1700
1758
|
}
|
|
1701
|
-
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
1702
|
-
validateComponentLinks(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1703
1759
|
break;
|
|
1704
1760
|
}
|
|
1705
1761
|
case HandlerType.OnSignature:
|
|
1706
1762
|
{
|
|
1707
1763
|
assertStruct(result, OnSignatureResponseStruct);
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
return;
|
|
1764
|
+
if (result && hasProperty(result, 'id')) {
|
|
1765
|
+
_class_private_method_get(this, _assertInterfaceExists, assertInterfaceExists).call(this, snapId, result.id);
|
|
1711
1766
|
}
|
|
1712
|
-
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
1713
|
-
validateComponentLinks(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1714
1767
|
break;
|
|
1715
1768
|
}
|
|
1716
1769
|
case HandlerType.OnHomePage:
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1770
|
+
{
|
|
1771
|
+
assertStruct(result, OnHomePageResponseStruct);
|
|
1772
|
+
if (result && hasProperty(result, 'id')) {
|
|
1773
|
+
_class_private_method_get(this, _assertInterfaceExists, assertInterfaceExists).call(this, snapId, result.id);
|
|
1774
|
+
}
|
|
1775
|
+
break;
|
|
1776
|
+
}
|
|
1777
|
+
case HandlerType.OnNameLookup:
|
|
1778
|
+
assertStruct(result, OnNameLookupResponseStruct);
|
|
1720
1779
|
break;
|
|
1721
1780
|
default:
|
|
1722
1781
|
break;
|
|
@@ -1869,6 +1928,7 @@ function isValidUpdate(snapId, newVersionRange) {
|
|
|
1869
1928
|
}
|
|
1870
1929
|
async function callLifecycleHook(snapId, handler) {
|
|
1871
1930
|
const permissionName = handlerEndowments[handler];
|
|
1931
|
+
assert(permissionName, 'Lifecycle hook must have an endowment.');
|
|
1872
1932
|
const hasPermission = this.messagingSystem.call('PermissionController:hasPermission', snapId, permissionName);
|
|
1873
1933
|
if (!hasPermission) {
|
|
1874
1934
|
return;
|