{"version":3,"file":"utils.cjs","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n  HardenedBIP32Node,\n  BIP32Node,\n  SLIP10PathNode,\n  SupportedCurve,\n  CryptographicFunctions,\n} from '@metamask/key-tree';\nimport { SLIP10Node } from '@metamask/key-tree';\nimport type { Messenger } from '@metamask/messenger';\nimport { rpcErrors } from '@metamask/rpc-errors';\nimport type { MagicValue } from '@metamask/snaps-utils';\nimport { refine, string } from '@metamask/superstruct';\nimport {\n  assertExhaustive,\n  add0x,\n  assert,\n  concatBytes,\n  createDataView,\n  stringToBytes,\n} from '@metamask/utils';\nimport { keccak_256 as keccak256 } from '@noble/hashes/sha3';\n\nimport { SnapEndowments } from './endowments';\nimport type { KeyringControllerWithKeyringV2UnsafeAction } from './types';\n\nconst HARDENED_VALUE = 0x80000000;\n\nexport const FORBIDDEN_KEYS = ['constructor', '__proto__', 'prototype'];\n\n/**\n * Maps an interface with method hooks to an object, using the keys of the\n * interface, and `true` as value. This ensures that the `methodHooks` object\n * has the same values as the interface.\n */\nexport type MethodHooksObject<HooksType extends Record<string, unknown>> = {\n  [Key in keyof HooksType]: true;\n};\n\n/**\n * Get a BIP-32 derivation path array from a hash, which is compatible with\n * `@metamask/key-tree`. The hash is assumed to be 32 bytes long.\n *\n * @param hash - The hash to derive indices from.\n * @returns The derived indices as a {@link HardenedBIP32Node} array.\n */\nfunction getDerivationPathArray(hash: Uint8Array): HardenedBIP32Node[] {\n  const array: HardenedBIP32Node[] = [];\n  const view = createDataView(hash);\n\n  for (let index = 0; index < 8; index++) {\n    const uint32 = view.getUint32(index * 4);\n\n    // This is essentially `index | 0x80000000`. Because JavaScript numbers are\n    // signed, we use the bitwise unsigned right shift operator to ensure that\n    // the result is a positive number.\n    // eslint-disable-next-line no-bitwise\n    const pathIndex = (uint32 | HARDENED_VALUE) >>> 0;\n    array.push(`bip32:${pathIndex - HARDENED_VALUE}'` as const);\n  }\n\n  return array;\n}\n\ntype BaseDeriveEntropyOptions = {\n  /**\n   * The input value to derive entropy from.\n   */\n  input: string;\n\n  /**\n   * An optional salt to use when deriving entropy.\n   */\n  salt?: string;\n\n  /**\n   * A hardened BIP-32 index, which is used to derive the root key from the\n   * mnemonic phrase.\n   */\n  magic: MagicValue;\n\n  /**\n   * The cryptographic functions to use for the derivation.\n   */\n  cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\ntype SeedDeriveEntropyOptions = BaseDeriveEntropyOptions & {\n  /**\n   * The mnemonic seed to use for entropy derivation.\n   */\n  seed: Uint8Array;\n};\n\n/**\n * Get the derivation path to use for entropy derivation.\n *\n * This is based on the reference implementation of\n * [SIP-6](https://metamask.github.io/SIPs/SIPS/sip-6).\n *\n * @param options - The options for entropy derivation.\n * @param options.input - The input value to derive entropy from.\n * @param options.salt - An optional salt to use when deriving entropy.\n * @param options.magic - A hardened BIP-32 index, which is used to derive the\n * root key from the mnemonic phrase.\n * @returns The derivation path to be used for entropy key derivation.\n */\nfunction getEntropyDerivationPath({\n  input,\n  salt,\n  magic,\n}: Required<Omit<BaseDeriveEntropyOptions, 'cryptographicFunctions'>>):\n  | BIP32Node[]\n  | SLIP10PathNode[] {\n  const inputBytes = stringToBytes(input);\n  const saltBytes = stringToBytes(salt);\n\n  // Get the derivation path from the snap ID.\n  const hash = keccak256(concatBytes([inputBytes, keccak256(saltBytes)]));\n  const computedDerivationPath = getDerivationPathArray(hash);\n\n  return [`bip32:${magic}`, ...computedDerivationPath];\n}\n\n/**\n * Derive entropy from the given mnemonic seed and salt.\n *\n * This is based on the reference implementation of\n * [SIP-6](https://metamask.github.io/SIPs/SIPS/sip-6).\n *\n * @param options - The options for entropy derivation.\n * @param options.input - The input value to derive entropy from.\n * @param options.salt - An optional salt to use when deriving entropy.\n * @param options.seed - The mnemonic seed to use for entropy\n * derivation.\n * @param options.magic - A hardened BIP-32 index, which is used to derive the\n * root key from the mnemonic phrase.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the derivation.\n * @returns The derived entropy.\n */\nexport async function deriveEntropyFromSeed({\n  input,\n  salt = '',\n  seed,\n  magic,\n  cryptographicFunctions,\n}: SeedDeriveEntropyOptions) {\n  const computedDerivationPath = getEntropyDerivationPath({\n    input,\n    salt,\n    magic,\n  });\n\n  // Derive the private key using BIP-32.\n  const { privateKey } = await SLIP10Node.fromSeed(\n    {\n      derivationPath: [seed, ...computedDerivationPath],\n      curve: 'secp256k1',\n    },\n    cryptographicFunctions,\n  );\n\n  // This should never happen, but this keeps TypeScript happy.\n  assert(privateKey, 'Failed to derive the entropy.');\n\n  return add0x(privateKey);\n}\n\n/**\n * Get the path prefix to use for key derivation in `key-tree`. This assumes the\n * following:\n *\n * - The Secp256k1 curve always uses the BIP-32 specification.\n * - The Ed25519 curve always uses the SLIP-10 specification.\n * - The BIP-32-Ed25519 curve always uses the CIP-3 specification.\n *\n * While this does not matter in most situations (no known case at the time of\n * writing), `key-tree` requires a specific specification to be used.\n *\n * @param curve - The curve to get the path prefix for. The curve is NOT\n * validated by this function.\n * @returns The path prefix, i.e., `bip32` or `slip10`.\n */\nexport function getPathPrefix(\n  curve: SupportedCurve,\n): 'bip32' | 'slip10' | 'cip3' {\n  switch (curve) {\n    case 'secp256k1':\n      return 'bip32';\n    case 'ed25519':\n      return 'slip10';\n    case 'ed25519Bip32':\n      return 'cip3';\n    default:\n      return assertExhaustive(curve);\n  }\n}\n\ntype BaseGetNodeArgs = {\n  curve: SupportedCurve;\n  path: string[];\n  cryptographicFunctions: CryptographicFunctions | undefined;\n};\n\ntype GetNodeArgsMnemonic = BaseGetNodeArgs & {\n  secretRecoveryPhrase: Uint8Array;\n};\n\ntype GetNodeArgsSeed = BaseGetNodeArgs & {\n  seed: Uint8Array;\n};\n\n/**\n * Get a `key-tree`-compatible node.\n *\n * Note: This function assumes that all the parameters have been validated\n * beforehand.\n *\n * @param options - The derivation options.\n * @param options.curve - The curve to use for derivation.\n * @param options.secretRecoveryPhrase - The secret recovery phrase to use for\n * derivation.\n * @param options.path - The derivation path to use as array, starting with an\n * \"m\" as the first item.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the node.\n * @returns The `key-tree` SLIP-10 node.\n */\nexport async function getNodeFromMnemonic({\n  curve,\n  secretRecoveryPhrase,\n  path,\n  cryptographicFunctions,\n}: GetNodeArgsMnemonic) {\n  const prefix = getPathPrefix(curve);\n\n  return await SLIP10Node.fromDerivationPath(\n    {\n      curve,\n      derivationPath: [\n        secretRecoveryPhrase,\n        ...(path.slice(1).map((index) => `${prefix}:${index}`) as\n          | BIP32Node[]\n          | SLIP10PathNode[]),\n      ],\n    },\n    cryptographicFunctions,\n  );\n}\n\n/**\n * Get a `key-tree`-compatible node.\n *\n * Note: This function assumes that all the parameters have been validated\n * beforehand.\n *\n * @param options - The derivation options.\n * @param options.curve - The curve to use for derivation.\n * @param options.seed - The BIP-39 to use for\n * derivation.\n * @param options.path - The derivation path to use as array, starting with an\n * \"m\" as the first item.\n * @param options.cryptographicFunctions - The cryptographic functions to use\n * for the node.\n * @returns The `key-tree` SLIP-10 node.\n */\nexport async function getNodeFromSeed({\n  curve,\n  seed,\n  path,\n  cryptographicFunctions,\n}: GetNodeArgsSeed) {\n  const prefix = getPathPrefix(curve);\n\n  return await SLIP10Node.fromSeed(\n    {\n      curve,\n      derivationPath: [\n        seed,\n        ...(path.slice(1).map((index) => `${prefix}:${index}`) as\n          | BIP32Node[]\n          | SLIP10PathNode[]),\n      ],\n    },\n    cryptographicFunctions,\n  );\n}\n\n/**\n * Validate the key of a state object.\n *\n * @param key - The key to validate.\n * @returns `true` if the key is valid, `false` otherwise.\n */\nexport function isValidStateKey(key: string | undefined) {\n  if (key === undefined) {\n    return true;\n  }\n\n  return key.split('.').every((part) => part.length > 0);\n}\n\nexport const StateKeyStruct = refine(string(), 'state key', (value) => {\n  if (!isValidStateKey(value)) {\n    return 'Invalid state key. Each part of the key must be non-empty.';\n  }\n\n  return true;\n});\n\n/**\n * Get a value using the entropy source hooks: getMnemonic or getMnemonicSeed.\n * This function calls the passed hook and handles any errors that occur,\n * throwing formatted JSON-RPC errors.\n *\n * @param hook - The hook.\n * @param source - The entropy source to use.\n * @returns The secret recovery phrase.\n */\nexport async function getValueFromEntropySource(\n  hook: (source?: string | undefined) => Promise<Uint8Array>,\n  source?: string | undefined,\n): Promise<Uint8Array> {\n  try {\n    return await hook(source);\n  } catch (error) {\n    if (error instanceof Error) {\n      throw rpcErrors.invalidParams({\n        message: error.message,\n      });\n    }\n\n    throw rpcErrors.internal({\n      message: 'An unknown error occurred.',\n      data: {\n        error: error.toString(),\n      },\n    });\n  }\n}\n\n/**\n * The permissions that allow a Snap to show UI. Snaps must have at least one\n * of these permissions to use the interface management RPC methods.\n */\nexport const UI_PERMISSIONS = [\n  'snap_dialog',\n  'snap_notify',\n  SnapEndowments.HomePage,\n  SnapEndowments.SettingsPage,\n  SnapEndowments.TransactionInsight,\n  SnapEndowments.SignatureInsight,\n] as const;\n\nexport const HD_KEYRING = 'hd';\n\n/**\n * Get the mnemonic for a given entropy source. If no source is\n * provided, the primary HD keyring's mnemonic will be returned.\n *\n * @param messenger - The messenger.\n * @param source - The ID of the entropy source keyring.\n * @returns The mnemonic.\n */\nexport async function getMnemonic(\n  messenger: Messenger<string, KeyringControllerWithKeyringV2UnsafeAction>,\n  source?: string | undefined,\n): Promise<Uint8Array> {\n  if (!source) {\n    const mnemonic = (await messenger.call(\n      'KeyringController:withKeyringV2Unsafe',\n      {\n        type: HD_KEYRING,\n        index: 0,\n      },\n      async ({ keyring }) => keyring.mnemonic,\n    )) as Uint8Array | null;\n\n    if (!mnemonic) {\n      throw new Error('Primary keyring mnemonic unavailable.');\n    }\n\n    return mnemonic;\n  }\n\n  try {\n    const keyringData = await messenger.call(\n      'KeyringController:withKeyringV2Unsafe',\n      {\n        id: source,\n      },\n      async ({ keyring }) => ({\n        type: keyring.type,\n        mnemonic: keyring.mnemonic,\n      }),\n    );\n\n    const { type, mnemonic } = keyringData as {\n      type: string;\n      mnemonic?: Uint8Array;\n    };\n\n    // The keyring isn't guaranteed to have a mnemonic (e.g.,\n    // hardware wallets, which can't be used as entropy sources),\n    // so we throw an error if it doesn't.\n    assert(type === HD_KEYRING && mnemonic);\n\n    return mnemonic;\n  } catch {\n    throw new Error(`Entropy source with ID \"${source}\" not found.`);\n  }\n}\n\n/**\n * Get the mnemonic seed for a given entropy source. If no source is\n * provided, the primary HD keyring's mnemonic seed will be returned.\n *\n * @param messenger - The messenger.\n * @param source - The ID of the entropy source keyring.\n * @returns The mnemonic seed.\n */\nexport async function getMnemonicSeed(\n  messenger: Messenger<string, KeyringControllerWithKeyringV2UnsafeAction>,\n  source?: string | undefined,\n): Promise<Uint8Array> {\n  if (!source) {\n    const seed = (await messenger.call(\n      'KeyringController:withKeyringV2Unsafe',\n      {\n        type: HD_KEYRING,\n        index: 0,\n      },\n      async ({ keyring }) => keyring.seed,\n    )) as Uint8Array | null;\n\n    if (!seed) {\n      throw new Error('Primary keyring mnemonic unavailable.');\n    }\n\n    return seed;\n  }\n\n  try {\n    const keyringData = await messenger.call(\n      'KeyringController:withKeyringV2Unsafe',\n      {\n        id: source,\n      },\n      async ({ keyring }) => ({\n        type: keyring.type,\n        seed: keyring.seed,\n      }),\n    );\n\n    const { type, seed } = keyringData as { type: string; seed?: Uint8Array };\n\n    // The keyring isn't guaranteed to have a mnemonic (e.g.,\n    // hardware wallets, which can't be used as entropy sources),\n    // so we throw an error if it doesn't.\n    assert(type === HD_KEYRING && seed);\n\n    return seed;\n  } catch {\n    throw new Error(`Entropy source with ID \"${source}\" not found.`);\n  }\n}\n"]}