@metamask/snaps-controllers 12.2.0 → 12.3.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/cronjob/CronjobController.cjs +13 -4
  3. package/dist/cronjob/CronjobController.cjs.map +1 -1
  4. package/dist/cronjob/CronjobController.d.cts.map +1 -1
  5. package/dist/cronjob/CronjobController.d.mts.map +1 -1
  6. package/dist/cronjob/CronjobController.mjs +15 -6
  7. package/dist/cronjob/CronjobController.mjs.map +1 -1
  8. package/dist/interface/SnapInterfaceController.cjs +15 -1
  9. package/dist/interface/SnapInterfaceController.cjs.map +1 -1
  10. package/dist/interface/SnapInterfaceController.d.cts +10 -2
  11. package/dist/interface/SnapInterfaceController.d.cts.map +1 -1
  12. package/dist/interface/SnapInterfaceController.d.mts +10 -2
  13. package/dist/interface/SnapInterfaceController.d.mts.map +1 -1
  14. package/dist/interface/SnapInterfaceController.mjs +17 -3
  15. package/dist/interface/SnapInterfaceController.mjs.map +1 -1
  16. package/dist/interface/utils.cjs +104 -4
  17. package/dist/interface/utils.cjs.map +1 -1
  18. package/dist/interface/utils.d.cts +71 -2
  19. package/dist/interface/utils.d.cts.map +1 -1
  20. package/dist/interface/utils.d.mts +71 -2
  21. package/dist/interface/utils.d.mts.map +1 -1
  22. package/dist/interface/utils.mjs +101 -5
  23. package/dist/interface/utils.mjs.map +1 -1
  24. package/dist/services/AbstractExecutionService.cjs +127 -202
  25. package/dist/services/AbstractExecutionService.cjs.map +1 -1
  26. package/dist/services/AbstractExecutionService.d.cts +8 -53
  27. package/dist/services/AbstractExecutionService.d.cts.map +1 -1
  28. package/dist/services/AbstractExecutionService.d.mts +8 -53
  29. package/dist/services/AbstractExecutionService.d.mts.map +1 -1
  30. package/dist/services/AbstractExecutionService.mjs +127 -202
  31. package/dist/services/AbstractExecutionService.mjs.map +1 -1
  32. package/dist/services/iframe/IframeExecutionService.cjs +2 -2
  33. package/dist/services/iframe/IframeExecutionService.cjs.map +1 -1
  34. package/dist/services/iframe/IframeExecutionService.d.cts +1 -1
  35. package/dist/services/iframe/IframeExecutionService.d.cts.map +1 -1
  36. package/dist/services/iframe/IframeExecutionService.d.mts +1 -1
  37. package/dist/services/iframe/IframeExecutionService.d.mts.map +1 -1
  38. package/dist/services/iframe/IframeExecutionService.mjs +2 -2
  39. package/dist/services/iframe/IframeExecutionService.mjs.map +1 -1
  40. package/dist/services/offscreen/OffscreenExecutionService.cjs +5 -5
  41. package/dist/services/offscreen/OffscreenExecutionService.cjs.map +1 -1
  42. package/dist/services/offscreen/OffscreenExecutionService.d.cts +4 -4
  43. package/dist/services/offscreen/OffscreenExecutionService.d.cts.map +1 -1
  44. package/dist/services/offscreen/OffscreenExecutionService.d.mts +4 -4
  45. package/dist/services/offscreen/OffscreenExecutionService.d.mts.map +1 -1
  46. package/dist/services/offscreen/OffscreenExecutionService.mjs +5 -5
  47. package/dist/services/offscreen/OffscreenExecutionService.mjs.map +1 -1
  48. package/dist/services/proxy/ProxyExecutionService.cjs +6 -6
  49. package/dist/services/proxy/ProxyExecutionService.cjs.map +1 -1
  50. package/dist/services/proxy/ProxyExecutionService.d.cts +4 -4
  51. package/dist/services/proxy/ProxyExecutionService.d.cts.map +1 -1
  52. package/dist/services/proxy/ProxyExecutionService.d.mts +4 -4
  53. package/dist/services/proxy/ProxyExecutionService.d.mts.map +1 -1
  54. package/dist/services/proxy/ProxyExecutionService.mjs +6 -6
  55. package/dist/services/proxy/ProxyExecutionService.mjs.map +1 -1
  56. package/dist/services/webview/WebViewExecutionService.cjs +6 -6
  57. package/dist/services/webview/WebViewExecutionService.cjs.map +1 -1
  58. package/dist/services/webview/WebViewExecutionService.d.cts +5 -5
  59. package/dist/services/webview/WebViewExecutionService.d.cts.map +1 -1
  60. package/dist/services/webview/WebViewExecutionService.d.mts +5 -5
  61. package/dist/services/webview/WebViewExecutionService.d.mts.map +1 -1
  62. package/dist/services/webview/WebViewExecutionService.mjs +6 -6
  63. package/dist/services/webview/WebViewExecutionService.mjs.map +1 -1
  64. package/dist/snaps/SnapController.cjs +43 -72
  65. package/dist/snaps/SnapController.cjs.map +1 -1
  66. package/dist/snaps/SnapController.d.cts +5 -9
  67. package/dist/snaps/SnapController.d.cts.map +1 -1
  68. package/dist/snaps/SnapController.d.mts +5 -9
  69. package/dist/snaps/SnapController.d.mts.map +1 -1
  70. package/dist/snaps/SnapController.mjs +43 -72
  71. package/dist/snaps/SnapController.mjs.map +1 -1
  72. package/dist/snaps/registry/json.cjs +4 -2
  73. package/dist/snaps/registry/json.cjs.map +1 -1
  74. package/dist/snaps/registry/json.d.cts.map +1 -1
  75. package/dist/snaps/registry/json.d.mts.map +1 -1
  76. package/dist/snaps/registry/json.mjs +4 -2
  77. package/dist/snaps/registry/json.mjs.map +1 -1
  78. package/package.json +4 -4
  79. package/dist/snaps/RequestQueue.cjs +0 -44
  80. package/dist/snaps/RequestQueue.cjs.map +0 -1
  81. package/dist/snaps/RequestQueue.d.cts +0 -25
  82. package/dist/snaps/RequestQueue.d.cts.map +0 -1
  83. package/dist/snaps/RequestQueue.d.mts +0 -25
  84. package/dist/snaps/RequestQueue.d.mts.map +0 -1
  85. package/dist/snaps/RequestQueue.mjs +0 -40
  86. package/dist/snaps/RequestQueue.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [12.3.0]
