@metamask/snaps-controllers 0.32.2 → 0.33.1-flask.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +575 -0
  2. package/dist/services/{offscreen/OffscreenPostMessageStream.d.ts → ProxyPostMessageStream.d.ts} +9 -9
  3. package/dist/services/ProxyPostMessageStream.js +62 -0
  4. package/dist/services/ProxyPostMessageStream.js.map +1 -0
  5. package/dist/services/browser.d.ts +2 -0
  6. package/dist/services/browser.js +4 -0
  7. package/dist/services/browser.js.map +1 -1
  8. package/dist/services/index.d.ts +2 -0
  9. package/dist/services/index.js +4 -0
  10. package/dist/services/index.js.map +1 -1
  11. package/dist/services/offscreen/OffscreenExecutionService.d.ts +2 -2
  12. package/dist/services/offscreen/OffscreenExecutionService.js +8 -3
  13. package/dist/services/offscreen/OffscreenExecutionService.js.map +1 -1
  14. package/dist/services/offscreen/index.d.ts +0 -1
  15. package/dist/services/offscreen/index.js +0 -1
  16. package/dist/services/offscreen/index.js.map +1 -1
  17. package/dist/services/webworker/WebWorkerExecutionService.d.ts +44 -0
  18. package/dist/services/webworker/WebWorkerExecutionService.js +100 -0
  19. package/dist/services/webworker/WebWorkerExecutionService.js.map +1 -0
  20. package/dist/services/webworker/index.d.ts +1 -0
  21. package/dist/services/webworker/index.js +18 -0
  22. package/dist/services/webworker/index.js.map +1 -0
  23. package/dist/snaps/SnapController.d.ts +13 -3
  24. package/dist/snaps/SnapController.js +35 -23
  25. package/dist/snaps/SnapController.js.map +1 -1
  26. package/dist/snaps/endowments/cronjob.js +1 -0
  27. package/dist/snaps/endowments/cronjob.js.map +1 -1
  28. package/dist/snaps/endowments/ethereum-provider.js +1 -0
  29. package/dist/snaps/endowments/ethereum-provider.js.map +1 -1
  30. package/dist/snaps/endowments/index.d.ts +2 -0
  31. package/dist/snaps/endowments/keyring.d.ts +2 -1
  32. package/dist/snaps/endowments/keyring.js +1 -0
  33. package/dist/snaps/endowments/keyring.js.map +1 -1
  34. package/dist/snaps/endowments/long-running.js +1 -0
  35. package/dist/snaps/endowments/long-running.js.map +1 -1
  36. package/dist/snaps/endowments/network-access.js +1 -0
  37. package/dist/snaps/endowments/network-access.js.map +1 -1
  38. package/dist/snaps/endowments/rpc.d.ts +2 -1
  39. package/dist/snaps/endowments/rpc.js +1 -0
  40. package/dist/snaps/endowments/rpc.js.map +1 -1
  41. package/dist/snaps/endowments/transaction-insight.js +1 -0
  42. package/dist/snaps/endowments/transaction-insight.js.map +1 -1
  43. package/dist/snaps/endowments/web-assembly.js +1 -0
  44. package/dist/snaps/endowments/web-assembly.js.map +1 -1
  45. package/package.json +23 -23
  46. package/dist/services/offscreen/OffscreenPostMessageStream.js +0 -66
  47. package/dist/services/offscreen/OffscreenPostMessageStream.js.map +0 -1
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _ProxyPostMessageStream_instances, _ProxyPostMessageStream_stream, _ProxyPostMessageStream_jobId, _ProxyPostMessageStream_extra, _ProxyPostMessageStream_onData;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ProxyPostMessageStream = void 0;
16
+ const post_message_stream_1 = require("@metamask/post-message-stream");
17
+ /**
18
+ * A post message stream that wraps messages in a job ID, before sending them
19
+ * over the underlying stream.
20
+ */
21
+ class ProxyPostMessageStream extends post_message_stream_1.BasePostMessageStream {
22
+ /**
23
+ * Initializes a new `ProxyPostMessageStream` instance.
24
+ *
25
+ * @param args - The constructor arguments.
26
+ * @param args.stream - The underlying stream to use for communication.
27
+ * @param args.jobId - The ID of the job this stream is associated with.
28
+ * @param args.extra - Extra data to include in the post message.
29
+ */
30
+ constructor({ stream, jobId, extra }) {
31
+ super();
32
+ _ProxyPostMessageStream_instances.add(this);
33
+ _ProxyPostMessageStream_stream.set(this, void 0);
34
+ _ProxyPostMessageStream_jobId.set(this, void 0);
35
+ _ProxyPostMessageStream_extra.set(this, void 0);
36
+ __classPrivateFieldSet(this, _ProxyPostMessageStream_stream, stream, "f");
37
+ __classPrivateFieldSet(this, _ProxyPostMessageStream_jobId, jobId, "f");
38
+ __classPrivateFieldSet(this, _ProxyPostMessageStream_extra, extra, "f");
39
+ __classPrivateFieldGet(this, _ProxyPostMessageStream_stream, "f").on('data', __classPrivateFieldGet(this, _ProxyPostMessageStream_instances, "m", _ProxyPostMessageStream_onData).bind(this));
40
+ }
41
+ /**
42
+ * Write data to the underlying stream. This wraps the data in an object with
43
+ * the job ID.
44
+ *
45
+ * @param data - The data to write.
46
+ */
47
+ _postMessage(data) {
48
+ __classPrivateFieldGet(this, _ProxyPostMessageStream_stream, "f").write({
49
+ jobId: __classPrivateFieldGet(this, _ProxyPostMessageStream_jobId, "f"),
50
+ data,
51
+ extra: __classPrivateFieldGet(this, _ProxyPostMessageStream_extra, "f"),
52
+ });
53
+ }
54
+ }
55
+ exports.ProxyPostMessageStream = ProxyPostMessageStream;
56
+ _ProxyPostMessageStream_stream = new WeakMap(), _ProxyPostMessageStream_jobId = new WeakMap(), _ProxyPostMessageStream_extra = new WeakMap(), _ProxyPostMessageStream_instances = new WeakSet(), _ProxyPostMessageStream_onData = function _ProxyPostMessageStream_onData(data) {
57
+ if (data.jobId !== __classPrivateFieldGet(this, _ProxyPostMessageStream_jobId, "f")) {
58
+ return;
59
+ }
60
+ this.push(data.data);
61
+ };
62
+ //# sourceMappingURL=ProxyPostMessageStream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProxyPostMessageStream.js","sourceRoot":"","sources":["../../src/services/ProxyPostMessageStream.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uEAAsE;AAetE;;;GAGG;AACH,MAAa,sBAAuB,SAAQ,2CAAqB;IAO/D;;;;;;;OAOG;IACH,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAA8B;QAC9D,KAAK,EAAE,CAAC;;QAfV,iDAAwC;QAExC,gDAAwB;QAExB,gDAA0C;QAaxC,uBAAA,IAAI,kCAAW,MAAM,MAAA,CAAC;QACtB,uBAAA,IAAI,iCAAU,KAAK,MAAA,CAAC;QACpB,uBAAA,IAAI,iCAAU,KAAK,MAAA,CAAC;QAEpB,uBAAA,IAAI,sCAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAA,IAAI,yEAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACnD,CAAC;IAgBD;;;;;OAKG;IACH,YAAY,CAAC,IAAsB;QACjC,uBAAA,IAAI,sCAAQ,CAAC,KAAK,CAAC;YACjB,KAAK,EAAE,uBAAA,IAAI,qCAAO;YAClB,IAAI;YACJ,KAAK,EAAE,uBAAA,IAAI,qCAAO;SACnB,CAAC,CAAC;IACL,CAAC;CACF;AApDD,wDAoDC;0QArBS,IAAsB;IAC5B,IAAI,IAAI,CAAC,KAAK,KAAK,uBAAA,IAAI,qCAAO,EAAE;QAC9B,OAAO;KACR;IAED,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC","sourcesContent":["import { BasePostMessageStream } from '@metamask/post-message-stream';\nimport { JsonRpcRequest } from '@metamask/utils';\n\nexport type ProxyPostMessageStreamArgs = {\n stream: BasePostMessageStream;\n jobId: string;\n extra?: Record<string, unknown>;\n};\n\nexport type ProxyPostMessage = {\n jobId: string;\n data: JsonRpcRequest;\n extra?: Record<string, unknown>;\n};\n\n/**\n * A post message stream that wraps messages in a job ID, before sending them\n * over the underlying stream.\n */\nexport class ProxyPostMessageStream extends BasePostMessageStream {\n readonly #stream: BasePostMessageStream;\n\n readonly #jobId: string;\n\n readonly #extra?: Record<string, unknown>;\n\n /**\n * Initializes a new `ProxyPostMessageStream` instance.\n *\n * @param args - The constructor arguments.\n * @param args.stream - The underlying stream to use for communication.\n * @param args.jobId - The ID of the job this stream is associated with.\n * @param args.extra - Extra data to include in the post message.\n */\n constructor({ stream, jobId, extra }: ProxyPostMessageStreamArgs) {\n super();\n\n this.#stream = stream;\n this.#jobId = jobId;\n this.#extra = extra;\n\n this.#stream.on('data', this.#onData.bind(this));\n }\n\n /**\n * Handle incoming data from the underlying stream. This checks that the job\n * ID matches the expected job ID, and pushes the data to the stream if so.\n *\n * @param data - The data to handle.\n */\n #onData(data: ProxyPostMessage) {\n if (data.jobId !== this.#jobId) {\n return;\n }\n\n this.push(data.data);\n }\n\n /**\n * Write data to the underlying stream. This wraps the data in an object with\n * the job ID.\n *\n * @param data - The data to write.\n */\n _postMessage(data: ProxyPostMessage) {\n this.#stream.write({\n jobId: this.#jobId,\n data,\n extra: this.#extra,\n });\n }\n}\n"]}
@@ -1,4 +1,6 @@
1
1
  export * from './AbstractExecutionService';
