{"version":3,"file":"snaps.mjs","sourceRoot":"","sources":["../src/snaps.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n  Caveat,\n  SubjectPermissions,\n  PermissionConstraint,\n} from '@metamask/permission-controller';\nimport type { BlockReason } from '@metamask/snaps-registry';\nimport {\n  selectiveUnion,\n  type SnapId,\n  type Snap as TruncatedSnap,\n} from '@metamask/snaps-sdk';\nimport type { Struct } from '@metamask/superstruct';\nimport {\n  is,\n  empty,\n  enums,\n  intersection,\n  literal,\n  refine,\n  string,\n  validate,\n} from '@metamask/superstruct';\nimport type { Json } from '@metamask/utils';\nimport { assert, isObject, assertStruct, definePattern } from '@metamask/utils';\nimport { base64 } from '@scure/base';\nimport stableStringify from 'fast-json-stable-stringify';\nimport validateNPMPackage from 'validate-npm-package-name';\n\nimport { SnapCaveatType } from './caveats';\nimport { checksumFiles } from './checksum';\nimport type { LocalizationFile } from './localization';\nimport type {\n  InitialConnections,\n  SnapManifest,\n  SnapPermissions,\n} from './manifest/validation';\nimport type { FetchedSnapFiles, SnapsPermissionRequest } from './types';\nimport { SnapIdPrefixes, uri } from './types';\nimport type { VirtualFile } from './virtual-file';\n\n// This RegEx matches valid npm package names (with some exceptions) and space-\n// separated alphanumerical words, optionally with dashes and underscores.\n// The RegEx consists of two parts. The first part matches space-separated\n// words. It is based on the following Stackoverflow answer:\n// https://stackoverflow.com/a/34974982\n// The second part, after the pipe operator, is the same RegEx used for the\n// `name` field of the official package.json JSON Schema, except that we allow\n// mixed-case letters. It was originally copied from:\n// https://github.com/SchemaStore/schemastore/blob/81a16897c1dabfd98c72242a5fd62eb080ff76d8/src/schemas/json/package.json#L132-L138\nexport const PROPOSED_NAME_REGEX =\n  /^(?:[A-Za-z0-9-_]+( [A-Za-z0-9-_]+)*)|(?:(?:@[A-Za-z0-9-*~][A-Za-z0-9-*._~]*\\/)?[A-Za-z0-9-~][A-Za-z0-9-._~]*)$/u;\n\nexport enum SnapStatus {\n  Installing = 'installing',\n  Updating = 'updating',\n  Running = 'running',\n  Stopped = 'stopped',\n  Crashed = 'crashed',\n}\n\nexport enum SnapStatusEvents {\n  Start = 'START',\n  Stop = 'STOP',\n  Crash = 'CRASH',\n  Update = 'UPDATE',\n}\n\nexport type StatusContext = { snapId: SnapId };\nexport type StatusEvents = { type: SnapStatusEvents };\nexport type StatusStates = {\n  value: SnapStatus;\n  context: StatusContext;\n};\nexport type Status = StatusStates['value'];\n\nexport type VersionHistory = {\n  origin: string;\n  version: string;\n  // Unix timestamp\n  date: number;\n};\n\nexport type SnapAuxiliaryFile = {\n  path: string;\n  // Value here should be stored as base64\n  value: string;\n};\n\n/**\n * @deprecated Use SnapAuxiliaryFile instead. This was a typo that has been fixed.\n */\nexport type SnapAuxilaryFile = SnapAuxiliaryFile;\n\n/**\n * A Snap's data as stored in the StorageService.\n */\nexport type StorageServiceSnapData = {\n  sourceCode: string;\n};\n\n/**\n * A Snap's data as stored in the StorageService and the SnapController state.\n */\nexport type PersistedSnap = Snap & StorageServiceSnapData;\n\n/**\n * A Snap as it exists in {@link SnapController} state.\n */\nexport type Snap = TruncatedSnap & {\n  /**\n   * The initial connections of the Snap, optional, requested on installation.\n   */\n  initialConnections?: InitialConnections;\n  /**\n   * The initial permissions of the Snap, which will be requested when it is\n   * installed.\n   */\n  initialPermissions: SnapPermissions;\n\n  /**\n   * The Snap's manifest file.\n   */\n  manifest: SnapManifest;\n\n  /**\n   * Information detailing why the snap is blocked.\n   */\n  blockInformation?: BlockReason;\n\n  /**\n   * The current status of the Snap, e.g. whether it's running or stopped.\n   */\n  status: Status;\n\n  /**\n   * The version history of the Snap.\n   * Can be used to derive when the Snap was installed, when it was updated to a certain version and who requested the change.\n   */\n  versionHistory: VersionHistory[];\n\n  /**\n   * Static auxiliary files that can be loaded at runtime.\n   */\n  auxiliaryFiles?: SnapAuxiliaryFile[];\n\n  /**\n   * Localization files which are used to translate the manifest.\n   */\n  localizationFiles?: LocalizationFile[];\n\n  /**\n   * Flag to signal whether this snap was preinstalled or not.\n   *\n   * A lack of specifying this option will be deemed as not preinstalled.\n   */\n  preinstalled?: boolean;\n\n  /**\n   * Flag to signal whether this snap is removable or not.\n   *\n   * A lack of specifying this option will be deemed as removable.\n   */\n  removable?: boolean;\n\n  /**\n   * Flag to signal whether this snap should be hidden from the user or not.\n   */\n  hidden?: boolean;\n\n  /**\n   * Flag to signal whether this snap should hide the Snap branding like header or avatar in the UI or not.\n   */\n  hideSnapBranding?: boolean;\n};\n\nexport type TruncatedSnapFields =\n  | 'id'\n  | 'initialPermissions'\n  | 'version'\n  | 'enabled'\n  | 'blocked';\n\n/**\n * Gets a checksummable manifest by removing the shasum property and reserializing the JSON using a deterministic algorithm.\n *\n * @param manifest - The manifest itself.\n * @returns A virtual file containing the checksummable manifest.\n */\nfunction getChecksummableManifest(\n  manifest: VirtualFile<SnapManifest>,\n): VirtualFile {\n  const manifestCopy = manifest.clone() as VirtualFile<any>;\n  delete manifestCopy.result.source.shasum;\n\n  // We use fast-json-stable-stringify to deterministically serialize the JSON\n  // This is required before checksumming so we get reproducible checksums across platforms etc\n  manifestCopy.value = stableStringify(manifestCopy.result);\n  return manifestCopy;\n}\n\n/**\n * Calculates the Base64-encoded SHA-256 digest of all required Snap files.\n *\n * @param files - All required Snap files to be included in the checksum.\n * @returns The Base64-encoded SHA-256 digest of the source code.\n */\nexport async function getSnapChecksum(\n  files: FetchedSnapFiles,\n): Promise<string> {\n  const { manifest, sourceCode, svgIcon, auxiliaryFiles, localizationFiles } =\n    files;\n\n  const all = [\n    getChecksummableManifest(manifest),\n    sourceCode,\n    svgIcon,\n    ...auxiliaryFiles,\n    ...localizationFiles,\n  ].filter((file) => file !== undefined);\n\n  return base64.encode(await checksumFiles(all as VirtualFile[]));\n}\n\n/**\n * Checks whether the `source.shasum` property of a Snap manifest matches the\n * shasum of the snap.\n *\n * @param files - All required Snap files to be included in the checksum.\n * @param errorMessage - The error message to throw if validation fails.\n */\nexport async function validateSnapShasum(\n  files: FetchedSnapFiles,\n  errorMessage = 'Invalid Snap manifest: manifest shasum does not match computed shasum.',\n): Promise<void> {\n  if (files.manifest.result.source.shasum !== (await getSnapChecksum(files))) {\n    throw new Error(errorMessage);\n  }\n}\n\nexport const LOCALHOST_HOSTNAMES = ['localhost', '127.0.0.1', '[::1]'] as const;\n\n// Require snap ids to only consist of printable ASCII characters\nexport const BaseSnapIdStruct = definePattern(\n  'Base Snap Id',\n  /^[\\x21-\\x7E]*$/u,\n);\n\nconst LocalSnapIdSubUrlStruct = uri({\n  protocol: enums(['http:', 'https:']),\n  hostname: enums(LOCALHOST_HOSTNAMES),\n  hash: empty(string()),\n  search: empty(string()),\n});\n\nexport const LocalSnapIdStruct = refine(\n  BaseSnapIdStruct,\n  'local Snap Id',\n  (value) => {\n    if (!value.startsWith(SnapIdPrefixes.local)) {\n      return `Expected local snap ID, got \"${value}\".`;\n    }\n\n    const [error] = validate(\n      value.slice(SnapIdPrefixes.local.length),\n      LocalSnapIdSubUrlStruct,\n    );\n    return error ?? true;\n  },\n);\nexport const NpmSnapIdStruct = intersection([\n  BaseSnapIdStruct,\n  uri({\n    protocol: literal(SnapIdPrefixes.npm),\n    pathname: refine(string(), 'package name', function* (value) {\n      const normalized = value.startsWith('/') ? value.slice(1) : value;\n      const { errors, validForNewPackages, warnings } =\n        validateNPMPackage(normalized);\n      if (!validForNewPackages) {\n        if (errors === undefined) {\n          assert(warnings !== undefined);\n          yield* warnings;\n        } else {\n          yield* errors;\n        }\n      }\n      return true;\n    }),\n    search: empty(string()),\n    hash: empty(string()),\n  }),\n]) as unknown as Struct<string, null>;\n\nexport const HttpSnapIdStruct = intersection([\n  BaseSnapIdStruct,\n  uri({\n    protocol: enums(['http:', 'https:']),\n    search: empty(string()),\n    hash: empty(string()),\n  }),\n]) as unknown as Struct<string, null>;\n\nexport const SnapIdPrefixStruct = refine(\n  string(),\n  'Snap ID prefix',\n  (value) => {\n    if (\n      Object.values(SnapIdPrefixes).some((prefix) => value.startsWith(prefix))\n    ) {\n      return true;\n    }\n\n    const allowedPrefixes = Object.values(SnapIdPrefixes)\n      .map((prefix) => `\"${prefix}\"`)\n      .join(', ');\n\n    return `Invalid or no prefix found. Expected Snap ID to start with one of: ${allowedPrefixes}, but received: \"${value}\"`;\n  },\n);\n\nexport const SnapIdStruct = selectiveUnion((value) => {\n  if (typeof value === 'string' && value.startsWith(SnapIdPrefixes.npm)) {\n    return NpmSnapIdStruct;\n  }\n\n  if (typeof value === 'string' && value.startsWith(SnapIdPrefixes.local)) {\n    return LocalSnapIdStruct;\n  }\n\n  return SnapIdPrefixStruct;\n});\n\n/**\n * Extracts the snap prefix from a snap ID.\n *\n * @param snapId - The snap ID to extract the prefix from.\n * @returns The snap prefix from a snap id, e.g. `npm:`.\n */\nexport function getSnapPrefix(snapId: string): SnapIdPrefixes {\n  const prefix = Object.values(SnapIdPrefixes).find((possiblePrefix) =>\n    snapId.startsWith(possiblePrefix),\n  );\n  if (prefix !== undefined) {\n    return prefix;\n  }\n  throw new Error(`Invalid or no prefix found for \"${snapId}\"`);\n}\n\n/**\n * Strips snap prefix from a full snap ID.\n *\n * @param snapId - The snap ID to strip.\n * @returns The stripped snap ID.\n */\nexport function stripSnapPrefix(snapId: string): string {\n  return snapId.replace(getSnapPrefix(snapId), '');\n}\n\n/**\n * Check if the given value is a valid snap ID. This function is a type guard,\n * and will narrow the type of the value to `SnapId` if it returns `true`.\n *\n * @param value - The value to check.\n * @returns `true` if the value is a valid snap ID, and `false` otherwise.\n */\nexport function isSnapId(value: unknown): value is SnapId {\n  return is(value, SnapIdStruct);\n}\n\n/**\n * Assert that the given value is a valid snap ID.\n *\n * @param value - The value to check.\n * @throws If the value is not a valid snap ID.\n */\nexport function assertIsValidSnapId(value: unknown): asserts value is SnapId {\n  assertStruct(value, SnapIdStruct, 'Invalid snap ID');\n}\n\n/**\n * Utility function to check if an origin has permission (and caveat) for a particular snap.\n *\n * @param permissions - An origin's permissions object.\n * @param snapId - The id of the snap.\n * @returns A boolean based on if an origin has the specified snap.\n */\nexport function isSnapPermitted(\n  permissions: SubjectPermissions<PermissionConstraint>,\n  snapId: SnapId,\n) {\n  return Boolean(\n    (\n      (\n        (permissions?.wallet_snap?.caveats?.find(\n          (caveat) => caveat.type === SnapCaveatType.SnapIds,\n        ) ?? {}) as Caveat<string, Json>\n      ).value as Record<string, unknown>\n    )?.[snapId],\n  );\n}\n\n/**\n * Checks whether the passed in requestedPermissions is a valid\n * permission request for a `wallet_snap` permission.\n *\n * @param requestedPermissions - The requested permissions.\n * @throws If the criteria is not met.\n */\nexport function verifyRequestedSnapPermissions(\n  requestedPermissions: unknown,\n): asserts requestedPermissions is SnapsPermissionRequest {\n  assert(\n    isObject(requestedPermissions),\n    'Requested permissions must be an object.',\n  );\n\n  const { wallet_snap: walletSnapPermission } = requestedPermissions;\n\n  assert(\n    isObject(walletSnapPermission),\n    'wallet_snap is missing from the requested permissions.',\n  );\n\n  const { caveats } = walletSnapPermission;\n\n  assert(\n    Array.isArray(caveats) && caveats.length === 1,\n    'wallet_snap must have a caveat property with a single-item array value.',\n  );\n\n  const [caveat] = caveats;\n\n  assert(\n    isObject(caveat) &&\n      caveat.type === SnapCaveatType.SnapIds &&\n      isObject(caveat.value),\n    `The requested permissions do not have a valid ${SnapCaveatType.SnapIds} caveat.`,\n  );\n}\n\nexport type { Snap as TruncatedSnap } from '@metamask/snaps-sdk';\n"]}