@metamask/snaps-utils 0.27.1 → 0.28.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.
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Creates the iframe to be used as the execution environment. This may run
3
+ * forever if the iframe never loads, but the promise should be wrapped in
4
+ * an initialization timeout in the SnapController.
5
+ *
6
+ * @param uri - The iframe URI.
7
+ * @param jobId - The job id.
8
+ * @returns A promise that resolves to the contentWindow of the iframe.
9
+ */
10
+ export declare function createWindow(uri: string, jobId: string): Promise<Window>;
package/dist/iframe.js ADDED
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWindow = void 0;
4
+ /**
5
+ * Creates the iframe to be used as the execution environment. This may run
6
+ * forever if the iframe never loads, but the promise should be wrapped in
7
+ * an initialization timeout in the SnapController.
8
+ *
9
+ * @param uri - The iframe URI.
10
+ * @param jobId - The job id.
11
+ * @returns A promise that resolves to the contentWindow of the iframe.
12
+ */
13
+ async function createWindow(uri, jobId) {
14
+ return await new Promise((resolve, reject) => {
15
+ const iframe = document.createElement('iframe');
16
+ // The order of operations appears to matter for everything except this
17
+ // attribute. We may as well set it here.
18
+ iframe.setAttribute('id', jobId);
19
+ // In the past, we've had problems that appear to be symptomatic of the
20
+ // iframe firing the `load` event before its scripts are actually loaded,
21
+ // which has prevented snaps from executing properly. Therefore, we set
22
+ // the `src` attribute and append the iframe to the DOM before attaching
23
+ // the `load` listener.
24
+ //
25
+ // `load` should only fire when "all dependent resources" have been
26
+ // loaded, which includes scripts.
27
+ //
28
+ // MDN article for `load` event: https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
29
+ // Re: `load` firing twice: https://stackoverflow.com/questions/10781880/dynamically-created-iframe-triggers-onload-event-twice/15880489#15880489
30
+ iframe.setAttribute('src', uri);
31
+ document.body.appendChild(iframe);
32
+ iframe.addEventListener('load', () => {
33
+ if (iframe.contentWindow) {
34
+ resolve(iframe.contentWindow);
35
+ }
36
+ else {
37
+ // We don't know of a case when this would happen, but better to fail
38
+ // fast if it does.
39
+ reject(new Error(`iframe.contentWindow not present on load for job "${jobId}".`));
40
+ }
41
+ });
42
+ // We need to set the sandbox attribute after appending the iframe to the
43
+ // DOM, otherwise errors in the iframe will not be propagated via `error`
44
+ // and `unhandledrejection` events, and we cannot catch and handle them.
45
+ // We wish we knew why this was the case.
46
+ //
47
+ // We set this property after adding the `load` listener because it
48
+ // appears to work dependably. ¯\_(ツ)_/¯
49
+ //
50
+ // We apply this property as a principle of least authority (POLA)
51
+ // measure.
52
+ // Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox
53
+ iframe.setAttribute('sandbox', 'allow-scripts');
54
+ });
55
+ }
56
+ exports.createWindow = createWindow;
57
+ //# sourceMappingURL=iframe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iframe.js","sourceRoot":"","sources":["../src/iframe.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;GAQG;AACI,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,KAAa;IAEb,OAAO,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC3C,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAChD,uEAAuE;QACvE,yCAAyC;QACzC,MAAM,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAEjC,uEAAuE;QACvE,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,uBAAuB;QACvB,EAAE;QACF,mEAAmE;QACnE,kCAAkC;QAClC,EAAE;QACF,mGAAmG;QACnG,iJAAiJ;QACjJ,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE;YACnC,IAAI,MAAM,CAAC,aAAa,EAAE;gBACxB,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;aAC/B;iBAAM;gBACL,qEAAqE;gBACrE,mBAAmB;gBACnB,MAAM,CACJ,IAAI,KAAK,CACP,qDAAqD,KAAK,IAAI,CAC/D,CACF,CAAC;aACH;QACH,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,yEAAyE;QACzE,wEAAwE;QACxE,yCAAyC;QACzC,EAAE;QACF,mEAAmE;QACnE,wCAAwC;QACxC,EAAE;QACF,kEAAkE;QAClE,WAAW;QACX,qFAAqF;QACrF,MAAM,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;AACL,CAAC;AAnDD,oCAmDC","sourcesContent":["/**\n * Creates the iframe to be used as the execution environment. This may run\n * forever if the iframe never loads, but the promise should be wrapped in\n * an initialization timeout in the SnapController.\n *\n * @param uri - The iframe URI.\n * @param jobId - The job id.\n * @returns A promise that resolves to the contentWindow of the iframe.\n */\nexport async function createWindow(\n uri: string,\n jobId: string,\n): Promise<Window> {\n return await new Promise((resolve, reject) => {\n const iframe = document.createElement('iframe');\n // The order of operations appears to matter for everything except this\n // attribute. We may as well set it here.\n iframe.setAttribute('id', jobId);\n\n // In the past, we've had problems that appear to be symptomatic of the\n // iframe firing the `load` event before its scripts are actually loaded,\n // which has prevented snaps from executing properly. Therefore, we set\n // the `src` attribute and append the iframe to the DOM before attaching\n // the `load` listener.\n //\n // `load` should only fire when \"all dependent resources\" have been\n // loaded, which includes scripts.\n //\n // MDN article for `load` event: https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event\n // Re: `load` firing twice: https://stackoverflow.com/questions/10781880/dynamically-created-iframe-triggers-onload-event-twice/15880489#15880489\n iframe.setAttribute('src', uri);\n document.body.appendChild(iframe);\n\n iframe.addEventListener('load', () => {\n if (iframe.contentWindow) {\n resolve(iframe.contentWindow);\n } else {\n // We don't know of a case when this would happen, but better to fail\n // fast if it does.\n reject(\n new Error(\n `iframe.contentWindow not present on load for job \"${jobId}\".`,\n ),\n );\n }\n });\n\n // We need to set the sandbox attribute after appending the iframe to the\n // DOM, otherwise errors in the iframe will not be propagated via `error`\n // and `unhandledrejection` events, and we cannot catch and handle them.\n // We wish we knew why this was the case.\n //\n // We set this property after adding the `load` listener because it\n // appears to work dependably. ¯\\_(ツ)_/¯\n //\n // We apply this property as a principle of least authority (POLA)\n // measure.\n // Ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox\n iframe.setAttribute('sandbox', 'allow-scripts');\n });\n}\n"]}
@@ -1,9 +1,11 @@
1
1
  export * from './caveats';
2
+ export * from './cronjob';
2
3
  export * from './deep-clone';
3
4
  export * from './default-endowments';
4
5
  export * from './entropy';
5
6
  export * from './flatMap';
6
7
  export * from './handlers';
8
+ export * from './iframe';
7
9
  export * from './json-rpc';
8
10
  export * from './manifest/index.browser';
9
11
  export * from './namespace';
@@ -15,11 +15,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./caveats"), exports);
18
+ __exportStar(require("./cronjob"), exports);
18
19
  __exportStar(require("./deep-clone"), exports);
19
20
  __exportStar(require("./default-endowments"), exports);
20
21
  __exportStar(require("./entropy"), exports);
21
22
  __exportStar(require("./flatMap"), exports);
22
23
  __exportStar(require("./handlers"), exports);
24
+ __exportStar(require("./iframe"), exports);
23
25
  __exportStar(require("./json-rpc"), exports);
24
26
  __exportStar(require("./manifest/index.browser"), exports);
