@metamask/snaps-controllers 16.0.0 → 16.1.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 CHANGED
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [16.1.1]
11
+
12
+ ### Fixed
13
+
14
+ - Override `disableSnapInstallation` feature flag when using automatic updates ([#3735](https://github.com/MetaMask/snaps/pull/3735))
15
+
16
+ ## [16.1.0]
17
+
18
+ ### Added
19
+
20
+ - Add NPM proxy support ([#3695](https://github.com/MetaMask/snaps/pull/3695))
21
+
22
+ ### Changed
23
+
24
+ - Bump `@metamask/permission-controller` from `12.0.0` to `12.1.0` ([#3714](https://github.com/MetaMask/snaps/pull/3714))
25
+ - Bump `@metamask/phishing-controller` from `13.1.0` to `15.0.0` ([#3707](https://github.com/MetaMask/snaps/pull/3707))
26
+
27
+ ### Removed
28
+
29
+ - Remove logic for granting CAIP-25 permissions ([#3723](https://github.com/MetaMask/snaps/pull/3723))
30
+
31
+ ### Fixed
32
+
33
+ - Prevent initial connections from being revoked as unused on update ([#3729](https://github.com/MetaMask/snaps/pull/3729))
34
+ - Keep dynamic permissions on update ([#3726](https://github.com/MetaMask/snaps/pull/3726))
35
+
10
36
  ## [16.0.0]
11
37
 
12
38
  ### Changed
@@ -934,7 +960,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
934
960
  - The version of the package no longer needs to match the version of all other
935
961
  MetaMask Snaps packages.
936
962
 
937
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@16.0.0...HEAD
963
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@16.1.1...HEAD
964
+ [16.1.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@16.1.0...@metamask/snaps-controllers@16.1.1
965
+ [16.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@16.0.0...@metamask/snaps-controllers@16.1.0
938
966
  [16.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@15.0.2...@metamask/snaps-controllers@16.0.0
939
967
  [15.0.2]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@15.0.1...@metamask/snaps-controllers@15.0.2
940
968
  [15.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@15.0.0...@metamask/snaps-controllers@15.0.1
@@ -83,7 +83,7 @@ class SnapController extends base_controller_1.BaseController {
83
83
  #preinstalledSnaps;
84
84
  #trackEvent;
85
85
  #trackSnapExport;
86
- constructor({ closeAllConnections, messenger, state, dynamicPermissions = ['eth_accounts'], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(undefined), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, preinstalledSnaps = null, encryptor, getMnemonicSeed, getFeatureFlags = () => ({}), clientCryptography, trackEvent, }) {
86
+ constructor({ closeAllConnections, messenger, state, dynamicPermissions = ['endowment:caip25', 'wallet_snap'], environmentEndowmentPermissions = [], excludedPermissions = {}, idleTimeCheckInterval = (0, utils_1.inMilliseconds)(5, utils_1.Duration.Second), maxIdleTime = (0, utils_1.inMilliseconds)(30, utils_1.Duration.Second), maxRequestTime = (0, utils_1.inMilliseconds)(60, utils_1.Duration.Second), fetchFunction = globalThis.fetch.bind(undefined), featureFlags = {}, detectSnapLocation: detectSnapLocationFunction = location_1.detectSnapLocation, preinstalledSnaps = null, encryptor, getMnemonicSeed, getFeatureFlags = () => ({}), clientCryptography, trackEvent, }) {
87
87
  super({
88
88
  messenger,
89
89
  metadata: {
@@ -412,6 +412,7 @@ class SnapController extends base_controller_1.BaseController {
412
412
  versionRange: resolvedVersion,
413
413
  fetch: this.#fetchFunction,
414
414
  allowLocal: false,
415
+ useNpmProxy: true,
415
416
  });
416
417
  await this.#updateSnap({
417
418
  origin: approval_controller_1.ORIGIN_METAMASK,
@@ -1407,7 +1408,9 @@ class SnapController extends base_controller_1.BaseController {
1407
1408
  * @returns The snap metadata if updated, `null` otherwise.
1408
1409
  */
1409
1410
  async #updateSnap({ origin, snapId, location, versionRange, automaticUpdate = false, }) {
1410
- this.#assertCanInstallSnaps();
1411
+ if (!automaticUpdate) {
1412
+ this.#assertCanInstallSnaps();
1413
+ }
1411
1414
  this.#assertCanUsePlatform();
1412
1415
  const snap = this.getExpect(snapId);
1413
1416
  const { preinstalled, removable, hidden, hideSnapBranding } = snap;
@@ -2303,12 +2306,41 @@ class SnapController extends base_controller_1.BaseController {
2303
2306
  getStateMutex: new async_mutex_1.Mutex(),
2304
2307
  });
2305
2308
  }
2309
+ /**
2310
+ * Get the desired permissions including dynamic permissions. That is, if a
2311
+ * dynamic permission was previously granted and at least one of its
2312
+ * dependencies is still desired, it will be included in the desired
2313
+ * permissions.
2314
+ *
2315
+ * @param oldPermissions - The old permissions.
2316
+ * @param desiredPermissions - The desired permissions.
2317
+ * @returns The desired permissions including dynamic permissions.
2318
+ */
2319
+ #getDesiredPermissions(oldPermissions, desiredPermissions) {
2320
+ return Object.keys(oldPermissions).reduce((accumulator, permissionName) => {
2321
+ if (this.#dynamicPermissions.includes(permissionName)) {
2322
+ const hasDependencies = (0, utils_1.hasProperty)(constants_1.DYNAMIC_PERMISSION_DEPENDENCIES, permissionName);
2323
+ const hasDependency = constants_1.DYNAMIC_PERMISSION_DEPENDENCIES[permissionName]?.some((dependency) => (0, utils_1.hasProperty)(desiredPermissions, dependency));
2324
+ // If the permission doesn't have dependencies, or if at least one of
2325
+ // its dependencies is desired, include it in the desired permissions.
2326
+ // NOTE: This effectively means that any permissions granted in the manifest
2327
+ // that are considered dynamic, will not be automatically revoked
2328
+ // when the permission is removed from the manifest.
2329
+ // TODO: Deal with this technical debt.
2330
+ if (!hasDependencies || hasDependency) {
2331
+ accumulator[permissionName] = oldPermissions[permissionName];
2332
+ }
2333
+ }
2334
+ return accumulator;
2335
+ }, desiredPermissions);
2336
+ }
2306
2337
  #calculatePermissionsChange(snapId, desiredPermissionsSet) {
2307
2338
  const oldPermissions = this.messenger.call('PermissionController:getPermissions', snapId) ?? {};
2308
- const newPermissions = (0, utils_2.permissionsDiff)(desiredPermissionsSet, oldPermissions);
2309
- // TODO(ritave): The assumption that these are unused only holds so long as we do not
2310
- // permit dynamic permission requests.
2311
- const unusedPermissions = (0, utils_2.permissionsDiff)(oldPermissions, desiredPermissionsSet);
2339
+ const desiredPermissionsSetWithDynamic = this.#getDesiredPermissions(oldPermissions, desiredPermissionsSet);
2340
+ const newPermissions = (0, utils_2.permissionsDiff)(desiredPermissionsSetWithDynamic, oldPermissions);
2341
+ // TODO: The assumption that these are unused only holds so long as we do
2342
+ // not permit dynamic permission requests.
2343
+ const unusedPermissions = (0, utils_2.permissionsDiff)(oldPermissions, desiredPermissionsSetWithDynamic);
2312
2344
  // It's a Set Intersection of oldPermissions and desiredPermissionsSet
2313
2345
  // oldPermissions ∖ (oldPermissions ∖ desiredPermissionsSet) ⟺ oldPermissions ∩ desiredPermissionsSet
2314
2346
  const approvedPermissions = (0, utils_2.permissionsDiff)(oldPermissions, unusedPermissions);
@@ -2335,46 +2367,6 @@ class SnapController extends base_controller_1.BaseController {
2335
2367
  const approvedConnections = (0, utils_2.setDiff)(filteredOldConnections, unusedConnections);
2336
2368
  return { newConnections, unusedConnections, approvedConnections };
2337
2369
  }
2338
- /**
2339
- * Get the permissions to grant to a Snap following an install, update or
2340
- * rollback.
2341
- *
2342
- * @param snapId - The snap ID.
2343
- * @param newPermissions - The new permissions to be granted.
2344
- * @returns The permissions to grant to the Snap.
2345
- */
2346
- #getPermissionsToGrant(snapId, newPermissions) {
2347
- if (Object.keys(newPermissions).includes(snaps_rpc_methods_1.SnapEndowments.EthereumProvider)) {
2348
- // This will return the globally selected network if the Snap doesn't have
2349
- // one set.
2350
- const networkClientId = this.messenger.call('SelectedNetworkController:getNetworkClientIdForDomain', snapId);
2351
- const { configuration } = this.messenger.call('NetworkController:getNetworkClientById', networkClientId);
2352
- const chainId = (0, utils_1.hexToNumber)(configuration.chainId);
2353
- // This needs to be assigned to have proper type inference.
2354
- const modifiedPermissions = {
2355
- ...newPermissions,
2356
- 'endowment:caip25': {
2357
- caveats: [
2358
- {
2359
- type: 'authorizedScopes',
2360
- value: {
2361
- requiredScopes: {},
2362
- optionalScopes: {
2363
- [`eip155:${chainId}`]: {
2364
- accounts: [],
2365
- },
2366
- },
2367
- sessionProperties: {},
2368
- isMultichainOrigin: false,
2369
- },
2370
- },
2371
- ],
2372
- },
2373
- };
2374
- return modifiedPermissions;
2375
- }
2376
- return newPermissions;
2377
- }
2378
2370
  /**
2379
2371
  * Update the permissions for a snap following an install, update or rollback.
2380
2372
  *
@@ -2394,9 +2386,8 @@ class SnapController extends base_controller_1.BaseController {
2394
2386
  });
2395
2387
  }
2396
2388
  if ((0, utils_1.isNonEmptyArray)(Object.keys(newPermissions))) {
2397
- const approvedPermissions = this.#getPermissionsToGrant(snapId, newPermissions);
2398
2389
  this.messenger.call('PermissionController:grantPermissions', {
2399
- approvedPermissions,
2390
+ approvedPermissions: newPermissions,
2400
2391
  subject: { origin: snapId },
2401
2392
  requestData,
2402
2393
  });