From 8987138c1687dcdc0ee16e3e8582cc6057a5707a Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 22 Oct 2025 10:02:12 +0200 Subject: [PATCH 1/3] feat: Add NPM proxy support --- .../snaps-controllers/src/snaps/SnapController.ts | 1 + packages/snaps-controllers/src/snaps/location/npm.ts | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/snaps-controllers/src/snaps/SnapController.ts b/packages/snaps-controllers/src/snaps/SnapController.ts index 0a547002f3..66ee3f7c80 100644 --- a/packages/snaps-controllers/src/snaps/SnapController.ts +++ b/packages/snaps-controllers/src/snaps/SnapController.ts @@ -1516,6 +1516,7 @@ export class SnapController extends BaseController< versionRange: resolvedVersion, fetch: this.#fetchFunction, allowLocal: false, + useNpmProxy: true, }); await this.#updateSnap({ diff --git a/packages/snaps-controllers/src/snaps/location/npm.ts b/packages/snaps-controllers/src/snaps/location/npm.ts index 237d35e58f..9ce0a55684 100644 --- a/packages/snaps-controllers/src/snaps/location/npm.ts +++ b/packages/snaps-controllers/src/snaps/location/npm.ts @@ -28,6 +28,10 @@ import type { DetectSnapLocationOptions, SnapLocation } from './location'; export const DEFAULT_NPM_REGISTRY = new URL('https://registry.npmjs.org'); +export const NPM_REGISTRY_PROXY = new URL( + 'https://npm-ota.dev-api.cx.metamask.io', +); + type NpmMeta = { registry: URL; packageName: string; @@ -48,6 +52,12 @@ export type NpmOptions = { * @default false */ allowCustomRegistries?: boolean; + /** + * Whether to use a MetaMask-owned proxy when sending requests to NPM. + * + * @default false + */ + useNpmProxy?: boolean; }; // Base class for NPM implementation, useful for extending with custom NPM fetching logic @@ -74,7 +84,7 @@ export abstract class BaseNpmLocation implements SnapLocation { url.username === '' && url.password === '' ) { - registry = DEFAULT_NPM_REGISTRY; + registry = opts.useNpmProxy ? NPM_REGISTRY_PROXY : DEFAULT_NPM_REGISTRY; } else { registry = 'https://'; if (url.username) { From 725a9f2cb279c1c19ab55bdcfdf813b2853a90b9 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 22 Oct 2025 10:37:25 +0200 Subject: [PATCH 2/3] Treat NPM proxy as real NPM --- packages/snaps-controllers/src/snaps/location/npm.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/snaps-controllers/src/snaps/location/npm.ts b/packages/snaps-controllers/src/snaps/location/npm.ts index 9ce0a55684..fe8c51171c 100644 --- a/packages/snaps-controllers/src/snaps/location/npm.ts +++ b/packages/snaps-controllers/src/snaps/location/npm.ts @@ -351,7 +351,11 @@ export function getNpmCanonicalBasePath(registryUrl: URL, packageName: string) { * @returns True if the registry is the NPM registry, otherwise false. */ function isNPM(registryUrl: URL) { - return registryUrl.toString() === DEFAULT_NPM_REGISTRY.toString(); + const registryUrlString = registryUrl.toString(); + return ( + registryUrlString === DEFAULT_NPM_REGISTRY.toString() || + registryUrlString === NPM_REGISTRY_PROXY.toString() + ); } /** From 4dda778b7d5210dd816b92a18c693844cc4a0b2c Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Thu, 6 Nov 2025 10:17:15 +0100 Subject: [PATCH 3/3] Use prod URL --- packages/snaps-controllers/src/snaps/location/npm.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/snaps-controllers/src/snaps/location/npm.ts b/packages/snaps-controllers/src/snaps/location/npm.ts index fe8c51171c..9aeedcfd0a 100644 --- a/packages/snaps-controllers/src/snaps/location/npm.ts +++ b/packages/snaps-controllers/src/snaps/location/npm.ts @@ -28,9 +28,7 @@ import type { DetectSnapLocationOptions, SnapLocation } from './location'; export const DEFAULT_NPM_REGISTRY = new URL('https://registry.npmjs.org'); -export const NPM_REGISTRY_PROXY = new URL( - 'https://npm-ota.dev-api.cx.metamask.io', -); +export const NPM_REGISTRY_PROXY = new URL('https://npm-ota.api.cx.metamask.io'); type NpmMeta = { registry: URL;