25
27
  __exportStar(require("./namespace"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,+CAA6B;AAC7B,uDAAqC;AACrC,4CAA0B;AAC1B,4CAA0B;AAC1B,6CAA2B;AAC3B,6CAA2B;AAC3B,2DAAyC;AACzC,8CAA4B;AAC5B,iDAA+B;AAC/B,2CAAyB;AACzB,yCAAuB;AACvB,0CAAwB;AACxB,0CAAwB;AACxB,6CAA2B;AAC3B,+DAA6C","sourcesContent":["export * from './caveats';\nexport * from './deep-clone';\nexport * from './default-endowments';\nexport * from './entropy';\nexport * from './flatMap';\nexport * from './handlers';\nexport * from './json-rpc';\nexport * from './manifest/index.browser';\nexport * from './namespace';\nexport * from './notification';\nexport * from './object';\nexport * from './path';\nexport * from './snaps';\nexport * from './types';\nexport * from './versions';\nexport * from './virtual-file/index.browser';\n"]}
1
+ {"version":3,"file":"index.browser.js","sourceRoot":"","sources":["../src/index.browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,4CAA0B;AAC1B,+CAA6B;AAC7B,uDAAqC;AACrC,4CAA0B;AAC1B,4CAA0B;AAC1B,6CAA2B;AAC3B,2CAAyB;AACzB,6CAA2B;AAC3B,2DAAyC;AACzC,8CAA4B;AAC5B,iDAA+B;AAC/B,2CAAyB;AACzB,yCAAuB;AACvB,0CAAwB;AACxB,0CAAwB;AACxB,6CAA2B;AAC3B,+DAA6C","sourcesContent":["export * from './caveats';\nexport * from './cronjob';\nexport * from './deep-clone';\nexport * from './default-endowments';\nexport * from './entropy';\nexport * from './flatMap';\nexport * from './handlers';\nexport * from './iframe';\nexport * from './json-rpc';\nexport * from './manifest/index.browser';\nexport * from './namespace';\nexport * from './notification';\nexport * from './object';\nexport * from './path';\nexport * from './snaps';\nexport * from './types';\nexport * from './versions';\nexport * from './virtual-file/index.browser';\n"]}
package/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export * from './eval';
7
7
  export * from './flatMap';
8
8
  export * from './fs';
9
9
  export * from './handlers';
10
+ export * from './iframe';
10
11
  export * from './json-rpc';
11
12
  export * from './manifest';
12
13
  export * from './mock';
package/dist/index.js CHANGED
@@ -23,6 +23,7 @@ __exportStar(require("./eval"), exports);
23
23
  __exportStar(require("./flatMap"), exports);
24
24
  __exportStar(require("./fs"), exports);
25
25
  __exportStar(require("./handlers"), exports);
26
+ __exportStar(require("./iframe"), exports);
26
27
  __exportStar(require("./json-rpc"), exports);
27
28
  __exportStar(require("./manifest"), exports);
28
29
  __exportStar(require("./mock"), exports);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,4CAA0B;AAC1B,+CAA6B;AAC7B,uDAAqC;AACrC,4CAA0B;AAC1B,yCAAuB;AACvB,4CAA0B;AAC1B,uCAAqB;AACrB,6CAA2B;AAC3B,6CAA2B;AAC3B,6CAA2B;AAC3B,yCAAuB;AACvB,8CAA4B;AAC5B,iDAA+B;AAC/B,wCAAsB;AACtB,2CAAyB;AACzB,yCAAuB;AACvB,iDAA+B;AAC/B,0CAAwB;AACxB,0CAAwB;AACxB,6CAA2B;AAC3B,iDAA+B","sourcesContent":["export * from './caveats';\nexport * from './cronjob';\nexport * from './deep-clone';\nexport * from './default-endowments';\nexport * from './entropy';\nexport * from './eval';\nexport * from './flatMap';\nexport * from './fs';\nexport * from './handlers';\nexport * from './json-rpc';\nexport * from './manifest';\nexport * from './mock';\nexport * from './namespace';\nexport * from './notification';\nexport * from './npm';\nexport * from './object';\nexport * from './path';\nexport * from './post-process';\nexport * from './snaps';\nexport * from './types';\nexport * from './versions';\nexport * from './virtual-file';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,4CAA0B;AAC1B,+CAA6B;AAC7B,uDAAqC;AACrC,4CAA0B;AAC1B,yCAAuB;AACvB,4CAA0B;AAC1B,uCAAqB;AACrB,6CAA2B;AAC3B,2CAAyB;AACzB,6CAA2B;AAC3B,6CAA2B;AAC3B,yCAAuB;AACvB,8CAA4B;AAC5B,iDAA+B;AAC/B,wCAAsB;AACtB,2CAAyB;AACzB,yCAAuB;AACvB,iDAA+B;AAC/B,0CAAwB;AACxB,0CAAwB;AACxB,6CAA2B;AAC3B,iDAA+B","sourcesContent":["export * from './caveats';\nexport * from './cronjob';\nexport * from './deep-clone';\nexport * from './default-endowments';\nexport * from './entropy';\nexport * from './eval';\nexport * from './flatMap';\nexport * from './fs';\nexport * from './handlers';\nexport * from './iframe';\nexport * from './json-rpc';\nexport * from './manifest';\nexport * from './mock';\nexport * from './namespace';\nexport * from './notification';\nexport * from './npm';\nexport * from './object';\nexport * from './path';\nexport * from './post-process';\nexport * from './snaps';\nexport * from './types';\nexport * from './versions';\nexport * from './virtual-file';\n"]}
@@ -1,27 +1,4 @@
1
1
  import { Infer, Struct } from 'superstruct';
2
- export declare type Base64Opts = {
3
- /**
4
- * Is the `=` padding at the end required or not.
5
- *
6
- * @default false
7
- */
8
- paddingRequired?: boolean;
9
- /**
10
- * Which character set should be used.
11
- * The sets are based on {@link https://datatracker.ietf.org/doc/html/rfc4648 RFC 4648}.
12
- *
13
- * @default 'base64'
14
- */
15
- characterSet?: 'base64' | 'base64url';
16
- };
17
- /**
18
- * Ensure that a provided string-based struct is valid base64.
19
- *
20
- * @param struct - The string based struct.
21
- * @param opts - Optional options to specialize base64 validation. See {@link Base64Opts} documentation.
22
- * @returns A superstruct validating base64.
23
- */
24
- export declare const base64: <T extends string, S>(struct: Struct<T, S>, opts?: Base64Opts) => Struct<T, S>;
25
2
  export declare const Bip32PathStruct: Struct<string[], Struct<string, null>>;
26
3
  export declare const bip32entropy: <T extends {
27
4
  path: string[];
@@ -213,7 +190,7 @@ export declare const PermissionsStruct: Struct<{
213
190
  }>;
214
191
  export declare type SnapPermissions = Infer<typeof PermissionsStruct>;
215
192
  export declare const SnapManifestStruct: Struct<{
216
- version: import("../versions").SemVerVersion;
193
+ version: import("@metamask/utils").SemVerVersion;
217
194
  description: string;
218
195
  proposedName: string;
219
196
  source: {
@@ -280,7 +257,7 @@ export declare const SnapManifestStruct: Struct<{
280
257
  url: string;
281
258
  } | undefined;
282
259
  }, {
283
- version: Struct<import("../versions").SemVerVersion, null>;
260
+ version: Struct<import("@metamask/utils").SemVerVersion, null>;
284
261
  description: Struct<string, null>;
285
262
  proposedName: Struct<string, null>;
286
263
  repository: Struct<{
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createSnapManifest = exports.assertIsSnapManifest = exports.isSnapManifest = exports.SnapManifestStruct = exports.PermissionsStruct = exports.SnapGetBip32EntropyPermissionsStruct = exports.Bip32EntropyStruct = exports.bip32entropy = exports.Bip32PathStruct = exports.base64 = void 0;
3
+ exports.createSnapManifest = exports.assertIsSnapManifest = exports.isSnapManifest = exports.SnapManifestStruct = exports.PermissionsStruct = exports.SnapGetBip32EntropyPermissionsStruct = exports.Bip32EntropyStruct = exports.bip32entropy = exports.Bip32PathStruct = void 0;
4
4
  const utils_1 = require("@metamask/utils");
5
5
  const superstruct_1 = require("superstruct");
6
6
  const cronjob_1 = require("../cronjob");
@@ -9,42 +9,12 @@ const json_rpc_1 = require("../json-rpc");
9
9
  const namespace_1 = require("../namespace");
10
10
  const path_1 = require("../path");
11
11
  const types_1 = require("../types");
12
- const versions_1 = require("../versions");
13
12
  // BIP-43 purposes that cannot be used for entropy derivation. These are in the
14
13
  // string form, ending with `'`.
15
14
  const FORBIDDEN_PURPOSES = [
16
15
  entropy_1.SIP_6_MAGIC_VALUE,
17
16
  entropy_1.STATE_ENCRYPTION_MAGIC_VALUE,
18
17
  ];
19
- /**
20
- * Ensure that a provided string-based struct is valid base64.
21
- *
22
- * @param struct - The string based struct.
23
- * @param opts - Optional options to specialize base64 validation. See {@link Base64Opts} documentation.
24
- * @returns A superstruct validating base64.
25
- */
26
- const base64 = (struct, opts = {}) => {
27
- var _a, _b;
28
- const paddingRequired = (_a = opts.paddingRequired) !== null && _a !== void 0 ? _a : false;
29
- const characterSet = (_b = opts.characterSet) !== null && _b !== void 0 ? _b : 'base64';
30
- let letters;
31
- if (characterSet === 'base64') {
32
- letters = String.raw `[A-Za-z0-9+\/]`;
33
- }
34
- else {
35
- (0, utils_1.assert)(characterSet === 'base64url');
36
- letters = String.raw `[-_A-Za-z0-9]`;
37
- }
38
- let re;
39
- if (paddingRequired) {
40
- re = new RegExp(`^(?:${letters}{4})*(?:${letters}{3}=|${letters}{2}==)?$`, 'u');
41
- }
42
- else {
43
- re = new RegExp(`^(?:${letters}{4})*(?:${letters}{2,3}|${letters}{3}=|${letters}{2}==)?$`, 'u');
44
- }
45
- return (0, superstruct_1.pattern)(struct, re);
46
- };
47
- exports.base64 = base64;
48
18
  const BIP32_INDEX_REGEX = /^\d+'?$/u;
49
19
  exports.Bip32PathStruct = (0, superstruct_1.refine)((0, superstruct_1.array)((0, superstruct_1.string)()), 'BIP-32 path', (path) => {
50
20
  if (path.length === 0) {
@@ -101,7 +71,7 @@ exports.PermissionsStruct = (0, superstruct_1.type)({
101
71
  /* eslint-enable @typescript-eslint/naming-convention */
102
72
  const relativePath = (struct) => (0, superstruct_1.coerce)(struct, struct, (value) => (0, path_1.normalizeRelative)(value));
103
73
  exports.SnapManifestStruct = (0, superstruct_1.object)({
104
- version: versions_1.VersionStruct,
74
+ version: utils_1.VersionStruct,
105
75
  description: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, 280),
106
76
  proposedName: (0, superstruct_1.size)((0, superstruct_1.pattern)((0, superstruct_1.string)(), /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u), 1, 214),
107
77
  repository: (0, superstruct_1.optional)((0, superstruct_1.object)({
@@ -109,7 +79,7 @@ exports.SnapManifestStruct = (0, superstruct_1.object)({
109
79
  url: (0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity),
110
80
  })),
111
81
  source: (0, superstruct_1.object)({
112
- shasum: (0, superstruct_1.size)((0, exports.base64)((0, superstruct_1.string)(), { paddingRequired: true }), 44, 44),
82
+ shasum: utils_1.ChecksumStruct,
113
83
  location: (0, superstruct_1.object)({
114
84
  npm: (0, superstruct_1.object)({
115
85
  filePath: relativePath((0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity)),
@@ -1 +1 @@
1
- {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/manifest/validation.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, assertStruct } from '@metamask/utils';\nimport {\n array,\n boolean,\n coerce,\n create,\n enums,\n Infer,\n integer,\n is,\n literal,\n object,\n optional,\n pattern,\n refine,\n size,\n string,\n Struct,\n type,\n union,\n} from 'superstruct';\n\nimport { CronjobSpecificationArrayStruct } from '../cronjob';\nimport { SIP_6_MAGIC_VALUE, STATE_ENCRYPTION_MAGIC_VALUE } from '../entropy';\nimport { RpcOriginsStruct } from '../json-rpc';\nimport { NamespacesStruct } from '../namespace';\nimport { normalizeRelative } from '../path';\nimport { NameStruct, NpmSnapFileNames } from '../types';\nimport { VersionStruct } from '../versions';\n\n// BIP-43 purposes that cannot be used for entropy derivation. These are in the\n// string form, ending with `'`.\nconst FORBIDDEN_PURPOSES: string[] = [\n SIP_6_MAGIC_VALUE,\n STATE_ENCRYPTION_MAGIC_VALUE,\n];\n\nexport type Base64Opts = {\n /**\n * Is the `=` padding at the end required or not.\n *\n * @default false\n */\n // Padding is optional in RFC 4648, that's why the default value is false\n paddingRequired?: boolean;\n /**\n * Which character set should be used.\n * The sets are based on {@link https://datatracker.ietf.org/doc/html/rfc4648 RFC 4648}.\n *\n * @default 'base64'\n */\n characterSet?: 'base64' | 'base64url';\n};\n\n/**\n * Ensure that a provided string-based struct is valid base64.\n *\n * @param struct - The string based struct.\n * @param opts - Optional options to specialize base64 validation. See {@link Base64Opts} documentation.\n * @returns A superstruct validating base64.\n */\nexport const base64 = <T extends string, S>(\n struct: Struct<T, S>,\n opts: Base64Opts = {},\n) => {\n const paddingRequired = opts.paddingRequired ?? false;\n const characterSet = opts.characterSet ?? 'base64';\n\n let letters: string;\n if (characterSet === 'base64') {\n letters = String.raw`[A-Za-z0-9+\\/]`;\n } else {\n assert(characterSet === 'base64url');\n letters = String.raw`[-_A-Za-z0-9]`;\n }\n\n let re: RegExp;\n if (paddingRequired) {\n re = new RegExp(\n `^(?:${letters}{4})*(?:${letters}{3}=|${letters}{2}==)?$`,\n 'u',\n );\n } else {\n re = new RegExp(\n `^(?:${letters}{4})*(?:${letters}{2,3}|${letters}{3}=|${letters}{2}==)?$`,\n 'u',\n );\n }\n\n return pattern(struct, re);\n};\n\nconst BIP32_INDEX_REGEX = /^\\d+'?$/u;\nexport const Bip32PathStruct = refine(\n array(string()),\n 'BIP-32 path',\n (path) => {\n if (path.length === 0) {\n return 'Path must be a non-empty BIP-32 derivation path array';\n }\n\n if (path[0] !== 'm') {\n return 'Path must start with \"m\".';\n }\n\n if (path.length < 3) {\n return 'Paths must have a length of at least three.';\n }\n\n if (path.slice(1).some((part) => !BIP32_INDEX_REGEX.test(part))) {\n return 'Path must be a valid BIP-32 derivation path array.';\n }\n\n if (FORBIDDEN_PURPOSES.includes(path[1])) {\n return `The purpose \"${path[1]}\" is not allowed for entropy derivation.`;\n }\n\n return true;\n },\n);\n\nexport const bip32entropy = <T extends { path: string[]; curve: string }, S>(\n struct: Struct<T, S>,\n) =>\n refine(struct, 'BIP-32 entropy', (value) => {\n if (\n value.curve === 'ed25519' &&\n value.path.slice(1).some((part) => !part.endsWith(\"'\"))\n ) {\n return 'Ed25519 does not support unhardened paths.';\n }\n\n return true;\n });\n\n// Used outside @metamask/snap-utils\nexport const Bip32EntropyStruct = bip32entropy(\n type({\n path: Bip32PathStruct,\n curve: enums(['ed25519', 'secp256k1']),\n }),\n);\n\nexport type Bip32Entropy = Infer<typeof Bip32EntropyStruct>;\n\nexport const SnapGetBip32EntropyPermissionsStruct = size(\n array(Bip32EntropyStruct),\n 1,\n Infinity,\n);\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport const PermissionsStruct = type({\n 'endowment:long-running': optional(object({})),\n 'endowment:network-access': optional(object({})),\n 'endowment:transaction-insight': optional(\n object({\n allowTransactionOrigin: optional(boolean()),\n }),\n ),\n 'endowment:cronjob': optional(\n object({ jobs: CronjobSpecificationArrayStruct }),\n ),\n 'endowment:rpc': optional(RpcOriginsStruct),\n snap_confirm: optional(object({})),\n snap_manageState: optional(object({})),\n snap_notify: optional(object({})),\n snap_getBip32Entropy: optional(SnapGetBip32EntropyPermissionsStruct),\n snap_getBip32PublicKey: optional(SnapGetBip32EntropyPermissionsStruct),\n snap_getBip44Entropy: optional(\n size(\n array(object({ coinType: size(integer(), 0, 2 ** 32 - 1) })),\n 1,\n Infinity,\n ),\n ),\n snap_getEntropy: optional(object({})),\n 'endowment:keyring': optional(\n object({\n namespaces: NamespacesStruct,\n }),\n ),\n});\n/* eslint-enable @typescript-eslint/naming-convention */\n\nconst relativePath = <Type extends string>(struct: Struct<Type>) =>\n coerce(struct, struct, (value) => normalizeRelative(value));\n\nexport type SnapPermissions = Infer<typeof PermissionsStruct>;\n\nexport const SnapManifestStruct = object({\n version: VersionStruct,\n description: size(string(), 1, 280),\n proposedName: size(\n pattern(\n string(),\n /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u,\n ),\n 1,\n 214,\n ),\n repository: optional(\n object({\n type: size(string(), 1, Infinity),\n url: size(string(), 1, Infinity),\n }),\n ),\n source: object({\n shasum: size(base64(string(), { paddingRequired: true }), 44, 44),\n location: object({\n npm: object({\n filePath: relativePath(size(string(), 1, Infinity)),\n iconPath: optional(relativePath(size(string(), 1, Infinity))),\n packageName: NameStruct,\n registry: union([\n literal('https://registry.npmjs.org'),\n literal('https://registry.npmjs.org/'),\n ]),\n }),\n }),\n }),\n initialPermissions: PermissionsStruct,\n manifestVersion: literal('0.1'),\n});\n\nexport type SnapManifest = Infer<typeof SnapManifestStruct>;\n\n/**\n * Check if the given value is a valid {@link SnapManifest} object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a valid {@link SnapManifest} object.\n */\nexport function isSnapManifest(value: unknown): value is SnapManifest {\n return is(value, SnapManifestStruct);\n}\n\n/**\n * Assert that the given value is a valid {@link SnapManifest} object.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid {@link SnapManifest} object.\n */\nexport function assertIsSnapManifest(\n value: unknown,\n): asserts value is SnapManifest {\n assertStruct(\n value,\n SnapManifestStruct,\n `\"${NpmSnapFileNames.Manifest}\" is invalid`,\n );\n}\n\n/**\n * Creates a {@link SnapManifest} object from JSON.\n *\n *\n * @param value - The value to check.\n * @throws If the value cannot be coerced to a {@link SnapManifest} object.\n * @returns The created {@link SnapManifest} object.\n */\nexport function createSnapManifest(value: unknown): SnapManifest {\n // TODO: Add a utility to prefix these errors similar to assertStruct\n return create(value, SnapManifestStruct);\n}\n"]}
1
+ {"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/manifest/validation.ts"],"names":[],"mappings":";;;AAAA,2CAA8E;AAC9E,6CAmBqB;AAErB,wCAA6D;AAC7D,wCAA6E;AAC7E,0CAA+C;AAC/C,4CAAgD;AAChD,kCAA4C;AAC5C,oCAAwD;AAExD,+EAA+E;AAC/E,gCAAgC;AAChC,MAAM,kBAAkB,GAAa;IACnC,2BAAiB;IACjB,sCAA4B;CAC7B,CAAC;AAEF,MAAM,iBAAiB,GAAG,UAAU,CAAC;AACxB,QAAA,eAAe,GAAG,IAAA,oBAAM,EACnC,IAAA,mBAAK,EAAC,IAAA,oBAAM,GAAE,CAAC,EACf,aAAa,EACb,CAAC,IAAI,EAAE,EAAE;IACP,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACrB,OAAO,uDAAuD,CAAC;KAChE;IAED,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE;QACnB,OAAO,2BAA2B,CAAC;KACpC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE;QACnB,OAAO,6CAA6C,CAAC;KACtD;IAED,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;QAC/D,OAAO,oDAAoD,CAAC;KAC7D;IAED,IAAI,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;QACxC,OAAO,gBAAgB,IAAI,CAAC,CAAC,CAAC,0CAA0C,CAAC;KAC1E;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CACF,CAAC;AAEK,MAAM,YAAY,GAAG,CAC1B,MAAoB,EACpB,EAAE,CACF,IAAA,oBAAM,EAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,KAAK,EAAE,EAAE;IACzC,IACE,KAAK,CAAC,KAAK,KAAK,SAAS;QACzB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EACvD;QACA,OAAO,4CAA4C,CAAC;KACrD;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC,CAAC;AAZQ,QAAA,YAAY,gBAYpB;AAEL,oCAAoC;AACvB,QAAA,kBAAkB,GAAG,IAAA,oBAAY,EAC5C,IAAA,kBAAI,EAAC;IACH,IAAI,EAAE,uBAAe;IACrB,KAAK,EAAE,IAAA,mBAAK,EAAC,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;CACvC,CAAC,CACH,CAAC;AAIW,QAAA,oCAAoC,GAAG,IAAA,kBAAI,EACtD,IAAA,mBAAK,EAAC,0BAAkB,CAAC,EACzB,CAAC,EACD,QAAQ,CACT,CAAC;AAEF,yDAAyD;AAC5C,QAAA,iBAAiB,GAAG,IAAA,kBAAI,EAAC;IACpC,wBAAwB,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IAC9C,0BAA0B,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IAChD,+BAA+B,EAAE,IAAA,sBAAQ,EACvC,IAAA,oBAAM,EAAC;QACL,sBAAsB,EAAE,IAAA,sBAAQ,EAAC,IAAA,qBAAO,GAAE,CAAC;KAC5C,CAAC,CACH;IACD,mBAAmB,EAAE,IAAA,sBAAQ,EAC3B,IAAA,oBAAM,EAAC,EAAE,IAAI,EAAE,yCAA+B,EAAE,CAAC,CAClD;IACD,eAAe,EAAE,IAAA,sBAAQ,EAAC,2BAAgB,CAAC;IAC3C,YAAY,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IAClC,gBAAgB,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IACtC,WAAW,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IACjC,oBAAoB,EAAE,IAAA,sBAAQ,EAAC,4CAAoC,CAAC;IACpE,sBAAsB,EAAE,IAAA,sBAAQ,EAAC,4CAAoC,CAAC;IACtE,oBAAoB,EAAE,IAAA,sBAAQ,EAC5B,IAAA,kBAAI,EACF,IAAA,mBAAK,EAAC,IAAA,oBAAM,EAAC,EAAE,QAAQ,EAAE,IAAA,kBAAI,EAAC,IAAA,qBAAO,GAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAC5D,CAAC,EACD,QAAQ,CACT,CACF;IACD,eAAe,EAAE,IAAA,sBAAQ,EAAC,IAAA,oBAAM,EAAC,EAAE,CAAC,CAAC;IACrC,mBAAmB,EAAE,IAAA,sBAAQ,EAC3B,IAAA,oBAAM,EAAC;QACL,UAAU,EAAE,4BAAgB;KAC7B,CAAC,CACH;CACF,CAAC,CAAC;AACH,wDAAwD;AAExD,MAAM,YAAY,GAAG,CAAsB,MAAoB,EAAE,EAAE,CACjE,IAAA,oBAAM,EAAC,MAAM,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,wBAAiB,EAAC,KAAK,CAAC,CAAC,CAAC;AAIjD,QAAA,kBAAkB,GAAG,IAAA,oBAAM,EAAC;IACvC,OAAO,EAAE,qBAAa;IACtB,WAAW,EAAE,IAAA,kBAAI,EAAC,IAAA,oBAAM,GAAE,EAAE,CAAC,EAAE,GAAG,CAAC;IACnC,YAAY,EAAE,IAAA,kBAAI,EAChB,IAAA,qBAAO,EACL,IAAA,oBAAM,GAAE,EACR,kHAAkH,CACnH,EACD,CAAC,EACD,GAAG,CACJ;IACD,UAAU,EAAE,IAAA,sBAAQ,EAClB,IAAA,oBAAM,EAAC;QACL,IAAI,EAAE,IAAA,kBAAI,EAAC,IAAA,oBAAM,GAAE,EAAE,CAAC,EAAE,QAAQ,CAAC;QACjC,GAAG,EAAE,IAAA,kBAAI,EAAC,IAAA,oBAAM,GAAE,EAAE,CAAC,EAAE,QAAQ,CAAC;KACjC,CAAC,CACH;IACD,MAAM,EAAE,IAAA,oBAAM,EAAC;QACb,MAAM,EAAE,sBAAc;QACtB,QAAQ,EAAE,IAAA,oBAAM,EAAC;YACf,GAAG,EAAE,IAAA,oBAAM,EAAC;gBACV,QAAQ,EAAE,YAAY,CAAC,IAAA,kBAAI,EAAC,IAAA,oBAAM,GAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC;gBACnD,QAAQ,EAAE,IAAA,sBAAQ,EAAC,YAAY,CAAC,IAAA,kBAAI,EAAC,IAAA,oBAAM,GAAE,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;gBAC7D,WAAW,EAAE,kBAAU;gBACvB,QAAQ,EAAE,IAAA,mBAAK,EAAC;oBACd,IAAA,qBAAO,EAAC,4BAA4B,CAAC;oBACrC,IAAA,qBAAO,EAAC,6BAA6B,CAAC;iBACvC,CAAC;aACH,CAAC;SACH,CAAC;KACH,CAAC;IACF,kBAAkB,EAAE,yBAAiB;IACrC,eAAe,EAAE,IAAA,qBAAO,EAAC,KAAK,CAAC;CAChC,CAAC,CAAC;AAIH;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,KAAc;IAC3C,OAAO,IAAA,gBAAE,EAAC,KAAK,EAAE,0BAAkB,CAAC,CAAC;AACvC,CAAC;AAFD,wCAEC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAClC,KAAc;IAEd,IAAA,oBAAY,EACV,KAAK,EACL,0BAAkB,EAClB,IAAI,wBAAgB,CAAC,QAAQ,cAAc,CAC5C,CAAC;AACJ,CAAC;AARD,oDAQC;AAED;;;;;;;GAOG;AACH,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,qEAAqE;IACrE,OAAO,IAAA,oBAAM,EAAC,KAAK,EAAE,0BAAkB,CAAC,CAAC;AAC3C,CAAC;AAHD,gDAGC","sourcesContent":["import { assertStruct, ChecksumStruct, VersionStruct } from '@metamask/utils';\nimport {\n array,\n boolean,\n coerce,\n create,\n enums,\n Infer,\n integer,\n is,\n literal,\n object,\n optional,\n pattern,\n refine,\n size,\n string,\n Struct,\n type,\n union,\n} from 'superstruct';\n\nimport { CronjobSpecificationArrayStruct } from '../cronjob';\nimport { SIP_6_MAGIC_VALUE, STATE_ENCRYPTION_MAGIC_VALUE } from '../entropy';\nimport { RpcOriginsStruct } from '../json-rpc';\nimport { NamespacesStruct } from '../namespace';\nimport { normalizeRelative } from '../path';\nimport { NameStruct, NpmSnapFileNames } from '../types';\n\n// BIP-43 purposes that cannot be used for entropy derivation. These are in the\n// string form, ending with `'`.\nconst FORBIDDEN_PURPOSES: string[] = [\n SIP_6_MAGIC_VALUE,\n STATE_ENCRYPTION_MAGIC_VALUE,\n];\n\nconst BIP32_INDEX_REGEX = /^\\d+'?$/u;\nexport const Bip32PathStruct = refine(\n array(string()),\n 'BIP-32 path',\n (path) => {\n if (path.length === 0) {\n return 'Path must be a non-empty BIP-32 derivation path array';\n }\n\n if (path[0] !== 'm') {\n return 'Path must start with \"m\".';\n }\n\n if (path.length < 3) {\n return 'Paths must have a length of at least three.';\n }\n\n if (path.slice(1).some((part) => !BIP32_INDEX_REGEX.test(part))) {\n return 'Path must be a valid BIP-32 derivation path array.';\n }\n\n if (FORBIDDEN_PURPOSES.includes(path[1])) {\n return `The purpose \"${path[1]}\" is not allowed for entropy derivation.`;\n }\n\n return true;\n },\n);\n\nexport const bip32entropy = <T extends { path: string[]; curve: string }, S>(\n struct: Struct<T, S>,\n) =>\n refine(struct, 'BIP-32 entropy', (value) => {\n if (\n value.curve === 'ed25519' &&\n value.path.slice(1).some((part) => !part.endsWith(\"'\"))\n ) {\n return 'Ed25519 does not support unhardened paths.';\n }\n\n return true;\n });\n\n// Used outside @metamask/snap-utils\nexport const Bip32EntropyStruct = bip32entropy(\n type({\n path: Bip32PathStruct,\n curve: enums(['ed25519', 'secp256k1']),\n }),\n);\n\nexport type Bip32Entropy = Infer<typeof Bip32EntropyStruct>;\n\nexport const SnapGetBip32EntropyPermissionsStruct = size(\n array(Bip32EntropyStruct),\n 1,\n Infinity,\n);\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport const PermissionsStruct = type({\n 'endowment:long-running': optional(object({})),\n 'endowment:network-access': optional(object({})),\n 'endowment:transaction-insight': optional(\n object({\n allowTransactionOrigin: optional(boolean()),\n }),\n ),\n 'endowment:cronjob': optional(\n object({ jobs: CronjobSpecificationArrayStruct }),\n ),\n 'endowment:rpc': optional(RpcOriginsStruct),\n snap_confirm: optional(object({})),\n snap_manageState: optional(object({})),\n snap_notify: optional(object({})),\n snap_getBip32Entropy: optional(SnapGetBip32EntropyPermissionsStruct),\n snap_getBip32PublicKey: optional(SnapGetBip32EntropyPermissionsStruct),\n snap_getBip44Entropy: optional(\n size(\n array(object({ coinType: size(integer(), 0, 2 ** 32 - 1) })),\n 1,\n Infinity,\n ),\n ),\n snap_getEntropy: optional(object({})),\n 'endowment:keyring': optional(\n object({\n namespaces: NamespacesStruct,\n }),\n ),\n});\n/* eslint-enable @typescript-eslint/naming-convention */\n\nconst relativePath = <Type extends string>(struct: Struct<Type>) =>\n coerce(struct, struct, (value) => normalizeRelative(value));\n\nexport type SnapPermissions = Infer<typeof PermissionsStruct>;\n\nexport const SnapManifestStruct = object({\n version: VersionStruct,\n description: size(string(), 1, 280),\n proposedName: size(\n pattern(\n string(),\n /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u,\n ),\n 1,\n 214,\n ),\n repository: optional(\n object({\n type: size(string(), 1, Infinity),\n url: size(string(), 1, Infinity),\n }),\n ),\n source: object({\n shasum: ChecksumStruct,\n location: object({\n npm: object({\n filePath: relativePath(size(string(), 1, Infinity)),\n iconPath: optional(relativePath(size(string(), 1, Infinity))),\n packageName: NameStruct,\n registry: union([\n literal('https://registry.npmjs.org'),\n literal('https://registry.npmjs.org/'),\n ]),\n }),\n }),\n }),\n initialPermissions: PermissionsStruct,\n manifestVersion: literal('0.1'),\n});\n\nexport type SnapManifest = Infer<typeof SnapManifestStruct>;\n\n/**\n * Check if the given value is a valid {@link SnapManifest} object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a valid {@link SnapManifest} object.\n */\nexport function isSnapManifest(value: unknown): value is SnapManifest {\n return is(value, SnapManifestStruct);\n}\n\n/**\n * Assert that the given value is a valid {@link SnapManifest} object.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid {@link SnapManifest} object.\n */\nexport function assertIsSnapManifest(\n value: unknown,\n): asserts value is SnapManifest {\n assertStruct(\n value,\n SnapManifestStruct,\n `\"${NpmSnapFileNames.Manifest}\" is invalid`,\n );\n}\n\n/**\n * Creates a {@link SnapManifest} object from JSON.\n *\n *\n * @param value - The value to check.\n * @throws If the value cannot be coerced to a {@link SnapManifest} object.\n * @returns The created {@link SnapManifest} object.\n */\nexport function createSnapManifest(value: unknown): SnapManifest {\n // TODO: Add a utility to prefix these errors similar to assertStruct\n return create(value, SnapManifestStruct);\n}\n"]}
package/dist/mock.js CHANGED
@@ -7,7 +7,7 @@ exports.generateMockEndowments = exports.isConstructor = exports.ALL_APIS = void
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
8
  const events_1 = __importDefault(require("events"));
9
9
  const default_endowments_1 = require("./default-endowments");
10
- const NETWORK_APIS = ['fetch', 'WebSocket'];
10
+ const NETWORK_APIS = ['fetch'];
11
11
  exports.ALL_APIS = [...default_endowments_1.DEFAULT_ENDOWMENTS, ...NETWORK_APIS];
12
12
  /**
13
13
  * Get a mock snap API, that always returns `true` for requests.
@@ -67,7 +67,6 @@ const generateMockClass = (value) => {
67
67
  // Things not currently auto-mocked because of NodeJS, by adding them here we
68
68
  // have types for them and can use that to generate mocks if needed.
69
69
  const mockWindow = {
70
- WebSocket: MockClass,
71
70
  crypto: crypto_1.default,
72
71
  SubtleCrypto: MockClass,
73
72
  };
package/dist/mock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'crypto';\nimport EventEmitter from 'events';\n\nimport { DEFAULT_ENDOWMENTS } from './default-endowments';\n\nconst NETWORK_APIS = ['fetch', 'WebSocket'];\n\nexport const ALL_APIS: string[] = [...DEFAULT_ENDOWMENTS, ...NETWORK_APIS];\n\ntype MockSnapGlobal = {\n request: () => Promise<any>;\n};\n\ntype MockEthereumProvider = EventEmitter & {\n request: () => Promise<any>;\n};\n\n/**\n * Get a mock snap API, that always returns `true` for requests.\n *\n * @returns A mocked snap provider.\n */\nfunction getMockSnapGlobal(): MockSnapGlobal {\n // eslint-disable-next-line @typescript-eslint/require-await\n return { request: async () => true };\n}\n\n/**\n * Get a mock Ethereum provider, that always returns `true` for requests.\n *\n * @returns A mocked ethereum provider.\n */\nfunction getMockEthereumProvider(): MockEthereumProvider {\n const mockProvider = new EventEmitter() as Partial<MockEthereumProvider>;\n // eslint-disable-next-line @typescript-eslint/require-await\n mockProvider.request = async () => true;\n return mockProvider as MockEthereumProvider;\n}\n\n/**\n * Check if a value is a constructor.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a constructor, or `false` otherwise.\n */\nexport const isConstructor = (value: any) =>\n Boolean(typeof value?.prototype?.constructor?.name === 'string');\n\n/**\n * A function that always returns `true`.\n *\n * @returns `true`.\n */\nconst mockFunction = () => true;\nclass MockClass {}\n\nconst handler = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n construct(Target: any, args: any[]): any {\n return new Proxy(new Target(...args), handler);\n },\n get(_target: any, _prop: any) {\n return mockFunction;\n },\n};\n\n/**\n * Generate a mock class for a given value. The value is wrapped in a Proxy, and\n * all methods are replaced with a mock function.\n *\n * @param value - The value to mock.\n * @returns A mock class.\n */\nconst generateMockClass = (value: any) => {\n return new Proxy(value, handler);\n};\n\n// Things not currently auto-mocked because of NodeJS, by adding them here we\n// have types for them and can use that to generate mocks if needed.\nconst mockWindow: Record<string, unknown> = {\n WebSocket: MockClass,\n crypto,\n SubtleCrypto: MockClass,\n};\n\n/**\n * Generate a mock endowment for a certain class or function on the `globalThis`\n * object.\n *\n * @param key - The key to generate the mock endowment for.\n * @returns A mocked class or function. If the key is part of the default\n * endowments, the original value is returned.\n */\nconst generateMockEndowment = (key: string) => {\n const globalValue = (globalThis as any)[key];\n\n // Default exposed APIs don't need to be mocked\n if (globalValue && DEFAULT_ENDOWMENTS.includes(key)) {\n return globalValue;\n }\n\n // Fall back to mockWindow for certain APIs not exposed in global in Node.JS\n const globalOrMocked = globalValue ?? mockWindow[key];\n\n const type = typeof globalOrMocked;\n const isFunction = type === 'function';\n if (isFunction && isConstructor(globalOrMocked)) {\n return generateMockClass(globalOrMocked);\n } else if (isFunction || !globalOrMocked) {\n // Fall back to function mock for now\n return mockFunction;\n }\n return globalOrMocked;\n};\n\n/**\n * Generate mock endowments for all the APIs as defined in {@link ALL_APIS}.\n *\n * @returns A map of endowments.\n */\nexport const generateMockEndowments = () => {\n return ALL_APIS.reduce<Record<string, any>>(\n (acc, cur) => ({ ...acc, [cur]: generateMockEndowment(cur) }),\n { snap: getMockSnapGlobal(), ethereum: getMockEthereumProvider() },\n );\n};\n"]}
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from 'crypto';\nimport EventEmitter from 'events';\n\nimport { DEFAULT_ENDOWMENTS } from './default-endowments';\n\nconst NETWORK_APIS = ['fetch'];\n\nexport const ALL_APIS: string[] = [...DEFAULT_ENDOWMENTS, ...NETWORK_APIS];\n\ntype MockSnapGlobal = {\n request: () => Promise<any>;\n};\n\ntype MockEthereumProvider = EventEmitter & {\n request: () => Promise<any>;\n};\n\n/**\n * Get a mock snap API, that always returns `true` for requests.\n *\n * @returns A mocked snap provider.\n */\nfunction getMockSnapGlobal(): MockSnapGlobal {\n // eslint-disable-next-line @typescript-eslint/require-await\n return { request: async () => true };\n}\n\n/**\n * Get a mock Ethereum provider, that always returns `true` for requests.\n *\n * @returns A mocked ethereum provider.\n */\nfunction getMockEthereumProvider(): MockEthereumProvider {\n const mockProvider = new EventEmitter() as Partial<MockEthereumProvider>;\n // eslint-disable-next-line @typescript-eslint/require-await\n mockProvider.request = async () => true;\n return mockProvider as MockEthereumProvider;\n}\n\n/**\n * Check if a value is a constructor.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a constructor, or `false` otherwise.\n */\nexport const isConstructor = (value: any) =>\n Boolean(typeof value?.prototype?.constructor?.name === 'string');\n\n/**\n * A function that always returns `true`.\n *\n * @returns `true`.\n */\nconst mockFunction = () => true;\nclass MockClass {}\n\nconst handler = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n construct(Target: any, args: any[]): any {\n return new Proxy(new Target(...args), handler);\n },\n get(_target: any, _prop: any) {\n return mockFunction;\n },\n};\n\n/**\n * Generate a mock class for a given value. The value is wrapped in a Proxy, and\n * all methods are replaced with a mock function.\n *\n * @param value - The value to mock.\n * @returns A mock class.\n */\nconst generateMockClass = (value: any) => {\n return new Proxy(value, handler);\n};\n\n// Things not currently auto-mocked because of NodeJS, by adding them here we\n// have types for them and can use that to generate mocks if needed.\nconst mockWindow: Record<string, unknown> = {\n crypto,\n SubtleCrypto: MockClass,\n};\n\n/**\n * Generate a mock endowment for a certain class or function on the `globalThis`\n * object.\n *\n * @param key - The key to generate the mock endowment for.\n * @returns A mocked class or function. If the key is part of the default\n * endowments, the original value is returned.\n */\nconst generateMockEndowment = (key: string) => {\n const globalValue = (globalThis as any)[key];\n\n // Default exposed APIs don't need to be mocked\n if (globalValue && DEFAULT_ENDOWMENTS.includes(key)) {\n return globalValue;\n }\n\n // Fall back to mockWindow for certain APIs not exposed in global in Node.JS\n const globalOrMocked = globalValue ?? mockWindow[key];\n\n const type = typeof globalOrMocked;\n const isFunction = type === 'function';\n if (isFunction && isConstructor(globalOrMocked)) {\n return generateMockClass(globalOrMocked);\n } else if (isFunction || !globalOrMocked) {\n // Fall back to function mock for now\n return mockFunction;\n }\n return globalOrMocked;\n};\n\n/**\n * Generate mock endowments for all the APIs as defined in {@link ALL_APIS}.\n *\n * @returns A map of endowments.\n */\nexport const generateMockEndowments = () => {\n return ALL_APIS.reduce<Record<string, any>>(\n (acc, cur) => ({ ...acc, [cur]: generateMockEndowment(cur) }),\n { snap: getMockSnapGlobal(), ethereum: getMockEthereumProvider() },\n );\n};\n"]}
package/dist/snaps.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Json } from '@metamask/utils';
1
+ import { BlockReason } from '@metamask/snaps-registry';
2
+ import { Json, SemVerVersion } from '@metamask/utils';
2
3
  import { SerializedEthereumRpcError } from 'eth-rpc-errors/dist/classes';
3
4
  import { Struct } from 'superstruct';
4
5
  import { SnapManifest, SnapPermissions } from './manifest/validation';
5
6
  import { SnapId, SnapIdPrefixes, SnapValidationFailureReason } from './types';
6
- import { SemVerVersion } from './versions';
7
7
  export declare const SNAP_PREFIX = "wallet_snap_";
8
8
  export declare const SNAP_PREFIX_REGEX: RegExp;
9
9
  export declare const PROPOSED_NAME_REGEX: RegExp;
@@ -15,10 +15,6 @@ export declare const PROPOSED_NAME_REGEX: RegExp;
15
15
  export declare type RequestedSnapPermissions = {
16
16
  [permission: string]: Record<string, Json>;
17
17
  };
18
- export declare type BlockedSnapInfo = {
19
- infoUrl?: string;
20
- reason?: string;
21
- };
22
18
  export declare enum SnapStatus {
23
19
  Installing = "installing",
24
20
  Updating = "updating",
@@ -82,7 +78,7 @@ export declare type Snap = {
82
78
  /**
83
79
  * Information detailing why the snap is blocked.
84
80
  */
85
- blockInformation?: BlockedSnapInfo;
81
+ blockInformation?: BlockReason;
86
82
  /**
87
83
  * The name of the permission used to invoke the Snap.
88
84
  */
package/dist/snaps.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"snaps.js","sourceRoot":"","sources":["../src/snaps.ts"],"names":[],"mappings":"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","sourcesContent":["import { assert, Json } from '@metamask/utils';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { base64 } from '@scure/base';\nimport { SerializedEthereumRpcError } from 'eth-rpc-errors/dist/classes';\nimport {\n empty,\n enums,\n intersection,\n literal,\n refine,\n string,\n Struct,\n validate,\n} from 'superstruct';\nimport validateNPMPackage from 'validate-npm-package-name';\n\nimport { SnapManifest, SnapPermissions } from './manifest/validation';\nimport {\n SnapId,\n SnapIdPrefixes,\n SnapValidationFailureReason,\n uri,\n} from './types';\nimport { SemVerVersion } from './versions';\n\nexport const SNAP_PREFIX = 'wallet_snap_';\n\nexport const SNAP_PREFIX_REGEX = new RegExp(`^${SNAP_PREFIX}`, 'u');\n\n// This RegEx matches valid npm package names (with some exceptions) and space-\n// separated alphanumerical words, optionally with dashes and underscores.\n// The RegEx consists of two parts. The first part matches space-separated\n// words. It is based on the following Stackoverflow answer:\n// https://stackoverflow.com/a/34974982\n// The second part, after the pipe operator, is the same RegEx used for the\n// `name` field of the official package.json JSON Schema, except that we allow\n// mixed-case letters. It was originally copied from:\n// https://github.com/SchemaStore/schemastore/blob/81a16897c1dabfd98c72242a5fd62eb080ff76d8/src/schemas/json/package.json#L132-L138\nexport const PROPOSED_NAME_REGEX =\n /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u;\n\n/**\n * wallet_enable / wallet_installSnaps permission typing.\n *\n * @deprecated This type is confusing and not descriptive, people confused it with typing initialPermissions, remove when removing wallet_enable.\n */\nexport type RequestedSnapPermissions = {\n [permission: string]: Record<string, Json>;\n};\n\nexport type BlockedSnapInfo = { infoUrl?: string; reason?: string };\n\nexport enum SnapStatus {\n Installing = 'installing',\n Updating = 'updating',\n Running = 'running',\n Stopped = 'stopped',\n Crashed = 'crashed',\n}\n\nexport enum SnapStatusEvents {\n Start = 'START',\n Stop = 'STOP',\n Crash = 'CRASH',\n Update = 'UPDATE',\n}\n\nexport type StatusContext = { snapId: string };\nexport type StatusEvents = { type: SnapStatusEvents };\nexport type StatusStates = {\n value: SnapStatus;\n context: StatusContext;\n};\nexport type Status = StatusStates['value'];\n\nexport type VersionHistory = {\n origin: string;\n version: string;\n // Unix timestamp\n date: number;\n};\n\nexport type PersistedSnap = Snap & {\n /**\n * The source code of the Snap.\n */\n sourceCode: string;\n};\n\n/**\n * A Snap as it exists in {@link SnapController} state.\n */\nexport type Snap = {\n /**\n * Whether the Snap is enabled, which determines if it can be started.\n */\n enabled: boolean;\n\n /**\n * The ID of the Snap.\n */\n id: SnapId;\n\n /**\n * The initial permissions of the Snap, which will be requested when it is\n * installed.\n */\n initialPermissions: SnapPermissions;\n\n /**\n * The Snap's manifest file.\n */\n manifest: SnapManifest;\n\n /**\n * Whether the Snap is blocked.\n */\n blocked: boolean;\n\n /**\n * Information detailing why the snap is blocked.\n */\n blockInformation?: BlockedSnapInfo;\n\n /**\n * The name of the permission used to invoke the Snap.\n */\n permissionName: string;\n\n /**\n * The current status of the Snap, e.g. whether it's running or stopped.\n */\n status: Status;\n\n /**\n * The version of the Snap.\n */\n version: SemVerVersion;\n\n /**\n * The version history of the Snap.\n * Can be used to derive when the Snap was installed, when it was updated to a certain version and who requested the change.\n */\n versionHistory: VersionHistory[];\n};\n\nexport type TruncatedSnapFields =\n | 'id'\n | 'initialPermissions'\n | 'permissionName'\n | 'version'\n | 'enabled'\n | 'blocked';\n\n/**\n * A {@link Snap} object with the fields that are relevant to an external\n * caller.\n */\nexport type TruncatedSnap = Pick<Snap, TruncatedSnapFields>;\n\nexport type ProcessSnapResult =\n | TruncatedSnap\n | { error: SerializedEthereumRpcError };\n\nexport type InstallSnapsResult = Record<SnapId, ProcessSnapResult>;\n\n/**\n * An error indicating that a Snap validation failure is programmatically\n * fixable during development.\n */\nexport class ProgrammaticallyFixableSnapError extends Error {\n reason: SnapValidationFailureReason;\n\n constructor(message: string, reason: SnapValidationFailureReason) {\n super(message);\n this.reason = reason;\n }\n}\n\n/**\n * Calculates the Base64-encoded SHA-256 digest of a Snap source code string.\n *\n * @param sourceCode - The UTF-8 string source code of a Snap.\n * @returns The Base64-encoded SHA-256 digest of the source code.\n */\nexport function getSnapSourceShasum(sourceCode: string): string {\n return base64.encode(sha256(sourceCode));\n}\n\nexport type ValidatedSnapId = `local:${string}` | `npm:${string}`;\n\n/**\n * Checks whether the `source.shasum` property of a Snap manifest matches the\n * shasum of a snap source code string.\n *\n * @param manifest - The manifest whose shasum to validate.\n * @param sourceCode - The source code of the snap.\n * @param errorMessage - The error message to throw if validation fails.\n */\nexport function validateSnapShasum(\n manifest: SnapManifest,\n sourceCode: string,\n errorMessage = 'Invalid Snap manifest: manifest shasum does not match computed shasum.',\n): void {\n if (manifest.source.shasum !== getSnapSourceShasum(sourceCode)) {\n throw new ProgrammaticallyFixableSnapError(\n errorMessage,\n SnapValidationFailureReason.ShasumMismatch,\n );\n }\n}\n\nexport const LOCALHOST_HOSTNAMES = ['localhost', '127.0.0.1', '[::1]'] as const;\n\nconst LocalSnapIdSubUrlStruct = uri({\n protocol: enums(['http:', 'https:']),\n hostname: enums(LOCALHOST_HOSTNAMES),\n hash: empty(string()),\n search: empty(string()),\n});\nexport const LocalSnapIdStruct = refine(string(), 'local Snap Id', (value) => {\n if (!value.startsWith(SnapIdPrefixes.local)) {\n return `Expected local Snap ID, got \"${value}\".`;\n }\n\n const [error] = validate(\n value.slice(SnapIdPrefixes.local.length),\n LocalSnapIdSubUrlStruct,\n );\n return error ?? true;\n});\nexport const NpmSnapIdStruct = intersection([\n string(),\n uri({\n protocol: literal(SnapIdPrefixes.npm),\n pathname: refine(string(), 'package name', function* (value) {\n const normalized = value.startsWith('/') ? value.slice(1) : value;\n const { errors, validForNewPackages, warnings } =\n validateNPMPackage(normalized);\n if (!validForNewPackages) {\n if (errors === undefined) {\n assert(warnings !== undefined);\n yield* warnings;\n } else {\n yield* errors;\n }\n }\n return true;\n }),\n search: empty(string()),\n hash: empty(string()),\n }),\n]) as unknown as Struct<string, null>;\n\nexport const HttpSnapIdStruct = intersection([\n string(),\n uri({\n protocol: enums(['http:', 'https:']),\n search: empty(string()),\n hash: empty(string()),\n }),\n]) as unknown as Struct<string, null>;\n\n/**\n * Extracts the snap prefix from a snap ID.\n *\n * @param snapId - The snap ID to extract the prefix from.\n * @returns The snap prefix from a snap id, e.g. `npm:`.\n */\nexport function getSnapPrefix(snapId: string): SnapIdPrefixes {\n const prefix = Object.values(SnapIdPrefixes).find((possiblePrefix) =>\n snapId.startsWith(possiblePrefix),\n );\n if (prefix !== undefined) {\n return prefix;\n }\n throw new Error(`Invalid or no prefix found for \"${snapId}\"`);\n}\n\n/**\n * Computes the permission name of a snap from its snap ID.\n *\n * @param snapId - The snap ID.\n * @returns The permission name corresponding to the given snap ID.\n */\nexport function getSnapPermissionName(snapId: string): string {\n return SNAP_PREFIX + snapId;\n}\n\n/**\n * Asserts the provided object is a snapId with a supported prefix.\n *\n * @param snapId - The object to validate.\n * @throws {@link Error}. If the validation fails.\n */\nexport function validateSnapId(\n snapId: unknown,\n): asserts snapId is ValidatedSnapId {\n if (!snapId || typeof snapId !== 'string') {\n throw new Error(`Invalid snap id. Not a string.`);\n }\n\n for (const prefix of Object.values(SnapIdPrefixes)) {\n if (snapId.startsWith(prefix) && snapId.replace(prefix, '').length > 0) {\n return;\n }\n }\n\n throw new Error(`Invalid snap id. Unknown prefix. Received: \"${snapId}\".`);\n}\n\n/**\n * Typeguard to ensure a chainId follows the CAIP-2 standard.\n *\n * @param chainId - The chainId being tested.\n * @returns `true` if the value is a valid CAIP chain id, and `false` otherwise.\n */\nexport function isCaipChainId(chainId: unknown): chainId is string {\n return (\n typeof chainId === 'string' &&\n /^(?<namespace>[-a-z0-9]{3,8}):(?<reference>[-a-zA-Z0-9]{1,32})$/u.test(\n chainId,\n )\n );\n}\n"]}
1
+ {"version":3,"file":"snaps.js","sourceRoot":"","sources":["../src/snaps.ts"],"names":[],"mappings":"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","sourcesContent":["import { BlockReason } from '@metamask/snaps-registry';\nimport { assert, Json, SemVerVersion } from '@metamask/utils';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { base64 } from '@scure/base';\nimport { SerializedEthereumRpcError } from 'eth-rpc-errors/dist/classes';\nimport {\n empty,\n enums,\n intersection,\n literal,\n refine,\n string,\n Struct,\n validate,\n} from 'superstruct';\nimport validateNPMPackage from 'validate-npm-package-name';\n\nimport { SnapManifest, SnapPermissions } from './manifest/validation';\nimport {\n SnapId,\n SnapIdPrefixes,\n SnapValidationFailureReason,\n uri,\n} from './types';\n\nexport const SNAP_PREFIX = 'wallet_snap_';\n\nexport const SNAP_PREFIX_REGEX = new RegExp(`^${SNAP_PREFIX}`, 'u');\n\n// This RegEx matches valid npm package names (with some exceptions) and space-\n// separated alphanumerical words, optionally with dashes and underscores.\n// The RegEx consists of two parts. The first part matches space-separated\n// words. It is based on the following Stackoverflow answer:\n// https://stackoverflow.com/a/34974982\n// The second part, after the pipe operator, is the same RegEx used for the\n// `name` field of the official package.json JSON Schema, except that we allow\n// mixed-case letters. It was originally copied from:\n// https://github.com/SchemaStore/schemastore/blob/81a16897c1dabfd98c72242a5fd62eb080ff76d8/src/schemas/json/package.json#L132-L138\nexport const PROPOSED_NAME_REGEX =\n /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u;\n\n/**\n * wallet_enable / wallet_installSnaps permission typing.\n *\n * @deprecated This type is confusing and not descriptive, people confused it with typing initialPermissions, remove when removing wallet_enable.\n */\nexport type RequestedSnapPermissions = {\n [permission: string]: Record<string, Json>;\n};\n\nexport enum SnapStatus {\n Installing = 'installing',\n Updating = 'updating',\n Running = 'running',\n Stopped = 'stopped',\n Crashed = 'crashed',\n}\n\nexport enum SnapStatusEvents {\n Start = 'START',\n Stop = 'STOP',\n Crash = 'CRASH',\n Update = 'UPDATE',\n}\n\nexport type StatusContext = { snapId: string };\nexport type StatusEvents = { type: SnapStatusEvents };\nexport type StatusStates = {\n value: SnapStatus;\n context: StatusContext;\n};\nexport type Status = StatusStates['value'];\n\nexport type VersionHistory = {\n origin: string;\n version: string;\n // Unix timestamp\n date: number;\n};\n\nexport type PersistedSnap = Snap & {\n /**\n * The source code of the Snap.\n */\n sourceCode: string;\n};\n\n/**\n * A Snap as it exists in {@link SnapController} state.\n */\nexport type Snap = {\n /**\n * Whether the Snap is enabled, which determines if it can be started.\n */\n enabled: boolean;\n\n /**\n * The ID of the Snap.\n */\n id: SnapId;\n\n /**\n * The initial permissions of the Snap, which will be requested when it is\n * installed.\n */\n initialPermissions: SnapPermissions;\n\n /**\n * The Snap's manifest file.\n */\n manifest: SnapManifest;\n\n /**\n * Whether the Snap is blocked.\n */\n blocked: boolean;\n\n /**\n * Information detailing why the snap is blocked.\n */\n blockInformation?: BlockReason;\n\n /**\n * The name of the permission used to invoke the Snap.\n */\n permissionName: string;\n\n /**\n * The current status of the Snap, e.g. whether it's running or stopped.\n */\n status: Status;\n\n /**\n * The version of the Snap.\n */\n version: SemVerVersion;\n\n /**\n * The version history of the Snap.\n * Can be used to derive when the Snap was installed, when it was updated to a certain version and who requested the change.\n */\n versionHistory: VersionHistory[];\n};\n\nexport type TruncatedSnapFields =\n | 'id'\n | 'initialPermissions'\n | 'permissionName'\n | 'version'\n | 'enabled'\n | 'blocked';\n\n/**\n * A {@link Snap} object with the fields that are relevant to an external\n * caller.\n */\nexport type TruncatedSnap = Pick<Snap, TruncatedSnapFields>;\n\nexport type ProcessSnapResult =\n | TruncatedSnap\n | { error: SerializedEthereumRpcError };\n\nexport type InstallSnapsResult = Record<SnapId, ProcessSnapResult>;\n\n/**\n * An error indicating that a Snap validation failure is programmatically\n * fixable during development.\n */\nexport class ProgrammaticallyFixableSnapError extends Error {\n reason: SnapValidationFailureReason;\n\n constructor(message: string, reason: SnapValidationFailureReason) {\n super(message);\n this.reason = reason;\n }\n}\n\n/**\n * Calculates the Base64-encoded SHA-256 digest of a Snap source code string.\n *\n * @param sourceCode - The UTF-8 string source code of a Snap.\n * @returns The Base64-encoded SHA-256 digest of the source code.\n */\nexport function getSnapSourceShasum(sourceCode: string): string {\n return base64.encode(sha256(sourceCode));\n}\n\nexport type ValidatedSnapId = `local:${string}` | `npm:${string}`;\n\n/**\n * Checks whether the `source.shasum` property of a Snap manifest matches the\n * shasum of a snap source code string.\n *\n * @param manifest - The manifest whose shasum to validate.\n * @param sourceCode - The source code of the snap.\n * @param errorMessage - The error message to throw if validation fails.\n */\nexport function validateSnapShasum(\n manifest: SnapManifest,\n sourceCode: string,\n errorMessage = 'Invalid Snap manifest: manifest shasum does not match computed shasum.',\n): void {\n if (manifest.source.shasum !== getSnapSourceShasum(sourceCode)) {\n throw new ProgrammaticallyFixableSnapError(\n errorMessage,\n SnapValidationFailureReason.ShasumMismatch,\n );\n }\n}\n\nexport const LOCALHOST_HOSTNAMES = ['localhost', '127.0.0.1', '[::1]'] as const;\n\nconst LocalSnapIdSubUrlStruct = uri({\n protocol: enums(['http:', 'https:']),\n hostname: enums(LOCALHOST_HOSTNAMES),\n hash: empty(string()),\n search: empty(string()),\n});\nexport const LocalSnapIdStruct = refine(string(), 'local Snap Id', (value) => {\n if (!value.startsWith(SnapIdPrefixes.local)) {\n return `Expected local Snap ID, got \"${value}\".`;\n }\n\n const [error] = validate(\n value.slice(SnapIdPrefixes.local.length),\n LocalSnapIdSubUrlStruct,\n );\n return error ?? true;\n});\nexport const NpmSnapIdStruct = intersection([\n string(),\n uri({\n protocol: literal(SnapIdPrefixes.npm),\n pathname: refine(string(), 'package name', function* (value) {\n const normalized = value.startsWith('/') ? value.slice(1) : value;\n const { errors, validForNewPackages, warnings } =\n validateNPMPackage(normalized);\n if (!validForNewPackages) {\n if (errors === undefined) {\n assert(warnings !== undefined);\n yield* warnings;\n } else {\n yield* errors;\n }\n }\n return true;\n }),\n search: empty(string()),\n hash: empty(string()),\n }),\n]) as unknown as Struct<string, null>;\n\nexport const HttpSnapIdStruct = intersection([\n string(),\n uri({\n protocol: enums(['http:', 'https:']),\n search: empty(string()),\n hash: empty(string()),\n }),\n]) as unknown as Struct<string, null>;\n\n/**\n * Extracts the snap prefix from a snap ID.\n *\n * @param snapId - The snap ID to extract the prefix from.\n * @returns The snap prefix from a snap id, e.g. `npm:`.\n */\nexport function getSnapPrefix(snapId: string): SnapIdPrefixes {\n const prefix = Object.values(SnapIdPrefixes).find((possiblePrefix) =>\n snapId.startsWith(possiblePrefix),\n );\n if (prefix !== undefined) {\n return prefix;\n }\n throw new Error(`Invalid or no prefix found for \"${snapId}\"`);\n}\n\n/**\n * Computes the permission name of a snap from its snap ID.\n *\n * @param snapId - The snap ID.\n * @returns The permission name corresponding to the given snap ID.\n */\nexport function getSnapPermissionName(snapId: string): string {\n return SNAP_PREFIX + snapId;\n}\n\n/**\n * Asserts the provided object is a snapId with a supported prefix.\n *\n * @param snapId - The object to validate.\n * @throws {@link Error}. If the validation fails.\n */\nexport function validateSnapId(\n snapId: unknown,\n): asserts snapId is ValidatedSnapId {\n if (!snapId || typeof snapId !== 'string') {\n throw new Error(`Invalid snap id. Not a string.`);\n }\n\n for (const prefix of Object.values(SnapIdPrefixes)) {\n if (snapId.startsWith(prefix) && snapId.replace(prefix, '').length > 0) {\n return;\n }\n }\n\n throw new Error(`Invalid snap id. Unknown prefix. Received: \"${snapId}\".`);\n}\n\n/**\n * Typeguard to ensure a chainId follows the CAIP-2 standard.\n *\n * @param chainId - The chainId being tested.\n * @returns `true` if the value is a valid CAIP chain id, and `false` otherwise.\n */\nexport function isCaipChainId(chainId: unknown): chainId is string {\n return (\n typeof chainId === 'string' &&\n /^(?<namespace>[-a-z0-9]{3,8}):(?<reference>[-a-zA-Z0-9]{1,32})$/u.test(\n chainId,\n )\n );\n}\n"]}
package/dist/types.d.ts CHANGED
@@ -9,14 +9,14 @@ export declare enum NpmSnapFileNames {
9
9
  export declare const NameStruct: Struct<string, null>;
10
10
  export declare const NpmSnapPackageJsonStruct: Struct<{
11
11
  name: string;
12
- version: import("./versions").SemVerVersion;
12
+ version: import("@metamask/utils").SemVerVersion;
13
13
  repository?: {
14
14
  type: string;
15
15
  url: string;
16
16
  } | undefined;
17
17
  main?: string | undefined;
18
18
  }, {
19
- version: Struct<import("./versions").SemVerVersion, null>;
19
+ version: Struct<import("@metamask/utils").SemVerVersion, null>;
20
20
  name: Struct<string, null>;
21
21
  main: Struct<string | undefined, null>;
22
22
  repository: Struct<{
@@ -100,10 +100,6 @@ declare type ObjectParameters<Type extends Record<string, (...args: any[]) => un
100
100
  declare type KeyringParameter<Fn> = Fn extends (...args: any[]) => unknown ? Parameters<Fn> : never;
101
101
  declare type KeyringParameters = KeyringParameter<Keyring[keyof Keyring]>;
102
102
  export declare type SnapExportsParameters = ObjectParameters<SnapFunctionExports> | KeyringParameters;
103
- declare const brand: unique symbol;
104
- export declare type Opaque<Base, Brand extends symbol> = Base & {
105
- [brand]: Brand;
106
- };
107
103
  declare type UriOptions<T extends string> = {
108
104
  protocol?: Struct<T>;
109
105
  hash?: Struct<T>;
package/dist/types.js CHANGED
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.isValidUrl = exports.uri = exports.SNAP_EXPORT_NAMES = exports.HandlerType = exports.SNAP_STREAM_NAMES = exports.SnapValidationFailureReason = exports.SnapIdPrefixes = exports.assertIsNpmSnapPackageJson = exports.isNpmSnapPackageJson = exports.NpmSnapPackageJsonStruct = exports.NameStruct = exports.NpmSnapFileNames = void 0;
4
4
  const utils_1 = require("@metamask/utils");
5
5
  const superstruct_1 = require("superstruct");
6
- const versions_1 = require("./versions");
7
6
  var NpmSnapFileNames;
8
7
  (function (NpmSnapFileNames) {
9
8
  NpmSnapFileNames["PackageJson"] = "package.json";
@@ -13,7 +12,7 @@ exports.NameStruct = (0, superstruct_1.size)((0, superstruct_1.pattern)((0, supe
13
12
  // Note we use `type` instead of `object` here, because the latter does not
14
13
  // allow unknown keys.
15
14
  exports.NpmSnapPackageJsonStruct = (0, superstruct_1.type)({
16
- version: versions_1.VersionStruct,
15
+ version: utils_1.VersionStruct,
17
16
  name: exports.NameStruct,
18
17
  main: (0, superstruct_1.optional)((0, superstruct_1.size)((0, superstruct_1.string)(), 1, Infinity)),
19
18
  repository: (0, superstruct_1.optional)((0, superstruct_1.object)({
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertStruct, Json } from '@metamask/utils';\nimport {\n Infer,\n instance,\n is,\n object,\n optional,\n pattern,\n refine,\n size,\n string,\n Struct,\n type,\n union,\n assert as assertSuperstruct,\n} from 'superstruct';\n\nimport { SnapFunctionExports, SnapKeyring as Keyring } from './handlers';\nimport { SnapManifest } from './manifest';\nimport { VersionStruct } from './versions';\n\nexport enum NpmSnapFileNames {\n PackageJson = 'package.json',\n Manifest = 'snap.manifest.json',\n}\n\nexport const NameStruct = size(\n pattern(\n string(),\n /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/u,\n ),\n 1,\n 214,\n);\n\n// Note we use `type` instead of `object` here, because the latter does not\n// allow unknown keys.\nexport const NpmSnapPackageJsonStruct = type({\n version: VersionStruct,\n name: NameStruct,\n main: optional(size(string(), 1, Infinity)),\n repository: optional(\n object({\n type: size(string(), 1, Infinity),\n url: size(string(), 1, Infinity),\n }),\n ),\n});\n\nexport type NpmSnapPackageJson = Infer<typeof NpmSnapPackageJsonStruct> &\n Record<string, any>;\n\n/**\n * Check if the given value is a valid {@link NpmSnapPackageJson} object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a valid {@link NpmSnapPackageJson} object.\n */\nexport function isNpmSnapPackageJson(\n value: unknown,\n): value is NpmSnapPackageJson {\n return is(value, NpmSnapPackageJsonStruct);\n}\n\n/**\n * Asserts that the given value is a valid {@link NpmSnapPackageJson} object.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid {@link NpmSnapPackageJson} object.\n */\nexport function assertIsNpmSnapPackageJson(\n value: unknown,\n): asserts value is NpmSnapPackageJson {\n assertStruct(\n value,\n NpmSnapPackageJsonStruct,\n `\"${NpmSnapFileNames.PackageJson}\" is invalid`,\n );\n}\n\n/**\n * An object for storing parsed but unvalidated Snap file contents.\n */\nexport type UnvalidatedSnapFiles = {\n manifest?: Json;\n packageJson?: Json;\n sourceCode?: string;\n svgIcon?: string;\n};\n\n/**\n * An object for storing the contents of Snap files that have passed JSON\n * Schema validation, or are non-empty if they are strings.\n */\nexport type SnapFiles = {\n manifest: SnapManifest;\n packageJson: NpmSnapPackageJson;\n sourceCode: string;\n svgIcon?: string;\n};\n\n/**\n * The possible prefixes for snap ids.\n */\n/* eslint-disable @typescript-eslint/naming-convention */\nexport enum SnapIdPrefixes {\n npm = 'npm:',\n local = 'local:',\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport type SnapId = string;\n\n/**\n * Snap validation failure reason codes that are programmatically fixable\n * if validation occurs during development.\n */\nexport enum SnapValidationFailureReason {\n NameMismatch = '\"name\" field mismatch',\n VersionMismatch = '\"version\" field mismatch',\n RepositoryMismatch = '\"repository\" field mismatch',\n ShasumMismatch = '\"shasum\" field mismatch',\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport enum SNAP_STREAM_NAMES {\n JSON_RPC = 'jsonRpc',\n COMMAND = 'command',\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport enum HandlerType {\n OnRpcRequest = 'onRpcRequest',\n OnTransaction = 'onTransaction',\n SnapKeyring = 'keyring',\n OnCronjob = 'onCronjob',\n}\n\nexport const SNAP_EXPORT_NAMES = Object.values(HandlerType);\n\nexport type SnapRpcHookArgs = {\n origin: string;\n handler: HandlerType;\n request: Record<string, unknown>;\n};\n\n// The snap is the callee\nexport type SnapRpcHook = (options: SnapRpcHookArgs) => Promise<unknown>;\n\ntype ObjectParameters<\n Type extends Record<string, (...args: any[]) => unknown>,\n> = Parameters<Type[keyof Type]>;\n\ntype KeyringParameter<Fn> = Fn extends (...args: any[]) => unknown\n ? Parameters<Fn>\n : never;\n\ntype KeyringParameters = KeyringParameter<Keyring[keyof Keyring]>;\n\nexport type SnapExportsParameters =\n | ObjectParameters<SnapFunctionExports>\n | KeyringParameters;\n\n// We use a symbol property name instead of { _type: Brand }, because that would show up in IDE suggestions,\n// while internal symbols do not.\ndeclare const brand: unique symbol;\nexport type Opaque<Base, Brand extends symbol> = Base & { [brand]: Brand };\n\ntype UriOptions<T extends string> = {\n protocol?: Struct<T>;\n hash?: Struct<T>;\n port?: Struct<T>;\n hostname?: Struct<T>;\n pathname?: Struct<T>;\n search?: Struct<T>;\n};\nexport const uri = (opts: UriOptions<any> = {}) =>\n refine(union([string(), instance(URL)]), 'uri', (value) => {\n try {\n const url = new URL(value);\n\n const UrlStruct = type(opts);\n assertSuperstruct(url, UrlStruct);\n return true;\n } catch {\n return `Expected URL, got \"${value.toString()}\".`;\n }\n });\n\n/**\n * Returns whether a given value is a valid URL.\n *\n * @param url - The value to check.\n * @param opts - Optional constraints for url checking.\n * @returns Whether `url` is valid URL or not.\n */\nexport function isValidUrl(\n url: unknown,\n opts: UriOptions<any> = {},\n): url is string | URL {\n return is(url, uri(opts));\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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","sourcesContent":["import { assertStruct, Json, VersionStruct } from '@metamask/utils';\nimport {\n Infer,\n instance,\n is,\n object,\n optional,\n pattern,\n refine,\n size,\n string,\n Struct,\n type,\n union,\n assert as assertSuperstruct,\n} from 'superstruct';\n\nimport { SnapFunctionExports, SnapKeyring as Keyring } from './handlers';\nimport { SnapManifest } from './manifest';\n\nexport enum NpmSnapFileNames {\n PackageJson = 'package.json',\n Manifest = 'snap.manifest.json',\n}\n\nexport const NameStruct = size(\n pattern(\n string(),\n /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\\/)?[a-z0-9-~][a-z0-9-._~]*$/u,\n ),\n 1,\n 214,\n);\n\n// Note we use `type` instead of `object` here, because the latter does not\n// allow unknown keys.\nexport const NpmSnapPackageJsonStruct = type({\n version: VersionStruct,\n name: NameStruct,\n main: optional(size(string(), 1, Infinity)),\n repository: optional(\n object({\n type: size(string(), 1, Infinity),\n url: size(string(), 1, Infinity),\n }),\n ),\n});\n\nexport type NpmSnapPackageJson = Infer<typeof NpmSnapPackageJsonStruct> &\n Record<string, any>;\n\n/**\n * Check if the given value is a valid {@link NpmSnapPackageJson} object.\n *\n * @param value - The value to check.\n * @returns Whether the value is a valid {@link NpmSnapPackageJson} object.\n */\nexport function isNpmSnapPackageJson(\n value: unknown,\n): value is NpmSnapPackageJson {\n return is(value, NpmSnapPackageJsonStruct);\n}\n\n/**\n * Asserts that the given value is a valid {@link NpmSnapPackageJson} object.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid {@link NpmSnapPackageJson} object.\n */\nexport function assertIsNpmSnapPackageJson(\n value: unknown,\n): asserts value is NpmSnapPackageJson {\n assertStruct(\n value,\n NpmSnapPackageJsonStruct,\n `\"${NpmSnapFileNames.PackageJson}\" is invalid`,\n );\n}\n\n/**\n * An object for storing parsed but unvalidated Snap file contents.\n */\nexport type UnvalidatedSnapFiles = {\n manifest?: Json;\n packageJson?: Json;\n sourceCode?: string;\n svgIcon?: string;\n};\n\n/**\n * An object for storing the contents of Snap files that have passed JSON\n * Schema validation, or are non-empty if they are strings.\n */\nexport type SnapFiles = {\n manifest: SnapManifest;\n packageJson: NpmSnapPackageJson;\n sourceCode: string;\n svgIcon?: string;\n};\n\n/**\n * The possible prefixes for snap ids.\n */\n/* eslint-disable @typescript-eslint/naming-convention */\nexport enum SnapIdPrefixes {\n npm = 'npm:',\n local = 'local:',\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport type SnapId = string;\n\n/**\n * Snap validation failure reason codes that are programmatically fixable\n * if validation occurs during development.\n */\nexport enum SnapValidationFailureReason {\n NameMismatch = '\"name\" field mismatch',\n VersionMismatch = '\"version\" field mismatch',\n RepositoryMismatch = '\"repository\" field mismatch',\n ShasumMismatch = '\"shasum\" field mismatch',\n}\n\n/* eslint-disable @typescript-eslint/naming-convention */\nexport enum SNAP_STREAM_NAMES {\n JSON_RPC = 'jsonRpc',\n COMMAND = 'command',\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport enum HandlerType {\n OnRpcRequest = 'onRpcRequest',\n OnTransaction = 'onTransaction',\n SnapKeyring = 'keyring',\n OnCronjob = 'onCronjob',\n}\n\nexport const SNAP_EXPORT_NAMES = Object.values(HandlerType);\n\nexport type SnapRpcHookArgs = {\n origin: string;\n handler: HandlerType;\n request: Record<string, unknown>;\n};\n\n// The snap is the callee\nexport type SnapRpcHook = (options: SnapRpcHookArgs) => Promise<unknown>;\n\ntype ObjectParameters<\n Type extends Record<string, (...args: any[]) => unknown>,\n> = Parameters<Type[keyof Type]>;\n\ntype KeyringParameter<Fn> = Fn extends (...args: any[]) => unknown\n ? Parameters<Fn>\n : never;\n\ntype KeyringParameters = KeyringParameter<Keyring[keyof Keyring]>;\n\nexport type SnapExportsParameters =\n | ObjectParameters<SnapFunctionExports>\n | KeyringParameters;\n\ntype UriOptions<T extends string> = {\n protocol?: Struct<T>;\n hash?: Struct<T>;\n port?: Struct<T>;\n hostname?: Struct<T>;\n pathname?: Struct<T>;\n search?: Struct<T>;\n};\nexport const uri = (opts: UriOptions<any> = {}) =>\n refine(union([string(), instance(URL)]), 'uri', (value) => {\n try {\n const url = new URL(value);\n\n const UrlStruct = type(opts);\n assertSuperstruct(url, UrlStruct);\n return true;\n } catch {\n return `Expected URL, got \"${value.toString()}\".`;\n }\n });\n\n/**\n * Returns whether a given value is a valid URL.\n *\n * @param url - The value to check.\n * @param opts - Optional constraints for url checking.\n * @returns Whether `url` is valid URL or not.\n */\nexport function isValidUrl(\n url: unknown,\n opts: UriOptions<any> = {},\n): url is string | URL {\n return is(url, uri(opts));\n}\n"]}
@@ -1,104 +1,5 @@
1
- import { Json } from '@metamask/utils';
2
- import { Struct } from 'superstruct';
3
- import { Opaque } from './types';
1
+ import { Json, SemVerVersion, SemVerRange } from '@metamask/utils';
4
2
  export declare const DEFAULT_REQUESTED_SNAP_VERSION: SemVerRange;
5
- /**
6
- * {@link https://codemix.com/opaque-types-in-javascript/ Opaque} type for SemVer ranges.
7
- *
8
- * @example Use {@link assertIsSemVerRange} and {@link isValidSemVerRange} to cast to proper type.
9
- * ```typescript
10
- * const unsafeRange: string = dataFromUser();
11
- * assertIsSemVerRange(unsafeRange);
12
- * unsafeRange
13
- * // ^? SemVerRange
14
- * ```
15
- * @example If you know what you're doing and want to side-step type safety, casting from a string works correctly.
16
- * ```typescript
17
- * const unsafeRange: string = dataFromUser();
18
- * unsafeRange as SemVerRange;
19
- * // ^? SemVerRange
20
- * ```
21
- * @see {@link assertIsSemVerRange}
22
- * @see {@link isValidSemVerRange}
23
- */
24
- export declare type SemVerRange = Opaque<string, typeof semVerRange>;
25
- declare const semVerRange: unique symbol;
26
- /**
27
- * {@link https://codemix.com/opaque-types-in-javascript/ Opaque} type for singular SemVer version.
28
- *
29
- * @example Use {@link assertIsSemVerVersion} and {@link isValidSemVerVersion} to cast to proper type.
30
- * ```typescript
31
- * const unsafeVersion: string = dataFromUser();
32
- * assertIsSemVerVersion(unsafeRange);
33
- * unsafeVersion
34
- * // ^? SemVerVersion
35
- * ```
36
- * @example If you know what you're doing and want to side-step type safety, casting from a string works correctly.
37
- * ```typescript
38
- * const unsafeVersion: string = dataFromUser();
39
- * unsafeRange as SemVerVersion;
40
- * // ^? SemVerVersion
41
- * ```
42
- * @see {@link assertIsSemVerVersion}
43
- * @see {@link isValidSemVerVersion}
44
- */
45
- export declare type SemVerVersion = Opaque<string, typeof semVerVersion>;
46
- declare const semVerVersion: unique symbol;
47
- /**
48
- * A struct for validating a version string.
49
- */
50
- export declare const VersionStruct: Struct<SemVerVersion, null>;
51
- export declare const VersionRangeStruct: Struct<SemVerRange, null>;
52
- /**
53
- * Checks whether a SemVer version is valid.
54
- *
55
- * @param version - A potential version.
56
- * @returns `true` if the version is valid, and `false` otherwise.
57
- */
58
- export declare function isValidSemVerVersion(version: unknown): version is SemVerVersion;
59
- /**
60
- * Checks whether a SemVer version range is valid.
61
- *
62
- * @param versionRange - A potential version range.
63
- * @returns `true` if the version range is valid, and `false` otherwise.
64
- */
65
- export declare function isValidSemVerRange(versionRange: unknown): versionRange is SemVerRange;
66
- /**
67
- * Asserts that a value is a valid concrete SemVer version.
68
- *
69
- * @param version - A potential SemVer concrete version.
70
- */
71
- export declare function assertIsSemVerVersion(version: unknown): asserts version is SemVerVersion;
72
- /**
73
- * Asserts that a value is a valid SemVer range.
74
- *
75
- * @param range - A potential SemVer range.
76
- */
77
- export declare function assertIsSemVerRange(range: unknown): asserts range is SemVerRange;
78
- /**
79
- * Checks whether a SemVer version is greater than another.
80
- *
81
- * @param version1 - The left-hand version.
82
- * @param version2 - The right-hand version.
83
- * @returns `version1 > version2`.
84
- */
85
- export declare function gtVersion(version1: SemVerVersion, version2: SemVerVersion): boolean;
86
- /**
87
- * Checks whether a SemVer version is greater than all possibilities in a range.
88
- *
89
- * @param version - A SemvVer version.
90
- * @param range - The range to check against.
91
- * @returns `version > range`.
92
- */
93
- export declare function gtRange(version: SemVerVersion, range: SemVerRange): boolean;
94
- /**
95
- * Returns whether a SemVer version satisfies a SemVer range.
96
- *
97
- * @param version - The SemVer version to check.
98
- * @param versionRange - The SemVer version range to check against.
99
- * @returns Whether the version satisfied the version range.
100
- */
101
- export declare function satisfiesVersionRange(version: SemVerVersion, versionRange: SemVerRange): boolean;
102
3
  /**
103
4
  * Return the highest version in the list that satisfies the range, or `null` if
104
5
  * none of them do. For the satisfaction check, pre-release versions will only
@@ -118,4 +19,3 @@ export declare function getTargetVersion(versions: SemVerVersion[], versionRange
118
19
  * the specified version.
119
20
  */
120
21
  export declare function resolveVersionRange(version?: Json): [error: undefined, range: SemVerRange] | [error: Error, range: undefined];
121
- export {};
package/dist/versions.js CHANGED
@@ -1,98 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.resolveVersionRange = exports.getTargetVersion = exports.satisfiesVersionRange = exports.gtRange = exports.gtVersion = exports.assertIsSemVerRange = exports.assertIsSemVerVersion = exports.isValidSemVerRange = exports.isValidSemVerVersion = exports.VersionRangeStruct = exports.VersionStruct = exports.DEFAULT_REQUESTED_SNAP_VERSION = void 0;
3
+ exports.resolveVersionRange = exports.getTargetVersion = exports.DEFAULT_REQUESTED_SNAP_VERSION = void 0;
4
4
  const utils_1 = require("@metamask/utils");
5
5
  const semver_1 = require("semver");
6
6
  const superstruct_1 = require("superstruct");
7
7
  exports.DEFAULT_REQUESTED_SNAP_VERSION = '*';
8
- /**
9
- * A struct for validating a version string.
10
- */
11
- exports.VersionStruct = (0, superstruct_1.refine)((0, superstruct_1.string)(), 'Version', (value) => {
12
- if ((0, semver_1.valid)(value) === null) {
13
- return `Expected SemVer version, got "${value}"`;
14
- }
15
- return true;
16
- });
17
- exports.VersionRangeStruct = (0, superstruct_1.refine)((0, superstruct_1.string)(), 'Version range', (value) => {
18
- if ((0, semver_1.validRange)(value) === null) {
19
- return `Expected SemVer range, got "${value}"`;
20
- }
21
- return true;
22
- });
23
- /**
24
- * Checks whether a SemVer version is valid.
25
- *
26
- * @param version - A potential version.
27
- * @returns `true` if the version is valid, and `false` otherwise.
28
- */
29
- function isValidSemVerVersion(version) {
30
- return (0, superstruct_1.is)(version, exports.VersionStruct);
31
- }
32
- exports.isValidSemVerVersion = isValidSemVerVersion;
33
- /**
34
- * Checks whether a SemVer version range is valid.
35
- *
36
- * @param versionRange - A potential version range.
37
- * @returns `true` if the version range is valid, and `false` otherwise.
38
- */
39
- function isValidSemVerRange(versionRange) {
40
- return (0, superstruct_1.is)(versionRange, exports.VersionRangeStruct);
41
- }
42
- exports.isValidSemVerRange = isValidSemVerRange;
43
- /**
44
- * Asserts that a value is a valid concrete SemVer version.
45
- *
46
- * @param version - A potential SemVer concrete version.
47
- */
48
- function assertIsSemVerVersion(version) {
49
- (0, utils_1.assertStruct)(version, exports.VersionStruct);
50
- }
51
- exports.assertIsSemVerVersion = assertIsSemVerVersion;
52
- /**
53
- * Asserts that a value is a valid SemVer range.
54
- *
55
- * @param range - A potential SemVer range.
56
- */
57
- function assertIsSemVerRange(range) {
58
- (0, utils_1.assertStruct)(range, exports.VersionRangeStruct);
59
- }
60
- exports.assertIsSemVerRange = assertIsSemVerRange;
61
- /**
62
- * Checks whether a SemVer version is greater than another.
63
- *
64
- * @param version1 - The left-hand version.
65
- * @param version2 - The right-hand version.
66
- * @returns `version1 > version2`.
67
- */
68
- function gtVersion(version1, version2) {
69
- return (0, semver_1.gt)(version1, version2);
70
- }
71
- exports.gtVersion = gtVersion;
72
- /**
73
- * Checks whether a SemVer version is greater than all possibilities in a range.
74
- *
75
- * @param version - A SemvVer version.
76
- * @param range - The range to check against.
77
- * @returns `version > range`.
78
- */
79
- function gtRange(version, range) {
80
- return (0, semver_1.gtr)(version, range);
81
- }
82
- exports.gtRange = gtRange;
83
- /**
84
- * Returns whether a SemVer version satisfies a SemVer range.
85
- *
86
- * @param version - The SemVer version to check.
87
- * @param versionRange - The SemVer version range to check against.
88
- * @returns Whether the version satisfied the version range.
89
- */
90
- function satisfiesVersionRange(version, versionRange) {
91
- return (0, semver_1.satisfies)(version, versionRange, {
92
- includePrerelease: true,
93
- });
94
- }
95
- exports.satisfiesVersionRange = satisfiesVersionRange;
96
8
  /**
97
9
  * Return the highest version in the list that satisfies the range, or `null` if
98
10
  * none of them do. For the satisfaction check, pre-release versions will only
@@ -126,7 +38,7 @@ function resolveVersionRange(version) {
126
38
  if (version === undefined || version === 'latest') {
127
39
  return [undefined, exports.DEFAULT_REQUESTED_SNAP_VERSION];
128
40
  }
129
- return (0, superstruct_1.validate)(version, exports.VersionRangeStruct);
41
+ return (0, superstruct_1.validate)(version, utils_1.VersionRangeStruct);
130
42
  }
131
43
  exports.resolveVersionRange = resolveVersionRange;
132
44
  //# sourceMappingURL=versions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":";;;AAAA,2CAAqD;AACrD,mCAOgB;AAChB,6CAAmE;AAItD,QAAA,8BAA8B,GAAG,GAAkB,CAAC;AA8CjE;;GAEG;AACU,QAAA,aAAa,GAAG,IAAA,oBAAM,EACjC,IAAA,oBAAM,GAA4C,EAClD,SAAS,EACT,CAAC,KAAK,EAAE,EAAE;IACR,IAAI,IAAA,cAAkB,EAAC,KAAK,CAAC,KAAK,IAAI,EAAE;QACtC,OAAO,iCAAiC,KAAK,GAAG,CAAC;KAClD;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CACF,CAAC;AAEW,QAAA,kBAAkB,GAAG,IAAA,oBAAM,EACtC,IAAA,oBAAM,GAA0C,EAChD,eAAe,EACf,CAAC,KAAK,EAAE,EAAE;IACR,IAAI,IAAA,mBAAgB,EAAC,KAAK,CAAC,KAAK,IAAI,EAAE;QACpC,OAAO,+BAA+B,KAAK,GAAG,CAAC;KAChD;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CACF,CAAC;AAEF;;;;;GAKG;AACH,SAAgB,oBAAoB,CAClC,OAAgB;IAEhB,OAAO,IAAA,gBAAE,EAAC,OAAO,EAAE,qBAAa,CAAC,CAAC;AACpC,CAAC;AAJD,oDAIC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAChC,YAAqB;IAErB,OAAO,IAAA,gBAAE,EAAC,YAAY,EAAE,0BAAkB,CAAC,CAAC;AAC9C,CAAC;AAJD,gDAIC;AAED;;;;GAIG;AACH,SAAgB,qBAAqB,CACnC,OAAgB;IAEhB,IAAA,oBAAY,EAAC,OAAO,EAAE,qBAAa,CAAC,CAAC;AACvC,CAAC;AAJD,sDAIC;AAED;;;;GAIG;AACH,SAAgB,mBAAmB,CACjC,KAAc;IAEd,IAAA,oBAAY,EAAC,KAAK,EAAE,0BAAkB,CAAC,CAAC;AAC1C,CAAC;AAJD,kDAIC;AAED;;;;;;GAMG;AACH,SAAgB,SAAS,CACvB,QAAuB,EACvB,QAAuB;IAEvB,OAAO,IAAA,WAAQ,EAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACtC,CAAC;AALD,8BAKC;AAED;;;;;;GAMG;AACH,SAAgB,OAAO,CAAC,OAAsB,EAAE,KAAkB;IAChE,OAAO,IAAA,YAAS,EAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACnC,CAAC;AAFD,0BAEC;AAED;;;;;;GAMG;AACH,SAAgB,qBAAqB,CACnC,OAAsB,EACtB,YAAyB;IAEzB,OAAO,IAAA,kBAAe,EAAC,OAAO,EAAE,YAAY,EAAE;QAC5C,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;AACL,CAAC;AAPD,sDAOC;AAED;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAC9B,QAAyB,EACzB,YAAyB;IAEzB,MAAM,0BAA0B,GAAG,IAAA,sBAAmB,EACpD,QAAQ,EACR,YAAY,CACb,CAAC;IAEF,4CAA4C;IAC5C,IAAI,0BAA0B,EAAE;QAC9B,OAAO,0BAA0B,CAAC;KACnC;IAED,iFAAiF;IACjF,OAAO,IAAA,sBAAmB,EAAC,QAAQ,EAAE,YAAY,EAAE;QACjD,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;AACL,CAAC;AAlBD,4CAkBC;AAED;;;;;;GAMG;AACH,SAAgB,mBAAmB,CACjC,OAAc;IAEd,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,EAAE;QACjD,OAAO,CAAC,SAAS,EAAE,sCAA8B,CAAC,CAAC;KACpD;IACD,OAAO,IAAA,sBAAQ,EAAC,OAAO,EAAE,0BAAkB,CAAC,CAAC;AAC/C,CAAC;AAPD,kDAOC","sourcesContent":["import { assertStruct, Json } from '@metamask/utils';\nimport {\n gt as gtSemver,\n gtr as gtrSemver,\n maxSatisfying as maxSatisfyingSemver,\n satisfies as satisfiesSemver,\n valid as validSemVerVersion,\n validRange as validSemVerRange,\n} from 'semver';\nimport { is, refine, string, Struct, validate } from 'superstruct';\n\nimport { Opaque } from './types';\n\nexport const DEFAULT_REQUESTED_SNAP_VERSION = '*' as SemVerRange;\n\n/**\n * {@link https://codemix.com/opaque-types-in-javascript/ Opaque} type for SemVer ranges.\n *\n * @example Use {@link assertIsSemVerRange} and {@link isValidSemVerRange} to cast to proper type.\n * ```typescript\n * const unsafeRange: string = dataFromUser();\n * assertIsSemVerRange(unsafeRange);\n * unsafeRange\n * // ^? SemVerRange\n * ```\n * @example If you know what you're doing and want to side-step type safety, casting from a string works correctly.\n * ```typescript\n * const unsafeRange: string = dataFromUser();\n * unsafeRange as SemVerRange;\n * // ^? SemVerRange\n * ```\n * @see {@link assertIsSemVerRange}\n * @see {@link isValidSemVerRange}\n */\nexport type SemVerRange = Opaque<string, typeof semVerRange>;\ndeclare const semVerRange: unique symbol;\n\n/**\n * {@link https://codemix.com/opaque-types-in-javascript/ Opaque} type for singular SemVer version.\n *\n * @example Use {@link assertIsSemVerVersion} and {@link isValidSemVerVersion} to cast to proper type.\n * ```typescript\n * const unsafeVersion: string = dataFromUser();\n * assertIsSemVerVersion(unsafeRange);\n * unsafeVersion\n * // ^? SemVerVersion\n * ```\n * @example If you know what you're doing and want to side-step type safety, casting from a string works correctly.\n * ```typescript\n * const unsafeVersion: string = dataFromUser();\n * unsafeRange as SemVerVersion;\n * // ^? SemVerVersion\n * ```\n * @see {@link assertIsSemVerVersion}\n * @see {@link isValidSemVerVersion}\n */\nexport type SemVerVersion = Opaque<string, typeof semVerVersion>;\ndeclare const semVerVersion: unique symbol;\n\n/**\n * A struct for validating a version string.\n */\nexport const VersionStruct = refine<SemVerVersion, null>(\n string() as unknown as Struct<SemVerVersion, null>,\n 'Version',\n (value) => {\n if (validSemVerVersion(value) === null) {\n return `Expected SemVer version, got \"${value}\"`;\n }\n return true;\n },\n);\n\nexport const VersionRangeStruct = refine<SemVerRange, null>(\n string() as unknown as Struct<SemVerRange, null>,\n 'Version range',\n (value) => {\n if (validSemVerRange(value) === null) {\n return `Expected SemVer range, got \"${value}\"`;\n }\n return true;\n },\n);\n\n/**\n * Checks whether a SemVer version is valid.\n *\n * @param version - A potential version.\n * @returns `true` if the version is valid, and `false` otherwise.\n */\nexport function isValidSemVerVersion(\n version: unknown,\n): version is SemVerVersion {\n return is(version, VersionStruct);\n}\n\n/**\n * Checks whether a SemVer version range is valid.\n *\n * @param versionRange - A potential version range.\n * @returns `true` if the version range is valid, and `false` otherwise.\n */\nexport function isValidSemVerRange(\n versionRange: unknown,\n): versionRange is SemVerRange {\n return is(versionRange, VersionRangeStruct);\n}\n\n/**\n * Asserts that a value is a valid concrete SemVer version.\n *\n * @param version - A potential SemVer concrete version.\n */\nexport function assertIsSemVerVersion(\n version: unknown,\n): asserts version is SemVerVersion {\n assertStruct(version, VersionStruct);\n}\n\n/**\n * Asserts that a value is a valid SemVer range.\n *\n * @param range - A potential SemVer range.\n */\nexport function assertIsSemVerRange(\n range: unknown,\n): asserts range is SemVerRange {\n assertStruct(range, VersionRangeStruct);\n}\n\n/**\n * Checks whether a SemVer version is greater than another.\n *\n * @param version1 - The left-hand version.\n * @param version2 - The right-hand version.\n * @returns `version1 > version2`.\n */\nexport function gtVersion(\n version1: SemVerVersion,\n version2: SemVerVersion,\n): boolean {\n return gtSemver(version1, version2);\n}\n\n/**\n * Checks whether a SemVer version is greater than all possibilities in a range.\n *\n * @param version - A SemvVer version.\n * @param range - The range to check against.\n * @returns `version > range`.\n */\nexport function gtRange(version: SemVerVersion, range: SemVerRange): boolean {\n return gtrSemver(version, range);\n}\n\n/**\n * Returns whether a SemVer version satisfies a SemVer range.\n *\n * @param version - The SemVer version to check.\n * @param versionRange - The SemVer version range to check against.\n * @returns Whether the version satisfied the version range.\n */\nexport function satisfiesVersionRange(\n version: SemVerVersion,\n versionRange: SemVerRange,\n): boolean {\n return satisfiesSemver(version, versionRange, {\n includePrerelease: true,\n });\n}\n\n/**\n * Return the highest version in the list that satisfies the range, or `null` if\n * none of them do. For the satisfaction check, pre-release versions will only\n * be checked if no satisfactory non-prerelease version is found first.\n *\n * @param versions - The list of version to check.\n * @param versionRange - The SemVer version range to check against.\n * @returns The highest version in the list that satisfies the range,\n * or `null` if none of them do.\n */\nexport function getTargetVersion(\n versions: SemVerVersion[],\n versionRange: SemVerRange,\n): SemVerVersion | null {\n const maxSatisfyingNonPreRelease = maxSatisfyingSemver(\n versions,\n versionRange,\n );\n\n // By default don't use pre-release versions\n if (maxSatisfyingNonPreRelease) {\n return maxSatisfyingNonPreRelease;\n }\n\n // If no satisfying release version is found by default, try pre-release versions\n return maxSatisfyingSemver(versions, versionRange, {\n includePrerelease: true,\n });\n}\n\n/**\n * Parse a version received by some subject attempting to access a snap.\n *\n * @param version - The received version value.\n * @returns `*` if the version is `undefined` or `latest\", otherwise returns\n * the specified version.\n */\nexport function resolveVersionRange(\n version?: Json,\n): [error: undefined, range: SemVerRange] | [error: Error, range: undefined] {\n if (version === undefined || version === 'latest') {\n return [undefined, DEFAULT_REQUESTED_SNAP_VERSION];\n }\n return validate(version, VersionRangeStruct);\n}\n"]}
1
+ {"version":3,"file":"versions.js","sourceRoot":"","sources":["../src/versions.ts"],"names":[],"mappings":";;;AAAA,2CAKyB;AACzB,mCAA8D;AAC9D,6CAAuC;AAE1B,QAAA,8BAA8B,GAAG,GAAkB,CAAC;AAEjE;;;;;;;;;GASG;AACH,SAAgB,gBAAgB,CAC9B,QAAyB,EACzB,YAAyB;IAEzB,MAAM,0BAA0B,GAAG,IAAA,sBAAmB,EACpD,QAAQ,EACR,YAAY,CACb,CAAC;IAEF,4CAA4C;IAC5C,IAAI,0BAA0B,EAAE;QAC9B,OAAO,0BAA0B,CAAC;KACnC;IAED,iFAAiF;IACjF,OAAO,IAAA,sBAAmB,EAAC,QAAQ,EAAE,YAAY,EAAE;QACjD,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;AACL,CAAC;AAlBD,4CAkBC;AAED;;;;;;GAMG;AACH,SAAgB,mBAAmB,CACjC,OAAc;IAEd,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,QAAQ,EAAE;QACjD,OAAO,CAAC,SAAS,EAAE,sCAA8B,CAAC,CAAC;KACpD;IACD,OAAO,IAAA,sBAAQ,EAAC,OAAO,EAAE,0BAAkB,CAAC,CAAC;AAC/C,CAAC;AAPD,kDAOC","sourcesContent":["import {\n Json,\n SemVerVersion,\n SemVerRange,\n VersionRangeStruct,\n} from '@metamask/utils';\nimport { maxSatisfying as maxSatisfyingSemver } from 'semver';\nimport { validate } from 'superstruct';\n\nexport const DEFAULT_REQUESTED_SNAP_VERSION = '*' as SemVerRange;\n\n/**\n * Return the highest version in the list that satisfies the range, or `null` if\n * none of them do. For the satisfaction check, pre-release versions will only\n * be checked if no satisfactory non-prerelease version is found first.\n *\n * @param versions - The list of version to check.\n * @param versionRange - The SemVer version range to check against.\n * @returns The highest version in the list that satisfies the range,\n * or `null` if none of them do.\n */\nexport function getTargetVersion(\n versions: SemVerVersion[],\n versionRange: SemVerRange,\n): SemVerVersion | null {\n const maxSatisfyingNonPreRelease = maxSatisfyingSemver(\n versions,\n versionRange,\n );\n\n // By default don't use pre-release versions\n if (maxSatisfyingNonPreRelease) {\n return maxSatisfyingNonPreRelease;\n }\n\n // If no satisfying release version is found by default, try pre-release versions\n return maxSatisfyingSemver(versions, versionRange, {\n includePrerelease: true,\n });\n}\n\n/**\n * Parse a version received by some subject attempting to access a snap.\n *\n * @param version - The received version value.\n * @returns `*` if the version is `undefined` or `latest\", otherwise returns\n * the specified version.\n */\nexport function resolveVersionRange(\n version?: Json,\n): [error: undefined, range: SemVerRange] | [error: Error, range: undefined] {\n if (version === undefined || version === 'latest') {\n return [undefined, DEFAULT_REQUESTED_SNAP_VERSION];\n }\n return validate(version, VersionRangeStruct);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metamask/snaps-utils",
3
- "version": "0.27.1",
3
+ "version": "0.28.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/MetaMask/snaps-monorepo.git"
@@ -53,8 +53,9 @@
53
53
  "@babel/core": "^7.18.6",
54
54
  "@babel/types": "^7.18.7",
55
55
  "@metamask/providers": "^10.2.1",
56
- "@metamask/snaps-ui": "^0.27.1",
57
- "@metamask/utils": "^3.3.1",
56
+ "@metamask/snaps-registry": "^1.0.0",
57
+ "@metamask/snaps-ui": "^0.28.0",
58
+ "@metamask/utils": "^3.4.1",
58
59
  "@noble/hashes": "^1.1.3",
59
60
  "@scure/base": "^1.1.1",
60
61
  "cron-parser": "^4.5.0",
@@ -62,8 +63,8 @@
62
63
  "fast-deep-equal": "^3.1.3",
63
64
  "rfdc": "^1.3.0",
64
65
  "semver": "^7.3.7",
65
- "ses": "^0.17.0",
66
- "superstruct": "^0.16.7",
66
+ "ses": "^0.18.1",
67
+ "superstruct": "^1.0.3",
67
68
  "validate-npm-package-name": "^5.0.0"
68
69
  },
69
70
  "devDependencies": {
@@ -73,6 +74,8 @@
73
74
  "@metamask/eslint-config-jest": "^11.0.0",
74
75
  "@metamask/eslint-config-nodejs": "^11.0.1",
75
76
  "@metamask/eslint-config-typescript": "^11.0.0",
77
+ "@metamask/key-tree": "^6.2.0",
78
+ "@metamask/post-message-stream": "^6.1.0",
76
79
  "@types/jest": "^27.5.1",
77
80
  "@types/semver": "^7.3.10",
78
81
  "@types/validate-npm-package-name": "^4.0.0",
@@ -92,6 +95,7 @@
92
95
  "prettier": "^2.7.1",
93
96
  "prettier-plugin-packagejson": "^2.2.11",
94
97
  "rimraf": "^3.0.2",
98
+ "serve-handler": "^6.1.5",
95
99
  "ts-jest": "^29.0.0",
96
100
  "typescript": "~4.8.4"
97
101
  },