@babylonlabs-io/ts-sdk 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/BTCVaultRegistry.abi-BH2-LHxN.cjs +2 -0
  2. package/dist/BTCVaultRegistry.abi-BH2-LHxN.cjs.map +1 -0
  3. package/dist/{BTCVaultRegistry.abi-DBW0dyqH.js → BTCVaultRegistry.abi-BzNTa_EU.js} +19 -52
  4. package/dist/BTCVaultRegistry.abi-BzNTa_EU.js.map +1 -0
  5. package/dist/BTCVaultRegistryKeyEpochs.abi-Btg0nBz1.js +262 -0
  6. package/dist/BTCVaultRegistryKeyEpochs.abi-Btg0nBz1.js.map +1 -0
  7. package/dist/BTCVaultRegistryKeyEpochs.abi-CReWFJdu.cjs +2 -0
  8. package/dist/BTCVaultRegistryKeyEpochs.abi-CReWFJdu.cjs.map +1 -0
  9. package/dist/{PeginManager-8EUlm10F.cjs → PeginManager-BHplS4dM.cjs} +2 -2
  10. package/dist/{PeginManager-8EUlm10F.cjs.map → PeginManager-BHplS4dM.cjs.map} +1 -1
  11. package/dist/{PeginManager-QRwMUxZg.js → PeginManager-DcwGom01.js} +2 -2
  12. package/dist/{PeginManager-QRwMUxZg.js.map → PeginManager-DcwGom01.js.map} +1 -1
  13. package/dist/VaultErrors.abi-Boz4w97c.js +5 -0
  14. package/dist/VaultErrors.abi-Boz4w97c.js.map +1 -0
  15. package/dist/VaultErrors.abi-DQ18kM0L.cjs +2 -0
  16. package/dist/VaultErrors.abi-DQ18kM0L.cjs.map +1 -0
  17. package/dist/buildAndBroadcastReclaim-C7bq5wNM.cjs +2 -0
  18. package/dist/buildAndBroadcastReclaim-C7bq5wNM.cjs.map +1 -0
  19. package/dist/{buildAndBroadcastReclaim-DoprHX7o.js → buildAndBroadcastReclaim-CcQ0b1be.js} +466 -456
  20. package/dist/buildAndBroadcastReclaim-CcQ0b1be.js.map +1 -0
  21. package/dist/index.cjs +1 -1
  22. package/dist/index.js +232 -229
  23. package/dist/index.js.map +1 -1
  24. package/dist/pegin-registration-client-BogzOk8B.cjs +2 -0
  25. package/dist/pegin-registration-client-BogzOk8B.cjs.map +1 -0
  26. package/dist/{pegin-registration-client-BWMwxtr8.js → pegin-registration-client-DvyrUNku.js} +45 -44
  27. package/dist/pegin-registration-client-DvyrUNku.js.map +1 -0
  28. package/dist/peginState-CIibG9S_.js +75 -0
  29. package/dist/peginState-CIibG9S_.js.map +1 -0
  30. package/dist/peginState-IyE22wWh.cjs +2 -0
  31. package/dist/peginState-IyE22wWh.cjs.map +1 -0
  32. package/dist/{reservation-DOAHVT3B.js → reservation-BZQABu4g.js} +2 -2
  33. package/dist/{reservation-DOAHVT3B.js.map → reservation-BZQABu4g.js.map} +1 -1
  34. package/dist/{reservation-ECxjZi5t.cjs → reservation-CA5knoQ0.cjs} +2 -2
  35. package/dist/{reservation-ECxjZi5t.cjs.map → reservation-CA5knoQ0.cjs.map} +1 -1
  36. package/dist/{signer-set-reader-C6g47hdk.cjs → signer-set-reader-D-CyIYR5.cjs} +2 -2
  37. package/dist/{signer-set-reader-C6g47hdk.cjs.map → signer-set-reader-D-CyIYR5.cjs.map} +1 -1
  38. package/dist/{signer-set-reader-C1VmC9_U.js → signer-set-reader-DFF9MgQN.js} +2 -2
  39. package/dist/{signer-set-reader-C1VmC9_U.js.map → signer-set-reader-DFF9MgQN.js.map} +1 -1
  40. package/dist/tbv/core/clients/eth/index.cjs +1 -1
  41. package/dist/tbv/core/clients/eth/index.js +2 -2
  42. package/dist/tbv/core/clients/eth/types.d.ts +8 -0
  43. package/dist/tbv/core/clients/eth/types.d.ts.map +1 -1
  44. package/dist/tbv/core/clients/eth/vault-registry-reader.d.ts.map +1 -1
  45. package/dist/tbv/core/clients/index.cjs +1 -1
  46. package/dist/tbv/core/clients/index.js +2 -2
  47. package/dist/tbv/core/contracts/__tests__/vaultErrors.abi.test.d.ts +2 -0
  48. package/dist/tbv/core/contracts/__tests__/vaultErrors.abi.test.d.ts.map +1 -0
  49. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts +14 -40
  50. package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts.map +1 -1
  51. package/dist/tbv/core/contracts/abis/VaultErrors.abi.d.ts +3 -0
  52. package/dist/tbv/core/contracts/abis/VaultErrors.abi.d.ts.map +1 -0
  53. package/dist/tbv/core/contracts/abis/vaultErrors.abi.json.d.ts +4 -0
  54. package/dist/tbv/core/contracts/errors.d.ts +7 -2
  55. package/dist/tbv/core/contracts/errors.d.ts.map +1 -1
  56. package/dist/tbv/core/contracts/index.cjs +1 -1
  57. package/dist/tbv/core/contracts/index.d.ts +2 -1
  58. package/dist/tbv/core/contracts/index.d.ts.map +1 -1
  59. package/dist/tbv/core/contracts/index.js +13 -10
  60. package/dist/tbv/core/contracts/index.js.map +1 -1
  61. package/dist/tbv/core/index.cjs +1 -1
  62. package/dist/tbv/core/index.js +225 -222
  63. package/dist/tbv/core/index.js.map +1 -1
  64. package/dist/tbv/core/managers/index.cjs +1 -1
  65. package/dist/tbv/core/managers/index.js +1 -1
  66. package/dist/tbv/core/services/activation/activateVault.d.ts +50 -0
  67. package/dist/tbv/core/services/activation/activateVault.d.ts.map +1 -1
  68. package/dist/tbv/core/services/activation/index.d.ts +1 -1
  69. package/dist/tbv/core/services/activation/index.d.ts.map +1 -1
  70. package/dist/tbv/core/services/delegated-claim/__tests__/realWasmWatchtowerArtifacts.test.d.ts +9 -0
  71. package/dist/tbv/core/services/delegated-claim/__tests__/realWasmWatchtowerArtifacts.test.d.ts.map +1 -0
  72. package/dist/tbv/core/services/delegated-claim/assembleWatchtowerArtifacts.d.ts +5 -7
  73. package/dist/tbv/core/services/delegated-claim/assembleWatchtowerArtifacts.d.ts.map +1 -1
  74. package/dist/tbv/core/services/delegated-claim/index.d.ts +3 -4
  75. package/dist/tbv/core/services/delegated-claim/index.d.ts.map +1 -1
  76. package/dist/tbv/core/services/delegated-claim/planDelegatedClaimSigning.d.ts.map +1 -1
  77. package/dist/tbv/core/services/delegated-claim/readWatchtowerArtifacts.d.ts +14 -8
  78. package/dist/tbv/core/services/delegated-claim/readWatchtowerArtifacts.d.ts.map +1 -1
  79. package/dist/tbv/core/services/delegated-claim/types.d.ts +32 -19
  80. package/dist/tbv/core/services/delegated-claim/types.d.ts.map +1 -1
  81. package/dist/tbv/core/services/deposit/peginState.d.ts +20 -1
  82. package/dist/tbv/core/services/deposit/peginState.d.ts.map +1 -1
  83. package/dist/tbv/core/services/index.cjs +1 -1
  84. package/dist/tbv/core/services/index.js +58 -58
  85. package/dist/tbv/core/utils/index.cjs +1 -1
  86. package/dist/tbv/core/utils/index.js +1 -1
  87. package/dist/tbv/index.cjs +1 -1
  88. package/dist/tbv/index.js +225 -222
  89. package/dist/tbv/index.js.map +1 -1
  90. package/dist/tbv/integrations/aave/clients/abis/AaveIntegrationAdapter.abi.json.d.ts +7 -701
  91. package/dist/tbv/integrations/aave/clients/query.d.ts +2 -2
  92. package/dist/tbv/integrations/aave/index.cjs +1 -1
  93. package/dist/tbv/integrations/aave/index.cjs.map +1 -1
  94. package/dist/tbv/integrations/aave/index.js +119 -119
  95. package/dist/tbv/integrations/aave/index.js.map +1 -1
  96. package/dist/{toRefundInputs-BZXvuOMY.cjs → toRefundInputs-8DgBT_Bg.cjs} +2 -2
  97. package/dist/{toRefundInputs-BZXvuOMY.cjs.map → toRefundInputs-8DgBT_Bg.cjs.map} +1 -1
  98. package/dist/{toRefundInputs-dKDSvpVI.js → toRefundInputs-CCMNAoRx.js} +2 -2
  99. package/dist/{toRefundInputs-dKDSvpVI.js.map → toRefundInputs-CCMNAoRx.js.map} +1 -1
  100. package/dist/types-Bda75Od0.cjs.map +1 -1
  101. package/dist/types-C5jj3Cc-.js.map +1 -1
  102. package/package.json +3 -3
  103. package/dist/BTCVaultRegistry.abi-CohlJX7c.cjs +0 -2
  104. package/dist/BTCVaultRegistry.abi-CohlJX7c.cjs.map +0 -1
  105. package/dist/BTCVaultRegistry.abi-DBW0dyqH.js.map +0 -1
  106. package/dist/BTCVaultRegistryKeyEpochs.abi-BWoxwPQv.js +0 -266
  107. package/dist/BTCVaultRegistryKeyEpochs.abi-BWoxwPQv.js.map +0 -1
  108. package/dist/BTCVaultRegistryKeyEpochs.abi-DCJnzKer.cjs +0 -2
  109. package/dist/BTCVaultRegistryKeyEpochs.abi-DCJnzKer.cjs.map +0 -1
  110. package/dist/buildAndBroadcastReclaim-DjX7wVb2.cjs +0 -2
  111. package/dist/buildAndBroadcastReclaim-DjX7wVb2.cjs.map +0 -1
  112. package/dist/buildAndBroadcastReclaim-DoprHX7o.js.map +0 -1
  113. package/dist/pegin-registration-client-BWMwxtr8.js.map +0 -1
  114. package/dist/pegin-registration-client-D4EguWaz.cjs +0 -2
  115. package/dist/pegin-registration-client-D4EguWaz.cjs.map +0 -1
  116. package/dist/peginState-BU2ONFXF.js +0 -68
  117. package/dist/peginState-BU2ONFXF.js.map +0 -1
  118. package/dist/peginState-DUv10EJR.cjs +0 -2
  119. package/dist/peginState-DUv10EJR.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BTCVaultRegistryKeyEpochs.abi-Btg0nBz1.js","sources":["../src/tbv/core/contracts/errors.ts","../src/tbv/core/contracts/abis/BTCVaultRegistryKeyEpochs.abi.ts"],"sourcesContent":["/**\n * Contract Error Handling Utilities\n *\n * Provides utilities for extracting and handling contract revert errors.\n * Maps known error selectors to user-friendly messages.\n *\n * @module contracts/errors\n */\n\nimport { decodeAbiParameters, type Hex, toFunctionSelector } from \"viem\";\n\n/**\n * `PeginFingerprintChanged(bytes32 expected, bytes32 actual)`.\n *\n * Re-derived rather than copied: `keccak256(\"PeginFingerprintChanged(bytes32,bytes32)\")`\n * begins `0x846c25bb`. Source is\n * https://github.com/babylonlabs-io/vault-contracts-aave-v4/pull/555, and the\n * value matches that repo's generated `snapshots/selectors.md` at head\n * 86577e40. `BTCVaultRegistry.abi.ts` carries the matching error entry, and a\n * test asserts the two agree.\n */\nexport const PEGIN_FINGERPRINT_CHANGED_SELECTOR = \"0x846c25bb\";\n\n/**\n * Shown when the contract reverted with explicitly empty data (`0x`). That can\n * mean a revert with no reason or a call the contract does not recognise, so\n * the wording claims neither.\n */\nexport const EMPTY_REVERT_MESSAGE =\n \"The contract rejected this deposit without giving a reason. \" +\n \"Refresh the app and try again; if it keeps happening, contact support.\";\n\n/** `\"0x\"` + 4-byte selector + two abi-encoded `bytes32` words. */\nconst FINGERPRINT_REVERT_DATA_LENGTH = 2 + 8 + 64 * 2;\n\n/**\n * The registry rejected a peg-in registration because the protocol state it\n * resolves at inclusion no longer matches the state the Pre-Pegin was built\n * against.\n *\n * Typed rather than one more entry in {@link CONTRACT_ERRORS} because the\n * consuming app has to branch on it — this is the one contract revert on the\n * peg-in path with a specific recovery, and matching an English message across\n * a package boundary to find it would be a string nobody can safely reword.\n *\n * `expected` and `actual` are the depositor's fingerprint and the registry's.\n * They are diagnostics only — the difference between \"the chain moved\" and\n * \"our encoder is wrong\" — and must never be shown to a depositor.\n */\nexport class PeginFingerprintChangedError extends Error {\n readonly expected?: Hex;\n readonly actual?: Hex;\n\n constructor(message: string, fingerprints?: { expected: Hex; actual: Hex }) {\n super(message);\n this.name = \"PeginFingerprintChangedError\";\n this.expected = fingerprints?.expected;\n this.actual = fingerprints?.actual;\n }\n}\n\n// `instanceof` alone fails across module boundaries (duplicate copies, test\n// mocks). Fall back to the name field, as the sibling drift guards do.\nexport function isPeginFingerprintChangedError(\n err: unknown,\n): err is PeginFingerprintChangedError {\n return (\n err instanceof PeginFingerprintChangedError ||\n (err instanceof Error && err.name === \"PeginFingerprintChangedError\")\n );\n}\n\n/**\n * Recover the two fingerprints from the revert payload, when there is one.\n *\n * `extractErrorData` sometimes yields only the 4-byte selector — a viem\n * `ContractFunctionRevertedError` that has already decoded the error exposes\n * its signature, not its raw data. Classification has already happened on that\n * selector by the time this runs, so returning `undefined` here loses a\n * diagnostic and nothing else. That is why this may return `undefined` on a\n * critical path and the selector match may not.\n */\nfunction decodeFingerprints(\n errorData: string,\n): { expected: Hex; actual: Hex } | undefined {\n if (errorData.length !== FINGERPRINT_REVERT_DATA_LENGTH) return undefined;\n try {\n const [expected, actual] = decodeAbiParameters(\n [{ type: \"bytes32\" }, { type: \"bytes32\" }],\n `0x${errorData.slice(10)}` as Hex,\n );\n return { expected, actual };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Peg-in registration reverts, keyed by error signature. Every signature must\n * exist in `vaultErrors.manifest.json` (a test enforces it); selectors are\n * derived from the signature, never written by hand.\n */\nconst PEGIN_ERROR_MESSAGES: Record<string, string> = {\n \"VaultAlreadyExists()\":\n \"Vault already exists: This Bitcoin transaction has already been registered. \" +\n \"Please select different UTXOs or use a different amount to create a unique transaction.\",\n \"InvalidBTCProofOfPossession()\":\n \"Invalid BTC proof of possession: The signature has an invalid length. \" +\n \"Please ensure you're signing with the correct Bitcoin wallet.\",\n \"InvalidBTCPublicKey()\":\n \"Invalid BTC public key: The Bitcoin public key format is invalid.\",\n \"InvalidAmount()\":\n \"Invalid amount: The deposit amount is invalid or below the minimum required.\",\n \"ApplicationNotRegistered()\":\n \"Application not registered: The application controller is not registered in the system.\",\n \"ZeroAddress()\":\n \"Vault provider not registered: The selected vault provider is not registered.\",\n \"Unauthorized()\":\n \"Unauthorized: The vault registry rejected this request. Please try again later or contact support.\",\n \"InvalidPeginFee(uint256,uint256)\":\n \"Invalid pegin fee: The ETH fee sent does not match the required amount. \" +\n \"This may indicate a fee rate change during the transaction.\",\n \"PrePeginOutputAlreadyUsed()\":\n \"This Bitcoin output is already registered for one of your vaults. \" +\n \"Select different UTXOs to create a new deposit.\",\n // keccak256(abi.encodePacked(hashlock, msg.sender)) collision in\n // BTCVaultRegistry.hashlockToVaultId. Hashlocks are derived from the\n // depositor's BTC wallet and selected UTXOs, so reusing the same UTXOs from\n // the same wallet (even after a previous vault expires) reverts here.\n \"DuplicateHashlock()\":\n \"Duplicate deposit: a BTCVault with this hashlock is already registered to your wallet. Hashlocks are derived from your BTC wallet and selected UTXOs — use different UTXOs to create a unique deposit.\",\n \"DepositorWotsPkHashAlreadyUsed()\":\n \"Duplicate deposit: these deposit keys are already registered to your wallet. \" +\n \"Select different UTXOs to create a new deposit.\",\n \"TooManyFundingInputs(uint256,uint256)\":\n \"Too many Bitcoin inputs: This deposit spends more UTXOs than the protocol allows. \" +\n \"Select fewer, larger UTXOs and try again.\",\n \"TooManyHtlcOutputs(uint256,uint256)\":\n \"Too many vaults in one deposit: Split this deposit into fewer vaults and try again.\",\n \"VaultBelowMinimum(uint256,uint256)\":\n \"Deposit too small: Each vault must be at least the protocol minimum. Increase the amount and try again.\",\n \"VaultAboveMaximum(uint256,uint256)\":\n \"Deposit too large: Each vault must be at most the protocol maximum. Reduce the amount and try again.\",\n \"VaultProviderCommissionExceeded(uint16,uint16)\":\n \"Vault provider commission changed: The provider's commission is now above the limit you accepted. \" +\n \"Review the new commission and try again.\",\n \"DepositNotAllowed()\":\n \"Deposit not allowed: Your address is not on this application's allow list.\",\n \"CapExceeded()\":\n \"Deposit cap reached: This deposit would exceed the application's total deposit cap \" +\n \"or your wallet's deposit cap. Try a smaller amount.\",\n \"LiveVaultCapExceeded()\":\n \"Vault limit reached: The protocol has no vault capacity left right now. Please try again later.\",\n \"ApplicationNotActive()\":\n \"Application unavailable: This application is not accepting deposits right now. Please try again later.\",\n \"TBV_Paused()\":\n \"The protocol is paused. Please try again later.\",\n \"TBV_Frozen()\":\n \"This action isn't available while the system is frozen.\",\n};\n\n/**\n * Known peg-in contract error selectors mapped to user-friendly messages.\n *\n * Error selectors are the first 4 bytes of keccak256(error signature).\n */\nexport const CONTRACT_ERRORS: Record<string, string> = Object.fromEntries(\n Object.entries(PEGIN_ERROR_MESSAGES).map(([signature, message]) => [\n toFunctionSelector(signature),\n message,\n ]),\n);\n\n/**\n * Extract error data from various error formats.\n *\n * Viem and wallet providers wrap errors in multiple levels. This function\n * searches through the error chain to find the revert data.\n *\n * @param error - The error object to extract data from\n * @returns The error data (e.g., \"0x04aabf33\") or undefined\n */\nexport function extractErrorData(error: unknown): string | undefined {\n return walkForErrorData(error, 0);\n}\n\n/**\n * Walk an error chain looking for revert data in any of viem 2.x's known\n * shapes. Covers:\n * - `.data: \"0x...\"` — raw revert hex (most common with `estimateGas`)\n * - `.revertData: \"0x...\"` — alternate viem shape\n * - `.signature: \"0x...\"` — 4-byte selector from a *decoded*\n * ContractFunctionRevertedError (set when the ABI included the error def)\n * - `.error.data: \"0x...\"` — RPC-level error shape from some providers\n * - `.walk(fn)` — viem's chainable error walker (BaseError.walk)\n * - `.cause` chain — viem wraps errors many layers deep\n *\n * Depth-limited (10) and walk-result-deduplicated so a cycle can't loop.\n */\nfunction walkForErrorData(\n error: unknown,\n depth: number,\n): string | undefined {\n if (depth > 10 || !error || typeof error !== \"object\") return undefined;\n\n const err = error as Record<string, unknown>;\n\n if (typeof err.data === \"string\" && err.data.startsWith(\"0x\")) {\n return err.data;\n }\n if (typeof err.revertData === \"string\" && err.revertData.startsWith(\"0x\")) {\n return err.revertData;\n }\n if (typeof err.signature === \"string\" && err.signature.startsWith(\"0x\")) {\n return err.signature;\n }\n if (typeof err.details === \"string\" && err.details.startsWith(\"0x\")) {\n return err.details;\n }\n\n // RPC-level error shape (`{ error: { data: \"0x...\" } }`)\n if (err.error && typeof err.error === \"object\") {\n const inner = (err.error as Record<string, unknown>).data;\n if (typeof inner === \"string\" && inner.startsWith(\"0x\")) {\n return inner;\n }\n }\n\n // Recurse through `.cause`\n if (err.cause) {\n const fromCause = walkForErrorData(err.cause, depth + 1);\n if (fromCause) return fromCause;\n }\n\n // Use viem's `.walk()` if available\n if (typeof err.walk === \"function\") {\n try {\n let found: string | undefined;\n (err.walk as (fn: (e: unknown) => boolean) => unknown)((e) => {\n if (e === error) return false; // avoid self-cycle\n const data = walkForErrorData(e, depth + 1);\n if (data) {\n found = data;\n return true;\n }\n return false;\n });\n if (found) return found;\n } catch {\n // walk failed; ignore\n }\n }\n\n // Last resort: regex an embedded hex selector out of the message\n if (depth === 0) {\n const message = typeof err.message === \"string\" ? err.message : \"\";\n const hexMatch = message.match(/\\b(0x[a-fA-F0-9]{8})\\b/);\n if (hexMatch) return hexMatch[1];\n }\n\n return undefined;\n}\n\n/**\n * Get a user-friendly error message for a contract error.\n *\n * Reads {@link CONTRACT_ERRORS} only, so it reports `PeginFingerprintChanged`\n * as unrecognised even though {@link handleContractError} throws a typed error\n * for it. That revert deliberately has no message-table entry: consumers branch\n * on {@link PeginFingerprintChangedError} and supply their own copy.\n *\n * @param error - The error object from a contract call\n * @returns A user-friendly error message, or undefined if error is not recognized\n */\nexport function getContractErrorMessage(error: unknown): string | undefined {\n const errorData = extractErrorData(error);\n if (errorData) {\n // Check exact match first, then match by 4-byte selector prefix.\n // Parametric errors (e.g. InvalidPeginFee(uint256,uint256)) return\n // the selector + ABI-encoded args, so the full string won't match.\n const selector = errorData.substring(0, 10); // \"0x\" + 4 bytes\n return CONTRACT_ERRORS[errorData] ?? CONTRACT_ERRORS[selector];\n }\n return undefined;\n}\n\n/**\n * Check if an error is a known contract error.\n *\n * \"Known\" means present in {@link CONTRACT_ERRORS}, so this returns `false` for\n * `PeginFingerprintChanged` — see {@link getContractErrorMessage} for why that\n * revert is typed instead of tabled. Use\n * {@link isPeginFingerprintChangedError} to recognise it.\n *\n * @param error - The error object to check\n * @returns True if the error is a known contract error\n */\nexport function isKnownContractError(error: unknown): boolean {\n const errorData = extractErrorData(error);\n if (errorData === undefined) return false;\n const selector = errorData.substring(0, 10);\n return errorData in CONTRACT_ERRORS || selector in CONTRACT_ERRORS;\n}\n\n/**\n * Handle a contract error by throwing a user-friendly error.\n *\n * This function extracts error data, maps it to a user-friendly message,\n * and throws an appropriate error. Use this in catch blocks after contract calls.\n *\n * @param error - The error from a contract call\n * @throws Always throws an error with a descriptive message\n */\nexport function handleContractError(error: unknown): never {\n // Log full error for debugging\n console.error(\"[Contract Error] Raw error:\", error);\n\n // Extract error data from the error chain\n const errorData = extractErrorData(error);\n console.error(\"[Contract Error] Extracted error data:\", errorData);\n\n // Check for known contract error signatures (exact match or 4-byte selector prefix)\n if (errorData) {\n const selector = errorData.substring(0, 10);\n\n // Typed ahead of the message map: the peg-in path branches on this one\n // rather than rendering it, and the two fingerprints are worth keeping.\n //\n // Lowercased before comparing because `extractErrorData` accepts mixed-case\n // hex — its last-resort message regex matches `[a-fA-F0-9]`, and `err.data`\n // from an arbitrary RPC provider carries no casing guarantee. viem returns\n // lowercase in practice, so this is belt-and-braces; but the app branches\n // on this selector, and a silent miss would drop the whole recovery path.\n if (selector.toLowerCase() === PEGIN_FINGERPRINT_CHANGED_SELECTOR) {\n throw new PeginFingerprintChangedError(\n \"Peg-in configuration fingerprint changed: the protocol state resolved \" +\n \"at inclusion differs from the state this deposit was built against.\",\n decodeFingerprints(errorData),\n );\n }\n\n const knownError = CONTRACT_ERRORS[errorData] ?? CONTRACT_ERRORS[selector];\n if (knownError) {\n console.error(\"[Contract Error] Known error:\", knownError);\n throw new Error(knownError);\n }\n\n // Revert data present but empty, as opposed to absent (no `errorData`).\n if (errorData === \"0x\") {\n throw new Error(EMPTY_REVERT_MESSAGE);\n }\n }\n\n // Check for gas estimation errors or internal JSON-RPC errors\n const errorMsg = (error as Error)?.message || \"\";\n if (\n errorMsg.includes(\"gas limit too high\") ||\n errorMsg.includes(\"21000000\") ||\n errorMsg.includes(\"Internal JSON-RPC error\")\n ) {\n // If we found error data but it's not in our known list, include it\n const errorHint = errorData ? ` (error code: ${errorData})` : \"\";\n console.error(\n \"[Contract Error] Transaction rejected. Error code:\",\n errorData,\n \"Message:\",\n errorMsg,\n );\n throw new Error(\n `Transaction failed: The contract rejected this transaction${errorHint}. ` +\n \"Possible causes: (1) Vault already exists for this transaction, \" +\n \"(2) Invalid signature, (3) Unauthorized caller. \" +\n \"Please check your transaction parameters and try again.\",\n );\n }\n\n // Default: re-throw original error with better context\n if (error instanceof Error) {\n console.error(\"[Contract Error] Unhandled error:\", error.message);\n throw error;\n }\n throw new Error(`Contract call failed: ${String(error)}`);\n}\n","/**\n * BTCVaultRegistry ABI — RFC-006 key-epoch view of `getBtcVaultProtocolInfo`.\n *\n * This is a deliberate second copy of a single function entry, NOT a\n * convenience re-export, and it must never be merged into\n * `BTCVaultRegistryABI`.\n *\n * `getBtcVaultProtocolInfo` returns a *positional* tuple. RFC-006 appended\n * three `uint64` epoch fields (`vpKeyEpoch`, `appKeeperKeyEpoch`,\n * `ucKeyEpoch`) after `vaultCoreVersion`. Declaring those three components\n * against a registry that predates RFC-006 makes viem read past the end of\n * the returndata and throw — and because the shared reader batches this call\n * through `multicall({ allowFailure: false })`, one bad decode fails the\n * whole batch. That would break vault status, resume, payout and refund\n * app-wide, on every network whose registry has not been upgraded yet.\n *\n * So the shared `BTCVaultRegistryABI` keeps the 13-field shape that decodes\n * against every deployed registry, and the extended shape lives here, read\n * only by `ViemVaultRegistryReader.getVaultKeyEpochs*` on the epoch-aware\n * path. Reading the same call through two ABIs is the price of keeping the\n * shared decode path independent of the registry version.\n *\n * The 13 shared components must stay an exact prefix of the 16 below;\n * `__tests__/abi-key-epochs.test.ts` pins that.\n *\n * Generated from vault-contracts-aave-v4\n * `src/protocol/lib/types/BTCVaultRegistryTypes.sol`.\n *\n * @module contracts/abis/BTCVaultRegistryKeyEpochs\n */\n\nexport const BTCVaultRegistryKeyEpochsABI = [\n {\n type: \"function\",\n name: \"getBtcVaultProtocolInfo\",\n inputs: [\n {\n name: \"vaultId\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n ],\n outputs: [\n {\n name: \"vProtocol\",\n type: \"tuple\",\n internalType: \"struct BTCVaultRegistryTypes.BTCVaultProtocolInfo\",\n components: [\n {\n name: \"depositorSignedPeginTx\",\n type: \"bytes\",\n internalType: \"bytes\",\n },\n {\n name: \"universalChallengersVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"appVaultKeepersVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"offchainParamsVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"verifiedAt\",\n type: \"uint256\",\n internalType: \"uint256\",\n },\n {\n name: \"depositorWotsPkHash\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"hashlock\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"htlcVout\",\n type: \"uint8\",\n internalType: \"uint8\",\n },\n {\n name: \"depositorPopSignature\",\n type: \"bytes\",\n internalType: \"bytes\",\n },\n {\n name: \"prePeginTxHash\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"vaultProviderCommissionBps\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"claimExpiredUntil\",\n type: \"uint256\",\n internalType: \"uint256\",\n },\n {\n name: \"vaultCoreVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n // RFC-006: per-pegin operation-key epochs, frozen at\n // `submitPeginRequest`. All three pack into one storage slot and were\n // appended after `vaultCoreVersion` so pre-existing rows decode\n // unchanged.\n {\n name: \"vpKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n {\n name: \"appKeeperKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n {\n name: \"ucKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n ],\n },\n ],\n stateMutability: \"view\",\n },\n] as const;\n"],"names":["PEGIN_FINGERPRINT_CHANGED_SELECTOR","EMPTY_REVERT_MESSAGE","FINGERPRINT_REVERT_DATA_LENGTH","PeginFingerprintChangedError","message","fingerprints","__publicField","isPeginFingerprintChangedError","err","decodeFingerprints","errorData","expected","actual","decodeAbiParameters","PEGIN_ERROR_MESSAGES","CONTRACT_ERRORS","signature","toFunctionSelector","extractErrorData","error","walkForErrorData","depth","inner","fromCause","found","e","data","hexMatch","getContractErrorMessage","selector","isKnownContractError","handleContractError","knownError","errorMsg","errorHint","BTCVaultRegistryKeyEpochsABI"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";var h=Object.defineProperty;var g=(t,n,e)=>n in t?h(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var s=(t,n,e)=>g(t,typeof n!="symbol"?n+"":n,e);const d=require("viem"),p="0x846c25bb",y="The contract rejected this deposit without giving a reason. Refresh the app and try again; if it keeps happening, contact support.",m=138;class l extends Error{constructor(e,r){super(e);s(this,"expected");s(this,"actual");this.name="PeginFingerprintChangedError",this.expected=r==null?void 0:r.expected,this.actual=r==null?void 0:r.actual}}function f(t){return t instanceof l||t instanceof Error&&t.name==="PeginFingerprintChangedError"}function T(t){if(t.length===m)try{const[n,e]=d.decodeAbiParameters([{type:"bytes32"},{type:"bytes32"}],`0x${t.slice(10)}`);return{expected:n,actual:e}}catch{return}}const E={"VaultAlreadyExists()":"Vault already exists: This Bitcoin transaction has already been registered. Please select different UTXOs or use a different amount to create a unique transaction.","InvalidBTCProofOfPossession()":"Invalid BTC proof of possession: The signature has an invalid length. Please ensure you're signing with the correct Bitcoin wallet.","InvalidBTCPublicKey()":"Invalid BTC public key: The Bitcoin public key format is invalid.","InvalidAmount()":"Invalid amount: The deposit amount is invalid or below the minimum required.","ApplicationNotRegistered()":"Application not registered: The application controller is not registered in the system.","ZeroAddress()":"Vault provider not registered: The selected vault provider is not registered.","Unauthorized()":"Unauthorized: The vault registry rejected this request. Please try again later or contact support.","InvalidPeginFee(uint256,uint256)":"Invalid pegin fee: The ETH fee sent does not match the required amount. This may indicate a fee rate change during the transaction.","PrePeginOutputAlreadyUsed()":"This Bitcoin output is already registered for one of your vaults. Select different UTXOs to create a new deposit.","DuplicateHashlock()":"Duplicate deposit: a BTCVault with this hashlock is already registered to your wallet. Hashlocks are derived from your BTC wallet and selected UTXOs — use different UTXOs to create a unique deposit.","DepositorWotsPkHashAlreadyUsed()":"Duplicate deposit: these deposit keys are already registered to your wallet. Select different UTXOs to create a new deposit.","TooManyFundingInputs(uint256,uint256)":"Too many Bitcoin inputs: This deposit spends more UTXOs than the protocol allows. Select fewer, larger UTXOs and try again.","TooManyHtlcOutputs(uint256,uint256)":"Too many vaults in one deposit: Split this deposit into fewer vaults and try again.","VaultBelowMinimum(uint256,uint256)":"Deposit too small: Each vault must be at least the protocol minimum. Increase the amount and try again.","VaultAboveMaximum(uint256,uint256)":"Deposit too large: Each vault must be at most the protocol maximum. Reduce the amount and try again.","VaultProviderCommissionExceeded(uint16,uint16)":"Vault provider commission changed: The provider's commission is now above the limit you accepted. Review the new commission and try again.","DepositNotAllowed()":"Deposit not allowed: Your address is not on this application's allow list.","CapExceeded()":"Deposit cap reached: This deposit would exceed the application's total deposit cap or your wallet's deposit cap. Try a smaller amount.","LiveVaultCapExceeded()":"Vault limit reached: The protocol has no vault capacity left right now. Please try again later.","ApplicationNotActive()":"Application unavailable: This application is not accepting deposits right now. Please try again later.","TBV_Paused()":"The protocol is paused. Please try again later.","TBV_Frozen()":"This action isn't available while the system is frozen."},i=Object.fromEntries(Object.entries(E).map(([t,n])=>[d.toFunctionSelector(t),n]));function o(t){return c(t,0)}function c(t,n){if(n>10||!t||typeof t!="object")return;const e=t;if(typeof e.data=="string"&&e.data.startsWith("0x"))return e.data;if(typeof e.revertData=="string"&&e.revertData.startsWith("0x"))return e.revertData;if(typeof e.signature=="string"&&e.signature.startsWith("0x"))return e.signature;if(typeof e.details=="string"&&e.details.startsWith("0x"))return e.details;if(e.error&&typeof e.error=="object"){const r=e.error.data;if(typeof r=="string"&&r.startsWith("0x"))return r}if(e.cause){const r=c(e.cause,n+1);if(r)return r}if(typeof e.walk=="function")try{let r;if(e.walk(a=>{if(a===t)return!1;const u=c(a,n+1);return u?(r=u,!0):!1}),r)return r}catch{}if(n===0){const a=(typeof e.message=="string"?e.message:"").match(/\b(0x[a-fA-F0-9]{8})\b/);if(a)return a[1]}}function v(t){const n=o(t);if(n){const e=n.substring(0,10);return i[n]??i[e]}}function w(t){const n=o(t);if(n===void 0)return!1;const e=n.substring(0,10);return n in i||e in i}function C(t){console.error("[Contract Error] Raw error:",t);const n=o(t);if(console.error("[Contract Error] Extracted error data:",n),n){const r=n.substring(0,10);if(r.toLowerCase()===p)throw new l("Peg-in configuration fingerprint changed: the protocol state resolved at inclusion differs from the state this deposit was built against.",T(n));const a=i[n]??i[r];if(a)throw console.error("[Contract Error] Known error:",a),new Error(a);if(n==="0x")throw new Error(y)}const e=(t==null?void 0:t.message)||"";if(e.includes("gas limit too high")||e.includes("21000000")||e.includes("Internal JSON-RPC error")){const r=n?` (error code: ${n})`:"";throw console.error("[Contract Error] Transaction rejected. Error code:",n,"Message:",e),new Error(`Transaction failed: The contract rejected this transaction${r}. Possible causes: (1) Vault already exists for this transaction, (2) Invalid signature, (3) Unauthorized caller. Please check your transaction parameters and try again.`)}throw t instanceof Error?(console.error("[Contract Error] Unhandled error:",t.message),t):new Error(`Contract call failed: ${String(t)}`)}const P=[{type:"function",name:"getBtcVaultProtocolInfo",inputs:[{name:"vaultId",type:"bytes32",internalType:"bytes32"}],outputs:[{name:"vProtocol",type:"tuple",internalType:"struct BTCVaultRegistryTypes.BTCVaultProtocolInfo",components:[{name:"depositorSignedPeginTx",type:"bytes",internalType:"bytes"},{name:"universalChallengersVersion",type:"uint16",internalType:"uint16"},{name:"appVaultKeepersVersion",type:"uint16",internalType:"uint16"},{name:"offchainParamsVersion",type:"uint16",internalType:"uint16"},{name:"verifiedAt",type:"uint256",internalType:"uint256"},{name:"depositorWotsPkHash",type:"bytes32",internalType:"bytes32"},{name:"hashlock",type:"bytes32",internalType:"bytes32"},{name:"htlcVout",type:"uint8",internalType:"uint8"},{name:"depositorPopSignature",type:"bytes",internalType:"bytes"},{name:"prePeginTxHash",type:"bytes32",internalType:"bytes32"},{name:"vaultProviderCommissionBps",type:"uint16",internalType:"uint16"},{name:"claimExpiredUntil",type:"uint256",internalType:"uint256"},{name:"vaultCoreVersion",type:"uint16",internalType:"uint16"},{name:"vpKeyEpoch",type:"uint64",internalType:"uint64"},{name:"appKeeperKeyEpoch",type:"uint64",internalType:"uint64"},{name:"ucKeyEpoch",type:"uint64",internalType:"uint64"}]}],stateMutability:"view"}];exports.BTCVaultRegistryKeyEpochsABI=P;exports.CONTRACT_ERRORS=i;exports.EMPTY_REVERT_MESSAGE=y;exports.PEGIN_FINGERPRINT_CHANGED_SELECTOR=p;exports.PeginFingerprintChangedError=l;exports.extractErrorData=o;exports.getContractErrorMessage=v;exports.handleContractError=C;exports.isKnownContractError=w;exports.isPeginFingerprintChangedError=f;
2
+ //# sourceMappingURL=BTCVaultRegistryKeyEpochs.abi-CReWFJdu.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BTCVaultRegistryKeyEpochs.abi-CReWFJdu.cjs","sources":["../src/tbv/core/contracts/errors.ts","../src/tbv/core/contracts/abis/BTCVaultRegistryKeyEpochs.abi.ts"],"sourcesContent":["/**\n * Contract Error Handling Utilities\n *\n * Provides utilities for extracting and handling contract revert errors.\n * Maps known error selectors to user-friendly messages.\n *\n * @module contracts/errors\n */\n\nimport { decodeAbiParameters, type Hex, toFunctionSelector } from \"viem\";\n\n/**\n * `PeginFingerprintChanged(bytes32 expected, bytes32 actual)`.\n *\n * Re-derived rather than copied: `keccak256(\"PeginFingerprintChanged(bytes32,bytes32)\")`\n * begins `0x846c25bb`. Source is\n * https://github.com/babylonlabs-io/vault-contracts-aave-v4/pull/555, and the\n * value matches that repo's generated `snapshots/selectors.md` at head\n * 86577e40. `BTCVaultRegistry.abi.ts` carries the matching error entry, and a\n * test asserts the two agree.\n */\nexport const PEGIN_FINGERPRINT_CHANGED_SELECTOR = \"0x846c25bb\";\n\n/**\n * Shown when the contract reverted with explicitly empty data (`0x`). That can\n * mean a revert with no reason or a call the contract does not recognise, so\n * the wording claims neither.\n */\nexport const EMPTY_REVERT_MESSAGE =\n \"The contract rejected this deposit without giving a reason. \" +\n \"Refresh the app and try again; if it keeps happening, contact support.\";\n\n/** `\"0x\"` + 4-byte selector + two abi-encoded `bytes32` words. */\nconst FINGERPRINT_REVERT_DATA_LENGTH = 2 + 8 + 64 * 2;\n\n/**\n * The registry rejected a peg-in registration because the protocol state it\n * resolves at inclusion no longer matches the state the Pre-Pegin was built\n * against.\n *\n * Typed rather than one more entry in {@link CONTRACT_ERRORS} because the\n * consuming app has to branch on it — this is the one contract revert on the\n * peg-in path with a specific recovery, and matching an English message across\n * a package boundary to find it would be a string nobody can safely reword.\n *\n * `expected` and `actual` are the depositor's fingerprint and the registry's.\n * They are diagnostics only — the difference between \"the chain moved\" and\n * \"our encoder is wrong\" — and must never be shown to a depositor.\n */\nexport class PeginFingerprintChangedError extends Error {\n readonly expected?: Hex;\n readonly actual?: Hex;\n\n constructor(message: string, fingerprints?: { expected: Hex; actual: Hex }) {\n super(message);\n this.name = \"PeginFingerprintChangedError\";\n this.expected = fingerprints?.expected;\n this.actual = fingerprints?.actual;\n }\n}\n\n// `instanceof` alone fails across module boundaries (duplicate copies, test\n// mocks). Fall back to the name field, as the sibling drift guards do.\nexport function isPeginFingerprintChangedError(\n err: unknown,\n): err is PeginFingerprintChangedError {\n return (\n err instanceof PeginFingerprintChangedError ||\n (err instanceof Error && err.name === \"PeginFingerprintChangedError\")\n );\n}\n\n/**\n * Recover the two fingerprints from the revert payload, when there is one.\n *\n * `extractErrorData` sometimes yields only the 4-byte selector — a viem\n * `ContractFunctionRevertedError` that has already decoded the error exposes\n * its signature, not its raw data. Classification has already happened on that\n * selector by the time this runs, so returning `undefined` here loses a\n * diagnostic and nothing else. That is why this may return `undefined` on a\n * critical path and the selector match may not.\n */\nfunction decodeFingerprints(\n errorData: string,\n): { expected: Hex; actual: Hex } | undefined {\n if (errorData.length !== FINGERPRINT_REVERT_DATA_LENGTH) return undefined;\n try {\n const [expected, actual] = decodeAbiParameters(\n [{ type: \"bytes32\" }, { type: \"bytes32\" }],\n `0x${errorData.slice(10)}` as Hex,\n );\n return { expected, actual };\n } catch {\n return undefined;\n }\n}\n\n/**\n * Peg-in registration reverts, keyed by error signature. Every signature must\n * exist in `vaultErrors.manifest.json` (a test enforces it); selectors are\n * derived from the signature, never written by hand.\n */\nconst PEGIN_ERROR_MESSAGES: Record<string, string> = {\n \"VaultAlreadyExists()\":\n \"Vault already exists: This Bitcoin transaction has already been registered. \" +\n \"Please select different UTXOs or use a different amount to create a unique transaction.\",\n \"InvalidBTCProofOfPossession()\":\n \"Invalid BTC proof of possession: The signature has an invalid length. \" +\n \"Please ensure you're signing with the correct Bitcoin wallet.\",\n \"InvalidBTCPublicKey()\":\n \"Invalid BTC public key: The Bitcoin public key format is invalid.\",\n \"InvalidAmount()\":\n \"Invalid amount: The deposit amount is invalid or below the minimum required.\",\n \"ApplicationNotRegistered()\":\n \"Application not registered: The application controller is not registered in the system.\",\n \"ZeroAddress()\":\n \"Vault provider not registered: The selected vault provider is not registered.\",\n \"Unauthorized()\":\n \"Unauthorized: The vault registry rejected this request. Please try again later or contact support.\",\n \"InvalidPeginFee(uint256,uint256)\":\n \"Invalid pegin fee: The ETH fee sent does not match the required amount. \" +\n \"This may indicate a fee rate change during the transaction.\",\n \"PrePeginOutputAlreadyUsed()\":\n \"This Bitcoin output is already registered for one of your vaults. \" +\n \"Select different UTXOs to create a new deposit.\",\n // keccak256(abi.encodePacked(hashlock, msg.sender)) collision in\n // BTCVaultRegistry.hashlockToVaultId. Hashlocks are derived from the\n // depositor's BTC wallet and selected UTXOs, so reusing the same UTXOs from\n // the same wallet (even after a previous vault expires) reverts here.\n \"DuplicateHashlock()\":\n \"Duplicate deposit: a BTCVault with this hashlock is already registered to your wallet. Hashlocks are derived from your BTC wallet and selected UTXOs — use different UTXOs to create a unique deposit.\",\n \"DepositorWotsPkHashAlreadyUsed()\":\n \"Duplicate deposit: these deposit keys are already registered to your wallet. \" +\n \"Select different UTXOs to create a new deposit.\",\n \"TooManyFundingInputs(uint256,uint256)\":\n \"Too many Bitcoin inputs: This deposit spends more UTXOs than the protocol allows. \" +\n \"Select fewer, larger UTXOs and try again.\",\n \"TooManyHtlcOutputs(uint256,uint256)\":\n \"Too many vaults in one deposit: Split this deposit into fewer vaults and try again.\",\n \"VaultBelowMinimum(uint256,uint256)\":\n \"Deposit too small: Each vault must be at least the protocol minimum. Increase the amount and try again.\",\n \"VaultAboveMaximum(uint256,uint256)\":\n \"Deposit too large: Each vault must be at most the protocol maximum. Reduce the amount and try again.\",\n \"VaultProviderCommissionExceeded(uint16,uint16)\":\n \"Vault provider commission changed: The provider's commission is now above the limit you accepted. \" +\n \"Review the new commission and try again.\",\n \"DepositNotAllowed()\":\n \"Deposit not allowed: Your address is not on this application's allow list.\",\n \"CapExceeded()\":\n \"Deposit cap reached: This deposit would exceed the application's total deposit cap \" +\n \"or your wallet's deposit cap. Try a smaller amount.\",\n \"LiveVaultCapExceeded()\":\n \"Vault limit reached: The protocol has no vault capacity left right now. Please try again later.\",\n \"ApplicationNotActive()\":\n \"Application unavailable: This application is not accepting deposits right now. Please try again later.\",\n \"TBV_Paused()\":\n \"The protocol is paused. Please try again later.\",\n \"TBV_Frozen()\":\n \"This action isn't available while the system is frozen.\",\n};\n\n/**\n * Known peg-in contract error selectors mapped to user-friendly messages.\n *\n * Error selectors are the first 4 bytes of keccak256(error signature).\n */\nexport const CONTRACT_ERRORS: Record<string, string> = Object.fromEntries(\n Object.entries(PEGIN_ERROR_MESSAGES).map(([signature, message]) => [\n toFunctionSelector(signature),\n message,\n ]),\n);\n\n/**\n * Extract error data from various error formats.\n *\n * Viem and wallet providers wrap errors in multiple levels. This function\n * searches through the error chain to find the revert data.\n *\n * @param error - The error object to extract data from\n * @returns The error data (e.g., \"0x04aabf33\") or undefined\n */\nexport function extractErrorData(error: unknown): string | undefined {\n return walkForErrorData(error, 0);\n}\n\n/**\n * Walk an error chain looking for revert data in any of viem 2.x's known\n * shapes. Covers:\n * - `.data: \"0x...\"` — raw revert hex (most common with `estimateGas`)\n * - `.revertData: \"0x...\"` — alternate viem shape\n * - `.signature: \"0x...\"` — 4-byte selector from a *decoded*\n * ContractFunctionRevertedError (set when the ABI included the error def)\n * - `.error.data: \"0x...\"` — RPC-level error shape from some providers\n * - `.walk(fn)` — viem's chainable error walker (BaseError.walk)\n * - `.cause` chain — viem wraps errors many layers deep\n *\n * Depth-limited (10) and walk-result-deduplicated so a cycle can't loop.\n */\nfunction walkForErrorData(\n error: unknown,\n depth: number,\n): string | undefined {\n if (depth > 10 || !error || typeof error !== \"object\") return undefined;\n\n const err = error as Record<string, unknown>;\n\n if (typeof err.data === \"string\" && err.data.startsWith(\"0x\")) {\n return err.data;\n }\n if (typeof err.revertData === \"string\" && err.revertData.startsWith(\"0x\")) {\n return err.revertData;\n }\n if (typeof err.signature === \"string\" && err.signature.startsWith(\"0x\")) {\n return err.signature;\n }\n if (typeof err.details === \"string\" && err.details.startsWith(\"0x\")) {\n return err.details;\n }\n\n // RPC-level error shape (`{ error: { data: \"0x...\" } }`)\n if (err.error && typeof err.error === \"object\") {\n const inner = (err.error as Record<string, unknown>).data;\n if (typeof inner === \"string\" && inner.startsWith(\"0x\")) {\n return inner;\n }\n }\n\n // Recurse through `.cause`\n if (err.cause) {\n const fromCause = walkForErrorData(err.cause, depth + 1);\n if (fromCause) return fromCause;\n }\n\n // Use viem's `.walk()` if available\n if (typeof err.walk === \"function\") {\n try {\n let found: string | undefined;\n (err.walk as (fn: (e: unknown) => boolean) => unknown)((e) => {\n if (e === error) return false; // avoid self-cycle\n const data = walkForErrorData(e, depth + 1);\n if (data) {\n found = data;\n return true;\n }\n return false;\n });\n if (found) return found;\n } catch {\n // walk failed; ignore\n }\n }\n\n // Last resort: regex an embedded hex selector out of the message\n if (depth === 0) {\n const message = typeof err.message === \"string\" ? err.message : \"\";\n const hexMatch = message.match(/\\b(0x[a-fA-F0-9]{8})\\b/);\n if (hexMatch) return hexMatch[1];\n }\n\n return undefined;\n}\n\n/**\n * Get a user-friendly error message for a contract error.\n *\n * Reads {@link CONTRACT_ERRORS} only, so it reports `PeginFingerprintChanged`\n * as unrecognised even though {@link handleContractError} throws a typed error\n * for it. That revert deliberately has no message-table entry: consumers branch\n * on {@link PeginFingerprintChangedError} and supply their own copy.\n *\n * @param error - The error object from a contract call\n * @returns A user-friendly error message, or undefined if error is not recognized\n */\nexport function getContractErrorMessage(error: unknown): string | undefined {\n const errorData = extractErrorData(error);\n if (errorData) {\n // Check exact match first, then match by 4-byte selector prefix.\n // Parametric errors (e.g. InvalidPeginFee(uint256,uint256)) return\n // the selector + ABI-encoded args, so the full string won't match.\n const selector = errorData.substring(0, 10); // \"0x\" + 4 bytes\n return CONTRACT_ERRORS[errorData] ?? CONTRACT_ERRORS[selector];\n }\n return undefined;\n}\n\n/**\n * Check if an error is a known contract error.\n *\n * \"Known\" means present in {@link CONTRACT_ERRORS}, so this returns `false` for\n * `PeginFingerprintChanged` — see {@link getContractErrorMessage} for why that\n * revert is typed instead of tabled. Use\n * {@link isPeginFingerprintChangedError} to recognise it.\n *\n * @param error - The error object to check\n * @returns True if the error is a known contract error\n */\nexport function isKnownContractError(error: unknown): boolean {\n const errorData = extractErrorData(error);\n if (errorData === undefined) return false;\n const selector = errorData.substring(0, 10);\n return errorData in CONTRACT_ERRORS || selector in CONTRACT_ERRORS;\n}\n\n/**\n * Handle a contract error by throwing a user-friendly error.\n *\n * This function extracts error data, maps it to a user-friendly message,\n * and throws an appropriate error. Use this in catch blocks after contract calls.\n *\n * @param error - The error from a contract call\n * @throws Always throws an error with a descriptive message\n */\nexport function handleContractError(error: unknown): never {\n // Log full error for debugging\n console.error(\"[Contract Error] Raw error:\", error);\n\n // Extract error data from the error chain\n const errorData = extractErrorData(error);\n console.error(\"[Contract Error] Extracted error data:\", errorData);\n\n // Check for known contract error signatures (exact match or 4-byte selector prefix)\n if (errorData) {\n const selector = errorData.substring(0, 10);\n\n // Typed ahead of the message map: the peg-in path branches on this one\n // rather than rendering it, and the two fingerprints are worth keeping.\n //\n // Lowercased before comparing because `extractErrorData` accepts mixed-case\n // hex — its last-resort message regex matches `[a-fA-F0-9]`, and `err.data`\n // from an arbitrary RPC provider carries no casing guarantee. viem returns\n // lowercase in practice, so this is belt-and-braces; but the app branches\n // on this selector, and a silent miss would drop the whole recovery path.\n if (selector.toLowerCase() === PEGIN_FINGERPRINT_CHANGED_SELECTOR) {\n throw new PeginFingerprintChangedError(\n \"Peg-in configuration fingerprint changed: the protocol state resolved \" +\n \"at inclusion differs from the state this deposit was built against.\",\n decodeFingerprints(errorData),\n );\n }\n\n const knownError = CONTRACT_ERRORS[errorData] ?? CONTRACT_ERRORS[selector];\n if (knownError) {\n console.error(\"[Contract Error] Known error:\", knownError);\n throw new Error(knownError);\n }\n\n // Revert data present but empty, as opposed to absent (no `errorData`).\n if (errorData === \"0x\") {\n throw new Error(EMPTY_REVERT_MESSAGE);\n }\n }\n\n // Check for gas estimation errors or internal JSON-RPC errors\n const errorMsg = (error as Error)?.message || \"\";\n if (\n errorMsg.includes(\"gas limit too high\") ||\n errorMsg.includes(\"21000000\") ||\n errorMsg.includes(\"Internal JSON-RPC error\")\n ) {\n // If we found error data but it's not in our known list, include it\n const errorHint = errorData ? ` (error code: ${errorData})` : \"\";\n console.error(\n \"[Contract Error] Transaction rejected. Error code:\",\n errorData,\n \"Message:\",\n errorMsg,\n );\n throw new Error(\n `Transaction failed: The contract rejected this transaction${errorHint}. ` +\n \"Possible causes: (1) Vault already exists for this transaction, \" +\n \"(2) Invalid signature, (3) Unauthorized caller. \" +\n \"Please check your transaction parameters and try again.\",\n );\n }\n\n // Default: re-throw original error with better context\n if (error instanceof Error) {\n console.error(\"[Contract Error] Unhandled error:\", error.message);\n throw error;\n }\n throw new Error(`Contract call failed: ${String(error)}`);\n}\n","/**\n * BTCVaultRegistry ABI — RFC-006 key-epoch view of `getBtcVaultProtocolInfo`.\n *\n * This is a deliberate second copy of a single function entry, NOT a\n * convenience re-export, and it must never be merged into\n * `BTCVaultRegistryABI`.\n *\n * `getBtcVaultProtocolInfo` returns a *positional* tuple. RFC-006 appended\n * three `uint64` epoch fields (`vpKeyEpoch`, `appKeeperKeyEpoch`,\n * `ucKeyEpoch`) after `vaultCoreVersion`. Declaring those three components\n * against a registry that predates RFC-006 makes viem read past the end of\n * the returndata and throw — and because the shared reader batches this call\n * through `multicall({ allowFailure: false })`, one bad decode fails the\n * whole batch. That would break vault status, resume, payout and refund\n * app-wide, on every network whose registry has not been upgraded yet.\n *\n * So the shared `BTCVaultRegistryABI` keeps the 13-field shape that decodes\n * against every deployed registry, and the extended shape lives here, read\n * only by `ViemVaultRegistryReader.getVaultKeyEpochs*` on the epoch-aware\n * path. Reading the same call through two ABIs is the price of keeping the\n * shared decode path independent of the registry version.\n *\n * The 13 shared components must stay an exact prefix of the 16 below;\n * `__tests__/abi-key-epochs.test.ts` pins that.\n *\n * Generated from vault-contracts-aave-v4\n * `src/protocol/lib/types/BTCVaultRegistryTypes.sol`.\n *\n * @module contracts/abis/BTCVaultRegistryKeyEpochs\n */\n\nexport const BTCVaultRegistryKeyEpochsABI = [\n {\n type: \"function\",\n name: \"getBtcVaultProtocolInfo\",\n inputs: [\n {\n name: \"vaultId\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n ],\n outputs: [\n {\n name: \"vProtocol\",\n type: \"tuple\",\n internalType: \"struct BTCVaultRegistryTypes.BTCVaultProtocolInfo\",\n components: [\n {\n name: \"depositorSignedPeginTx\",\n type: \"bytes\",\n internalType: \"bytes\",\n },\n {\n name: \"universalChallengersVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"appVaultKeepersVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"offchainParamsVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"verifiedAt\",\n type: \"uint256\",\n internalType: \"uint256\",\n },\n {\n name: \"depositorWotsPkHash\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"hashlock\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"htlcVout\",\n type: \"uint8\",\n internalType: \"uint8\",\n },\n {\n name: \"depositorPopSignature\",\n type: \"bytes\",\n internalType: \"bytes\",\n },\n {\n name: \"prePeginTxHash\",\n type: \"bytes32\",\n internalType: \"bytes32\",\n },\n {\n name: \"vaultProviderCommissionBps\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n {\n name: \"claimExpiredUntil\",\n type: \"uint256\",\n internalType: \"uint256\",\n },\n {\n name: \"vaultCoreVersion\",\n type: \"uint16\",\n internalType: \"uint16\",\n },\n // RFC-006: per-pegin operation-key epochs, frozen at\n // `submitPeginRequest`. All three pack into one storage slot and were\n // appended after `vaultCoreVersion` so pre-existing rows decode\n // unchanged.\n {\n name: \"vpKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n {\n name: \"appKeeperKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n {\n name: \"ucKeyEpoch\",\n type: \"uint64\",\n internalType: \"uint64\",\n },\n ],\n },\n ],\n stateMutability: \"view\",\n },\n] as const;\n"],"names":["PEGIN_FINGERPRINT_CHANGED_SELECTOR","EMPTY_REVERT_MESSAGE","FINGERPRINT_REVERT_DATA_LENGTH","PeginFingerprintChangedError","message","fingerprints","__publicField","isPeginFingerprintChangedError","err","decodeFingerprints","errorData","expected","actual","decodeAbiParameters","PEGIN_ERROR_MESSAGES","CONTRACT_ERRORS","signature","toFunctionSelector","extractErrorData","error","walkForErrorData","depth","inner","fromCause","found","e","data","hexMatch","getContractErrorMessage","selector","isKnownContractError","handleContractError","knownError","errorMsg","errorHint","BTCVaultRegistryKeyEpochsABI"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";var ve=Object.defineProperty;var Ee=(o,e,t)=>e in o?ve(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var w=(o,e,t)=>Ee(o,typeof e!="symbol"?e+"":e,t);const P=require("./sha2-Ce6KewYx.cjs"),O=require("bitcoinjs-lib"),I=require("buffer"),ee=require("viem"),te=require("./pegin-registration-client-D4EguWaz.cjs"),le=require("./tbv/core/clients/mempool/index.cjs"),Y=require("./tbv/core/wasm/index.cjs"),A=require("./verifyScriptPathSchnorrSignature-D2t1yACC.cjs"),$=require("./verifyKeyPathSchnorrSignature-CQUut2-O.cjs"),h=require("./bitcoin-D-O2GjbC.cjs"),Se=require("./signing-DvISftFk.cjs"),L=require("./validation-C6XTfZak.cjs"),ue=require("./deriveVaultRoot-C3uqnJto.cjs"),E=require("./PayoutManager-DOdsgcUR.cjs"),_e=require("./registration-records-DFQgBaYi.cjs"),oe=require("./psbtInputFields-BrV_ZfL_.cjs"),ne=require("./fundPeginTransaction-54-Rwb2k.cjs"),U=require("./constants-BwCg5K6R.cjs"),Be=require("./btcTxHash-CGb5BqFL.cjs"),Ae=require("./parseFundingOutpoints-C_-PT9BT.cjs"),Ce=require("@bitcoin-js/tiny-secp256k1-asmjs"),V=require("./bip322Verify-DLxJR9CQ.cjs");function he(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const pe=he(O),Ie=he(Ce),M=BigInt(2**32-1),se=BigInt(32);function He(o,e=!1){return e?{h:Number(o&M),l:Number(o>>se&M)}:{h:Number(o>>se&M)|0,l:Number(o&M)|0}}function $e(o,e=!1){const t=o.length;let n=new Uint32Array(t),r=new Uint32Array(t);for(let s=0;s<t;s++){const{h:i,l:a}=He(o[s],e);[n[s],r[s]]=[i,a]}return[n,r]}const Oe=(o,e,t)=>o<<t|e>>>32-t,Re=(o,e,t)=>e<<t|o>>>32-t,Fe=(o,e,t)=>e<<t-32|o>>>64-t,We=(o,e,t)=>o<<t-32|e>>>64-t,Ve=64;function de(o){const e=o.prepeginTxid.toLowerCase();if(!/^[0-9a-f]+$/.test(e)||e.length!==Ve)throw new Error(`buildDepositTerms: prepeginTxid must be 64 hex chars, got "${o.prepeginTxid}"`);if(o.peginAmounts.length===0)throw new Error("buildDepositTerms: at least one pegin amount is required");if(o.timelockPegin<=0||o.timelockAssert<=0||o.timelockRefund<=0)throw new Error("buildDepositTerms: timelocks must be positive");if(!Number.isInteger(o.maxAcceptableCommissionBps)||o.maxAcceptableCommissionBps<0||o.maxAcceptableCommissionBps>=U.MAX_VP_COMMISSION_BPS_EXCLUSIVE)throw new Error(`buildDepositTerms: maxAcceptableCommissionBps must be an integer in [0, ${U.MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${o.maxAcceptableCommissionBps}`);const t=BigInt(U.BPS_DENOMINATOR),n=o.peginAmounts.map((r,s)=>({htlcVout:s,vaultProviderBtcPubkey:o.vaultProviderBtcPubkey,peginAmount:r,commissionFee:r*BigInt(o.maxAcceptableCommissionBps)/t,depositorClaimValue:o.depositorClaimValue,peginMaxFee:o.peginMaxFee}));return{vaultCoreVersion:o.vaultCoreVersion,protocolFeeRate:o.protocolFeeRate,timelockPegin:o.timelockPegin,timelockAssert:o.timelockAssert,timelockRefund:o.timelockRefund,prepeginTxid:e,prepeginMaxFee:o.prepeginMaxFee,vaultKeeperBtcPubkeys:[...o.vaultKeeperBtcPubkeys],universalChallengerBtcPubkeys:[...o.universalChallengerBtcPubkeys],vaults:n}}const Me=/^0x[0-9a-f]+$/i,De=/^[0-9a-f]+$/i,Ke=/^[A-Za-z0-9+/]+={0,2}$/;function C(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty public key");return h.processPublicKeyToXOnly(o).toLowerCase()}function Ne(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty BIP-322 signature");if(o.startsWith("0x")||o.startsWith("0X")){if(!Me.test(o)||o.length<4||o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return o.toLowerCase()}if(De.test(o)){if(o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return`0x${o.toLowerCase()}`}if(!Ke.test(o)||o.length%4!==0)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");const e=I.Buffer.from(o,"base64");if(e.length===0||e.toString("base64")!==o)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");return`0x${e.toString("hex")}`}async function ge(o){const{wallet:e,depositTerms:t,fundedPrePeginTxHex:n,depositorBtcPubkey:r}=o,s=typeof e.approveDepositTerms=="function"?e.approveDepositTerms:void 0;if(!s&&!t)return;const i=n.startsWith("0x")?n.slice(2):n,c=O.Transaction.fromHex(i).getId();if(t&&t.prepeginTxid.replace(/^0x/,"").toLowerCase()!==c)throw new Error(`Deposit terms do not match the transaction being broadcast: terms are for prepeginTxid ${t.prepeginTxid}, but this transaction is ${c}.`);if(!s)return;if(!t)throw new Error("This wallet requires approved deposit terms before signing the Pre-PegIn transaction, but none were provided. Pass PreparePeginResult.depositTerms (fresh flows) or a resume rebuild.");if(typeof e.deriveContextHash!="function")throw new Error("A deposit-approval wallet must also implement deriveContextHash, but this one does not.");if(typeof e.holdsApprovedDepositTerms=="function"){let m=!1;try{m=await e.holdsApprovedDepositTerms(t)}catch{}if(m)return}typeof e.validateDepositTerms=="function"&&await e.validateDepositTerms(t);const p=Ae.parseFundingOutpointsFromTx(n);(await ue.deriveVaultRoot({deriveContextHash:e.deriveContextHash.bind(e)},{depositorBtcPubkey:h.hexToUint8Array(C(r)),fundingOutpoints:p})).fill(0),await s.call(e,t)}const Le=BigInt(0),H=BigInt(1),Ue=BigInt(2),Xe=BigInt(7),qe=BigInt(256),ze=BigInt(113),fe=[],me=[],Pe=[];for(let o=0,e=H,t=1,n=0;o<24;o++){[t,n]=[n,(2*t+3*n)%5],fe.push(2*(5*n+t)),me.push((o+1)*(o+2)/2%64);let r=Le;for(let s=0;s<7;s++)e=(e<<H^(e>>Xe)*ze)%qe,e&Ue&&(r^=H<<(H<<BigInt(s))-H);Pe.push(r)}const be=$e(Pe,!0),Ge=be[0],je=be[1],ie=(o,e,t)=>t>32?Fe(o,e,t):Oe(o,e,t),re=(o,e,t)=>t>32?We(o,e,t):Re(o,e,t);function Ye(o,e=24){const t=new Uint32Array(10);for(let n=24-e;n<24;n++){for(let i=0;i<10;i++)t[i]=o[i]^o[i+10]^o[i+20]^o[i+30]^o[i+40];for(let i=0;i<10;i+=2){const a=(i+8)%10,c=(i+2)%10,p=t[c],d=t[c+1],m=ie(p,d,1)^t[a],k=re(p,d,1)^t[a+1];for(let x=0;x<50;x+=10)o[i+x]^=m,o[i+x+1]^=k}let r=o[2],s=o[3];for(let i=0;i<24;i++){const a=me[i],c=ie(r,s,a),p=re(r,s,a),d=fe[i];r=o[d],s=o[d+1],o[d]=c,o[d+1]=p}for(let i=0;i<50;i+=10){for(let a=0;a<10;a++)t[a]=o[i+a];for(let a=0;a<10;a++)o[i+a]^=~t[(a+2)%10]&t[(a+4)%10]}o[0]^=Ge[n],o[1]^=je[n]}P.clean(t)}class Z{constructor(e,t,n,r=!1,s=24){w(this,"state");w(this,"pos",0);w(this,"posOut",0);w(this,"finished",!1);w(this,"state32");w(this,"destroyed",!1);w(this,"blockLen");w(this,"suffix");w(this,"outputLen");w(this,"enableXOF",!1);w(this,"rounds");if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=s,P.anumber(n,"outputLen"),!(0<e&&e<200))throw new Error("only keccak-f1600 function is supported");this.state=new Uint8Array(200),this.state32=P.u32(this.state)}clone(){return this._cloneInto()}keccak(){P.swap32IfBE(this.state32),Ye(this.state32,this.rounds),P.swap32IfBE(this.state32),this.posOut=0,this.pos=0}update(e){P.aexists(this),P.abytes(e);const{blockLen:t,state:n}=this,r=e.length;for(let s=0;s<r;){const i=Math.min(t-this.pos,r-s);for(let a=0;a<i;a++)n[this.pos++]^=e[s++];this.pos===t&&this.keccak()}return this}finish(){if(this.finished)return;this.finished=!0;const{state:e,suffix:t,pos:n,blockLen:r}=this;e[n]^=t,(t&128)!==0&&n===r-1&&this.keccak(),e[r-1]^=128,this.keccak()}writeInto(e){P.aexists(this,!1),P.abytes(e),this.finish();const t=this.state,{blockLen:n}=this;for(let r=0,s=e.length;r<s;){this.posOut>=n&&this.keccak();const i=Math.min(n-this.posOut,s-r);e.set(t.subarray(this.posOut,this.posOut+i),r),this.posOut+=i,r+=i}return e}xofInto(e){if(!this.enableXOF)throw new Error("XOF is not possible for this instance");return this.writeInto(e)}xof(e){return P.anumber(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(P.aoutput(e,this),this.finished)throw new Error("digest() was already called");return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,P.clean(this.state)}_cloneInto(e){const{blockLen:t,suffix:n,outputLen:r,rounds:s,enableXOF:i}=this;return e||(e=new Z(t,n,r,i,s)),e.state32.set(this.state32),e.pos=this.pos,e.posOut=this.posOut,e.finished=this.finished,e.rounds=s,e.suffix=n,e.outputLen=r,e.enableXOF=i,e.destroyed=this.destroyed,e}}const Qe=(o,e,t,n={})=>P.createHasher(()=>new Z(e,o,t),n),Ze=Qe(1,136,32),ae=64,y=20,Q=4,we=2,Je=0,et=1,D=[64,64],tt=o=>Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("");function J(o){return _e.ripemd160(P.sha256(o))}function xe(o){return(1<<o)-1}function ot(o){let e=1;for(;e*e<o+1;)e++;return Math.max(e,2)}function nt(o){const e=Q,t=o*xe(e);return{d:e,n:o,checksum_radix:ot(t)}}function X(o,e){const t=[];let n=e;for(;n>0;)t.push(n&255),n>>>=8;const r=new Uint8Array(o.length+t.length);r.set(o);for(let s=0;s<t.length;s++)r[o.length+s]=t[s];return J(r)}function q(o,e){let t=o;for(let n=0;n<e;n++)t=J(t);return t}function st(o,e){const t=xe(e.d),n=e.checksum_radix-1,r=Math.floor(e.n*t/e.checksum_radix),s=[];for(let d=0;d<e.n;d++){const m=X(o,d+we),k=q(m,t);s.push(Array.from(k))}const i=X(o,Je),a=q(i,n),c=X(o,et),p=q(c,r);return{config:e,message_terminals:s,checksum_major_terminal:Array.from(p),checksum_minor_terminal:Array.from(a)}}async function ye(o){try{if(o.length!==ae)throw new Error(`WOTS seed must be exactly ${ae} bytes, got ${o.length}`);const e=[];for(let t=0;t<D.length;t++){const n=D[t],r=nt(n),s=new Uint8Array(o.length+1);s.set(o),s[o.length]=t;const i=J(s);try{const a=st(i,r);if(a.config.d!==Q)throw new Error(`Block ${t}: expected d=${Q}, got d=${a.config.d}`);if(a.config.n!==n)throw new Error(`Block ${t}: expected n=${n}, got n=${a.config.n}`);if(a.message_terminals.length!==n)throw new Error(`Block ${t}: expected ${n} message terminals, got ${a.message_terminals.length}`);for(let c=0;c<a.message_terminals.length;c++)if(a.message_terminals[c].length!==y)throw new Error(`Block ${t} terminal ${c}: expected ${y} bytes, got ${a.message_terminals[c].length}`);if(a.checksum_minor_terminal.length!==y)throw new Error(`Block ${t} checksum_minor: expected ${y} bytes`);if(a.checksum_major_terminal.length!==y)throw new Error(`Block ${t} checksum_major: expected ${y} bytes`);e.push(a)}finally{s.fill(0),i.fill(0)}}if(e.length!==D.length)throw new Error(`Expected ${D.length} blocks, got ${e.length}`);return e}finally{o.fill(0)}}function z(o,e,t){if(o.length!==y)throw new Error(`Block ${e} ${t}: expected ${y} bytes, got ${o.length}`);for(let n=0;n<o.length;n++){const r=o[n];if(!Number.isInteger(r)||r<0||r>255)throw new Error(`Block ${e} ${t}[${n}]: invalid byte value ${r}`)}}function ke(o){if(o.length===0)throw new Error("Public keys array must not be empty");for(let s=0;s<o.length;s++){const i=o[s];z(i.checksum_minor_terminal,s,"checksum_minor_terminal"),z(i.checksum_major_terminal,s,"checksum_major_terminal");for(let a=0;a<i.message_terminals.length;a++)z(i.message_terminals[a],s,`message_terminal[${a}]`)}let e=0;for(const s of o)e+=we+s.message_terminals.length;const t=new Uint8Array(e*y);let n=0;for(const s of o){t.set(s.checksum_minor_terminal,n),n+=y,t.set(s.checksum_major_terminal,n),n+=y;for(const i of s.message_terminals)t.set(i,n),n+=y}const r=Ze(t);return`0x${tt(r)}`}async function Te(o,e){const t=[],n=[],r=[],s=[];try{for(let i=0;i<e;i++){const a=await Y.expandWotsSeed(o,i);try{const p=await ye(a);t.push(p),n.push(ke(p))}finally{a.fill(0)}const c=await Y.expandHashlockSecret(o,i);try{const p=h.uint8ArrayToHex(c);r.push(p),s.push(E.computeHashlock(h.ensureHexPrefix(p)).slice(2))}finally{c.fill(0)}}}finally{o.fill(0)}return{perVaultWotsKeys:t,wotsPkHashes:n,htlcSecretHexes:r,hashlocks:s}}const it=1,rt=2,at=33,ct=2,lt=3,ut=1,K=64,ht=0,G=1,ce=/^[0-9a-f]{64}$/i,pt=/^(?:[0-9a-f]{2})+$/;function dt(o){const e=o.slice(2);if(!pt.test(e))throw new Error("proof of possession witness is not even-length lowercase hex");return $.decodeWitnessStack(Uint8Array.from(I.Buffer.from(e,"hex")),"proof of possession witness")}function gt(o,e,t){var r;const n=dt(t);if(n.length===it){const[s]=n;let i,a;if(s.length===K)i=s,a=ht;else if(s.length===K+1&&s[K]===G)i=s.subarray(0,K),a=G;else throw new Error("proof of possession witness item must be a 64-byte Schnorr signature (or 65 bytes ending in 0x01)");if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const c=Uint8Array.from(I.Buffer.from(e,"hex"));if(!V.verifyBip322Simple(o,c,i,a))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2tr-verified"}}if(n.length===rt){if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const[s,i]=n;if(i.length!==at||i[0]!==ct&&i[0]!==lt)throw new Error(`proof of possession P2WPKH witness item 1 is not a compressed public key (${i.length} bytes, prefix 0x${((r=i[0])==null?void 0:r.toString(16))??"none"})`);if(!Ie.isPointCompressed(i))throw new Error("proof of possession P2WPKH witness pubkey is not a valid secp256k1 point");const a=I.Buffer.from(i.subarray(ut)).toString("hex");if(a!==e.toLowerCase())throw new Error(`proof of possession witness pubkey does not match the depositor key: witness carries ${a}, expected ${e}`);if(s.length<V.P2WPKH_ENCODED_SIG_MIN||s.length>V.P2WPKH_ENCODED_SIG_MAX)throw new Error(`proof of possession signature is ${s.length} bytes; vault ingestion accepts only 71/72-byte DER signatures with a sighash byte — try a different account or a Taproot address`);if(s[s.length-1]!==G)throw new Error(`proof of possession P2WPKH signature must end in a SIGHASH_ALL (0x01) byte, got 0x${s[s.length-1].toString(16)}`);if(!V.verifyBip322P2wpkhSimple(o,i,s))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2wpkh-verified"}}throw new Error(`proof of possession witness has ${n.length} items; expected 1 (P2TR) or 2 (P2WPKH)`)}const j="00".repeat(32),ft="00".repeat(32);function mt(o,e){const t={bitcoin:"bc",testnet:"tb",signet:"tb",regtest:"bcrt"};try{const n=pe.address.fromBech32(o);return n.prefix===t[e]&&n.version===0&&n.data.length===20}catch{return!1}}function Pt(o,e,t,n){const r=t==null?void 0:t[`${o}:${e}`];return r?Promise.resolve({txid:o,vout:e,value:r.value,scriptPubKey:r.scriptPubKey}):le.getUtxoInfo(o,e,n)}class bt{constructor(e){w(this,"config");this.config=e}async preparePegin(e){if(e.amounts.length===0)throw new Error("amounts must contain at least one entry");const t=await this.config.btcWallet.getPublicKeyHex(),n=C(t);if(E.supportsDepositApproval(this.config.btcWallet)){const l=(await E.requireChangeAddress(this.config.btcWallet)).trim();if(e.changeAddress.trim()!==l)throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not the approval wallet's change address ("${l}"). Refusing to build a tx the signing device would reject.`)}else if(!h.isAddressFromPublicKey(e.changeAddress,t,this.config.btcNetwork))throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`);const r=await this.prepareSizing(n,e);if(E.supportsDepositApproval(this.config.btcWallet)){const{validateDepositTerms:l}=this.config.btcWallet;typeof l=="function"&&await l.call(this.config.btcWallet,this.buildPeginDepositTerms({params:e,prepeginTxid:ft,prepeginMaxFee:r.fee,depositorClaimValue:r.depositorClaimValue,peginMaxFee:r.minPeginFee}))}const s=r.selectedUTXOs.map(l=>({txid:h.hexToUint8Array(l.txid),vout:l.vout})),i=await ue.deriveVaultRoot(this.config.btcWallet,{depositorBtcPubkey:h.hexToUint8Array(n),fundingOutpoints:s});let a,c;try{const l=await Y.expandAuthAnchor(i);try{a=h.uint8ArrayToHex(l),c=h.uint8ArrayToHex(P.sha256(l))}finally{l.fill(0)}}catch(l){throw i.fill(0),l}const p=await Te(i,e.amounts.length),{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,hashlocks:x}=p,f=await this.preparePeginCommit({depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:x,authAnchorHash:c,sizing:r,params:e});for(let l=0;l<f.perVault.length;l++)if(f.perVault[l].htlcVout!==l)throw new Error(`Internal invariant violation: htlcVout/index mismatch at vault ${l} (expected ${l}, got ${f.perVault[l].htlcVout})`);E.assertAuthAnchorOpReturn(f.fundedPrePeginTxHex,e.amounts.length,c);const{depositTerms:S,...T}=f;return{transaction:{...T,selectedUTXOs:r.selectedUTXOs,fee:r.fee,changeAmount:r.changeAmount},depositorBtcPubkey:n,derivedSecrets:{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,authAnchorHex:a},depositTerms:S}}async prepareSizing(e,t){const n=t.amounts.map(()=>j),r=t.vaultKeeperBtcPubkeys.length,s=await A.buildPrePeginPsbt({vaultCoreVersion:t.vaultCoreVersion,depositorPubkey:e,vaultProviderPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),hashlocks:n,timelockRefund:t.timelockRefund,pegInAmounts:t.amounts,feeRate:t.protocolFeeRate,minPeginFeeRate:t.minPeginFeeRate,numLocalChallengers:r,councilQuorum:t.councilQuorum,councilSize:t.councilSize,network:this.config.btcNetwork,authAnchorHash:j}),i=oe.selectUtxosForPegin([...t.availableUTXOs],s.totalOutputValue,t.mempoolFeeRate,ne.peginOutputCount(s.htlcValues.length,!0));return{selectedUTXOs:i.selectedUTXOs,fee:i.fee,changeAmount:i.changeAmount,depositorClaimValue:s.depositorClaimValue,minPeginFee:s.minPeginFee}}buildPeginDepositTerms(e){const{params:t}=e;return de({vaultCoreVersion:t.vaultCoreVersion,protocolFeeRate:t.protocolFeeRate,timelockPegin:t.timelockPegin,timelockAssert:t.timelockAssert,timelockRefund:t.timelockRefund,prepeginTxid:e.prepeginTxid,prepeginMaxFee:e.prepeginMaxFee,vaultProviderBtcPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperBtcPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerBtcPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),maxAcceptableCommissionBps:te.capMaxAcceptableCommissionBps(t.commissionBps),peginAmounts:t.amounts,depositorClaimValue:e.depositorClaimValue,peginMaxFee:e.peginMaxFee})}async preparePeginCommit(e){const{depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:r,authAnchorHash:s,sizing:i,params:a}=e,c=j.toLowerCase();for(let u=0;u<r.length;u++)if(r[u].toLowerCase()===c)throw new Error(`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${u} — internal substitution bug`);if(s.toLowerCase()===c)throw new Error("preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug");const p=h.stripHexPrefix(a.vaultProviderBtcPubkey),d=a.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),m=a.universalChallengerBtcPubkeys.map(h.stripHexPrefix),k=d.length,x={vaultCoreVersion:a.vaultCoreVersion,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlocks:r,timelockRefund:a.timelockRefund,pegInAmounts:a.amounts,feeRate:a.protocolFeeRate,minPeginFeeRate:a.minPeginFeeRate,numLocalChallengers:k,councilQuorum:a.councilQuorum,councilSize:a.councilSize,network:this.config.btcNetwork,authAnchorHash:s},f=await A.buildPrePeginPsbt(x);if(f.depositorClaimValue!==i.depositorClaimValue||f.minPeginFee!==i.minPeginFee)throw new Error(`Pre-PegIn sizing/commit divergence: depositorClaimValue ${i.depositorClaimValue} -> ${f.depositorClaimValue}, minPeginFee ${i.minPeginFee} -> ${f.minPeginFee}. The provisional deposit terms validated before derivation would not match the terms sent for approval; refusing to continue.`);const S=h.getNetwork(this.config.btcNetwork),T=ne.fundPeginTransaction({unfundedTxHex:f.psbtHex,selectedUTXOs:i.selectedUTXOs,changeAddress:a.changeAddress,changeAmount:i.changeAmount,network:S}),l=i.selectedUTXOs.reduce((u,B)=>u+BigInt(B.value),0n)-f.totalOutputValue-i.changeAmount;if(l!==i.fee)throw new Error(`Pre-PegIn funded fee ${l} does not match the sizing-pass fee ${i.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`);const R=h.stripHexPrefix(Be.calculateBtcTxHash(T)),F=[],g=[],b=[];for(let u=0;u<r.length;u++){const B=await A.buildPeginTxFromFundedPrePegin({prePeginParams:x,timelockPegin:a.timelockPegin,fundedPrePeginTxHex:T,htlcVout:u}),N=await $.buildPeginInputPsbt({vaultCoreVersion:a.vaultCoreVersion,peginTxHex:B.txHex,fundedPrePeginTxHex:T,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlock:r[u],timelockRefund:a.timelockRefund,network:this.config.btcNetwork});F.push(B),g.push(N.psbtHex),b.push(Se.createTaprootScriptPathSignOptions(t,1))}const v=this.buildPeginDepositTerms({params:a,prepeginTxid:R,prepeginMaxFee:i.fee,depositorClaimValue:f.depositorClaimValue,peginMaxFee:f.minPeginFee});E.supportsDepositApproval(this.config.btcWallet)&&await this.config.btcWallet.approveDepositTerms(v);const _=await E.signPsbtsWithFallback(this.config.btcWallet,g,b),W=[];for(let u=0;u<_.length;u++){A.assertPsbtUnsignedTxMatches({requestedPsbtHex:g[u],returnedPsbtHex:_[u]});const B=$.extractPeginInputSignature(_[u],n);A.assertScriptPathSchnorrSignature({requestedPsbtHex:g[u],signatureHex:B,signerXOnlyPubkeyHex:n,inputIndex:0});const N=$.finalizePeginInputPsbt(_[u]);W.push({htlcVout:u,htlcValue:f.htlcValues[u],peginTxHex:N,peginTxid:F[u].txid,peginInputSignature:B,vaultScriptPubKey:F[u].vaultScriptPubKey})}return{fundedPrePeginTxHex:T,prePeginTxid:R,perVault:W,depositTerms:v}}async signAndBroadcast(e){const{fundedPrePeginTxHex:t,depositorBtcPubkey:n}=e,r=t.startsWith("0x")?t.slice(2):t,s=O.Transaction.fromHex(r);if(s.ins.length===0)throw new Error("Transaction has no inputs");const i=new O.Psbt;i.setVersion(s.version),i.setLocktime(s.locktime);const a=I.Buffer.from(C(n),"hex"),c=this.config.mempoolApiUrl,p=s.ins.map(g=>{const b=I.Buffer.from(g.hash).reverse().toString("hex"),v=g.index;return Pt(b,v,e.localPrevouts,c).then(_=>({input:g,utxoData:_,txid:b,vout:v}))}),d=await Promise.all(p),m=d.reduce((g,b)=>g+BigInt(b.utxoData.value),0n),k=s.outs.reduce((g,b)=>g+BigInt(b.value),0n);if(m<k)throw new Error(`UTXO value mismatch: total input value (${m} sat) is less than total output value (${k} sat). This may indicate the mempool API returned manipulated UTXO data.`);const x=m-k;if(x>L.MAX_REASONABLE_FEE_SATS)throw new Error(`Implied transaction fee (${x} sat) exceeds maximum reasonable fee (${L.MAX_REASONABLE_FEE_SATS} sat). This may indicate manipulated UTXO data.`);for(const{input:g,utxoData:b,txid:v,vout:_}of d){const W=oe.getPsbtInputFields({value:b.value,scriptPubKey:b.scriptPubKey},a);i.addInput({hash:g.hash,index:g.index,sequence:g.sequence,...W})}for(const g of s.outs)i.addOutput({script:g.script,value:g.value});await ge({wallet:this.config.btcWallet,depositTerms:e.depositTerms,fundedPrePeginTxHex:t,depositorBtcPubkey:n});const f=i.toHex(),S=await this.config.btcWallet.signPsbt(f);A.assertPsbtUnsignedTxMatches({requestedPsbtHex:f,returnedPsbtHex:S});const T=$.assertReturnedKeyPathSignatures({requestedPsbtHex:f,returnedPsbtHex:S});if(E.supportsDepositApproval(this.config.btcWallet)&&T!==i.data.inputs.length)throw new Error(`Key-path verification covered ${T} of ${i.data.inputs.length} Pre-PegIn inputs; an approval wallet signs every input key-path, so the unverified ones must not be broadcast.`);const l=O.Psbt.fromHex(S);try{l.finalizeAllInputs()}catch(g){if(!l.data.inputs.every(v=>v.finalScriptWitness||v.finalScriptSig))throw new Error(`PSBT finalization failed and wallet did not auto-finalize: ${g}`)}const R=l.extractTransaction().toHex();return await le.pushTx(R,c)}async registerPeginOnChain(e){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.depositorPayoutBtcAddress??await this.config.btcWallet.getAddress(),s=this.resolvePayoutScriptPubKey(n,r);return this.createRegistrationClient().registerPeginOnChain({unsignedPrePeginTx:e.unsignedPrePeginTx,depositorSignedPeginTx:e.depositorSignedPeginTx,vaultProvider:e.vaultProvider,hashlock:e.hashlock,htlcVout:e.htlcVout,depositorPayoutScriptPubKey:s,depositorBtcPubkeyRaw:n,depositorWotsPkHash:e.depositorWotsPkHash,popSignature:e.popSignature,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint})}async registerPeginBatchOnChain(e){if(e.requests.length===0)throw new Error("Batch pegin requires at least one request");if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.requests.map(s=>this.resolvePayoutScriptPubKey(n,s.depositorPayoutBtcAddress));return this.createRegistrationClient().registerPeginBatchOnChain({vaultProvider:e.vaultProvider,unsignedPrePeginTx:e.unsignedPrePeginTx,popSignature:e.popSignature,depositorBtcPubkeyRaw:n,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint,requests:e.requests.map((s,i)=>({depositorSignedPeginTx:s.depositorSignedPeginTx,hashlock:s.hashlock,htlcVout:s.htlcVout,depositorPayoutScriptPubKey:r[i],depositorWotsPkHash:s.depositorWotsPkHash}))})}createRegistrationClient(){return new te.ViemPeginRegistrationClient({ethWallet:this.config.ethWallet,ethChain:this.config.ethChain,publicClient:this.config.publicClient,btcVaultRegistry:this.config.vaultContracts.btcVaultRegistry,requireQuotedCommissionBps:E.supportsDepositApproval(this.config.btcWallet)})}resolvePayoutScriptPubKey(e,t){if(!h.isAddressFromPublicKey(t,e,this.config.btcNetwork))throw h.stripHexPrefix(e).length===L.X_ONLY_PUBKEY_HEX_LEN&&mt(t,this.config.btcNetwork)?new Error(`BTC payout address "${t}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`):new Error(`BTC payout address "${t}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`);const n=h.getNetwork(this.config.btcNetwork);let r;try{r=pe.address.toOutputScript(t,n).toString("hex")}catch{throw new Error(`Invalid BTC payout address: "${t}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`)}return r}async signProofOfPossession(){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const e=this.config.ethWallet.account.address,t=C(await this.config.btcWallet.getPublicKeyHex()),n=this.config.vaultContracts.btcVaultRegistry,r=`${e.toLowerCase()}:${this.config.ethChain.id}:pegin:${n.toLowerCase()}`,s=await this.config.btcWallet.signMessage(r,"bip322-simple"),i=Ne(s);return gt(new TextEncoder().encode(r),t,i),{btcPopSignature:i,depositorEthAddress:e,depositorBtcPubkey:t}}async assertPopMatchesBtcWallet(e){const t=await this.config.btcWallet.getPublicKeyHex(),n=C(t),r=C(e.depositorBtcPubkey);if(n!==r)throw new Error(`Proof of possession was signed with BTC pubkey ${r} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`);return t}getNetwork(){return this.config.btcNetwork}getVaultContractAddress(){return this.config.vaultContracts.btcVaultRegistry}}exports.PeginManager=bt;exports.buildDepositTerms=de;exports.computeWotsBlockPublicKeysHash=ke;exports.deriveWotsBlocksFromSeed=ye;exports.ensurePrePeginTermsApproval=ge;exports.expandPerVaultSecrets=Te;
2
- //# sourceMappingURL=PeginManager-8EUlm10F.cjs.map
1
+ "use strict";var ve=Object.defineProperty;var Ee=(o,e,t)=>e in o?ve(o,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):o[e]=t;var w=(o,e,t)=>Ee(o,typeof e!="symbol"?e+"":e,t);const P=require("./sha2-Ce6KewYx.cjs"),O=require("bitcoinjs-lib"),I=require("buffer"),ee=require("viem"),te=require("./pegin-registration-client-BogzOk8B.cjs"),le=require("./tbv/core/clients/mempool/index.cjs"),Y=require("./tbv/core/wasm/index.cjs"),A=require("./verifyScriptPathSchnorrSignature-D2t1yACC.cjs"),$=require("./verifyKeyPathSchnorrSignature-CQUut2-O.cjs"),h=require("./bitcoin-D-O2GjbC.cjs"),Se=require("./signing-DvISftFk.cjs"),L=require("./validation-C6XTfZak.cjs"),ue=require("./deriveVaultRoot-C3uqnJto.cjs"),E=require("./PayoutManager-DOdsgcUR.cjs"),_e=require("./registration-records-DFQgBaYi.cjs"),oe=require("./psbtInputFields-BrV_ZfL_.cjs"),ne=require("./fundPeginTransaction-54-Rwb2k.cjs"),U=require("./constants-BwCg5K6R.cjs"),Be=require("./btcTxHash-CGb5BqFL.cjs"),Ae=require("./parseFundingOutpoints-C_-PT9BT.cjs"),Ce=require("@bitcoin-js/tiny-secp256k1-asmjs"),V=require("./bip322Verify-DLxJR9CQ.cjs");function he(o){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const t in o)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(o,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>o[t]})}}return e.default=o,Object.freeze(e)}const pe=he(O),Ie=he(Ce),M=BigInt(2**32-1),se=BigInt(32);function He(o,e=!1){return e?{h:Number(o&M),l:Number(o>>se&M)}:{h:Number(o>>se&M)|0,l:Number(o&M)|0}}function $e(o,e=!1){const t=o.length;let n=new Uint32Array(t),r=new Uint32Array(t);for(let s=0;s<t;s++){const{h:i,l:a}=He(o[s],e);[n[s],r[s]]=[i,a]}return[n,r]}const Oe=(o,e,t)=>o<<t|e>>>32-t,Re=(o,e,t)=>e<<t|o>>>32-t,Fe=(o,e,t)=>e<<t-32|o>>>64-t,We=(o,e,t)=>o<<t-32|e>>>64-t,Ve=64;function de(o){const e=o.prepeginTxid.toLowerCase();if(!/^[0-9a-f]+$/.test(e)||e.length!==Ve)throw new Error(`buildDepositTerms: prepeginTxid must be 64 hex chars, got "${o.prepeginTxid}"`);if(o.peginAmounts.length===0)throw new Error("buildDepositTerms: at least one pegin amount is required");if(o.timelockPegin<=0||o.timelockAssert<=0||o.timelockRefund<=0)throw new Error("buildDepositTerms: timelocks must be positive");if(!Number.isInteger(o.maxAcceptableCommissionBps)||o.maxAcceptableCommissionBps<0||o.maxAcceptableCommissionBps>=U.MAX_VP_COMMISSION_BPS_EXCLUSIVE)throw new Error(`buildDepositTerms: maxAcceptableCommissionBps must be an integer in [0, ${U.MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${o.maxAcceptableCommissionBps}`);const t=BigInt(U.BPS_DENOMINATOR),n=o.peginAmounts.map((r,s)=>({htlcVout:s,vaultProviderBtcPubkey:o.vaultProviderBtcPubkey,peginAmount:r,commissionFee:r*BigInt(o.maxAcceptableCommissionBps)/t,depositorClaimValue:o.depositorClaimValue,peginMaxFee:o.peginMaxFee}));return{vaultCoreVersion:o.vaultCoreVersion,protocolFeeRate:o.protocolFeeRate,timelockPegin:o.timelockPegin,timelockAssert:o.timelockAssert,timelockRefund:o.timelockRefund,prepeginTxid:e,prepeginMaxFee:o.prepeginMaxFee,vaultKeeperBtcPubkeys:[...o.vaultKeeperBtcPubkeys],universalChallengerBtcPubkeys:[...o.universalChallengerBtcPubkeys],vaults:n}}const Me=/^0x[0-9a-f]+$/i,De=/^[0-9a-f]+$/i,Ke=/^[A-Za-z0-9+/]+={0,2}$/;function C(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty public key");return h.processPublicKeyToXOnly(o).toLowerCase()}function Ne(o){if(typeof o!="string"||o.length===0)throw new Error("BTC wallet returned empty BIP-322 signature");if(o.startsWith("0x")||o.startsWith("0X")){if(!Me.test(o)||o.length<4||o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return o.toLowerCase()}if(De.test(o)){if(o.length%2!==0)throw new Error("BTC wallet returned malformed hex BIP-322 signature");return`0x${o.toLowerCase()}`}if(!Ke.test(o)||o.length%4!==0)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");const e=I.Buffer.from(o,"base64");if(e.length===0||e.toString("base64")!==o)throw new Error("BTC wallet returned malformed base64 BIP-322 signature");return`0x${e.toString("hex")}`}async function ge(o){const{wallet:e,depositTerms:t,fundedPrePeginTxHex:n,depositorBtcPubkey:r}=o,s=typeof e.approveDepositTerms=="function"?e.approveDepositTerms:void 0;if(!s&&!t)return;const i=n.startsWith("0x")?n.slice(2):n,c=O.Transaction.fromHex(i).getId();if(t&&t.prepeginTxid.replace(/^0x/,"").toLowerCase()!==c)throw new Error(`Deposit terms do not match the transaction being broadcast: terms are for prepeginTxid ${t.prepeginTxid}, but this transaction is ${c}.`);if(!s)return;if(!t)throw new Error("This wallet requires approved deposit terms before signing the Pre-PegIn transaction, but none were provided. Pass PreparePeginResult.depositTerms (fresh flows) or a resume rebuild.");if(typeof e.deriveContextHash!="function")throw new Error("A deposit-approval wallet must also implement deriveContextHash, but this one does not.");if(typeof e.holdsApprovedDepositTerms=="function"){let m=!1;try{m=await e.holdsApprovedDepositTerms(t)}catch{}if(m)return}typeof e.validateDepositTerms=="function"&&await e.validateDepositTerms(t);const p=Ae.parseFundingOutpointsFromTx(n);(await ue.deriveVaultRoot({deriveContextHash:e.deriveContextHash.bind(e)},{depositorBtcPubkey:h.hexToUint8Array(C(r)),fundingOutpoints:p})).fill(0),await s.call(e,t)}const Le=BigInt(0),H=BigInt(1),Ue=BigInt(2),Xe=BigInt(7),qe=BigInt(256),ze=BigInt(113),fe=[],me=[],Pe=[];for(let o=0,e=H,t=1,n=0;o<24;o++){[t,n]=[n,(2*t+3*n)%5],fe.push(2*(5*n+t)),me.push((o+1)*(o+2)/2%64);let r=Le;for(let s=0;s<7;s++)e=(e<<H^(e>>Xe)*ze)%qe,e&Ue&&(r^=H<<(H<<BigInt(s))-H);Pe.push(r)}const be=$e(Pe,!0),Ge=be[0],je=be[1],ie=(o,e,t)=>t>32?Fe(o,e,t):Oe(o,e,t),re=(o,e,t)=>t>32?We(o,e,t):Re(o,e,t);function Ye(o,e=24){const t=new Uint32Array(10);for(let n=24-e;n<24;n++){for(let i=0;i<10;i++)t[i]=o[i]^o[i+10]^o[i+20]^o[i+30]^o[i+40];for(let i=0;i<10;i+=2){const a=(i+8)%10,c=(i+2)%10,p=t[c],d=t[c+1],m=ie(p,d,1)^t[a],k=re(p,d,1)^t[a+1];for(let x=0;x<50;x+=10)o[i+x]^=m,o[i+x+1]^=k}let r=o[2],s=o[3];for(let i=0;i<24;i++){const a=me[i],c=ie(r,s,a),p=re(r,s,a),d=fe[i];r=o[d],s=o[d+1],o[d]=c,o[d+1]=p}for(let i=0;i<50;i+=10){for(let a=0;a<10;a++)t[a]=o[i+a];for(let a=0;a<10;a++)o[i+a]^=~t[(a+2)%10]&t[(a+4)%10]}o[0]^=Ge[n],o[1]^=je[n]}P.clean(t)}class Z{constructor(e,t,n,r=!1,s=24){w(this,"state");w(this,"pos",0);w(this,"posOut",0);w(this,"finished",!1);w(this,"state32");w(this,"destroyed",!1);w(this,"blockLen");w(this,"suffix");w(this,"outputLen");w(this,"enableXOF",!1);w(this,"rounds");if(this.blockLen=e,this.suffix=t,this.outputLen=n,this.enableXOF=r,this.rounds=s,P.anumber(n,"outputLen"),!(0<e&&e<200))throw new Error("only keccak-f1600 function is supported");this.state=new Uint8Array(200),this.state32=P.u32(this.state)}clone(){return this._cloneInto()}keccak(){P.swap32IfBE(this.state32),Ye(this.state32,this.rounds),P.swap32IfBE(this.state32),this.posOut=0,this.pos=0}update(e){P.aexists(this),P.abytes(e);const{blockLen:t,state:n}=this,r=e.length;for(let s=0;s<r;){const i=Math.min(t-this.pos,r-s);for(let a=0;a<i;a++)n[this.pos++]^=e[s++];this.pos===t&&this.keccak()}return this}finish(){if(this.finished)return;this.finished=!0;const{state:e,suffix:t,pos:n,blockLen:r}=this;e[n]^=t,(t&128)!==0&&n===r-1&&this.keccak(),e[r-1]^=128,this.keccak()}writeInto(e){P.aexists(this,!1),P.abytes(e),this.finish();const t=this.state,{blockLen:n}=this;for(let r=0,s=e.length;r<s;){this.posOut>=n&&this.keccak();const i=Math.min(n-this.posOut,s-r);e.set(t.subarray(this.posOut,this.posOut+i),r),this.posOut+=i,r+=i}return e}xofInto(e){if(!this.enableXOF)throw new Error("XOF is not possible for this instance");return this.writeInto(e)}xof(e){return P.anumber(e),this.xofInto(new Uint8Array(e))}digestInto(e){if(P.aoutput(e,this),this.finished)throw new Error("digest() was already called");return this.writeInto(e),this.destroy(),e}digest(){return this.digestInto(new Uint8Array(this.outputLen))}destroy(){this.destroyed=!0,P.clean(this.state)}_cloneInto(e){const{blockLen:t,suffix:n,outputLen:r,rounds:s,enableXOF:i}=this;return e||(e=new Z(t,n,r,i,s)),e.state32.set(this.state32),e.pos=this.pos,e.posOut=this.posOut,e.finished=this.finished,e.rounds=s,e.suffix=n,e.outputLen=r,e.enableXOF=i,e.destroyed=this.destroyed,e}}const Qe=(o,e,t,n={})=>P.createHasher(()=>new Z(e,o,t),n),Ze=Qe(1,136,32),ae=64,y=20,Q=4,we=2,Je=0,et=1,D=[64,64],tt=o=>Array.from(o).map(e=>e.toString(16).padStart(2,"0")).join("");function J(o){return _e.ripemd160(P.sha256(o))}function xe(o){return(1<<o)-1}function ot(o){let e=1;for(;e*e<o+1;)e++;return Math.max(e,2)}function nt(o){const e=Q,t=o*xe(e);return{d:e,n:o,checksum_radix:ot(t)}}function X(o,e){const t=[];let n=e;for(;n>0;)t.push(n&255),n>>>=8;const r=new Uint8Array(o.length+t.length);r.set(o);for(let s=0;s<t.length;s++)r[o.length+s]=t[s];return J(r)}function q(o,e){let t=o;for(let n=0;n<e;n++)t=J(t);return t}function st(o,e){const t=xe(e.d),n=e.checksum_radix-1,r=Math.floor(e.n*t/e.checksum_radix),s=[];for(let d=0;d<e.n;d++){const m=X(o,d+we),k=q(m,t);s.push(Array.from(k))}const i=X(o,Je),a=q(i,n),c=X(o,et),p=q(c,r);return{config:e,message_terminals:s,checksum_major_terminal:Array.from(p),checksum_minor_terminal:Array.from(a)}}async function ye(o){try{if(o.length!==ae)throw new Error(`WOTS seed must be exactly ${ae} bytes, got ${o.length}`);const e=[];for(let t=0;t<D.length;t++){const n=D[t],r=nt(n),s=new Uint8Array(o.length+1);s.set(o),s[o.length]=t;const i=J(s);try{const a=st(i,r);if(a.config.d!==Q)throw new Error(`Block ${t}: expected d=${Q}, got d=${a.config.d}`);if(a.config.n!==n)throw new Error(`Block ${t}: expected n=${n}, got n=${a.config.n}`);if(a.message_terminals.length!==n)throw new Error(`Block ${t}: expected ${n} message terminals, got ${a.message_terminals.length}`);for(let c=0;c<a.message_terminals.length;c++)if(a.message_terminals[c].length!==y)throw new Error(`Block ${t} terminal ${c}: expected ${y} bytes, got ${a.message_terminals[c].length}`);if(a.checksum_minor_terminal.length!==y)throw new Error(`Block ${t} checksum_minor: expected ${y} bytes`);if(a.checksum_major_terminal.length!==y)throw new Error(`Block ${t} checksum_major: expected ${y} bytes`);e.push(a)}finally{s.fill(0),i.fill(0)}}if(e.length!==D.length)throw new Error(`Expected ${D.length} blocks, got ${e.length}`);return e}finally{o.fill(0)}}function z(o,e,t){if(o.length!==y)throw new Error(`Block ${e} ${t}: expected ${y} bytes, got ${o.length}`);for(let n=0;n<o.length;n++){const r=o[n];if(!Number.isInteger(r)||r<0||r>255)throw new Error(`Block ${e} ${t}[${n}]: invalid byte value ${r}`)}}function ke(o){if(o.length===0)throw new Error("Public keys array must not be empty");for(let s=0;s<o.length;s++){const i=o[s];z(i.checksum_minor_terminal,s,"checksum_minor_terminal"),z(i.checksum_major_terminal,s,"checksum_major_terminal");for(let a=0;a<i.message_terminals.length;a++)z(i.message_terminals[a],s,`message_terminal[${a}]`)}let e=0;for(const s of o)e+=we+s.message_terminals.length;const t=new Uint8Array(e*y);let n=0;for(const s of o){t.set(s.checksum_minor_terminal,n),n+=y,t.set(s.checksum_major_terminal,n),n+=y;for(const i of s.message_terminals)t.set(i,n),n+=y}const r=Ze(t);return`0x${tt(r)}`}async function Te(o,e){const t=[],n=[],r=[],s=[];try{for(let i=0;i<e;i++){const a=await Y.expandWotsSeed(o,i);try{const p=await ye(a);t.push(p),n.push(ke(p))}finally{a.fill(0)}const c=await Y.expandHashlockSecret(o,i);try{const p=h.uint8ArrayToHex(c);r.push(p),s.push(E.computeHashlock(h.ensureHexPrefix(p)).slice(2))}finally{c.fill(0)}}}finally{o.fill(0)}return{perVaultWotsKeys:t,wotsPkHashes:n,htlcSecretHexes:r,hashlocks:s}}const it=1,rt=2,at=33,ct=2,lt=3,ut=1,K=64,ht=0,G=1,ce=/^[0-9a-f]{64}$/i,pt=/^(?:[0-9a-f]{2})+$/;function dt(o){const e=o.slice(2);if(!pt.test(e))throw new Error("proof of possession witness is not even-length lowercase hex");return $.decodeWitnessStack(Uint8Array.from(I.Buffer.from(e,"hex")),"proof of possession witness")}function gt(o,e,t){var r;const n=dt(t);if(n.length===it){const[s]=n;let i,a;if(s.length===K)i=s,a=ht;else if(s.length===K+1&&s[K]===G)i=s.subarray(0,K),a=G;else throw new Error("proof of possession witness item must be a 64-byte Schnorr signature (or 65 bytes ending in 0x01)");if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const c=Uint8Array.from(I.Buffer.from(e,"hex"));if(!V.verifyBip322Simple(o,c,i,a))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2tr-verified"}}if(n.length===rt){if(!ce.test(e))throw new Error(`depositor public key must be bare 64-char x-only hex, got "${e}"`);const[s,i]=n;if(i.length!==at||i[0]!==ct&&i[0]!==lt)throw new Error(`proof of possession P2WPKH witness item 1 is not a compressed public key (${i.length} bytes, prefix 0x${((r=i[0])==null?void 0:r.toString(16))??"none"})`);if(!Ie.isPointCompressed(i))throw new Error("proof of possession P2WPKH witness pubkey is not a valid secp256k1 point");const a=I.Buffer.from(i.subarray(ut)).toString("hex");if(a!==e.toLowerCase())throw new Error(`proof of possession witness pubkey does not match the depositor key: witness carries ${a}, expected ${e}`);if(s.length<V.P2WPKH_ENCODED_SIG_MIN||s.length>V.P2WPKH_ENCODED_SIG_MAX)throw new Error(`proof of possession signature is ${s.length} bytes; vault ingestion accepts only 71/72-byte DER signatures with a sighash byte — try a different account or a Taproot address`);if(s[s.length-1]!==G)throw new Error(`proof of possession P2WPKH signature must end in a SIGHASH_ALL (0x01) byte, got 0x${s[s.length-1].toString(16)}`);if(!V.verifyBip322P2wpkhSimple(o,i,s))throw new Error("proof of possession signature does not verify against the depositor key");return{kind:"p2wpkh-verified"}}throw new Error(`proof of possession witness has ${n.length} items; expected 1 (P2TR) or 2 (P2WPKH)`)}const j="00".repeat(32),ft="00".repeat(32);function mt(o,e){const t={bitcoin:"bc",testnet:"tb",signet:"tb",regtest:"bcrt"};try{const n=pe.address.fromBech32(o);return n.prefix===t[e]&&n.version===0&&n.data.length===20}catch{return!1}}function Pt(o,e,t,n){const r=t==null?void 0:t[`${o}:${e}`];return r?Promise.resolve({txid:o,vout:e,value:r.value,scriptPubKey:r.scriptPubKey}):le.getUtxoInfo(o,e,n)}class bt{constructor(e){w(this,"config");this.config=e}async preparePegin(e){if(e.amounts.length===0)throw new Error("amounts must contain at least one entry");const t=await this.config.btcWallet.getPublicKeyHex(),n=C(t);if(E.supportsDepositApproval(this.config.btcWallet)){const l=(await E.requireChangeAddress(this.config.btcWallet)).trim();if(e.changeAddress.trim()!==l)throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not the approval wallet's change address ("${l}"). Refusing to build a tx the signing device would reject.`)}else if(!h.isAddressFromPublicKey(e.changeAddress,t,this.config.btcNetwork))throw new Error(`Pre-PegIn changeAddress "${e.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`);const r=await this.prepareSizing(n,e);if(E.supportsDepositApproval(this.config.btcWallet)){const{validateDepositTerms:l}=this.config.btcWallet;typeof l=="function"&&await l.call(this.config.btcWallet,this.buildPeginDepositTerms({params:e,prepeginTxid:ft,prepeginMaxFee:r.fee,depositorClaimValue:r.depositorClaimValue,peginMaxFee:r.minPeginFee}))}const s=r.selectedUTXOs.map(l=>({txid:h.hexToUint8Array(l.txid),vout:l.vout})),i=await ue.deriveVaultRoot(this.config.btcWallet,{depositorBtcPubkey:h.hexToUint8Array(n),fundingOutpoints:s});let a,c;try{const l=await Y.expandAuthAnchor(i);try{a=h.uint8ArrayToHex(l),c=h.uint8ArrayToHex(P.sha256(l))}finally{l.fill(0)}}catch(l){throw i.fill(0),l}const p=await Te(i,e.amounts.length),{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,hashlocks:x}=p,f=await this.preparePeginCommit({depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:x,authAnchorHash:c,sizing:r,params:e});for(let l=0;l<f.perVault.length;l++)if(f.perVault[l].htlcVout!==l)throw new Error(`Internal invariant violation: htlcVout/index mismatch at vault ${l} (expected ${l}, got ${f.perVault[l].htlcVout})`);E.assertAuthAnchorOpReturn(f.fundedPrePeginTxHex,e.amounts.length,c);const{depositTerms:S,...T}=f;return{transaction:{...T,selectedUTXOs:r.selectedUTXOs,fee:r.fee,changeAmount:r.changeAmount},depositorBtcPubkey:n,derivedSecrets:{perVaultWotsKeys:d,wotsPkHashes:m,htlcSecretHexes:k,authAnchorHex:a},depositTerms:S}}async prepareSizing(e,t){const n=t.amounts.map(()=>j),r=t.vaultKeeperBtcPubkeys.length,s=await A.buildPrePeginPsbt({vaultCoreVersion:t.vaultCoreVersion,depositorPubkey:e,vaultProviderPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),hashlocks:n,timelockRefund:t.timelockRefund,pegInAmounts:t.amounts,feeRate:t.protocolFeeRate,minPeginFeeRate:t.minPeginFeeRate,numLocalChallengers:r,councilQuorum:t.councilQuorum,councilSize:t.councilSize,network:this.config.btcNetwork,authAnchorHash:j}),i=oe.selectUtxosForPegin([...t.availableUTXOs],s.totalOutputValue,t.mempoolFeeRate,ne.peginOutputCount(s.htlcValues.length,!0));return{selectedUTXOs:i.selectedUTXOs,fee:i.fee,changeAmount:i.changeAmount,depositorClaimValue:s.depositorClaimValue,minPeginFee:s.minPeginFee}}buildPeginDepositTerms(e){const{params:t}=e;return de({vaultCoreVersion:t.vaultCoreVersion,protocolFeeRate:t.protocolFeeRate,timelockPegin:t.timelockPegin,timelockAssert:t.timelockAssert,timelockRefund:t.timelockRefund,prepeginTxid:e.prepeginTxid,prepeginMaxFee:e.prepeginMaxFee,vaultProviderBtcPubkey:h.stripHexPrefix(t.vaultProviderBtcPubkey),vaultKeeperBtcPubkeys:t.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),universalChallengerBtcPubkeys:t.universalChallengerBtcPubkeys.map(h.stripHexPrefix),maxAcceptableCommissionBps:te.capMaxAcceptableCommissionBps(t.commissionBps),peginAmounts:t.amounts,depositorClaimValue:e.depositorClaimValue,peginMaxFee:e.peginMaxFee})}async preparePeginCommit(e){const{depositorBtcPubkeyRaw:t,depositorBtcPubkey:n,hashlocks:r,authAnchorHash:s,sizing:i,params:a}=e,c=j.toLowerCase();for(let u=0;u<r.length;u++)if(r[u].toLowerCase()===c)throw new Error(`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${u} — internal substitution bug`);if(s.toLowerCase()===c)throw new Error("preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug");const p=h.stripHexPrefix(a.vaultProviderBtcPubkey),d=a.vaultKeeperBtcPubkeys.map(h.stripHexPrefix),m=a.universalChallengerBtcPubkeys.map(h.stripHexPrefix),k=d.length,x={vaultCoreVersion:a.vaultCoreVersion,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlocks:r,timelockRefund:a.timelockRefund,pegInAmounts:a.amounts,feeRate:a.protocolFeeRate,minPeginFeeRate:a.minPeginFeeRate,numLocalChallengers:k,councilQuorum:a.councilQuorum,councilSize:a.councilSize,network:this.config.btcNetwork,authAnchorHash:s},f=await A.buildPrePeginPsbt(x);if(f.depositorClaimValue!==i.depositorClaimValue||f.minPeginFee!==i.minPeginFee)throw new Error(`Pre-PegIn sizing/commit divergence: depositorClaimValue ${i.depositorClaimValue} -> ${f.depositorClaimValue}, minPeginFee ${i.minPeginFee} -> ${f.minPeginFee}. The provisional deposit terms validated before derivation would not match the terms sent for approval; refusing to continue.`);const S=h.getNetwork(this.config.btcNetwork),T=ne.fundPeginTransaction({unfundedTxHex:f.psbtHex,selectedUTXOs:i.selectedUTXOs,changeAddress:a.changeAddress,changeAmount:i.changeAmount,network:S}),l=i.selectedUTXOs.reduce((u,B)=>u+BigInt(B.value),0n)-f.totalOutputValue-i.changeAmount;if(l!==i.fee)throw new Error(`Pre-PegIn funded fee ${l} does not match the sizing-pass fee ${i.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`);const R=h.stripHexPrefix(Be.calculateBtcTxHash(T)),F=[],g=[],b=[];for(let u=0;u<r.length;u++){const B=await A.buildPeginTxFromFundedPrePegin({prePeginParams:x,timelockPegin:a.timelockPegin,fundedPrePeginTxHex:T,htlcVout:u}),N=await $.buildPeginInputPsbt({vaultCoreVersion:a.vaultCoreVersion,peginTxHex:B.txHex,fundedPrePeginTxHex:T,depositorPubkey:n,vaultProviderPubkey:p,vaultKeeperPubkeys:d,universalChallengerPubkeys:m,hashlock:r[u],timelockRefund:a.timelockRefund,network:this.config.btcNetwork});F.push(B),g.push(N.psbtHex),b.push(Se.createTaprootScriptPathSignOptions(t,1))}const v=this.buildPeginDepositTerms({params:a,prepeginTxid:R,prepeginMaxFee:i.fee,depositorClaimValue:f.depositorClaimValue,peginMaxFee:f.minPeginFee});E.supportsDepositApproval(this.config.btcWallet)&&await this.config.btcWallet.approveDepositTerms(v);const _=await E.signPsbtsWithFallback(this.config.btcWallet,g,b),W=[];for(let u=0;u<_.length;u++){A.assertPsbtUnsignedTxMatches({requestedPsbtHex:g[u],returnedPsbtHex:_[u]});const B=$.extractPeginInputSignature(_[u],n);A.assertScriptPathSchnorrSignature({requestedPsbtHex:g[u],signatureHex:B,signerXOnlyPubkeyHex:n,inputIndex:0});const N=$.finalizePeginInputPsbt(_[u]);W.push({htlcVout:u,htlcValue:f.htlcValues[u],peginTxHex:N,peginTxid:F[u].txid,peginInputSignature:B,vaultScriptPubKey:F[u].vaultScriptPubKey})}return{fundedPrePeginTxHex:T,prePeginTxid:R,perVault:W,depositTerms:v}}async signAndBroadcast(e){const{fundedPrePeginTxHex:t,depositorBtcPubkey:n}=e,r=t.startsWith("0x")?t.slice(2):t,s=O.Transaction.fromHex(r);if(s.ins.length===0)throw new Error("Transaction has no inputs");const i=new O.Psbt;i.setVersion(s.version),i.setLocktime(s.locktime);const a=I.Buffer.from(C(n),"hex"),c=this.config.mempoolApiUrl,p=s.ins.map(g=>{const b=I.Buffer.from(g.hash).reverse().toString("hex"),v=g.index;return Pt(b,v,e.localPrevouts,c).then(_=>({input:g,utxoData:_,txid:b,vout:v}))}),d=await Promise.all(p),m=d.reduce((g,b)=>g+BigInt(b.utxoData.value),0n),k=s.outs.reduce((g,b)=>g+BigInt(b.value),0n);if(m<k)throw new Error(`UTXO value mismatch: total input value (${m} sat) is less than total output value (${k} sat). This may indicate the mempool API returned manipulated UTXO data.`);const x=m-k;if(x>L.MAX_REASONABLE_FEE_SATS)throw new Error(`Implied transaction fee (${x} sat) exceeds maximum reasonable fee (${L.MAX_REASONABLE_FEE_SATS} sat). This may indicate manipulated UTXO data.`);for(const{input:g,utxoData:b,txid:v,vout:_}of d){const W=oe.getPsbtInputFields({value:b.value,scriptPubKey:b.scriptPubKey},a);i.addInput({hash:g.hash,index:g.index,sequence:g.sequence,...W})}for(const g of s.outs)i.addOutput({script:g.script,value:g.value});await ge({wallet:this.config.btcWallet,depositTerms:e.depositTerms,fundedPrePeginTxHex:t,depositorBtcPubkey:n});const f=i.toHex(),S=await this.config.btcWallet.signPsbt(f);A.assertPsbtUnsignedTxMatches({requestedPsbtHex:f,returnedPsbtHex:S});const T=$.assertReturnedKeyPathSignatures({requestedPsbtHex:f,returnedPsbtHex:S});if(E.supportsDepositApproval(this.config.btcWallet)&&T!==i.data.inputs.length)throw new Error(`Key-path verification covered ${T} of ${i.data.inputs.length} Pre-PegIn inputs; an approval wallet signs every input key-path, so the unverified ones must not be broadcast.`);const l=O.Psbt.fromHex(S);try{l.finalizeAllInputs()}catch(g){if(!l.data.inputs.every(v=>v.finalScriptWitness||v.finalScriptSig))throw new Error(`PSBT finalization failed and wallet did not auto-finalize: ${g}`)}const R=l.extractTransaction().toHex();return await le.pushTx(R,c)}async registerPeginOnChain(e){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.depositorPayoutBtcAddress??await this.config.btcWallet.getAddress(),s=this.resolvePayoutScriptPubKey(n,r);return this.createRegistrationClient().registerPeginOnChain({unsignedPrePeginTx:e.unsignedPrePeginTx,depositorSignedPeginTx:e.depositorSignedPeginTx,vaultProvider:e.vaultProvider,hashlock:e.hashlock,htlcVout:e.htlcVout,depositorPayoutScriptPubKey:s,depositorBtcPubkeyRaw:n,depositorWotsPkHash:e.depositorWotsPkHash,popSignature:e.popSignature,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint})}async registerPeginBatchOnChain(e){if(e.requests.length===0)throw new Error("Batch pegin requires at least one request");if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const t=this.config.ethWallet.account.address;if(!ee.isAddressEqual(e.popSignature.depositorEthAddress,t))throw new Error(`Proof of possession was signed for ${e.popSignature.depositorEthAddress} but the Ethereum wallet is currently connected to ${t}. Reconnect the original account or call signProofOfPossession() again.`);const n=await this.assertPopMatchesBtcWallet(e.popSignature),r=e.requests.map(s=>this.resolvePayoutScriptPubKey(n,s.depositorPayoutBtcAddress));return this.createRegistrationClient().registerPeginBatchOnChain({vaultProvider:e.vaultProvider,unsignedPrePeginTx:e.unsignedPrePeginTx,popSignature:e.popSignature,depositorBtcPubkeyRaw:n,quotedCommissionBps:e.quotedCommissionBps,expectedFingerprint:e.expectedFingerprint,requests:e.requests.map((s,i)=>({depositorSignedPeginTx:s.depositorSignedPeginTx,hashlock:s.hashlock,htlcVout:s.htlcVout,depositorPayoutScriptPubKey:r[i],depositorWotsPkHash:s.depositorWotsPkHash}))})}createRegistrationClient(){return new te.ViemPeginRegistrationClient({ethWallet:this.config.ethWallet,ethChain:this.config.ethChain,publicClient:this.config.publicClient,btcVaultRegistry:this.config.vaultContracts.btcVaultRegistry,requireQuotedCommissionBps:E.supportsDepositApproval(this.config.btcWallet)})}resolvePayoutScriptPubKey(e,t){if(!h.isAddressFromPublicKey(t,e,this.config.btcNetwork))throw h.stripHexPrefix(e).length===L.X_ONLY_PUBKEY_HEX_LEN&&mt(t,this.config.btcNetwork)?new Error(`BTC payout address "${t}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`):new Error(`BTC payout address "${t}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`);const n=h.getNetwork(this.config.btcNetwork);let r;try{r=pe.address.toOutputScript(t,n).toString("hex")}catch{throw new Error(`Invalid BTC payout address: "${t}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`)}return r}async signProofOfPossession(){if(!this.config.ethWallet.account)throw new Error("Ethereum wallet account not found");const e=this.config.ethWallet.account.address,t=C(await this.config.btcWallet.getPublicKeyHex()),n=this.config.vaultContracts.btcVaultRegistry,r=`${e.toLowerCase()}:${this.config.ethChain.id}:pegin:${n.toLowerCase()}`,s=await this.config.btcWallet.signMessage(r,"bip322-simple"),i=Ne(s);return gt(new TextEncoder().encode(r),t,i),{btcPopSignature:i,depositorEthAddress:e,depositorBtcPubkey:t}}async assertPopMatchesBtcWallet(e){const t=await this.config.btcWallet.getPublicKeyHex(),n=C(t),r=C(e.depositorBtcPubkey);if(n!==r)throw new Error(`Proof of possession was signed with BTC pubkey ${r} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`);return t}getNetwork(){return this.config.btcNetwork}getVaultContractAddress(){return this.config.vaultContracts.btcVaultRegistry}}exports.PeginManager=bt;exports.buildDepositTerms=de;exports.computeWotsBlockPublicKeysHash=ke;exports.deriveWotsBlocksFromSeed=ye;exports.ensurePrePeginTermsApproval=ge;exports.expandPerVaultSecrets=Te;
2
+ //# sourceMappingURL=PeginManager-BHplS4dM.cjs.map