@metamask/snaps-controllers 5.0.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 CHANGED
@@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [5.0.1]
10
+ ### Fixed
11
+ - Fix issue installing non-allowlisted Snaps in allowlist mode ([#2196](https://github.com/MetaMask/snaps/pull/2196))
12
+
9
13
  ## [5.0.0]
10
14
  ### Added
11
15
  - Add support for dynamic user interfaces ([#1465](https://github.com/MetaMask/snaps/pull/1465), [#2126](https://github.com/MetaMask/snaps/pull/2126), [#2144](https://github.com/MetaMask/snaps/pull/2144), [#2152](https://github.com/MetaMask/snaps/pull/2152), [#2143](https://github.com/MetaMask/snaps/pull/2143))
@@ -188,7 +192,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
188
192
  - The version of the package no longer needs to match the version of all other
189
193
  MetaMask Snaps packages.
190
194
 
191
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@5.0.0...HEAD
195
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@5.0.1...HEAD
196
+ [5.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@5.0.0...@metamask/snaps-controllers@5.0.1
192
197
  [5.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@4.1.0...@metamask/snaps-controllers@5.0.0
193
198
  [4.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@4.0.0...@metamask/snaps-controllers@4.1.0
194
199
  [4.0.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@3.6.0...@metamask/snaps-controllers@4.0.0
@@ -117,13 +117,12 @@ class JsonSnapsRegistry extends _basecontroller.BaseController {
117
117
  _class_private_method_init(this, _getSingle);
118
118
  _class_private_method_init(this, _get);
119
119
  /**
120
- * Find an allowlisted version within a specified version range.
120
+ * Find an allowlisted version within a specified version range. Otherwise return the version range itself.
121
121
  *
122
122
  * @param snapId - The ID of the snap we are trying to resolve a version for.
123
123
  * @param versionRange - The version range.
124
124
  * @param refetch - An optional flag used to determine if we are refetching the registry.
125
- * @returns An allowlisted version within the specified version range.
126
- * @throws If an allowlisted version does not exist within the version range.
125
+ * @returns An allowlisted version within the specified version range if available otherwise returns the input version range.
127
126
  */ _class_private_method_init(this, _resolveVersion);
128
127
  /**
129
128
  * Get metadata for the given snap ID.
@@ -271,13 +270,19 @@ async function resolveVersion(snapId, versionRange, refetch = false) {
271
270
  await _class_private_method_get(this, _triggerUpdate, triggerUpdate).call(this);
272
271
  return _class_private_method_get(this, _resolveVersion, resolveVersion).call(this, snapId, versionRange, true);
273
272
  }
274
- (0, _utils.assert)(versions, 'The snap is not on the allowlist');
273
+ // If we cannot narrow down the version range we return the unaltered version range.
274
+ if (!versions) {
275
+ return versionRange;
276
+ }
275
277
  const targetVersion = (0, _snapsutils.getTargetVersion)(Object.keys(versions), versionRange);
276
278
  if (!targetVersion && _class_private_field_get(this, _refetchOnAllowlistMiss) && !refetch) {
277
279
  await _class_private_method_get(this, _triggerUpdate, triggerUpdate).call(this);
278
280
  return _class_private_method_get(this, _resolveVersion, resolveVersion).call(this, snapId, versionRange, true);
279
281
  }
280
- (0, _utils.assert)(targetVersion, 'No matching versions of the snap are on the allowlist');
282
+ // If we cannot narrow down the version range we return the unaltered version range.
283
+ if (!targetVersion) {
284
+ return versionRange;
285
+ }
281
286
  // A semver version is technically also a valid semver range.
282
287
  (0, _utils.assertIsSemVerRange)(targetVersion);
283
288
  return targetVersion;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/snaps/registry/json.ts"],"sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { SnapsRegistryDatabase } from '@metamask/snaps-registry';\nimport { verify } from '@metamask/snaps-registry';\nimport { getTargetVersion } from '@metamask/snaps-utils';\nimport type { Hex, SemVerRange, SemVerVersion } from '@metamask/utils';\nimport {\n assert,\n assertIsSemVerRange,\n Duration,\n inMilliseconds,\n satisfiesVersionRange,\n} from '@metamask/utils';\n\nimport type {\n SnapsRegistry,\n SnapsRegistryInfo,\n SnapsRegistryMetadata,\n SnapsRegistryRequest,\n SnapsRegistryResult,\n} from './registry';\nimport { SnapsRegistryStatus } from './registry';\n\n// TODO: Replace with a Codefi URL\nconst SNAP_REGISTRY_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/registry.json';\n\nconst SNAP_REGISTRY_SIGNATURE_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/signature.json';\n\ntype JsonSnapsRegistryUrl = {\n registry: string;\n signature: string;\n};\n\nexport type JsonSnapsRegistryArgs = {\n messenger: SnapsRegistryMessenger;\n state?: SnapsRegistryState;\n fetchFunction?: typeof fetch;\n url?: JsonSnapsRegistryUrl;\n recentFetchThreshold?: number;\n refetchOnAllowlistMiss?: boolean;\n failOnUnavailableRegistry?: boolean;\n publicKey?: Hex;\n};\n\nexport type GetResult = {\n type: `${typeof controllerName}:get`;\n handler: SnapsRegistry['get'];\n};\n\nexport type ResolveVersion = {\n type: `${typeof controllerName}:resolveVersion`;\n handler: SnapsRegistry['resolveVersion'];\n};\n\nexport type GetMetadata = {\n type: `${typeof controllerName}:getMetadata`;\n handler: SnapsRegistry['getMetadata'];\n};\n\nexport type Update = {\n type: `${typeof controllerName}:update`;\n handler: SnapsRegistry['update'];\n};\n\nexport type SnapsRegistryActions =\n | GetResult\n | GetMetadata\n | Update\n | ResolveVersion;\n\nexport type SnapsRegistryEvents = never;\n\nexport type SnapsRegistryMessenger = RestrictedControllerMessenger<\n 'SnapsRegistry',\n SnapsRegistryActions,\n SnapsRegistryEvents,\n SnapsRegistryActions['type'],\n SnapsRegistryEvents['type']\n>;\n\nexport type SnapsRegistryState = {\n database: SnapsRegistryDatabase | null;\n lastUpdated: number | null;\n};\n\nconst controllerName = 'SnapsRegistry';\n\nconst defaultState = {\n database: null,\n lastUpdated: null,\n};\n\nexport class JsonSnapsRegistry extends BaseController<\n typeof controllerName,\n SnapsRegistryState,\n SnapsRegistryMessenger\n> {\n #url: JsonSnapsRegistryUrl;\n\n #publicKey?: Hex;\n\n #fetchFunction: typeof fetch;\n\n #recentFetchThreshold: number;\n\n #refetchOnAllowlistMiss: boolean;\n\n #failOnUnavailableRegistry: boolean;\n\n #currentUpdate: Promise<void> | null;\n\n constructor({\n messenger,\n state,\n url = {\n registry: SNAP_REGISTRY_URL,\n signature: SNAP_REGISTRY_SIGNATURE_URL,\n },\n publicKey,\n fetchFunction = globalThis.fetch.bind(globalThis),\n recentFetchThreshold = inMilliseconds(5, Duration.Minute),\n failOnUnavailableRegistry = true,\n refetchOnAllowlistMiss = true,\n }: JsonSnapsRegistryArgs) {\n super({\n messenger,\n metadata: {\n database: { persist: true, anonymous: false },\n lastUpdated: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n ...defaultState,\n ...state,\n },\n });\n this.#url = url;\n this.#publicKey = publicKey;\n this.#fetchFunction = fetchFunction;\n this.#recentFetchThreshold = recentFetchThreshold;\n this.#refetchOnAllowlistMiss = refetchOnAllowlistMiss;\n this.#failOnUnavailableRegistry = failOnUnavailableRegistry;\n this.#currentUpdate = null;\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:get',\n async (...args) => this.#get(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:getMetadata',\n async (...args) => this.#getMetadata(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:resolveVersion',\n async (...args) => this.#resolveVersion(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:update',\n async () => this.#triggerUpdate(),\n );\n }\n\n #wasRecentlyFetched() {\n return (\n this.state.lastUpdated &&\n Date.now() - this.state.lastUpdated < this.#recentFetchThreshold\n );\n }\n\n /**\n * Triggers an update of the registry database.\n *\n * If an existing update is in progress this function will await that update.\n */\n async #triggerUpdate() {\n // If an update is ongoing, wait for that.\n if (this.#currentUpdate) {\n await this.#currentUpdate;\n return;\n }\n // If no update exists, create promise and store globally.\n if (this.#currentUpdate === null) {\n this.#currentUpdate = this.#update();\n }\n await this.#currentUpdate;\n this.#currentUpdate = null;\n }\n\n /**\n * Updates the registry database if the registry hasn't been updated recently.\n *\n * NOTE: SHOULD NOT be called directly, instead `triggerUpdate` should be used.\n */\n async #update() {\n // No-op if we recently fetched the registry.\n if (this.#wasRecentlyFetched()) {\n return;\n }\n\n try {\n const database = await this.#safeFetch(this.#url.registry);\n\n if (this.#publicKey) {\n const signature = await this.#safeFetch(this.#url.signature);\n this.#verifySignature(database, signature);\n }\n\n this.update((state) => {\n state.database = JSON.parse(database);\n state.lastUpdated = Date.now();\n });\n } catch {\n // Ignore\n }\n }\n\n async #getDatabase(): Promise<SnapsRegistryDatabase | null> {\n if (this.state.database === null) {\n await this.#triggerUpdate();\n }\n\n // If the database is still null and we require it, throw.\n if (this.#failOnUnavailableRegistry && this.state.database === null) {\n throw new Error('Snaps registry is unavailable, installation blocked.');\n }\n return this.state.database;\n }\n\n async #getSingle(\n snapId: string,\n snapInfo: SnapsRegistryInfo,\n refetch = false,\n ): Promise<SnapsRegistryResult> {\n const database = await this.#getDatabase();\n\n const blockedEntry = database?.blockedSnaps.find((blocked) => {\n if ('id' in blocked) {\n return (\n blocked.id === snapId &&\n satisfiesVersionRange(snapInfo.version, blocked.versionRange)\n );\n }\n\n return blocked.checksum === snapInfo.checksum;\n });\n\n if (blockedEntry) {\n return {\n status: SnapsRegistryStatus.Blocked,\n reason: blockedEntry.reason,\n };\n }\n\n const verified = database?.verifiedSnaps[snapId];\n const version = verified?.versions?.[snapInfo.version];\n if (version && version.checksum === snapInfo.checksum) {\n return { status: SnapsRegistryStatus.Verified };\n }\n // For now, if we have an allowlist miss, we can refetch once and try again.\n if (this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#getSingle(snapId, snapInfo, true);\n }\n return { status: SnapsRegistryStatus.Unverified };\n }\n\n async #get(\n snaps: SnapsRegistryRequest,\n ): Promise<Record<string, SnapsRegistryResult>> {\n return Object.entries(snaps).reduce<\n Promise<Record<string, SnapsRegistryResult>>\n >(async (previousPromise, [snapId, snapInfo]) => {\n const result = await this.#getSingle(snapId, snapInfo);\n const acc = await previousPromise;\n acc[snapId] = result;\n return acc;\n }, Promise.resolve({}));\n }\n\n /**\n * Find an allowlisted version within a specified version range.\n *\n * @param snapId - The ID of the snap we are trying to resolve a version for.\n * @param versionRange - The version range.\n * @param refetch - An optional flag used to determine if we are refetching the registry.\n * @returns An allowlisted version within the specified version range.\n * @throws If an allowlisted version does not exist within the version range.\n */\n async #resolveVersion(\n snapId: string,\n versionRange: SemVerRange,\n refetch = false,\n ): Promise<SemVerRange> {\n const database = await this.#getDatabase();\n const versions = database?.verifiedSnaps[snapId]?.versions ?? null;\n\n if (!versions && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n assert(versions, 'The snap is not on the allowlist');\n\n const targetVersion = getTargetVersion(\n Object.keys(versions) as SemVerVersion[],\n versionRange,\n );\n\n if (!targetVersion && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n assert(\n targetVersion,\n 'No matching versions of the snap are on the allowlist',\n );\n\n // A semver version is technically also a valid semver range.\n assertIsSemVerRange(targetVersion);\n return targetVersion;\n }\n\n /**\n * Get metadata for the given snap ID.\n *\n * @param snapId - The ID of the snap to get metadata for.\n * @returns The metadata for the given snap ID, or `null` if the snap is not\n * verified.\n */\n async #getMetadata(snapId: string): Promise<SnapsRegistryMetadata | null> {\n const database = await this.#getDatabase();\n return database?.verifiedSnaps[snapId]?.metadata ?? null;\n }\n\n /**\n * Verify the signature of the registry.\n *\n * @param database - The registry database.\n * @param signature - The signature of the registry.\n * @throws If the signature is invalid.\n * @private\n */\n #verifySignature(database: string, signature: string) {\n assert(this.#publicKey, 'No public key provided.');\n\n const valid = verify({\n registry: database,\n signature: JSON.parse(signature),\n publicKey: this.#publicKey,\n });\n\n assert(valid, 'Invalid registry signature.');\n }\n\n /**\n * Fetch the given URL, throwing if the response is not OK.\n *\n * @param url - The URL to fetch.\n * @returns The response body.\n * @private\n */\n async #safeFetch(url: string) {\n const response = await this.#fetchFunction(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}.`);\n }\n\n return await response.text();\n }\n}\n"],"names":["JsonSnapsRegistry","SNAP_REGISTRY_URL","SNAP_REGISTRY_SIGNATURE_URL","controllerName","defaultState","database","lastUpdated","BaseController","constructor","messenger","state","url","registry","signature","publicKey","fetchFunction","globalThis","fetch","bind","recentFetchThreshold","inMilliseconds","Duration","Minute","failOnUnavailableRegistry","refetchOnAllowlistMiss","metadata","persist","anonymous","name","currentUpdate","messagingSystem","registerActionHandler","args","get","getMetadata","resolveVersion","triggerUpdate","Date","now","update","wasRecentlyFetched","safeFetch","verifySignature","JSON","parse","Error","snapId","snapInfo","refetch","getDatabase","blockedEntry","blockedSnaps","find","blocked","id","satisfiesVersionRange","version","versionRange","checksum","status","SnapsRegistryStatus","Blocked","reason","verified","verifiedSnaps","versions","Verified","getSingle","Unverified","snaps","Object","entries","reduce","previousPromise","result","acc","Promise","resolve","assert","targetVersion","getTargetVersion","keys","assertIsSemVerRange","valid","verify","response","ok","text"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/snaps/registry/json.ts"],"sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { SnapsRegistryDatabase } from '@metamask/snaps-registry';\nimport { verify } from '@metamask/snaps-registry';\nimport { getTargetVersion } from '@metamask/snaps-utils';\nimport type { Hex, SemVerRange, SemVerVersion } from '@metamask/utils';\nimport {\n assert,\n assertIsSemVerRange,\n Duration,\n inMilliseconds,\n satisfiesVersionRange,\n} from '@metamask/utils';\n\nimport type {\n SnapsRegistry,\n SnapsRegistryInfo,\n SnapsRegistryMetadata,\n SnapsRegistryRequest,\n SnapsRegistryResult,\n} from './registry';\nimport { SnapsRegistryStatus } from './registry';\n\n// TODO: Replace with a Codefi URL\nconst SNAP_REGISTRY_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/registry.json';\n\nconst SNAP_REGISTRY_SIGNATURE_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/signature.json';\n\ntype JsonSnapsRegistryUrl = {\n registry: string;\n signature: string;\n};\n\nexport type JsonSnapsRegistryArgs = {\n messenger: SnapsRegistryMessenger;\n state?: SnapsRegistryState;\n fetchFunction?: typeof fetch;\n url?: JsonSnapsRegistryUrl;\n recentFetchThreshold?: number;\n refetchOnAllowlistMiss?: boolean;\n failOnUnavailableRegistry?: boolean;\n publicKey?: Hex;\n};\n\nexport type GetResult = {\n type: `${typeof controllerName}:get`;\n handler: SnapsRegistry['get'];\n};\n\nexport type ResolveVersion = {\n type: `${typeof controllerName}:resolveVersion`;\n handler: SnapsRegistry['resolveVersion'];\n};\n\nexport type GetMetadata = {\n type: `${typeof controllerName}:getMetadata`;\n handler: SnapsRegistry['getMetadata'];\n};\n\nexport type Update = {\n type: `${typeof controllerName}:update`;\n handler: SnapsRegistry['update'];\n};\n\nexport type SnapsRegistryActions =\n | GetResult\n | GetMetadata\n | Update\n | ResolveVersion;\n\nexport type SnapsRegistryEvents = never;\n\nexport type SnapsRegistryMessenger = RestrictedControllerMessenger<\n 'SnapsRegistry',\n SnapsRegistryActions,\n SnapsRegistryEvents,\n SnapsRegistryActions['type'],\n SnapsRegistryEvents['type']\n>;\n\nexport type SnapsRegistryState = {\n database: SnapsRegistryDatabase | null;\n lastUpdated: number | null;\n};\n\nconst controllerName = 'SnapsRegistry';\n\nconst defaultState = {\n database: null,\n lastUpdated: null,\n};\n\nexport class JsonSnapsRegistry extends BaseController<\n typeof controllerName,\n SnapsRegistryState,\n SnapsRegistryMessenger\n> {\n #url: JsonSnapsRegistryUrl;\n\n #publicKey?: Hex;\n\n #fetchFunction: typeof fetch;\n\n #recentFetchThreshold: number;\n\n #refetchOnAllowlistMiss: boolean;\n\n #failOnUnavailableRegistry: boolean;\n\n #currentUpdate: Promise<void> | null;\n\n constructor({\n messenger,\n state,\n url = {\n registry: SNAP_REGISTRY_URL,\n signature: SNAP_REGISTRY_SIGNATURE_URL,\n },\n publicKey,\n fetchFunction = globalThis.fetch.bind(globalThis),\n recentFetchThreshold = inMilliseconds(5, Duration.Minute),\n failOnUnavailableRegistry = true,\n refetchOnAllowlistMiss = true,\n }: JsonSnapsRegistryArgs) {\n super({\n messenger,\n metadata: {\n database: { persist: true, anonymous: false },\n lastUpdated: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n ...defaultState,\n ...state,\n },\n });\n this.#url = url;\n this.#publicKey = publicKey;\n this.#fetchFunction = fetchFunction;\n this.#recentFetchThreshold = recentFetchThreshold;\n this.#refetchOnAllowlistMiss = refetchOnAllowlistMiss;\n this.#failOnUnavailableRegistry = failOnUnavailableRegistry;\n this.#currentUpdate = null;\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:get',\n async (...args) => this.#get(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:getMetadata',\n async (...args) => this.#getMetadata(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:resolveVersion',\n async (...args) => this.#resolveVersion(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:update',\n async () => this.#triggerUpdate(),\n );\n }\n\n #wasRecentlyFetched() {\n return (\n this.state.lastUpdated &&\n Date.now() - this.state.lastUpdated < this.#recentFetchThreshold\n );\n }\n\n /**\n * Triggers an update of the registry database.\n *\n * If an existing update is in progress this function will await that update.\n */\n async #triggerUpdate() {\n // If an update is ongoing, wait for that.\n if (this.#currentUpdate) {\n await this.#currentUpdate;\n return;\n }\n // If no update exists, create promise and store globally.\n if (this.#currentUpdate === null) {\n this.#currentUpdate = this.#update();\n }\n await this.#currentUpdate;\n this.#currentUpdate = null;\n }\n\n /**\n * Updates the registry database if the registry hasn't been updated recently.\n *\n * NOTE: SHOULD NOT be called directly, instead `triggerUpdate` should be used.\n */\n async #update() {\n // No-op if we recently fetched the registry.\n if (this.#wasRecentlyFetched()) {\n return;\n }\n\n try {\n const database = await this.#safeFetch(this.#url.registry);\n\n if (this.#publicKey) {\n const signature = await this.#safeFetch(this.#url.signature);\n this.#verifySignature(database, signature);\n }\n\n this.update((state) => {\n state.database = JSON.parse(database);\n state.lastUpdated = Date.now();\n });\n } catch {\n // Ignore\n }\n }\n\n async #getDatabase(): Promise<SnapsRegistryDatabase | null> {\n if (this.state.database === null) {\n await this.#triggerUpdate();\n }\n\n // If the database is still null and we require it, throw.\n if (this.#failOnUnavailableRegistry && this.state.database === null) {\n throw new Error('Snaps registry is unavailable, installation blocked.');\n }\n return this.state.database;\n }\n\n async #getSingle(\n snapId: string,\n snapInfo: SnapsRegistryInfo,\n refetch = false,\n ): Promise<SnapsRegistryResult> {\n const database = await this.#getDatabase();\n\n const blockedEntry = database?.blockedSnaps.find((blocked) => {\n if ('id' in blocked) {\n return (\n blocked.id === snapId &&\n satisfiesVersionRange(snapInfo.version, blocked.versionRange)\n );\n }\n\n return blocked.checksum === snapInfo.checksum;\n });\n\n if (blockedEntry) {\n return {\n status: SnapsRegistryStatus.Blocked,\n reason: blockedEntry.reason,\n };\n }\n\n const verified = database?.verifiedSnaps[snapId];\n const version = verified?.versions?.[snapInfo.version];\n if (version && version.checksum === snapInfo.checksum) {\n return { status: SnapsRegistryStatus.Verified };\n }\n // For now, if we have an allowlist miss, we can refetch once and try again.\n if (this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#getSingle(snapId, snapInfo, true);\n }\n return { status: SnapsRegistryStatus.Unverified };\n }\n\n async #get(\n snaps: SnapsRegistryRequest,\n ): Promise<Record<string, SnapsRegistryResult>> {\n return Object.entries(snaps).reduce<\n Promise<Record<string, SnapsRegistryResult>>\n >(async (previousPromise, [snapId, snapInfo]) => {\n const result = await this.#getSingle(snapId, snapInfo);\n const acc = await previousPromise;\n acc[snapId] = result;\n return acc;\n }, Promise.resolve({}));\n }\n\n /**\n * Find an allowlisted version within a specified version range. Otherwise return the version range itself.\n *\n * @param snapId - The ID of the snap we are trying to resolve a version for.\n * @param versionRange - The version range.\n * @param refetch - An optional flag used to determine if we are refetching the registry.\n * @returns An allowlisted version within the specified version range if available otherwise returns the input version range.\n */\n async #resolveVersion(\n snapId: string,\n versionRange: SemVerRange,\n refetch = false,\n ): Promise<SemVerRange> {\n const database = await this.#getDatabase();\n const versions = database?.verifiedSnaps[snapId]?.versions ?? null;\n\n if (!versions && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n // If we cannot narrow down the version range we return the unaltered version range.\n if (!versions) {\n return versionRange;\n }\n\n const targetVersion = getTargetVersion(\n Object.keys(versions) as SemVerVersion[],\n versionRange,\n );\n\n if (!targetVersion && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n // If we cannot narrow down the version range we return the unaltered version range.\n if (!targetVersion) {\n return versionRange;\n }\n\n // A semver version is technically also a valid semver range.\n assertIsSemVerRange(targetVersion);\n return targetVersion;\n }\n\n /**\n * Get metadata for the given snap ID.\n *\n * @param snapId - The ID of the snap to get metadata for.\n * @returns The metadata for the given snap ID, or `null` if the snap is not\n * verified.\n */\n async #getMetadata(snapId: string): Promise<SnapsRegistryMetadata | null> {\n const database = await this.#getDatabase();\n return database?.verifiedSnaps[snapId]?.metadata ?? null;\n }\n\n /**\n * Verify the signature of the registry.\n *\n * @param database - The registry database.\n * @param signature - The signature of the registry.\n * @throws If the signature is invalid.\n * @private\n */\n #verifySignature(database: string, signature: string) {\n assert(this.#publicKey, 'No public key provided.');\n\n const valid = verify({\n registry: database,\n signature: JSON.parse(signature),\n publicKey: this.#publicKey,\n });\n\n assert(valid, 'Invalid registry signature.');\n }\n\n /**\n * Fetch the given URL, throwing if the response is not OK.\n *\n * @param url - The URL to fetch.\n * @returns The response body.\n * @private\n */\n async #safeFetch(url: string) {\n const response = await this.#fetchFunction(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}.`);\n }\n\n return await response.text();\n }\n}\n"],"names":["JsonSnapsRegistry","SNAP_REGISTRY_URL","SNAP_REGISTRY_SIGNATURE_URL","controllerName","defaultState","database","lastUpdated","BaseController","constructor","messenger","state","url","registry","signature","publicKey","fetchFunction","globalThis","fetch","bind","recentFetchThreshold","inMilliseconds","Duration","Minute","failOnUnavailableRegistry","refetchOnAllowlistMiss","metadata","persist","anonymous","name","currentUpdate","messagingSystem","registerActionHandler","args","get","getMetadata","resolveVersion","triggerUpdate","Date","now","update","wasRecentlyFetched","safeFetch","verifySignature","JSON","parse","Error","snapId","snapInfo","refetch","getDatabase","blockedEntry","blockedSnaps","find","blocked","id","satisfiesVersionRange","version","versionRange","checksum","status","SnapsRegistryStatus","Blocked","reason","verified","verifiedSnaps","versions","Verified","getSingle","Unverified","snaps","Object","entries","reduce","previousPromise","result","acc","Promise","resolve","targetVersion","getTargetVersion","keys","assertIsSemVerRange","assert","valid","verify","response","ok","text"],"mappings":"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"}
@@ -107,13 +107,12 @@ export class JsonSnapsRegistry extends BaseController {
107
107
  _class_private_method_init(this, _getSingle);
108
108
  _class_private_method_init(this, _get);
109
109
  /**
110
- * Find an allowlisted version within a specified version range.
110
+ * Find an allowlisted version within a specified version range. Otherwise return the version range itself.
111
111
  *
112
112
  * @param snapId - The ID of the snap we are trying to resolve a version for.
113
113
  * @param versionRange - The version range.
114
114
  * @param refetch - An optional flag used to determine if we are refetching the registry.
115
- * @returns An allowlisted version within the specified version range.
116
- * @throws If an allowlisted version does not exist within the version range.
115
+ * @returns An allowlisted version within the specified version range if available otherwise returns the input version range.
117
116
  */ _class_private_method_init(this, _resolveVersion);
118
117
  /**
119
118
  * Get metadata for the given snap ID.
@@ -261,13 +260,19 @@ async function resolveVersion(snapId, versionRange, refetch = false) {
261
260
  await _class_private_method_get(this, _triggerUpdate, triggerUpdate).call(this);
262
261
  return _class_private_method_get(this, _resolveVersion, resolveVersion).call(this, snapId, versionRange, true);
263
262
  }
264
- assert(versions, 'The snap is not on the allowlist');
263
+ // If we cannot narrow down the version range we return the unaltered version range.
264
+ if (!versions) {
265
+ return versionRange;
266
+ }
265
267
  const targetVersion = getTargetVersion(Object.keys(versions), versionRange);
266
268
  if (!targetVersion && _class_private_field_get(this, _refetchOnAllowlistMiss) && !refetch) {
267
269
  await _class_private_method_get(this, _triggerUpdate, triggerUpdate).call(this);
268
270
  return _class_private_method_get(this, _resolveVersion, resolveVersion).call(this, snapId, versionRange, true);
269
271
  }
270
- assert(targetVersion, 'No matching versions of the snap are on the allowlist');
272
+ // If we cannot narrow down the version range we return the unaltered version range.
273
+ if (!targetVersion) {
274
+ return versionRange;
275
+ }
271
276
  // A semver version is technically also a valid semver range.
272
277
  assertIsSemVerRange(targetVersion);
273
278
  return targetVersion;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/snaps/registry/json.ts"],"sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { SnapsRegistryDatabase } from '@metamask/snaps-registry';\nimport { verify } from '@metamask/snaps-registry';\nimport { getTargetVersion } from '@metamask/snaps-utils';\nimport type { Hex, SemVerRange, SemVerVersion } from '@metamask/utils';\nimport {\n assert,\n assertIsSemVerRange,\n Duration,\n inMilliseconds,\n satisfiesVersionRange,\n} from '@metamask/utils';\n\nimport type {\n SnapsRegistry,\n SnapsRegistryInfo,\n SnapsRegistryMetadata,\n SnapsRegistryRequest,\n SnapsRegistryResult,\n} from './registry';\nimport { SnapsRegistryStatus } from './registry';\n\n// TODO: Replace with a Codefi URL\nconst SNAP_REGISTRY_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/registry.json';\n\nconst SNAP_REGISTRY_SIGNATURE_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/signature.json';\n\ntype JsonSnapsRegistryUrl = {\n registry: string;\n signature: string;\n};\n\nexport type JsonSnapsRegistryArgs = {\n messenger: SnapsRegistryMessenger;\n state?: SnapsRegistryState;\n fetchFunction?: typeof fetch;\n url?: JsonSnapsRegistryUrl;\n recentFetchThreshold?: number;\n refetchOnAllowlistMiss?: boolean;\n failOnUnavailableRegistry?: boolean;\n publicKey?: Hex;\n};\n\nexport type GetResult = {\n type: `${typeof controllerName}:get`;\n handler: SnapsRegistry['get'];\n};\n\nexport type ResolveVersion = {\n type: `${typeof controllerName}:resolveVersion`;\n handler: SnapsRegistry['resolveVersion'];\n};\n\nexport type GetMetadata = {\n type: `${typeof controllerName}:getMetadata`;\n handler: SnapsRegistry['getMetadata'];\n};\n\nexport type Update = {\n type: `${typeof controllerName}:update`;\n handler: SnapsRegistry['update'];\n};\n\nexport type SnapsRegistryActions =\n | GetResult\n | GetMetadata\n | Update\n | ResolveVersion;\n\nexport type SnapsRegistryEvents = never;\n\nexport type SnapsRegistryMessenger = RestrictedControllerMessenger<\n 'SnapsRegistry',\n SnapsRegistryActions,\n SnapsRegistryEvents,\n SnapsRegistryActions['type'],\n SnapsRegistryEvents['type']\n>;\n\nexport type SnapsRegistryState = {\n database: SnapsRegistryDatabase | null;\n lastUpdated: number | null;\n};\n\nconst controllerName = 'SnapsRegistry';\n\nconst defaultState = {\n database: null,\n lastUpdated: null,\n};\n\nexport class JsonSnapsRegistry extends BaseController<\n typeof controllerName,\n SnapsRegistryState,\n SnapsRegistryMessenger\n> {\n #url: JsonSnapsRegistryUrl;\n\n #publicKey?: Hex;\n\n #fetchFunction: typeof fetch;\n\n #recentFetchThreshold: number;\n\n #refetchOnAllowlistMiss: boolean;\n\n #failOnUnavailableRegistry: boolean;\n\n #currentUpdate: Promise<void> | null;\n\n constructor({\n messenger,\n state,\n url = {\n registry: SNAP_REGISTRY_URL,\n signature: SNAP_REGISTRY_SIGNATURE_URL,\n },\n publicKey,\n fetchFunction = globalThis.fetch.bind(globalThis),\n recentFetchThreshold = inMilliseconds(5, Duration.Minute),\n failOnUnavailableRegistry = true,\n refetchOnAllowlistMiss = true,\n }: JsonSnapsRegistryArgs) {\n super({\n messenger,\n metadata: {\n database: { persist: true, anonymous: false },\n lastUpdated: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n ...defaultState,\n ...state,\n },\n });\n this.#url = url;\n this.#publicKey = publicKey;\n this.#fetchFunction = fetchFunction;\n this.#recentFetchThreshold = recentFetchThreshold;\n this.#refetchOnAllowlistMiss = refetchOnAllowlistMiss;\n this.#failOnUnavailableRegistry = failOnUnavailableRegistry;\n this.#currentUpdate = null;\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:get',\n async (...args) => this.#get(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:getMetadata',\n async (...args) => this.#getMetadata(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:resolveVersion',\n async (...args) => this.#resolveVersion(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:update',\n async () => this.#triggerUpdate(),\n );\n }\n\n #wasRecentlyFetched() {\n return (\n this.state.lastUpdated &&\n Date.now() - this.state.lastUpdated < this.#recentFetchThreshold\n );\n }\n\n /**\n * Triggers an update of the registry database.\n *\n * If an existing update is in progress this function will await that update.\n */\n async #triggerUpdate() {\n // If an update is ongoing, wait for that.\n if (this.#currentUpdate) {\n await this.#currentUpdate;\n return;\n }\n // If no update exists, create promise and store globally.\n if (this.#currentUpdate === null) {\n this.#currentUpdate = this.#update();\n }\n await this.#currentUpdate;\n this.#currentUpdate = null;\n }\n\n /**\n * Updates the registry database if the registry hasn't been updated recently.\n *\n * NOTE: SHOULD NOT be called directly, instead `triggerUpdate` should be used.\n */\n async #update() {\n // No-op if we recently fetched the registry.\n if (this.#wasRecentlyFetched()) {\n return;\n }\n\n try {\n const database = await this.#safeFetch(this.#url.registry);\n\n if (this.#publicKey) {\n const signature = await this.#safeFetch(this.#url.signature);\n this.#verifySignature(database, signature);\n }\n\n this.update((state) => {\n state.database = JSON.parse(database);\n state.lastUpdated = Date.now();\n });\n } catch {\n // Ignore\n }\n }\n\n async #getDatabase(): Promise<SnapsRegistryDatabase | null> {\n if (this.state.database === null) {\n await this.#triggerUpdate();\n }\n\n // If the database is still null and we require it, throw.\n if (this.#failOnUnavailableRegistry && this.state.database === null) {\n throw new Error('Snaps registry is unavailable, installation blocked.');\n }\n return this.state.database;\n }\n\n async #getSingle(\n snapId: string,\n snapInfo: SnapsRegistryInfo,\n refetch = false,\n ): Promise<SnapsRegistryResult> {\n const database = await this.#getDatabase();\n\n const blockedEntry = database?.blockedSnaps.find((blocked) => {\n if ('id' in blocked) {\n return (\n blocked.id === snapId &&\n satisfiesVersionRange(snapInfo.version, blocked.versionRange)\n );\n }\n\n return blocked.checksum === snapInfo.checksum;\n });\n\n if (blockedEntry) {\n return {\n status: SnapsRegistryStatus.Blocked,\n reason: blockedEntry.reason,\n };\n }\n\n const verified = database?.verifiedSnaps[snapId];\n const version = verified?.versions?.[snapInfo.version];\n if (version && version.checksum === snapInfo.checksum) {\n return { status: SnapsRegistryStatus.Verified };\n }\n // For now, if we have an allowlist miss, we can refetch once and try again.\n if (this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#getSingle(snapId, snapInfo, true);\n }\n return { status: SnapsRegistryStatus.Unverified };\n }\n\n async #get(\n snaps: SnapsRegistryRequest,\n ): Promise<Record<string, SnapsRegistryResult>> {\n return Object.entries(snaps).reduce<\n Promise<Record<string, SnapsRegistryResult>>\n >(async (previousPromise, [snapId, snapInfo]) => {\n const result = await this.#getSingle(snapId, snapInfo);\n const acc = await previousPromise;\n acc[snapId] = result;\n return acc;\n }, Promise.resolve({}));\n }\n\n /**\n * Find an allowlisted version within a specified version range.\n *\n * @param snapId - The ID of the snap we are trying to resolve a version for.\n * @param versionRange - The version range.\n * @param refetch - An optional flag used to determine if we are refetching the registry.\n * @returns An allowlisted version within the specified version range.\n * @throws If an allowlisted version does not exist within the version range.\n */\n async #resolveVersion(\n snapId: string,\n versionRange: SemVerRange,\n refetch = false,\n ): Promise<SemVerRange> {\n const database = await this.#getDatabase();\n const versions = database?.verifiedSnaps[snapId]?.versions ?? null;\n\n if (!versions && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n assert(versions, 'The snap is not on the allowlist');\n\n const targetVersion = getTargetVersion(\n Object.keys(versions) as SemVerVersion[],\n versionRange,\n );\n\n if (!targetVersion && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n assert(\n targetVersion,\n 'No matching versions of the snap are on the allowlist',\n );\n\n // A semver version is technically also a valid semver range.\n assertIsSemVerRange(targetVersion);\n return targetVersion;\n }\n\n /**\n * Get metadata for the given snap ID.\n *\n * @param snapId - The ID of the snap to get metadata for.\n * @returns The metadata for the given snap ID, or `null` if the snap is not\n * verified.\n */\n async #getMetadata(snapId: string): Promise<SnapsRegistryMetadata | null> {\n const database = await this.#getDatabase();\n return database?.verifiedSnaps[snapId]?.metadata ?? null;\n }\n\n /**\n * Verify the signature of the registry.\n *\n * @param database - The registry database.\n * @param signature - The signature of the registry.\n * @throws If the signature is invalid.\n * @private\n */\n #verifySignature(database: string, signature: string) {\n assert(this.#publicKey, 'No public key provided.');\n\n const valid = verify({\n registry: database,\n signature: JSON.parse(signature),\n publicKey: this.#publicKey,\n });\n\n assert(valid, 'Invalid registry signature.');\n }\n\n /**\n * Fetch the given URL, throwing if the response is not OK.\n *\n * @param url - The URL to fetch.\n * @returns The response body.\n * @private\n */\n async #safeFetch(url: string) {\n const response = await this.#fetchFunction(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}.`);\n }\n\n return await response.text();\n }\n}\n"],"names":["BaseController","verify","getTargetVersion","assert","assertIsSemVerRange","Duration","inMilliseconds","satisfiesVersionRange","SnapsRegistryStatus","SNAP_REGISTRY_URL","SNAP_REGISTRY_SIGNATURE_URL","controllerName","defaultState","database","lastUpdated","JsonSnapsRegistry","constructor","messenger","state","url","registry","signature","publicKey","fetchFunction","globalThis","fetch","bind","recentFetchThreshold","Minute","failOnUnavailableRegistry","refetchOnAllowlistMiss","metadata","persist","anonymous","name","currentUpdate","messagingSystem","registerActionHandler","args","get","getMetadata","resolveVersion","triggerUpdate","Date","now","update","wasRecentlyFetched","safeFetch","verifySignature","JSON","parse","Error","snapId","snapInfo","refetch","getDatabase","blockedEntry","blockedSnaps","find","blocked","id","version","versionRange","checksum","status","Blocked","reason","verified","verifiedSnaps","versions","Verified","getSingle","Unverified","snaps","Object","entries","reduce","previousPromise","result","acc","Promise","resolve","targetVersion","keys","valid","response","ok","text"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../src/snaps/registry/json.ts"],"sourcesContent":["import type { RestrictedControllerMessenger } from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { SnapsRegistryDatabase } from '@metamask/snaps-registry';\nimport { verify } from '@metamask/snaps-registry';\nimport { getTargetVersion } from '@metamask/snaps-utils';\nimport type { Hex, SemVerRange, SemVerVersion } from '@metamask/utils';\nimport {\n assert,\n assertIsSemVerRange,\n Duration,\n inMilliseconds,\n satisfiesVersionRange,\n} from '@metamask/utils';\n\nimport type {\n SnapsRegistry,\n SnapsRegistryInfo,\n SnapsRegistryMetadata,\n SnapsRegistryRequest,\n SnapsRegistryResult,\n} from './registry';\nimport { SnapsRegistryStatus } from './registry';\n\n// TODO: Replace with a Codefi URL\nconst SNAP_REGISTRY_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/registry.json';\n\nconst SNAP_REGISTRY_SIGNATURE_URL =\n 'https://cdn.jsdelivr.net/gh/MetaMask/snaps-registry@gh-pages/latest/signature.json';\n\ntype JsonSnapsRegistryUrl = {\n registry: string;\n signature: string;\n};\n\nexport type JsonSnapsRegistryArgs = {\n messenger: SnapsRegistryMessenger;\n state?: SnapsRegistryState;\n fetchFunction?: typeof fetch;\n url?: JsonSnapsRegistryUrl;\n recentFetchThreshold?: number;\n refetchOnAllowlistMiss?: boolean;\n failOnUnavailableRegistry?: boolean;\n publicKey?: Hex;\n};\n\nexport type GetResult = {\n type: `${typeof controllerName}:get`;\n handler: SnapsRegistry['get'];\n};\n\nexport type ResolveVersion = {\n type: `${typeof controllerName}:resolveVersion`;\n handler: SnapsRegistry['resolveVersion'];\n};\n\nexport type GetMetadata = {\n type: `${typeof controllerName}:getMetadata`;\n handler: SnapsRegistry['getMetadata'];\n};\n\nexport type Update = {\n type: `${typeof controllerName}:update`;\n handler: SnapsRegistry['update'];\n};\n\nexport type SnapsRegistryActions =\n | GetResult\n | GetMetadata\n | Update\n | ResolveVersion;\n\nexport type SnapsRegistryEvents = never;\n\nexport type SnapsRegistryMessenger = RestrictedControllerMessenger<\n 'SnapsRegistry',\n SnapsRegistryActions,\n SnapsRegistryEvents,\n SnapsRegistryActions['type'],\n SnapsRegistryEvents['type']\n>;\n\nexport type SnapsRegistryState = {\n database: SnapsRegistryDatabase | null;\n lastUpdated: number | null;\n};\n\nconst controllerName = 'SnapsRegistry';\n\nconst defaultState = {\n database: null,\n lastUpdated: null,\n};\n\nexport class JsonSnapsRegistry extends BaseController<\n typeof controllerName,\n SnapsRegistryState,\n SnapsRegistryMessenger\n> {\n #url: JsonSnapsRegistryUrl;\n\n #publicKey?: Hex;\n\n #fetchFunction: typeof fetch;\n\n #recentFetchThreshold: number;\n\n #refetchOnAllowlistMiss: boolean;\n\n #failOnUnavailableRegistry: boolean;\n\n #currentUpdate: Promise<void> | null;\n\n constructor({\n messenger,\n state,\n url = {\n registry: SNAP_REGISTRY_URL,\n signature: SNAP_REGISTRY_SIGNATURE_URL,\n },\n publicKey,\n fetchFunction = globalThis.fetch.bind(globalThis),\n recentFetchThreshold = inMilliseconds(5, Duration.Minute),\n failOnUnavailableRegistry = true,\n refetchOnAllowlistMiss = true,\n }: JsonSnapsRegistryArgs) {\n super({\n messenger,\n metadata: {\n database: { persist: true, anonymous: false },\n lastUpdated: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n ...defaultState,\n ...state,\n },\n });\n this.#url = url;\n this.#publicKey = publicKey;\n this.#fetchFunction = fetchFunction;\n this.#recentFetchThreshold = recentFetchThreshold;\n this.#refetchOnAllowlistMiss = refetchOnAllowlistMiss;\n this.#failOnUnavailableRegistry = failOnUnavailableRegistry;\n this.#currentUpdate = null;\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:get',\n async (...args) => this.#get(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:getMetadata',\n async (...args) => this.#getMetadata(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:resolveVersion',\n async (...args) => this.#resolveVersion(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n 'SnapsRegistry:update',\n async () => this.#triggerUpdate(),\n );\n }\n\n #wasRecentlyFetched() {\n return (\n this.state.lastUpdated &&\n Date.now() - this.state.lastUpdated < this.#recentFetchThreshold\n );\n }\n\n /**\n * Triggers an update of the registry database.\n *\n * If an existing update is in progress this function will await that update.\n */\n async #triggerUpdate() {\n // If an update is ongoing, wait for that.\n if (this.#currentUpdate) {\n await this.#currentUpdate;\n return;\n }\n // If no update exists, create promise and store globally.\n if (this.#currentUpdate === null) {\n this.#currentUpdate = this.#update();\n }\n await this.#currentUpdate;\n this.#currentUpdate = null;\n }\n\n /**\n * Updates the registry database if the registry hasn't been updated recently.\n *\n * NOTE: SHOULD NOT be called directly, instead `triggerUpdate` should be used.\n */\n async #update() {\n // No-op if we recently fetched the registry.\n if (this.#wasRecentlyFetched()) {\n return;\n }\n\n try {\n const database = await this.#safeFetch(this.#url.registry);\n\n if (this.#publicKey) {\n const signature = await this.#safeFetch(this.#url.signature);\n this.#verifySignature(database, signature);\n }\n\n this.update((state) => {\n state.database = JSON.parse(database);\n state.lastUpdated = Date.now();\n });\n } catch {\n // Ignore\n }\n }\n\n async #getDatabase(): Promise<SnapsRegistryDatabase | null> {\n if (this.state.database === null) {\n await this.#triggerUpdate();\n }\n\n // If the database is still null and we require it, throw.\n if (this.#failOnUnavailableRegistry && this.state.database === null) {\n throw new Error('Snaps registry is unavailable, installation blocked.');\n }\n return this.state.database;\n }\n\n async #getSingle(\n snapId: string,\n snapInfo: SnapsRegistryInfo,\n refetch = false,\n ): Promise<SnapsRegistryResult> {\n const database = await this.#getDatabase();\n\n const blockedEntry = database?.blockedSnaps.find((blocked) => {\n if ('id' in blocked) {\n return (\n blocked.id === snapId &&\n satisfiesVersionRange(snapInfo.version, blocked.versionRange)\n );\n }\n\n return blocked.checksum === snapInfo.checksum;\n });\n\n if (blockedEntry) {\n return {\n status: SnapsRegistryStatus.Blocked,\n reason: blockedEntry.reason,\n };\n }\n\n const verified = database?.verifiedSnaps[snapId];\n const version = verified?.versions?.[snapInfo.version];\n if (version && version.checksum === snapInfo.checksum) {\n return { status: SnapsRegistryStatus.Verified };\n }\n // For now, if we have an allowlist miss, we can refetch once and try again.\n if (this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#getSingle(snapId, snapInfo, true);\n }\n return { status: SnapsRegistryStatus.Unverified };\n }\n\n async #get(\n snaps: SnapsRegistryRequest,\n ): Promise<Record<string, SnapsRegistryResult>> {\n return Object.entries(snaps).reduce<\n Promise<Record<string, SnapsRegistryResult>>\n >(async (previousPromise, [snapId, snapInfo]) => {\n const result = await this.#getSingle(snapId, snapInfo);\n const acc = await previousPromise;\n acc[snapId] = result;\n return acc;\n }, Promise.resolve({}));\n }\n\n /**\n * Find an allowlisted version within a specified version range. Otherwise return the version range itself.\n *\n * @param snapId - The ID of the snap we are trying to resolve a version for.\n * @param versionRange - The version range.\n * @param refetch - An optional flag used to determine if we are refetching the registry.\n * @returns An allowlisted version within the specified version range if available otherwise returns the input version range.\n */\n async #resolveVersion(\n snapId: string,\n versionRange: SemVerRange,\n refetch = false,\n ): Promise<SemVerRange> {\n const database = await this.#getDatabase();\n const versions = database?.verifiedSnaps[snapId]?.versions ?? null;\n\n if (!versions && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n // If we cannot narrow down the version range we return the unaltered version range.\n if (!versions) {\n return versionRange;\n }\n\n const targetVersion = getTargetVersion(\n Object.keys(versions) as SemVerVersion[],\n versionRange,\n );\n\n if (!targetVersion && this.#refetchOnAllowlistMiss && !refetch) {\n await this.#triggerUpdate();\n return this.#resolveVersion(snapId, versionRange, true);\n }\n\n // If we cannot narrow down the version range we return the unaltered version range.\n if (!targetVersion) {\n return versionRange;\n }\n\n // A semver version is technically also a valid semver range.\n assertIsSemVerRange(targetVersion);\n return targetVersion;\n }\n\n /**\n * Get metadata for the given snap ID.\n *\n * @param snapId - The ID of the snap to get metadata for.\n * @returns The metadata for the given snap ID, or `null` if the snap is not\n * verified.\n */\n async #getMetadata(snapId: string): Promise<SnapsRegistryMetadata | null> {\n const database = await this.#getDatabase();\n return database?.verifiedSnaps[snapId]?.metadata ?? null;\n }\n\n /**\n * Verify the signature of the registry.\n *\n * @param database - The registry database.\n * @param signature - The signature of the registry.\n * @throws If the signature is invalid.\n * @private\n */\n #verifySignature(database: string, signature: string) {\n assert(this.#publicKey, 'No public key provided.');\n\n const valid = verify({\n registry: database,\n signature: JSON.parse(signature),\n publicKey: this.#publicKey,\n });\n\n assert(valid, 'Invalid registry signature.');\n }\n\n /**\n * Fetch the given URL, throwing if the response is not OK.\n *\n * @param url - The URL to fetch.\n * @returns The response body.\n * @private\n */\n async #safeFetch(url: string) {\n const response = await this.#fetchFunction(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${url}.`);\n }\n\n return await response.text();\n }\n}\n"],"names":["BaseController","verify","getTargetVersion","assert","assertIsSemVerRange","Duration","inMilliseconds","satisfiesVersionRange","SnapsRegistryStatus","SNAP_REGISTRY_URL","SNAP_REGISTRY_SIGNATURE_URL","controllerName","defaultState","database","lastUpdated","JsonSnapsRegistry","constructor","messenger","state","url","registry","signature","publicKey","fetchFunction","globalThis","fetch","bind","recentFetchThreshold","Minute","failOnUnavailableRegistry","refetchOnAllowlistMiss","metadata","persist","anonymous","name","currentUpdate","messagingSystem","registerActionHandler","args","get","getMetadata","resolveVersion","triggerUpdate","Date","now","update","wasRecentlyFetched","safeFetch","verifySignature","JSON","parse","Error","snapId","snapInfo","refetch","getDatabase","blockedEntry","blockedSnaps","find","blocked","id","version","versionRange","checksum","status","Blocked","reason","verified","verifiedSnaps","versions","Verified","getSingle","Unverified","snaps","Object","entries","reduce","previousPromise","result","acc","Promise","resolve","targetVersion","keys","valid","response","ok","text"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-controllers",
3
- "version": "5.0.0",
3
+ "version": "5.0.1",
4
4
  "description": "Controllers for MetaMask Snaps.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -52,8 +52,8 @@
52
52
  "@metamask/rpc-errors": "^6.1.0",
53
53
  "@metamask/snaps-registry": "^3.0.0",
54
54
  "@metamask/snaps-rpc-methods": "^6.0.0",
55
- "@metamask/snaps-sdk": "^2.0.0",
56
- "@metamask/snaps-utils": "^6.0.0",
55
+ "@metamask/snaps-sdk": "^2.1.0",
56
+ "@metamask/snaps-utils": "^6.1.0",
57
57
  "@metamask/utils": "^8.3.0",
58
58
  "@xstate/fsm": "^2.0.0",
59
59
  "browserify-zlib": "^0.2.0",
@@ -69,7 +69,7 @@
69
69
  "devDependencies": {
70
70
  "@esbuild-plugins/node-globals-polyfill": "^0.2.3",
71
71
  "@esbuild-plugins/node-modules-polyfill": "^0.2.2",
72
- "@lavamoat/allow-scripts": "^3.0.0",
72
+ "@lavamoat/allow-scripts": "^3.0.2",
73
73
  "@metamask/auto-changelog": "^3.4.4",
74
74
  "@metamask/eslint-config": "^12.1.0",
75
75
  "@metamask/eslint-config-jest": "^12.1.0",
@@ -125,7 +125,7 @@
125
125
  "webdriverio": "^8.19.0"
126
126
  },
127
127
  "peerDependencies": {
128
- "@metamask/snaps-execution-environments": "^4.0.0"
128
+ "@metamask/snaps-execution-environments": "^4.0.1"
129
129
  },
130
130
  "peerDependenciesMeta": {
131
131
  "@metamask/snaps-execution-environments": {