2
2
  export * from './ExecutionService';
3
+ export * from './ProxyPostMessageStream';
3
4
  export * from './iframe';
4
5
  export * from './offscreen';
6
+ export { WebWorkerExecutionService } from './webworker';
@@ -14,9 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.WebWorkerExecutionService = void 0;
17
18
  // Subset of exports meant for browser environments, omits Node.js services
18
19
  __exportStar(require("./AbstractExecutionService"), exports);
19
20
  __exportStar(require("./ExecutionService"), exports);
21
+ __exportStar(require("./ProxyPostMessageStream"), exports);
20
22
  __exportStar(require("./iframe"), exports);
21
23
  __exportStar(require("./offscreen"), exports);
24
+ var webworker_1 = require("./webworker");
25
+ Object.defineProperty(exports, "WebWorkerExecutionService", { enumerable: true, get: function () { return webworker_1.WebWorkerExecutionService; } });
22
26
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/services/browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2EAA2E;AAC3E,6DAA2C;AAC3C,qDAAmC;AACnC,2CAAyB;AACzB,8CAA4B","sourcesContent":["// Subset of exports meant for browser environments, omits Node.js services\nexport * from './AbstractExecutionService';\nexport * from './ExecutionService';\nexport * from './iframe';\nexport * from './offscreen';\n"]}
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/services/browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,2EAA2E;AAC3E,6DAA2C;AAC3C,qDAAmC;AACnC,2DAAyC;AACzC,2CAAyB;AACzB,8CAA4B;AAC5B,yCAAwD;AAA/C,sHAAA,yBAAyB,OAAA","sourcesContent":["// Subset of exports meant for browser environments, omits Node.js services\nexport * from './AbstractExecutionService';\nexport * from './ExecutionService';\nexport * from './ProxyPostMessageStream';\nexport * from './iframe';\nexport * from './offscreen';\nexport { WebWorkerExecutionService } from './webworker';\n"]}
@@ -1,5 +1,7 @@
1
1
  export * from './AbstractExecutionService';
2
2
  export * from './ExecutionService';
3
+ export * from './ProxyPostMessageStream';
3
4
  export * from './iframe';
4
5
  export * from './node';
5
6
  export * from './offscreen';
7
+ export { WebWorkerExecutionService } from './webworker';
@@ -14,9 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.WebWorkerExecutionService = void 0;
17
18
  __exportStar(require("./AbstractExecutionService"), exports);
18
19
  __exportStar(require("./ExecutionService"), exports);
20
+ __exportStar(require("./ProxyPostMessageStream"), exports);
19
21
  __exportStar(require("./iframe"), exports);
20
22
  __exportStar(require("./node"), exports);