11
+
12
+ ### Added
13
+
14
+ - Add support for `AccountSelector` component ([#3088](https://github.com/MetaMask/snaps/pull/3088))
15
+
16
+ ### Changed
17
+
18
+ - Fetch registry files in parallel ([#3416](https://github.com/MetaMask/snaps/pull/3416))
19
+
20
+ ### Fixed
21
+
22
+ - Prevent scheduling background events less than 1 second in the future ([#3414](https://github.com/MetaMask/snaps/pull/3414))
23
+
10
24
  ## [12.2.0]
11
25
 
12
26
  ### Added
@@ -766,7 +780,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
766
780
  - The version of the package no longer needs to match the version of all other
767
781
  MetaMask Snaps packages.
768
782
 
769
- [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.2.0...HEAD
783
+ [Unreleased]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.3.0...HEAD
784
+ [12.3.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.2.0...@metamask/snaps-controllers@12.3.0
770
785
  [12.2.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.1.0...@metamask/snaps-controllers@12.2.0
771
786
  [12.1.0]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.0.1...@metamask/snaps-controllers@12.1.0
772
787
  [12.0.1]: https://github.com/MetaMask/snaps/compare/@metamask/snaps-controllers@12.0.0...@metamask/snaps-controllers@12.0.1
@@ -101,9 +101,6 @@ class CronjobController extends base_controller_1.BaseController {
101
101
  scheduledAt,
102
102
  };
103
103
  __classPrivateFieldGet(this, _CronjobController_instances, "m", _CronjobController_setUpBackgroundEvent).call(this, event);
104
- this.update((state) => {
105
- state.events[event.id] = (0, immer_1.castDraft)(event);
106
- });
107
104
  return event.id;
108
105
  }
109
106
  /**
@@ -131,7 +128,13 @@ class CronjobController extends base_controller_1.BaseController {
131
128
  * @returns An array of background events.
132
129
  */
133
130
  getBackgroundEvents(snapId) {
134
- return Object.values(this.state.events).filter((snapEvent) => snapEvent.snapId === snapId);
131
+ return Object.values(this.state.events)
132
+ .filter((snapEvent) => snapEvent.snapId === snapId)
133
+ .map((event) => ({
134
+ ...event,
135
+ // Truncate dates to remove milliseconds.
136
+ date: (0, snaps_utils_1.toCensoredISO8601String)(event.date),
137
+ }));
135
138
  }
136
139
  /**
137
140
  * Unregister all jobs and background events related to the given snapId.
@@ -323,6 +326,12 @@ async function _CronjobController_executeCronjob(job) {
323
326
  if (ms <= 0) {
324
327
  throw new Error('Cannot schedule an event in the past.');
325
328
  }
329
+ // The event may already be in state when we get here.
330
+ if (!(0, utils_1.hasProperty)(this.state.events, event.id)) {
331
+ this.update((state) => {
332
+ state.events[event.id] = (0, immer_1.castDraft)(event);
333
+ });
334
+ }
326
335
  const timer = new Timer_1.Timer(ms);
327
336
  timer.start(() => {
328
337
  this.messagingSystem
@@ -1 +1 @@
1
- {"version":3,"file":"CronjobController.cjs","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport {\n getCronjobCaveatJobs,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { BackgroundEvent, SnapId } from '@metamask/snaps-sdk';\nimport type {\n TruncatedSnap,\n CronjobSpecification,\n} from '@metamask/snaps-utils';\nimport {\n HandlerType,\n parseCronExpression,\n logError,\n logWarning,\n} from '@metamask/snaps-utils';\nimport { assert, Duration, inMilliseconds } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { DateTime } from 'luxon';\nimport { nanoid } from 'nanoid';\n\nimport type {\n GetAllSnaps,\n HandleSnapRequest,\n SnapDisabled,\n SnapEnabled,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '..';\nimport { getRunnableSnaps } from '..';\nimport { Timer } from '../snaps/Timer';\n\nexport type CronjobControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n CronjobControllerState\n>;\nexport type CronjobControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n CronjobControllerState\n>;\n\nexport type ScheduleBackgroundEvent = {\n type: `${typeof controllerName}:scheduleBackgroundEvent`;\n handler: CronjobController['scheduleBackgroundEvent'];\n};\n\nexport type CancelBackgroundEvent = {\n type: `${typeof controllerName}:cancelBackgroundEvent`;\n handler: CronjobController['cancelBackgroundEvent'];\n};\n\nexport type GetBackgroundEvents = {\n type: `${typeof controllerName}:getBackgroundEvents`;\n handler: CronjobController['getBackgroundEvents'];\n};\n\nexport type CronjobControllerActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | CronjobControllerGetStateAction\n | ScheduleBackgroundEvent\n | CancelBackgroundEvent\n | GetBackgroundEvents;\n\nexport type CronjobControllerEvents =\n | SnapInstalled\n | SnapUninstalled\n | SnapUpdated\n | SnapEnabled\n | SnapDisabled\n | CronjobControllerStateChangeEvent;\n\nexport type CronjobControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n CronjobControllerActions,\n CronjobControllerEvents,\n CronjobControllerActions['type'],\n CronjobControllerEvents['type']\n>;\n\nexport const DAILY_TIMEOUT = inMilliseconds(24, Duration.Hour);\n\nexport type CronjobControllerArgs = {\n messenger: CronjobControllerMessenger;\n /**\n * Persisted state that will be used for rehydration.\n */\n state?: CronjobControllerState;\n};\n\nexport type Cronjob = {\n timer?: Timer;\n id: string;\n snapId: SnapId;\n} & CronjobSpecification;\n\nexport type StoredJobInformation = {\n lastRun: number;\n};\n\nexport type CronjobControllerState = {\n jobs: Record<string, StoredJobInformation>;\n events: Record<string, BackgroundEvent>;\n};\n\nconst controllerName = 'CronjobController';\n\n/**\n * Use this controller to register and schedule periodically executed jobs\n * using RPC method hooks.\n */\nexport class CronjobController extends BaseController<\n typeof controllerName,\n CronjobControllerState,\n CronjobControllerMessenger\n> {\n #dailyTimer!: Timer;\n\n readonly #timers: Map<string, Timer>;\n\n // Mapping from jobId to snapId\n readonly #snapIds: Map<string, SnapId>;\n\n constructor({ messenger, state }: CronjobControllerArgs) {\n super({\n messenger,\n metadata: {\n jobs: { persist: true, anonymous: false },\n events: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n jobs: {},\n events: {},\n ...state,\n },\n });\n this.#timers = new Map();\n this.#snapIds = new Map();\n\n this._handleSnapRegisterEvent = this._handleSnapRegisterEvent.bind(this);\n this._handleSnapUnregisterEvent =\n this._handleSnapUnregisterEvent.bind(this);\n this._handleEventSnapUpdated = this._handleEventSnapUpdated.bind(this);\n this._handleSnapDisabledEvent = this._handleSnapDisabledEvent.bind(this);\n this._handleSnapEnabledEvent = this._handleSnapEnabledEvent.bind(this);\n // Subscribe to Snap events\n /* eslint-disable @typescript-eslint/unbound-method */\n\n this.messagingSystem.subscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:scheduleBackgroundEvent`,\n (...args) => this.scheduleBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:cancelBackgroundEvent`,\n (...args) => this.cancelBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getBackgroundEvents`,\n (...args) => this.getBackgroundEvents(...args),\n );\n\n this.dailyCheckIn();\n\n this.#rescheduleBackgroundEvents(Object.values(this.state.events));\n }\n\n /**\n * Retrieve all cronjob specifications for all runnable snaps.\n *\n * @returns Array of Cronjob specifications.\n */\n #getAllJobs(): Cronjob[] {\n const snaps = this.messagingSystem.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(snaps);\n\n const jobs = filteredSnaps.map((snap) => this.#getSnapJobs(snap.id));\n return jobs.flat().filter((job) => job !== undefined) as Cronjob[];\n }\n\n /**\n * Retrieve all Cronjob specifications for a Snap.\n *\n * @param snapId - ID of a Snap.\n * @returns Array of Cronjob specifications.\n */\n #getSnapJobs(snapId: SnapId): Cronjob[] | undefined {\n const permissions = this.messagingSystem.call(\n 'PermissionController:getPermissions',\n snapId,\n );\n\n const permission = permissions?.[SnapEndowments.Cronjob];\n const definitions = getCronjobCaveatJobs(permission);\n\n return definitions?.map((definition, idx) => {\n return { ...definition, id: `${snapId}-${idx}`, snapId };\n });\n }\n\n /**\n * Register cron jobs for a given snap by getting specification from a permission caveats.\n * Once registered, each job will be scheduled.\n *\n * @param snapId - ID of a snap.\n */\n register(snapId: SnapId) {\n const jobs = this.#getSnapJobs(snapId);\n jobs?.forEach((job) => this.#schedule(job));\n }\n\n /**\n * Schedule a new job.\n * This will interpret the cron expression and tell the timer to execute the job\n * at the next suitable point in time.\n * Job last run state will be initialized afterwards.\n *\n * Note: Schedule will be skipped if the job's execution time is too far in the future and\n * will be revisited on a daily check.\n *\n * @param job - Cronjob specification.\n */\n #schedule(job: Cronjob) {\n if (this.#timers.has(job.id)) {\n return;\n }\n\n const parsed = parseCronExpression(job.expression);\n const next = parsed.next();\n const now = new Date();\n const ms = next.getTime() - now.getTime();\n\n // Don't schedule this job yet as it is too far in the future\n if (ms > DAILY_TIMEOUT) {\n return;\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.#executeCronjob(job).catch((error) => {\n // TODO: Decide how to handle errors.\n logError(error);\n });\n\n this.#timers.delete(job.id);\n this.#schedule(job);\n });\n\n if (!this.state.jobs[job.id]?.lastRun) {\n this.#updateJobLastRunState(job.id, 0); // 0 for init, never ran actually\n }\n\n this.#timers.set(job.id, timer);\n this.#snapIds.set(job.id, job.snapId);\n }\n\n /**\n * Execute job.\n *\n * @param job - Cronjob specification.\n */\n async #executeCronjob(job: Cronjob) {\n this.#updateJobLastRunState(job.id, Date.now());\n await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: job.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: job.request,\n });\n }\n\n /**\n * Schedule a background event.\n *\n * @param backgroundEventWithoutId - Background event.\n * @returns An id representing the background event.\n */\n scheduleBackgroundEvent(\n backgroundEventWithoutId: Omit<BackgroundEvent, 'id' | 'scheduledAt'>,\n ) {\n // Remove millisecond precision and convert to UTC.\n const scheduledAt = DateTime.fromJSDate(new Date())\n .toUTC()\n .startOf('second')\n .toISO({\n suppressMilliseconds: true,\n });\n\n assert(scheduledAt);\n\n const event = {\n ...backgroundEventWithoutId,\n id: nanoid(),\n scheduledAt,\n };\n\n this.#setUpBackgroundEvent(event);\n this.update((state) => {\n state.events[event.id] = castDraft(event);\n });\n\n return event.id;\n }\n\n /**\n * Cancel a background event.\n *\n * @param origin - The origin making the cancel call.\n * @param id - The id of the background event to cancel.\n * @throws If the event does not exist.\n */\n cancelBackgroundEvent(origin: string, id: string) {\n assert(\n this.state.events[id],\n `A background event with the id of \"${id}\" does not exist.`,\n );\n\n assert(\n this.state.events[id].snapId === origin,\n 'Only the origin that scheduled this event can cancel it.',\n );\n\n const timer = this.#timers.get(id);\n timer?.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n this.update((state) => {\n delete state.events[id];\n });\n }\n\n /**\n * A helper function to handle setup of the background event.\n *\n * @param event - A background event.\n */\n #setUpBackgroundEvent(event: BackgroundEvent) {\n const date = new Date(event.date);\n const now = new Date();\n const ms = date.getTime() - now.getTime();\n\n if (ms <= 0) {\n throw new Error('Cannot schedule an event in the past.');\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.messagingSystem\n .call('SnapController:handleRequest', {\n snapId: event.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: event.request,\n })\n .catch((error) => {\n logError(error);\n });\n\n this.#timers.delete(event.id);\n this.#snapIds.delete(event.id);\n this.update((state) => {\n delete state.events[event.id];\n });\n });\n\n this.#timers.set(event.id, timer);\n this.#snapIds.set(event.id, event.snapId);\n }\n\n /**\n * Get a list of a Snap's background events.\n *\n * @param snapId - The id of the Snap to fetch background events for.\n * @returns An array of background events.\n */\n getBackgroundEvents(snapId: SnapId): BackgroundEvent[] {\n return Object.values(this.state.events).filter(\n (snapEvent) => snapEvent.snapId === snapId,\n );\n }\n\n /**\n * Unregister all jobs and background events related to the given snapId.\n *\n * @param snapId - ID of a snap.\n * @param skipEvents - Whether the unregistration process should skip scheduled background events.\n */\n unregister(snapId: SnapId, skipEvents = false) {\n const jobs = [...this.#snapIds.entries()].filter(\n ([_, jobSnapId]) => jobSnapId === snapId,\n );\n\n if (jobs.length) {\n const eventIds: string[] = [];\n jobs.forEach(([id]) => {\n const timer = this.#timers.get(id);\n if (timer) {\n timer.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n if (!skipEvents && this.state.events[id]) {\n eventIds.push(id);\n }\n }\n });\n\n if (eventIds.length > 0) {\n this.update((state) => {\n eventIds.forEach((id) => {\n delete state.events[id];\n });\n });\n }\n }\n }\n\n /**\n * Update time of a last run for the Cronjob specified by ID.\n *\n * @param jobId - ID of a cron job.\n * @param lastRun - Unix timestamp when the job was last ran.\n */\n #updateJobLastRunState(jobId: string, lastRun: number) {\n this.update((state) => {\n state.jobs[jobId] = {\n lastRun,\n };\n });\n }\n\n /**\n * Runs every 24 hours to check if new jobs need to be scheduled.\n *\n * This is necessary for longer running jobs that execute with more than 24 hours between them.\n */\n dailyCheckIn() {\n const jobs = this.#getAllJobs();\n\n for (const job of jobs) {\n const parsed = parseCronExpression(job.expression);\n const lastRun = this.state.jobs[job.id]?.lastRun;\n // If a job was supposed to run while we were shut down but wasn't we run it now\n if (\n lastRun !== undefined &&\n parsed.hasPrev() &&\n parsed.prev().getTime() > lastRun\n ) {\n this.#executeCronjob(job).catch((error) => {\n logError(error);\n });\n }\n\n // Try scheduling, will fail if an existing scheduled job is found\n this.#schedule(job);\n }\n\n this.#dailyTimer = new Timer(DAILY_TIMEOUT);\n this.#dailyTimer.start(() => {\n this.dailyCheckIn();\n });\n }\n\n /**\n * Reschedule background events.\n *\n * @param backgroundEvents - A list of background events to reschdule.\n */\n #rescheduleBackgroundEvents(backgroundEvents: BackgroundEvent[]) {\n for (const snapEvent of backgroundEvents) {\n const { date } = snapEvent;\n const now = new Date();\n const then = new Date(date);\n if (then.getTime() < now.getTime()) {\n // Remove expired events from state\n this.update((state) => {\n delete state.events[snapEvent.id];\n });\n\n logWarning(\n `Background event with id \"${snapEvent.id}\" not scheduled as its date has expired.`,\n );\n } else {\n this.#setUpBackgroundEvent(snapEvent);\n }\n }\n }\n\n /**\n * Run controller teardown process and unsubscribe from Snap events.\n */\n destroy() {\n super.destroy();\n\n /* eslint-disable @typescript-eslint/unbound-method */\n this.messagingSystem.unsubscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.#snapIds.forEach((snapId) => this.unregister(snapId));\n }\n\n /**\n * Handle events that should cause cronjobs to be registered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapRegisterEvent(snap: TruncatedSnap) {\n this.register(snap.id);\n }\n\n /**\n * Handle events that could cause cronjobs to be registered\n * and for background events to be rescheduled.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapEnabledEvent(snap: TruncatedSnap) {\n const events = this.getBackgroundEvents(snap.id);\n this.#rescheduleBackgroundEvents(events);\n this.register(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapUnregisterEvent(snap: TruncatedSnap) {\n this.unregister(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapDisabledEvent(snap: TruncatedSnap) {\n this.unregister(snap.id, true);\n }\n\n /**\n * Handle cron jobs on 'snapUpdated' event.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleEventSnapUpdated(snap: TruncatedSnap) {\n this.unregister(snap.id);\n this.register(snap.id);\n }\n}\n"]}
1
+ {"version":3,"file":"CronjobController.cjs","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport {\n getCronjobCaveatJobs,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { BackgroundEvent, SnapId } from '@metamask/snaps-sdk';\nimport type {\n TruncatedSnap,\n CronjobSpecification,\n} from '@metamask/snaps-utils';\nimport {\n HandlerType,\n parseCronExpression,\n logError,\n logWarning,\n toCensoredISO8601String,\n} from '@metamask/snaps-utils';\nimport { assert, Duration, hasProperty, inMilliseconds } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { DateTime } from 'luxon';\nimport { nanoid } from 'nanoid';\n\nimport type {\n GetAllSnaps,\n HandleSnapRequest,\n SnapDisabled,\n SnapEnabled,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '..';\nimport { getRunnableSnaps } from '..';\nimport { Timer } from '../snaps/Timer';\n\nexport type CronjobControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n CronjobControllerState\n>;\nexport type CronjobControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n CronjobControllerState\n>;\n\nexport type ScheduleBackgroundEvent = {\n type: `${typeof controllerName}:scheduleBackgroundEvent`;\n handler: CronjobController['scheduleBackgroundEvent'];\n};\n\nexport type CancelBackgroundEvent = {\n type: `${typeof controllerName}:cancelBackgroundEvent`;\n handler: CronjobController['cancelBackgroundEvent'];\n};\n\nexport type GetBackgroundEvents = {\n type: `${typeof controllerName}:getBackgroundEvents`;\n handler: CronjobController['getBackgroundEvents'];\n};\n\nexport type CronjobControllerActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | CronjobControllerGetStateAction\n | ScheduleBackgroundEvent\n | CancelBackgroundEvent\n | GetBackgroundEvents;\n\nexport type CronjobControllerEvents =\n | SnapInstalled\n | SnapUninstalled\n | SnapUpdated\n | SnapEnabled\n | SnapDisabled\n | CronjobControllerStateChangeEvent;\n\nexport type CronjobControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n CronjobControllerActions,\n CronjobControllerEvents,\n CronjobControllerActions['type'],\n CronjobControllerEvents['type']\n>;\n\nexport const DAILY_TIMEOUT = inMilliseconds(24, Duration.Hour);\n\nexport type CronjobControllerArgs = {\n messenger: CronjobControllerMessenger;\n /**\n * Persisted state that will be used for rehydration.\n */\n state?: CronjobControllerState;\n};\n\nexport type Cronjob = {\n timer?: Timer;\n id: string;\n snapId: SnapId;\n} & CronjobSpecification;\n\nexport type StoredJobInformation = {\n lastRun: number;\n};\n\nexport type CronjobControllerState = {\n jobs: Record<string, StoredJobInformation>;\n events: Record<string, BackgroundEvent>;\n};\n\nconst controllerName = 'CronjobController';\n\n/**\n * Use this controller to register and schedule periodically executed jobs\n * using RPC method hooks.\n */\nexport class CronjobController extends BaseController<\n typeof controllerName,\n CronjobControllerState,\n CronjobControllerMessenger\n> {\n #dailyTimer!: Timer;\n\n readonly #timers: Map<string, Timer>;\n\n // Mapping from jobId to snapId\n readonly #snapIds: Map<string, SnapId>;\n\n constructor({ messenger, state }: CronjobControllerArgs) {\n super({\n messenger,\n metadata: {\n jobs: { persist: true, anonymous: false },\n events: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n jobs: {},\n events: {},\n ...state,\n },\n });\n this.#timers = new Map();\n this.#snapIds = new Map();\n\n this._handleSnapRegisterEvent = this._handleSnapRegisterEvent.bind(this);\n this._handleSnapUnregisterEvent =\n this._handleSnapUnregisterEvent.bind(this);\n this._handleEventSnapUpdated = this._handleEventSnapUpdated.bind(this);\n this._handleSnapDisabledEvent = this._handleSnapDisabledEvent.bind(this);\n this._handleSnapEnabledEvent = this._handleSnapEnabledEvent.bind(this);\n // Subscribe to Snap events\n /* eslint-disable @typescript-eslint/unbound-method */\n\n this.messagingSystem.subscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:scheduleBackgroundEvent`,\n (...args) => this.scheduleBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:cancelBackgroundEvent`,\n (...args) => this.cancelBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getBackgroundEvents`,\n (...args) => this.getBackgroundEvents(...args),\n );\n\n this.dailyCheckIn();\n\n this.#rescheduleBackgroundEvents(Object.values(this.state.events));\n }\n\n /**\n * Retrieve all cronjob specifications for all runnable snaps.\n *\n * @returns Array of Cronjob specifications.\n */\n #getAllJobs(): Cronjob[] {\n const snaps = this.messagingSystem.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(snaps);\n\n const jobs = filteredSnaps.map((snap) => this.#getSnapJobs(snap.id));\n return jobs.flat().filter((job) => job !== undefined) as Cronjob[];\n }\n\n /**\n * Retrieve all Cronjob specifications for a Snap.\n *\n * @param snapId - ID of a Snap.\n * @returns Array of Cronjob specifications.\n */\n #getSnapJobs(snapId: SnapId): Cronjob[] | undefined {\n const permissions = this.messagingSystem.call(\n 'PermissionController:getPermissions',\n snapId,\n );\n\n const permission = permissions?.[SnapEndowments.Cronjob];\n const definitions = getCronjobCaveatJobs(permission);\n\n return definitions?.map((definition, idx) => {\n return { ...definition, id: `${snapId}-${idx}`, snapId };\n });\n }\n\n /**\n * Register cron jobs for a given snap by getting specification from a permission caveats.\n * Once registered, each job will be scheduled.\n *\n * @param snapId - ID of a snap.\n */\n register(snapId: SnapId) {\n const jobs = this.#getSnapJobs(snapId);\n jobs?.forEach((job) => this.#schedule(job));\n }\n\n /**\n * Schedule a new job.\n * This will interpret the cron expression and tell the timer to execute the job\n * at the next suitable point in time.\n * Job last run state will be initialized afterwards.\n *\n * Note: Schedule will be skipped if the job's execution time is too far in the future and\n * will be revisited on a daily check.\n *\n * @param job - Cronjob specification.\n */\n #schedule(job: Cronjob) {\n if (this.#timers.has(job.id)) {\n return;\n }\n\n const parsed = parseCronExpression(job.expression);\n const next = parsed.next();\n const now = new Date();\n const ms = next.getTime() - now.getTime();\n\n // Don't schedule this job yet as it is too far in the future\n if (ms > DAILY_TIMEOUT) {\n return;\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.#executeCronjob(job).catch((error) => {\n // TODO: Decide how to handle errors.\n logError(error);\n });\n\n this.#timers.delete(job.id);\n this.#schedule(job);\n });\n\n if (!this.state.jobs[job.id]?.lastRun) {\n this.#updateJobLastRunState(job.id, 0); // 0 for init, never ran actually\n }\n\n this.#timers.set(job.id, timer);\n this.#snapIds.set(job.id, job.snapId);\n }\n\n /**\n * Execute job.\n *\n * @param job - Cronjob specification.\n */\n async #executeCronjob(job: Cronjob) {\n this.#updateJobLastRunState(job.id, Date.now());\n await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: job.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: job.request,\n });\n }\n\n /**\n * Schedule a background event.\n *\n * @param backgroundEventWithoutId - Background event.\n * @returns An id representing the background event.\n */\n scheduleBackgroundEvent(\n backgroundEventWithoutId: Omit<BackgroundEvent, 'id' | 'scheduledAt'>,\n ) {\n // Remove millisecond precision and convert to UTC.\n const scheduledAt = DateTime.fromJSDate(new Date())\n .toUTC()\n .startOf('second')\n .toISO({\n suppressMilliseconds: true,\n });\n\n assert(scheduledAt);\n\n const event = {\n ...backgroundEventWithoutId,\n id: nanoid(),\n scheduledAt,\n };\n\n this.#setUpBackgroundEvent(event);\n\n return event.id;\n }\n\n /**\n * Cancel a background event.\n *\n * @param origin - The origin making the cancel call.\n * @param id - The id of the background event to cancel.\n * @throws If the event does not exist.\n */\n cancelBackgroundEvent(origin: string, id: string) {\n assert(\n this.state.events[id],\n `A background event with the id of \"${id}\" does not exist.`,\n );\n\n assert(\n this.state.events[id].snapId === origin,\n 'Only the origin that scheduled this event can cancel it.',\n );\n\n const timer = this.#timers.get(id);\n timer?.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n this.update((state) => {\n delete state.events[id];\n });\n }\n\n /**\n * A helper function to handle setup of the background event.\n *\n * @param event - A background event.\n */\n #setUpBackgroundEvent(event: BackgroundEvent) {\n const date = new Date(event.date);\n const now = new Date();\n const ms = date.getTime() - now.getTime();\n\n if (ms <= 0) {\n throw new Error('Cannot schedule an event in the past.');\n }\n\n // The event may already be in state when we get here.\n if (!hasProperty(this.state.events, event.id)) {\n this.update((state) => {\n state.events[event.id] = castDraft(event);\n });\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.messagingSystem\n .call('SnapController:handleRequest', {\n snapId: event.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: event.request,\n })\n .catch((error) => {\n logError(error);\n });\n\n this.#timers.delete(event.id);\n this.#snapIds.delete(event.id);\n this.update((state) => {\n delete state.events[event.id];\n });\n });\n\n this.#timers.set(event.id, timer);\n this.#snapIds.set(event.id, event.snapId);\n }\n\n /**\n * Get a list of a Snap's background events.\n *\n * @param snapId - The id of the Snap to fetch background events for.\n * @returns An array of background events.\n */\n getBackgroundEvents(snapId: SnapId): BackgroundEvent[] {\n return Object.values(this.state.events)\n .filter((snapEvent) => snapEvent.snapId === snapId)\n .map((event) => ({\n ...event,\n // Truncate dates to remove milliseconds.\n date: toCensoredISO8601String(event.date),\n }));\n }\n\n /**\n * Unregister all jobs and background events related to the given snapId.\n *\n * @param snapId - ID of a snap.\n * @param skipEvents - Whether the unregistration process should skip scheduled background events.\n */\n unregister(snapId: SnapId, skipEvents = false) {\n const jobs = [...this.#snapIds.entries()].filter(\n ([_, jobSnapId]) => jobSnapId === snapId,\n );\n\n if (jobs.length) {\n const eventIds: string[] = [];\n jobs.forEach(([id]) => {\n const timer = this.#timers.get(id);\n if (timer) {\n timer.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n if (!skipEvents && this.state.events[id]) {\n eventIds.push(id);\n }\n }\n });\n\n if (eventIds.length > 0) {\n this.update((state) => {\n eventIds.forEach((id) => {\n delete state.events[id];\n });\n });\n }\n }\n }\n\n /**\n * Update time of a last run for the Cronjob specified by ID.\n *\n * @param jobId - ID of a cron job.\n * @param lastRun - Unix timestamp when the job was last ran.\n */\n #updateJobLastRunState(jobId: string, lastRun: number) {\n this.update((state) => {\n state.jobs[jobId] = {\n lastRun,\n };\n });\n }\n\n /**\n * Runs every 24 hours to check if new jobs need to be scheduled.\n *\n * This is necessary for longer running jobs that execute with more than 24 hours between them.\n */\n dailyCheckIn() {\n const jobs = this.#getAllJobs();\n\n for (const job of jobs) {\n const parsed = parseCronExpression(job.expression);\n const lastRun = this.state.jobs[job.id]?.lastRun;\n // If a job was supposed to run while we were shut down but wasn't we run it now\n if (\n lastRun !== undefined &&\n parsed.hasPrev() &&\n parsed.prev().getTime() > lastRun\n ) {\n this.#executeCronjob(job).catch((error) => {\n logError(error);\n });\n }\n\n // Try scheduling, will fail if an existing scheduled job is found\n this.#schedule(job);\n }\n\n this.#dailyTimer = new Timer(DAILY_TIMEOUT);\n this.#dailyTimer.start(() => {\n this.dailyCheckIn();\n });\n }\n\n /**\n * Reschedule background events.\n *\n * @param backgroundEvents - A list of background events to reschdule.\n */\n #rescheduleBackgroundEvents(backgroundEvents: BackgroundEvent[]) {\n for (const snapEvent of backgroundEvents) {\n const { date } = snapEvent;\n const now = new Date();\n const then = new Date(date);\n if (then.getTime() < now.getTime()) {\n // Remove expired events from state\n this.update((state) => {\n delete state.events[snapEvent.id];\n });\n\n logWarning(\n `Background event with id \"${snapEvent.id}\" not scheduled as its date has expired.`,\n );\n } else {\n this.#setUpBackgroundEvent(snapEvent);\n }\n }\n }\n\n /**\n * Run controller teardown process and unsubscribe from Snap events.\n */\n destroy() {\n super.destroy();\n\n /* eslint-disable @typescript-eslint/unbound-method */\n this.messagingSystem.unsubscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.#snapIds.forEach((snapId) => this.unregister(snapId));\n }\n\n /**\n * Handle events that should cause cronjobs to be registered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapRegisterEvent(snap: TruncatedSnap) {\n this.register(snap.id);\n }\n\n /**\n * Handle events that could cause cronjobs to be registered\n * and for background events to be rescheduled.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapEnabledEvent(snap: TruncatedSnap) {\n const events = this.getBackgroundEvents(snap.id);\n this.#rescheduleBackgroundEvents(events);\n this.register(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapUnregisterEvent(snap: TruncatedSnap) {\n this.unregister(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapDisabledEvent(snap: TruncatedSnap) {\n this.unregister(snap.id, true);\n }\n\n /**\n * Handle cron jobs on 'snapUpdated' event.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleEventSnapUpdated(snap: TruncatedSnap) {\n this.unregister(snap.id);\n this.register(snap.id);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"CronjobController.d.cts","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CronjobController.d.cts","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CronjobController.d.mts","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CronjobController.d.mts","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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"}
@@ -12,8 +12,8 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
12
12
  var _CronjobController_instances, _CronjobController_dailyTimer, _CronjobController_timers, _CronjobController_snapIds, _CronjobController_getAllJobs, _CronjobController_getSnapJobs, _CronjobController_schedule, _CronjobController_executeCronjob, _CronjobController_setUpBackgroundEvent, _CronjobController_updateJobLastRunState, _CronjobController_rescheduleBackgroundEvents;
13
13
  import { BaseController } from "@metamask/base-controller";
14
14
  import { getCronjobCaveatJobs, SnapEndowments } from "@metamask/snaps-rpc-methods";
15
- import { HandlerType, parseCronExpression, logError, logWarning } from "@metamask/snaps-utils";
16
- import { assert, Duration, inMilliseconds } from "@metamask/utils";
15
+ import { HandlerType, parseCronExpression, logError, logWarning, toCensoredISO8601String } from "@metamask/snaps-utils";
16
+ import { assert, Duration, hasProperty, inMilliseconds } from "@metamask/utils";
17
17
  import { castDraft } from "immer";
18
18
  import { DateTime } from "luxon";
19
19
  import { nanoid } from "nanoid";
@@ -98,9 +98,6 @@ export class CronjobController extends BaseController {
98
98
  scheduledAt,
99
99
  };
100
100
  __classPrivateFieldGet(this, _CronjobController_instances, "m", _CronjobController_setUpBackgroundEvent).call(this, event);
101
- this.update((state) => {
102
- state.events[event.id] = castDraft(event);
103
- });
104
101
  return event.id;
105
102
  }
106
103
  /**
@@ -128,7 +125,13 @@ export class CronjobController extends BaseController {
128
125
  * @returns An array of background events.
129
126
  */
130
127
  getBackgroundEvents(snapId) {
131
- return Object.values(this.state.events).filter((snapEvent) => snapEvent.snapId === snapId);
128
+ return Object.values(this.state.events)
129
+ .filter((snapEvent) => snapEvent.snapId === snapId)
130
+ .map((event) => ({
131
+ ...event,
132
+ // Truncate dates to remove milliseconds.
133
+ date: toCensoredISO8601String(event.date),
134
+ }));
132
135
  }
133
136
  /**
134
137
  * Unregister all jobs and background events related to the given snapId.
@@ -319,6 +322,12 @@ async function _CronjobController_executeCronjob(job) {
319
322
  if (ms <= 0) {
320
323
  throw new Error('Cannot schedule an event in the past.');
321
324
  }
325
+ // The event may already be in state when we get here.
326
+ if (!hasProperty(this.state.events, event.id)) {
327
+ this.update((state) => {
328
+ state.events[event.id] = castDraft(event);
329
+ });
330
+ }
322
331
  const timer = new Timer(ms);
323
332
  timer.start(() => {
324
333
  this.messagingSystem
@@ -1 +1 @@
1
- {"version":3,"file":"CronjobController.mjs","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport {\n getCronjobCaveatJobs,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { BackgroundEvent, SnapId } from '@metamask/snaps-sdk';\nimport type {\n TruncatedSnap,\n CronjobSpecification,\n} from '@metamask/snaps-utils';\nimport {\n HandlerType,\n parseCronExpression,\n logError,\n logWarning,\n} from '@metamask/snaps-utils';\nimport { assert, Duration, inMilliseconds } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { DateTime } from 'luxon';\nimport { nanoid } from 'nanoid';\n\nimport type {\n GetAllSnaps,\n HandleSnapRequest,\n SnapDisabled,\n SnapEnabled,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '..';\nimport { getRunnableSnaps } from '..';\nimport { Timer } from '../snaps/Timer';\n\nexport type CronjobControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n CronjobControllerState\n>;\nexport type CronjobControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n CronjobControllerState\n>;\n\nexport type ScheduleBackgroundEvent = {\n type: `${typeof controllerName}:scheduleBackgroundEvent`;\n handler: CronjobController['scheduleBackgroundEvent'];\n};\n\nexport type CancelBackgroundEvent = {\n type: `${typeof controllerName}:cancelBackgroundEvent`;\n handler: CronjobController['cancelBackgroundEvent'];\n};\n\nexport type GetBackgroundEvents = {\n type: `${typeof controllerName}:getBackgroundEvents`;\n handler: CronjobController['getBackgroundEvents'];\n};\n\nexport type CronjobControllerActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | CronjobControllerGetStateAction\n | ScheduleBackgroundEvent\n | CancelBackgroundEvent\n | GetBackgroundEvents;\n\nexport type CronjobControllerEvents =\n | SnapInstalled\n | SnapUninstalled\n | SnapUpdated\n | SnapEnabled\n | SnapDisabled\n | CronjobControllerStateChangeEvent;\n\nexport type CronjobControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n CronjobControllerActions,\n CronjobControllerEvents,\n CronjobControllerActions['type'],\n CronjobControllerEvents['type']\n>;\n\nexport const DAILY_TIMEOUT = inMilliseconds(24, Duration.Hour);\n\nexport type CronjobControllerArgs = {\n messenger: CronjobControllerMessenger;\n /**\n * Persisted state that will be used for rehydration.\n */\n state?: CronjobControllerState;\n};\n\nexport type Cronjob = {\n timer?: Timer;\n id: string;\n snapId: SnapId;\n} & CronjobSpecification;\n\nexport type StoredJobInformation = {\n lastRun: number;\n};\n\nexport type CronjobControllerState = {\n jobs: Record<string, StoredJobInformation>;\n events: Record<string, BackgroundEvent>;\n};\n\nconst controllerName = 'CronjobController';\n\n/**\n * Use this controller to register and schedule periodically executed jobs\n * using RPC method hooks.\n */\nexport class CronjobController extends BaseController<\n typeof controllerName,\n CronjobControllerState,\n CronjobControllerMessenger\n> {\n #dailyTimer!: Timer;\n\n readonly #timers: Map<string, Timer>;\n\n // Mapping from jobId to snapId\n readonly #snapIds: Map<string, SnapId>;\n\n constructor({ messenger, state }: CronjobControllerArgs) {\n super({\n messenger,\n metadata: {\n jobs: { persist: true, anonymous: false },\n events: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n jobs: {},\n events: {},\n ...state,\n },\n });\n this.#timers = new Map();\n this.#snapIds = new Map();\n\n this._handleSnapRegisterEvent = this._handleSnapRegisterEvent.bind(this);\n this._handleSnapUnregisterEvent =\n this._handleSnapUnregisterEvent.bind(this);\n this._handleEventSnapUpdated = this._handleEventSnapUpdated.bind(this);\n this._handleSnapDisabledEvent = this._handleSnapDisabledEvent.bind(this);\n this._handleSnapEnabledEvent = this._handleSnapEnabledEvent.bind(this);\n // Subscribe to Snap events\n /* eslint-disable @typescript-eslint/unbound-method */\n\n this.messagingSystem.subscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:scheduleBackgroundEvent`,\n (...args) => this.scheduleBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:cancelBackgroundEvent`,\n (...args) => this.cancelBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getBackgroundEvents`,\n (...args) => this.getBackgroundEvents(...args),\n );\n\n this.dailyCheckIn();\n\n this.#rescheduleBackgroundEvents(Object.values(this.state.events));\n }\n\n /**\n * Retrieve all cronjob specifications for all runnable snaps.\n *\n * @returns Array of Cronjob specifications.\n */\n #getAllJobs(): Cronjob[] {\n const snaps = this.messagingSystem.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(snaps);\n\n const jobs = filteredSnaps.map((snap) => this.#getSnapJobs(snap.id));\n return jobs.flat().filter((job) => job !== undefined) as Cronjob[];\n }\n\n /**\n * Retrieve all Cronjob specifications for a Snap.\n *\n * @param snapId - ID of a Snap.\n * @returns Array of Cronjob specifications.\n */\n #getSnapJobs(snapId: SnapId): Cronjob[] | undefined {\n const permissions = this.messagingSystem.call(\n 'PermissionController:getPermissions',\n snapId,\n );\n\n const permission = permissions?.[SnapEndowments.Cronjob];\n const definitions = getCronjobCaveatJobs(permission);\n\n return definitions?.map((definition, idx) => {\n return { ...definition, id: `${snapId}-${idx}`, snapId };\n });\n }\n\n /**\n * Register cron jobs for a given snap by getting specification from a permission caveats.\n * Once registered, each job will be scheduled.\n *\n * @param snapId - ID of a snap.\n */\n register(snapId: SnapId) {\n const jobs = this.#getSnapJobs(snapId);\n jobs?.forEach((job) => this.#schedule(job));\n }\n\n /**\n * Schedule a new job.\n * This will interpret the cron expression and tell the timer to execute the job\n * at the next suitable point in time.\n * Job last run state will be initialized afterwards.\n *\n * Note: Schedule will be skipped if the job's execution time is too far in the future and\n * will be revisited on a daily check.\n *\n * @param job - Cronjob specification.\n */\n #schedule(job: Cronjob) {\n if (this.#timers.has(job.id)) {\n return;\n }\n\n const parsed = parseCronExpression(job.expression);\n const next = parsed.next();\n const now = new Date();\n const ms = next.getTime() - now.getTime();\n\n // Don't schedule this job yet as it is too far in the future\n if (ms > DAILY_TIMEOUT) {\n return;\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.#executeCronjob(job).catch((error) => {\n // TODO: Decide how to handle errors.\n logError(error);\n });\n\n this.#timers.delete(job.id);\n this.#schedule(job);\n });\n\n if (!this.state.jobs[job.id]?.lastRun) {\n this.#updateJobLastRunState(job.id, 0); // 0 for init, never ran actually\n }\n\n this.#timers.set(job.id, timer);\n this.#snapIds.set(job.id, job.snapId);\n }\n\n /**\n * Execute job.\n *\n * @param job - Cronjob specification.\n */\n async #executeCronjob(job: Cronjob) {\n this.#updateJobLastRunState(job.id, Date.now());\n await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: job.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: job.request,\n });\n }\n\n /**\n * Schedule a background event.\n *\n * @param backgroundEventWithoutId - Background event.\n * @returns An id representing the background event.\n */\n scheduleBackgroundEvent(\n backgroundEventWithoutId: Omit<BackgroundEvent, 'id' | 'scheduledAt'>,\n ) {\n // Remove millisecond precision and convert to UTC.\n const scheduledAt = DateTime.fromJSDate(new Date())\n .toUTC()\n .startOf('second')\n .toISO({\n suppressMilliseconds: true,\n });\n\n assert(scheduledAt);\n\n const event = {\n ...backgroundEventWithoutId,\n id: nanoid(),\n scheduledAt,\n };\n\n this.#setUpBackgroundEvent(event);\n this.update((state) => {\n state.events[event.id] = castDraft(event);\n });\n\n return event.id;\n }\n\n /**\n * Cancel a background event.\n *\n * @param origin - The origin making the cancel call.\n * @param id - The id of the background event to cancel.\n * @throws If the event does not exist.\n */\n cancelBackgroundEvent(origin: string, id: string) {\n assert(\n this.state.events[id],\n `A background event with the id of \"${id}\" does not exist.`,\n );\n\n assert(\n this.state.events[id].snapId === origin,\n 'Only the origin that scheduled this event can cancel it.',\n );\n\n const timer = this.#timers.get(id);\n timer?.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n this.update((state) => {\n delete state.events[id];\n });\n }\n\n /**\n * A helper function to handle setup of the background event.\n *\n * @param event - A background event.\n */\n #setUpBackgroundEvent(event: BackgroundEvent) {\n const date = new Date(event.date);\n const now = new Date();\n const ms = date.getTime() - now.getTime();\n\n if (ms <= 0) {\n throw new Error('Cannot schedule an event in the past.');\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.messagingSystem\n .call('SnapController:handleRequest', {\n snapId: event.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: event.request,\n })\n .catch((error) => {\n logError(error);\n });\n\n this.#timers.delete(event.id);\n this.#snapIds.delete(event.id);\n this.update((state) => {\n delete state.events[event.id];\n });\n });\n\n this.#timers.set(event.id, timer);\n this.#snapIds.set(event.id, event.snapId);\n }\n\n /**\n * Get a list of a Snap's background events.\n *\n * @param snapId - The id of the Snap to fetch background events for.\n * @returns An array of background events.\n */\n getBackgroundEvents(snapId: SnapId): BackgroundEvent[] {\n return Object.values(this.state.events).filter(\n (snapEvent) => snapEvent.snapId === snapId,\n );\n }\n\n /**\n * Unregister all jobs and background events related to the given snapId.\n *\n * @param snapId - ID of a snap.\n * @param skipEvents - Whether the unregistration process should skip scheduled background events.\n */\n unregister(snapId: SnapId, skipEvents = false) {\n const jobs = [...this.#snapIds.entries()].filter(\n ([_, jobSnapId]) => jobSnapId === snapId,\n );\n\n if (jobs.length) {\n const eventIds: string[] = [];\n jobs.forEach(([id]) => {\n const timer = this.#timers.get(id);\n if (timer) {\n timer.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n if (!skipEvents && this.state.events[id]) {\n eventIds.push(id);\n }\n }\n });\n\n if (eventIds.length > 0) {\n this.update((state) => {\n eventIds.forEach((id) => {\n delete state.events[id];\n });\n });\n }\n }\n }\n\n /**\n * Update time of a last run for the Cronjob specified by ID.\n *\n * @param jobId - ID of a cron job.\n * @param lastRun - Unix timestamp when the job was last ran.\n */\n #updateJobLastRunState(jobId: string, lastRun: number) {\n this.update((state) => {\n state.jobs[jobId] = {\n lastRun,\n };\n });\n }\n\n /**\n * Runs every 24 hours to check if new jobs need to be scheduled.\n *\n * This is necessary for longer running jobs that execute with more than 24 hours between them.\n */\n dailyCheckIn() {\n const jobs = this.#getAllJobs();\n\n for (const job of jobs) {\n const parsed = parseCronExpression(job.expression);\n const lastRun = this.state.jobs[job.id]?.lastRun;\n // If a job was supposed to run while we were shut down but wasn't we run it now\n if (\n lastRun !== undefined &&\n parsed.hasPrev() &&\n parsed.prev().getTime() > lastRun\n ) {\n this.#executeCronjob(job).catch((error) => {\n logError(error);\n });\n }\n\n // Try scheduling, will fail if an existing scheduled job is found\n this.#schedule(job);\n }\n\n this.#dailyTimer = new Timer(DAILY_TIMEOUT);\n this.#dailyTimer.start(() => {\n this.dailyCheckIn();\n });\n }\n\n /**\n * Reschedule background events.\n *\n * @param backgroundEvents - A list of background events to reschdule.\n */\n #rescheduleBackgroundEvents(backgroundEvents: BackgroundEvent[]) {\n for (const snapEvent of backgroundEvents) {\n const { date } = snapEvent;\n const now = new Date();\n const then = new Date(date);\n if (then.getTime() < now.getTime()) {\n // Remove expired events from state\n this.update((state) => {\n delete state.events[snapEvent.id];\n });\n\n logWarning(\n `Background event with id \"${snapEvent.id}\" not scheduled as its date has expired.`,\n );\n } else {\n this.#setUpBackgroundEvent(snapEvent);\n }\n }\n }\n\n /**\n * Run controller teardown process and unsubscribe from Snap events.\n */\n destroy() {\n super.destroy();\n\n /* eslint-disable @typescript-eslint/unbound-method */\n this.messagingSystem.unsubscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.#snapIds.forEach((snapId) => this.unregister(snapId));\n }\n\n /**\n * Handle events that should cause cronjobs to be registered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapRegisterEvent(snap: TruncatedSnap) {\n this.register(snap.id);\n }\n\n /**\n * Handle events that could cause cronjobs to be registered\n * and for background events to be rescheduled.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapEnabledEvent(snap: TruncatedSnap) {\n const events = this.getBackgroundEvents(snap.id);\n this.#rescheduleBackgroundEvents(events);\n this.register(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapUnregisterEvent(snap: TruncatedSnap) {\n this.unregister(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapDisabledEvent(snap: TruncatedSnap) {\n this.unregister(snap.id, true);\n }\n\n /**\n * Handle cron jobs on 'snapUpdated' event.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleEventSnapUpdated(snap: TruncatedSnap) {\n this.unregister(snap.id);\n this.register(snap.id);\n }\n}\n"]}
1
+ {"version":3,"file":"CronjobController.mjs","sourceRoot":"","sources":["../../src/cronjob/CronjobController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { GetPermissions } from '@metamask/permission-controller';\nimport {\n getCronjobCaveatJobs,\n SnapEndowments,\n} from '@metamask/snaps-rpc-methods';\nimport type { BackgroundEvent, SnapId } from '@metamask/snaps-sdk';\nimport type {\n TruncatedSnap,\n CronjobSpecification,\n} from '@metamask/snaps-utils';\nimport {\n HandlerType,\n parseCronExpression,\n logError,\n logWarning,\n toCensoredISO8601String,\n} from '@metamask/snaps-utils';\nimport { assert, Duration, hasProperty, inMilliseconds } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { DateTime } from 'luxon';\nimport { nanoid } from 'nanoid';\n\nimport type {\n GetAllSnaps,\n HandleSnapRequest,\n SnapDisabled,\n SnapEnabled,\n SnapInstalled,\n SnapUninstalled,\n SnapUpdated,\n} from '..';\nimport { getRunnableSnaps } from '..';\nimport { Timer } from '../snaps/Timer';\n\nexport type CronjobControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n CronjobControllerState\n>;\nexport type CronjobControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n CronjobControllerState\n>;\n\nexport type ScheduleBackgroundEvent = {\n type: `${typeof controllerName}:scheduleBackgroundEvent`;\n handler: CronjobController['scheduleBackgroundEvent'];\n};\n\nexport type CancelBackgroundEvent = {\n type: `${typeof controllerName}:cancelBackgroundEvent`;\n handler: CronjobController['cancelBackgroundEvent'];\n};\n\nexport type GetBackgroundEvents = {\n type: `${typeof controllerName}:getBackgroundEvents`;\n handler: CronjobController['getBackgroundEvents'];\n};\n\nexport type CronjobControllerActions =\n | GetAllSnaps\n | HandleSnapRequest\n | GetPermissions\n | CronjobControllerGetStateAction\n | ScheduleBackgroundEvent\n | CancelBackgroundEvent\n | GetBackgroundEvents;\n\nexport type CronjobControllerEvents =\n | SnapInstalled\n | SnapUninstalled\n | SnapUpdated\n | SnapEnabled\n | SnapDisabled\n | CronjobControllerStateChangeEvent;\n\nexport type CronjobControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n CronjobControllerActions,\n CronjobControllerEvents,\n CronjobControllerActions['type'],\n CronjobControllerEvents['type']\n>;\n\nexport const DAILY_TIMEOUT = inMilliseconds(24, Duration.Hour);\n\nexport type CronjobControllerArgs = {\n messenger: CronjobControllerMessenger;\n /**\n * Persisted state that will be used for rehydration.\n */\n state?: CronjobControllerState;\n};\n\nexport type Cronjob = {\n timer?: Timer;\n id: string;\n snapId: SnapId;\n} & CronjobSpecification;\n\nexport type StoredJobInformation = {\n lastRun: number;\n};\n\nexport type CronjobControllerState = {\n jobs: Record<string, StoredJobInformation>;\n events: Record<string, BackgroundEvent>;\n};\n\nconst controllerName = 'CronjobController';\n\n/**\n * Use this controller to register and schedule periodically executed jobs\n * using RPC method hooks.\n */\nexport class CronjobController extends BaseController<\n typeof controllerName,\n CronjobControllerState,\n CronjobControllerMessenger\n> {\n #dailyTimer!: Timer;\n\n readonly #timers: Map<string, Timer>;\n\n // Mapping from jobId to snapId\n readonly #snapIds: Map<string, SnapId>;\n\n constructor({ messenger, state }: CronjobControllerArgs) {\n super({\n messenger,\n metadata: {\n jobs: { persist: true, anonymous: false },\n events: { persist: true, anonymous: false },\n },\n name: controllerName,\n state: {\n jobs: {},\n events: {},\n ...state,\n },\n });\n this.#timers = new Map();\n this.#snapIds = new Map();\n\n this._handleSnapRegisterEvent = this._handleSnapRegisterEvent.bind(this);\n this._handleSnapUnregisterEvent =\n this._handleSnapUnregisterEvent.bind(this);\n this._handleEventSnapUpdated = this._handleEventSnapUpdated.bind(this);\n this._handleSnapDisabledEvent = this._handleSnapDisabledEvent.bind(this);\n this._handleSnapEnabledEvent = this._handleSnapEnabledEvent.bind(this);\n // Subscribe to Snap events\n /* eslint-disable @typescript-eslint/unbound-method */\n\n this.messagingSystem.subscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.subscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:scheduleBackgroundEvent`,\n (...args) => this.scheduleBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:cancelBackgroundEvent`,\n (...args) => this.cancelBackgroundEvent(...args),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getBackgroundEvents`,\n (...args) => this.getBackgroundEvents(...args),\n );\n\n this.dailyCheckIn();\n\n this.#rescheduleBackgroundEvents(Object.values(this.state.events));\n }\n\n /**\n * Retrieve all cronjob specifications for all runnable snaps.\n *\n * @returns Array of Cronjob specifications.\n */\n #getAllJobs(): Cronjob[] {\n const snaps = this.messagingSystem.call('SnapController:getAll');\n const filteredSnaps = getRunnableSnaps(snaps);\n\n const jobs = filteredSnaps.map((snap) => this.#getSnapJobs(snap.id));\n return jobs.flat().filter((job) => job !== undefined) as Cronjob[];\n }\n\n /**\n * Retrieve all Cronjob specifications for a Snap.\n *\n * @param snapId - ID of a Snap.\n * @returns Array of Cronjob specifications.\n */\n #getSnapJobs(snapId: SnapId): Cronjob[] | undefined {\n const permissions = this.messagingSystem.call(\n 'PermissionController:getPermissions',\n snapId,\n );\n\n const permission = permissions?.[SnapEndowments.Cronjob];\n const definitions = getCronjobCaveatJobs(permission);\n\n return definitions?.map((definition, idx) => {\n return { ...definition, id: `${snapId}-${idx}`, snapId };\n });\n }\n\n /**\n * Register cron jobs for a given snap by getting specification from a permission caveats.\n * Once registered, each job will be scheduled.\n *\n * @param snapId - ID of a snap.\n */\n register(snapId: SnapId) {\n const jobs = this.#getSnapJobs(snapId);\n jobs?.forEach((job) => this.#schedule(job));\n }\n\n /**\n * Schedule a new job.\n * This will interpret the cron expression and tell the timer to execute the job\n * at the next suitable point in time.\n * Job last run state will be initialized afterwards.\n *\n * Note: Schedule will be skipped if the job's execution time is too far in the future and\n * will be revisited on a daily check.\n *\n * @param job - Cronjob specification.\n */\n #schedule(job: Cronjob) {\n if (this.#timers.has(job.id)) {\n return;\n }\n\n const parsed = parseCronExpression(job.expression);\n const next = parsed.next();\n const now = new Date();\n const ms = next.getTime() - now.getTime();\n\n // Don't schedule this job yet as it is too far in the future\n if (ms > DAILY_TIMEOUT) {\n return;\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.#executeCronjob(job).catch((error) => {\n // TODO: Decide how to handle errors.\n logError(error);\n });\n\n this.#timers.delete(job.id);\n this.#schedule(job);\n });\n\n if (!this.state.jobs[job.id]?.lastRun) {\n this.#updateJobLastRunState(job.id, 0); // 0 for init, never ran actually\n }\n\n this.#timers.set(job.id, timer);\n this.#snapIds.set(job.id, job.snapId);\n }\n\n /**\n * Execute job.\n *\n * @param job - Cronjob specification.\n */\n async #executeCronjob(job: Cronjob) {\n this.#updateJobLastRunState(job.id, Date.now());\n await this.messagingSystem.call('SnapController:handleRequest', {\n snapId: job.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: job.request,\n });\n }\n\n /**\n * Schedule a background event.\n *\n * @param backgroundEventWithoutId - Background event.\n * @returns An id representing the background event.\n */\n scheduleBackgroundEvent(\n backgroundEventWithoutId: Omit<BackgroundEvent, 'id' | 'scheduledAt'>,\n ) {\n // Remove millisecond precision and convert to UTC.\n const scheduledAt = DateTime.fromJSDate(new Date())\n .toUTC()\n .startOf('second')\n .toISO({\n suppressMilliseconds: true,\n });\n\n assert(scheduledAt);\n\n const event = {\n ...backgroundEventWithoutId,\n id: nanoid(),\n scheduledAt,\n };\n\n this.#setUpBackgroundEvent(event);\n\n return event.id;\n }\n\n /**\n * Cancel a background event.\n *\n * @param origin - The origin making the cancel call.\n * @param id - The id of the background event to cancel.\n * @throws If the event does not exist.\n */\n cancelBackgroundEvent(origin: string, id: string) {\n assert(\n this.state.events[id],\n `A background event with the id of \"${id}\" does not exist.`,\n );\n\n assert(\n this.state.events[id].snapId === origin,\n 'Only the origin that scheduled this event can cancel it.',\n );\n\n const timer = this.#timers.get(id);\n timer?.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n this.update((state) => {\n delete state.events[id];\n });\n }\n\n /**\n * A helper function to handle setup of the background event.\n *\n * @param event - A background event.\n */\n #setUpBackgroundEvent(event: BackgroundEvent) {\n const date = new Date(event.date);\n const now = new Date();\n const ms = date.getTime() - now.getTime();\n\n if (ms <= 0) {\n throw new Error('Cannot schedule an event in the past.');\n }\n\n // The event may already be in state when we get here.\n if (!hasProperty(this.state.events, event.id)) {\n this.update((state) => {\n state.events[event.id] = castDraft(event);\n });\n }\n\n const timer = new Timer(ms);\n timer.start(() => {\n this.messagingSystem\n .call('SnapController:handleRequest', {\n snapId: event.snapId,\n origin: 'metamask',\n handler: HandlerType.OnCronjob,\n request: event.request,\n })\n .catch((error) => {\n logError(error);\n });\n\n this.#timers.delete(event.id);\n this.#snapIds.delete(event.id);\n this.update((state) => {\n delete state.events[event.id];\n });\n });\n\n this.#timers.set(event.id, timer);\n this.#snapIds.set(event.id, event.snapId);\n }\n\n /**\n * Get a list of a Snap's background events.\n *\n * @param snapId - The id of the Snap to fetch background events for.\n * @returns An array of background events.\n */\n getBackgroundEvents(snapId: SnapId): BackgroundEvent[] {\n return Object.values(this.state.events)\n .filter((snapEvent) => snapEvent.snapId === snapId)\n .map((event) => ({\n ...event,\n // Truncate dates to remove milliseconds.\n date: toCensoredISO8601String(event.date),\n }));\n }\n\n /**\n * Unregister all jobs and background events related to the given snapId.\n *\n * @param snapId - ID of a snap.\n * @param skipEvents - Whether the unregistration process should skip scheduled background events.\n */\n unregister(snapId: SnapId, skipEvents = false) {\n const jobs = [...this.#snapIds.entries()].filter(\n ([_, jobSnapId]) => jobSnapId === snapId,\n );\n\n if (jobs.length) {\n const eventIds: string[] = [];\n jobs.forEach(([id]) => {\n const timer = this.#timers.get(id);\n if (timer) {\n timer.cancel();\n this.#timers.delete(id);\n this.#snapIds.delete(id);\n if (!skipEvents && this.state.events[id]) {\n eventIds.push(id);\n }\n }\n });\n\n if (eventIds.length > 0) {\n this.update((state) => {\n eventIds.forEach((id) => {\n delete state.events[id];\n });\n });\n }\n }\n }\n\n /**\n * Update time of a last run for the Cronjob specified by ID.\n *\n * @param jobId - ID of a cron job.\n * @param lastRun - Unix timestamp when the job was last ran.\n */\n #updateJobLastRunState(jobId: string, lastRun: number) {\n this.update((state) => {\n state.jobs[jobId] = {\n lastRun,\n };\n });\n }\n\n /**\n * Runs every 24 hours to check if new jobs need to be scheduled.\n *\n * This is necessary for longer running jobs that execute with more than 24 hours between them.\n */\n dailyCheckIn() {\n const jobs = this.#getAllJobs();\n\n for (const job of jobs) {\n const parsed = parseCronExpression(job.expression);\n const lastRun = this.state.jobs[job.id]?.lastRun;\n // If a job was supposed to run while we were shut down but wasn't we run it now\n if (\n lastRun !== undefined &&\n parsed.hasPrev() &&\n parsed.prev().getTime() > lastRun\n ) {\n this.#executeCronjob(job).catch((error) => {\n logError(error);\n });\n }\n\n // Try scheduling, will fail if an existing scheduled job is found\n this.#schedule(job);\n }\n\n this.#dailyTimer = new Timer(DAILY_TIMEOUT);\n this.#dailyTimer.start(() => {\n this.dailyCheckIn();\n });\n }\n\n /**\n * Reschedule background events.\n *\n * @param backgroundEvents - A list of background events to reschdule.\n */\n #rescheduleBackgroundEvents(backgroundEvents: BackgroundEvent[]) {\n for (const snapEvent of backgroundEvents) {\n const { date } = snapEvent;\n const now = new Date();\n const then = new Date(date);\n if (then.getTime() < now.getTime()) {\n // Remove expired events from state\n this.update((state) => {\n delete state.events[snapEvent.id];\n });\n\n logWarning(\n `Background event with id \"${snapEvent.id}\" not scheduled as its date has expired.`,\n );\n } else {\n this.#setUpBackgroundEvent(snapEvent);\n }\n }\n }\n\n /**\n * Run controller teardown process and unsubscribe from Snap events.\n */\n destroy() {\n super.destroy();\n\n /* eslint-disable @typescript-eslint/unbound-method */\n this.messagingSystem.unsubscribe(\n 'SnapController:snapInstalled',\n this._handleSnapRegisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUninstalled',\n this._handleSnapUnregisterEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapEnabled',\n this._handleSnapEnabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapDisabled',\n this._handleSnapDisabledEvent,\n );\n\n this.messagingSystem.unsubscribe(\n 'SnapController:snapUpdated',\n this._handleEventSnapUpdated,\n );\n /* eslint-enable @typescript-eslint/unbound-method */\n\n this.#snapIds.forEach((snapId) => this.unregister(snapId));\n }\n\n /**\n * Handle events that should cause cronjobs to be registered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapRegisterEvent(snap: TruncatedSnap) {\n this.register(snap.id);\n }\n\n /**\n * Handle events that could cause cronjobs to be registered\n * and for background events to be rescheduled.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapEnabledEvent(snap: TruncatedSnap) {\n const events = this.getBackgroundEvents(snap.id);\n this.#rescheduleBackgroundEvents(events);\n this.register(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapUnregisterEvent(snap: TruncatedSnap) {\n this.unregister(snap.id);\n }\n\n /**\n * Handle events that should cause cronjobs and background events to be unregistered.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleSnapDisabledEvent(snap: TruncatedSnap) {\n this.unregister(snap.id, true);\n }\n\n /**\n * Handle cron jobs on 'snapUpdated' event.\n *\n * @param snap - Basic Snap information.\n */\n // TODO: Either fix this lint violation or explain why it's necessary to\n // ignore.\n // eslint-disable-next-line no-restricted-syntax\n private _handleEventSnapUpdated(snap: TruncatedSnap) {\n this.unregister(snap.id);\n this.register(snap.id);\n }\n}\n"]}
@@ -4,7 +4,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
4
4
  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");
5
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
6
  };
7
- var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_getAccountByAddress, _SnapInterfaceController_getAssetsState, _SnapInterfaceController_getSnap, _SnapInterfaceController_validateContent, _SnapInterfaceController_onNotificationsListUpdated;
7
+ var _SnapInterfaceController_instances, _SnapInterfaceController_registerMessageHandlers, _SnapInterfaceController_validateArgs, _SnapInterfaceController_validateApproval, _SnapInterfaceController_checkPhishingList, _SnapInterfaceController_hasApprovalRequest, _SnapInterfaceController_acceptApprovalRequest, _SnapInterfaceController_getSelectedAccount, _SnapInterfaceController_listAccounts, _SnapInterfaceController_getAccountByAddress, _SnapInterfaceController_getAssetsState, _SnapInterfaceController_getSnap, _SnapInterfaceController_validateContent, _SnapInterfaceController_onNotificationsListUpdated;
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.SnapInterfaceController = void 0;
10
10
  const base_controller_1 = require("@metamask/base-controller");
@@ -63,6 +63,9 @@ class SnapInterfaceController extends base_controller_1.BaseController {
63
63
  const componentState = (0, utils_2.constructState)({}, element, {
64
64
  getAssetsState: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAssetsState).bind(this),
65
65
  getAccountByAddress: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAccountByAddress).bind(this),
66
+ getSelectedAccount: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getSelectedAccount).bind(this),
67
+ listAccounts: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_listAccounts).bind(this),
68
+ snapOwnsAccount: (account) => (0, snaps_utils_1.snapOwnsAccount)(snapId, account),
66
69
  });
67
70
  this.update((draftState) => {
68
71
  // @ts-expect-error - TS2589: Type instantiation is excessively deep and
@@ -105,6 +108,9 @@ class SnapInterfaceController extends base_controller_1.BaseController {
105
108
  const newState = (0, utils_2.constructState)(oldState, element, {
106
109
  getAssetsState: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAssetsState).bind(this),
107
110
  getAccountByAddress: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getAccountByAddress).bind(this),
111
+ getSelectedAccount: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_getSelectedAccount).bind(this),
112
+ listAccounts: __classPrivateFieldGet(this, _SnapInterfaceController_instances, "m", _SnapInterfaceController_listAccounts).bind(this),
113
+ snapOwnsAccount: (account) => (0, snaps_utils_1.snapOwnsAccount)(snapId, account),
108
114
  });
109
115
  this.update((draftState) => {
110
116
  draftState.interfaces[id].state = newState;
@@ -180,6 +186,14 @@ _SnapInterfaceController_instances = new WeakSet(), _SnapInterfaceController_reg
180
186
  */
181
187
  async function _SnapInterfaceController_acceptApprovalRequest(id, value) {
182
188
  await this.messagingSystem.call('ApprovalController:acceptRequest', id, value);
189
+ }, _SnapInterfaceController_getSelectedAccount = function _SnapInterfaceController_getSelectedAccount() {
190
+ return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
191
+ }, _SnapInterfaceController_listAccounts = function _SnapInterfaceController_listAccounts(chainIds) {
192
+ const accounts = this.messagingSystem.call('AccountsController:listMultichainAccounts');
193
+ if (!chainIds || chainIds.length === 0) {
194
+ return accounts;
195
+ }
196
+ return accounts.filter((account) => account.scopes.some((scope) => (0, utils_2.isMatchingChainId)(scope, chainIds)));
183
197
  }, _SnapInterfaceController_getAccountByAddress = function _SnapInterfaceController_getAccountByAddress(address) {
184
198
  const { address: parsedAddress } = (0, utils_1.parseCaipAccountId)(address);
185
199
  return this.messagingSystem.call('AccountsController:getAccountByAddress', parsedAddress);
@@ -1 +1 @@
1
- {"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TestOrigin } from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n FungibleAssetMetadata,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport { getJsonSizeUnsafe, validateJsxElements } from '@metamask/snaps-utils';\nimport type { CaipAccountId, CaipAssetType, Json } from '@metamask/utils';\nimport { assert, hasProperty, parseCaipAccountId } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport {\n constructState,\n getJsxInterface,\n validateInterfaceContext,\n} from './utils';\nimport type { GetSnap } from '../snaps';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\ntype AccountsControllerGetAccountByAddressAction = {\n type: `AccountsController:getAccountByAddress`;\n handler: (address: string) => InternalAccount | undefined;\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\ntype MultichainAssetsControllerGetStateAction = ControllerGetStateAction<\n 'MultichainAssetsController',\n {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n }\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetAccountByAddressAction;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\n #getAccountByAddress(address: CaipAccountId) {\n const { address: parsedAddress } = parseCaipAccountId(address);\n\n return this.messagingSystem.call(\n 'AccountsController:getAccountByAddress',\n parsedAddress,\n );\n }\n\n /**\n * Get the MultichainAssetsController state.\n *\n * @returns The MultichainAssetsController state.\n */\n #getAssetsState() {\n return this.messagingSystem.call('MultichainAssetsController:getState');\n }\n\n /**\n * Get a snap by its id.\n *\n * @param id - The snap id.\n * @returns The snap.\n */\n #getSnap(id: string) {\n return this.messagingSystem.call('SnapController:get', id);\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n validateJsxElements(element, {\n isOnPhishingList: this.#checkPhishingList.bind(this),\n getSnap: this.#getSnap.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}
1
+ {"version":3,"file":"SnapInterfaceController.cjs","sourceRoot":"","sources":["../../src/interface/SnapInterfaceController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n AcceptRequest,\n HasApprovalRequest,\n} from '@metamask/approval-controller';\nimport type {\n RestrictedMessenger,\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { TestOrigin } from '@metamask/phishing-controller';\nimport type {\n InterfaceState,\n SnapId,\n ComponentOrElement,\n InterfaceContext,\n FungibleAssetMetadata,\n} from '@metamask/snaps-sdk';\nimport { ContentType } from '@metamask/snaps-sdk';\nimport type { JSXElement } from '@metamask/snaps-sdk/jsx';\nimport type { InternalAccount } from '@metamask/snaps-utils';\nimport {\n getJsonSizeUnsafe,\n snapOwnsAccount,\n validateJsxElements,\n} from '@metamask/snaps-utils';\nimport type {\n CaipAccountId,\n CaipAssetType,\n CaipChainId,\n Json,\n} from '@metamask/utils';\nimport { assert, hasProperty, parseCaipAccountId } from '@metamask/utils';\nimport { castDraft } from 'immer';\nimport { nanoid } from 'nanoid';\n\nimport {\n constructState,\n getJsxInterface,\n isMatchingChainId,\n validateInterfaceContext,\n} from './utils';\nimport type { GetSnap } from '../snaps';\n\nconst MAX_UI_CONTENT_SIZE = 10_000_000; // 10 mb\n\nconst controllerName = 'SnapInterfaceController';\n\nexport type CreateInterface = {\n type: `${typeof controllerName}:createInterface`;\n handler: SnapInterfaceController['createInterface'];\n};\n\nexport type GetInterface = {\n type: `${typeof controllerName}:getInterface`;\n handler: SnapInterfaceController['getInterface'];\n};\n\nexport type UpdateInterface = {\n type: `${typeof controllerName}:updateInterface`;\n handler: SnapInterfaceController['updateInterface'];\n};\n\nexport type DeleteInterface = {\n type: `${typeof controllerName}:deleteInterface`;\n handler: SnapInterfaceController['deleteInterface'];\n};\n\nexport type UpdateInterfaceState = {\n type: `${typeof controllerName}:updateInterfaceState`;\n handler: SnapInterfaceController['updateInterfaceState'];\n};\n\nexport type ResolveInterface = {\n type: `${typeof controllerName}:resolveInterface`;\n handler: SnapInterfaceController['resolveInterface'];\n};\n\ntype AccountsControllerGetAccountByAddressAction = {\n type: `AccountsController:getAccountByAddress`;\n handler: (address: string) => InternalAccount | undefined;\n};\n\ntype AccountsControllerGetSelectedMultichainAccountAction = {\n type: `AccountsController:getSelectedMultichainAccount`;\n handler: () => InternalAccount;\n};\n\ntype AccountsControllerListMultichainAccountsAction = {\n type: `AccountsController:listMultichainAccounts`;\n handler: (chainId?: CaipChainId) => InternalAccount[];\n};\n\nexport type SnapInterfaceControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n SnapInterfaceControllerState\n>;\n\ntype MultichainAssetsControllerGetStateAction = ControllerGetStateAction<\n 'MultichainAssetsController',\n {\n assetsMetadata: {\n [asset: CaipAssetType]: FungibleAssetMetadata;\n };\n accountsAssets: { [account: string]: CaipAssetType[] };\n }\n>;\n\nexport type SnapInterfaceControllerAllowedActions =\n | TestOrigin\n | HasApprovalRequest\n | AcceptRequest\n | GetSnap\n | MultichainAssetsControllerGetStateAction\n | AccountsControllerGetSelectedMultichainAccountAction\n | AccountsControllerGetAccountByAddressAction\n | AccountsControllerListMultichainAccountsAction;\n\nexport type SnapInterfaceControllerActions =\n | CreateInterface\n | GetInterface\n | UpdateInterface\n | DeleteInterface\n | UpdateInterfaceState\n | ResolveInterface\n | SnapInterfaceControllerGetStateAction;\n\nexport type SnapInterfaceControllerStateChangeEvent =\n ControllerStateChangeEvent<\n typeof controllerName,\n SnapInterfaceControllerState\n >;\n\ntype OtherNotification = { type: string; [key: string]: unknown };\n\nexport type ExpandedView = {\n title: string;\n interfaceId: string;\n footerLink?: { href: string; text: string };\n};\n\ntype NormalSnapNotificationData = { message: string; origin: string };\n\ntype ExpandedSnapNotificationData = {\n message: string;\n origin: string;\n detailedView: ExpandedView;\n};\n\ntype SnapNotification = {\n type: 'snap';\n data: NormalSnapNotificationData | ExpandedSnapNotificationData;\n readDate: string | null;\n};\n\ntype Notification = OtherNotification | SnapNotification;\n\ntype NotificationListUpdatedEvent = {\n type: 'NotificationServicesController:notificationsListUpdated';\n payload: [Notification[]];\n};\n\nexport type SnapInterfaceControllerEvents =\n | SnapInterfaceControllerStateChangeEvent\n | NotificationListUpdatedEvent;\n\nexport type SnapInterfaceControllerMessenger = RestrictedMessenger<\n typeof controllerName,\n SnapInterfaceControllerActions | SnapInterfaceControllerAllowedActions,\n SnapInterfaceControllerEvents,\n SnapInterfaceControllerAllowedActions['type'],\n SnapInterfaceControllerEvents['type']\n>;\n\nexport type StoredInterface = {\n snapId: SnapId;\n content: JSXElement;\n state: InterfaceState;\n context: InterfaceContext | null;\n contentType: ContentType | null;\n};\n\nexport type SnapInterfaceControllerState = {\n interfaces: Record<string, StoredInterface>;\n};\n\nexport type SnapInterfaceControllerArgs = {\n messenger: SnapInterfaceControllerMessenger;\n state?: SnapInterfaceControllerState;\n};\n\n/**\n * Use this controller to manage snaps UI interfaces using RPC method hooks.\n */\nexport class SnapInterfaceController extends BaseController<\n typeof controllerName,\n SnapInterfaceControllerState,\n SnapInterfaceControllerMessenger\n> {\n constructor({ messenger, state }: SnapInterfaceControllerArgs) {\n super({\n messenger,\n metadata: {\n interfaces: {\n persist: (interfaces: Record<string, StoredInterface>) => {\n return Object.entries(interfaces).reduce<\n Record<string, StoredInterface>\n >((persistedInterfaces, [id, snapInterface]) => {\n switch (snapInterface.contentType) {\n case ContentType.Notification:\n persistedInterfaces[id] = snapInterface;\n return persistedInterfaces;\n default:\n return persistedInterfaces;\n }\n }, {});\n },\n anonymous: false,\n },\n },\n name: controllerName,\n state: { interfaces: {}, ...state },\n });\n\n this.messagingSystem.subscribe(\n 'NotificationServicesController:notificationsListUpdated',\n this.#onNotificationsListUpdated.bind(this),\n );\n\n this.#registerMessageHandlers();\n }\n\n /**\n * Constructor helper for registering this controller's messaging system\n * actions.\n */\n #registerMessageHandlers() {\n this.messagingSystem.registerActionHandler(\n `${controllerName}:createInterface`,\n this.createInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:getInterface`,\n this.getInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterface`,\n this.updateInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:deleteInterface`,\n this.deleteInterface.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:updateInterfaceState`,\n this.updateInterfaceState.bind(this),\n );\n\n this.messagingSystem.registerActionHandler(\n `${controllerName}:resolveInterface`,\n this.resolveInterface.bind(this),\n );\n }\n\n /**\n * Create an interface in the controller state with the associated data.\n *\n * @param snapId - The snap id that created the interface.\n * @param content - The interface content.\n * @param context - An optional interface context object.\n * @param contentType - The type of content.\n * @returns The newly interface id.\n */\n async createInterface(\n snapId: SnapId,\n content: ComponentOrElement,\n context?: InterfaceContext,\n contentType?: ContentType,\n ) {\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const id = nanoid();\n const componentState = constructState({}, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n // @ts-expect-error - TS2589: Type instantiation is excessively deep and\n // possibly infinite.\n draftState.interfaces[id] = {\n snapId,\n content: castDraft(element),\n state: componentState,\n context: context ?? null,\n contentType: contentType ?? null,\n };\n });\n\n return id;\n }\n\n /**\n * Get the data of a given interface id.\n *\n * @param snapId - The snap id requesting the interface data.\n * @param id - The interface id.\n * @returns The interface state.\n */\n getInterface(snapId: SnapId, id: string) {\n this.#validateArgs(snapId, id);\n\n return this.state.interfaces[id];\n }\n\n /**\n * Update the interface with the given content.\n *\n * @param snapId - The snap id requesting the update.\n * @param id - The interface id.\n * @param content - The new content.\n * @param context - An optional interface context object.\n */\n async updateInterface(\n snapId: SnapId,\n id: string,\n content: ComponentOrElement,\n context?: InterfaceContext,\n ) {\n this.#validateArgs(snapId, id);\n const element = getJsxInterface(content);\n await this.#validateContent(element);\n validateInterfaceContext(context);\n\n const oldState = this.state.interfaces[id].state;\n const newState = constructState(oldState, element, {\n getAssetsState: this.#getAssetsState.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n getSelectedAccount: this.#getSelectedAccount.bind(this),\n listAccounts: this.#listAccounts.bind(this),\n snapOwnsAccount: (account: InternalAccount) =>\n snapOwnsAccount(snapId, account),\n });\n\n this.update((draftState) => {\n draftState.interfaces[id].state = newState;\n draftState.interfaces[id].content = castDraft(element);\n if (context) {\n draftState.interfaces[id].context = context;\n }\n });\n }\n\n /**\n * Delete an interface from state.\n *\n * @param id - The interface id.\n */\n deleteInterface(id: string) {\n this.update((draftState) => {\n delete draftState.interfaces[id];\n });\n }\n\n /**\n * Update the interface state.\n *\n * @param id - The interface id.\n * @param state - The new state.\n */\n updateInterfaceState(id: string, state: InterfaceState) {\n this.update((draftState) => {\n draftState.interfaces[id].state = state;\n });\n }\n\n /**\n * Resolve the promise of a given interface approval request.\n * The approval needs to have the same ID as the interface.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async resolveInterface(snapId: SnapId, id: string, value: Json) {\n this.#validateArgs(snapId, id);\n this.#validateApproval(id);\n\n await this.#acceptApprovalRequest(id, value);\n\n this.deleteInterface(id);\n }\n\n /**\n * Utility function to validate the args passed to the other methods.\n *\n * @param snapId - The snap id.\n * @param id - The interface id.\n */\n #validateArgs(snapId: SnapId, id: string) {\n const existingInterface = this.state.interfaces[id];\n\n assert(\n existingInterface !== undefined,\n `Interface with id '${id}' not found.`,\n );\n assert(\n existingInterface.snapId === snapId,\n `Interface not created by ${snapId}.`,\n );\n }\n\n /**\n * Utility function to validate that the approval request exists.\n *\n * @param id - The interface id.\n */\n #validateApproval(id: string) {\n assert(\n this.#hasApprovalRequest(id),\n `Approval request with id '${id}' not found.`,\n );\n }\n\n /**\n * Check an origin against the phishing list.\n *\n * @param origin - The origin to check.\n * @returns True if the origin is on the phishing list, otherwise false.\n */\n #checkPhishingList(origin: string) {\n return this.messagingSystem.call('PhishingController:testOrigin', origin)\n .result;\n }\n\n /**\n * Check if an approval request exists for a given interface by looking up\n * if the ApprovalController has a request with the given interface ID.\n *\n * @param id - The interface id.\n * @returns True if an approval request exists, otherwise false.\n */\n #hasApprovalRequest(id: string) {\n return this.messagingSystem.call('ApprovalController:hasRequest', {\n id,\n });\n }\n\n /**\n * Accept an approval request for a given interface.\n *\n * @param id - The interface id.\n * @param value - The value to resolve the promise with.\n */\n async #acceptApprovalRequest(id: string, value: Json) {\n await this.messagingSystem.call(\n 'ApprovalController:acceptRequest',\n id,\n value,\n );\n }\n\n /**\n * Get the selected account in the client.\n *\n * @returns The selected account.\n */\n #getSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n /**\n * Get a list of accounts for the given chain IDs.\n *\n * @param chainIds - The chain IDs to get the accounts for.\n * @returns The list of accounts.\n */\n #listAccounts(chainIds?: CaipChainId[]) {\n const accounts = this.messagingSystem.call(\n 'AccountsController:listMultichainAccounts',\n );\n\n if (!chainIds || chainIds.length === 0) {\n return accounts;\n }\n\n return accounts.filter((account) =>\n account.scopes.some((scope) => isMatchingChainId(scope, chainIds)),\n );\n }\n\n /**\n * Get an account by its address.\n *\n * @param address - The account address.\n * @returns The account or undefined if not found.\n */\n #getAccountByAddress(address: CaipAccountId) {\n const { address: parsedAddress } = parseCaipAccountId(address);\n\n return this.messagingSystem.call(\n 'AccountsController:getAccountByAddress',\n parsedAddress,\n );\n }\n\n /**\n * Get the MultichainAssetsController state.\n *\n * @returns The MultichainAssetsController state.\n */\n #getAssetsState() {\n return this.messagingSystem.call('MultichainAssetsController:getState');\n }\n\n /**\n * Get a snap by its id.\n *\n * @param id - The snap id.\n * @returns The snap.\n */\n #getSnap(id: string) {\n return this.messagingSystem.call('SnapController:get', id);\n }\n\n /**\n * Utility function to validate the components of an interface.\n * Throws if something is invalid.\n *\n * @param element - The JSX element to verify.\n */\n async #validateContent(element: JSXElement) {\n // We assume the validity of this JSON to be validated by the caller.\n // E.g., in the RPC method implementation.\n const size = getJsonSizeUnsafe(element);\n assert(\n size <= MAX_UI_CONTENT_SIZE,\n `A Snap UI may not be larger than ${MAX_UI_CONTENT_SIZE / 1000000} MB.`,\n );\n\n validateJsxElements(element, {\n isOnPhishingList: this.#checkPhishingList.bind(this),\n getSnap: this.#getSnap.bind(this),\n getAccountByAddress: this.#getAccountByAddress.bind(this),\n });\n }\n\n #onNotificationsListUpdated(notificationsList: Notification[]) {\n const snapNotificationsWithInterface = notificationsList.filter(\n (notification) => {\n return (\n notification.type === 'snap' &&\n hasProperty((notification as SnapNotification).data, 'detailedView')\n );\n },\n );\n\n const interfaceIdSet = new Set(\n snapNotificationsWithInterface.map(\n (notification) =>\n (\n (notification as SnapNotification)\n .data as ExpandedSnapNotificationData\n ).detailedView.interfaceId,\n ),\n );\n\n this.update((state) => {\n Object.entries(state.interfaces).forEach(([id, snapInterface]) => {\n if (\n snapInterface.contentType === ContentType.Notification &&\n !interfaceIdSet.has(id)\n ) {\n delete state.interfaces[id];\n }\n });\n });\n }\n}\n"]}