@metamask/snaps-controllers 3.1.1 → 3.3.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 +16 -1
- package/dist/cjs/snaps/SnapController.js +69 -17
- package/dist/cjs/snaps/SnapController.js.map +1 -1
- package/dist/cjs/snaps/endowments/enum.js +1 -0
- package/dist/cjs/snaps/endowments/enum.js.map +1 -1
- package/dist/cjs/snaps/endowments/home-page.js +37 -0
- package/dist/cjs/snaps/endowments/home-page.js.map +1 -0
- package/dist/cjs/snaps/endowments/index.js +5 -2
- package/dist/cjs/snaps/endowments/index.js.map +1 -1
- package/dist/cjs/utils.js +9 -0
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/snaps/SnapController.js +72 -20
- package/dist/esm/snaps/SnapController.js.map +1 -1
- package/dist/esm/snaps/endowments/enum.js +1 -0
- package/dist/esm/snaps/endowments/enum.js.map +1 -1
- package/dist/esm/snaps/endowments/home-page.js +27 -0
- package/dist/esm/snaps/endowments/home-page.js.map +1 -0
- package/dist/esm/snaps/endowments/index.js +5 -2
- package/dist/esm/snaps/endowments/index.js.map +1 -1
- package/dist/esm/utils.js +12 -0
- package/dist/esm/utils.js.map +1 -1
- package/dist/types/snaps/SnapController.d.ts +10 -6
- package/dist/types/snaps/endowments/enum.d.ts +2 -1
- package/dist/types/snaps/endowments/home-page.d.ts +15 -0
- package/dist/types/snaps/endowments/index.d.ts +9 -0
- package/dist/types/utils.d.ts +9 -0
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.3.0]
|
|
10
|
+
### Added
|
|
11
|
+
- Add manifest localization functionality ([#1889](https://github.com/MetaMask/snaps/pull/1889))
|
|
12
|
+
- Add support for unencrypted storage using `snap_manageState` ([#1902](https://github.com/MetaMask/snaps/pull/1902))
|
|
13
|
+
- Add `OnHomePage` export ([#1896](https://github.com/MetaMask/snaps/pull/1896))
|
|
14
|
+
|
|
15
|
+
## [3.2.0]
|
|
16
|
+
### Added
|
|
17
|
+
- Add support for links in custom UI and notifications ([#1814](https://github.com/MetaMask/snaps/pull/1814))
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Fix an issue where snaps throwing a `SnapError` would be allowed to run for longer than expected ([#1897](https://github.com/MetaMask/snaps/pull/1897))
|
|
21
|
+
|
|
9
22
|
## [3.1.1]
|
|
10
23
|
### Fixed
|
|
11
24
|
- Fix a few issues with allowlist version resolving ([#1888](https://github.com/MetaMask/snaps/pull/1888))
|
|
@@ -94,7 +107,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
94
107
|
- The version of the package no longer needs to match the version of all other
|
|
95
108
|
MetaMask Snaps packages.
|
|
96
109
|
|
|
97
|
-
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.
|
|
110
|
+
[Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.3.0...HEAD
|
|
111
|
+
[3.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.2.0...@metamask/snaps-controllers@3.3.0
|
|
112
|
+
[3.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.1.1...@metamask/snaps-controllers@3.2.0
|
|
98
113
|
[3.1.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.1.0...@metamask/snaps-controllers@3.1.1
|
|
99
114
|
[3.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.0.0...@metamask/snaps-controllers@3.1.0
|
|
100
115
|
[3.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@2.0.2...@metamask/snaps-controllers@3.0.0
|
|
@@ -29,6 +29,7 @@ const _basecontroller = require("@metamask/base-controller");
|
|
|
29
29
|
const _permissioncontroller = require("@metamask/permission-controller");
|
|
30
30
|
const _rpcerrors = require("@metamask/rpc-errors");
|
|
31
31
|
const _snapsrpcmethods = require("@metamask/snaps-rpc-methods");
|
|
32
|
+
const _snapsui = require("@metamask/snaps-ui");
|
|
32
33
|
const _snapsutils = require("@metamask/snaps-utils");
|
|
33
34
|
const _utils = require("@metamask/utils");
|
|
34
35
|
const _fsm = require("@xstate/fsm");
|
|
@@ -120,7 +121,8 @@ const TRUNCATED_SNAP_PROPERTIES = new Set([
|
|
|
120
121
|
]);
|
|
121
122
|
const defaultState = {
|
|
122
123
|
snaps: {},
|
|
123
|
-
snapStates: {}
|
|
124
|
+
snapStates: {},
|
|
125
|
+
unencryptedSnapStates: {}
|
|
124
126
|
};
|
|
125
127
|
/**
|
|
126
128
|
* Truncates the properties of a snap to only ones that are easily serializable.
|
|
@@ -192,7 +194,7 @@ _initializeStateMachine = /*#__PURE__*/ new WeakSet(), /**
|
|
|
192
194
|
*
|
|
193
195
|
* @param snapId - The id of the Snap whose message handler to get.
|
|
194
196
|
* @returns The RPC handler for the given snap.
|
|
195
|
-
*/ _getRpcRequestHandler = /*#__PURE__*/ new WeakSet(), _executeWithTimeout = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestStart = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestFinish = /*#__PURE__*/ new WeakSet(), /**
|
|
197
|
+
*/ _getRpcRequestHandler = /*#__PURE__*/ new WeakSet(), _triggerPhishingListUpdate = /*#__PURE__*/ new WeakSet(), _checkPhishingList = /*#__PURE__*/ new WeakSet(), _assertSnapRpcRequestResult = /*#__PURE__*/ new WeakSet(), _executeWithTimeout = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestStart = /*#__PURE__*/ new WeakSet(), _recordSnapRpcRequestFinish = /*#__PURE__*/ new WeakSet(), /**
|
|
196
198
|
* Retrieves the rollback snapshot of a snap.
|
|
197
199
|
*
|
|
198
200
|
* @param snapId - The snap id.
|
|
@@ -401,9 +403,14 @@ class SnapController extends _basecontroller.BaseControllerV2 {
|
|
|
401
403
|
*
|
|
402
404
|
* @param snapId - The id of the Snap whose state should be updated.
|
|
403
405
|
* @param newSnapState - The new state of the snap.
|
|
404
|
-
|
|
406
|
+
* @param encrypted - A flag to indicate whether to use encrypted storage or not.
|
|
407
|
+
*/ updateSnapState(snapId, newSnapState, encrypted) {
|
|
405
408
|
this.update((state)=>{
|
|
406
|
-
|
|
409
|
+
if (encrypted) {
|
|
410
|
+
state.snapStates[snapId] = newSnapState;
|
|
411
|
+
} else {
|
|
412
|
+
state.unencryptedSnapStates[snapId] = newSnapState;
|
|
413
|
+
}
|
|
407
414
|
});
|
|
408
415
|
}
|
|
409
416
|
/**
|
|
@@ -411,9 +418,14 @@ class SnapController extends _basecontroller.BaseControllerV2 {
|
|
|
411
418
|
* This is distinct from the state MetaMask uses to manage snaps.
|
|
412
419
|
*
|
|
413
420
|
* @param snapId - The id of the Snap whose state should be cleared.
|
|
414
|
-
|
|
421
|
+
* @param encrypted - A flag to indicate whether to use encrypted storage or not.
|
|
422
|
+
*/ clearSnapState(snapId, encrypted) {
|
|
415
423
|
this.update((state)=>{
|
|
416
|
-
|
|
424
|
+
if (encrypted) {
|
|
425
|
+
state.snapStates[snapId] = null;
|
|
426
|
+
} else {
|
|
427
|
+
state.unencryptedSnapStates[snapId] = null;
|
|
428
|
+
}
|
|
417
429
|
});
|
|
418
430
|
}
|
|
419
431
|
/**
|
|
@@ -421,10 +433,10 @@ class SnapController extends _basecontroller.BaseControllerV2 {
|
|
|
421
433
|
* This is distinct from the state MetaMask uses to manage snaps.
|
|
422
434
|
*
|
|
423
435
|
* @param snapId - The id of the Snap whose state to get.
|
|
424
|
-
* @
|
|
425
|
-
* @
|
|
426
|
-
*/
|
|
427
|
-
const state = this.state.snapStates[snapId];
|
|
436
|
+
* @param encrypted - A flag to indicate whether to use encrypted storage or not.
|
|
437
|
+
* @returns The requested snap state or null if no state exists.
|
|
438
|
+
*/ getSnapState(snapId, encrypted) {
|
|
439
|
+
const state = encrypted ? this.state.snapStates[snapId] : this.state.unencryptedSnapStates[snapId];
|
|
428
440
|
return state ?? null;
|
|
429
441
|
}
|
|
430
442
|
/**
|
|
@@ -941,6 +953,10 @@ class SnapController extends _basecontroller.BaseControllerV2 {
|
|
|
941
953
|
persist: true,
|
|
942
954
|
anonymous: false
|
|
943
955
|
},
|
|
956
|
+
unencryptedSnapStates: {
|
|
957
|
+
persist: true,
|
|
958
|
+
anonymous: false
|
|
959
|
+
},
|
|
944
960
|
snaps: {
|
|
945
961
|
persist: (snaps)=>{
|
|
946
962
|
return Object.values(snaps)// We should not persist snaps that are in the installing state,
|
|
@@ -1020,6 +1036,14 @@ class SnapController extends _basecontroller.BaseControllerV2 {
|
|
|
1020
1036
|
*/ _class_private_method_init(this, _fetchSnap);
|
|
1021
1037
|
_class_private_method_init(this, _validateSnapPermissions);
|
|
1022
1038
|
_class_private_method_init(this, _getRpcRequestHandler);
|
|
1039
|
+
_class_private_method_init(this, _triggerPhishingListUpdate);
|
|
1040
|
+
_class_private_method_init(this, _checkPhishingList);
|
|
1041
|
+
/**
|
|
1042
|
+
* Asserts that the returned result of a Snap RPC call is the expected shape.
|
|
1043
|
+
*
|
|
1044
|
+
* @param handlerType - The handler type of the RPC Request.
|
|
1045
|
+
* @param result - The result of the RPC request.
|
|
1046
|
+
*/ _class_private_method_init(this, _assertSnapRpcRequestResult);
|
|
1023
1047
|
/**
|
|
1024
1048
|
* Awaits the specified promise and rejects if the promise doesn't resolve
|
|
1025
1049
|
* before the timeout.
|
|
@@ -1212,11 +1236,11 @@ function initializeStateMachine() {
|
|
|
1212
1236
|
function registerMessageHandlers() {
|
|
1213
1237
|
this.messagingSystem.registerActionHandler(`${controllerName}:clearSnapState`, (...args)=>this.clearSnapState(...args));
|
|
1214
1238
|
this.messagingSystem.registerActionHandler(`${controllerName}:get`, (...args)=>this.get(...args));
|
|
1215
|
-
this.messagingSystem.registerActionHandler(`${controllerName}:getSnapState`,
|
|
1239
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:getSnapState`, (...args)=>this.getSnapState(...args));
|
|
1216
1240
|
this.messagingSystem.registerActionHandler(`${controllerName}:handleRequest`, async (...args)=>this.handleRequest(...args));
|
|
1217
1241
|
this.messagingSystem.registerActionHandler(`${controllerName}:has`, (...args)=>this.has(...args));
|
|
1218
1242
|
this.messagingSystem.registerActionHandler(`${controllerName}:updateBlockedSnaps`, async ()=>this.updateBlockedSnaps());
|
|
1219
|
-
this.messagingSystem.registerActionHandler(`${controllerName}:updateSnapState`,
|
|
1243
|
+
this.messagingSystem.registerActionHandler(`${controllerName}:updateSnapState`, (...args)=>this.updateSnapState(...args));
|
|
1220
1244
|
this.messagingSystem.registerActionHandler(`${controllerName}:enable`, (...args)=>this.enableSnap(...args));
|
|
1221
1245
|
this.messagingSystem.registerActionHandler(`${controllerName}:disable`, async (...args)=>this.disableSnap(...args));
|
|
1222
1246
|
this.messagingSystem.registerActionHandler(`${controllerName}:remove`, async (...args)=>this.removeSnap(...args));
|
|
@@ -1425,7 +1449,7 @@ async function getEndowments(snapId) {
|
|
|
1425
1449
|
}
|
|
1426
1450
|
function set(args) {
|
|
1427
1451
|
const { id: snapId, origin, files, isUpdate = false } = args;
|
|
1428
|
-
const { manifest, sourceCode: sourceCodeFile, svgIcon, auxiliaryFiles: rawAuxiliaryFiles } = files;
|
|
1452
|
+
const { manifest, sourceCode: sourceCodeFile, svgIcon, auxiliaryFiles: rawAuxiliaryFiles, localizationFiles } = files;
|
|
1429
1453
|
(0, _snapsutils.assertIsSnapManifest)(manifest.result);
|
|
1430
1454
|
const { version } = manifest.result;
|
|
1431
1455
|
const sourceCode = sourceCodeFile.toString();
|
|
@@ -1459,7 +1483,8 @@ function set(args) {
|
|
|
1459
1483
|
sourceCode,
|
|
1460
1484
|
version,
|
|
1461
1485
|
versionHistory,
|
|
1462
|
-
auxiliaryFiles
|
|
1486
|
+
auxiliaryFiles,
|
|
1487
|
+
localizationFiles: localizationFiles.map((file)=>file.result)
|
|
1463
1488
|
};
|
|
1464
1489
|
// If the snap was blocked, it isn't any longer
|
|
1465
1490
|
delete snap.blockInformation;
|
|
@@ -1487,12 +1512,15 @@ async function fetchSnap(snapId, location) {
|
|
|
1487
1512
|
const sourceCode = await location.fetch(manifest.result.source.location.npm.filePath);
|
|
1488
1513
|
const { iconPath } = manifest.result.source.location.npm;
|
|
1489
1514
|
const svgIcon = iconPath ? await location.fetch(iconPath) : undefined;
|
|
1490
|
-
const auxiliaryFiles =
|
|
1515
|
+
const auxiliaryFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.files);
|
|
1516
|
+
const localizationFiles = await (0, _utils1.getSnapFiles)(location, manifest.result.source.locales);
|
|
1517
|
+
const validatedLocalizationFiles = (0, _snapsutils.getValidatedLocalizationFiles)(localizationFiles);
|
|
1491
1518
|
const files = {
|
|
1492
1519
|
manifest,
|
|
1493
1520
|
sourceCode,
|
|
1494
1521
|
svgIcon,
|
|
1495
|
-
auxiliaryFiles
|
|
1522
|
+
auxiliaryFiles,
|
|
1523
|
+
localizationFiles: validatedLocalizationFiles
|
|
1496
1524
|
};
|
|
1497
1525
|
(0, _snapsutils.validateFetchedSnap)(files);
|
|
1498
1526
|
return {
|
|
@@ -1561,7 +1589,7 @@ function getRpcRequestHandler(snapId) {
|
|
|
1561
1589
|
// This will either get the result or reject due to the timeout.
|
|
1562
1590
|
try {
|
|
1563
1591
|
const result = await _class_private_method_get(this, _executeWithTimeout, executeWithTimeout).call(this, handleRpcRequestPromise, timer);
|
|
1564
|
-
_class_private_method_get(this,
|
|
1592
|
+
await _class_private_method_get(this, _assertSnapRpcRequestResult, assertSnapRpcRequestResult).call(this, handlerType, result);
|
|
1565
1593
|
return result;
|
|
1566
1594
|
} catch (error) {
|
|
1567
1595
|
const [jsonRpcError, handled] = (0, _snapsutils.unwrapError)(error);
|
|
@@ -1569,11 +1597,35 @@ function getRpcRequestHandler(snapId) {
|
|
|
1569
1597
|
await this.stopSnap(snapId, _snapsutils.SnapStatusEvents.Crash);
|
|
1570
1598
|
}
|
|
1571
1599
|
throw jsonRpcError;
|
|
1600
|
+
} finally{
|
|
1601
|
+
_class_private_method_get(this, _recordSnapRpcRequestFinish, recordSnapRpcRequestFinish).call(this, snapId, request.id);
|
|
1572
1602
|
}
|
|
1573
1603
|
};
|
|
1574
1604
|
runtime.rpcHandler = rpcHandler;
|
|
1575
1605
|
return rpcHandler;
|
|
1576
1606
|
}
|
|
1607
|
+
async function triggerPhishingListUpdate() {
|
|
1608
|
+
return this.messagingSystem.call('PhishingController:maybeUpdateState');
|
|
1609
|
+
}
|
|
1610
|
+
function checkPhishingList(origin) {
|
|
1611
|
+
return this.messagingSystem.call('PhishingController:testOrigin', origin).result;
|
|
1612
|
+
}
|
|
1613
|
+
async function assertSnapRpcRequestResult(handlerType, result) {
|
|
1614
|
+
switch(handlerType){
|
|
1615
|
+
case _snapsutils.HandlerType.OnTransaction:
|
|
1616
|
+
(0, _utils.assertStruct)(result, _snapsutils.OnTransactionResponseStruct);
|
|
1617
|
+
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
1618
|
+
(0, _snapsui.assertUILinksAreSafe)(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1619
|
+
break;
|
|
1620
|
+
case _snapsutils.HandlerType.OnHomePage:
|
|
1621
|
+
(0, _utils.assertStruct)(result, _snapsutils.OnHomePageResponseStruct);
|
|
1622
|
+
await _class_private_method_get(this, _triggerPhishingListUpdate, triggerPhishingListUpdate).call(this);
|
|
1623
|
+
(0, _snapsui.assertUILinksAreSafe)(result.content, _class_private_method_get(this, _checkPhishingList, checkPhishingList).bind(this));
|
|
1624
|
+
break;
|
|
1625
|
+
default:
|
|
1626
|
+
break;
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1577
1629
|
async function executeWithTimeout(promise, timer) {
|
|
1578
1630
|
const result = await (0, _utils1.withTimeout)(promise, timer ?? this.maxRequestTime);
|
|
1579
1631
|
if (result === _utils1.hasTimedOut) {
|