21
23
  __exportStar(require("./offscreen"), exports);
24
+ var webworker_1 = require("./webworker");
25
+ Object.defineProperty(exports, "WebWorkerExecutionService", { enumerable: true, get: function () { return webworker_1.WebWorkerExecutionService; } });
22
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,qDAAmC;AACnC,2CAAyB;AACzB,yCAAuB;AACvB,8CAA4B","sourcesContent":["export * from './AbstractExecutionService';\nexport * from './ExecutionService';\nexport * from './iframe';\nexport * from './node';\nexport * from './offscreen';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6DAA2C;AAC3C,qDAAmC;AACnC,2DAAyC;AACzC,2CAAyB;AACzB,yCAAuB;AACvB,8CAA4B;AAC5B,yCAAwD;AAA/C,sHAAA,yBAAyB,OAAA","sourcesContent":["export * from './AbstractExecutionService';\nexport * from './ExecutionService';\nexport * from './ProxyPostMessageStream';\nexport * from './iframe';\nexport * from './node';\nexport * from './offscreen';\nexport { WebWorkerExecutionService } from './webworker';\n"]}
@@ -1,5 +1,5 @@
1
1
  import { AbstractExecutionService, ExecutionServiceArgs, Job } from '../AbstractExecutionService';
2
- import { OffscreenPostMessageStream } from './OffscreenPostMessageStream';
2
+ import { ProxyPostMessageStream } from '../ProxyPostMessageStream';
3
3
  declare type OffscreenExecutionEnvironmentServiceArgs = {
4
4
  documentUrl: URL;
5
5
  frameUrl: URL;
@@ -37,7 +37,7 @@ export declare class OffscreenExecutionService extends AbstractExecutionService<
37
37
  */
38
38
  protected initEnvStream(jobId: string): Promise<{
39
39
  worker: string;
40
- stream: OffscreenPostMessageStream;
40
+ stream: ProxyPostMessageStream;
41
41
  }>;
42
42
  /**
43
43
  * Creates the offscreen document to be used as the execution environment.
@@ -16,7 +16,7 @@ exports.OffscreenExecutionService = void 0;
16
16
  const post_message_stream_1 = require("@metamask/post-message-stream");
17
17
  const nanoid_1 = require("nanoid");
18
18
  const AbstractExecutionService_1 = require("../AbstractExecutionService");
19
- const OffscreenPostMessageStream_1 = require("./OffscreenPostMessageStream");
19
+ const ProxyPostMessageStream_1 = require("../ProxyPostMessageStream");
20
20
  class OffscreenExecutionService extends AbstractExecutionService_1.AbstractExecutionService {
21
21
  /**
22
22
  * Create a new offscreen execution service.
@@ -71,9 +71,14 @@ class OffscreenExecutionService extends AbstractExecutionService_1.AbstractExecu
71
71
  async initEnvStream(jobId) {
72
72
  // Lazily create the offscreen document.
73
73
  await this.createDocument();
74
- const stream = new OffscreenPostMessageStream_1.OffscreenPostMessageStream({
74
+ const stream = new ProxyPostMessageStream_1.ProxyPostMessageStream({
75
75
  stream: __classPrivateFieldGet(this, _OffscreenExecutionService_runtimeStream, "f"),
76
- frameUrl: this.frameUrl.toString(),
76
+ extra: {
77
+ // TODO: Rather than injecting the frame URL here, we should come up
78
+ // with a better way to do this. The frame URL is needed to avoid hard
79
+ // coding it in the offscreen execution environment.
80
+ frameUrl: this.frameUrl.toString(),
81
+ },
77
82
  jobId,
78
83
  });
79
84
  return { worker: jobId, stream };
@@ -1 +1 @@
1
- {"version":3,"file":"OffscreenExecutionService.js","sourceRoot":"","sources":["../../../src/services/offscreen/OffscreenExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uEAAgF;AAChF,mCAAgC;AAEhC,0EAIqC;AACrC,6EAA0E;AAO1E,MAAa,yBAA0B,SAAQ,mDAAgC;IAO7E;;;;;;;;;;;;;OAaG;IACH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,iBAAiB,GACwB;QACzC,KAAK,CAAC;YACJ,SAAS;YACT,iBAAiB;SAClB,CAAC,CAAC;QAzBL,2DAAyD;QA2BvD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,uBAAA,IAAI,4CAAkB,IAAI,qDAA+B,CAAC;YACxD,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,OAAO;SAChB,CAAC,MAAA,CAAC;IACL,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,YAAY,CAAC,GAAgB;QAC3C,0EAA0E;QAC1E,8CAA8C;QAC9C,uBAAA,IAAI,gDAAe,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,GAAG,CAAC,EAAE;YACb,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,cAAc;gBACtB,EAAE,EAAE,IAAA,eAAM,GAAE;aACb;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,aAAa,CAAC,KAAa;QACzC,wCAAwC;QACxC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAE5B,MAAM,MAAM,GAAG,IAAI,uDAA0B,CAAC;YAC5C,MAAM,EAAE,uBAAA,IAAI,gDAAe;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;YAClC,KAAK;SACN,CAAC,CAAC;QAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,cAAc;QAC1B,wDAAwD;QACxD,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE;YACxC,OAAO;SACR;QAED,MAAM,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;YACpC,aAAa,EAAE,sCAAsC;YACrD,OAAO,EAAE,CAAC,kBAAkB,CAAC;YAC7B,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;SACjC,CAAC,CAAC;IACL,CAAC;CACF;AA9FD,8DA8FC","sourcesContent":["import { BrowserRuntimePostMessageStream } from '@metamask/post-message-stream';\nimport { nanoid } from 'nanoid';\n\nimport {\n AbstractExecutionService,\n ExecutionServiceArgs,\n Job,\n} from '../AbstractExecutionService';\nimport { OffscreenPostMessageStream } from './OffscreenPostMessageStream';\n\ntype OffscreenExecutionEnvironmentServiceArgs = {\n documentUrl: URL;\n frameUrl: URL;\n} & ExecutionServiceArgs;\n\nexport class OffscreenExecutionService extends AbstractExecutionService<string> {\n public readonly documentUrl: URL;\n\n public readonly frameUrl: URL;\n\n readonly #runtimeStream: BrowserRuntimePostMessageStream;\n\n /**\n * Create a new offscreen execution service.\n *\n * @param args - The constructor arguments.\n * @param args.documentUrl - The URL of the offscreen document to use as the\n * execution environment. This must be a URL relative to the location where\n * this is called. This cannot be a public (http(s)) URL.\n * @param args.frameUrl - The URL of the iframe to load inside the offscreen\n * document.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n */\n constructor({\n documentUrl,\n frameUrl,\n messenger,\n setupSnapProvider,\n }: OffscreenExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n });\n\n this.documentUrl = documentUrl;\n this.frameUrl = frameUrl;\n this.#runtimeStream = new BrowserRuntimePostMessageStream({\n name: 'parent',\n target: 'child',\n });\n }\n\n /**\n * Send a termination command to the offscreen document.\n *\n * @param job - The job to terminate.\n */\n protected async terminateJob(job: Job<string>) {\n // The `AbstractExecutionService` will have already closed the job stream,\n // so we write to the runtime stream directly.\n this.#runtimeStream.write({\n jobId: job.id,\n data: {\n jsonrpc: '2.0',\n method: 'terminateJob',\n id: nanoid(),\n },\n });\n }\n\n /**\n * Create a new stream for the specified job. This wraps the runtime stream\n * in a stream specific to the job.\n *\n * @param jobId - The job ID.\n */\n protected async initEnvStream(jobId: string) {\n // Lazily create the offscreen document.\n await this.createDocument();\n\n const stream = new OffscreenPostMessageStream({\n stream: this.#runtimeStream,\n frameUrl: this.frameUrl.toString(),\n jobId,\n });\n\n return { worker: jobId, stream };\n }\n\n /**\n * Creates the offscreen document to be used as the execution environment.\n *\n * If the document already exists, this does nothing.\n */\n private async createDocument() {\n // Extensions can only have a single offscreen document.\n if (await chrome.offscreen.hasDocument()) {\n return;\n }\n\n await chrome.offscreen.createDocument({\n justification: 'MetaMask Snaps Execution Environment',\n reasons: ['IFRAME_SCRIPTING'],\n url: this.documentUrl.toString(),\n });\n }\n}\n"]}
1
+ {"version":3,"file":"OffscreenExecutionService.js","sourceRoot":"","sources":["../../../src/services/offscreen/OffscreenExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uEAAgF;AAChF,mCAAgC;AAEhC,0EAIqC;AACrC,sEAAmE;AAOnE,MAAa,yBAA0B,SAAQ,mDAAgC;IAO7E;;;;;;;;;;;;;OAaG;IACH,YAAY,EACV,WAAW,EACX,QAAQ,EACR,SAAS,EACT,iBAAiB,GACwB;QACzC,KAAK,CAAC;YACJ,SAAS;YACT,iBAAiB;SAClB,CAAC,CAAC;QAzBL,2DAAyD;QA2BvD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,uBAAA,IAAI,4CAAkB,IAAI,qDAA+B,CAAC;YACxD,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,OAAO;SAChB,CAAC,MAAA,CAAC;IACL,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,YAAY,CAAC,GAAgB;QAC3C,0EAA0E;QAC1E,8CAA8C;QAC9C,uBAAA,IAAI,gDAAe,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,GAAG,CAAC,EAAE;YACb,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,cAAc;gBACtB,EAAE,EAAE,IAAA,eAAM,GAAE;aACb;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,aAAa,CAAC,KAAa;QACzC,wCAAwC;QACxC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAE5B,MAAM,MAAM,GAAG,IAAI,+CAAsB,CAAC;YACxC,MAAM,EAAE,uBAAA,IAAI,gDAAe;YAC3B,KAAK,EAAE;gBACL,oEAAoE;gBACpE,sEAAsE;gBACtE,oDAAoD;gBACpD,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;aACnC;YACD,KAAK;SACN,CAAC,CAAC;QAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,cAAc;QAC1B,wDAAwD;QACxD,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE;YACxC,OAAO;SACR;QAED,MAAM,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;YACpC,aAAa,EAAE,sCAAsC;YACrD,OAAO,EAAE,CAAC,kBAAkB,CAAC;YAC7B,GAAG,EAAE,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE;SACjC,CAAC,CAAC;IACL,CAAC;CACF;AAnGD,8DAmGC","sourcesContent":["import { BrowserRuntimePostMessageStream } from '@metamask/post-message-stream';\nimport { nanoid } from 'nanoid';\n\nimport {\n AbstractExecutionService,\n ExecutionServiceArgs,\n Job,\n} from '../AbstractExecutionService';\nimport { ProxyPostMessageStream } from '../ProxyPostMessageStream';\n\ntype OffscreenExecutionEnvironmentServiceArgs = {\n documentUrl: URL;\n frameUrl: URL;\n} & ExecutionServiceArgs;\n\nexport class OffscreenExecutionService extends AbstractExecutionService<string> {\n public readonly documentUrl: URL;\n\n public readonly frameUrl: URL;\n\n readonly #runtimeStream: BrowserRuntimePostMessageStream;\n\n /**\n * Create a new offscreen execution service.\n *\n * @param args - The constructor arguments.\n * @param args.documentUrl - The URL of the offscreen document to use as the\n * execution environment. This must be a URL relative to the location where\n * this is called. This cannot be a public (http(s)) URL.\n * @param args.frameUrl - The URL of the iframe to load inside the offscreen\n * document.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n */\n constructor({\n documentUrl,\n frameUrl,\n messenger,\n setupSnapProvider,\n }: OffscreenExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n });\n\n this.documentUrl = documentUrl;\n this.frameUrl = frameUrl;\n this.#runtimeStream = new BrowserRuntimePostMessageStream({\n name: 'parent',\n target: 'child',\n });\n }\n\n /**\n * Send a termination command to the offscreen document.\n *\n * @param job - The job to terminate.\n */\n protected async terminateJob(job: Job<string>) {\n // The `AbstractExecutionService` will have already closed the job stream,\n // so we write to the runtime stream directly.\n this.#runtimeStream.write({\n jobId: job.id,\n data: {\n jsonrpc: '2.0',\n method: 'terminateJob',\n id: nanoid(),\n },\n });\n }\n\n /**\n * Create a new stream for the specified job. This wraps the runtime stream\n * in a stream specific to the job.\n *\n * @param jobId - The job ID.\n */\n protected async initEnvStream(jobId: string) {\n // Lazily create the offscreen document.\n await this.createDocument();\n\n const stream = new ProxyPostMessageStream({\n stream: this.#runtimeStream,\n extra: {\n // TODO: Rather than injecting the frame URL here, we should come up\n // with a better way to do this. The frame URL is needed to avoid hard\n // coding it in the offscreen execution environment.\n frameUrl: this.frameUrl.toString(),\n },\n jobId,\n });\n\n return { worker: jobId, stream };\n }\n\n /**\n * Creates the offscreen document to be used as the execution environment.\n *\n * If the document already exists, this does nothing.\n */\n private async createDocument() {\n // Extensions can only have a single offscreen document.\n if (await chrome.offscreen.hasDocument()) {\n return;\n }\n\n await chrome.offscreen.createDocument({\n justification: 'MetaMask Snaps Execution Environment',\n reasons: ['IFRAME_SCRIPTING'],\n url: this.documentUrl.toString(),\n });\n }\n}\n"]}
@@ -1,2 +1 @@
1
1
  export * from './OffscreenExecutionService';
2
- export * from './OffscreenPostMessageStream';
@@ -15,5 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./OffscreenExecutionService"), exports);
18
- __exportStar(require("./OffscreenPostMessageStream"), exports);
19
18
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/offscreen/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,+DAA6C","sourcesContent":["export * from './OffscreenExecutionService';\nexport * from './OffscreenPostMessageStream';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/offscreen/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C","sourcesContent":["export * from './OffscreenExecutionService';\n"]}
@@ -0,0 +1,44 @@
1
+ import { AbstractExecutionService, ExecutionServiceArgs, Job } from '../AbstractExecutionService';
2
+ import { ProxyPostMessageStream } from '../ProxyPostMessageStream';
3
+ declare type WebWorkerExecutionEnvironmentServiceArgs = {
4
+ documentUrl: URL;
5
+ } & ExecutionServiceArgs;
6
+ export declare const WORKER_POOL_ID = "snaps-worker-pool";
7
+ export declare class WebWorkerExecutionService extends AbstractExecutionService<string> {
8
+ #private;
9
+ /**
10
+ * Create a new webworker execution service.
11
+ *
12
+ * @param args - The constructor arguments.
13
+ * @param args.documentUrl - The URL of the worker pool document to use as the
14
+ * execution environment.
15
+ * @param args.messenger - The messenger to use for communication with the
16
+ * `SnapController`.
17
+ * @param args.setupSnapProvider - The function to use to set up the snap
18
+ * provider.
19
+ */
20
+ constructor({ documentUrl, messenger, setupSnapProvider, }: WebWorkerExecutionEnvironmentServiceArgs);
21
+ /**
22
+ * Send a termination command to the worker pool document.
23
+ *
24
+ * @param job - The job to terminate.
25
+ */
26
+ protected terminateJob(job: Job<string>): Promise<void>;
27
+ /**
28
+ * Create a new stream for the specified job. This wraps the runtime stream
29
+ * in a stream specific to the job.
30
+ *
31
+ * @param jobId - The job ID.
32
+ */
33
+ protected initEnvStream(jobId: string): Promise<{
34
+ worker: string;
35
+ stream: ProxyPostMessageStream;
36
+ }>;
37
+ /**
38
+ * Creates the worker pool document to be used as the execution environment.
39
+ *
40
+ * If the document already exists, this does nothing.
41
+ */
42
+ private createDocument;
43
+ }
44
+ export {};
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _WebWorkerExecutionService_documentUrl, _WebWorkerExecutionService_runtimeStream;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.WebWorkerExecutionService = exports.WORKER_POOL_ID = void 0;
16
+ const post_message_stream_1 = require("@metamask/post-message-stream");
17
+ const snaps_utils_1 = require("@metamask/snaps-utils");
18
+ const utils_1 = require("@metamask/utils");
19
+ const nanoid_1 = require("nanoid");
20
+ const AbstractExecutionService_1 = require("../AbstractExecutionService");
21
+ const ProxyPostMessageStream_1 = require("../ProxyPostMessageStream");
22
+ exports.WORKER_POOL_ID = 'snaps-worker-pool';
23
+ class WebWorkerExecutionService extends AbstractExecutionService_1.AbstractExecutionService {
24
+ /**
25
+ * Create a new webworker execution service.
26
+ *
27
+ * @param args - The constructor arguments.
28
+ * @param args.documentUrl - The URL of the worker pool document to use as the
29
+ * execution environment.
30
+ * @param args.messenger - The messenger to use for communication with the
31
+ * `SnapController`.
32
+ * @param args.setupSnapProvider - The function to use to set up the snap
33
+ * provider.
34
+ */
35
+ constructor({ documentUrl, messenger, setupSnapProvider, }) {
36
+ super({
37
+ messenger,
38
+ setupSnapProvider,
39
+ });
40
+ _WebWorkerExecutionService_documentUrl.set(this, void 0);
41
+ _WebWorkerExecutionService_runtimeStream.set(this, void 0);
42
+ __classPrivateFieldSet(this, _WebWorkerExecutionService_documentUrl, documentUrl, "f");
43
+ }
44
+ /**
45
+ * Send a termination command to the worker pool document.
46
+ *
47
+ * @param job - The job to terminate.
48
+ */
49
+ async terminateJob(job) {
50
+ // The `AbstractExecutionService` will have already closed the job stream,
51
+ // so we write to the runtime stream directly.
52
+ (0, utils_1.assert)(__classPrivateFieldGet(this, _WebWorkerExecutionService_runtimeStream, "f"), 'Runtime stream not initialized.');
53
+ __classPrivateFieldGet(this, _WebWorkerExecutionService_runtimeStream, "f").write({
54
+ jobId: job.id,
55
+ data: {
56
+ jsonrpc: '2.0',
57
+ method: 'terminateJob',
58
+ id: (0, nanoid_1.nanoid)(),
59
+ },
60
+ });
61
+ }
62
+ /**
63
+ * Create a new stream for the specified job. This wraps the runtime stream
64
+ * in a stream specific to the job.
65
+ *
66
+ * @param jobId - The job ID.
67
+ */
68
+ async initEnvStream(jobId) {
69
+ // Lazily create the worker pool document.
70
+ await this.createDocument();
71
+ // `createDocument` should have initialized the runtime stream.
72
+ (0, utils_1.assert)(__classPrivateFieldGet(this, _WebWorkerExecutionService_runtimeStream, "f"), 'Runtime stream not initialized.');
73
+ const stream = new ProxyPostMessageStream_1.ProxyPostMessageStream({
74
+ stream: __classPrivateFieldGet(this, _WebWorkerExecutionService_runtimeStream, "f"),
75
+ jobId,
76
+ });
77
+ return { worker: jobId, stream };
78
+ }
79
+ /**
80
+ * Creates the worker pool document to be used as the execution environment.
81
+ *
82
+ * If the document already exists, this does nothing.
83
+ */
84
+ async createDocument() {
85
+ // We only want to create a single pool.
86
+ if (document.getElementById(exports.WORKER_POOL_ID)) {
87
+ return;
88
+ }
89
+ const window = await (0, snaps_utils_1.createWindow)(__classPrivateFieldGet(this, _WebWorkerExecutionService_documentUrl, "f").href, exports.WORKER_POOL_ID, false);
90
+ __classPrivateFieldSet(this, _WebWorkerExecutionService_runtimeStream, new post_message_stream_1.WindowPostMessageStream({
91
+ name: 'parent',
92
+ target: 'child',
93
+ targetWindow: window,
94
+ targetOrigin: '*',
95
+ }), "f");
96
+ }
97
+ }
98
+ exports.WebWorkerExecutionService = WebWorkerExecutionService;
99
+ _WebWorkerExecutionService_documentUrl = new WeakMap(), _WebWorkerExecutionService_runtimeStream = new WeakMap();
100
+ //# sourceMappingURL=WebWorkerExecutionService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WebWorkerExecutionService.js","sourceRoot":"","sources":["../../../src/services/webworker/WebWorkerExecutionService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,uEAGuC;AACvC,uDAAqD;AACrD,2CAAyC;AACzC,mCAAgC;AAEhC,0EAIqC;AACrC,sEAAmE;AAMtD,QAAA,cAAc,GAAG,mBAAmB,CAAC;AAElD,MAAa,yBAA0B,SAAQ,mDAAgC;IAK7E;;;;;;;;;;OAUG;IACH,YAAY,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,GACwB;QACzC,KAAK,CAAC;YACJ,SAAS;YACT,iBAAiB;SAClB,CAAC,CAAC;QAvBL,yDAAkB;QAElB,2DAAuC;QAuBrC,uBAAA,IAAI,0CAAgB,WAAW,MAAA,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACO,KAAK,CAAC,YAAY,CAAC,GAAgB;QAC3C,0EAA0E;QAC1E,8CAA8C;QAC9C,IAAA,cAAM,EAAC,uBAAA,IAAI,gDAAe,EAAE,iCAAiC,CAAC,CAAC;QAC/D,uBAAA,IAAI,gDAAe,CAAC,KAAK,CAAC;YACxB,KAAK,EAAE,GAAG,CAAC,EAAE;YACb,IAAI,EAAE;gBACJ,OAAO,EAAE,KAAK;gBACd,MAAM,EAAE,cAAc;gBACtB,EAAE,EAAE,IAAA,eAAM,GAAE;aACb;SACF,CAAC,CAAC;IACL,CAAC;IAED;;;;;OAKG;IACO,KAAK,CAAC,aAAa,CAAC,KAAa;QACzC,0CAA0C;QAC1C,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAE5B,+DAA+D;QAC/D,IAAA,cAAM,EAAC,uBAAA,IAAI,gDAAe,EAAE,iCAAiC,CAAC,CAAC;QAE/D,MAAM,MAAM,GAAG,IAAI,+CAAsB,CAAC;YACxC,MAAM,EAAE,uBAAA,IAAI,gDAAe;YAC3B,KAAK;SACN,CAAC,CAAC;QAEH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,cAAc;QAC1B,wCAAwC;QACxC,IAAI,QAAQ,CAAC,cAAc,CAAC,sBAAc,CAAC,EAAE;YAC3C,OAAO;SACR;QAED,MAAM,MAAM,GAAG,MAAM,IAAA,0BAAY,EAC/B,uBAAA,IAAI,8CAAa,CAAC,IAAI,EACtB,sBAAc,EACd,KAAK,CACN,CAAC;QAEF,uBAAA,IAAI,4CAAkB,IAAI,6CAAuB,CAAC;YAChD,IAAI,EAAE,QAAQ;YACd,MAAM,EAAE,OAAO;YACf,YAAY,EAAE,MAAM;YACpB,YAAY,EAAE,GAAG;SAClB,CAAC,MAAA,CAAC;IACL,CAAC;CACF;AA7FD,8DA6FC","sourcesContent":["import {\n BasePostMessageStream,\n WindowPostMessageStream,\n} from '@metamask/post-message-stream';\nimport { createWindow } from '@metamask/snaps-utils';\nimport { assert } from '@metamask/utils';\nimport { nanoid } from 'nanoid';\n\nimport {\n AbstractExecutionService,\n ExecutionServiceArgs,\n Job,\n} from '../AbstractExecutionService';\nimport { ProxyPostMessageStream } from '../ProxyPostMessageStream';\n\ntype WebWorkerExecutionEnvironmentServiceArgs = {\n documentUrl: URL;\n} & ExecutionServiceArgs;\n\nexport const WORKER_POOL_ID = 'snaps-worker-pool';\n\nexport class WebWorkerExecutionService extends AbstractExecutionService<string> {\n #documentUrl: URL;\n\n #runtimeStream?: BasePostMessageStream;\n\n /**\n * Create a new webworker execution service.\n *\n * @param args - The constructor arguments.\n * @param args.documentUrl - The URL of the worker pool document to use as the\n * execution environment.\n * @param args.messenger - The messenger to use for communication with the\n * `SnapController`.\n * @param args.setupSnapProvider - The function to use to set up the snap\n * provider.\n */\n constructor({\n documentUrl,\n messenger,\n setupSnapProvider,\n }: WebWorkerExecutionEnvironmentServiceArgs) {\n super({\n messenger,\n setupSnapProvider,\n });\n\n this.#documentUrl = documentUrl;\n }\n\n /**\n * Send a termination command to the worker pool document.\n *\n * @param job - The job to terminate.\n */\n protected async terminateJob(job: Job<string>) {\n // The `AbstractExecutionService` will have already closed the job stream,\n // so we write to the runtime stream directly.\n assert(this.#runtimeStream, 'Runtime stream not initialized.');\n this.#runtimeStream.write({\n jobId: job.id,\n data: {\n jsonrpc: '2.0',\n method: 'terminateJob',\n id: nanoid(),\n },\n });\n }\n\n /**\n * Create a new stream for the specified job. This wraps the runtime stream\n * in a stream specific to the job.\n *\n * @param jobId - The job ID.\n */\n protected async initEnvStream(jobId: string) {\n // Lazily create the worker pool document.\n await this.createDocument();\n\n // `createDocument` should have initialized the runtime stream.\n assert(this.#runtimeStream, 'Runtime stream not initialized.');\n\n const stream = new ProxyPostMessageStream({\n stream: this.#runtimeStream,\n jobId,\n });\n\n return { worker: jobId, stream };\n }\n\n /**\n * Creates the worker pool document to be used as the execution environment.\n *\n * If the document already exists, this does nothing.\n */\n private async createDocument() {\n // We only want to create a single pool.\n if (document.getElementById(WORKER_POOL_ID)) {\n return;\n }\n\n const window = await createWindow(\n this.#documentUrl.href,\n WORKER_POOL_ID,\n false,\n );\n\n this.#runtimeStream = new WindowPostMessageStream({\n name: 'parent',\n target: 'child',\n targetWindow: window,\n targetOrigin: '*',\n });\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export * from './WebWorkerExecutionService';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./WebWorkerExecutionService"), exports);
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/webworker/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C","sourcesContent":["export * from './WebWorkerExecutionService';\n"]}
@@ -1,9 +1,8 @@
1
1
  import { AddApprovalRequest, UpdateRequestState } from '@metamask/approval-controller';
2
2
  import { BaseControllerV2 as BaseController, RestrictedControllerMessenger } from '@metamask/base-controller';
3
- import { GetEndowments, GetPermissions, GetSubjects, GrantPermissions, HasPermission, HasPermissions, RevokeAllPermissions, RevokePermissionForAllSubjects, RevokePermissions, UpdateCaveat } from '@metamask/permission-controller';
3
+ import { GetEndowments, GetPermissions, GetSubjects, GrantPermissions, HasPermission, HasPermissions, RevokeAllPermissions, RevokePermissionForAllSubjects, RevokePermissions, UpdateCaveat, GetSubjectMetadata } from '@metamask/permission-controller';
4
4
  import { BlockReason } from '@metamask/snaps-registry';
5
5
  import { InstallSnapsResult, PersistedSnap, RequestedSnapPermissions, Snap, SnapId, SnapRpcHook, SnapRpcHookArgs, SnapStatusEvents, StatusContext, StatusEvents, StatusStates, TruncatedSnap, ValidatedSnapId } from '@metamask/snaps-utils';
6
- import { GetSubjectMetadata } from '@metamask/subject-metadata-controller';
7
6
  import { Json } from '@metamask/utils';
8
7
  import { StateMachine } from '@xstate/fsm';
9
8
  import type { Patch } from 'immer';
@@ -175,7 +174,11 @@ export declare type GetRegistryMetadata = {
175
174
  type: `${typeof controllerName}:getRegistryMetadata`;
176
175
  handler: SnapController['getRegistryMetadata'];
177
176
  };
178
- export declare type SnapControllerActions = ClearSnapState | GetSnap | GetSnapState | HandleSnapRequest | HasSnap | UpdateBlockedSnaps | UpdateSnapState | EnableSnap | DisableSnap | RemoveSnap | GetPermittedSnaps | InstallSnaps | RemoveSnapError | GetAllSnaps | IncrementActiveReferences | DecrementActiveReferences | GetRegistryMetadata;
177
+ export declare type DisconnectOrigin = {
178
+ type: `${typeof controllerName}:disconnectOrigin`;
179
+ handler: SnapController['removeSnapFromSubject'];
180
+ };
181
+ export declare type SnapControllerActions = ClearSnapState | GetSnap | GetSnapState | HandleSnapRequest | HasSnap | UpdateBlockedSnaps | UpdateSnapState | EnableSnap | DisableSnap | RemoveSnap | GetPermittedSnaps | InstallSnaps | RemoveSnapError | GetAllSnaps | IncrementActiveReferences | DecrementActiveReferences | GetRegistryMetadata | DisconnectOrigin;
179
182
  export declare type SnapStateChange = {
180
183
  type: `${typeof controllerName}:stateChange`;
181
184
  payload: [SnapControllerState, Patch[]];
@@ -466,6 +469,13 @@ export declare class SnapController extends BaseController<string, SnapControlle
466
469
  * @param snapIds - The ids of the Snaps.
467
470
  */
468
471
  removeSnaps(snapIds: string[]): Promise<void>;
472
+ /**
473
+ * Removes a snap's permission (caveat) from the specified subject.
474
+ *
475
+ * @param origin - The origin from which to remove the snap.
476
+ * @param snapId - The id of the snap to remove.
477
+ */
478
+ removeSnapFromSubject(origin: string, snapId: SnapId): void;
469
479
  /**
470
480
  * Safely revokes all permissions granted to a Snap.
471
481
  *
@@ -14,9 +14,9 @@ var _SnapController_instances, _SnapController_closeAllConnections, _SnapControl
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.SnapController = exports.SNAP_APPROVAL_RESULT = exports.SNAP_APPROVAL_UPDATE = exports.SNAP_APPROVAL_INSTALL = exports.controllerName = void 0;
16
16
  const base_controller_1 = require("@metamask/base-controller");
17
+ const permission_controller_1 = require("@metamask/permission-controller");
17
18
  const rpc_methods_1 = require("@metamask/rpc-methods");
18
19
  const snaps_utils_1 = require("@metamask/snaps-utils");
19
- const subject_metadata_controller_1 = require("@metamask/subject-metadata-controller");
20
20
  const utils_1 = require("@metamask/utils");
21
21
  const fsm_1 = require("@xstate/fsm");
22
22
  const eth_rpc_errors_1 = require("eth-rpc-errors");
@@ -469,6 +469,34 @@ class SnapController extends base_controller_1.BaseControllerV2 {
469
469
  this.messagingSystem.publish(`SnapController:snapRemoved`, truncated);
470
470
  }));
471
471
  }
472
+ /**
473
+ * Removes a snap's permission (caveat) from the specified subject.
474
+ *
475
+ * @param origin - The origin from which to remove the snap.
476
+ * @param snapId - The id of the snap to remove.
477
+ */
478
+ removeSnapFromSubject(origin, snapId) {
479
+ const subjectPermissions = this.messagingSystem.call('PermissionController:getPermissions', origin);
480
+ const snapIdsCaveat = subjectPermissions?.[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds);
481
+ if (!snapIdsCaveat) {
482
+ return;
483
+ }
484
+ const caveatHasSnap = Boolean(snapIdsCaveat.value?.[snapId]);
485
+ if (caveatHasSnap) {
486
+ const newCaveatValue = {
487
+ ...snapIdsCaveat.value,
488
+ };
489
+ delete newCaveatValue[snapId];
490
+ if (Object.keys(newCaveatValue).length > 0) {
491
+ this.messagingSystem.call('PermissionController:updateCaveat', origin, rpc_methods_1.WALLET_SNAP_PERMISSION_KEY, snaps_utils_1.SnapCaveatType.SnapIds, newCaveatValue);
492
+ }
493
+ else {
494
+ this.messagingSystem.call('PermissionController:revokePermissions', {
495
+ [origin]: [rpc_methods_1.WALLET_SNAP_PERMISSION_KEY],
496
+ });
497
+ }
498
+ }
499
+ }
472
500
  /**
473
501
  * Safely revokes all permissions granted to a Snap.
474
502
  *
@@ -645,7 +673,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
645
673
  return truncated;
646
674
  }
647
675
  catch (error) {
648
- (0, snaps_utils_1.logError)(`Error when adding snap.`, error);
676
+ (0, snaps_utils_1.logError)(`Error when adding ${snapId}.`, error);
649
677
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
650
678
  loading: false,
651
679
  type: exports.SNAP_APPROVAL_INSTALL,
@@ -762,7 +790,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
762
790
  return truncatedSnap;
763
791
  }
764
792
  catch (error) {
765
- (0, snaps_utils_1.logError)(`Error when updating snap,`, error);
793
+ (0, snaps_utils_1.logError)(`Error when updating ${snapId},`, error);
766
794
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_updateApproval).call(this, pendingApproval.id, {
767
795
  loading: false,
768
796
  error: error instanceof Error ? error.message : error.toString(),
@@ -846,7 +874,7 @@ class SnapController extends base_controller_1.BaseControllerV2 {
846
874
  }
847
875
  if (permissionName === endowments_1.SnapEndowments.Rpc) {
848
876
  const subject = this.messagingSystem.call('SubjectMetadataController:getSubjectMetadata', origin);
849
- const isSnap = subject?.subjectType === subject_metadata_controller_1.SubjectType.Snap;
877
+ const isSnap = subject?.subjectType === permission_controller_1.SubjectType.Snap;
850
878
  const permissions = this.messagingSystem.call('PermissionController:getPermissions', snapId);
851
879
  const rpcPermission = permissions?.[endowments_1.SnapEndowments.Rpc];
852
880
  (0, utils_1.assert)(rpcPermission);
@@ -934,6 +962,7 @@ _SnapController_closeAllConnections = new WeakMap(), _SnapController_environment
934
962
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:incrementActiveReferences`, (...args) => this.incrementActiveReferences(...args));
935
963
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:decrementActiveReferences`, (...args) => this.decrementActiveReferences(...args));
936
964
  this.messagingSystem.registerActionHandler(`${exports.controllerName}:getRegistryMetadata`, async (...args) => this.getRegistryMetadata(...args));
965
+ this.messagingSystem.registerActionHandler(`${exports.controllerName}:disconnectOrigin`, (...args) => this.removeSnapFromSubject(...args));
937
966
  }, _SnapController_pollForLastRequestStatus = function _SnapController_pollForLastRequestStatus() {
938
967
  __classPrivateFieldSet(this, _SnapController_timeoutForLastRequestStatus, setTimeout(() => {
939
968
  __classPrivateFieldGet(this, _SnapController_instances, "m", _SnapController_stopSnapsLastRequestPastMax).call(this).catch((error) => {
@@ -1014,24 +1043,7 @@ async function _SnapController_terminateSnap(snapId) {
1014
1043
  }, _SnapController_removeSnapFromSubjects = function _SnapController_removeSnapFromSubjects(snapId) {
1015
1044
  const subjects = this.messagingSystem.call('PermissionController:getSubjectNames');
1016
1045
  for (const subject of subjects) {
1017
- const subjectPermissions = this.messagingSystem.call('PermissionController:getPermissions', subject);
1018
- const snapIdsCaveat = (subjectPermissions?.[rpc_methods_1.WALLET_SNAP_PERMISSION_KEY]?.caveats?.find((caveat) => caveat.type === snaps_utils_1.SnapCaveatType.SnapIds) ??
1019
- {});
1020
- const caveatHasSnap = Boolean(snapIdsCaveat.value?.[snapId]);
1021
- if (caveatHasSnap) {
1022
- const newCaveatValue = {
1023
- ...snapIdsCaveat.value,
1024
- };
1025
- delete newCaveatValue[snapId];
1026
- if (Object.keys(newCaveatValue).length > 0) {
1027
- this.messagingSystem.call('PermissionController:updateCaveat', subject, rpc_methods_1.WALLET_SNAP_PERMISSION_KEY, snaps_utils_1.SnapCaveatType.SnapIds, newCaveatValue);
1028
- }
1029
- else {
1030
- this.messagingSystem.call('PermissionController:revokePermissions', {
1031
- [subject]: [rpc_methods_1.WALLET_SNAP_PERMISSION_KEY],
1032
- });
1033
- }
1034
- }
1046
+ this.removeSnapFromSubject(subject, snapId);
1035
1047
  }
1036
1048
  }, _SnapController_createApproval = function _SnapController_createApproval({ origin, snapId, type, }) {
1037
1049
  const id = (0, nanoid_1.nanoid)();
@@ -1156,7 +1168,7 @@ async function _SnapController_getEndowments(snapId) {
1156
1168
  // This is a bug in TypeScript: https://github.com/microsoft/TypeScript/issues/48313
1157
1169
  // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
1158
1170
  snaps_utils_1.DEFAULT_ENDOWMENTS.length + allEndowments.length) {
1159
- (0, snaps_utils_1.logError)('Duplicate endowments found. Default endowments should not be requested.', allEndowments);
1171
+ (0, snaps_utils_1.logError)(`Duplicate endowments found for ${snapId}. Default endowments should not be requested.`, allEndowments);
1160
1172
  }
1161
1173
  return dedupedEndowments;
1162
1174
  }, _SnapController_set = function _SnapController_set(args) {