{"version":3,"file":"SnapController.cjs","sourceRoot":"","sources":["../../src/snaps/SnapController.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n  ORIGIN_METAMASK,\n  type ApprovalControllerAddRequestAction,\n  type ApprovalControllerUpdateRequestStateAction,\n} from '@metamask/approval-controller';\nimport type {\n  ControllerGetStateAction,\n  ControllerStateChangeEvent,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { CryptographicFunctions } from '@metamask/key-tree';\nimport type { Messenger } from '@metamask/messenger';\nimport type {\n  Caveat,\n  PermissionControllerGetEndowmentsAction,\n  PermissionControllerGetPermissionsAction,\n  SubjectMetadataControllerGetSubjectMetadataAction,\n  SubjectMetadataControllerAddSubjectMetadataAction,\n  PermissionControllerGetSubjectNamesAction,\n  PermissionControllerGrantPermissionsAction,\n  PermissionControllerHasPermissionAction,\n  PermissionControllerHasPermissionsAction,\n  PermissionConstraint,\n  PermissionsRequest,\n  RequestedPermissions,\n  PermissionControllerRevokeAllPermissionsAction,\n  PermissionControllerRevokePermissionForAllSubjectsAction,\n  PermissionControllerRevokePermissionsAction,\n  SubjectPermissions,\n  PermissionControllerUpdateCaveatAction,\n  ValidPermission,\n} from '@metamask/permission-controller';\nimport { SubjectType } from '@metamask/permission-controller';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { BlockReason } from '@metamask/snaps-registry';\nimport {\n  WALLET_SNAP_PERMISSION_KEY,\n  getMaxRequestTimeCaveat,\n  handlerEndowments,\n  SnapEndowments,\n  getKeyringCaveatOrigins,\n  getRpcCaveatOrigins,\n  processSnapPermissions,\n  getEncryptionEntropy,\n  getChainIdsCaveat,\n} from '@metamask/snaps-rpc-methods';\nimport type {\n  RequestSnapsParams,\n  RequestSnapsResult,\n  SnapId,\n  ComponentOrElement,\n  ContentType,\n  OnAssetsLookupResponse,\n  OnAssetsConversionResponse,\n  OnAssetsConversionArguments,\n  AssetConversion,\n  OnAssetsLookupArguments,\n  OnAssetsMarketDataArguments,\n  OnAssetsMarketDataResponse,\n  AssetMarketData,\n  AssetMetadata,\n  EmptyObject,\n} from '@metamask/snaps-sdk';\nimport {\n  AuxiliaryFileEncoding,\n  getErrorMessage,\n  OnAssetsLookupResponseStruct,\n} from '@metamask/snaps-sdk';\nimport type {\n  FetchedSnapFiles,\n  InitialConnections,\n  PersistedSnap,\n  Snap,\n  SnapManifest,\n  SnapPermissions,\n  SnapRpcHookArgs,\n  StatusContext,\n  StatusEvents,\n  StatusStates,\n  StorageServiceSnapData,\n  TruncatedSnap,\n  TruncatedSnapFields,\n} from '@metamask/snaps-utils';\nimport {\n  logWarning,\n  getPlatformVersion,\n  assertIsSnapManifest,\n  assertIsValidSnapId,\n  DEFAULT_ENDOWMENTS,\n  encodeAuxiliaryFile,\n  HandlerType,\n  isOriginAllowed,\n  logError,\n  normalizeRelative,\n  OnTransactionResponseStruct,\n  OnSignatureResponseStruct,\n  resolveVersionRange,\n  SnapCaveatType,\n  SnapStatus,\n  SnapStatusEvents,\n  unwrapError,\n  OnHomePageResponseStruct,\n  getValidatedLocalizationFiles,\n  VirtualFile,\n  NpmSnapFileNames,\n  OnNameLookupResponseStruct,\n  getLocalizedSnapManifest,\n  MAX_FILE_SIZE,\n  OnSettingsPageResponseStruct,\n  isValidUrl,\n  OnAssetHistoricalPriceResponseStruct,\n  OnAssetsConversionResponseStruct,\n  OnAssetsMarketDataResponseStruct,\n} from '@metamask/snaps-utils';\nimport type {\n  StorageServiceGetItemAction,\n  StorageServiceSetItemAction,\n  StorageServiceRemoveItemAction,\n  StorageServiceClearAction,\n} from '@metamask/storage-service';\nimport type {\n  Json,\n  NonEmptyArray,\n  SemVerRange,\n  CaipAssetType,\n  JsonRpcRequest,\n  SemVerVersion,\n  CaipAssetTypeOrId,\n} from '@metamask/utils';\nimport {\n  isObject,\n  assert,\n  assertIsJsonRpcRequest,\n  assertStruct,\n  Duration,\n  gtRange,\n  gtVersion,\n  hasProperty,\n  inMilliseconds,\n  isNonEmptyArray,\n  satisfiesVersionRange,\n  timeSince,\n  createDeferredPromise,\n} from '@metamask/utils';\nimport type { StateMachine } from '@xstate/fsm';\nimport { createMachine, interpret } from '@xstate/fsm';\nimport { Mutex } from 'async-mutex';\nimport type { Patch } from 'immer';\nimport { nanoid } from 'nanoid';\nimport { gt, gte } from 'semver';\n\nimport {\n  ALLOWED_PERMISSIONS,\n  CLIENT_ONLY_HANDLERS,\n  DYNAMIC_PERMISSION_DEPENDENCIES,\n  INTERFACE_HANDLERS,\n  LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS,\n  METAMASK_ORIGIN,\n  STATE_DEBOUNCE_TIMEOUT,\n} from './constants';\nimport type { SnapLocation } from './location';\nimport { detectSnapLocation } from './location';\nimport type {\n  SnapRegistryControllerGetAction,\n  SnapRegistryControllerGetMetadataAction,\n  SnapRegistryControllerResolveVersionAction,\n  SnapRegistryControllerRequestUpdateAction,\n  SnapRegistryInfo,\n  SnapRegistryRequest,\n  SnapRegistryControllerRegistryUpdatedEvent,\n} from './registry';\nimport { SnapRegistryStatus } from './registry';\nimport { getRunnableSnaps } from './selectors';\nimport type { SnapControllerMethodActions } from './SnapController-method-action-types';\nimport { Timer } from './Timer';\nimport { forceStrict, validateMachine } from '../fsm';\nimport type {\n  SnapInterfaceControllerCreateInterfaceAction,\n  SnapInterfaceControllerGetInterfaceAction,\n  SnapInterfaceControllerSetInterfaceDisplayedAction,\n} from '../interface';\nimport { log } from '../logging';\nimport type {\n  ExecutionServiceEvents,\n  ExecutionServiceExecuteSnapAction,\n  ExecutionServiceHandleRpcRequestAction,\n  ExecutionServiceTerminateSnapAction,\n  SnapErrorJson,\n} from '../services';\nimport type {\n  EncryptionResult,\n  ExportableKeyEncryptor,\n  KeyDerivationOptions,\n} from '../types';\nimport {\n  debouncePersistState,\n  fetchSnap,\n  hasTimedOut,\n  permissionsDiff,\n  setDiff,\n  throttleTracking,\n  withTimeout,\n  isTrackableHandler,\n  isLocalSnapId,\n} from '../utils';\n\nexport const controllerName = 'SnapController';\n\n// This is used by the `generate-method-action-types` script.\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst MESSENGER_EXPOSED_METHODS = [\n  'init',\n  'updateRegistry',\n  'enableSnap',\n  'disableSnap',\n  'stopSnap',\n  'stopAllSnaps',\n  'isSnapRunning',\n  'hasSnap',\n  'getSnap',\n  'updateSnapState',\n  'clearSnapState',\n  'getSnapState',\n  'getSnapFile',\n  'isMinimumPlatformVersion',\n  'clearState',\n  'removeSnap',\n  'removeSnaps',\n  'disconnectOrigin',\n  'revokeDynamicSnapPermissions',\n  'getAllSnaps',\n  'getRunnableSnaps',\n  'getPermittedSnaps',\n  'installSnaps',\n  'handleRequest',\n  'setClientActive',\n] as const;\n\nexport const SNAP_APPROVAL_INSTALL = 'wallet_installSnap';\nexport const SNAP_APPROVAL_UPDATE = 'wallet_updateSnap';\nexport const SNAP_APPROVAL_RESULT = 'wallet_installSnapResult';\n\nconst TRUNCATED_SNAP_PROPERTIES = new Set<TruncatedSnapFields>([\n  'initialPermissions',\n  'id',\n  'version',\n  'enabled',\n  'blocked',\n]);\n\nexport type PendingRequest = {\n  requestId: unknown;\n  timer: Timer;\n};\n\nexport type PreinstalledSnapFile = {\n  path: string;\n  value: string | Uint8Array;\n};\n\nexport type PreinstalledSnap = {\n  snapId: SnapId;\n  manifest: SnapManifest;\n  files: PreinstalledSnapFile[];\n  removable?: boolean;\n  hidden?: boolean;\n  hideSnapBranding?: boolean;\n};\n\n/**\n * A wrapper type for any data stored during runtime of Snaps.\n * It is not persisted in state as it contains non-serializable data and is only relevant for the\n * current session.\n */\nexport type SnapRuntimeData = {\n  /**\n   * A promise that resolves when the Snap has finished installing\n   */\n  installPromise: null | Promise<PersistedSnap>;\n\n  /**\n   * A promise that resolves when the Snap has finished booting\n   */\n  startPromise: null | Promise<void>;\n\n  /**\n   * A promise that resolves when the Snap has finished stopping\n   */\n  stopPromise: null | Promise<void>;\n\n  /**\n   * A Unix timestamp for the last time the Snap received an RPC request\n   */\n  lastRequest: null | number;\n\n  /**\n   * The current pending inbound requests, meaning requests that are processed by snaps.\n   */\n  pendingInboundRequests: PendingRequest[];\n\n  /**\n   * The current pending outbound requests, meaning requests made from snaps towards the MetaMask\n   * extension.\n   */\n  pendingOutboundRequests: number;\n\n  /**\n   * The finite state machine interpreter for possible states that the Snap can be in such as\n   * stopped, running, blocked\n   *\n   * @see {@link SnapController:constructor}\n   */\n  interpreter: StateMachine.Service<StatusContext, StatusEvents, StatusStates>;\n\n  /**\n   * Cached encryption key used for state encryption.\n   */\n  encryptionKey: string | null;\n\n  /**\n   * Cached encryption salt used for state encryption.\n   */\n  encryptionSalt: string | null;\n\n  /**\n   * Cached encrypted state of the Snap.\n   */\n  state?: Record<string, Json> | null;\n\n  /**\n   * Cached unencrypted state of the Snap.\n   */\n  unencryptedState?: Record<string, Json> | null;\n\n  /**\n   * A mutex to prevent concurrent state updates.\n   */\n  stateMutex: Mutex;\n\n  /**\n   * A mutex to prevent concurrent state decryption.\n   */\n  getStateMutex: Mutex;\n};\n\n// Types that probably should be defined elsewhere in prod\ntype StoredSnaps = Record<SnapId, Snap>;\n\nexport type SnapControllerState = {\n  snaps: StoredSnaps;\n  snapStates: Record<SnapId, string | null>;\n  unencryptedSnapStates: Record<SnapId, string | null>;\n  isReady: boolean;\n};\n\nexport type PersistedSnapControllerState = SnapControllerState & {\n  snaps: Record<SnapId, Snap>;\n  snapStates: Record<SnapId, string>;\n};\n\ntype RollbackSnapshot = {\n  statePatches: Patch[];\n  permissions: {\n    revoked?: SubjectPermissions<ValidPermission<string, Caveat<string, any>>>;\n    granted?: RequestedPermissions;\n    requestData?: Record<string, unknown>;\n  };\n  previousSourceCode?: string;\n  previousInitialConnections?: Record<string, EmptyObject> | null;\n  newInitialConnections?: Record<string, EmptyObject>;\n  newVersion: string;\n};\n\ntype PendingApproval = {\n  id: string;\n  promise: Promise<unknown>;\n};\n\n// Controller Messenger Actions\n\nexport type SnapControllerGetStateAction = ControllerGetStateAction<\n  typeof controllerName,\n  SnapControllerState\n>;\n\nexport type SnapControllerActions =\n  | SnapControllerGetStateAction\n  | SnapControllerMethodActions;\n\n// Controller Messenger Events\n\n/**\n * Emitted when an installed snap has been blocked.\n */\nexport type SnapControllerSnapBlockedEvent = {\n  type: `${typeof controllerName}:snapBlocked`;\n  payload: [snapId: string, blockedSnapInfo?: BlockReason];\n};\n\n/**\n * Emitted when a snap installation or update is started.\n */\nexport type SnapControllerSnapInstallStartedEvent = {\n  type: `${typeof controllerName}:snapInstallStarted`;\n  payload: [snapId: SnapId, origin: string, isUpdate: boolean];\n};\n\n/**\n * Emitted when a snap installation or update failed.\n */\nexport type SnapControllerSnapInstallFailedEvent = {\n  type: `${typeof controllerName}:snapInstallFailed`;\n  payload: [snapId: SnapId, origin: string, isUpdate: boolean, error: string];\n};\n\n/**\n * Emitted when a snap has been started after being added and authorized during\n * installation.\n */\nexport type SnapControllerSnapInstalledEvent = {\n  type: `${typeof controllerName}:snapInstalled`;\n  payload: [snap: TruncatedSnap, origin: string, preinstalled: boolean];\n};\n\n/**\n * Emitted when a snap that has previously been fully installed, is uninstalled.\n */\nexport type SnapControllerSnapUninstalledEvent = {\n  type: `${typeof controllerName}:snapUninstalled`;\n  payload: [snap: TruncatedSnap];\n};\n\n/**\n * Emitted when an installed snap has been unblocked.\n */\nexport type SnapControllerSnapUnblockedEvent = {\n  type: `${typeof controllerName}:snapUnblocked`;\n  payload: [snapId: string];\n};\n\n/**\n * Emitted when a snap is updated.\n */\nexport type SnapControllerSnapUpdatedEvent = {\n  type: `${typeof controllerName}:snapUpdated`;\n  payload: [\n    snap: TruncatedSnap,\n    oldVersion: string,\n    origin: string,\n    preinstalled: boolean,\n  ];\n};\n\n/**\n * Emitted when a snap is rolled back.\n */\nexport type SnapControllerSnapRolledbackEvent = {\n  type: `${typeof controllerName}:snapRolledback`;\n  payload: [snap: TruncatedSnap, failedVersion: string];\n};\n\n/**\n * Emitted when a Snap is terminated. This is different from the snap being\n * stopped as it can also be triggered when a snap fails initialization.\n */\nexport type SnapControllerSnapTerminatedEvent = {\n  type: `${typeof controllerName}:snapTerminated`;\n  payload: [snap: TruncatedSnap];\n};\n\n/**\n * Emitted when a Snap is enabled by a user.\n * This is not emitted by default when installing a snap.\n */\nexport type SnapControllerSnapEnabledEvent = {\n  type: `${typeof controllerName}:snapEnabled`;\n  payload: [snap: TruncatedSnap];\n};\n\n/**\n * Emitted when a Snap is disabled by a user.\n */\nexport type SnapControllerSnapDisabledEvent = {\n  type: `${typeof controllerName}:snapDisabled`;\n  payload: [snap: TruncatedSnap];\n};\n\n/**\n * Emitted when there is a state change.\n */\nexport type SnapControllerStateChangeEvent = ControllerStateChangeEvent<\n  typeof controllerName,\n  SnapControllerState\n>;\n\ntype KeyringControllerLockEvent = {\n  type: 'KeyringController:lock';\n  payload: [];\n};\n\nexport type SnapControllerEvents =\n  | SnapControllerSnapBlockedEvent\n  | SnapControllerSnapInstalledEvent\n  | SnapControllerSnapUninstalledEvent\n  | SnapControllerSnapInstallStartedEvent\n  | SnapControllerSnapInstallFailedEvent\n  | SnapControllerSnapUnblockedEvent\n  | SnapControllerSnapUpdatedEvent\n  | SnapControllerSnapRolledbackEvent\n  | SnapControllerSnapTerminatedEvent\n  | SnapControllerSnapEnabledEvent\n  | SnapControllerSnapDisabledEvent\n  | SnapControllerStateChangeEvent;\n\ntype AllowedActions =\n  | PermissionControllerGetEndowmentsAction\n  | PermissionControllerGetPermissionsAction\n  | PermissionControllerGetSubjectNamesAction\n  | SubjectMetadataControllerGetSubjectMetadataAction\n  | SubjectMetadataControllerAddSubjectMetadataAction\n  | PermissionControllerHasPermissionAction\n  | PermissionControllerHasPermissionsAction\n  | PermissionControllerRevokePermissionsAction\n  | PermissionControllerRevokeAllPermissionsAction\n  | PermissionControllerRevokePermissionForAllSubjectsAction\n  | PermissionControllerGrantPermissionsAction\n  | PermissionControllerUpdateCaveatAction\n  | ApprovalControllerAddRequestAction\n  | ExecutionServiceHandleRpcRequestAction\n  | ExecutionServiceExecuteSnapAction\n  | ExecutionServiceTerminateSnapAction\n  | ApprovalControllerUpdateRequestStateAction\n  | SnapRegistryControllerGetAction\n  | SnapRegistryControllerGetMetadataAction\n  | SnapRegistryControllerResolveVersionAction\n  | SnapRegistryControllerRequestUpdateAction\n  | SnapInterfaceControllerCreateInterfaceAction\n  | SnapInterfaceControllerGetInterfaceAction\n  | SnapInterfaceControllerSetInterfaceDisplayedAction\n  | StorageServiceSetItemAction\n  | StorageServiceGetItemAction\n  | StorageServiceRemoveItemAction\n  | StorageServiceClearAction;\n\ntype AllowedEvents =\n  | ExecutionServiceEvents\n  | SnapControllerSnapInstalledEvent\n  | SnapControllerSnapUpdatedEvent\n  | KeyringControllerLockEvent\n  | SnapRegistryControllerRegistryUpdatedEvent;\n\nexport type SnapControllerMessenger = Messenger<\n  typeof controllerName,\n  SnapControllerActions | AllowedActions,\n  SnapControllerEvents | AllowedEvents\n>;\n\ntype FeatureFlags = {\n  requireAllowlist?: boolean;\n  allowLocalSnaps?: boolean;\n  disableSnapInstallation?: boolean;\n  rejectInvalidPlatformVersion?: boolean;\n\n  /**\n   * Force any local Snap to be treated as a preinstalled Snap.\n   *\n   * This should only be used for local testing, and should not be enabled in\n   * any production builds (including beta and Flask).\n   */\n  forcePreinstalledSnaps?: boolean;\n\n  /**\n   * Automatically update preinstalled Snaps \"over the air\",\n   * when a new version of the Snap is added to the registry.\n   */\n  autoUpdatePreinstalledSnaps?: boolean;\n};\n\ntype DynamicFeatureFlags = {\n  disableSnaps?: boolean;\n};\n\nexport type SnapControllerArgs = {\n  /**\n   * A list of permissions that are allowed to be dynamic, meaning they can be revoked from the snap whenever.\n   */\n  dynamicPermissions?: string[];\n\n  /**\n   * The names of endowment permissions whose values are the names of JavaScript\n   * APIs that will be added to the snap execution environment at runtime.\n   */\n  environmentEndowmentPermissions?: string[];\n\n  /**\n   * Excluded permissions with its associated error message used to forbid certain permissions.\n   */\n  excludedPermissions?: Record<string, string>;\n\n  /**\n   * The function that will be used by the controller fo make network requests.\n   * Should be compatible with {@link fetch}.\n   */\n  fetchFunction?: typeof fetch;\n\n  /**\n   * Flags that enable or disable features in the controller.\n   * See {@link FeatureFlags}.\n   */\n  featureFlags: FeatureFlags;\n\n  /**\n   * How frequently to check whether a snap is idle.\n   */\n  idleTimeCheckInterval?: number;\n\n  /**\n   * The maximum amount of time that a snap may be idle.\n   */\n  maxIdleTime?: number;\n\n  /**\n   * The controller messenger.\n   */\n  messenger: SnapControllerMessenger;\n\n  /**\n   * The maximum amount of time a snap may take to process an RPC request,\n   * unless it is permitted to take longer.\n   */\n  maxRequestTime?: number;\n\n  /**\n   * The npm registry URL that will be used to fetch published snaps.\n   */\n  npmRegistryUrl?: string;\n\n  /**\n   * Persisted state that will be used for rehydration.\n   */\n  state?: PersistedSnapControllerState;\n\n  /**\n   * A function that takes Snap Id and converts it into a class that fetches files.\n   *\n   * Used for test overrides.\n   */\n  detectSnapLocation?: typeof detectSnapLocation;\n\n  /**\n   * A list of snaps to be preinstalled into the SnapController state on initialization.\n   */\n  preinstalledSnaps?: PreinstalledSnap[] | null;\n\n  /**\n   * A utility object containing functions required for state encryption.\n   */\n  encryptor: ExportableKeyEncryptor;\n\n  /**\n   * A hook to access the mnemonic seed of the user's primary keyring.\n   *\n   * @returns The mnemonic seed as bytes.\n   */\n  getMnemonicSeed: () => Promise<Uint8Array>;\n\n  /**\n   * A hook to get dynamic feature flags at runtime.\n   *\n   * @returns The feature flags.\n   */\n  getFeatureFlags: () => DynamicFeatureFlags;\n\n  /**\n   * The cryptographic functions to use for the client. This may be an empty\n   * object to fall back to the default cryptographic functions.\n   */\n  clientCryptography?: CryptographicFunctions;\n\n  /**\n   * MetaMetrics event tracking hook.\n   */\n  trackEvent: TrackEventHook;\n\n  /**\n   * A hook that returns a promise that resolves when the onboarding has completed.\n   *\n   * @returns A promise that resolves when onboarding is complete.\n   */\n  ensureOnboardingComplete: () => Promise<void>;\n};\n\ntype AddSnapArgs = {\n  id: SnapId;\n  origin: string;\n  location: SnapLocation;\n  versionRange: SemVerRange;\n};\n\n// When we set a snap, we need all required properties to be present and\n// validated.\ntype SetSnapArgs = Omit<AddSnapArgs, 'location' | 'versionRange'> & {\n  files: FetchedSnapFiles;\n  isUpdate?: boolean;\n  removable?: boolean;\n  preinstalled?: boolean;\n  hidden?: boolean;\n  hideSnapBranding?: boolean;\n};\n\ntype TrackingEventPayload = {\n  event: string;\n  category: string;\n  properties: Record<string, Json | undefined>;\n};\n\ntype TrackEventHook = (event: TrackingEventPayload) => void;\n\nconst defaultState: SnapControllerState = {\n  snaps: {},\n  snapStates: {},\n  unencryptedSnapStates: {},\n  isReady: false,\n};\n\n/**\n * Truncates the properties of a snap to only ones that are easily serializable.\n *\n * @param snap - The snap to truncate.\n * @returns Object with serializable snap properties.\n */\nfunction truncateSnap(snap: Snap): TruncatedSnap {\n  const truncatedSnap = Object.keys(snap).reduce<Partial<TruncatedSnap>>(\n    (serialized, key) => {\n      if (TRUNCATED_SNAP_PROPERTIES.has(key as any)) {\n        serialized[key as keyof TruncatedSnap] = snap[\n          key as keyof TruncatedSnap\n        ] as any;\n      }\n\n      return serialized;\n    },\n    {},\n  );\n\n  return truncatedSnap as TruncatedSnap;\n}\n\n/*\n * A snap is initialized in three phases:\n * - Add: Loads the snap from a remote source and parses it.\n * - Authorize: Requests the snap's required permissions from the user.\n * - Start: Initializes the snap in its SES realm with the authorized permissions.\n */\n\nexport class SnapController extends BaseController<\n  typeof controllerName,\n  SnapControllerState,\n  SnapControllerMessenger\n> {\n  readonly #dynamicPermissions: string[];\n\n  readonly #environmentEndowmentPermissions: string[];\n\n  readonly #excludedPermissions: Record<string, string>;\n\n  readonly #featureFlags: FeatureFlags;\n\n  readonly #fetchFunction: typeof fetch;\n\n  readonly #idleTimeCheckInterval: number;\n\n  readonly #maxIdleTime: number;\n\n  // This property cannot be hash private yet because of tests.\n  // eslint-disable-next-line no-restricted-syntax\n  private readonly maxRequestTime: number;\n\n  readonly #encryptor: ExportableKeyEncryptor;\n\n  readonly #getMnemonicSeed: () => Promise<Uint8Array>;\n\n  readonly #getFeatureFlags: () => DynamicFeatureFlags;\n\n  readonly #clientCryptography: CryptographicFunctions | undefined;\n\n  readonly #detectSnapLocation: typeof detectSnapLocation;\n\n  readonly #snapsRuntimeData: Map<SnapId, SnapRuntimeData>;\n\n  readonly #rollbackSnapshots: Map<string, RollbackSnapshot>;\n\n  #timeoutForLastRequestStatus?: number;\n\n  #statusMachine!: StateMachine.Machine<\n    StatusContext,\n    StatusEvents,\n    StatusStates\n  >;\n\n  readonly #preinstalledSnaps: PreinstalledSnap[] | null;\n\n  readonly #trackEvent: TrackEventHook;\n\n  readonly #trackSnapExport: ReturnType<typeof throttleTracking>;\n\n  readonly #ensureOnboardingComplete: () => Promise<void>;\n\n  // A promise that resolves when the controller has finished setting up.\n  // This is used to ensure that the controller is ready to be used.\n  // It is resolved when the controller has finished setting up and the platform is ready.\n  // It is rejected if there is an error during setup.\n  #controllerSetup = createDeferredPromise();\n\n  constructor({\n    messenger,\n    state,\n    dynamicPermissions = ['endowment:caip25', 'wallet_snap'],\n    environmentEndowmentPermissions = [],\n    excludedPermissions = {},\n    idleTimeCheckInterval = inMilliseconds(5, Duration.Second),\n    maxIdleTime = inMilliseconds(30, Duration.Second),\n    maxRequestTime = inMilliseconds(60, Duration.Second),\n    fetchFunction = globalThis.fetch.bind(undefined),\n    featureFlags = {},\n    detectSnapLocation: detectSnapLocationFunction = detectSnapLocation,\n    preinstalledSnaps = null,\n    encryptor,\n    getMnemonicSeed,\n    getFeatureFlags = () => ({}),\n    clientCryptography,\n    trackEvent,\n    ensureOnboardingComplete,\n  }: SnapControllerArgs) {\n    super({\n      messenger,\n      metadata: {\n        isReady: {\n          includeInStateLogs: true,\n          includeInDebugSnapshot: true,\n          persist: false,\n          usedInUi: false,\n        },\n        snapStates: {\n          includeInStateLogs: false,\n          persist: true,\n          includeInDebugSnapshot: false,\n          usedInUi: false,\n        },\n        unencryptedSnapStates: {\n          includeInStateLogs: false,\n          persist: true,\n          includeInDebugSnapshot: false,\n          usedInUi: false,\n        },\n        snaps: {\n          includeInStateLogs: (snaps) => {\n            // Delete larger snap properties\n            return Object.values(snaps).reduce<Record<SnapId, Partial<Snap>>>(\n              (acc, snap) => {\n                const snapCopy: Partial<Snap> = { ...snap };\n                delete snapCopy.auxiliaryFiles;\n                acc[snap.id] = snapCopy;\n                return acc;\n              },\n              {},\n            );\n          },\n          persist: (snaps) => {\n            return (\n              Object.values(snaps)\n                // We should not persist snaps that are in the installing state,\n                // since they haven't completed installation and would be unusable\n                .filter((snap) => snap.status !== SnapStatus.Installing)\n                .map((snap) => {\n                  return {\n                    ...snap,\n                    // At the time state is rehydrated, no snap will be running.\n                    status: SnapStatus.Stopped,\n                  };\n                })\n                .reduce((memo: Record<SnapId, Snap>, snap) => {\n                  memo[snap.id] = snap;\n                  return memo;\n                }, {})\n            );\n          },\n          includeInDebugSnapshot: false,\n          // TODO: Ensure larger snap properties are not sent to the UI\n          // Currently these are stripped out manually in the extension\n          usedInUi: true,\n        },\n      },\n      name: controllerName,\n      state: {\n        ...defaultState,\n        ...state,\n      },\n    });\n\n    this.#dynamicPermissions = dynamicPermissions;\n    this.#environmentEndowmentPermissions = environmentEndowmentPermissions;\n    this.#excludedPermissions = excludedPermissions;\n    this.#featureFlags = featureFlags;\n    this.#fetchFunction = fetchFunction;\n    this.#idleTimeCheckInterval = idleTimeCheckInterval;\n    this.#maxIdleTime = maxIdleTime;\n    this.maxRequestTime = maxRequestTime;\n    this.#detectSnapLocation = detectSnapLocationFunction;\n    this.#encryptor = encryptor;\n    this.#getMnemonicSeed = getMnemonicSeed;\n    this.#getFeatureFlags = getFeatureFlags;\n    this.#clientCryptography = clientCryptography;\n    this.#preinstalledSnaps = preinstalledSnaps;\n    this._onUnhandledSnapError = this._onUnhandledSnapError.bind(this);\n    this._onOutboundRequest = this._onOutboundRequest.bind(this);\n    this._onOutboundResponse = this._onOutboundResponse.bind(this);\n    this.#rollbackSnapshots = new Map();\n    this.#snapsRuntimeData = new Map();\n    this.#trackEvent = trackEvent;\n    this.#ensureOnboardingComplete = ensureOnboardingComplete;\n\n    this.#pollForLastRequestStatus();\n\n    /* eslint-disable @typescript-eslint/unbound-method */\n    this.messenger.subscribe(\n      'ExecutionService:unhandledError',\n      this._onUnhandledSnapError,\n    );\n\n    this.messenger.subscribe(\n      'ExecutionService:outboundRequest',\n      this._onOutboundRequest,\n    );\n\n    this.messenger.subscribe(\n      'ExecutionService:outboundResponse',\n      this._onOutboundResponse,\n    );\n    /* eslint-enable @typescript-eslint/unbound-method */\n\n    this.messenger.subscribe(\n      'SnapController:snapInstalled',\n      ({ id }, origin) => {\n        this.#callLifecycleHook(origin, id, HandlerType.OnInstall).catch(\n          (error) => {\n            logError(\n              `Error when calling \\`onInstall\\` lifecycle hook for snap \"${id}\": ${getErrorMessage(\n                error,\n              )}`,\n            );\n          },\n        );\n      },\n    );\n\n    this.messenger.subscribe(\n      'SnapController:snapUpdated',\n      ({ id }, _oldVersion, origin) => {\n        this.#callLifecycleHook(origin, id, HandlerType.OnUpdate).catch(\n          (error) => {\n            logError(\n              `Error when calling \\`onUpdate\\` lifecycle hook for snap \"${id}\": ${getErrorMessage(\n                error,\n              )}`,\n            );\n          },\n        );\n      },\n    );\n\n    this.messenger.subscribe(\n      'KeyringController:lock',\n      this.#handleLock.bind(this),\n    );\n\n    this.messenger.subscribe('SnapRegistryController:registryUpdated', () => {\n      this.#handleRegistryUpdate().catch((error) => {\n        logError(\n          `Error when processing Snaps registry update: ${getErrorMessage(\n            error,\n          )}`,\n        );\n      });\n    });\n\n    this.#initializeStateMachine();\n    this.#registerMessageHandlers();\n\n    Object.values(this.state?.snaps ?? {}).forEach((snap) =>\n      this.#setupRuntime(snap.id),\n    );\n\n    this.#trackSnapExport = throttleTracking(\n      (snapId: SnapId, handler: string, success: boolean, origin: string) => {\n        const snapMetadata = this.messenger.call(\n          'SnapRegistryController:getMetadata',\n          snapId,\n        );\n        this.#trackEvent({\n          event: 'Snap Export Used',\n          category: 'Snaps',\n          properties: {\n            // eslint-disable-next-line @typescript-eslint/naming-convention\n            snap_id: snapId,\n            export: handler,\n            // eslint-disable-next-line @typescript-eslint/naming-convention\n            snap_category: snapMetadata?.category,\n            success,\n            origin,\n          },\n        });\n      },\n    );\n  }\n\n  /**\n   * We track status of a Snap using a finite-state-machine.\n   * It keeps track of whether the snap is started / stopped / etc.\n   *\n   * @see {@link SnapController.transition} for interacting with the machine.\n   */\n  // We initialize the machine in the instance because the status is currently tightly coupled\n  // with the SnapController - the guard checks for enabled status inside the SnapController state.\n  // In the future, side-effects could be added to the machine during transitions.\n  #initializeStateMachine() {\n    const disableGuard = ({ snapId }: StatusContext) => {\n      return this.getSnapExpect(snapId).enabled;\n    };\n\n    const statusConfig: StateMachine.Config<\n      StatusContext,\n      StatusEvents,\n      StatusStates\n    > = {\n      initial: SnapStatus.Installing,\n      states: {\n        [SnapStatus.Installing]: {\n          on: {\n            [SnapStatusEvents.Start]: {\n              target: SnapStatus.Running,\n              cond: disableGuard,\n            },\n          },\n        },\n        [SnapStatus.Updating]: {\n          on: {\n            [SnapStatusEvents.Start]: {\n              target: SnapStatus.Running,\n              cond: disableGuard,\n            },\n            [SnapStatusEvents.Stop]: SnapStatus.Stopped,\n          },\n        },\n        [SnapStatus.Running]: {\n          on: {\n            [SnapStatusEvents.Stop]: SnapStatus.Stopped,\n            [SnapStatusEvents.Crash]: SnapStatus.Crashed,\n          },\n        },\n        [SnapStatus.Stopped]: {\n          on: {\n            [SnapStatusEvents.Start]: {\n              target: SnapStatus.Running,\n              cond: disableGuard,\n            },\n            [SnapStatusEvents.Update]: SnapStatus.Updating,\n          },\n        },\n        [SnapStatus.Crashed]: {\n          on: {\n            [SnapStatusEvents.Start]: {\n              target: SnapStatus.Running,\n              cond: disableGuard,\n            },\n            [SnapStatusEvents.Update]: SnapStatus.Updating,\n          },\n        },\n      },\n    };\n    this.#statusMachine = createMachine(statusConfig);\n    validateMachine(this.#statusMachine);\n  }\n\n  /**\n   * Constructor helper for registering the controller's messaging system\n   * actions.\n   */\n  #registerMessageHandlers(): void {\n    this.messenger.registerActionHandler(\n      `${controllerName}:init`,\n      async (...args) => this.init(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:clearSnapState`,\n      (...args) => this.clearSnapState(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getSnap`,\n      (...args) => this.getSnap(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getSnapState`,\n      async (...args) => this.getSnapState(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:handleRequest`,\n      async (...args) => this.handleRequest(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:hasSnap`,\n      (...args) => this.hasSnap(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:updateRegistry`,\n      async () => this.updateRegistry(),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:updateSnapState`,\n      async (...args) => this.updateSnapState(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:enableSnap`,\n      (...args) => this.enableSnap(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:disableSnap`,\n      async (...args) => this.disableSnap(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:removeSnap`,\n      async (...args) => this.removeSnap(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getPermittedSnaps`,\n      (...args) => this.getPermittedSnaps(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:installSnaps`,\n      async (...args) => this.installSnaps(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getAllSnaps`,\n      (...args) => this.getAllSnaps(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getRunnableSnaps`,\n      (...args) => this.getRunnableSnaps(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:disconnectOrigin`,\n      (...args) => this.disconnectOrigin(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:revokeDynamicSnapPermissions`,\n      (...args) => this.revokeDynamicSnapPermissions(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:getSnapFile`,\n      async (...args) => this.getSnapFile(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:stopAllSnaps`,\n      async (...args) => this.stopAllSnaps(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:isMinimumPlatformVersion`,\n      (...args) => this.isMinimumPlatformVersion(...args),\n    );\n\n    this.messenger.registerActionHandler(\n      `${controllerName}:setClientActive`,\n      (...args) => this.setClientActive(...args),\n    );\n  }\n\n  /**\n   * Initialise the SnapController.\n   *\n   * Currently this method sets up the controller and calls the `onStart` lifecycle hook for all\n   * runnable Snaps.\n   *\n   * @param waitForPlatform - Whether to wait for the platform to be ready before returning.\n   */\n  async init(waitForPlatform = true) {\n    try {\n      if (this.#preinstalledSnaps) {\n        await this.#handlePreinstalledSnaps(this.#preinstalledSnaps);\n      }\n\n      this.#controllerSetup.resolve();\n\n      // Populate the `isReady` state.\n      if (waitForPlatform) {\n        await this.#ensureCanUsePlatform();\n      } else {\n        this.#ensureCanUsePlatform().catch(logError);\n      }\n\n      this.#callLifecycleHooks(METAMASK_ORIGIN, HandlerType.OnStart);\n    } catch (error) {\n      this.#controllerSetup.reject(error);\n      logWarning('Error during SnapController initialization.', error);\n    }\n  }\n\n  async #handlePreinstalledSnaps(preinstalledSnaps: PreinstalledSnap[]) {\n    for (const {\n      snapId,\n      manifest,\n      files,\n      removable,\n      hidden,\n      hideSnapBranding,\n    } of preinstalledSnaps) {\n      const existingSnap = this.getSnap(snapId);\n      const isAlreadyInstalled = existingSnap !== null;\n      const isUpdate =\n        isAlreadyInstalled && gtVersion(manifest.version, existingSnap.version);\n      const isPreinstalled = existingSnap?.preinstalled === true;\n      const isMissingSource =\n        isAlreadyInstalled &&\n        isPreinstalled &&\n        !(await this.#hasSourceCode(snapId));\n\n      // Disallow downgrades and overwriting non preinstalled snaps\n      // As a mitigation for state corruption on mobile, if the source code is missing\n      // we allow overwriting and potentially downgrading the current version of the preinstalled Snap.\n      if (\n        isAlreadyInstalled &&\n        !isMissingSource &&\n        (!isUpdate || !isPreinstalled)\n      ) {\n        continue;\n      }\n\n      const manifestFile = new VirtualFile<SnapManifest>({\n        path: NpmSnapFileNames.Manifest,\n        value: JSON.stringify(manifest),\n        result: manifest,\n      });\n\n      const virtualFiles = files.map(\n        ({ path, value }) => new VirtualFile({ value, path }),\n      );\n      const { filePath, iconPath } = manifest.source.location.npm;\n      const sourceCode = virtualFiles.find((file) => file.path === filePath);\n      const svgIcon = iconPath\n        ? virtualFiles.find((file) => file.path === iconPath)\n        : undefined;\n\n      assert(sourceCode, 'Source code not provided for preinstalled snap.');\n\n      assert(\n        !iconPath || (iconPath && svgIcon),\n        'Icon not provided for preinstalled snap.',\n      );\n\n      assert(\n        manifest.source.files === undefined,\n        'Auxiliary files are not currently supported for preinstalled snaps.',\n      );\n\n      const localizationFiles =\n        manifest.source.locales?.map((path) =>\n          virtualFiles.find((file) => file.path === path),\n        ) ?? [];\n\n      const validatedLocalizationFiles = getValidatedLocalizationFiles(\n        localizationFiles.filter(Boolean) as VirtualFile[],\n      );\n\n      assert(\n        localizationFiles.length === validatedLocalizationFiles.length,\n        'Missing localization files for preinstalled snap.',\n      );\n\n      const filesObject: FetchedSnapFiles = {\n        manifest: manifestFile,\n        sourceCode,\n        svgIcon,\n        auxiliaryFiles: [],\n        localizationFiles: validatedLocalizationFiles,\n      };\n\n      // Add snap to the SnapController state\n      await this.#set({\n        id: snapId,\n        origin: METAMASK_ORIGIN,\n        files: filesObject,\n        removable,\n        hidden,\n        hideSnapBranding,\n        preinstalled: true,\n      });\n\n      // Setup permissions\n      const processedPermissions = processSnapPermissions(\n        manifest.initialPermissions,\n      );\n\n      this.#validateSnapPermissions(processedPermissions);\n\n      const { newPermissions, unusedPermissions } =\n        this.#calculatePermissionsChange(snapId, processedPermissions);\n\n      this.#updatePermissions({ snapId, newPermissions, unusedPermissions });\n\n      if (manifest.initialConnections) {\n        this.#handleInitialConnections(\n          snapId,\n          existingSnap?.initialConnections ?? null,\n          manifest.initialConnections,\n        );\n      }\n\n      // Set status\n      this.update((state) => {\n        state.snaps[snapId].status = SnapStatus.Stopped;\n      });\n\n      this.#setupRuntime(snapId);\n\n      // Emit events\n      if (isUpdate) {\n        this.messenger.publish(\n          'SnapController:snapUpdated',\n          this.#getTruncatedSnapExpect(snapId),\n          existingSnap.version,\n          METAMASK_ORIGIN,\n          true,\n        );\n      } else if (!isMissingSource) {\n        this.messenger.publish(\n          'SnapController:snapInstalled',\n          this.#getTruncatedSnapExpect(snapId),\n          METAMASK_ORIGIN,\n          true,\n        );\n      }\n\n      if (isMissingSource) {\n        logWarning(\n          `The source code for \"${snapId}\" was missing and has been automatically restored. If you see this message, please file a bug report.`,\n        );\n        this.messenger.captureException?.(\n          new Error(\n            `The source code for \"${snapId}\" was missing and has been automatically restored. This could indicate persistence issues.`,\n          ),\n        );\n      }\n    }\n\n    // Ensure all preinstalled Snaps have their expected permissions.\n    for (const snap of Object.values(this.state.snaps).filter(\n      ({ preinstalled }) => preinstalled,\n    )) {\n      const processedPermissions = processSnapPermissions(\n        snap.manifest.initialPermissions,\n      );\n\n      this.#validateSnapPermissions(processedPermissions);\n\n      const { newPermissions, unusedPermissions } =\n        this.#calculatePermissionsChange(snap.id, processedPermissions);\n\n      if (\n        isNonEmptyArray(Object.keys(newPermissions)) ||\n        isNonEmptyArray(Object.keys(unusedPermissions))\n      ) {\n        const { proposedName } = getLocalizedSnapManifest(\n          snap.manifest,\n          'en',\n          snap.localizationFiles ?? [],\n        );\n\n        // Recover the SVG icon from the constructor argument.\n        // Theoretically this may be out of date, but this is the best we can do.\n        const preinstalledSnap = preinstalledSnaps.find(\n          (potentialSnap) => potentialSnap.snapId === snap.id,\n        );\n        const { iconPath } = snap.manifest.source.location.npm;\n        const svgIcon =\n          iconPath && preinstalledSnap\n            ? preinstalledSnap.files.find((file) => file.path === iconPath)\n            : undefined;\n\n        // If the permissions are out of sync, it is possible that the SubjectMetadataController also is.\n        this.messenger.call('SubjectMetadataController:addSubjectMetadata', {\n          subjectType: SubjectType.Snap,\n          name: proposedName,\n          origin: snap.id,\n          version: snap.version,\n          svgIcon: svgIcon ? new VirtualFile(svgIcon).toString() : null,\n        });\n\n        this.#updatePermissions({\n          snapId: snap.id,\n          newPermissions,\n          unusedPermissions,\n        });\n        logWarning(\n          `The permissions for \"${snap.id}\" were out of sync and have been automatically restored. If you see this message, please file a bug report.`,\n        );\n        this.messenger.captureException?.(\n          new Error(\n            `The permissions for \"${snap.id}\" were out of sync and have been automatically restored. This could indicate persistence issues.`,\n          ),\n        );\n      }\n    }\n  }\n\n  #pollForLastRequestStatus() {\n    this.#timeoutForLastRequestStatus = setTimeout(() => {\n      this.#stopSnapsLastRequestPastMax().catch((error) => {\n        // TODO: Decide how to handle errors.\n        logError(error);\n      });\n\n      this.#pollForLastRequestStatus();\n    }, this.#idleTimeCheckInterval) as unknown as number;\n  }\n\n  /**\n   * Trigger an update of the registry.\n   *\n   * As a side-effect, this will _always_ check if preinstalled Snaps can be updated and whether any Snaps need to be blocked/unblocked.\n   */\n  async updateRegistry(): Promise<void> {\n    await this.#ensureCanUsePlatform();\n    await this.messenger.call('SnapRegistryController:requestUpdate');\n  }\n\n  /**\n   * Checks all installed Snaps against the blocklist and\n   * blocks/unblocks Snaps as appropriate. See {@link SnapController.blockSnap}\n   * for more information.\n   *\n   * Also updates any preinstalled Snaps to the latest allowlisted version.\n   */\n  async #handleRegistryUpdate() {\n    const blockedSnaps = await this.messenger.call(\n      'SnapRegistryController:get',\n      Object.values(this.state.snaps).reduce<SnapRegistryRequest>(\n        (blockListArg, snap) => {\n          blockListArg[snap.id] = {\n            version: snap.version,\n            checksum: snap.manifest.source.shasum,\n          };\n          return blockListArg;\n        },\n        {},\n      ),\n    );\n\n    await Promise.all(\n      Object.entries(blockedSnaps).map(async ([snapId, { status, reason }]) => {\n        if (status === SnapRegistryStatus.Blocked) {\n          return this.#blockSnap(snapId as SnapId, reason);\n        }\n\n        return this.#unblockSnap(snapId as SnapId);\n      }),\n    );\n\n    if (!this.#featureFlags.autoUpdatePreinstalledSnaps) {\n      return;\n    }\n\n    const preinstalledVersionRange = '*' as SemVerRange;\n\n    await Promise.allSettled(\n      Object.values(this.state.snaps)\n        .filter((snap) => snap.preinstalled)\n        .map(async (snap) => {\n          const resolvedVersion = await this.#resolveAllowlistVersion(\n            snap.id,\n            preinstalledVersionRange,\n          );\n\n          if (\n            resolvedVersion !== preinstalledVersionRange &&\n            gtVersion(resolvedVersion as unknown as SemVerVersion, snap.version)\n          ) {\n            const location = this.#detectSnapLocation(snap.id, {\n              versionRange: resolvedVersion,\n              fetch: this.#fetchFunction,\n              allowLocal: false,\n              useNpmProxy: true,\n            });\n\n            await this.#updateSnap({\n              origin: ORIGIN_METAMASK,\n              snapId: snap.id,\n              location,\n              versionRange: resolvedVersion,\n              automaticUpdate: true,\n            });\n          }\n        }),\n    );\n  }\n\n  /**\n   * Blocks an installed snap and prevents it from being started again. Emits\n   * {@link SnapControllerSnapBlockedEvent}. Does nothing if the snap is not installed.\n   *\n   * @param snapId - The snap to block.\n   * @param blockedSnapInfo - Information detailing why the snap is blocked.\n   */\n  async #blockSnap(\n    snapId: SnapId,\n    blockedSnapInfo?: BlockReason,\n  ): Promise<void> {\n    if (!this.hasSnap(snapId)) {\n      return;\n    }\n\n    try {\n      this.update((state: any) => {\n        state.snaps[snapId].blocked = true;\n        state.snaps[snapId].blockInformation = blockedSnapInfo;\n      });\n\n      await this.disableSnap(snapId);\n    } catch (error) {\n      logError(\n        `Encountered error when stopping blocked snap \"${snapId}\".`,\n        error,\n      );\n    }\n\n    this.messenger.publish(\n      `${controllerName}:snapBlocked`,\n      snapId,\n      blockedSnapInfo,\n    );\n  }\n\n  /**\n   * Unblocks a snap so that it can be enabled and started again. Emits\n   * {@link SnapControllerSnapUnblockedEvent}. Does nothing if the snap is not installed or already\n   * unblocked.\n   *\n   * @param snapId - The id of the snap to unblock.\n   */\n  #unblockSnap(snapId: SnapId) {\n    if (!this.hasSnap(snapId) || !this.state.snaps[snapId].blocked) {\n      return;\n    }\n\n    this.update((state: any) => {\n      state.snaps[snapId].blocked = false;\n      delete state.snaps[snapId].blockInformation;\n    });\n\n    this.messenger.publish(`${controllerName}:snapUnblocked`, snapId);\n  }\n\n  async #assertIsInstallAllowed(\n    snapId: SnapId,\n    {\n      platformVersion,\n      ...snapInfo\n    }: SnapRegistryInfo & {\n      permissions: SnapPermissions;\n      platformVersion: string | undefined;\n    },\n  ) {\n    const results = await this.messenger.call('SnapRegistryController:get', {\n      [snapId]: snapInfo,\n    });\n\n    const result = results[snapId];\n    if (result.status === SnapRegistryStatus.Blocked) {\n      throw new Error(\n        `Cannot install version \"${\n          snapInfo.version\n        }\" of snap \"${snapId}\": The version is blocked. ${\n          result.reason?.explanation ?? ''\n        }`,\n      );\n    }\n\n    const isAllowlistingRequired = Object.keys(snapInfo.permissions).some(\n      (permission) => !ALLOWED_PERMISSIONS.includes(permission),\n    );\n\n    if (\n      this.#featureFlags.requireAllowlist &&\n      isAllowlistingRequired &&\n      result.status !== SnapRegistryStatus.Verified\n    ) {\n      throw new Error(\n        `Cannot install version \"${snapInfo.version}\" of snap \"${snapId}\": ${\n          result.status === SnapRegistryStatus.Unavailable\n            ? 'The registry is temporarily unavailable.'\n            : 'The snap is not on the allowlist.'\n        }`,\n      );\n    }\n\n    this.#validatePlatformVersion(snapId, platformVersion);\n  }\n\n  /**\n   * Asserts whether new Snaps are allowed to be installed.\n   */\n  #assertCanInstallSnaps() {\n    assert(\n      this.#featureFlags.disableSnapInstallation !== true,\n      'Installing Snaps is currently disabled in this version of MetaMask.',\n    );\n  }\n\n  /**\n   * Waits for onboarding and then asserts whether the Snaps platform is allowed to run.\n   */\n  async #ensureCanUsePlatform() {\n    // Ensure the controller has finished setting up.\n    await this.#controllerSetup.promise;\n\n    // Ensure the user has onboarded before allowing access to Snaps.\n    await this.#ensureOnboardingComplete();\n\n    const flags = this.#getFeatureFlags();\n\n    // If the user has onboarded, the Snaps Platform is considered ready,\n    // if it isn't forced to be disabled via feature flags.\n    const isReady = flags.disableSnaps !== true;\n    if (this.state.isReady !== isReady) {\n      this.update((state) => {\n        state.isReady = isReady;\n      });\n    }\n\n    assert(\n      isReady,\n      'The Snaps platform requires basic functionality to be used. Enable basic functionality in the settings to use the Snaps platform.',\n    );\n  }\n\n  async #stopSnapsLastRequestPastMax() {\n    const entries = [...this.#snapsRuntimeData.entries()];\n    return Promise.all(\n      entries\n        .filter(\n          ([_snapId, runtime]) =>\n            runtime.pendingInboundRequests.length === 0 &&\n            runtime.lastRequest &&\n            this.#maxIdleTime &&\n            timeSince(runtime.lastRequest) > this.#maxIdleTime,\n        )\n        .map(async ([snapId]) => this.stopSnap(snapId, SnapStatusEvents.Stop)),\n    );\n  }\n\n  _onUnhandledSnapError(snapId: string, error: SnapErrorJson) {\n    // Log the error that caused the crash\n    // so it gets raised to the developer for debugging purposes.\n    logError(`Unhandled error from \"${snapId}\":`, error);\n    this.stopSnap(snapId as SnapId, SnapStatusEvents.Crash).catch(\n      (stopSnapError) => {\n        // TODO: Decide how to handle errors.\n        logError(stopSnapError);\n      },\n    );\n  }\n\n  _onOutboundRequest(snapId: string) {\n    const runtime = this.#getRuntimeExpect(snapId as SnapId);\n    // Ideally we would only pause the pending request that is making the outbound request\n    // but right now we don't have a way to know which request initiated the outbound request\n    runtime.pendingInboundRequests\n      .filter((pendingRequest) => pendingRequest.timer.status === 'running')\n      .forEach((pendingRequest) => pendingRequest.timer.pause());\n    runtime.pendingOutboundRequests += 1;\n  }\n\n  _onOutboundResponse(snapId: string) {\n    const runtime = this.#getRuntimeExpect(snapId as SnapId);\n    runtime.pendingOutboundRequests -= 1;\n    if (runtime.pendingOutboundRequests === 0) {\n      runtime.pendingInboundRequests\n        .filter((pendingRequest) => pendingRequest.timer.status === 'paused')\n        .forEach((pendingRequest) => pendingRequest.timer.resume());\n    }\n  }\n\n  /**\n   * Transitions between states using `snapStatusStateMachineConfig` as the template to figure out\n   * the next state. This transition function uses a very minimal subset of XState conventions:\n   * - supports initial state\n   * - .on supports raw event target string\n   * - .on supports {target, cond} object\n   * - the arguments for `cond` is the `SerializedSnap` instead of Xstate convention of `(event,\n   * context) => boolean`\n   *\n   * @param snapId - The id of the snap to transition.\n   * @param event - The event enum to use to transition.\n   */\n  #transition(snapId: SnapId, event: StatusEvents | StatusEvents['type']) {\n    const { interpreter } = this.#getRuntimeExpect(snapId);\n    interpreter.send(event);\n    this.update((state: any) => {\n      state.snaps[snapId].status = interpreter.state.value;\n    });\n  }\n\n  /**\n   * Starts the given snap. Throws an error if no such snap exists\n   * or if it is already running.\n   *\n   * @param snapId - The id of the Snap to start.\n   */\n  async startSnap(snapId: SnapId): Promise<void> {\n    await this.#ensureCanUsePlatform();\n    const snap = this.state.snaps[snapId];\n\n    if (!snap.enabled) {\n      throw new Error(`Snap \"${snapId}\" is disabled.`);\n    }\n\n    const sourceCode = await this.#getSourceCode(snapId);\n\n    await this.#startSnap({\n      snapId,\n      sourceCode,\n    });\n  }\n\n  /**\n   * Enables the given snap. A snap can only be started if it is enabled. A snap\n   * can only be enabled if it isn't blocked.\n   *\n   * @param snapId - The id of the Snap to enable.\n   */\n  enableSnap(snapId: SnapId): void {\n    this.getSnapExpect(snapId);\n\n    if (this.state.snaps[snapId].blocked) {\n      throw new Error(`Snap \"${snapId}\" is blocked and cannot be enabled.`);\n    }\n\n    this.update((state: any) => {\n      state.snaps[snapId].enabled = true;\n    });\n\n    this.messenger.publish(\n      'SnapController:snapEnabled',\n      this.#getTruncatedSnapExpect(snapId),\n    );\n  }\n\n  /**\n   * Disables the given snap. A snap can only be started if it is enabled.\n   *\n   * @param snapId - The id of the Snap to disable.\n   * @returns A promise that resolves once the snap has been disabled.\n   */\n  async disableSnap(snapId: SnapId): Promise<void> {\n    if (!this.hasSnap(snapId)) {\n      throw new Error(`Snap \"${snapId}\" not found.`);\n    }\n\n    this.update((state: any) => {\n      state.snaps[snapId].enabled = false;\n    });\n\n    if (this.isSnapRunning(snapId)) {\n      await this.stopSnap(snapId, SnapStatusEvents.Stop);\n    }\n\n    this.messenger.publish(\n      'SnapController:snapDisabled',\n      this.#getTruncatedSnapExpect(snapId),\n    );\n  }\n\n  /**\n   * Stops the given snap, removes all hooks, closes all connections, and\n   * terminates its worker.\n   *\n   * @param snapId - The id of the Snap to stop.\n   * @param statusEvent - The Snap status event that caused the snap to be\n   * stopped.\n   */\n  public async stopSnap(\n    snapId: SnapId,\n    statusEvent:\n      | SnapStatusEvents.Stop\n      | SnapStatusEvents.Crash = SnapStatusEvents.Stop,\n  ): Promise<void> {\n    const runtime = this.#getRuntime(snapId);\n    if (!runtime) {\n      throw new Error(`The snap \"${snapId}\" is not running.`);\n    }\n\n    // If we are already stopping, wait for that to finish.\n    if (runtime.stopPromise) {\n      await runtime.stopPromise;\n      return;\n    }\n\n    // Flag that the Snap is actively stopping, this prevents other calls to stopSnap\n    // while we are handling termination of the Snap\n    const { promise, resolve } = createDeferredPromise();\n    runtime.stopPromise = promise;\n\n    try {\n      if (this.isSnapRunning(snapId)) {\n        await this.#terminateSnap(snapId);\n      }\n    } finally {\n      // Reset request tracking\n      runtime.lastRequest = null;\n      runtime.pendingInboundRequests = [];\n      runtime.pendingOutboundRequests = 0;\n      runtime.stopPromise = null;\n      if (this.isSnapRunning(snapId)) {\n        this.#transition(snapId, statusEvent);\n      }\n      resolve();\n    }\n  }\n\n  /**\n   * Stops all running snaps, removes all hooks, closes all connections, and\n   * terminates their workers.\n   *\n   * @param statusEvent - The Snap status event that caused the snap to be\n   * stopped.\n   */\n  public async stopAllSnaps(\n    statusEvent:\n      | SnapStatusEvents.Stop\n      | SnapStatusEvents.Crash = SnapStatusEvents.Stop,\n  ): Promise<void> {\n    const snaps = Object.values(this.state.snaps).filter((snap) =>\n      this.isSnapRunning(snap.id),\n    );\n    const promises = snaps.map(async (snap) =>\n      this.stopSnap(snap.id, statusEvent),\n    );\n    await Promise.allSettled(promises);\n  }\n\n  /**\n   * Terminates the specified snap and emits the `snapTerminated` event.\n   *\n   * @param snapId - The snap to terminate.\n   */\n  async #terminateSnap(snapId: SnapId) {\n    await this.messenger.call('ExecutionService:terminateSnap', snapId);\n\n    // Hack to give up execution for a bit to let gracefully terminating Snaps return.\n    await new Promise((resolve) => setTimeout(resolve, 1));\n\n    const runtime = this.#getRuntimeExpect(snapId);\n    // Unresponsive requests may still be timed, time them out.\n    runtime.pendingInboundRequests\n      .filter((pendingRequest) => pendingRequest.timer.status !== 'finished')\n      .forEach((pendingRequest) => pendingRequest.timer.finish());\n\n    // Hack to give up execution for a bit to let timed out requests return.\n    await new Promise((resolve) => setTimeout(resolve, 1));\n\n    this.messenger.publish(\n      'SnapController:snapTerminated',\n      this.#getTruncatedSnapExpect(snapId),\n    );\n  }\n\n  /**\n   * Returns whether the given snap is running.\n   * Throws an error if the snap doesn't exist.\n   *\n   * @param snapId - The id of the Snap to check.\n   * @returns `true` if the snap is running, otherwise `false`.\n   */\n  isSnapRunning(snapId: SnapId): boolean {\n    return this.getSnapExpect(snapId).status === 'running';\n  }\n\n  /**\n   * Returns whether the given snap has been added to state.\n   *\n   * @param snapId - The id of the Snap to check for.\n   * @returns `true` if the snap exists in the controller state, otherwise `false`.\n   */\n  hasSnap(snapId: SnapId): boolean {\n    return Boolean(this.getSnap(snapId));\n  }\n\n  /**\n   * Gets the snap with the given id if it exists, including all data.\n   * This should not be used if the snap is to be serializable, as e.g.\n   * the snap sourceCode may be quite large.\n   *\n   * @param snapId - The id of the Snap to get.\n   * @returns The entire snap object from the controller state.\n   */\n  getSnap(snapId: string): Snap | null {\n    return this.state.snaps[snapId as SnapId] ?? null;\n  }\n\n  /**\n   * Gets the snap with the given id, throws if doesn't.\n   * This should not be used if the snap is to be serializable, as e.g.\n   * the snap sourceCode may be quite large.\n   *\n   * @see {@link SnapController.getSnap}\n   * @throws {@link Error}. If the snap doesn't exist\n   * @param snapId - The id of the snap to get.\n   * @returns The entire snap object.\n   */\n  getSnapExpect(snapId: SnapId): Snap {\n    const snap = this.getSnap(snapId);\n    assert(snap !== null, `Snap \"${snapId}\" not found.`);\n    return snap;\n  }\n\n  /**\n   * Gets the snap with the given id if it exists, excluding any\n   * non-serializable or expensive-to-serialize data.\n   *\n   * @param snapId - The id of the Snap to get.\n   * @returns A truncated version of the snap state, that is less expensive to serialize.\n   */\n  #getTruncatedSnap(snapId: SnapId): TruncatedSnap | null {\n    const snap = this.getSnap(snapId);\n\n    return snap ? truncateSnap(snap) : null;\n  }\n\n  /**\n   * Gets the snap with the given id, throw if it doesn't exist.\n   *\n   * @throws {@link Error}. If snap doesn't exist\n   * @param snapId - The id of the snap to get.\n   * @returns A truncated version of the snap state, that is less expensive to serialize.\n   */\n  #getTruncatedSnapExpect(snapId: SnapId): TruncatedSnap {\n    return truncateSnap(this.getSnapExpect(snapId));\n  }\n\n  /**\n   * Check if a given Snap has a cached encryption key stored in the runtime.\n   *\n   * @param snapId - The Snap ID.\n   * @param runtime - The Snap runtime data.\n   * @returns True if the Snap has a cached encryption key, otherwise false.\n   */\n  #hasCachedEncryptionKey(\n    snapId: SnapId,\n    runtime = this.#getRuntimeExpect(snapId),\n  ): runtime is SnapRuntimeData & {\n    encryptionKey: string;\n    encryptionSalt: string;\n  } {\n    return runtime.encryptionKey !== null && runtime.encryptionSalt !== null;\n  }\n\n  /**\n   * Generate an encryption key to be used for state encryption for a given Snap.\n   *\n   * @param options - An options bag.\n   * @param options.snapId - The Snap ID.\n   * @param options.salt - A salt to be used for the encryption key.\n   * @param options.useCache - Whether to use caching or not.\n   * @param options.keyMetadata - Optional metadata about how to derive the encryption key.\n   * @returns An encryption key.\n   */\n  async #getSnapEncryptionKey({\n    snapId,\n    salt: passedSalt,\n    useCache,\n    keyMetadata,\n  }: {\n    snapId: SnapId;\n    salt?: string;\n    useCache: boolean;\n    keyMetadata?: KeyDerivationOptions;\n  }): Promise<{ key: unknown; salt: string }> {\n    const runtime = this.#getRuntimeExpect(snapId);\n\n    if (this.#hasCachedEncryptionKey(snapId, runtime) && useCache) {\n      return {\n        key: await this.#encryptor.importKey(runtime.encryptionKey),\n        salt: runtime.encryptionSalt,\n      };\n    }\n\n    const salt = passedSalt ?? this.#encryptor.generateSalt();\n    const seed = await this.#getMnemonicSeed();\n\n    const entropy = await getEncryptionEntropy({\n      snapId,\n      seed,\n      cryptographicFunctions: this.#clientCryptography,\n    });\n\n    const encryptionKey = await this.#encryptor.keyFromPassword(\n      entropy,\n      salt,\n      true,\n      keyMetadata,\n    );\n    const exportedKey = await this.#encryptor.exportKey(encryptionKey);\n\n    // Cache exported encryption key in runtime\n    if (useCache) {\n      runtime.encryptionKey = exportedKey;\n      runtime.encryptionSalt = salt;\n    }\n    return { key: encryptionKey, salt };\n  }\n\n  /**\n   * Decrypt the encrypted state for a given Snap.\n   *\n   * @param snapId - The Snap ID.\n   * @param state - The encrypted state as a string.\n   * @returns A valid JSON object derived from the encrypted state.\n   * @throws If the decryption fails or the decrypted state is not valid JSON.\n   */\n  async #decryptSnapState(snapId: SnapId, state: string) {\n    try {\n      // We assume that the state string here is valid JSON since we control serialization.\n      // This lets us skip JSON validation.\n      const parsed = JSON.parse(state) as EncryptionResult;\n      const { salt, keyMetadata } = parsed;\n\n      // We only cache encryption keys if they are already cached or if the encryption key is using the latest key derivation params.\n      const useCache =\n        this.#hasCachedEncryptionKey(snapId) ||\n        this.#encryptor.isVaultUpdated(state);\n\n      const { key } = await this.#getSnapEncryptionKey({\n        snapId,\n        salt,\n        useCache,\n        // When decrypting state we expect key metadata to be present.\n        // If it isn't present, we assume that the Snap state we are decrypting is old enough to use the legacy encryption params.\n        keyMetadata: keyMetadata ?? LEGACY_ENCRYPTION_KEY_DERIVATION_OPTIONS,\n      });\n      const decryptedState = await this.#encryptor.decryptWithKey(key, parsed);\n\n      // We assume this to be valid JSON, since all RPC requests from a Snap are validated and sanitized.\n      return decryptedState as Record<string, Json>;\n    } catch {\n      throw rpcErrors.internal({\n        message: 'Failed to decrypt snap state, the state must be corrupted.',\n      });\n    }\n  }\n\n  /**\n   * Encrypt a JSON state object for a given Snap.\n   *\n   * Note: This function does not assert the validity of the object,\n   * please ensure only valid JSON is passed to it.\n   *\n   * @param snapId - The Snap ID.\n   * @param state - The state object.\n   * @returns A string containing the encrypted JSON object.\n   */\n  async #encryptSnapState(snapId: SnapId, state: Record<string, Json>) {\n    const { key, salt } = await this.#getSnapEncryptionKey({\n      snapId,\n      useCache: true,\n    });\n    const encryptedState = await this.#encryptor.encryptWithKey(key, state);\n\n    encryptedState.salt = salt;\n    return JSON.stringify(encryptedState);\n  }\n\n  /**\n   * Get the new Snap state to persist based on the given state and encryption\n   * flag.\n   *\n   * - If the state is null, return null.\n   * - If the state should be encrypted, return the encrypted state.\n   * - Otherwise, if the state should not be encrypted, return the JSON-\n   * stringified state.\n   *\n   * @param snapId - The Snap ID.\n   * @param state - The state to persist.\n   * @param encrypted - A flag to indicate whether to use encrypted storage or\n   * not.\n   * @returns The state to persist.\n   */\n  async #getStateToPersist(\n    snapId: SnapId,\n    state: Record<string, Json> | null,\n    encrypted: boolean,\n  ) {\n    if (state === null) {\n      return null;\n    }\n\n    if (encrypted) {\n      return await this.#encryptSnapState(snapId, state);\n    }\n\n    return JSON.stringify(state);\n  }\n\n  /**\n   * Persist the state of a Snap.\n   *\n   * This function is debounced per Snap, meaning that multiple calls to this\n   * function for the same Snap will only result in one state update. It also\n   * uses a mutex to ensure that only one state update per Snap is processed at\n   * a time, avoiding possible race conditions.\n   *\n   * @param snapId - The Snap ID.\n   * @param newSnapState - The new state of the Snap.\n   * @param encrypted - A flag to indicate whether to use encrypted storage or\n   * not.\n   */\n  readonly #persistSnapState = debouncePersistState(\n    (\n      snapId: SnapId,\n      newSnapState: Record<string, Json> | null,\n      encrypted: boolean,\n    ) => {\n      const runtime = this.#getRuntimeExpect(snapId);\n      runtime.stateMutex\n        .runExclusive(async () => {\n          const newState = await this.#getStateToPersist(\n            snapId,\n            newSnapState,\n            encrypted,\n          );\n\n          if (encrypted) {\n            return this.update((state) => {\n              state.snapStates[snapId] = newState;\n            });\n          }\n\n          return this.update((state) => {\n            state.unencryptedSnapStates[snapId] = newState;\n          });\n        })\n        .catch(logError);\n    },\n    STATE_DEBOUNCE_TIMEOUT,\n  );\n\n  /**\n   * Updates the own state of the snap with the given id.\n   * This is distinct from the state MetaMask uses to manage snaps.\n   *\n   * @param snapId - The id of the Snap whose state should be updated.\n   * @param newSnapState - The new state of the snap.\n   * @param encrypted - A flag to indicate whether to use encrypted storage or not.\n   */\n  async updateSnapState(\n    snapId: SnapId,\n    newSnapState: Record<string, Json>,\n    encrypted: boolean,\n  ) {\n    const runtime = this.#getRuntimeExpect(snapId);\n\n    if (encrypted) {\n      runtime.state = newSnapState;\n    } else {\n      runtime.unencryptedState = newSnapState;\n    }\n\n    this.#persistSnapState(snapId, newSnapState, encrypted);\n  }\n\n  /**\n   * Clears the state of the snap with the given id.\n   * This is distinct from the state MetaMask uses to manage snaps.\n   *\n   * @param snapId - The id of the Snap whose state should be cleared.\n   * @param encrypted - A flag to indicate whether to use encrypted storage or not.\n   */\n  clearSnapState(snapId: SnapId, encrypted: boolean) {\n    const runtime = this.#getRuntimeExpect(snapId);\n    if (encrypted) {\n      runtime.state = null;\n    } else {\n      runtime.unencryptedState = null;\n    }\n\n    this.#persistSnapState(snapId, null, encrypted);\n  }\n\n  /**\n   * Gets the own state of the snap with the given id.\n   * This is distinct from the state MetaMask uses to manage snaps.\n   *\n   * @param snapId - The id of the Snap whose state to get.\n   * @param encrypted - A flag to indicate whether to use encrypted storage or not.\n   * @returns The requested snap state or null if no state exists.\n   */\n  async getSnapState(snapId: SnapId, encrypted: boolean): Promise<Json> {\n    const runtime = this.#getRuntimeExpect(snapId);\n    return await runtime.getStateMutex.runExclusive(async () => {\n      const cachedState = encrypted ? runtime.state : runtime.unencryptedState;\n\n      if (cachedState !== undefined) {\n        return cachedState;\n      }\n\n      const state = encrypted\n        ? this.state.snapStates[snapId]\n        : this.state.unencryptedSnapStates[snapId];\n\n      if (state === null || state === undefined) {\n        return null;\n      }\n\n      if (!encrypted) {\n        // For performance reasons, we do not validate that the state is JSON,\n        // since we control serialization.\n        const json = JSON.parse(state);\n        runtime.unencryptedState = json;\n\n        return json;\n      }\n\n      const decrypted = await this.#decryptSnapState(snapId, state);\n      // eslint-disable-next-line require-atomic-updates\n      runtime.state = decrypted;\n\n      return decrypted;\n    });\n  }\n\n  /**\n   * Gets a static auxiliary snap file in a chosen file encoding.\n   *\n   * @param snapId - The id of the Snap whose state to get.\n   * @param path - The path to the requested file.\n   * @param encoding - An optional requested file encoding.\n   * @returns The file requested in the chosen file encoding or null if the file is not found.\n   */\n  async getSnapFile(\n    snapId: SnapId,\n    path: string,\n    encoding: AuxiliaryFileEncoding = AuxiliaryFileEncoding.Base64,\n  ): Promise<string | null> {\n    const snap = this.getSnapExpect(snapId);\n    const normalizedPath = normalizeRelative(path);\n    const value = snap.auxiliaryFiles?.find(\n      (file) => file.path === normalizedPath,\n    )?.value;\n\n    if (!value) {\n      return null;\n    }\n\n    const encoded = await encodeAuxiliaryFile(value, encoding);\n\n    assert(\n      encoded.length < MAX_FILE_SIZE,\n      `Failed to encode static file to \"${encoding}\": Static files must be less than 64 MB when encoded.`,\n    );\n\n    return encoded;\n  }\n\n  /**\n   * Determine if a given Snap ID supports a given minimum version of the Snaps platform\n   * by inspecting the platformVersion in the Snap manifest.\n   *\n   * @param snapId - The Snap ID.\n   * @param version - The version.\n   * @returns True if the platform version is equal or greater to the passed version, false otherwise.\n   */\n  isMinimumPlatformVersion(snapId: SnapId, version: SemVerVersion): boolean {\n    const snap = this.getSnapExpect(snapId);\n\n    const { platformVersion } = snap.manifest;\n\n    if (!platformVersion) {\n      return false;\n    }\n\n    return gte(platformVersion, version);\n  }\n\n  /**\n   * Completely clear the controller's state: delete all associated data,\n   * handlers, event listeners, and permissions; tear down all snap providers.\n   * Also re-initializes the controller after clearing the state.\n   */\n  async clearState() {\n    const snapIds = Object.keys(this.state.snaps);\n\n    await this.stopAllSnaps();\n    snapIds.forEach((snapId) => this.#revokeAllSnapPermissions(snapId));\n\n    this.update((state) => {\n      state.isReady = false;\n      state.snaps = {};\n      state.snapStates = {};\n      state.unencryptedSnapStates = {};\n    });\n\n    this.#snapsRuntimeData.clear();\n    this.#rollbackSnapshots.clear();\n\n    await this.#clearStorageService();\n\n    this.#controllerSetup = createDeferredPromise();\n\n    // Re-initialize the controller after clearing the state, re-installing preinstalled Snaps etc.\n    await this.init(false);\n  }\n\n  /**\n   * Removes the given snap from state, and clears all associated handlers\n   * and listeners.\n   *\n   * @param snapId - The id of the Snap.\n   * @returns A promise that resolves once the snap has been removed.\n   */\n  async removeSnap(snapId: SnapId): Promise<void> {\n    return this.removeSnaps([snapId]);\n  }\n\n  /**\n   * Stops the given snaps, removes them from state, and clears all associated\n   * permissions, handlers, and listeners.\n   *\n   * @param snapIds - The ids of the Snaps.\n   */\n  async removeSnaps(snapIds: SnapId[]): Promise<void> {\n    if (!Array.isArray(snapIds)) {\n      throw new Error('Expected array of snap ids.');\n    }\n\n    snapIds.forEach((snapId) => {\n      const snap = this.getSnapExpect(snapId);\n      assert(snap.removable !== false, `${snapId} is not removable.`);\n    });\n\n    await Promise.all(\n      snapIds.map(async (snapId) => {\n        const snap = this.getSnapExpect(snapId);\n        const truncated = this.#getTruncatedSnapExpect(snapId);\n        // Disable the snap and revoke all of its permissions before deleting\n        // it. This ensures that the snap will not be restarted or otherwise\n        // affect the host environment while we are deleting it.\n        await this.disableSnap(snapId);\n        this.#revokeAllSnapPermissions(snapId);\n\n        this.#removeSnapFromSubjects(snapId);\n\n        this.#snapsRuntimeData.delete(snapId);\n\n        this.update((state: any) => {\n          delete state.snaps[snapId];\n          delete state.snapStates[snapId];\n          delete state.unencryptedSnapStates[snapId];\n        });\n\n        await this.#removeSourceCode(snapId);\n\n        // If the snap has been fully installed before, also emit snapUninstalled.\n        if (snap.status !== SnapStatus.Installing) {\n          this.messenger.publish(`SnapController:snapUninstalled`, truncated);\n        }\n      }),\n    );\n  }\n\n  #handleInitialConnections(\n    snapId: SnapId,\n    previousInitialConnections: InitialConnections | null,\n    initialConnections: InitialConnections,\n  ) {\n    if (previousInitialConnections) {\n      const revokedInitialConnections = setDiff(\n        previousInitialConnections,\n        initialConnections,\n      );\n\n      for (const origin of Object.keys(revokedInitialConnections)) {\n        this.disconnectOrigin(origin, snapId);\n      }\n    }\n\n    for (const origin of Object.keys(initialConnections)) {\n      this.#addSnapToSubject(origin, snapId);\n    }\n  }\n\n  #addSnapToSubject(origin: string, snapId: SnapId) {\n    const subjectPermissions = this.messenger.call(\n      'PermissionController:getPermissions',\n      origin,\n    ) as SubjectPermissions<PermissionConstraint>;\n\n    const existingCaveat = subjectPermissions?.[\n      WALLET_SNAP_PERMISSION_KEY\n    ]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);\n\n    const subjectHasSnap = Boolean(\n      (existingCaveat?.value as Record<string, Json>)?.[snapId],\n    );\n\n    // If the subject is already connected to the snap, this is a no-op.\n    if (subjectHasSnap) {\n      return;\n    }\n\n    // If an existing caveat exists, we add the snap to that.\n    if (existingCaveat) {\n      this.messenger.call(\n        'PermissionController:updateCaveat',\n        origin,\n        WALLET_SNAP_PERMISSION_KEY,\n        SnapCaveatType.SnapIds,\n        { ...(existingCaveat.value as Record<string, Json>), [snapId]: {} },\n      );\n      return;\n    }\n\n    const approvedPermissions = {\n      [WALLET_SNAP_PERMISSION_KEY]: {\n        caveats: [\n          {\n            type: SnapCaveatType.SnapIds,\n            value: {\n              [snapId]: {},\n            },\n          },\n        ],\n      },\n    } as RequestedPermissions;\n\n    this.messenger.call('PermissionController:grantPermissions', {\n      approvedPermissions,\n      subject: { origin },\n    });\n  }\n\n  /**\n   * Disconnect the Snap from the given origin, meaning the origin can no longer\n   * interact with the Snap until it is reconnected.\n   *\n   * @param origin - The origin from which to remove the Snap.\n   * @param snapId - The id of the snap to remove.\n   */\n  disconnectOrigin(origin: string, snapId: SnapId) {\n    const subjectPermissions = this.messenger.call(\n      'PermissionController:getPermissions',\n      origin,\n    ) as SubjectPermissions<PermissionConstraint>;\n\n    const snapIdsCaveat = subjectPermissions?.[\n      WALLET_SNAP_PERMISSION_KEY\n    ]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds) as\n      | Caveat<string, Json>\n      | undefined;\n\n    if (!snapIdsCaveat) {\n      return;\n    }\n\n    const caveatHasSnap = Boolean(\n      (snapIdsCaveat.value as Record<string, Json>)?.[snapId],\n    );\n    if (caveatHasSnap) {\n      const newCaveatValue = {\n        ...(snapIdsCaveat.value as Record<string, Json>),\n      };\n      delete newCaveatValue[snapId];\n      if (Object.keys(newCaveatValue).length > 0) {\n        this.messenger.call(\n          'PermissionController:updateCaveat',\n          origin,\n          WALLET_SNAP_PERMISSION_KEY,\n          SnapCaveatType.SnapIds,\n          newCaveatValue,\n        );\n      } else {\n        this.messenger.call('PermissionController:revokePermissions', {\n          [origin]: [WALLET_SNAP_PERMISSION_KEY],\n        });\n      }\n    }\n  }\n\n  /**\n   * Checks if a list of permissions are dynamic and allowed to be revoked, if they are they will all be revoked.\n   *\n   * @param snapId - The snap ID.\n   * @param permissionNames - The names of the permissions.\n   * @throws If non-dynamic permissions are passed.\n   */\n  revokeDynamicSnapPermissions(\n    snapId: string,\n    permissionNames: NonEmptyArray<string>,\n  ) {\n    assert(\n      permissionNames.every((permissionName) =>\n        this.#dynamicPermissions.includes(permissionName),\n      ),\n      'Non-dynamic permissions cannot be revoked',\n    );\n    this.messenger.call('PermissionController:revokePermissions', {\n      [snapId]: permissionNames,\n    });\n  }\n\n  /**\n   * Removes a snap's permission (caveat) from all subjects.\n   *\n   * @param snapId - The id of the Snap.\n   */\n  #removeSnapFromSubjects(snapId: SnapId) {\n    const subjects = this.messenger.call(\n      'PermissionController:getSubjectNames',\n    );\n    for (const subject of subjects) {\n      this.disconnectOrigin(subject, snapId);\n    }\n  }\n\n  /**\n   * Safely revokes all permissions granted to a Snap.\n   *\n   * @param snapId - The snap ID.\n   */\n  #revokeAllSnapPermissions(snapId: string) {\n    if (this.messenger.call('PermissionController:hasPermissions', snapId)) {\n      this.messenger.call('PermissionController:revokeAllPermissions', snapId);\n    }\n  }\n\n  /**\n   * Gets all snaps in their truncated format.\n   *\n   * @returns All installed snaps in their truncated format.\n   */\n  getAllSnaps(): TruncatedSnap[] {\n    return Object.values(this.state.snaps).map(truncateSnap);\n  }\n\n  /**\n   * Gets all runnable snaps.\n   *\n   * @returns All runnable snaps.\n   */\n  getRunnableSnaps(): TruncatedSnap[] {\n    return getRunnableSnaps(this.getAllSnaps());\n  }\n\n  /**\n   * Gets the serialized permitted snaps of the given origin, if any.\n   *\n   * @param origin - The origin whose permitted snaps to retrieve.\n   * @returns The serialized permitted snaps for the origin.\n   */\n  getPermittedSnaps(origin: string): RequestSnapsResult {\n    const permissions =\n      this.messenger.call('PermissionController:getPermissions', origin) ?? {};\n    const snaps =\n      permissions[WALLET_SNAP_PERMISSION_KEY]?.caveats?.find(\n        (caveat) => caveat.type === SnapCaveatType.SnapIds,\n      )?.value ?? {};\n    return Object.keys(snaps).reduce<RequestSnapsResult>(\n      (permittedSnaps, snapId) => {\n        const snap = this.getSnap(snapId);\n        const truncatedSnap = this.#getTruncatedSnap(snapId as SnapId);\n\n        if (truncatedSnap && snap?.status !== SnapStatus.Installing) {\n          permittedSnaps[snapId] = truncatedSnap;\n        }\n        return permittedSnaps;\n      },\n      {},\n    );\n  }\n\n  /**\n   * Installs the snaps requested by the given origin, returning the snap\n   * object if the origin is permitted to install it, and an authorization error\n   * otherwise.\n   *\n   * @param origin - The origin that requested to install the snaps.\n   * @param requestedSnaps - The snaps to install.\n   * @returns An object of snap ids and snap objects, or errors if a\n   * snap couldn't be installed.\n   */\n  async installSnaps(\n    origin: string,\n    requestedSnaps: RequestSnapsParams,\n  ): Promise<RequestSnapsResult> {\n    await this.#ensureCanUsePlatform();\n\n    const result: RequestSnapsResult = {};\n\n    const snapIds = Object.keys(requestedSnaps);\n\n    const pendingUpdates = [];\n    const pendingInstalls = [];\n\n    try {\n      for (const [snapId, { version: rawVersion }] of Object.entries(\n        requestedSnaps,\n      )) {\n        assertIsValidSnapId(snapId);\n\n        const [error, version] = resolveVersionRange(rawVersion);\n\n        if (error) {\n          throw rpcErrors.invalidParams(\n            `The \"version\" field must be a valid SemVer version range if specified. Received: \"${\n              rawVersion as string\n            }\".`,\n          );\n        }\n\n        const location = this.#detectSnapLocation(snapId, {\n          versionRange: version,\n          fetch: this.#fetchFunction,\n          allowLocal: this.#featureFlags.allowLocalSnaps,\n          resolveVersion: async (range) =>\n            this.#featureFlags.requireAllowlist\n              ? await this.#resolveAllowlistVersion(snapId, range)\n              : range,\n        });\n\n        // Existing snaps may need to be updated, unless they should be re-installed (e.g. local snaps)\n        // Everything else is treated as an install\n        const isUpdate = this.hasSnap(snapId) && !location.shouldAlwaysReload;\n\n        if (isUpdate && this.#isValidUpdate(snapId, version)) {\n          const existingSnap = this.getSnapExpect(snapId);\n          pendingUpdates.push({ snapId, oldVersion: existingSnap.version });\n          let rollbackSnapshot = this.#getRollbackSnapshot(snapId);\n          if (rollbackSnapshot === undefined) {\n            rollbackSnapshot = this.#createRollbackSnapshot(snapId);\n            rollbackSnapshot.newVersion = version;\n          } else {\n            throw new Error('This snap is already being updated.');\n          }\n        } else if (!isUpdate) {\n          pendingInstalls.push(snapId);\n        }\n\n        result[snapId] = await this.#processRequestedSnap(\n          origin,\n          snapId,\n          location,\n          version,\n        );\n      }\n\n      // Once we finish all installs / updates, emit events.\n      pendingInstalls.forEach((snapId) =>\n        this.messenger.publish(\n          `SnapController:snapInstalled`,\n          this.#getTruncatedSnapExpect(snapId),\n          origin,\n          false,\n        ),\n      );\n\n      pendingUpdates.forEach(({ snapId, oldVersion }) =>\n        this.messenger.publish(\n          `SnapController:snapUpdated`,\n          this.#getTruncatedSnapExpect(snapId),\n          oldVersion,\n          origin,\n          false,\n        ),\n      );\n\n      snapIds.forEach((snapId) => this.#rollbackSnapshots.delete(snapId));\n    } catch (error) {\n      const installed = pendingInstalls.filter((snapId) =>\n        this.hasSnap(snapId),\n      );\n      await this.removeSnaps(installed);\n      const snapshottedSnaps = [...this.#rollbackSnapshots.keys()];\n      const snapsToRollback = pendingUpdates\n        .map(({ snapId }) => snapId)\n        .filter((snapId) => snapshottedSnaps.includes(snapId));\n      await this.#rollbackSnaps(snapsToRollback);\n\n      throw error;\n    }\n\n    return result;\n  }\n\n  /**\n   * Adds, authorizes, and runs the given snap with a snap provider.\n   * Results from this method should be efficiently serializable.\n   *\n   * @param origin - The origin requesting the snap.\n   * @param snapId - The id of the snap.\n   * @param location - The location implementation of the snap.\n   * @param versionRange - The semver range of the snap to install.\n   * @returns The resulting snap object, or an error if something went wrong.\n   */\n  async #processRequestedSnap(\n    origin: string,\n    snapId: SnapId,\n    location: SnapLocation,\n    versionRange: SemVerRange,\n  ): Promise<TruncatedSnap> {\n    const existingSnap = this.#getTruncatedSnap(snapId);\n\n    // For devX we always re-install local snaps.\n    if (existingSnap && !location.shouldAlwaysReload) {\n      if (satisfiesVersionRange(existingSnap.version, versionRange)) {\n        return existingSnap;\n      }\n\n      return await this.#updateSnap({\n        origin,\n        snapId,\n        location,\n        versionRange,\n      });\n    }\n\n    this.#assertCanInstallSnaps();\n\n    let pendingApproval = this.#createApproval({\n      origin,\n      snapId,\n      type: SNAP_APPROVAL_INSTALL,\n    });\n\n    this.messenger.publish(\n      'SnapController:snapInstallStarted',\n      snapId,\n      origin,\n      false,\n    );\n\n    // Existing snaps must be stopped before overwriting\n    if (existingSnap && this.isSnapRunning(snapId)) {\n      await this.stopSnap(snapId, SnapStatusEvents.Stop);\n    }\n\n    // Existing snaps that should be re-installed should not maintain their existing permissions\n    if (existingSnap && location.shouldAlwaysReload) {\n      this.#revokeAllSnapPermissions(snapId);\n    }\n\n    try {\n      const { sourceCode } = await this.#add({\n        origin,\n        id: snapId,\n        location,\n        versionRange,\n      });\n\n      await this.#authorize(snapId, pendingApproval);\n\n      pendingApproval = this.#createApproval({\n        origin,\n        snapId,\n        type: SNAP_APPROVAL_RESULT,\n      });\n\n      await this.#startSnap({\n        snapId,\n        sourceCode,\n      });\n\n      const truncated = this.#getTruncatedSnapExpect(snapId);\n\n      this.#updateApproval(pendingApproval.id, {\n        loading: false,\n        type: SNAP_APPROVAL_INSTALL,\n      });\n\n      return truncated;\n    } catch (error) {\n      logError(`Error when adding ${snapId}.`, error);\n\n      const errorString =\n        error instanceof Error ? error.message : error.toString();\n\n      this.#updateApproval(pendingApproval.id, {\n        loading: false,\n        type: SNAP_APPROVAL_INSTALL,\n        error: errorString,\n      });\n\n      this.messenger.publish(\n        'SnapController:snapInstallFailed',\n        snapId,\n        origin,\n        false,\n        errorString,\n      );\n\n      throw error;\n    }\n  }\n\n  #createApproval({\n    origin,\n    snapId,\n    type,\n  }: {\n    origin: string;\n    snapId: SnapId;\n    type: string;\n  }): PendingApproval {\n    const id = nanoid();\n    const promise = this.messenger.call(\n      'ApprovalController:addRequest',\n      {\n        origin,\n        id,\n        type,\n        requestData: {\n          // Mirror previous installation metadata\n          metadata: { id, origin: snapId, dappOrigin: origin },\n          snapId,\n        },\n        requestState: {\n          loading: true,\n        },\n      },\n      true,\n    );\n\n    return { id, promise };\n  }\n\n  #updateApproval(id: string, requestState: Record<string, Json>) {\n    try {\n      this.messenger.call('ApprovalController:updateRequestState', {\n        id,\n        requestState,\n      });\n    } catch {\n      // Do nothing\n    }\n  }\n\n  /**\n   * Updates an installed snap. The flow is similar to\n   * {@link SnapController.installSnaps}. The user will be asked if they want\n   * to update, then approve any permission changes, and finally the snap will\n   * be restarted.\n   *\n   * The update will fail if the user rejects any prompt or if the new version\n   * of the snap is blocked.\n   *\n   * If the original version of the snap was blocked and the update succeeded,\n   * the snap will be unblocked and enabled before it is restarted.\n   *\n   * @param options - An options bag.\n   * @param options.origin - The origin requesting the snap update.\n   * @param options.snapId - The id of the Snap to be updated.\n   * @param options.location - The location implementation of the snap.\n   * @param options.versionRange - A semver version range in which the maximum version will be chosen.\n   * @param options.automaticUpdate - An optional boolean flag to indicate whether this update should be done\n   * automatically.\n   * @returns The snap metadata if updated, `null` otherwise.\n   */\n  async #updateSnap({\n    origin,\n    snapId,\n    location,\n    versionRange,\n    automaticUpdate = false,\n  }: {\n    origin: string;\n    snapId: SnapId;\n    location: SnapLocation;\n    versionRange: SemVerRange;\n    automaticUpdate?: boolean;\n  }): Promise<TruncatedSnap> {\n    if (!automaticUpdate) {\n      this.#assertCanInstallSnaps();\n    }\n    await this.#ensureCanUsePlatform();\n\n    const snap = this.getSnapExpect(snapId);\n\n    const { preinstalled, removable, hidden, hideSnapBranding } = snap;\n\n    if (preinstalled && !automaticUpdate) {\n      throw new Error('Preinstalled Snaps cannot be manually updated.');\n    }\n\n    let pendingApproval = automaticUpdate\n      ? null\n      : this.#createApproval({\n          origin,\n          snapId,\n          type: SNAP_APPROVAL_UPDATE,\n        });\n\n    try {\n      this.messenger.publish(\n        'SnapController:snapInstallStarted',\n        snapId,\n        origin,\n        true,\n      );\n\n      const oldManifest = snap.manifest;\n\n      const newSnap = await fetchSnap(snapId, location);\n      const { sourceCode: sourceCodeFile, manifest: manifestFile } = newSnap;\n\n      const manifest = manifestFile.result;\n\n      const newVersion = manifest.version;\n      if (!gtVersion(newVersion, snap.version)) {\n        throw rpcErrors.invalidParams(\n          `Snap \"${snapId}@${snap.version}\" is already installed. Couldn't update to a version inside requested \"${versionRange}\" range.`,\n        );\n      }\n\n      if (!satisfiesVersionRange(newVersion, versionRange)) {\n        throw new Error(\n          `Version mismatch. Manifest for \"${snapId}\" specifies version \"${newVersion}\" which doesn't satisfy requested version range \"${versionRange}\".`,\n        );\n      }\n\n      await this.#assertIsInstallAllowed(snapId, {\n        version: newVersion,\n        checksum: manifest.source.shasum,\n        permissions: manifest.initialPermissions,\n        platformVersion: manifest.platformVersion,\n      });\n\n      const processedPermissions = processSnapPermissions(\n        manifest.initialPermissions,\n      );\n\n      this.#validateSnapPermissions(processedPermissions);\n\n      const { newPermissions, unusedPermissions, approvedPermissions } =\n        this.#calculatePermissionsChange(snapId, processedPermissions);\n\n      const { newConnections, unusedConnections, approvedConnections } =\n        this.#calculateConnectionsChange(\n          snapId,\n          oldManifest.initialConnections ?? {},\n          manifest.initialConnections ?? {},\n        );\n\n      let approvedNewPermissions;\n      let requestData;\n\n      if (pendingApproval) {\n        this.#updateApproval(pendingApproval.id, {\n          permissions: newPermissions,\n          newVersion: manifest.version,\n          newPermissions,\n          approvedPermissions,\n          unusedPermissions,\n          newConnections,\n          unusedConnections,\n          approvedConnections,\n          loading: false,\n        });\n\n        const { permissions, ...rest } =\n          (await pendingApproval.promise) as PermissionsRequest;\n\n        approvedNewPermissions = permissions;\n        requestData = rest;\n\n        pendingApproval = this.#createApproval({\n          origin,\n          snapId,\n          type: SNAP_APPROVAL_RESULT,\n        });\n      } else {\n        assert(automaticUpdate);\n        approvedNewPermissions = newPermissions;\n      }\n\n      if (this.isSnapRunning(snapId)) {\n        await this.stopSnap(snapId, SnapStatusEvents.Stop);\n      }\n\n      this.#transition(snapId, SnapStatusEvents.Update);\n\n      await this.#set({\n        origin,\n        id: snapId,\n        files: newSnap,\n        removable,\n        preinstalled,\n        hidden,\n        hideSnapBranding,\n        isUpdate: true,\n      });\n\n      this.#updatePermissions({\n        snapId,\n        unusedPermissions,\n        newPermissions: approvedNewPermissions,\n        requestData,\n      });\n\n      const previousInitialConnections = oldManifest.initialConnections ?? null;\n      const newInitialConnections = manifest.initialConnections ?? {};\n      this.#handleInitialConnections(\n        snapId,\n        previousInitialConnections,\n        newInitialConnections,\n      );\n\n      const rollbackSnapshot = this.#getRollbackSnapshot(snapId);\n      if (rollbackSnapshot !== undefined) {\n        rollbackSnapshot.permissions.revoked = unusedPermissions;\n        rollbackSnapshot.permissions.granted = approvedNewPermissions;\n        rollbackSnapshot.permissions.requestData = requestData;\n        rollbackSnapshot.previousInitialConnections =\n          previousInitialConnections;\n        rollbackSnapshot.newInitialConnections = newInitialConnections;\n      }\n\n      const sourceCode = sourceCodeFile.toString();\n\n      assert(\n        typeof sourceCode === 'string' && sourceCode.length > 0,\n        `Invalid source code for snap \"${snapId}\".`,\n      );\n\n      try {\n        await this.#startSnap({ snapId, sourceCode });\n      } catch {\n        throw new Error(`Snap ${snapId} crashed with updated source code.`);\n      }\n\n      const truncatedSnap = this.#getTruncatedSnapExpect(snapId);\n\n      if (pendingApproval) {\n        this.#updateApproval(pendingApproval.id, {\n          loading: false,\n          type: SNAP_APPROVAL_UPDATE,\n        });\n      }\n\n      return truncatedSnap;\n    } catch (error) {\n      logError(`Error when updating ${snapId},`, error);\n\n      const errorString =\n        error instanceof Error ? error.message : error.toString();\n\n      if (pendingApproval) {\n        this.#updateApproval(pendingApproval.id, {\n          loading: false,\n          error: errorString,\n          type: SNAP_APPROVAL_UPDATE,\n        });\n      }\n\n      this.messenger.publish(\n        'SnapController:snapInstallFailed',\n        snapId,\n        origin,\n        true,\n        errorString,\n      );\n\n      throw error;\n    }\n  }\n\n  async #resolveAllowlistVersion(\n    snapId: SnapId,\n    versionRange: SemVerRange,\n  ): Promise<SemVerRange> {\n    return await this.messenger.call(\n      'SnapRegistryController:resolveVersion',\n      snapId,\n      versionRange,\n    );\n  }\n\n  /**\n   * Returns a promise representing the complete installation of the requested snap.\n   * If the snap is already being installed, the previously pending promise will be returned.\n   *\n   * @param args - Object containing the snap id and either the URL of the snap's manifest,\n   * or the snap's manifest and source code. The object may also optionally contain a target\n   * version.\n   * @returns The resulting snap object.\n   */\n  async #add(args: AddSnapArgs): Promise<PersistedSnap> {\n    const { id: snapId, location, versionRange } = args;\n\n    this.#setupRuntime(snapId);\n    const runtime = this.#getRuntimeExpect(snapId);\n    if (!runtime.installPromise) {\n      log(`Adding snap: ${snapId}`);\n\n      // If fetching and setting the snap succeeds, this property will be set\n      // to null in the authorize() method.\n      runtime.installPromise = (async () => {\n        const fetchedSnap = await fetchSnap(snapId, location);\n        const manifest = fetchedSnap.manifest.result;\n        if (!satisfiesVersionRange(manifest.version, versionRange)) {\n          throw new Error(\n            `Version mismatch. Manifest for \"${snapId}\" specifies version \"${manifest.version}\" which doesn't satisfy requested version range \"${versionRange}\".`,\n          );\n        }\n\n        await this.#assertIsInstallAllowed(snapId, {\n          version: manifest.version,\n          checksum: manifest.source.shasum,\n          permissions: manifest.initialPermissions,\n          platformVersion: manifest.platformVersion,\n        });\n\n        const preinstalledArgs =\n          this.#featureFlags.forcePreinstalledSnaps && isLocalSnapId(snapId)\n            ? {\n                preinstalled: true,\n                hideSnapBranding: true,\n                hidden: false,\n              }\n            : {};\n\n        return this.#set({\n          ...args,\n          files: fetchedSnap,\n          id: snapId,\n          ...preinstalledArgs,\n        });\n      })();\n    }\n\n    try {\n      return await runtime.installPromise;\n    } catch (error) {\n      // Reset promise so users can retry installation in case the problem is\n      // temporary.\n      runtime.installPromise = null;\n      throw error;\n    }\n  }\n\n  async #startSnap(snapData: { snapId: SnapId; sourceCode: string }) {\n    const { snapId } = snapData;\n    if (this.isSnapRunning(snapId)) {\n      throw new Error(`Snap \"${snapId}\" is already started.`);\n    }\n\n    try {\n      const runtime = this.#getRuntimeExpect(snapId);\n      const result = await this.messenger.call('ExecutionService:executeSnap', {\n        ...snapData,\n        endowments: await this.#getEndowments(snapId),\n      });\n\n      this.#transition(snapId, SnapStatusEvents.Start);\n      // We treat the initialization of the snap as the first request, for idle timing purposes.\n      runtime.lastRequest = Date.now();\n      return result;\n    } catch (error) {\n      await this.#terminateSnap(snapId);\n      throw error;\n    }\n  }\n\n  /**\n   * Gets the names of all endowments that will be added to the Snap's\n   * Compartment when it executes. These should be the names of global\n   * JavaScript APIs accessible in the root realm of the execution environment.\n   *\n   * Throws an error if the endowment getter for a permission returns a truthy\n   * value that is not an array of strings.\n   *\n   * @param snapId - The id of the snap whose SES endowments to get.\n   * @returns An array of the names of the endowments.\n   */\n  async #getEndowments(snapId: string): Promise<string[]> {\n    let allEndowments: string[] = [];\n\n    for (const permissionName of this.#environmentEndowmentPermissions) {\n      if (\n        this.messenger.call(\n          'PermissionController:hasPermission',\n          snapId,\n          permissionName,\n        )\n      ) {\n        const endowments = await this.messenger.call(\n          'PermissionController:getEndowments',\n          snapId,\n          permissionName,\n        );\n\n        if (endowments) {\n          // We don't have any guarantees about the type of the endowments\n          // value, so we have to guard at runtime.\n          if (\n            !Array.isArray(endowments) ||\n            endowments.some((value) => typeof value !== 'string')\n          ) {\n            throw new Error('Expected an array of string endowment names.');\n          }\n\n          allEndowments = allEndowments.concat(endowments as string[]);\n        }\n      }\n    }\n\n    const dedupedEndowments = [\n      ...new Set([...DEFAULT_ENDOWMENTS, ...allEndowments]),\n    ];\n\n    if (\n      dedupedEndowments.length <\n      DEFAULT_ENDOWMENTS.length + allEndowments.length\n    ) {\n      logError(\n        `Duplicate endowments found for ${snapId}. Default endowments should not be requested.`,\n        allEndowments,\n      );\n    }\n    return dedupedEndowments;\n  }\n\n  /**\n   * Sets a snap in state. Called when a snap is installed or updated. Performs\n   * various validation checks on the received arguments, and will throw if\n   * validation fails.\n   *\n   * The snap will be enabled and unblocked by the time this method returns,\n   * regardless of its previous state.\n   *\n   * See {@link SnapController.add} and {@link SnapController.updateSnap} for\n   * usage.\n   *\n   * @param args - The add snap args.\n   * @returns The resulting snap object.\n   */\n  async #set(args: SetSnapArgs): Promise<PersistedSnap> {\n    const {\n      id: snapId,\n      origin,\n      files,\n      isUpdate = false,\n      removable,\n      preinstalled,\n      hidden,\n      hideSnapBranding,\n    } = args;\n\n    const {\n      manifest,\n      sourceCode: sourceCodeFile,\n      svgIcon,\n      auxiliaryFiles: rawAuxiliaryFiles,\n      localizationFiles,\n    } = files;\n\n    assertIsSnapManifest(manifest.result);\n    const { version } = manifest.result;\n\n    const sourceCode = sourceCodeFile.toString();\n\n    assert(\n      typeof sourceCode === 'string' && sourceCode.length > 0,\n      `Invalid source code for snap \"${snapId}\".`,\n    );\n\n    const auxiliaryFiles = rawAuxiliaryFiles.map((file) => {\n      assert(typeof file.data.base64 === 'string');\n      return {\n        path: file.path,\n        value: file.data.base64,\n      };\n    });\n\n    const snapsState = this.state.snaps;\n\n    const existingSnap = snapsState[snapId];\n\n    const previousVersionHistory = existingSnap?.versionHistory ?? [];\n    const versionHistory = [\n      ...previousVersionHistory,\n      {\n        version,\n        date: Date.now(),\n        origin,\n      },\n    ];\n\n    const localizedFiles = localizationFiles.map((file) => file.result);\n\n    const snap: Snap = {\n      // Restore relevant snap state if it exists\n      ...existingSnap,\n\n      // Note that the snap will be unblocked and enabled, regardless of its\n      // previous state.\n      blocked: false,\n      enabled: true,\n\n      removable,\n      preinstalled,\n      hidden,\n      hideSnapBranding,\n\n      id: snapId,\n      initialConnections: manifest.result.initialConnections,\n      initialPermissions: manifest.result.initialPermissions,\n      manifest: manifest.result,\n      status: this.#statusMachine.config.initial as StatusStates['value'],\n      version,\n      versionHistory,\n      auxiliaryFiles,\n      localizationFiles: localizedFiles,\n    };\n\n    // If the snap was blocked, it isn't any longer\n    delete snap.blockInformation;\n\n    // store the snap back in state\n    const { inversePatches } = this.update((state: any) => {\n      state.snaps[snapId] = snap;\n    });\n\n    // checking for isUpdate here as this function is also used in\n    // the install flow, we do not care to create snapshots for installs\n    if (isUpdate) {\n      const rollbackSnapshot = this.#getRollbackSnapshot(snapId);\n\n      if (rollbackSnapshot !== undefined) {\n        // Save statePatches first, before any async operations that might throw.\n        // This ensures rollback can revert state changes even if subsequent operations fail.\n        rollbackSnapshot.statePatches = inversePatches;\n\n        const previousSourceCode = await this.#getSourceCode(snapId);\n        rollbackSnapshot.previousSourceCode = previousSourceCode;\n      }\n    }\n\n    await this.#setSourceCode(snapId, sourceCode);\n\n    // In case the Snap uses a localized manifest, we need to get the\n    // proposed name from the localized manifest.\n    const { proposedName } = getLocalizedSnapManifest(\n      manifest.result,\n      'en',\n      localizedFiles,\n    );\n\n    this.messenger.call('SubjectMetadataController:addSubjectMetadata', {\n      subjectType: SubjectType.Snap,\n      name: proposedName,\n      origin: snap.id,\n      version,\n      svgIcon: svgIcon?.toString() ?? null,\n    });\n\n    return { ...snap, sourceCode };\n  }\n\n  #validateSnapPermissions(\n    processedPermissions: Record<string, Pick<PermissionConstraint, 'caveats'>>,\n  ) {\n    const permissionKeys = Object.keys(processedPermissions);\n    const handlerPermissions = Array.from(\n      new Set(Object.values(handlerEndowments)),\n    );\n\n    assert(\n      permissionKeys.some((key) => handlerPermissions.includes(key)),\n      `A snap must request at least one of the following permissions: ${handlerPermissions\n        .filter((handler) => handler !== null)\n        .join(', ')}.`,\n    );\n\n    const excludedPermissionErrors = permissionKeys.reduce<string[]>(\n      (errors, permission) => {\n        if (hasProperty(this.#excludedPermissions, permission)) {\n          errors.push(this.#excludedPermissions[permission]);\n        }\n\n        return errors;\n      },\n      [],\n    );\n\n    assert(\n      excludedPermissionErrors.length === 0,\n      `One or more permissions are not allowed:\\n${excludedPermissionErrors.join(\n        '\\n',\n      )}`,\n    );\n  }\n\n  /**\n   * Validate that the platform version specified in the manifest (if any) is\n   * compatible with the current platform version.\n   *\n   * @param snapId - The ID of the Snap.\n   * @param platformVersion - The platform version to validate against.\n   * @throws If the platform version is greater than the current platform\n   * version.\n   */\n  #validatePlatformVersion(\n    snapId: SnapId,\n    platformVersion: string | undefined,\n  ) {\n    if (platformVersion === undefined) {\n      return;\n    }\n\n    if (gt(platformVersion, getPlatformVersion())) {\n      const message = `The Snap \"${snapId}\" requires platform version \"${platformVersion}\" which is greater than the current platform version \"${getPlatformVersion()}\".`;\n\n      if (this.#featureFlags.rejectInvalidPlatformVersion) {\n        throw new Error(message);\n      }\n\n      logWarning(message);\n    }\n  }\n\n  /**\n   * Initiates a request for the given snap's initial permissions.\n   * Must be called in order. See processRequestedSnap.\n   *\n   * @param snapId - The id of the Snap.\n   * @param pendingApproval - Pending approval to update.\n   * @returns The snap's approvedPermissions.\n   */\n  async #authorize(\n    snapId: SnapId,\n    pendingApproval: PendingApproval,\n  ): Promise<void> {\n    log(`Authorizing snap: ${snapId}`);\n    const snapsState = this.state.snaps;\n    const snap = snapsState[snapId];\n    const { initialPermissions, initialConnections } = snap;\n\n    try {\n      const processedPermissions = processSnapPermissions(initialPermissions);\n\n      this.#validateSnapPermissions(processedPermissions);\n\n      this.#updateApproval(pendingApproval.id, {\n        loading: false,\n        connections: initialConnections ?? {},\n        permissions: processedPermissions,\n      });\n\n      const { permissions: approvedPermissions, ...requestData } =\n        (await pendingApproval.promise) as PermissionsRequest;\n\n      this.#updatePermissions({\n        snapId,\n        newPermissions: approvedPermissions,\n        requestData,\n      });\n\n      if (snap.manifest.initialConnections) {\n        this.#handleInitialConnections(\n          snapId,\n          null,\n          snap.manifest.initialConnections,\n        );\n      }\n    } finally {\n      const runtime = this.#getRuntimeExpect(snapId);\n      runtime.installPromise = null;\n    }\n  }\n\n  destroy() {\n    super.destroy();\n\n    if (this.#timeoutForLastRequestStatus) {\n      clearTimeout(this.#timeoutForLastRequestStatus);\n    }\n\n    /* eslint-disable @typescript-eslint/unbound-method */\n    this.messenger.unsubscribe(\n      'ExecutionService:unhandledError',\n      this._onUnhandledSnapError,\n    );\n\n    this.messenger.unsubscribe(\n      'ExecutionService:outboundRequest',\n      this._onOutboundRequest,\n    );\n\n    this.messenger.unsubscribe(\n      'ExecutionService:outboundResponse',\n      this._onOutboundResponse,\n    );\n\n    this.messenger.clearEventSubscriptions('SnapController:snapInstalled');\n\n    this.messenger.clearEventSubscriptions('SnapController:snapUpdated');\n    /* eslint-enable @typescript-eslint/unbound-method */\n  }\n\n  /**\n   * Passes a JSON-RPC request object to the RPC handler function of a snap.\n   *\n   * @param options - A bag of options.\n   * @param options.snapId - The ID of the recipient snap.\n   * @param options.origin - The origin of the RPC request.\n   * @param options.handler - The handler to trigger on the snap for the request.\n   * @param options.request - The JSON-RPC request object.\n   * @returns The result of the JSON-RPC request.\n   */\n  async handleRequest({\n    snapId,\n    origin,\n    handler: handlerType,\n    request: rawRequest,\n  }: SnapRpcHookArgs & { snapId: SnapId }): Promise<unknown> {\n    await this.#ensureCanUsePlatform();\n\n    const snap = this.getSnap(snapId);\n\n    assert(\n      snap,\n      `The Snap \"${snapId}\" is not installed. Please install it before invoking it.`,\n    );\n\n    assert(\n      origin === METAMASK_ORIGIN || isValidUrl(origin),\n      \"'origin' must be a valid URL or 'metamask'.\",\n    );\n\n    const request = {\n      jsonrpc: '2.0',\n      id: nanoid(),\n      ...rawRequest,\n    };\n\n    assertIsJsonRpcRequest(request);\n\n    const permissionName = handlerEndowments[handlerType];\n\n    assert(\n      typeof permissionName === 'string' || permissionName === null,\n      \"'permissionName' must be either a string or null.\",\n    );\n\n    const permissions = this.messenger.call(\n      'PermissionController:getPermissions',\n      snapId,\n    );\n\n    // If permissionName is null, the handler does not require a permission.\n    if (\n      permissionName !== null &&\n      (!permissions || !hasProperty(permissions, permissionName))\n    ) {\n      throw new Error(\n        `Snap \"${snapId}\" is not permitted to use \"${permissionName}\".`,\n      );\n    }\n\n    const handlerPermissions = permissionName\n      ? (permissions as SubjectPermissions<PermissionConstraint>)[\n          permissionName\n        ]\n      : undefined;\n\n    if (\n      permissionName === SnapEndowments.Rpc ||\n      permissionName === SnapEndowments.Keyring\n    ) {\n      assert(handlerPermissions);\n\n      const subject = this.messenger.call(\n        'SubjectMetadataController:getSubjectMetadata',\n        origin,\n      );\n\n      const origins =\n        permissionName === SnapEndowments.Rpc\n          ? getRpcCaveatOrigins(handlerPermissions)\n          : getKeyringCaveatOrigins(handlerPermissions);\n      assert(origins);\n\n      if (\n        !isOriginAllowed(\n          origins,\n          subject?.subjectType ?? SubjectType.Website,\n          origin,\n        )\n      ) {\n        throw new Error(\n          `Snap \"${snapId}\" is not permitted to handle requests from \"${origin}\".`,\n        );\n      }\n    }\n\n    if (\n      origin !== METAMASK_ORIGIN &&\n      CLIENT_ONLY_HANDLERS.includes(handlerType)\n    ) {\n      throw new Error(`\"${handlerType}\" can only be invoked by MetaMask.`);\n    }\n\n    if (!snap.enabled) {\n      throw new Error(`Snap \"${snapId}\" is disabled.`);\n    }\n\n    if (snap.status === SnapStatus.Installing) {\n      throw new Error(\n        `Snap \"${snapId}\" is currently being installed. Please try again later.`,\n      );\n    }\n\n    const timeout = this.#getExecutionTimeout(handlerPermissions);\n\n    const runtime = this.#getRuntimeExpect(snapId);\n\n    if (runtime.stopPromise) {\n      await runtime.stopPromise;\n    }\n\n    if (!this.isSnapRunning(snapId)) {\n      if (!runtime.startPromise) {\n        runtime.startPromise = this.startSnap(snapId);\n      }\n\n      try {\n        await runtime.startPromise;\n      } finally {\n        runtime.startPromise = null;\n      }\n    }\n\n    const transformedRequest = this.#transformSnapRpcRequest(\n      snapId,\n      handlerType,\n      request,\n    );\n\n    const timer = new Timer(timeout);\n    this.#recordSnapRpcRequestStart(snapId, transformedRequest.id, timer);\n\n    const handleRpcRequestPromise = this.messenger.call(\n      'ExecutionService:handleRpcRequest',\n      snapId,\n      { origin, handler: handlerType, request: transformedRequest },\n    );\n\n    // This will either get the result or reject due to the timeout.\n    try {\n      const result = await withTimeout(handleRpcRequestPromise, timer);\n\n      if (result === hasTimedOut) {\n        const stopping =\n          runtime.stopPromise !== null || !this.isSnapRunning(snapId);\n        throw new Error(\n          stopping\n            ? `${snapId} was stopped and the request was cancelled. This is likely because the Snap crashed.`\n            : `${snapId} failed to respond to the request in time.`,\n        );\n      }\n\n      await this.#assertSnapRpcResponse(snapId, handlerType, result);\n\n      const transformedResult = await this.#transformSnapRpcResponse(\n        snapId,\n        handlerType,\n        transformedRequest,\n        result,\n      );\n\n      if (\n        INTERFACE_HANDLERS.includes(handlerType) &&\n        transformedResult !== null\n      ) {\n        assert(\n          isObject(transformedResult) &&\n            hasProperty(transformedResult, 'id') &&\n            typeof transformedResult.id === 'string',\n          'Interface response must have an ID.',\n        );\n\n        this.messenger.call(\n          'SnapInterfaceController:setInterfaceDisplayed',\n          snapId,\n          transformedResult.id,\n        );\n      }\n\n      this.#recordSnapRpcRequestFinish(\n        snapId,\n        transformedRequest.id,\n        handlerType,\n        origin,\n        true,\n      );\n\n      return transformedResult;\n    } catch (error) {\n      // We flag the RPC request as finished early since termination may affect pending requests\n      this.#recordSnapRpcRequestFinish(\n        snapId,\n        transformedRequest.id,\n        handlerType,\n        origin,\n        false,\n      );\n\n      const [jsonRpcError, handled] = unwrapError(error);\n\n      const stopping =\n        runtime.stopPromise !== null || !this.isSnapRunning(snapId);\n\n      if (!handled) {\n        if (!stopping) {\n          logError(\n            `\"${snapId}\" crashed due to an unhandled error:`,\n            jsonRpcError,\n          );\n        }\n        await this.stopSnap(snapId, SnapStatusEvents.Crash);\n      }\n\n      throw jsonRpcError;\n    }\n  }\n\n  /**\n   * Set the active state of the client. This will trigger the `onActive` or\n   * `onInactive` lifecycle hooks for all Snaps.\n   *\n   * @param active - A boolean indicating whether the client is active or not.\n   */\n  setClientActive(active: boolean) {\n    if (active) {\n      this.#callLifecycleHooks(METAMASK_ORIGIN, HandlerType.OnActive);\n    } else {\n      this.#callLifecycleHooks(METAMASK_ORIGIN, HandlerType.OnInactive);\n    }\n  }\n\n  /**\n   * Determine the execution timeout for a given handler permission.\n   *\n   * If no permission is specified or the permission itself has no execution timeout defined\n   * the constructor argument `maxRequestTime` will be used.\n   *\n   * @param permission - An optional permission constraint for the handler being called.\n   * @returns The execution timeout for the given handler.\n   */\n  #getExecutionTimeout(permission?: PermissionConstraint): number {\n    return getMaxRequestTimeCaveat(permission) ?? this.maxRequestTime;\n  }\n\n  /**\n   * Create a dynamic interface in the SnapInterfaceController.\n   *\n   * @param snapId - The snap ID.\n   * @param content - The initial interface content.\n   * @param contentType - The type of content.\n   * @returns An identifier that can be used to identify the interface.\n   */\n  async #createInterface(\n    snapId: SnapId,\n    content: ComponentOrElement,\n    contentType?: ContentType,\n  ): Promise<string> {\n    return this.messenger.call(\n      'SnapInterfaceController:createInterface',\n      snapId,\n      content,\n      undefined,\n      contentType,\n    );\n  }\n\n  #assertInterfaceExists(snapId: SnapId, id: string) {\n    // This will throw if the interface isn't accessible, but we assert nevertheless.\n    assert(\n      this.messenger.call('SnapInterfaceController:getInterface', snapId, id),\n    );\n  }\n\n  /**\n   * Transform a RPC response if necessary.\n   *\n   * @param snapId - The snap ID of the snap that produced the result.\n   * @param handlerType - The handler type that produced the result.\n   * @param request - The request that returned the result.\n   * @param result - The response.\n   * @returns The transformed result if applicable, otherwise the original result.\n   */\n  async #transformSnapRpcResponse(\n    snapId: SnapId,\n    handlerType: HandlerType,\n    request: Record<string, unknown>,\n    result: unknown,\n  ) {\n    switch (handlerType) {\n      case HandlerType.OnTransaction:\n      case HandlerType.OnSignature:\n      case HandlerType.OnHomePage:\n      case HandlerType.OnSettingsPage: {\n        // Since this type has been asserted earlier we can cast\n        const castResult = result as Record<string, Json> | null;\n\n        // If a handler returns static content, we turn it into a dynamic UI\n        if (castResult && hasProperty(castResult, 'content')) {\n          const { content, ...rest } = castResult;\n          const id = await this.#createInterface(\n            snapId,\n            content as ComponentOrElement,\n          );\n\n          return { ...rest, id };\n        }\n        return result;\n      }\n      case HandlerType.OnAssetsLookup:\n        // We can cast since the request and result have already been validated.\n        return this.#transformOnAssetsLookupResult(\n          snapId,\n          request as { params: OnAssetsLookupArguments },\n          result as OnAssetsLookupResponse,\n        );\n\n      case HandlerType.OnAssetsConversion:\n        // We can cast since the request and result have already been validated.\n        return this.#transformOnAssetsConversionResult(\n          request as {\n            params: OnAssetsConversionArguments;\n          },\n          result as OnAssetsConversionResponse,\n        );\n\n      case HandlerType.OnAssetsMarketData:\n        // We can cast since the request and result have already been validated.\n        return this.#transformOnAssetsMarketDataResult(\n          request as { params: OnAssetsMarketDataArguments },\n          result as OnAssetsMarketDataResponse,\n        );\n\n      default:\n        return result;\n    }\n  }\n\n  /**\n   * Transform an RPC response coming from the `onAssetsLookup` handler.\n   *\n   * This filters out responses that are out of scope for the Snap based on\n   * its permissions and the incoming request.\n   *\n   * @param snapId - The snap ID of the snap that produced the result.\n   * @param request - The request that returned the result.\n   * @param request.params - The parameters for the request.\n   * @param result - The result.\n   * @param result.assets - The assets returned by the Snap.\n   * @returns The transformed result.\n   */\n  #transformOnAssetsLookupResult(\n    snapId: SnapId,\n    { params: requestedParams }: { params: OnAssetsLookupArguments },\n    { assets }: OnAssetsLookupResponse,\n  ) {\n    const permissions = this.messenger.call(\n      'PermissionController:getPermissions',\n      snapId,\n    );\n    // We know the permissions are guaranteed to be set here.\n    assert(permissions);\n\n    const permission = permissions[SnapEndowments.Assets];\n    const scopes = getChainIdsCaveat(permission);\n    assert(scopes);\n\n    const { assets: requestedAssets } = requestedParams;\n\n    const filteredAssets = Object.keys(assets).reduce<\n      Record<CaipAssetType, AssetMetadata | null>\n    >((accumulator, assetType) => {\n      const castAssetType = assetType as CaipAssetTypeOrId;\n      const isValid =\n        scopes.some((scope) => castAssetType.startsWith(scope)) &&\n        requestedAssets.includes(castAssetType);\n      // Filter out unrequested assets and assets for scopes the Snap hasn't registered for.\n      if (isValid) {\n        accumulator[castAssetType] = assets[castAssetType];\n      }\n      return accumulator;\n    }, {});\n    return { assets: filteredAssets };\n  }\n\n  /**\n   * Transform an RPC response coming from the `onAssetsConversion` handler.\n   *\n   * This filters out responses that are out of scope for the Snap based on\n   * the incoming request.\n   *\n   * @param request - The request that returned the result.\n   * @param request.params - The parameters for the request.\n   * @param result - The result.\n   * @param result.conversionRates - The conversion rates returned by the Snap.\n   * @returns The transformed result.\n   */\n  #transformOnAssetsConversionResult(\n    { params: requestedParams }: { params: OnAssetsConversionArguments },\n    { conversionRates }: OnAssetsConversionResponse,\n  ) {\n    const { conversions: requestedConversions } = requestedParams;\n\n    const filteredConversionRates = requestedConversions.reduce<\n      Record<CaipAssetType, Record<CaipAssetType, AssetConversion>>\n    >((accumulator, conversion) => {\n      const rate = conversionRates[conversion.from]?.[conversion.to];\n      // Only include rates that were actually requested.\n      if (rate) {\n        accumulator[conversion.from] ??= {};\n        accumulator[conversion.from][conversion.to] = rate;\n      }\n      return accumulator;\n    }, {});\n    return { conversionRates: filteredConversionRates };\n  }\n\n  /**\n   * Transforms an RPC response coming from the `onAssetsMarketData` handler.\n   *\n   * This filters out responses that are out of scope for the Snap based on\n   * the incoming request.\n   *\n   * @param request - The request that returned the result.\n   * @param request.params - The parameters for the request.\n   * @param result - The result.\n   * @param result.marketData - The market data returned by the Snap.\n   * @returns The transformed result.\n   */\n  #transformOnAssetsMarketDataResult(\n    { params: requestedParams }: { params: OnAssetsMarketDataArguments },\n    { marketData }: OnAssetsMarketDataResponse,\n  ) {\n    const { assets: requestedAssets } = requestedParams;\n\n    const filteredMarketData = requestedAssets.reduce<\n      Record<CaipAssetTypeOrId, Record<CaipAssetType, AssetMarketData | null>>\n    >((accumulator, assets) => {\n      const result = marketData[assets.asset]?.[assets.unit];\n      // Only include rates that were actually requested.\n      if (result) {\n        accumulator[assets.asset] ??= {};\n        accumulator[assets.asset][assets.unit] = result;\n      }\n      return accumulator;\n    }, {});\n    return { marketData: filteredMarketData };\n  }\n\n  /**\n   * Transforms a JSON-RPC request before sending it to the Snap, if required for a given handler.\n   *\n   * @param snapId - The Snap ID.\n   * @param handlerType - The handler being called.\n   * @param request - The JSON-RPC request.\n   * @returns The potentially transformed JSON-RPC request.\n   */\n  #transformSnapRpcRequest(\n    snapId: SnapId,\n    handlerType: HandlerType,\n    request: JsonRpcRequest,\n  ) {\n    switch (handlerType) {\n      // For onUserInput we inject context, so the client doesn't have to worry about keeping it in sync.\n      case HandlerType.OnUserInput: {\n        assert(request.params && hasProperty(request.params, 'id'));\n\n        const interfaceId = request.params.id as string;\n        const { context } = this.messenger.call(\n          'SnapInterfaceController:getInterface',\n          snapId,\n          interfaceId,\n        );\n\n        return {\n          ...request,\n          params: { ...request.params, context },\n        };\n      }\n\n      default:\n        return request;\n    }\n  }\n\n  /**\n   * Assert that the returned result of a Snap RPC call is the expected shape.\n   *\n   * @param snapId - The snap ID.\n   * @param handlerType - The handler type of the RPC Request.\n   * @param result - The result of the RPC request.\n   */\n  async #assertSnapRpcResponse(\n    snapId: SnapId,\n    handlerType: HandlerType,\n    result: unknown,\n  ) {\n    switch (handlerType) {\n      case HandlerType.OnTransaction: {\n        assertStruct(result, OnTransactionResponseStruct);\n\n        if (result && hasProperty(result, 'id')) {\n          this.#assertInterfaceExists(snapId, result.id as string);\n        }\n\n        break;\n      }\n      case HandlerType.OnSignature: {\n        assertStruct(result, OnSignatureResponseStruct);\n\n        if (result && hasProperty(result, 'id')) {\n          this.#assertInterfaceExists(snapId, result.id as string);\n        }\n\n        break;\n      }\n      case HandlerType.OnHomePage: {\n        assertStruct(result, OnHomePageResponseStruct);\n\n        if (result && hasProperty(result, 'id')) {\n          this.#assertInterfaceExists(snapId, result.id as string);\n        }\n\n        break;\n      }\n      case HandlerType.OnSettingsPage: {\n        assertStruct(result, OnSettingsPageResponseStruct);\n\n        if (result && hasProperty(result, 'id')) {\n          this.#assertInterfaceExists(snapId, result.id as string);\n        }\n\n        break;\n      }\n      case HandlerType.OnNameLookup:\n        assertStruct(result, OnNameLookupResponseStruct);\n        break;\n      case HandlerType.OnAssetsLookup:\n        assertStruct(result, OnAssetsLookupResponseStruct);\n        break;\n      case HandlerType.OnAssetsConversion:\n        assertStruct(result, OnAssetsConversionResponseStruct);\n        break;\n      case HandlerType.OnAssetHistoricalPrice:\n        assertStruct(result, OnAssetHistoricalPriceResponseStruct);\n        break;\n      case HandlerType.OnAssetsMarketData:\n        assertStruct(result, OnAssetsMarketDataResponseStruct);\n        break;\n      default:\n        break;\n    }\n  }\n\n  #recordSnapRpcRequestStart(snapId: SnapId, requestId: unknown, timer: Timer) {\n    const runtime = this.#getRuntimeExpect(snapId);\n    runtime.pendingInboundRequests.push({ requestId, timer });\n    runtime.lastRequest = null;\n  }\n\n  #recordSnapRpcRequestFinish(\n    snapId: SnapId,\n    requestId: unknown,\n    handlerType: HandlerType,\n    origin: string,\n    success: boolean,\n  ) {\n    const runtime = this.#getRuntimeExpect(snapId);\n    runtime.pendingInboundRequests = runtime.pendingInboundRequests.filter(\n      (request) => request.requestId !== requestId,\n    );\n\n    if (runtime.pendingInboundRequests.length === 0) {\n      runtime.lastRequest = Date.now();\n    }\n\n    const snap = this.getSnap(snapId);\n\n    if (isTrackableHandler(handlerType) && !snap?.preinstalled) {\n      try {\n        this.#trackSnapExport(snapId, handlerType, success, origin);\n      } catch (error) {\n        logError(\n          `Error when calling MetaMetrics hook for snap \"${snap?.id}\": ${getErrorMessage(\n            error,\n          )}`,\n        );\n      }\n    }\n  }\n\n  /**\n   * Retrieves the rollback snapshot of a snap.\n   *\n   * @param snapId - The snap id.\n   * @returns A `RollbackSnapshot` or `undefined` if one doesn't exist.\n   */\n  #getRollbackSnapshot(snapId: SnapId): RollbackSnapshot | undefined {\n    return this.#rollbackSnapshots.get(snapId);\n  }\n\n  /**\n   * Creates a `RollbackSnapshot` that is used to help ensure\n   * atomicity in multiple snap updates.\n   *\n   * @param snapId - The snap id.\n   * @throws {@link Error}. If the snap exists before creation or if creation fails.\n   * @returns A `RollbackSnapshot`.\n   */\n  #createRollbackSnapshot(snapId: SnapId): RollbackSnapshot {\n    assert(\n      this.#rollbackSnapshots.get(snapId) === undefined,\n      `Snap \"${snapId}\" rollback snapshot already exists.`,\n    );\n\n    this.#rollbackSnapshots.set(snapId, {\n      statePatches: [],\n      permissions: {},\n      newVersion: '',\n    });\n\n    const newRollbackSnapshot = this.#rollbackSnapshots.get(snapId);\n\n    assert(\n      newRollbackSnapshot !== undefined,\n      `Snapshot creation failed for ${snapId}.`,\n    );\n    return newRollbackSnapshot;\n  }\n\n  /**\n   * Rolls back a snap to its previous state, permissions\n   * and source code based on the `RollbackSnapshot` that\n   * is captured during the update process. After rolling back,\n   * the function also emits an event indicating that the\n   * snap has been rolled back and it clears the snapshot\n   * for that snap.\n   *\n   * @param snapId - The snap id.\n   * @throws {@link Error}. If a snapshot does not exist.\n   */\n  async #rollbackSnap(snapId: SnapId) {\n    const rollbackSnapshot = this.#getRollbackSnapshot(snapId);\n    if (!rollbackSnapshot) {\n      throw new Error('A snapshot does not exist for this snap.');\n    }\n\n    await this.stopSnap(snapId, SnapStatusEvents.Stop);\n    // Always set to stopped even if it wasn't running initially\n    if (this.getSnap(snapId)?.status !== SnapStatus.Stopped) {\n      this.#transition(snapId, SnapStatusEvents.Stop);\n    }\n\n    const {\n      statePatches,\n      permissions,\n      previousInitialConnections,\n      newInitialConnections,\n      previousSourceCode,\n    } = rollbackSnapshot;\n\n    if (statePatches?.length) {\n      this.applyPatches(statePatches);\n    }\n\n    // If the snap has a previous source code, set it back to the previous source code.\n    // If it doesn't, we don't need to set it back to the previous source code because it means we haven't updated the source code.\n    if (previousSourceCode) {\n      await this.#setSourceCode(snapId, previousSourceCode);\n    }\n\n    // Reset snap status, as we may have been in another state when we stored state patches\n    // But now we are 100% in a stopped state\n    if (this.getSnap(snapId)?.status !== SnapStatus.Stopped) {\n      this.update((state) => {\n        state.snaps[snapId].status = SnapStatus.Stopped;\n      });\n    }\n\n    this.#updatePermissions({\n      snapId,\n      unusedPermissions: permissions.granted,\n      newPermissions: permissions.revoked,\n      requestData: permissions.requestData,\n    });\n\n    // Calling this in reverse order to undo the changes\n    this.#handleInitialConnections(\n      snapId,\n      newInitialConnections ?? null,\n      previousInitialConnections ?? {},\n    );\n\n    const truncatedSnap = this.#getTruncatedSnapExpect(snapId);\n\n    this.messenger.publish(\n      'SnapController:snapRolledback',\n      truncatedSnap,\n      rollbackSnapshot.newVersion,\n    );\n\n    this.#rollbackSnapshots.delete(snapId);\n  }\n\n  /**\n   * Iterates through an array of snap ids\n   * and calls `rollbackSnap` on them.\n   *\n   * @param snapIds - An array of snap ids.\n   */\n  async #rollbackSnaps(snapIds: SnapId[]) {\n    for (const snapId of snapIds) {\n      await this.#rollbackSnap(snapId);\n    }\n  }\n\n  #getRuntime(snapId: SnapId): SnapRuntimeData | undefined {\n    return this.#snapsRuntimeData.get(snapId);\n  }\n\n  #getRuntimeExpect(snapId: SnapId): SnapRuntimeData {\n    const runtime = this.#getRuntime(snapId);\n    assert(runtime !== undefined, `Snap \"${snapId}\" runtime data not found`);\n    return runtime;\n  }\n\n  #setupRuntime(snapId: SnapId) {\n    if (this.#snapsRuntimeData.has(snapId)) {\n      return;\n    }\n\n    const snap = this.getSnap(snapId);\n    const interpreter = interpret(this.#statusMachine);\n    interpreter.start({\n      context: { snapId },\n      value:\n        snap?.status ??\n        (this.#statusMachine.config.initial as StatusStates['value']),\n    });\n\n    forceStrict(interpreter);\n\n    this.#snapsRuntimeData.set(snapId, {\n      lastRequest: null,\n      startPromise: null,\n      stopPromise: null,\n      installPromise: null,\n      encryptionKey: null,\n      encryptionSalt: null,\n      pendingInboundRequests: [],\n      pendingOutboundRequests: 0,\n      interpreter,\n      stateMutex: new Mutex(),\n      getStateMutex: new Mutex(),\n    });\n  }\n\n  /**\n   * Get the desired permissions including dynamic permissions. That is, if a\n   * dynamic permission was previously granted and at least one of its\n   * dependencies is still desired, it will be included in the desired\n   * permissions.\n   *\n   * @param oldPermissions - The old permissions.\n   * @param desiredPermissions - The desired permissions.\n   * @returns The desired permissions including dynamic permissions.\n   */\n  #getDesiredPermissions(\n    oldPermissions: SubjectPermissions<\n      ValidPermission<string, Caveat<string, any>>\n    >,\n    desiredPermissions: Record<string, Pick<PermissionConstraint, 'caveats'>>,\n  ) {\n    return Object.keys(oldPermissions).reduce<\n      Record<string, Pick<PermissionConstraint, 'caveats'>>\n    >((accumulator, permissionName) => {\n      if (this.#dynamicPermissions.includes(permissionName)) {\n        const hasDependencies = hasProperty(\n          DYNAMIC_PERMISSION_DEPENDENCIES,\n          permissionName,\n        );\n\n        const hasDependency = DYNAMIC_PERMISSION_DEPENDENCIES[\n          permissionName\n        ]?.some((dependency) => hasProperty(desiredPermissions, dependency));\n\n        // If the permission doesn't have dependencies, or if at least one of\n        // its dependencies is desired, include it in the desired permissions.\n        // NOTE: This effectively means that any permissions granted in the manifest\n        // that are considered dynamic, will not be automatically revoked\n        // when the permission is removed from the manifest.\n        // TODO: Deal with this technical debt.\n        if (!hasDependencies || hasDependency) {\n          accumulator[permissionName] = oldPermissions[permissionName];\n        }\n      }\n\n      return accumulator;\n    }, desiredPermissions);\n  }\n\n  #calculatePermissionsChange(\n    snapId: SnapId,\n    desiredPermissionsSet: Record<\n      string,\n      Pick<PermissionConstraint, 'caveats'>\n    >,\n  ): {\n    newPermissions: Record<string, Pick<PermissionConstraint, 'caveats'>>;\n    unusedPermissions: SubjectPermissions<\n      ValidPermission<string, Caveat<string, any>>\n    >;\n    approvedPermissions: SubjectPermissions<\n      ValidPermission<string, Caveat<string, any>>\n    >;\n  } {\n    const oldPermissions =\n      this.messenger.call('PermissionController:getPermissions', snapId) ?? {};\n    const desiredPermissionsSetWithDynamic = this.#getDesiredPermissions(\n      oldPermissions,\n      desiredPermissionsSet,\n    );\n\n    const newPermissions = permissionsDiff(\n      desiredPermissionsSetWithDynamic,\n      oldPermissions,\n    );\n\n    // TODO: The assumption that these are unused only holds so long as we do\n    //  not permit dynamic permission requests.\n    const unusedPermissions = permissionsDiff(\n      oldPermissions,\n      desiredPermissionsSetWithDynamic,\n    );\n\n    // It's a Set Intersection of oldPermissions and desiredPermissionsSet\n    // oldPermissions ∖ (oldPermissions ∖ desiredPermissionsSet) ⟺ oldPermissions ∩ desiredPermissionsSet\n    const approvedPermissions = permissionsDiff(\n      oldPermissions,\n      unusedPermissions,\n    );\n\n    return { newPermissions, unusedPermissions, approvedPermissions };\n  }\n\n  #isSubjectConnectedToSnap(snapId: SnapId, origin: string) {\n    const subjectPermissions = this.messenger.call(\n      'PermissionController:getPermissions',\n      origin,\n    ) as SubjectPermissions<PermissionConstraint>;\n\n    const existingCaveat = subjectPermissions?.[\n      WALLET_SNAP_PERMISSION_KEY\n    ]?.caveats?.find((caveat) => caveat.type === SnapCaveatType.SnapIds);\n\n    return Boolean((existingCaveat?.value as Record<string, Json>)?.[snapId]);\n  }\n\n  #calculateConnectionsChange(\n    snapId: SnapId,\n    oldConnectionsSet: Record<string, Json>,\n    desiredConnectionsSet: Record<string, Json>,\n  ): {\n    newConnections: Record<string, Json>;\n    unusedConnections: Record<string, Json>;\n    approvedConnections: Record<string, Json>;\n  } {\n    // Filter out any origins that have been revoked since last install/update.\n    // That way they will be represented as new.\n    const filteredOldConnections = Object.keys(oldConnectionsSet)\n      .filter((origin) => this.#isSubjectConnectedToSnap(snapId, origin))\n      .reduce<Record<string, Json>>((accumulator, origin) => {\n        accumulator[origin] = oldConnectionsSet[origin];\n        return accumulator;\n      }, {});\n\n    const newConnections = setDiff(\n      desiredConnectionsSet,\n      filteredOldConnections,\n    );\n\n    const unusedConnections = setDiff(\n      filteredOldConnections,\n      desiredConnectionsSet,\n    );\n\n    // It's a Set Intersection of oldConnections and desiredConnectionsSet\n    // oldConnections ∖ (oldConnections ∖ desiredConnectionsSet) ⟺ oldConnections ∩ desiredConnectionsSet\n    const approvedConnections = setDiff(\n      filteredOldConnections,\n      unusedConnections,\n    );\n\n    return { newConnections, unusedConnections, approvedConnections };\n  }\n\n  /**\n   * Update the permissions for a snap following an install, update or rollback.\n   *\n   * Grants newly requested permissions and revokes unused/revoked permissions.\n   *\n   * @param args - An options bag.\n   * @param args.snapId - The snap ID.\n   * @param args.newPermissions - New permissions to be granted.\n   * @param args.unusedPermissions - Unused permissions to be revoked.\n   * @param args.requestData - Optional request data from an approval.\n   */\n  #updatePermissions({\n    snapId,\n    unusedPermissions = {},\n    newPermissions = {},\n    requestData,\n  }: {\n    snapId: SnapId;\n    newPermissions?:\n      | RequestedPermissions\n      | Record<string, Pick<PermissionConstraint, 'caveats'>>;\n    unusedPermissions?:\n      | RequestedPermissions\n      | SubjectPermissions<ValidPermission<string, Caveat<string, any>>>;\n    requestData?: Record<string, unknown>;\n  }) {\n    const unusedPermissionsKeys = Object.keys(unusedPermissions);\n    if (isNonEmptyArray(unusedPermissionsKeys)) {\n      this.messenger.call('PermissionController:revokePermissions', {\n        [snapId]: unusedPermissionsKeys,\n      });\n    }\n\n    if (isNonEmptyArray(Object.keys(newPermissions))) {\n      this.messenger.call('PermissionController:grantPermissions', {\n        approvedPermissions: newPermissions,\n        subject: { origin: snapId },\n        requestData,\n      });\n    }\n  }\n\n  /**\n   * Checks if a snap will pass version validation checks\n   * with the new version range that is requested. The first\n   * check that is done is to check if the existing snap version\n   * falls inside the requested range. If it does, we want to return\n   * false because we do not care to create a rollback snapshot in\n   * that scenario. The second check is to ensure that the current\n   * snap version is not greater than all possible versions in\n   * the requested version range. If it is, then we also want\n   * to return false in that scenario.\n   *\n   * @param snapId - The snap id.\n   * @param newVersionRange - The new version range being requested.\n   * @returns `true` if validation checks pass and `false` if they do not.\n   */\n  #isValidUpdate(snapId: SnapId, newVersionRange: SemVerRange): boolean {\n    const existingSnap = this.getSnapExpect(snapId);\n\n    if (satisfiesVersionRange(existingSnap.version, newVersionRange)) {\n      return false;\n    }\n\n    if (gtRange(existingSnap.version, newVersionRange)) {\n      return false;\n    }\n\n    return true;\n  }\n\n  /**\n   * Call a lifecycle hook for all runnable Snaps.\n   *\n   * @param origin - The origin of the request.\n   * @param handler - The lifecycle hook to call. This should be one of the\n   * supported lifecycle hooks.\n   */\n  #callLifecycleHooks(origin: string, handler: HandlerType) {\n    const snaps = this.getRunnableSnaps();\n    for (const { id } of snaps) {\n      const hasLifecycleHooksEndowment = this.messenger.call(\n        'PermissionController:hasPermission',\n        id,\n        SnapEndowments.LifecycleHooks,\n      );\n\n      if (!hasLifecycleHooksEndowment) {\n        continue;\n      }\n\n      this.#callLifecycleHook(origin, id, handler).catch((error) => {\n        logError(\n          `Error calling lifecycle hook \"${handler}\" for Snap \"${id}\": ${getErrorMessage(\n            error,\n          )}`,\n        );\n      });\n    }\n  }\n\n  /**\n   * Call a lifecycle hook on a snap, if the snap has the\n   * `endowment:lifecycle-hooks` permission. If the snap does not have the\n   * permission, nothing happens.\n   *\n   * @param origin - The origin.\n   * @param snapId - The snap ID.\n   * @param handler - The lifecycle hook to call. This should be one of the\n   * supported lifecycle hooks.\n   * @private\n   */\n  async #callLifecycleHook(\n    origin: string,\n    snapId: SnapId,\n    handler: HandlerType,\n  ) {\n    const permissionName = handlerEndowments[handler];\n\n    assert(permissionName, 'Lifecycle hook must have an endowment.');\n\n    const hasPermission = this.messenger.call(\n      'PermissionController:hasPermission',\n      snapId,\n      permissionName,\n    );\n\n    if (!hasPermission) {\n      return;\n    }\n\n    await this.handleRequest({\n      snapId,\n      handler,\n      origin,\n      request: {\n        jsonrpc: '2.0',\n        method: handler,\n      },\n    });\n  }\n\n  /**\n   * Handle the `KeyringController:lock` event.\n   *\n   * Currently this clears the cached encrypted state (if any) for all Snaps.\n   */\n  #handleLock() {\n    for (const runtime of this.#snapsRuntimeData.values()) {\n      runtime.encryptionKey = null;\n      runtime.encryptionSalt = null;\n      runtime.state = undefined;\n    }\n  }\n\n  /**\n   * Check whether a Snap has valid source code in storage.\n   *\n   * @param snapId - The Snap ID.\n   * @returns True if the source code is valid, otherwise false.\n   */\n  async #hasSourceCode(snapId: SnapId): Promise<boolean> {\n    const sourceCode = await this.#getSourceCode(snapId).catch(() => null);\n    return typeof sourceCode === 'string';\n  }\n\n  /**\n   * Retrieve the source code for a Snap from storage.\n   *\n   * @param snapId - The Snap ID.\n   * @returns The source code for the Snap.\n   */\n  async #getSourceCode(snapId: SnapId): Promise<string> {\n    const storage = await this.#getStorage(snapId);\n\n    assert(storage?.sourceCode, `Source code for Snap \"${snapId}\" not found.`);\n\n    return storage.sourceCode;\n  }\n\n  /**\n   * Retrieve the storage for a Snap from the StorageService.\n   *\n   * @param snapId - The Snap ID.\n   * @returns The storage for the Snap.\n   */\n  async #getStorage(snapId: SnapId): Promise<StorageServiceSnapData | null> {\n    const { result, error } = await this.messenger.call(\n      'StorageService:getItem',\n      this.name,\n      snapId,\n    );\n\n    assert(!error, `Error retrieving storage for snap \"${snapId}\": ${error}`);\n\n    return result as StorageServiceSnapData | null;\n  }\n\n  /**\n   * Store the source code for a Snap in storage.\n   * For now we call the StorageService with just the source code\n   * since that's all we store.\n   *\n   * @param snapId - The Snap ID.\n   * @param sourceCode - The source code for the Snap.\n   */\n  async #setSourceCode(snapId: SnapId, sourceCode: string): Promise<void> {\n    await this.messenger.call('StorageService:setItem', this.name, snapId, {\n      sourceCode,\n    });\n  }\n\n  /**\n   * Remove the source code for a Snap from storage.\n   * Since we only store source code, this effectively\n   * removes all data for the Snap for now.\n   *\n   * @param snapId - The Snap ID.\n   */\n  async #removeSourceCode(snapId: SnapId): Promise<void> {\n    await this.messenger.call('StorageService:removeItem', this.name, snapId);\n  }\n\n  /**\n   * Clear all Snap data from the StorageService.\n   */\n  async #clearStorageService(): Promise<void> {\n    await this.messenger.call('StorageService:clear', this.name);\n  }\n}\n"]}