@babylonlabs-io/ts-sdk 0.36.3 → 0.37.2
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.
- package/dist/PayoutManager-BxAY2x0g.cjs +2 -0
- package/dist/PayoutManager-BxAY2x0g.cjs.map +1 -0
- package/dist/{PayoutManager-s_uH8Uuj.js → PayoutManager-sfxuOBGq.js} +51 -43
- package/dist/PayoutManager-sfxuOBGq.js.map +1 -0
- package/dist/{PeginManager-CB-dVkT2.js → PeginManager-B1Mh8dJ3.js} +332 -323
- package/dist/PeginManager-B1Mh8dJ3.js.map +1 -0
- package/dist/PeginManager-BbHPyz-G.cjs +2 -0
- package/dist/PeginManager-BbHPyz-G.cjs.map +1 -0
- package/dist/assertPsbtUnsignedTxMatches-BoHwgW30.cjs +2 -0
- package/dist/assertPsbtUnsignedTxMatches-BoHwgW30.cjs.map +1 -0
- package/dist/assertPsbtUnsignedTxMatches-D7RxpR4A.js +263 -0
- package/dist/assertPsbtUnsignedTxMatches-D7RxpR4A.js.map +1 -0
- package/dist/{bitcoin-B0S8SHCX.js → bitcoin-B5aNKtsk.js} +77 -60
- package/dist/{bitcoin-B0S8SHCX.js.map → bitcoin-B5aNKtsk.js.map} +1 -1
- package/dist/bitcoin-CHfKAhcI.cjs +2 -0
- package/dist/{bitcoin-B3aqjuMP.cjs.map → bitcoin-CHfKAhcI.cjs.map} +1 -1
- package/dist/{buildAndBroadcastRefund-C2VqXiOx.js → buildAndBroadcastRefund-Ck_ddlLk.js} +333 -328
- package/dist/buildAndBroadcastRefund-Ck_ddlLk.js.map +1 -0
- package/dist/buildAndBroadcastRefund-DyPQyghx.cjs +2 -0
- package/dist/buildAndBroadcastRefund-DyPQyghx.cjs.map +1 -0
- package/dist/{challengeAssert-Yyyj-EdR.cjs → challengeAssert-BKDS_ADt.cjs} +2 -2
- package/dist/{challengeAssert-Yyyj-EdR.cjs.map → challengeAssert-BKDS_ADt.cjs.map} +1 -1
- package/dist/{challengeAssert-BzxQmdZy.js → challengeAssert-BXESW00N.js} +7 -7
- package/dist/{challengeAssert-BzxQmdZy.js.map → challengeAssert-BXESW00N.js.map} +1 -1
- package/dist/fundPeginTransaction-BBE3wTjR.cjs +2 -0
- package/dist/{fundPeginTransaction-DaWoYCgO.cjs.map → fundPeginTransaction-BBE3wTjR.cjs.map} +1 -1
- package/dist/fundPeginTransaction-t-6TsHAY.js +84 -0
- package/dist/{fundPeginTransaction-oV-dNJOU.js.map → fundPeginTransaction-t-6TsHAY.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +174 -166
- package/dist/{noPayout-BXeUw0Qq.cjs → noPayout-B6s8vrW6.cjs} +2 -2
- package/dist/{noPayout-BXeUw0Qq.cjs.map → noPayout-B6s8vrW6.cjs.map} +1 -1
- package/dist/{noPayout-DBX6G96_.js → noPayout-BhgknZBx.js} +2 -2
- package/dist/{noPayout-DBX6G96_.js.map → noPayout-BhgknZBx.js.map} +1 -1
- package/dist/{peginInput-tbw9BpZy.cjs → peginInput-57FK2O99.cjs} +2 -2
- package/dist/{peginInput-tbw9BpZy.cjs.map → peginInput-57FK2O99.cjs.map} +1 -1
- package/dist/{peginInput-C2QPvuhR.js → peginInput-CYJzbuwA.js} +3 -3
- package/dist/{peginInput-C2QPvuhR.js.map → peginInput-CYJzbuwA.js.map} +1 -1
- package/dist/{reservation-fZUvejYK.js → reservation-CB-4FBPk.js} +3 -3
- package/dist/{reservation-fZUvejYK.js.map → reservation-CB-4FBPk.js.map} +1 -1
- package/dist/{reservation-DF0uiCUC.cjs → reservation-hjXStM03.cjs} +2 -2
- package/dist/{reservation-DF0uiCUC.cjs.map → reservation-hjXStM03.cjs.map} +1 -1
- package/dist/tbv/core/clients/index.cjs +1 -1
- package/dist/tbv/core/clients/index.js +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.js +172 -164
- package/dist/tbv/core/managers/PayoutManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/PeginManager.d.ts +7 -8
- package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.d.ts +3 -1
- package/dist/tbv/core/primitives/index.d.ts.map +1 -1
- package/dist/tbv/core/primitives/index.js +31 -27
- package/dist/tbv/core/primitives/psbt/__tests__/assertPsbtUnsignedTxMatches.test.d.ts +5 -0
- package/dist/tbv/core/primitives/psbt/__tests__/assertPsbtUnsignedTxMatches.test.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/assertPsbtUnsignedTxMatches.d.ts +31 -0
- package/dist/tbv/core/primitives/psbt/assertPsbtUnsignedTxMatches.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/index.d.ts +2 -0
- package/dist/tbv/core/primitives/psbt/index.d.ts.map +1 -1
- package/dist/tbv/core/primitives/utils/bitcoin.d.ts +33 -3
- package/dist/tbv/core/primitives/utils/bitcoin.d.ts.map +1 -1
- package/dist/tbv/core/primitives/utils/index.d.ts +1 -1
- package/dist/tbv/core/primitives/utils/index.d.ts.map +1 -1
- package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts.map +1 -1
- package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts.map +1 -1
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +2 -2
- package/dist/tbv/core/services/refund/buildAndBroadcastRefund.d.ts.map +1 -1
- package/dist/tbv/core/utils/fee/__tests__/peginFeeMath.test.d.ts +19 -0
- package/dist/tbv/core/utils/fee/__tests__/peginFeeMath.test.d.ts.map +1 -0
- package/dist/tbv/core/utils/fee/index.d.ts +1 -0
- package/dist/tbv/core/utils/fee/index.d.ts.map +1 -1
- package/dist/tbv/core/utils/fee/peginFeeMath.d.ts +99 -0
- package/dist/tbv/core/utils/fee/peginFeeMath.d.ts.map +1 -0
- package/dist/tbv/core/utils/index.cjs +1 -1
- package/dist/tbv/core/utils/index.js +44 -40
- package/dist/tbv/core/utils/transaction/fundPeginTransaction.d.ts.map +1 -1
- package/dist/tbv/core/utils/utxo/selectUtxos.d.ts.map +1 -1
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +172 -164
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/{vault-registry-reader-Br9m8bHF.cjs → vault-registry-reader-7gOYnrQD.cjs} +2 -2
- package/dist/{vault-registry-reader-Br9m8bHF.cjs.map → vault-registry-reader-7gOYnrQD.cjs.map} +1 -1
- package/dist/{vault-registry-reader-CohvzvoH.js → vault-registry-reader-Blhu9FW2.js} +2 -2
- package/dist/{vault-registry-reader-CohvzvoH.js.map → vault-registry-reader-Blhu9FW2.js.map} +1 -1
- package/dist/waitForTransactionReceiptSmartAware-CmgFXFza.js +265 -0
- package/dist/waitForTransactionReceiptSmartAware-CmgFXFza.js.map +1 -0
- package/dist/waitForTransactionReceiptSmartAware-tv1mtSIY.cjs +2 -0
- package/dist/waitForTransactionReceiptSmartAware-tv1mtSIY.cjs.map +1 -0
- package/package.json +1 -1
- package/dist/PayoutManager-BhJoQZsG.cjs +0 -2
- package/dist/PayoutManager-BhJoQZsG.cjs.map +0 -1
- package/dist/PayoutManager-s_uH8Uuj.js.map +0 -1
- package/dist/PeginManager-BPXVXu8t.cjs +0 -2
- package/dist/PeginManager-BPXVXu8t.cjs.map +0 -1
- package/dist/PeginManager-CB-dVkT2.js.map +0 -1
- package/dist/bitcoin-B3aqjuMP.cjs +0 -2
- package/dist/buildAndBroadcastRefund-C2VqXiOx.js.map +0 -1
- package/dist/buildAndBroadcastRefund-CBIfcF47.cjs +0 -2
- package/dist/buildAndBroadcastRefund-CBIfcF47.cjs.map +0 -1
- package/dist/fundPeginTransaction-DaWoYCgO.cjs +0 -2
- package/dist/fundPeginTransaction-oV-dNJOU.js +0 -76
- package/dist/payout-BNFMBXS6.js +0 -193
- package/dist/payout-BNFMBXS6.js.map +0 -1
- package/dist/payout-DQ_fmJUA.cjs +0 -2
- package/dist/payout-DQ_fmJUA.cjs.map +0 -1
- package/dist/waitForTransactionReceiptSmartAware-Cj_DKm0G.js +0 -217
- package/dist/waitForTransactionReceiptSmartAware-Cj_DKm0G.js.map +0 -1
- package/dist/waitForTransactionReceiptSmartAware-D9ykVriz.cjs +0 -2
- package/dist/waitForTransactionReceiptSmartAware-D9ykVriz.cjs.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PeginManager-BbHPyz-G.cjs","sources":["../../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/_u64.js","../src/tbv/core/managers/pegin/assertAuthAnchorOpReturn.ts","../src/tbv/core/vault-secrets/context.ts","../src/tbv/core/vault-secrets/deriveVaultRoot.ts","../../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/legacy.js","../../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/sha3.js","../src/tbv/core/wots/blockDerivation.ts","../src/tbv/core/managers/pegin/expandPerVaultSecrets.ts","../src/tbv/core/managers/pegin/normalizeWalletInputs.ts","../src/tbv/core/managers/pegin/signPsbtsWithFallback.ts","../src/tbv/core/managers/PeginManager.ts"],"sourcesContent":["/**\n * Internal helpers for u64. BigUint64Array is too slow as per 2025, so we implement it using Uint32Array.\n * @todo re-check https://issues.chromium.org/issues/42212588\n * @module\n */\nconst U32_MASK64 = /* @__PURE__ */ BigInt(2 ** 32 - 1);\nconst _32n = /* @__PURE__ */ BigInt(32);\nfunction fromBig(n, le = false) {\n if (le)\n return { h: Number(n & U32_MASK64), l: Number((n >> _32n) & U32_MASK64) };\n return { h: Number((n >> _32n) & U32_MASK64) | 0, l: Number(n & U32_MASK64) | 0 };\n}\nfunction split(lst, le = false) {\n const len = lst.length;\n let Ah = new Uint32Array(len);\n let Al = new Uint32Array(len);\n for (let i = 0; i < len; i++) {\n const { h, l } = fromBig(lst[i], le);\n [Ah[i], Al[i]] = [h, l];\n }\n return [Ah, Al];\n}\nconst toBig = (h, l) => (BigInt(h >>> 0) << _32n) | BigInt(l >>> 0);\n// for Shift in [0, 32)\nconst shrSH = (h, _l, s) => h >>> s;\nconst shrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in [1, 32)\nconst rotrSH = (h, l, s) => (h >>> s) | (l << (32 - s));\nconst rotrSL = (h, l, s) => (h << (32 - s)) | (l >>> s);\n// Right rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotrBH = (h, l, s) => (h << (64 - s)) | (l >>> (s - 32));\nconst rotrBL = (h, l, s) => (h >>> (s - 32)) | (l << (64 - s));\n// Right rotate for shift===32 (just swaps l&h)\nconst rotr32H = (_h, l) => l;\nconst rotr32L = (h, _l) => h;\n// Left rotate for Shift in [1, 32)\nconst rotlSH = (h, l, s) => (h << s) | (l >>> (32 - s));\nconst rotlSL = (h, l, s) => (l << s) | (h >>> (32 - s));\n// Left rotate for Shift in (32, 64), NOTE: 32 is special case.\nconst rotlBH = (h, l, s) => (l << (s - 32)) | (h >>> (64 - s));\nconst rotlBL = (h, l, s) => (h << (s - 32)) | (l >>> (64 - s));\n// JS uses 32-bit signed integers for bitwise operations which means we cannot\n// simple take carry out of low bit sum by shift, we need to use division.\nfunction add(Ah, Al, Bh, Bl) {\n const l = (Al >>> 0) + (Bl >>> 0);\n return { h: (Ah + Bh + ((l / 2 ** 32) | 0)) | 0, l: l | 0 };\n}\n// Addition with more than 2 elements\nconst add3L = (Al, Bl, Cl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0);\nconst add3H = (low, Ah, Bh, Ch) => (Ah + Bh + Ch + ((low / 2 ** 32) | 0)) | 0;\nconst add4L = (Al, Bl, Cl, Dl) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0);\nconst add4H = (low, Ah, Bh, Ch, Dh) => (Ah + Bh + Ch + Dh + ((low / 2 ** 32) | 0)) | 0;\nconst add5L = (Al, Bl, Cl, Dl, El) => (Al >>> 0) + (Bl >>> 0) + (Cl >>> 0) + (Dl >>> 0) + (El >>> 0);\nconst add5H = (low, Ah, Bh, Ch, Dh, Eh) => (Ah + Bh + Ch + Dh + Eh + ((low / 2 ** 32) | 0)) | 0;\n// prettier-ignore\nexport { add, add3H, add3L, add4H, add4L, add5H, add5L, fromBig, rotlBH, rotlBL, rotlSH, rotlSL, rotr32H, rotr32L, rotrBH, rotrBL, rotrSH, rotrSL, shrSH, shrSL, split, toBig };\n// prettier-ignore\nconst u64 = {\n fromBig, split, toBig,\n shrSH, shrSL,\n rotrSH, rotrSL, rotrBH, rotrBL,\n rotr32H, rotr32L,\n rotlSH, rotlSL, rotlBH, rotlBL,\n add, add3L, add3H, add4L, add4H, add5H, add5L,\n};\nexport default u64;\n//# sourceMappingURL=_u64.js.map","/**\n * Structural verifier for the auth-anchor OP_RETURN in a funded\n * Pre-PegIn transaction.\n *\n * @module managers/pegin/assertAuthAnchorOpReturn\n */\n\nimport * as bitcoin from \"bitcoinjs-lib\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\n\n/** OP_RETURN opcode. */\nconst OP_RETURN = 0x6a;\n/** Push-32-bytes opcode (raw push, not OP_PUSHDATA1). */\nconst OP_PUSH32 = 0x20;\n/** Encoded length of a standard OP_RETURN script with a 32-byte payload. */\nconst OP_RETURN_PUSH32_SCRIPT_LEN = 1 + 1 + 32;\n\n/**\n * Verify the broadcast Pre-PegIn carries the expected OP_RETURN\n * commitment to the auth anchor.\n *\n * The OP_RETURN sits at `vout = vaultCount` (right after the per-vault\n * HTLC outputs and before the depositor-claim/change outputs) and\n * pushes the 32-byte `SHA256(authAnchor)`. The script encoding is\n * exactly `OP_RETURN || PUSH32 || <32 bytes>` (34 bytes). A\n * non-conformant WASM build that omitted the OP_RETURN, swapped its\n * position, or changed its push payload would let the depositor\n * obtain a valid bearer token for a Pre-PegIn whose on-chain\n * commitment doesn't actually bind the anchor — degrading the auth\n * from on-chain-bound to a shared secret. Fail closed.\n *\n * @throws If the OP_RETURN is missing, mis-located, mis-encoded, or\n * pushes a payload other than `expectedAuthAnchorHashHex`.\n */\nexport function assertAuthAnchorOpReturn(\n fundedPrePeginTxHex: string,\n vaultCount: number,\n expectedAuthAnchorHashHex: string,\n): void {\n const cleanHex = stripHexPrefix(fundedPrePeginTxHex);\n const tx = bitcoin.Transaction.fromHex(cleanHex);\n\n if (tx.outs.length <= vaultCount) {\n throw new Error(\n `Pre-PegIn auth-anchor OP_RETURN missing: tx has ${tx.outs.length} ` +\n `outputs, expected at least ${vaultCount + 1} (vault outputs + OP_RETURN)`,\n );\n }\n\n const opReturnOutput = tx.outs[vaultCount];\n const script = opReturnOutput.script;\n if (\n script.length !== OP_RETURN_PUSH32_SCRIPT_LEN ||\n script[0] !== OP_RETURN ||\n script[1] !== OP_PUSH32\n ) {\n throw new Error(\n `Pre-PegIn auth-anchor OP_RETURN at vout ${vaultCount} has unexpected ` +\n `script encoding (got ${script.length}-byte script with prefix ` +\n `0x${script.slice(0, Math.min(2, script.length)).toString(\"hex\")}; ` +\n `expected ${OP_RETURN_PUSH32_SCRIPT_LEN}-byte OP_RETURN + PUSH32 layout)`,\n );\n }\n\n const pushedHex = script.slice(2).toString(\"hex\").toLowerCase();\n if (pushedHex !== expectedAuthAnchorHashHex.toLowerCase()) {\n throw new Error(\n `Pre-PegIn auth-anchor OP_RETURN payload mismatch at vout ${vaultCount}: ` +\n `tx pushes ${pushedHex}, expected ${expectedAuthAnchorHashHex}`,\n );\n }\n\n if (opReturnOutput.value !== 0) {\n throw new Error(\n `Pre-PegIn auth-anchor OP_RETURN at vout ${vaultCount} has non-zero ` +\n `value ${opReturnOutput.value}; OP_RETURN outputs must be 0-value`,\n );\n }\n}\n","/**\n * Canonical `vaultContext` byte encoding per\n * `derive-vault-secrets.md` §2.3.\n *\n * ```\n * vaultContext :=\n * I2OSP(32, 4) || depositorBtcPubkey // 32B x-only\n * || I2OSP(32, 4) || fundingOutpointsCommitment // 32B SHA-256\n * ```\n *\n * `fundingOutpointsCommitment` is SHA-256 over the canonically-sorted\n * funding outpoints of the Pre-PegIn transaction, serialized as\n * `txid (32B display/RPC order) || vout (4B u32 big-endian)` per\n * outpoint. Sorting by 36-byte lex order makes the commitment\n * invariant under tx-level input reordering, so same-inputs RBF and\n * reorg rebroadcasts yield the same context.\n *\n * @module vault-secrets/context\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\nconst DEPOSITOR_PUBKEY_SIZE = 32;\nconst TXID_SIZE = 32;\nconst OUTPOINT_SIZE = 36;\nconst COMMITMENT_SIZE = 32;\nconst FIELD_LEN_PREFIX_SIZE = 4;\nconst VAULT_CONTEXT_SIZE =\n FIELD_LEN_PREFIX_SIZE +\n DEPOSITOR_PUBKEY_SIZE +\n FIELD_LEN_PREFIX_SIZE +\n COMMITMENT_SIZE;\n\nexport interface FundingOutpoint {\n /**\n * Bitcoin txid in **display / RPC order** (byte-reversed from the\n * internal little-endian wire form used when hashing a raw tx).\n */\n txid: Uint8Array;\n /** Output index within the referenced transaction (u32). */\n vout: number;\n}\n\nexport interface VaultContextInput {\n /** Depositor's x-only BTC public key (32 bytes). */\n depositorBtcPubkey: Uint8Array;\n /** Funding outpoints of the Pre-PegIn transaction. MUST be non-empty. */\n fundingOutpoints: readonly FundingOutpoint[];\n}\n\nfunction writeUint32BE(out: Uint8Array, offset: number, value: number): void {\n out[offset] = (value >>> 24) & 0xff;\n out[offset + 1] = (value >>> 16) & 0xff;\n out[offset + 2] = (value >>> 8) & 0xff;\n out[offset + 3] = value & 0xff;\n}\n\nfunction serializeOutpoint(outpoint: FundingOutpoint): Uint8Array {\n if (outpoint.txid.length !== TXID_SIZE) {\n throw new Error(\n `outpoint.txid must be exactly ${TXID_SIZE} bytes, got ${outpoint.txid.length}`,\n );\n }\n if (\n !Number.isInteger(outpoint.vout) ||\n outpoint.vout < 0 ||\n outpoint.vout > 0xffffffff\n ) {\n throw new Error(`outpoint.vout must be a u32, got ${outpoint.vout}`);\n }\n const out = new Uint8Array(OUTPOINT_SIZE);\n out.set(outpoint.txid, 0);\n writeUint32BE(out, TXID_SIZE, outpoint.vout);\n return out;\n}\n\nfunction compareBytes(a: Uint8Array, b: Uint8Array): number {\n const len = Math.min(a.length, b.length);\n for (let i = 0; i < len; i++) {\n if (a[i] !== b[i]) return a[i] - b[i];\n }\n return a.length - b.length;\n}\n\n/**\n * Compute SHA-256 over canonically-sorted funding outpoints.\n *\n * Outpoints are serialized as 36-byte `txid || vout_BE`, sorted\n * ascending lexicographically, concatenated, then hashed.\n *\n * @stability frozen — on-chain-binding. Any change to layout, sort\n * order, or serialization is a hard fork; existing deposits would no\n * longer match their committed `depositorWotsPkHash`.\n *\n * @throws If `outpoints` is empty or contains duplicates.\n */\nexport function buildFundingOutpointsCommitment(\n outpoints: readonly FundingOutpoint[],\n): Uint8Array {\n if (outpoints.length === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: outpoints must be non-empty\",\n );\n }\n const serialized = outpoints.map(serializeOutpoint);\n serialized.sort(compareBytes);\n\n for (let i = 1; i < serialized.length; i++) {\n if (compareBytes(serialized[i - 1], serialized[i]) === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: duplicate outpoint detected\",\n );\n }\n }\n\n const flat = new Uint8Array(serialized.length * OUTPOINT_SIZE);\n for (let i = 0; i < serialized.length; i++) {\n flat.set(serialized[i], i * OUTPOINT_SIZE);\n }\n return sha256(flat);\n}\n\n/**\n * Build the canonical `vaultContext` byte string fed into the wallet's\n * `deriveContextHash` (or a locally-implemented equivalent on the\n * app side).\n *\n * Output length is always 72 bytes.\n *\n * @stability frozen — on-chain-binding. The 72-byte layout is the\n * input to `deriveContextHash`; any change rotates the vault root and\n * therefore every WOTS key, hashlock secret, and auth anchor derived\n * from it. Existing deposits cannot be recovered after a layout change.\n */\nexport function buildVaultContext(input: VaultContextInput): Uint8Array {\n if (input.depositorBtcPubkey.length !== DEPOSITOR_PUBKEY_SIZE) {\n throw new Error(\n `vaultContext: depositorBtcPubkey must be exactly ${DEPOSITOR_PUBKEY_SIZE} bytes, got ${input.depositorBtcPubkey.length}`,\n );\n }\n const commitment = buildFundingOutpointsCommitment(input.fundingOutpoints);\n\n const out = new Uint8Array(VAULT_CONTEXT_SIZE);\n let offset = 0;\n\n writeUint32BE(out, offset, DEPOSITOR_PUBKEY_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(input.depositorBtcPubkey, offset);\n offset += DEPOSITOR_PUBKEY_SIZE;\n\n writeUint32BE(out, offset, COMMITMENT_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(commitment, offset);\n\n return out;\n}\n","/**\n * Vault-root derivation via the wallet's `deriveContextHash` API.\n *\n * Implements the canonical root source from `derive-vault-secrets.md`\n * §2.2:\n *\n * ```\n * rootDerivation = deriveContextHash(\"babylon-btc-vault\", hex(vaultContext))\n * ```\n *\n * The 32-byte output is fed directly into the {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, and {@link expandWotsSeed} functions in\n * this module.\n *\n * @module vault-secrets/deriveVaultRoot\n */\n\nimport { hexToUint8Array, uint8ArrayToHex } from \"../primitives/utils/bitcoin\";\n\nimport { buildVaultContext, type VaultContextInput } from \"./context\";\n\n/**\n * The fixed `appName` passed to the wallet's `deriveContextHash` for\n * Babylon vault derivations. The wallet displays this in its approval\n * dialog. Defined by `derive-vault-secrets.md` §2.2 — must not be\n * changed without coordinating a spec revision and a downstream\n * migration plan, as it provides app-level domain separation across\n * applications using the same wallet.\n */\nexport const VAULT_APP_NAME = \"babylon-btc-vault\";\n\n/** Expected length of the wallet output in bytes per spec §2.1. */\nconst ROOT_OUTPUT_BYTES = 32;\n\n/** Expected length of the wallet output in lowercase hex chars. */\nconst ROOT_OUTPUT_HEX_LEN = ROOT_OUTPUT_BYTES * 2;\n\nconst LOWERCASE_HEX_RE = /^[0-9a-f]+$/;\n\n/**\n * Minimal structural shape for the wallet capability needed by this\n * helper. Typed against the method directly so callers can pass any\n * value that implements `deriveContextHash` — `BitcoinWallet` from\n * this SDK, `IBTCProvider` from `@babylonlabs-io/wallet-connector`,\n * or a test mock — without depending on the rest of either interface.\n */\nexport interface DeriveContextHashCapableWallet {\n deriveContextHash(appName: string, context: string): Promise<string>;\n}\n\n/**\n * Derive the 32-byte vault root from a wallet by encoding the\n * canonical {@link VaultContextInput} and forwarding to\n * `wallet.deriveContextHash`.\n *\n * Validates the wallet's output strictly: must be exactly 64\n * lowercase hex characters per `derive-context-hash.md` §2.1. A\n * conformant wallet always satisfies this, but we re-check at the\n * SDK boundary so a non-conformant wallet (or a wallet returning a\n * malformed value through a buggy adapter) fails loud here rather\n * than producing silently-wrong derived secrets downstream.\n *\n * The helper itself produces only valid spec inputs (`appName` is\n * the hardcoded `VAULT_APP_NAME`; `context` is hex of the 72-byte\n * `vaultContext`, always 144 chars lowercase), so input-side\n * validation is unnecessary.\n *\n * @param wallet - Any value implementing `deriveContextHash`.\n * @param input - The canonical {@link VaultContextInput} that\n * uniquely identifies the vault. Encoded by\n * {@link buildVaultContext} into a 72-byte structure\n * before being hex-encoded for the wallet.\n * @stability frozen — on-chain-binding. The pair (`VAULT_APP_NAME`,\n * `vaultContext` encoding) is the wallet's input space; changing\n * either rotates the root and invalidates every secret derived from\n * it. `VAULT_APP_NAME` is fixed by `derive-vault-secrets.md` §2.2\n * and must never change without a coordinated spec revision.\n *\n * @returns 32-byte root suitable for {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, {@link expandWotsSeed}.\n * @throws If the wallet returns a non-64-char or non-lowercase-hex\n * string. Errors from the wallet (user rejection,\n * method-not-supported, etc.) propagate unchanged.\n */\nexport async function deriveVaultRoot(\n wallet: DeriveContextHashCapableWallet,\n input: VaultContextInput,\n): Promise<Uint8Array> {\n const vaultContext = buildVaultContext(input);\n const contextHex = uint8ArrayToHex(vaultContext);\n\n const rootHex = await wallet.deriveContextHash(VAULT_APP_NAME, contextHex);\n\n if (typeof rootHex !== \"string\") {\n throw new Error(\n `deriveVaultRoot: wallet must return a string, got ${typeof rootHex}`,\n );\n }\n if (rootHex.length !== ROOT_OUTPUT_HEX_LEN) {\n throw new Error(\n `deriveVaultRoot: wallet must return a ${ROOT_OUTPUT_HEX_LEN}-character hex string (${ROOT_OUTPUT_BYTES} bytes), got length ${rootHex.length}`,\n );\n }\n if (!LOWERCASE_HEX_RE.test(rootHex)) {\n throw new Error(\n \"deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters\",\n );\n }\n\n return hexToUint8Array(rootHex);\n}\n","/**\n\nSHA1 (RFC 3174), MD5 (RFC 1321) and RIPEMD160 (RFC 2286) legacy, weak hash functions.\nDon't use them in a new protocol. What \"weak\" means:\n\n- Collisions can be made with 2^18 effort in MD5, 2^60 in SHA1, 2^80 in RIPEMD160.\n- No practical pre-image attacks (only theoretical, 2^123.4)\n- HMAC seems kinda ok: https://www.rfc-editor.org/rfc/rfc6151\n * @module\n */\nimport { Chi, HashMD, Maj } from \"./_md.js\";\nimport { clean, createHasher, rotl } from \"./utils.js\";\n/** Initial SHA1 state */\nconst SHA1_IV = /* @__PURE__ */ Uint32Array.from([\n 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0,\n]);\n// Reusable temporary buffer\nconst SHA1_W = /* @__PURE__ */ new Uint32Array(80);\n/** Internal SHA1 legacy hash class. */\nexport class _SHA1 extends HashMD {\n A = SHA1_IV[0] | 0;\n B = SHA1_IV[1] | 0;\n C = SHA1_IV[2] | 0;\n D = SHA1_IV[3] | 0;\n E = SHA1_IV[4] | 0;\n constructor() {\n super(64, 20, 8, false);\n }\n get() {\n const { A, B, C, D, E } = this;\n return [A, B, C, D, E];\n }\n set(A, B, C, D, E) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n this.E = E | 0;\n }\n process(view, offset) {\n for (let i = 0; i < 16; i++, offset += 4)\n SHA1_W[i] = view.getUint32(offset, false);\n for (let i = 16; i < 80; i++)\n SHA1_W[i] = rotl(SHA1_W[i - 3] ^ SHA1_W[i - 8] ^ SHA1_W[i - 14] ^ SHA1_W[i - 16], 1);\n // Compression function main loop, 80 rounds\n let { A, B, C, D, E } = this;\n for (let i = 0; i < 80; i++) {\n let F, K;\n if (i < 20) {\n F = Chi(B, C, D);\n K = 0x5a827999;\n }\n else if (i < 40) {\n F = B ^ C ^ D;\n K = 0x6ed9eba1;\n }\n else if (i < 60) {\n F = Maj(B, C, D);\n K = 0x8f1bbcdc;\n }\n else {\n F = B ^ C ^ D;\n K = 0xca62c1d6;\n }\n const T = (rotl(A, 5) + F + E + K + SHA1_W[i]) | 0;\n E = D;\n D = C;\n C = rotl(B, 30);\n B = A;\n A = T;\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n E = (E + this.E) | 0;\n this.set(A, B, C, D, E);\n }\n roundClean() {\n clean(SHA1_W);\n }\n destroy() {\n this.set(0, 0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n/** SHA1 (RFC 3174) legacy hash function. It was cryptographically broken. */\nexport const sha1 = /* @__PURE__ */ createHasher(() => new _SHA1());\n/** Per-round constants */\nconst p32 = /* @__PURE__ */ Math.pow(2, 32);\nconst K = /* @__PURE__ */ Array.from({ length: 64 }, (_, i) => Math.floor(p32 * Math.abs(Math.sin(i + 1))));\n/** md5 initial state: same as sha1, but 4 u32 instead of 5. */\nconst MD5_IV = /* @__PURE__ */ SHA1_IV.slice(0, 4);\n// Reusable temporary buffer\nconst MD5_W = /* @__PURE__ */ new Uint32Array(16);\n/** Internal MD5 legacy hash class. */\nexport class _MD5 extends HashMD {\n A = MD5_IV[0] | 0;\n B = MD5_IV[1] | 0;\n C = MD5_IV[2] | 0;\n D = MD5_IV[3] | 0;\n constructor() {\n super(64, 16, 8, true);\n }\n get() {\n const { A, B, C, D } = this;\n return [A, B, C, D];\n }\n set(A, B, C, D) {\n this.A = A | 0;\n this.B = B | 0;\n this.C = C | 0;\n this.D = D | 0;\n }\n process(view, offset) {\n for (let i = 0; i < 16; i++, offset += 4)\n MD5_W[i] = view.getUint32(offset, true);\n // Compression function main loop, 64 rounds\n let { A, B, C, D } = this;\n for (let i = 0; i < 64; i++) {\n let F, g, s;\n if (i < 16) {\n F = Chi(B, C, D);\n g = i;\n s = [7, 12, 17, 22];\n }\n else if (i < 32) {\n F = Chi(D, B, C);\n g = (5 * i + 1) % 16;\n s = [5, 9, 14, 20];\n }\n else if (i < 48) {\n F = B ^ C ^ D;\n g = (3 * i + 5) % 16;\n s = [4, 11, 16, 23];\n }\n else {\n F = C ^ (B | ~D);\n g = (7 * i) % 16;\n s = [6, 10, 15, 21];\n }\n F = F + A + K[i] + MD5_W[g];\n A = D;\n D = C;\n C = B;\n B = B + rotl(F, s[i % 4]);\n }\n // Add the compressed chunk to the current hash value\n A = (A + this.A) | 0;\n B = (B + this.B) | 0;\n C = (C + this.C) | 0;\n D = (D + this.D) | 0;\n this.set(A, B, C, D);\n }\n roundClean() {\n clean(MD5_W);\n }\n destroy() {\n this.set(0, 0, 0, 0);\n clean(this.buffer);\n }\n}\n/**\n * MD5 (RFC 1321) legacy hash function. It was cryptographically broken.\n * MD5 architecture is similar to SHA1, with some differences:\n * - Reduced output length: 16 bytes (128 bit) instead of 20\n * - 64 rounds, instead of 80\n * - Little-endian: could be faster, but will require more code\n * - Non-linear index selection: huge speed-up for unroll\n * - Per round constants: more memory accesses, additional speed-up for unroll\n */\nexport const md5 = /* @__PURE__ */ createHasher(() => new _MD5());\n// RIPEMD-160\nconst Rho160 = /* @__PURE__ */ Uint8Array.from([\n 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,\n]);\nconst Id160 = /* @__PURE__ */ (() => Uint8Array.from(new Array(16).fill(0).map((_, i) => i)))();\nconst Pi160 = /* @__PURE__ */ (() => Id160.map((i) => (9 * i + 5) % 16))();\nconst idxLR = /* @__PURE__ */ (() => {\n const L = [Id160];\n const R = [Pi160];\n const res = [L, R];\n for (let i = 0; i < 4; i++)\n for (let j of res)\n j.push(j[i].map((k) => Rho160[k]));\n return res;\n})();\nconst idxL = /* @__PURE__ */ (() => idxLR[0])();\nconst idxR = /* @__PURE__ */ (() => idxLR[1])();\n// const [idxL, idxR] = idxLR;\nconst shifts160 = /* @__PURE__ */ [\n [11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],\n [12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],\n [13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],\n [14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],\n [15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5],\n].map((i) => Uint8Array.from(i));\nconst shiftsL160 = /* @__PURE__ */ idxL.map((idx, i) => idx.map((j) => shifts160[i][j]));\nconst shiftsR160 = /* @__PURE__ */ idxR.map((idx, i) => idx.map((j) => shifts160[i][j]));\nconst Kl160 = /* @__PURE__ */ Uint32Array.from([\n 0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e,\n]);\nconst Kr160 = /* @__PURE__ */ Uint32Array.from([\n 0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000,\n]);\n// It's called f() in spec.\nfunction ripemd_f(group, x, y, z) {\n if (group === 0)\n return x ^ y ^ z;\n if (group === 1)\n return (x & y) | (~x & z);\n if (group === 2)\n return (x | ~y) ^ z;\n if (group === 3)\n return (x & z) | (y & ~z);\n return x ^ (y | ~z);\n}\n// Reusable temporary buffer\nconst BUF_160 = /* @__PURE__ */ new Uint32Array(16);\nexport class _RIPEMD160 extends HashMD {\n h0 = 0x67452301 | 0;\n h1 = 0xefcdab89 | 0;\n h2 = 0x98badcfe | 0;\n h3 = 0x10325476 | 0;\n h4 = 0xc3d2e1f0 | 0;\n constructor() {\n super(64, 20, 8, true);\n }\n get() {\n const { h0, h1, h2, h3, h4 } = this;\n return [h0, h1, h2, h3, h4];\n }\n set(h0, h1, h2, h3, h4) {\n this.h0 = h0 | 0;\n this.h1 = h1 | 0;\n this.h2 = h2 | 0;\n this.h3 = h3 | 0;\n this.h4 = h4 | 0;\n }\n process(view, offset) {\n for (let i = 0; i < 16; i++, offset += 4)\n BUF_160[i] = view.getUint32(offset, true);\n // prettier-ignore\n let al = this.h0 | 0, ar = al, bl = this.h1 | 0, br = bl, cl = this.h2 | 0, cr = cl, dl = this.h3 | 0, dr = dl, el = this.h4 | 0, er = el;\n // Instead of iterating 0 to 80, we split it into 5 groups\n // And use the groups in constants, functions, etc. Much simpler\n for (let group = 0; group < 5; group++) {\n const rGroup = 4 - group;\n const hbl = Kl160[group], hbr = Kr160[group]; // prettier-ignore\n const rl = idxL[group], rr = idxR[group]; // prettier-ignore\n const sl = shiftsL160[group], sr = shiftsR160[group]; // prettier-ignore\n for (let i = 0; i < 16; i++) {\n const tl = (rotl(al + ripemd_f(group, bl, cl, dl) + BUF_160[rl[i]] + hbl, sl[i]) + el) | 0;\n al = el, el = dl, dl = rotl(cl, 10) | 0, cl = bl, bl = tl; // prettier-ignore\n }\n // 2 loops are 10% faster\n for (let i = 0; i < 16; i++) {\n const tr = (rotl(ar + ripemd_f(rGroup, br, cr, dr) + BUF_160[rr[i]] + hbr, sr[i]) + er) | 0;\n ar = er, er = dr, dr = rotl(cr, 10) | 0, cr = br, br = tr; // prettier-ignore\n }\n }\n // Add the compressed chunk to the current hash value\n this.set((this.h1 + cl + dr) | 0, (this.h2 + dl + er) | 0, (this.h3 + el + ar) | 0, (this.h4 + al + br) | 0, (this.h0 + bl + cr) | 0);\n }\n roundClean() {\n clean(BUF_160);\n }\n destroy() {\n this.destroyed = true;\n clean(this.buffer);\n this.set(0, 0, 0, 0, 0);\n }\n}\n/**\n * RIPEMD-160 - a legacy hash function from 1990s.\n * * https://homes.esat.kuleuven.be/~bosselae/ripemd160.html\n * * https://homes.esat.kuleuven.be/~bosselae/ripemd160/pdf/AB-9601/AB-9601.pdf\n */\nexport const ripemd160 = /* @__PURE__ */ createHasher(() => new _RIPEMD160());\n//# sourceMappingURL=legacy.js.map","/**\n * SHA3 (keccak) hash function, based on a new \"Sponge function\" design.\n * Different from older hashes, the internal state is bigger than output size.\n *\n * Check out [FIPS-202](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf),\n * [Website](https://keccak.team/keccak.html),\n * [the differences between SHA-3 and Keccak](https://crypto.stackexchange.com/questions/15727/what-are-the-key-differences-between-the-draft-sha-3-standard-and-the-keccak-sub).\n *\n * Check out `sha3-addons` module for cSHAKE, k12, and others.\n * @module\n */\nimport { rotlBH, rotlBL, rotlSH, rotlSL, split } from \"./_u64.js\";\n// prettier-ignore\nimport { abytes, aexists, anumber, aoutput, clean, createHasher, oidNist, swap32IfBE, u32 } from \"./utils.js\";\n// No __PURE__ annotations in sha3 header:\n// EVERYTHING is in fact used on every export.\n// Various per round constants calculations\nconst _0n = BigInt(0);\nconst _1n = BigInt(1);\nconst _2n = BigInt(2);\nconst _7n = BigInt(7);\nconst _256n = BigInt(256);\nconst _0x71n = BigInt(0x71);\nconst SHA3_PI = [];\nconst SHA3_ROTL = [];\nconst _SHA3_IOTA = []; // no pure annotation: var is always used\nfor (let round = 0, R = _1n, x = 1, y = 0; round < 24; round++) {\n // Pi\n [x, y] = [y, (2 * x + 3 * y) % 5];\n SHA3_PI.push(2 * (5 * y + x));\n // Rotational\n SHA3_ROTL.push((((round + 1) * (round + 2)) / 2) % 64);\n // Iota\n let t = _0n;\n for (let j = 0; j < 7; j++) {\n R = ((R << _1n) ^ ((R >> _7n) * _0x71n)) % _256n;\n if (R & _2n)\n t ^= _1n << ((_1n << BigInt(j)) - _1n);\n }\n _SHA3_IOTA.push(t);\n}\nconst IOTAS = split(_SHA3_IOTA, true);\nconst SHA3_IOTA_H = IOTAS[0];\nconst SHA3_IOTA_L = IOTAS[1];\n// Left rotation (without 0, 32, 64)\nconst rotlH = (h, l, s) => (s > 32 ? rotlBH(h, l, s) : rotlSH(h, l, s));\nconst rotlL = (h, l, s) => (s > 32 ? rotlBL(h, l, s) : rotlSL(h, l, s));\n/** `keccakf1600` internal function, additionally allows to adjust round count. */\nexport function keccakP(s, rounds = 24) {\n const B = new Uint32Array(5 * 2);\n // NOTE: all indices are x2 since we store state as u32 instead of u64 (bigints to slow in js)\n for (let round = 24 - rounds; round < 24; round++) {\n // Theta θ\n for (let x = 0; x < 10; x++)\n B[x] = s[x] ^ s[x + 10] ^ s[x + 20] ^ s[x + 30] ^ s[x + 40];\n for (let x = 0; x < 10; x += 2) {\n const idx1 = (x + 8) % 10;\n const idx0 = (x + 2) % 10;\n const B0 = B[idx0];\n const B1 = B[idx0 + 1];\n const Th = rotlH(B0, B1, 1) ^ B[idx1];\n const Tl = rotlL(B0, B1, 1) ^ B[idx1 + 1];\n for (let y = 0; y < 50; y += 10) {\n s[x + y] ^= Th;\n s[x + y + 1] ^= Tl;\n }\n }\n // Rho (ρ) and Pi (π)\n let curH = s[2];\n let curL = s[3];\n for (let t = 0; t < 24; t++) {\n const shift = SHA3_ROTL[t];\n const Th = rotlH(curH, curL, shift);\n const Tl = rotlL(curH, curL, shift);\n const PI = SHA3_PI[t];\n curH = s[PI];\n curL = s[PI + 1];\n s[PI] = Th;\n s[PI + 1] = Tl;\n }\n // Chi (χ)\n for (let y = 0; y < 50; y += 10) {\n for (let x = 0; x < 10; x++)\n B[x] = s[y + x];\n for (let x = 0; x < 10; x++)\n s[y + x] ^= ~B[(x + 2) % 10] & B[(x + 4) % 10];\n }\n // Iota (ι)\n s[0] ^= SHA3_IOTA_H[round];\n s[1] ^= SHA3_IOTA_L[round];\n }\n clean(B);\n}\n/** Keccak sponge function. */\nexport class Keccak {\n state;\n pos = 0;\n posOut = 0;\n finished = false;\n state32;\n destroyed = false;\n blockLen;\n suffix;\n outputLen;\n enableXOF = false;\n rounds;\n // NOTE: we accept arguments in bytes instead of bits here.\n constructor(blockLen, suffix, outputLen, enableXOF = false, rounds = 24) {\n this.blockLen = blockLen;\n this.suffix = suffix;\n this.outputLen = outputLen;\n this.enableXOF = enableXOF;\n this.rounds = rounds;\n // Can be passed from user as dkLen\n anumber(outputLen, 'outputLen');\n // 1600 = 5x5 matrix of 64bit. 1600 bits === 200 bytes\n // 0 < blockLen < 200\n if (!(0 < blockLen && blockLen < 200))\n throw new Error('only keccak-f1600 function is supported');\n this.state = new Uint8Array(200);\n this.state32 = u32(this.state);\n }\n clone() {\n return this._cloneInto();\n }\n keccak() {\n swap32IfBE(this.state32);\n keccakP(this.state32, this.rounds);\n swap32IfBE(this.state32);\n this.posOut = 0;\n this.pos = 0;\n }\n update(data) {\n aexists(this);\n abytes(data);\n const { blockLen, state } = this;\n const len = data.length;\n for (let pos = 0; pos < len;) {\n const take = Math.min(blockLen - this.pos, len - pos);\n for (let i = 0; i < take; i++)\n state[this.pos++] ^= data[pos++];\n if (this.pos === blockLen)\n this.keccak();\n }\n return this;\n }\n finish() {\n if (this.finished)\n return;\n this.finished = true;\n const { state, suffix, pos, blockLen } = this;\n // Do the padding\n state[pos] ^= suffix;\n if ((suffix & 0x80) !== 0 && pos === blockLen - 1)\n this.keccak();\n state[blockLen - 1] ^= 0x80;\n this.keccak();\n }\n writeInto(out) {\n aexists(this, false);\n abytes(out);\n this.finish();\n const bufferOut = this.state;\n const { blockLen } = this;\n for (let pos = 0, len = out.length; pos < len;) {\n if (this.posOut >= blockLen)\n this.keccak();\n const take = Math.min(blockLen - this.posOut, len - pos);\n out.set(bufferOut.subarray(this.posOut, this.posOut + take), pos);\n this.posOut += take;\n pos += take;\n }\n return out;\n }\n xofInto(out) {\n // Sha3/Keccak usage with XOF is probably mistake, only SHAKE instances can do XOF\n if (!this.enableXOF)\n throw new Error('XOF is not possible for this instance');\n return this.writeInto(out);\n }\n xof(bytes) {\n anumber(bytes);\n return this.xofInto(new Uint8Array(bytes));\n }\n digestInto(out) {\n aoutput(out, this);\n if (this.finished)\n throw new Error('digest() was already called');\n this.writeInto(out);\n this.destroy();\n return out;\n }\n digest() {\n return this.digestInto(new Uint8Array(this.outputLen));\n }\n destroy() {\n this.destroyed = true;\n clean(this.state);\n }\n _cloneInto(to) {\n const { blockLen, suffix, outputLen, rounds, enableXOF } = this;\n to ||= new Keccak(blockLen, suffix, outputLen, enableXOF, rounds);\n to.state32.set(this.state32);\n to.pos = this.pos;\n to.posOut = this.posOut;\n to.finished = this.finished;\n to.rounds = rounds;\n // Suffix can change in cSHAKE\n to.suffix = suffix;\n to.outputLen = outputLen;\n to.enableXOF = enableXOF;\n to.destroyed = this.destroyed;\n return to;\n }\n}\nconst genKeccak = (suffix, blockLen, outputLen, info = {}) => createHasher(() => new Keccak(blockLen, suffix, outputLen), info);\n/** SHA3-224 hash function. */\nexport const sha3_224 = /* @__PURE__ */ genKeccak(0x06, 144, 28, \n/* @__PURE__ */ oidNist(0x07));\n/** SHA3-256 hash function. Different from keccak-256. */\nexport const sha3_256 = /* @__PURE__ */ genKeccak(0x06, 136, 32, \n/* @__PURE__ */ oidNist(0x08));\n/** SHA3-384 hash function. */\nexport const sha3_384 = /* @__PURE__ */ genKeccak(0x06, 104, 48, \n/* @__PURE__ */ oidNist(0x09));\n/** SHA3-512 hash function. */\nexport const sha3_512 = /* @__PURE__ */ genKeccak(0x06, 72, 64, \n/* @__PURE__ */ oidNist(0x0a));\n/** keccak-224 hash function. */\nexport const keccak_224 = /* @__PURE__ */ genKeccak(0x01, 144, 28);\n/** keccak-256 hash function. Different from SHA3-256. */\nexport const keccak_256 = /* @__PURE__ */ genKeccak(0x01, 136, 32);\n/** keccak-384 hash function. */\nexport const keccak_384 = /* @__PURE__ */ genKeccak(0x01, 104, 48);\n/** keccak-512 hash function. */\nexport const keccak_512 = /* @__PURE__ */ genKeccak(0x01, 72, 64);\nconst genShake = (suffix, blockLen, outputLen, info = {}) => createHasher((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true), info);\n/** SHAKE128 XOF with 128-bit security. */\nexport const shake128 = \n/* @__PURE__ */\ngenShake(0x1f, 168, 16, /* @__PURE__ */ oidNist(0x0b));\n/** SHAKE256 XOF with 256-bit security. */\nexport const shake256 = \n/* @__PURE__ */\ngenShake(0x1f, 136, 32, /* @__PURE__ */ oidNist(0x0c));\n/** SHAKE128 XOF with 256-bit output (NIST version). */\nexport const shake128_32 = \n/* @__PURE__ */\ngenShake(0x1f, 168, 32, /* @__PURE__ */ oidNist(0x0b));\n/** SHAKE256 XOF with 512-bit output (NIST version). */\nexport const shake256_64 = \n/* @__PURE__ */\ngenShake(0x1f, 136, 64, /* @__PURE__ */ oidNist(0x0c));\n//# sourceMappingURL=sha3.js.map","/**\n * WOTS Block Key Derivation\n *\n * Derives deterministic WOTS (Winternitz One-Time Signature) block public\n * keys from a per-vault 64-byte seed, matching the Rust `babe::wots`\n * chain logic.\n *\n * Callers obtain the seed from `expandWotsSeed(root, htlcVout)` in the\n * vault-secrets module, where\n * `root = await deriveVaultRoot(wallet, vaultContextInput)`. Per-vault\n * uniqueness is already encoded in the seed via `htlcVout`, so this\n * module only handles the chain derivation — no further key splitting\n * by `(vaultId, depositorPk, appContract)` is needed.\n *\n * @module wots/blockDerivation\n */\n\nimport { ripemd160 } from \"@noble/hashes/legacy.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { keccak_256 } from \"@noble/hashes/sha3.js\";\nimport type { Hex } from \"viem\";\n\nimport type {\n WotsBlockPublicKey,\n WotsConfig,\n} from \"../clients/vault-provider/types\";\n\n// ---------------------------------------------------------------------------\n// Constants — must match btc-vault / babe::wots\n// ---------------------------------------------------------------------------\n\n/** Required size of the per-vault WOTS seed in bytes. */\nconst WOTS_SEED_SIZE = 64;\n\n/** Hash160 output size in bytes (= RIPEMD-160(SHA-256(x))). */\nconst CHAIN_ELEMENT_SIZE = 20;\n\n/** Bits per WOTS digit. Matches `babe::WOTS_DIGIT_BITS`. */\nconst WOTS_DIGIT_BITS = 4;\n\n/** Number of checksum digits in canonical WOTS ordering. */\nconst WOTS_CHECKSUM_DIGITS = 2;\n\n/** Digit index for the checksum minor chain (canonical ordering). */\nconst CHECKSUM_MINOR_DIGIT_INDEX = 0;\n\n/** Digit index for the checksum major chain (canonical ordering). */\nconst CHECKSUM_MAJOR_DIGIT_INDEX = 1;\n\n/**\n * Message digit counts per assert block.\n * Matches `btc_vault::ASSERT_WOTS_BLOCK_DIGIT_COUNTS`.\n */\nconst ASSERT_WOTS_BLOCK_DIGIT_COUNTS: readonly number[] = [64, 64];\n\n// ---------------------------------------------------------------------------\n// Cryptographic primitives\n// ---------------------------------------------------------------------------\n\nconst toHex = (bytes: Uint8Array) =>\n Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n\nfunction hash160(data: Uint8Array): Uint8Array {\n return ripemd160(sha256(data));\n}\n\n// ---------------------------------------------------------------------------\n// WOTS chain derivation — mirrors Rust babe::wots\n// ---------------------------------------------------------------------------\n\nfunction maxDigitValue(d: number): number {\n return (1 << d) - 1;\n}\n\nfunction defaultChecksumRadix(wMax: number): number {\n let radix = 1;\n while (radix * radix < wMax + 1) radix++;\n return Math.max(radix, 2);\n}\n\nfunction createWotsConfig(n: number): WotsConfig {\n const d = WOTS_DIGIT_BITS;\n const wMax = n * maxDigitValue(d);\n return { d, n, checksum_radix: defaultChecksumRadix(wMax) };\n}\n\n/**\n * Derive the starting chain value for a given digit index.\n * Matches Rust `chain_start_for_digit(seed, digit_index)`:\n * hash160(seed || varint_le(digit_index))\n */\nfunction chainStartForDigit(seed: Uint8Array, digitIndex: number): Uint8Array {\n const suffixBytes: number[] = [];\n let idx = digitIndex;\n while (idx > 0) {\n suffixBytes.push(idx & 0xff);\n idx >>>= 8;\n }\n const preimage = new Uint8Array(seed.length + suffixBytes.length);\n preimage.set(seed);\n for (let i = 0; i < suffixBytes.length; i++) {\n preimage[seed.length + i] = suffixBytes[i];\n }\n return hash160(preimage);\n}\n\n/**\n * Compute the terminal value of a Hash160 chain of given length.\n * Matches Rust `compute_chain(seed, len)` — returns chain[len].\n */\nfunction computeChainTerminal(start: Uint8Array, steps: number): Uint8Array {\n let current = start;\n for (let i = 0; i < steps; i++) {\n current = hash160(current);\n }\n return current;\n}\n\n// ---------------------------------------------------------------------------\n// Per-block public key derivation\n// ---------------------------------------------------------------------------\n\nfunction deriveBlockPublicKey(\n blockSeed: Uint8Array,\n config: WotsConfig,\n): WotsBlockPublicKey {\n const k = maxDigitValue(config.d);\n const checksumMinorMax = config.checksum_radix - 1;\n const checksumMajorMax = Math.floor((config.n * k) / config.checksum_radix);\n\n const messageTerminals: number[][] = [];\n for (let digit = 0; digit < config.n; digit++) {\n const start = chainStartForDigit(blockSeed, digit + WOTS_CHECKSUM_DIGITS);\n const terminal = computeChainTerminal(start, k);\n messageTerminals.push(Array.from(terminal));\n }\n\n const checksumMinorStart = chainStartForDigit(\n blockSeed,\n CHECKSUM_MINOR_DIGIT_INDEX,\n );\n const checksumMinorTerminal = computeChainTerminal(\n checksumMinorStart,\n checksumMinorMax,\n );\n\n const checksumMajorStart = chainStartForDigit(\n blockSeed,\n CHECKSUM_MAJOR_DIGIT_INDEX,\n );\n const checksumMajorTerminal = computeChainTerminal(\n checksumMajorStart,\n checksumMajorMax,\n );\n\n return {\n config,\n message_terminals: messageTerminals,\n checksum_major_terminal: Array.from(checksumMajorTerminal),\n checksum_minor_terminal: Array.from(checksumMinorTerminal),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Derive deterministic WOTS block public keys from a per-vault 64-byte seed.\n *\n * The seed must come from `expandWotsSeed(root, htlcVout)` (vault-secrets\n * module). Per-vault uniqueness is encoded in `htlcVout`; this function\n * only handles the chain derivation. Per-block 20-byte seeds are derived\n * as `hash160(seed || blockIdx)` and fed into the standard Rust\n * `babe::wots` chain logic.\n *\n * The seed is zeroed in the `finally` block.\n *\n * @stability frozen — on-chain-binding. Per-block seed derivation,\n * chain length, checksum-digit ordering, and terminal byte layout\n * must match Rust `babe::wots` byte-for-byte. Any divergence rotates\n * `depositorWotsPkHash` and breaks resume + on-chain verification\n * for every existing vault.\n *\n * @param seed - 64-byte per-vault seed.\n * @returns Array of 2 WOTS block public keys.\n * @throws If `seed.length !== 64`.\n */\nexport async function deriveWotsBlocksFromSeed(\n seed: Uint8Array,\n): Promise<WotsBlockPublicKey[]> {\n // try/finally wraps the size check so the seed buffer is zeroed on\n // every exit path, including malformed-input rejection.\n try {\n if (seed.length !== WOTS_SEED_SIZE) {\n throw new Error(\n `WOTS seed must be exactly ${WOTS_SEED_SIZE} bytes, got ${seed.length}`,\n );\n }\n\n const blocks: WotsBlockPublicKey[] = [];\n\n for (\n let blockIdx = 0;\n blockIdx < ASSERT_WOTS_BLOCK_DIGIT_COUNTS.length;\n blockIdx++\n ) {\n const n = ASSERT_WOTS_BLOCK_DIGIT_COUNTS[blockIdx];\n const config = createWotsConfig(n);\n\n // Per-block 20-byte seed: hash160(seed || blockIdx)\n const blockSeedInput = new Uint8Array(seed.length + 1);\n blockSeedInput.set(seed);\n blockSeedInput[seed.length] = blockIdx;\n const blockSeed = hash160(blockSeedInput);\n\n try {\n const block = deriveBlockPublicKey(blockSeed, config);\n\n if (block.config.d !== WOTS_DIGIT_BITS) {\n throw new Error(\n `Block ${blockIdx}: expected d=${WOTS_DIGIT_BITS}, got d=${block.config.d}`,\n );\n }\n if (block.config.n !== n) {\n throw new Error(\n `Block ${blockIdx}: expected n=${n}, got n=${block.config.n}`,\n );\n }\n if (block.message_terminals.length !== n) {\n throw new Error(\n `Block ${blockIdx}: expected ${n} message terminals, got ${block.message_terminals.length}`,\n );\n }\n for (let t = 0; t < block.message_terminals.length; t++) {\n if (block.message_terminals[t].length !== CHAIN_ELEMENT_SIZE) {\n throw new Error(\n `Block ${blockIdx} terminal ${t}: expected ${CHAIN_ELEMENT_SIZE} bytes, got ${block.message_terminals[t].length}`,\n );\n }\n }\n if (block.checksum_minor_terminal.length !== CHAIN_ELEMENT_SIZE) {\n throw new Error(\n `Block ${blockIdx} checksum_minor: expected ${CHAIN_ELEMENT_SIZE} bytes`,\n );\n }\n if (block.checksum_major_terminal.length !== CHAIN_ELEMENT_SIZE) {\n throw new Error(\n `Block ${blockIdx} checksum_major: expected ${CHAIN_ELEMENT_SIZE} bytes`,\n );\n }\n\n blocks.push(block);\n } finally {\n blockSeedInput.fill(0);\n blockSeed.fill(0);\n }\n }\n\n if (blocks.length !== ASSERT_WOTS_BLOCK_DIGIT_COUNTS.length) {\n throw new Error(\n `Expected ${ASSERT_WOTS_BLOCK_DIGIT_COUNTS.length} blocks, got ${blocks.length}`,\n );\n }\n\n return blocks;\n } finally {\n seed.fill(0);\n }\n}\n\n/** Validate a single chain terminal: correct length and all bytes in [0, 255]. */\nfunction validateTerminal(\n terminal: number[],\n blockIdx: number,\n label: string,\n): void {\n if (terminal.length !== CHAIN_ELEMENT_SIZE) {\n throw new Error(\n `Block ${blockIdx} ${label}: expected ${CHAIN_ELEMENT_SIZE} bytes, got ${terminal.length}`,\n );\n }\n for (let j = 0; j < terminal.length; j++) {\n const b = terminal[j];\n if (!Number.isInteger(b) || b < 0 || b > 255) {\n throw new Error(\n `Block ${blockIdx} ${label}[${j}]: invalid byte value ${b}`,\n );\n }\n }\n}\n\n/**\n * Compute the keccak256 hash of WOTS block public keys.\n *\n * Matches Rust `btc_vault::wots_public_keys_keccak256`: for each block,\n * chain tips are concatenated in canonical order\n * `[checksum_minor, checksum_major, message_terminals...]`, then all\n * blocks are concatenated and hashed.\n *\n * The result is committed on-chain as `depositorWotsPkHash` so the vault\n * provider can verify submitted WOTS public keys.\n *\n * @stability frozen — on-chain-binding. Concatenation order of chain\n * tips and the keccak256 input layout MUST match Rust\n * `btc_vault::wots_public_keys_keccak256` byte-for-byte. Any change\n * rotates the on-chain commitment and breaks every existing vault.\n */\nexport function computeWotsBlockPublicKeysHash(\n publicKeys: WotsBlockPublicKey[],\n): Hex {\n if (publicKeys.length === 0) {\n throw new Error(\"Public keys array must not be empty\");\n }\n\n for (let i = 0; i < publicKeys.length; i++) {\n const pk = publicKeys[i];\n validateTerminal(pk.checksum_minor_terminal, i, \"checksum_minor_terminal\");\n validateTerminal(pk.checksum_major_terminal, i, \"checksum_major_terminal\");\n for (let t = 0; t < pk.message_terminals.length; t++) {\n validateTerminal(pk.message_terminals[t], i, `message_terminal[${t}]`);\n }\n }\n\n let totalTips = 0;\n for (const pk of publicKeys) {\n totalTips += WOTS_CHECKSUM_DIGITS + pk.message_terminals.length;\n }\n\n const buffer = new Uint8Array(totalTips * CHAIN_ELEMENT_SIZE);\n let offset = 0;\n\n for (const pk of publicKeys) {\n buffer.set(pk.checksum_minor_terminal, offset);\n offset += CHAIN_ELEMENT_SIZE;\n buffer.set(pk.checksum_major_terminal, offset);\n offset += CHAIN_ELEMENT_SIZE;\n for (const terminal of pk.message_terminals) {\n buffer.set(terminal, offset);\n offset += CHAIN_ELEMENT_SIZE;\n }\n }\n\n const digest = keccak_256(buffer);\n return `0x${toHex(digest)}`;\n}\n","/**\n * Per-vault HKDF expansion of WOTS keys + HTLC preimages from the\n * wallet root.\n *\n * @module managers/pegin/expandPerVaultSecrets\n */\n\nimport type { Hex } from \"viem\";\n\nimport type { WotsBlockPublicKey } from \"../../clients/vault-provider/types\";\nimport {\n ensureHexPrefix,\n uint8ArrayToHex,\n} from \"../../primitives/utils/bitcoin\";\nimport { computeHashlock } from \"../../services\";\nimport {\n expandHashlockSecret,\n expandWotsSeed,\n} from \"../../vault-secrets\";\nimport {\n computeWotsBlockPublicKeysHash,\n deriveWotsBlocksFromSeed,\n} from \"../../wots\";\n\n/**\n * Result of {@link expandPerVaultSecrets}.\n */\nexport interface PerVaultExpansionResult {\n perVaultWotsKeys: WotsBlockPublicKey[][];\n /** Keccak256 of WOTS keys, ready as `depositorWotsPkHash` (0x-prefixed). */\n wotsPkHashes: Hex[];\n /** HTLC preimage hex per vault (no 0x prefix). */\n htlcSecretHexes: string[];\n /** SHA-256 of each HTLC preimage as 64-char hex (no 0x prefix). */\n hashlocks: string[];\n}\n\n/**\n * Derive per-vault WOTS keys + HTLC preimages from the wallet root.\n *\n * Takes ownership of `root`: zeros the buffer (and per-vault secret\n * buffers) before returning, regardless of how the caller exits.\n *\n * @param root 32-byte wallet-derived root from `deriveVaultRoot`.\n * @param vaultCount Number of vaults (= length of `amounts`).\n */\nexport async function expandPerVaultSecrets(\n root: Uint8Array,\n vaultCount: number,\n): Promise<PerVaultExpansionResult> {\n const perVaultWotsKeys: WotsBlockPublicKey[][] = [];\n const wotsPkHashes: Hex[] = [];\n const htlcSecretHexes: string[] = [];\n const hashlocks: string[] = [];\n\n try {\n for (let i = 0; i < vaultCount; i++) {\n const wotsSeed = await expandWotsSeed(root, i);\n try {\n const wotsPublicKeys = await deriveWotsBlocksFromSeed(wotsSeed);\n perVaultWotsKeys.push(wotsPublicKeys);\n wotsPkHashes.push(computeWotsBlockPublicKeysHash(wotsPublicKeys));\n } finally {\n wotsSeed.fill(0);\n }\n\n const secretBytes = await expandHashlockSecret(root, i);\n try {\n const secretHex = uint8ArrayToHex(secretBytes);\n htlcSecretHexes.push(secretHex);\n hashlocks.push(computeHashlock(ensureHexPrefix(secretHex)).slice(2));\n } finally {\n secretBytes.fill(0);\n }\n }\n } finally {\n root.fill(0);\n }\n\n return { perVaultWotsKeys, wotsPkHashes, htlcSecretHexes, hashlocks };\n}\n","/**\n * Normalizers for wallet-returned values consumed by the Pre-PegIn flow.\n *\n * @module managers/pegin/normalizeWalletInputs\n */\n\nimport { Buffer } from \"buffer\";\nimport type { Hex } from \"viem\";\n\nimport { processPublicKeyToXOnly } from \"../../primitives/utils/bitcoin\";\n\nconst HEX_SIGNATURE_REGEX = /^0x[0-9a-f]+$/i;\nconst UNPREFIXED_HEX_SIGNATURE_REGEX = /^[0-9a-f]+$/i;\nconst BASE64_SIGNATURE_REGEX = /^[A-Za-z0-9+/]+={0,2}$/;\n\n/**\n * Normalize a wallet-returned BTC public key to the canonical x-only\n * 64-char lowercase hex form (no 0x prefix).\n *\n * Throws on empty/non-string input. Idempotent on x-only input.\n */\nexport function normalizeXOnlyPubkey(raw: unknown): string {\n if (typeof raw !== \"string\" || raw.length === 0) {\n throw new Error(\"BTC wallet returned empty public key\");\n }\n // Lowercase so case-sensitive equality checks downstream don't fail\n // on uppercase wallet output (processPublicKeyToXOnly passes a 64-char\n // input through unchanged).\n return processPublicKeyToXOnly(raw).toLowerCase();\n}\n\n/**\n * Normalize a wallet-returned BIP-322 signature into 0x-prefixed hex.\n *\n * Accepts:\n * - 0x-prefixed lowercase/uppercase hex\n * - unprefixed hex (wins over base64 when input is pure `[0-9a-fA-F]+`)\n * - canonical standard base64 (`[A-Za-z0-9+/]` with `=` padding to a\n * multiple of 4 and no non-canonical encodings)\n *\n * Rejects URL-safe base64 (`-`/`_`) and base64 without padding. Wallets\n * known to return BIP-322 signatures (Keystone, UniSat, OKX, OneKey,\n * Unisat) all use standard base64; URL-safe is an explicit non-goal.\n */\nexport function normalizePopSignature(raw: unknown): Hex {\n if (typeof raw !== \"string\" || raw.length === 0) {\n throw new Error(\"BTC wallet returned empty BIP-322 signature\");\n }\n\n if (raw.startsWith(\"0x\") || raw.startsWith(\"0X\")) {\n if (\n !HEX_SIGNATURE_REGEX.test(raw) ||\n raw.length < 4 ||\n raw.length % 2 !== 0\n ) {\n throw new Error(\"BTC wallet returned malformed hex BIP-322 signature\");\n }\n return raw.toLowerCase() as Hex;\n }\n\n // Prefer hex when the input could be either: every hex char is also a\n // valid base64 char, so the base64 branch alone would silently misdecode\n // a wallet returning \"deadbeef\" instead of \"0xdeadbeef\".\n if (UNPREFIXED_HEX_SIGNATURE_REGEX.test(raw)) {\n if (raw.length % 2 !== 0) {\n throw new Error(\"BTC wallet returned malformed hex BIP-322 signature\");\n }\n return `0x${raw.toLowerCase()}` as Hex;\n }\n\n if (!BASE64_SIGNATURE_REGEX.test(raw) || raw.length % 4 !== 0) {\n throw new Error(\"BTC wallet returned malformed base64 BIP-322 signature\");\n }\n const bytes = Buffer.from(raw, \"base64\");\n // Round-trip to reject non-canonical base64 (e.g. \"AB==\" decodes but\n // re-encodes to \"AA==\").\n if (bytes.length === 0 || bytes.toString(\"base64\") !== raw) {\n throw new Error(\"BTC wallet returned malformed base64 BIP-322 signature\");\n }\n return `0x${bytes.toString(\"hex\")}` as Hex;\n}\n","/**\n * Batch-sign helper that prefers native `signPsbts` and falls back to\n * sequential `signPsbt` for wallets that don't implement batch signing.\n *\n * @module managers/pegin/signPsbtsWithFallback\n */\n\nimport type {\n BitcoinWallet,\n SignPsbtOptions,\n} from \"../../../../shared/wallets\";\n\n/**\n * Sign multiple PSBTs against a wallet. Wallets exposing native batch\n * signing (e.g. UniSat) sign all PSBTs in a single interaction; others\n * (Ledger, AppKit) loop `signPsbt` internally, so the popup UX depends\n * on the wallet adapter.\n *\n * @throws If `signPsbts` returns a different number of signed PSBTs\n * than were submitted.\n */\nexport async function signPsbtsWithFallback(\n wallet: BitcoinWallet,\n psbtsHexes: string[],\n options: SignPsbtOptions[],\n): Promise<string[]> {\n if (typeof wallet.signPsbts === \"function\") {\n const signedPsbts = await wallet.signPsbts(psbtsHexes, options);\n if (signedPsbts.length !== psbtsHexes.length) {\n throw new Error(\n `Expected ${psbtsHexes.length} signed PSBTs but received ${signedPsbts.length}`,\n );\n }\n return signedPsbts;\n }\n\n const signedPsbts: string[] = [];\n for (let i = 0; i < psbtsHexes.length; i++) {\n const signed = await wallet.signPsbt(psbtsHexes[i], options[i]);\n signedPsbts.push(signed);\n }\n return signedPsbts;\n}\n","/**\n * Peg-in Manager - Wallet Orchestration for Peg-in Operations\n *\n * This module provides the PeginManager class that orchestrates the complete\n * peg-in flow using SDK primitives, utilities, and wallet interfaces.\n *\n * @remarks\n * PeginManager handles the peg-in flow:\n * 1. **preparePegin()** - Build Pre-PegIn HTLC, fund it, sign PegIn input\n * 2. **signProofOfPossession()** - Sign BIP-322 PoP (one per deposit session)\n * 3. **registerPeginOnChain()** - Submit to Ethereum contract with PoP\n * 4. **signAndBroadcast()** - Sign and broadcast Pre-PegIn tx to Bitcoin network\n * 5. *(Use {@link PayoutManager} for payout authorization signing)*\n *\n * @see {@link PayoutManager} - For Step 5: sign payout transactions\n * @see {@link buildPrePeginPsbt} - Lower-level primitive used internally\n *\n * @module managers/PeginManager\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport * as bitcoin from \"bitcoinjs-lib\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport {\n assertAuthAnchorOpReturn,\n expandPerVaultSecrets,\n normalizePopSignature,\n normalizeXOnlyPubkey,\n signPsbtsWithFallback,\n} from \"./pegin\";\nimport {\n encodeFunctionData,\n isAddressEqual,\n zeroAddress,\n type Address,\n type Chain,\n type Hex,\n type PublicClient,\n type WalletClient,\n} from \"viem\";\n\nimport type { BitcoinWallet, Hash, SignPsbtOptions } from \"../../../shared/wallets\";\nimport type { WotsBlockPublicKey } from \"../clients/vault-provider/types\";\nimport { type UtxoInfo, getUtxoInfo, pushTx } from \"../clients/mempool\";\nimport { BTCVaultRegistryABI, handleContractError } from \"../contracts\";\nimport {\n assertPsbtUnsignedTxMatches,\n buildPrePeginPsbt,\n buildPeginTxFromFundedPrePegin,\n buildPeginInputPsbt,\n extractPeginInputSignature,\n finalizePeginInputPsbt,\n deriveVaultId,\n type PrePeginParams,\n type Network,\n} from \"../primitives\";\nimport {\n ensureHexPrefix,\n hexToUint8Array,\n isAddressFromPublicKey,\n stripHexPrefix,\n uint8ArrayToHex,\n} from \"../primitives/utils/bitcoin\";\nimport {\n calculateBtcTxHash,\n fundPeginTransaction,\n getNetwork,\n getPsbtInputFields,\n peginOutputCount,\n selectUtxosForPegin,\n type UTXO,\n MAX_REASONABLE_FEE_SATS,\n waitForTransactionReceiptSmartAware,\n} from \"../utils\";\nimport { createTaprootScriptPathSignOptions } from \"../utils/signing\";\nimport {\n deriveVaultRoot,\n expandAuthAnchor,\n type FundingOutpoint,\n} from \"../vault-secrets\";\n\n/** Referral code sent with pegin registration — 0 means no referral. */\nconst NO_REFERRAL_CODE = 0;\n\n/**\n * 32-byte zero hex used as a placeholder during the sizing pass for any\n * value whose content does not affect output sizes — currently the\n * per-vault hashlocks and the auth-anchor commitment. The commit pass\n * substitutes real values; UTXO selection and fee sizing are invariant\n * under the swap because all four (placeholder hashlock, real\n * SHA256(secret), placeholder anchor, real SHA256(authAnchor)) are\n * 32-byte pushes. Substitution invariance is pinned in `pegin.test.ts`.\n */\nconst SIZING_PASS_PLACEHOLDER_BYTES32_HEX = \"00\".repeat(32);\n\n/**\n * Configuration for the PeginManager.\n */\nexport interface PeginManagerConfig {\n /**\n * Bitcoin network to use for transactions.\n */\n btcNetwork: Network;\n\n /**\n * Bitcoin wallet for signing peg-in transactions.\n */\n btcWallet: BitcoinWallet;\n\n /**\n * Ethereum wallet for registering peg-in on-chain.\n * Uses viem's WalletClient directly for proper gas estimation.\n */\n ethWallet: WalletClient;\n\n /**\n * Ethereum chain configuration.\n * Required for proper gas estimation in contract calls.\n */\n ethChain: Chain;\n\n /**\n * Public client used for read calls (`readContract`, `estimateGas`,\n * `waitForTransactionReceipt`). Pass a client configured with the\n * caller's RPC URL so reads hit the same endpoint as the rest of the\n * application instead of viem's stock chain default.\n */\n publicClient: PublicClient;\n\n /**\n * Vault contract addresses.\n */\n vaultContracts: {\n /**\n * BTCVaultRegistry contract address on Ethereum.\n */\n btcVaultRegistry: Address;\n };\n\n /**\n * Mempool API URL for fetching UTXO data and broadcasting transactions.\n * Use MEMPOOL_API_URLS constant for standard mempool.space URLs, or provide\n * a custom URL if running your own mempool instance.\n */\n mempoolApiUrl: string;\n}\n\n/**\n * Parameters for the pegin flow (pre-pegin + pegin transactions).\n */\nexport interface PreparePeginParams {\n /**\n * Amounts to peg in per HTLC (in satoshis).\n * Must have the same length as `hashlocks`.\n * For single deposits, pass a single-element array.\n */\n amounts: readonly bigint[];\n\n /**\n * Vault provider's BTC public key (x-only, 64-char hex).\n * Can be provided with or without \"0x\" prefix (will be stripped automatically).\n */\n vaultProviderBtcPubkey: string;\n\n /**\n * Vault keeper BTC public keys (x-only, 64-char hex).\n * Can be provided with or without \"0x\" prefix (will be stripped automatically).\n */\n vaultKeeperBtcPubkeys: readonly string[];\n\n /**\n * Universal challenger BTC public keys (x-only, 64-char hex).\n * Can be provided with or without \"0x\" prefix (will be stripped automatically).\n */\n universalChallengerBtcPubkeys: readonly string[];\n\n /**\n * CSV timelock in blocks for the PegIn vault output.\n */\n timelockPegin: number;\n\n /**\n * CSV timelock in blocks for the Pre-PegIn HTLC refund path.\n */\n timelockRefund: number;\n\n /**\n * Protocol fee rate in sat/vB from the contract offchain params.\n * Used by WASM for computing depositorClaimValue and min pegin fee.\n */\n protocolFeeRate: bigint;\n\n /**\n * Mempool fee rate in sat/vB for funding the Pre-PegIn transaction.\n * Used for UTXO selection and change calculation.\n */\n mempoolFeeRate: number;\n\n /**\n * M in M-of-N council multisig (from contract params).\n */\n councilQuorum: number;\n\n /**\n * N in M-of-N council multisig (from contract params).\n */\n councilSize: number;\n\n /**\n * Available UTXOs from the depositor's wallet for funding the Pre-PegIn transaction.\n */\n availableUTXOs: readonly UTXO[];\n\n /**\n * Bitcoin address for receiving change from the Pre-PegIn transaction.\n */\n changeAddress: string;\n}\n\n/**\n * Result of preparing a pegin.\n */\n/** Per-vault PegIn data derived from a shared Pre-PegIn transaction */\nexport interface PerVaultPeginData {\n /** Index of the HTLC output in the Pre-PegIn transaction (0, 1, 2, ...) */\n htlcVout: number;\n /** HTLC output value in satoshis */\n htlcValue: bigint;\n /** Depositor-signed PegIn transaction hex (for contract registration) */\n peginTxHex: string;\n /** PegIn transaction ID */\n peginTxid: string;\n /** Depositor's Schnorr signature over PegIn input (HTLC leaf 0) */\n peginInputSignature: string;\n /** Vault output scriptPubKey hex */\n vaultScriptPubKey: string;\n}\n\n/**\n * Broadcast-ready transaction output of {@link PeginManager.preparePegin}.\n * Safe to log / persist — contains no sensitive material.\n */\nexport interface PreparePeginTransaction {\n /**\n * Funded, pre-witness Pre-PegIn tx hex. Pass this for register calls'\n * `unsignedPrePeginTx` — despite the contract-side name, the registry\n * stores the funded form so indexers can rebuild refund PSBTs.\n */\n fundedPrePeginTxHex: string;\n /** Funded Pre-PegIn transaction ID */\n prePeginTxid: string;\n /** Per-vault PegIn data — one entry per amount */\n perVault: PerVaultPeginData[];\n /** UTXOs selected to fund the Pre-PegIn transaction */\n selectedUTXOs: UTXO[];\n /** Transaction fee in satoshis */\n fee: bigint;\n /** Change amount in satoshis (if any) */\n changeAmount: bigint;\n}\n\n/**\n * Sensitive material derived from the wallet root. Do not log; do not\n * persist beyond the activation flow. Strings are immutable in JS, so\n * lifetime is GC-only — secrets stay live until the result is dropped.\n */\nexport interface PreparePeginDerivedSecrets {\n /** Per-vault WOTS block public keys (one array per vault). */\n perVaultWotsKeys: WotsBlockPublicKey[][];\n /** Per-vault keccak256 of WOTS keys, ready as `depositorWotsPkHash`. */\n wotsPkHashes: Hex[];\n /**\n * Per-vault HTLC preimage hex (no 0x prefix). Re-derivable any time\n * via `expandHashlockSecret(root, htlcVout)`; not persisted.\n */\n htlcSecretHexes: string[];\n /**\n * Raw 32-byte auth-anchor preimage as 64-char lowercase hex (no `0x`).\n * Sent to the VP via `auth_createDepositorToken` to obtain a bearer\n * token; the VP validates `SHA256(authAnchorHex) === OP_RETURN_PUSH32`\n * in the broadcast Pre-PegIn. Reveal is intentional: once exposed\n * the anchor is public, but its scope is bound to a single\n * `peginTxid`. Domain-separated from `htlcSecretHexes` and\n * `perVaultWotsKeys` via the HKDF `info` label, so revealing it does\n * not weaken the other derived secrets.\n */\n authAnchorHex: string;\n}\n\nexport interface PreparePeginResult {\n /** Broadcast-ready Pre-PegIn + per-vault PegIn txs. Safe to log. */\n transaction: PreparePeginTransaction;\n /**\n * x-only depositor pubkey snapshot used end-to-end across sizing,\n * vault-root derivation, and PSBT signing. Safe to persist; not\n * sensitive. Reusing this snapshot downstream guarantees that\n * derived secrets and signed PSBTs reference the same identity.\n */\n depositorBtcPubkey: string;\n /** Sensitive derived material — see {@link PreparePeginDerivedSecrets}. */\n derivedSecrets: PreparePeginDerivedSecrets;\n}\n\n\n/**\n * Parameters for signing and broadcasting a transaction.\n */\nexport interface SignAndBroadcastParams {\n /**\n * Funded Pre-PegIn transaction hex from preparePegin().\n */\n fundedPrePeginTxHex: string;\n\n /**\n * Depositor's BTC public key (x-only, 64-char hex).\n * Can be provided with or without \"0x\" prefix.\n * Required for Taproot signing.\n */\n depositorBtcPubkey: string;\n\n /**\n * Optional pre-fetched prevout data for inputs not yet in the mempool.\n * Key format: \"txid:vout\" (e.g. \"abc123...def:0\").\n * When provided, matching inputs skip the mempool API fetch.\n * Useful for split transactions where outputs are unconfirmed.\n */\n localPrevouts?: Record<string, { scriptPubKey: string; value: number }>;\n}\n\n/**\n * BIP-322 BTC Proof-of-Possession binding a depositor's BTC key to their\n * Ethereum account. Produced by {@link PeginManager.signProofOfPossession}\n * and reusable across every register call in the same session — the\n * embedded identities are re-checked at register time.\n */\nexport interface PopSignature {\n /** BIP-322 signature over the PoP message (0x-prefixed hex). */\n btcPopSignature: Hex;\n /** Ethereum address the PoP was signed for. */\n depositorEthAddress: Address;\n /** BTC x-only public key (64-char hex, no 0x prefix). */\n depositorBtcPubkey: string;\n}\n\n/**\n * Parameters for registering a peg-in on Ethereum.\n */\nexport interface RegisterPeginParams {\n /**\n * Funded, pre-witness Pre-PegIn tx hex — pass\n * {@link PreparePeginTransaction.fundedPrePeginTxHex} from\n * {@link PreparePeginResult.transaction}. The contract-side parameter\n * is named `unsignedPrePeginTx` but it stores the funded form.\n */\n unsignedPrePeginTx: string;\n\n /**\n * Depositor-signed PegIn transaction hex (submitted to contract; vault ID derived from this).\n */\n depositorSignedPeginTx: string;\n\n /**\n * Vault provider's Ethereum address.\n */\n vaultProvider: Address;\n\n /**\n * SHA256 hashlock for HTLC activation (bytes32 hex with 0x prefix).\n */\n hashlock: Hex;\n\n /**\n * Depositor's BTC payout address (e.g. bc1p..., bc1q...).\n * Converted to scriptPubKey internally via bitcoinjs-lib.\n *\n * If omitted, defaults to the connected BTC wallet's address\n * via `btcWallet.getAddress()`.\n */\n depositorPayoutBtcAddress?: string;\n\n /** Keccak256 hash of the depositor's WOTS public key (bytes32) */\n depositorWotsPkHash: Hex;\n\n /** Proof of possession from {@link PeginManager.signProofOfPossession}. */\n popSignature: PopSignature;\n\n /**\n * Zero-based index of the HTLC output in the Pre-PegIn transaction that\n * this PegIn spends. In a batch Pre-PegIn with N HTLC outputs, each vault\n * registration references a different htlcVout (0..N-1).\n */\n htlcVout: number;\n}\n\n/**\n * Result of registering a peg-in on Ethereum.\n */\nexport interface RegisterPeginResult {\n /**\n * Ethereum transaction hash for the peg-in registration.\n */\n ethTxHash: Hash;\n\n /**\n * Derived vault ID: keccak256(abi.encode(peginTxHash, depositor)).\n * Used for contract reads/writes and indexer queries.\n */\n vaultId: Hex;\n\n /**\n * Raw Bitcoin pegin transaction hash (double-SHA256 of the signed pegin tx).\n * Used for VP RPC operations which key on the BTC transaction ID.\n */\n peginTxHash: Hex;\n}\n\n/**\n * Single request in a batch pegin registration.\n * All requests in a batch share the same vault provider, depositor BTC\n * pubkey, and Pre-PegIn transaction.\n */\nexport interface BatchPeginRequestItem {\n /** Signed PegIn tx hex for this vault */\n depositorSignedPeginTx: string;\n /** SHA256 hashlock for HTLC activation (bytes32 hex) */\n hashlock: Hex;\n /** Zero-based HTLC output index in the Pre-PegIn tx (unique per request) */\n htlcVout: number;\n /** Depositor's BTC payout address (required — funds are sent here on payout) */\n depositorPayoutBtcAddress: string;\n /** Keccak256 hash of the depositor's WOTS public key (bytes32) */\n depositorWotsPkHash: Hex;\n}\n\n/**\n * Parameters for registerPeginBatchOnChain.\n */\nexport interface RegisterPeginBatchParams {\n /** Vault provider address (shared across all vaults in batch) */\n vaultProvider: Address;\n /**\n * Funded, pre-witness Pre-PegIn tx hex — shared across every request in\n * the batch. See {@link RegisterPeginParams.unsignedPrePeginTx}.\n */\n unsignedPrePeginTx: string;\n /** Individual pegin requests (one per vault) */\n requests: BatchPeginRequestItem[];\n /** Proof of possession from {@link PeginManager.signProofOfPossession}. */\n popSignature: PopSignature;\n}\n\n/**\n * Per-vault result from a batch pegin registration.\n */\nexport interface BatchPeginResultItem {\n /** Derived vault ID: keccak256(abi.encode(peginTxHash, depositor)) */\n vaultId: Hex;\n /** Raw BTC pegin transaction hash */\n peginTxHash: Hex;\n}\n\n/**\n * Result of registering a batch of pegins on Ethereum in a single transaction.\n */\nexport interface RegisterPeginBatchResult {\n /** Ethereum transaction hash */\n ethTxHash: Hex;\n /** Per-vault results (same order as input requests) */\n vaults: BatchPeginResultItem[];\n}\n\n\n/**\n * Resolve prevout data for a transaction input.\n * Checks localPrevouts first; falls back to mempool API.\n */\nfunction resolveUtxoInfo(\n txid: string,\n vout: number,\n localPrevouts: Record<string, { scriptPubKey: string; value: number }> | undefined,\n apiUrl: string,\n): Promise<UtxoInfo> {\n const local = localPrevouts?.[`${txid}:${vout}`];\n if (local) {\n return Promise.resolve({\n txid,\n vout,\n value: local.value,\n scriptPubKey: local.scriptPubKey,\n });\n }\n return getUtxoInfo(txid, vout, apiUrl);\n}\n\n/**\n * Manager for orchestrating peg-in operations.\n *\n * This manager provides a high-level API for creating peg-in transactions\n * by coordinating between SDK primitives, utilities, and wallet interfaces.\n *\n * @remarks\n * The complete peg-in flow consists of 5 steps:\n *\n * | Step | Method | Description |\n * |------|--------|-------------|\n * | 1 | {@link preparePegin} | Build Pre-PegIn HTLC, fund it, sign PegIn input |\n * | 2 | {@link signProofOfPossession} | Sign BIP-322 PoP (one per deposit session) |\n * | 3 | {@link registerPeginOnChain} | Submit to Ethereum contract |\n * | 4 | {@link signAndBroadcast} | Sign and broadcast Pre-PegIn tx to Bitcoin network |\n * | 5 | {@link PayoutManager} | Sign BOTH payout authorizations |\n *\n * **Important:** Step 5 uses {@link PayoutManager}, not this class. After\n * step 4, the vault provider observes the broadcast Pre-PegIn and prepares\n * 3 transactions per claimer:\n * - `claim_tx` - Claim transaction\n * - `assert_tx` - Assert transaction\n * - `payout_tx` - Payout transaction\n *\n * You must sign the Payout transaction for each claimer:\n * - {@link PayoutManager.signPayoutTransaction} - uses assert_tx as input reference\n *\n * Submit all signatures to the vault provider to drive the contract to\n * `VERIFIED` (and then activate by revealing the HTLC secret, which is a\n * services-layer step outside this manager).\n *\n * @see {@link PayoutManager} - Required for Step 5 (payout authorization)\n * @see {@link buildPrePeginPsbt} - Lower-level primitive for custom implementations\n * @see {@link https://github.com/babylonlabs-io/babylon-toolkit/blob/main/packages/babylon-ts-sdk/docs/quickstart/managers.md | Managers Quickstart}\n */\n/**\n * Maximum time (ms) to wait for a transaction receipt before timing out.\n * Matches the prior vault-service polling timeout so users see a clear error\n * instead of an indefinite hang when a transaction is dropped from the mempool.\n */\nconst RECEIPT_TIMEOUT_MS = 120_000;\n\nexport class PeginManager {\n private readonly config: PeginManagerConfig;\n\n /**\n * Creates a new PeginManager instance.\n *\n * @param config - Manager configuration including wallets and contract addresses\n */\n constructor(config: PeginManagerConfig) {\n this.config = config;\n }\n\n /**\n * Prepare a peg-in: sizing pass → vault-root derivation (one wallet\n * popup) → per-vault WOTS / hashlock derivation → commit pass with\n * batch PSBT signing (one popup). Returns broadcast-ready txs, the\n * pubkey snapshot, and the sensitive derived material.\n *\n * @throws If the wallet rejects, insufficient funds, or an internal\n * invariant violation.\n */\n async preparePegin(\n params: PreparePeginParams,\n ): Promise<PreparePeginResult> {\n if (params.amounts.length === 0) {\n throw new Error(\"amounts must contain at least one entry\");\n }\n\n // Raw form for `signInputs[].publicKey` (UniSat/OKX/OneKey reject\n // x-only); x-only form for protocol/HTLC use. One snapshot binds\n // sizing, root derivation, and PSBT signing to one identity.\n const depositorBtcPubkeyRaw =\n await this.config.btcWallet.getPublicKeyHex();\n const depositorBtcPubkey = normalizeXOnlyPubkey(depositorBtcPubkeyRaw);\n\n // Pre-PegIn change pays back to the depositor. The wallet will sign\n // whatever output the PSBT carries; nothing downstream proves the\n // change address belongs to the signing key, so a state-race / stale\n // FE / hostile adapter that puts an attacker-controlled address here\n // would drain the change after signing. Bind once at entry using the\n // pubkey snapshot above (no second wallet read).\n if (\n !isAddressFromPublicKey(\n params.changeAddress,\n depositorBtcPubkeyRaw,\n this.config.btcNetwork,\n )\n ) {\n throw new Error(\n `Pre-PegIn changeAddress \"${params.changeAddress}\" is not derived ` +\n `from the connected wallet's public key. Refusing to build a tx ` +\n `that would send change to an address the signing key doesn't control.`,\n );\n }\n\n // Sizing pass uses a placeholder for the auth-anchor hash because\n // the wallet popup that produces the real anchor hasn't run yet.\n // The OP_RETURN's byte length is invariant under content swap, so\n // UTXO selection and fees match the commit pass.\n const sizing = await this.prepareSizing(depositorBtcPubkey, params);\n\n const fundingOutpoints: FundingOutpoint[] = sizing.selectedUTXOs.map(\n (u) => ({\n txid: hexToUint8Array(u.txid),\n vout: u.vout,\n }),\n );\n const root = await deriveVaultRoot(this.config.btcWallet, {\n depositorBtcPubkey: hexToUint8Array(depositorBtcPubkey),\n fundingOutpoints,\n });\n\n // Take ownership of the auth anchor before per-vault expansion (which\n // zeros `root`). Convert to hex immediately, then zero the buffer.\n // `authAnchorHex` is a JS string — immutable, GC-only — and lives\n // until the result is dropped. If anything in this window throws,\n // `expandPerVaultSecrets` won't run to zero `root`, so we wipe it\n // here on the throw path.\n let authAnchorHex: string;\n let authAnchorHash: string;\n try {\n const authAnchorBytes = await expandAuthAnchor(root);\n try {\n authAnchorHex = uint8ArrayToHex(authAnchorBytes);\n authAnchorHash = uint8ArrayToHex(sha256(authAnchorBytes));\n } finally {\n authAnchorBytes.fill(0);\n }\n } catch (err) {\n root.fill(0);\n throw err;\n }\n\n const derived = await expandPerVaultSecrets(root, params.amounts.length);\n const { perVaultWotsKeys, wotsPkHashes, htlcSecretHexes, hashlocks } =\n derived;\n\n const commit = await this.preparePeginCommit({\n depositorBtcPubkeyRaw,\n depositorBtcPubkey,\n hashlocks,\n authAnchorHash,\n sizing,\n params,\n });\n\n // Downstream consumers look up per-vault secrets by index; pin the\n // contract so a future WASM output-ordering change fails loud.\n for (let i = 0; i < commit.perVault.length; i++) {\n if (commit.perVault[i].htlcVout !== i) {\n throw new Error(\n `Internal invariant violation: htlcVout/index mismatch at vault ${i} ` +\n `(expected ${i}, got ${commit.perVault[i].htlcVout})`,\n );\n }\n }\n\n // Structural guarantee that the broadcast tx actually carries the\n // OP_RETURN we'll later reveal a preimage for. Without this assertion\n // a malicious WASM build could emit no OP_RETURN, the VP would still\n // issue a token (if mis-configured) on a tx with no on-chain\n // commitment, and the auth flow would degrade to a pure shared\n // secret. Fail closed.\n assertAuthAnchorOpReturn(\n commit.fundedPrePeginTxHex,\n params.amounts.length,\n authAnchorHash,\n );\n\n return {\n transaction: {\n ...commit,\n selectedUTXOs: sizing.selectedUTXOs,\n fee: sizing.fee,\n changeAmount: sizing.changeAmount,\n },\n depositorBtcPubkey,\n derivedSecrets: {\n perVaultWotsKeys,\n wotsPkHashes,\n htlcSecretHexes,\n authAnchorHex,\n },\n };\n }\n\n /**\n * Build unfunded Pre-PegIn + select UTXOs. No PSBT signing.\n *\n * Returns the full selection result (UTXOs, fee, changeAmount) so the\n * commit pass funds the broadcast tx with the exact same set used to\n * build the vault-context funding-outpoints commitment. Re-running\n * `selectUtxosForPegin` in the commit pass would be deterministic given\n * the same inputs, but threading the result through guarantees the\n * domain separator structurally matches the funded tx inputs.\n *\n * Sizing runs before the wallet popup, so neither the real per-vault\n * hashlocks nor the real `authAnchorHash` are known yet. Both slots\n * are filled with a 32-byte placeholder; the commit pass swaps in the\n * real values. Output budget is identical (32-byte push regardless of\n * content), so UTXO selection is invariant under substitution.\n */\n private async prepareSizing(\n depositorBtcPubkey: string,\n params: PreparePeginParams,\n ): Promise<{ selectedUTXOs: UTXO[]; fee: bigint; changeAmount: bigint }> {\n const placeholderHashlocks = params.amounts.map(\n () => SIZING_PASS_PLACEHOLDER_BYTES32_HEX,\n );\n const numLocalChallengers = params.vaultKeeperBtcPubkeys.length;\n\n const prePegin = await buildPrePeginPsbt({\n depositorPubkey: depositorBtcPubkey,\n vaultProviderPubkey: stripHexPrefix(params.vaultProviderBtcPubkey),\n vaultKeeperPubkeys: params.vaultKeeperBtcPubkeys.map(stripHexPrefix),\n universalChallengerPubkeys:\n params.universalChallengerBtcPubkeys.map(stripHexPrefix),\n hashlocks: placeholderHashlocks,\n timelockRefund: params.timelockRefund,\n pegInAmounts: params.amounts,\n feeRate: params.protocolFeeRate,\n numLocalChallengers,\n councilQuorum: params.councilQuorum,\n councilSize: params.councilSize,\n network: this.config.btcNetwork,\n authAnchorHash: SIZING_PASS_PLACEHOLDER_BYTES32_HEX,\n });\n\n const selection = selectUtxosForPegin(\n [...params.availableUTXOs],\n prePegin.totalOutputValue,\n params.mempoolFeeRate,\n peginOutputCount(\n prePegin.htlcValues.length,\n SIZING_PASS_PLACEHOLDER_BYTES32_HEX,\n ),\n );\n\n return {\n selectedUTXOs: selection.selectedUTXOs,\n fee: selection.fee,\n changeAmount: selection.changeAmount,\n };\n }\n\n /** Build PegIn txs and batch-sign their inputs with real hashlocks. */\n private async preparePeginCommit(args: {\n depositorBtcPubkeyRaw: string;\n depositorBtcPubkey: string;\n hashlocks: readonly string[];\n authAnchorHash: string;\n sizing: { selectedUTXOs: UTXO[]; fee: bigint; changeAmount: bigint };\n params: PreparePeginParams;\n }): Promise<{\n fundedPrePeginTxHex: string;\n prePeginTxid: string;\n perVault: PerVaultPeginData[];\n }> {\n const {\n depositorBtcPubkeyRaw,\n depositorBtcPubkey,\n hashlocks,\n authAnchorHash,\n sizing,\n params,\n } = args;\n\n // Refuse to build the broadcast tx if the orchestrator forgot to\n // substitute real values for the sizing-pass placeholder. A\n // placeholder-zero hashlock would produce an HTLC that no real\n // preimage can spend; a placeholder-zero auth anchor would let\n // the depositor reveal a known-public preimage to the VP. Fail\n // before signing, not after broadcast.\n const placeholderLower = SIZING_PASS_PLACEHOLDER_BYTES32_HEX.toLowerCase();\n for (let i = 0; i < hashlocks.length; i++) {\n if (hashlocks[i].toLowerCase() === placeholderLower) {\n throw new Error(\n `preparePeginCommit refusing to build with sizing-pass placeholder ` +\n `hashlock at vault ${i} — internal substitution bug`,\n );\n }\n }\n if (authAnchorHash.toLowerCase() === placeholderLower) {\n throw new Error(\n `preparePeginCommit refusing to build with sizing-pass placeholder ` +\n `auth-anchor hash — internal substitution bug`,\n );\n }\n\n const vaultProviderBtcPubkey = stripHexPrefix(params.vaultProviderBtcPubkey);\n const vaultKeeperBtcPubkeys = params.vaultKeeperBtcPubkeys.map(stripHexPrefix);\n const universalChallengerBtcPubkeys =\n params.universalChallengerBtcPubkeys.map(stripHexPrefix);\n const numLocalChallengers = vaultKeeperBtcPubkeys.length;\n\n const prePeginParams: PrePeginParams = {\n depositorPubkey: depositorBtcPubkey,\n vaultProviderPubkey: vaultProviderBtcPubkey,\n vaultKeeperPubkeys: vaultKeeperBtcPubkeys,\n universalChallengerPubkeys: universalChallengerBtcPubkeys,\n hashlocks,\n timelockRefund: params.timelockRefund,\n pegInAmounts: params.amounts,\n feeRate: params.protocolFeeRate,\n numLocalChallengers,\n councilQuorum: params.councilQuorum,\n councilSize: params.councilSize,\n network: this.config.btcNetwork,\n authAnchorHash,\n };\n\n const prePeginResult = await buildPrePeginPsbt(prePeginParams);\n\n const network = getNetwork(this.config.btcNetwork);\n const fundedPrePeginTxHex = fundPeginTransaction({\n unfundedTxHex: prePeginResult.psbtHex,\n selectedUTXOs: sizing.selectedUTXOs,\n changeAddress: params.changeAddress,\n changeAmount: sizing.changeAmount,\n network,\n });\n\n const prePeginTxid = stripHexPrefix(calculateBtcTxHash(fundedPrePeginTxHex));\n\n const peginTxResults: Array<{\n txHex: string;\n txid: string;\n vaultScriptPubKey: string;\n }> = [];\n const psbtsToSign: string[] = [];\n const signOptions: SignPsbtOptions[] = [];\n\n for (let i = 0; i < hashlocks.length; i++) {\n const peginTxResult = await buildPeginTxFromFundedPrePegin({\n prePeginParams,\n timelockPegin: params.timelockPegin,\n fundedPrePeginTxHex,\n htlcVout: i,\n });\n\n const peginInputPsbtResult = await buildPeginInputPsbt({\n peginTxHex: peginTxResult.txHex,\n fundedPrePeginTxHex,\n depositorPubkey: depositorBtcPubkey,\n vaultProviderPubkey: vaultProviderBtcPubkey,\n vaultKeeperPubkeys: vaultKeeperBtcPubkeys,\n universalChallengerPubkeys: universalChallengerBtcPubkeys,\n hashlock: hashlocks[i],\n timelockRefund: params.timelockRefund,\n network: this.config.btcNetwork,\n });\n\n peginTxResults.push(peginTxResult);\n psbtsToSign.push(peginInputPsbtResult.psbtHex);\n signOptions.push(\n createTaprootScriptPathSignOptions(depositorBtcPubkeyRaw, 1),\n );\n }\n\n const signedPsbts = await signPsbtsWithFallback(\n this.config.btcWallet,\n psbtsToSign,\n signOptions,\n );\n\n const perVault: PerVaultPeginData[] = [];\n for (let i = 0; i < signedPsbts.length; i++) {\n assertPsbtUnsignedTxMatches({\n requestedPsbtHex: psbtsToSign[i],\n returnedPsbtHex: signedPsbts[i],\n });\n\n const peginInputSignature = extractPeginInputSignature(\n signedPsbts[i],\n depositorBtcPubkey,\n );\n\n const depositorSignedPeginTxHex = finalizePeginInputPsbt(signedPsbts[i]);\n\n perVault.push({\n htlcVout: i,\n htlcValue: prePeginResult.htlcValues[i],\n peginTxHex: depositorSignedPeginTxHex,\n peginTxid: peginTxResults[i].txid,\n peginInputSignature,\n vaultScriptPubKey: peginTxResults[i].vaultScriptPubKey,\n });\n }\n\n return {\n fundedPrePeginTxHex,\n prePeginTxid,\n perVault,\n };\n }\n\n\n /**\n * Signs and broadcasts a funded peg-in transaction to the Bitcoin network.\n *\n * This method:\n * 1. Parses the funded transaction hex\n * 2. Fetches UTXO data from mempool for each input\n * 3. Creates a PSBT with proper witnessUtxo/tapInternalKey\n * 4. Signs via btcWallet.signPsbt()\n * 5. Finalizes and extracts the transaction\n * 6. Broadcasts via mempool API\n *\n * @param params - Transaction hex and depositor public key\n * @returns The broadcasted Bitcoin transaction ID\n * @throws Error if signing or broadcasting fails\n */\n async signAndBroadcast(params: SignAndBroadcastParams): Promise<string> {\n const { fundedPrePeginTxHex, depositorBtcPubkey } = params;\n\n // Step 1: Parse the funded transaction\n const cleanHex = fundedPrePeginTxHex.startsWith(\"0x\")\n ? fundedPrePeginTxHex.slice(2)\n : fundedPrePeginTxHex;\n const tx = Transaction.fromHex(cleanHex);\n\n if (tx.ins.length === 0) {\n throw new Error(\"Transaction has no inputs\");\n }\n\n // Step 2: Create PSBT and add inputs with UTXO data from mempool\n const psbt = new Psbt();\n psbt.setVersion(tx.version);\n psbt.setLocktime(tx.locktime);\n\n const publicKeyNoCoord = Buffer.from(\n normalizeXOnlyPubkey(depositorBtcPubkey),\n \"hex\",\n );\n const apiUrl = this.config.mempoolApiUrl;\n\n // Resolve prevout data for each input (local cache or mempool API)\n const utxoDataPromises = tx.ins.map((input) => {\n const txid = Buffer.from(input.hash).reverse().toString(\"hex\");\n const vout = input.index;\n return resolveUtxoInfo(txid, vout, params.localPrevouts, apiUrl).then(\n (utxoData) => ({ input, utxoData, txid, vout }),\n );\n });\n\n const inputsWithUtxoData = await Promise.all(utxoDataPromises);\n\n // Cross-validate: total input value must cover total output value.\n // A mismatch indicates the mempool API returned manipulated UTXO data,\n // which could lead to fee-siphoning or invalid signatures.\n const totalInputValue = inputsWithUtxoData.reduce(\n (sum, i) => sum + BigInt(i.utxoData.value),\n 0n,\n );\n const totalOutputValue = tx.outs.reduce(\n (sum, out) => sum + BigInt(out.value),\n 0n,\n );\n if (totalInputValue < totalOutputValue) {\n throw new Error(\n `UTXO value mismatch: total input value (${totalInputValue} sat) is less than ` +\n `total output value (${totalOutputValue} sat). ` +\n `This may indicate the mempool API returned manipulated UTXO data.`,\n );\n }\n\n const impliedFee = totalInputValue - totalOutputValue;\n if (impliedFee > MAX_REASONABLE_FEE_SATS) {\n throw new Error(\n `Implied transaction fee (${impliedFee} sat) exceeds maximum reasonable fee ` +\n `(${MAX_REASONABLE_FEE_SATS} sat). This may indicate manipulated UTXO data.`,\n );\n }\n\n // Add inputs with proper PSBT fields based on script type\n for (const { input, utxoData, txid, vout } of inputsWithUtxoData) {\n const psbtInputFields = getPsbtInputFields(\n {\n txid,\n vout,\n value: utxoData.value,\n scriptPubKey: utxoData.scriptPubKey,\n },\n publicKeyNoCoord,\n );\n\n psbt.addInput({\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n ...psbtInputFields,\n });\n }\n\n // Step 3: Add outputs\n for (const output of tx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n // Step 4: Sign PSBT via wallet\n const requestedPsbtHex = psbt.toHex();\n const signedPsbtHex =\n await this.config.btcWallet.signPsbt(requestedPsbtHex);\n\n assertPsbtUnsignedTxMatches({\n requestedPsbtHex,\n returnedPsbtHex: signedPsbtHex,\n });\n\n const signedPsbt = Psbt.fromHex(signedPsbtHex);\n\n // Step 5: Finalize and extract transaction\n try {\n signedPsbt.finalizeAllInputs();\n } catch (e) {\n // Some wallets (e.g. UniSat, OKX) auto-finalize PSBTs before returning them.\n // Attempting to finalize again throws, which is expected and safe to skip —\n // but verify the wallet actually finalized all inputs.\n const allFinalized = signedPsbt.data.inputs.every(\n (inp) => inp.finalScriptWitness || inp.finalScriptSig,\n );\n if (!allFinalized) {\n throw new Error(\n `PSBT finalization failed and wallet did not auto-finalize: ${e}`,\n );\n }\n }\n\n const signedTxHex = signedPsbt.extractTransaction().toHex();\n\n // Step 6: Broadcast to Bitcoin network\n const btcTxid = await pushTx(signedTxHex, apiUrl);\n\n return btcTxid;\n }\n\n /**\n * Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.\n *\n * This method:\n * 1. Re-verifies the PopSignature against the currently connected ETH\n * and BTC wallets — refuses to proceed if either has changed\n * 2. Derives vault ID and checks if it already exists (pre-flight)\n * 3. Encodes the contract call using viem\n * 4. Estimates gas (catches contract errors early with proper revert\n * reasons)\n * 5. Sends transaction with pre-estimated gas via\n * ethWallet.sendTransaction()\n *\n * The PopSignature must be obtained via\n * {@link signProofOfPossession} before this call.\n *\n * @param params - Registration parameters including the PopSignature\n * and the prepared Pre-PegIn / PegIn transactions\n * @returns Result containing Ethereum transaction hash and vault ID\n * @throws Error if the PopSignature does not match the connected wallets\n * @throws Error if the vault already exists\n * @throws Error if contract simulation fails (e.g., invalid signature,\n * unauthorized)\n */\n async registerPeginOnChain(\n params: RegisterPeginParams,\n ): Promise<RegisterPeginResult> {\n const {\n unsignedPrePeginTx,\n depositorSignedPeginTx,\n vaultProvider,\n hashlock,\n htlcVout,\n depositorPayoutBtcAddress,\n depositorWotsPkHash,\n popSignature,\n } = params;\n\n // Step 1: Re-verify the PoP artifact against the currently connected\n // wallets so a mid-flow account/wallet switch fails here instead of\n // surfacing downstream as an opaque contract revert.\n if (!this.config.ethWallet.account) {\n throw new Error(\"Ethereum wallet account not found\");\n }\n const depositorEthAddress = this.config.ethWallet.account.address;\n if (!isAddressEqual(popSignature.depositorEthAddress, depositorEthAddress)) {\n throw new Error(\n `Proof of possession was signed for ${popSignature.depositorEthAddress} ` +\n `but the Ethereum wallet is currently connected to ${depositorEthAddress}. ` +\n `Reconnect the original account or call signProofOfPossession() again.`,\n );\n }\n // The raw (parity-preserving) pubkey is required to validate P2WPKH\n // payout addresses; the x-only form on `popSignature` would let an\n // attacker substitute the opposite-parity P2WPKH address.\n const verifiedBtcPubkeyRaw =\n await this.assertPopMatchesBtcWallet(popSignature);\n const btcPopSignature = popSignature.btcPopSignature;\n\n // Step 2: Format parameters for contract call\n const depositorBtcPubkeyHex = ensureHexPrefix(popSignature.depositorBtcPubkey);\n const unsignedPrePeginTxHex = ensureHexPrefix(unsignedPrePeginTx);\n const depositorSignedPeginTxHex = ensureHexPrefix(depositorSignedPeginTx);\n\n // Only read the wallet address if the caller didn't supply one — avoids\n // an unnecessary adapter prompt on the common explicit-address path.\n const resolvedPayoutAddress =\n depositorPayoutBtcAddress ?? (await this.config.btcWallet.getAddress());\n const payoutScriptPubKey = this.resolvePayoutScriptPubKey(\n verifiedBtcPubkeyRaw,\n resolvedPayoutAddress,\n );\n\n // Step 3: Calculate pegin tx hash and derive vault ID, then check if it already exists\n const peginTxHash = calculateBtcTxHash(depositorSignedPeginTxHex);\n const derivedVaultIdHex = await deriveVaultId(\n stripHexPrefix(peginTxHash),\n stripHexPrefix(depositorEthAddress),\n );\n const vaultId = ensureHexPrefix(derivedVaultIdHex) as Hex;\n const exists = await this.checkVaultExists(vaultId);\n\n if (exists) {\n throw new Error(\n `Vault already exists (ID: ${vaultId}, peginTxHash: ${peginTxHash}). ` +\n `Vault IDs are derived from the pegin transaction hash and depositor address. ` +\n `To create a new vault, use different UTXOs or a different amount to generate a unique transaction.`,\n );\n }\n\n // Step 4: Query required pegin fee from the contract\n const publicClient = this.config.publicClient;\n\n let peginFee: bigint;\n try {\n peginFee = (await publicClient.readContract({\n address: this.config.vaultContracts.btcVaultRegistry,\n abi: BTCVaultRegistryABI,\n functionName: \"getPegInFee\",\n args: [vaultProvider],\n })) as bigint;\n } catch (error) {\n throw new Error(\n \"Failed to query pegin fee from the contract. \" +\n \"Please check your network connection and that the contract address is correct.\",\n { cause: error },\n );\n }\n\n // Step 5: Encode the contract call data\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequest\",\n args: [\n depositorEthAddress,\n depositorBtcPubkeyHex,\n btcPopSignature,\n unsignedPrePeginTxHex,\n depositorSignedPeginTxHex,\n vaultProvider,\n hashlock,\n htlcVout,\n payoutScriptPubKey,\n depositorWotsPkHash,\n ],\n });\n\n // Step 6: Estimate gas first to catch contract errors before showing wallet popup\n // This ensures users see actual contract revert reasons instead of gas errors\n // The gas estimate is then passed to sendTransaction to avoid double estimation\n let gasEstimate: bigint;\n try {\n gasEstimate = await publicClient.estimateGas({\n to: this.config.vaultContracts.btcVaultRegistry,\n data: callData,\n value: peginFee,\n account: this.config.ethWallet.account.address,\n });\n } catch (error) {\n // Estimation failed - handle contract error with actual revert reason\n handleContractError(error); // always throws (return type: never)\n }\n\n // Step 7: Submit peg-in request to contract (estimation passed)\n let ethTxHash: Hex;\n try {\n // Send transaction with pre-estimated gas to skip internal estimation\n // Note: viem's sendTransaction uses `gas`, not `gasLimit`\n ethTxHash = await this.config.ethWallet.sendTransaction({\n to: this.config.vaultContracts.btcVaultRegistry,\n data: callData,\n value: peginFee,\n account: this.config.ethWallet.account,\n chain: this.config.ethChain,\n gas: gasEstimate,\n });\n } catch (error) {\n // Use proper error handler for better error messages\n handleContractError(error); // always throws (return type: never)\n }\n\n // Step 8: Wait for transaction receipt and verify it was not reverted.\n // Smart-account-aware wrapper so Safe-style multisigs work alongside\n // Externally Owned Accounts (EOAs — wallets controlled by a single\n // private key, e.g. MetaMask). The EOA path is unchanged.\n const receipt = await waitForTransactionReceiptSmartAware({\n publicClient,\n walletAddress: this.config.ethWallet.account.address,\n hash: ethTxHash,\n timeout: RECEIPT_TIMEOUT_MS,\n });\n if (receipt.status === \"reverted\") {\n handleContractError(\n new Error(\n `Transaction reverted. Hash: ${receipt.transactionHash}. ` +\n `Check the transaction on block explorer for details.`,\n ),\n );\n }\n\n return {\n ethTxHash: receipt.transactionHash,\n vaultId,\n peginTxHash,\n };\n }\n\n /**\n * Register multiple pegins on Ethereum in a single transaction.\n *\n * Uses the contract's submitPeginRequestBatch() to submit all vault\n * registrations atomically. All vaults must share the same vault provider.\n * The PoP signature is signed once and included in each request.\n *\n * @param params - Batch registration parameters\n * @returns Batch result with per-vault IDs and single ETH tx hash\n */\n async registerPeginBatchOnChain(\n params: RegisterPeginBatchParams,\n ): Promise<RegisterPeginBatchResult> {\n const { vaultProvider, unsignedPrePeginTx, requests, popSignature } =\n params;\n\n if (requests.length === 0) {\n throw new Error(\"Batch pegin requires at least one request\");\n }\n\n // Step 1: Re-verify the PoP (same reasoning as registerPeginOnChain).\n if (!this.config.ethWallet.account) {\n throw new Error(\"Ethereum wallet account not found\");\n }\n const depositorEthAddress = this.config.ethWallet.account.address;\n if (!isAddressEqual(popSignature.depositorEthAddress, depositorEthAddress)) {\n throw new Error(\n `Proof of possession was signed for ${popSignature.depositorEthAddress} ` +\n `but the Ethereum wallet is currently connected to ${depositorEthAddress}. ` +\n `Reconnect the original account or call signProofOfPossession() again.`,\n );\n }\n // The raw (parity-preserving) pubkey is required to validate P2WPKH\n // payout addresses; the x-only form on `popSignature` would let an\n // attacker substitute the opposite-parity P2WPKH address.\n const verifiedBtcPubkeyRaw =\n await this.assertPopMatchesBtcWallet(popSignature);\n const btcPopSignature = popSignature.btcPopSignature;\n\n // Step 2: Resolve per-request payout scriptPubKey. The verified pubkey\n // comes from the just-checked PoP; `depositorPayoutBtcAddress` is\n // required per-request, so no wallet read is needed here.\n const resolvedPayoutScripts: Hex[] = requests.map((req) =>\n this.resolvePayoutScriptPubKey(\n verifiedBtcPubkeyRaw,\n req.depositorPayoutBtcAddress,\n ),\n );\n\n // Step 3: Pre-compute vault IDs and check for duplicates\n const vaultResults: BatchPeginResultItem[] = [];\n for (const req of requests) {\n const depositorSignedPeginTxHex = ensureHexPrefix(\n req.depositorSignedPeginTx,\n );\n const peginTxHash = calculateBtcTxHash(depositorSignedPeginTxHex);\n const derivedVaultIdHex = await deriveVaultId(\n stripHexPrefix(peginTxHash),\n stripHexPrefix(depositorEthAddress),\n );\n const vaultId = ensureHexPrefix(derivedVaultIdHex) as Hex;\n const exists = await this.checkVaultExists(vaultId);\n if (exists) {\n throw new Error(\n `Vault already exists (ID: ${vaultId}, peginTxHash: ${peginTxHash}). ` +\n `To create a new vault, use different UTXOs or a different amount.`,\n );\n }\n vaultResults.push({ vaultId, peginTxHash });\n }\n\n // Step 4: Query pegin fee and compute total\n const publicClient = this.config.publicClient;\n\n let peginFee: bigint;\n try {\n peginFee = (await publicClient.readContract({\n address: this.config.vaultContracts.btcVaultRegistry,\n abi: BTCVaultRegistryABI,\n functionName: \"getPegInFee\",\n args: [vaultProvider],\n })) as bigint;\n } catch (error) {\n throw new Error(\n \"Failed to query pegin fee from the contract. \" +\n \"Please check your network connection and that the contract address is correct.\",\n { cause: error },\n );\n }\n const totalFee = peginFee * BigInt(requests.length);\n\n // Step 5: Build BatchPeginRequest[] tuple array. Depositor BTC pubkey,\n // PoP, and Pre-PegIn tx hex are shared across the batch (carried on\n // the top-level params / PopSignature, not per request).\n const depositorBtcPubkeyHex = ensureHexPrefix(\n popSignature.depositorBtcPubkey,\n ) as Hex;\n const unsignedPrePeginTxHex = ensureHexPrefix(unsignedPrePeginTx) as Hex;\n const batchRequests = requests.map((req, i) => ({\n depositorBtcPubKey: depositorBtcPubkeyHex,\n btcPopSignature,\n unsignedPrePeginTx: unsignedPrePeginTxHex,\n depositorSignedPeginTx: ensureHexPrefix(\n req.depositorSignedPeginTx,\n ) as Hex,\n hashlock: req.hashlock,\n htlcVout: req.htlcVout,\n referralCode: NO_REFERRAL_CODE,\n depositorPayoutBtcAddress: resolvedPayoutScripts[i],\n depositorWotsPkHash: req.depositorWotsPkHash,\n }));\n\n // Step 6: Encode batch call data\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequestBatch\",\n args: [depositorEthAddress, vaultProvider, batchRequests],\n });\n\n // Step 7: Estimate gas\n let gasEstimate: bigint;\n try {\n gasEstimate = await publicClient.estimateGas({\n to: this.config.vaultContracts.btcVaultRegistry,\n data: callData,\n value: totalFee,\n account: this.config.ethWallet.account.address,\n });\n } catch (error) {\n handleContractError(error); // always throws (return type: never)\n }\n\n // Step 8: Submit batch transaction\n let ethTxHash: Hex;\n try {\n ethTxHash = await this.config.ethWallet.sendTransaction({\n to: this.config.vaultContracts.btcVaultRegistry,\n data: callData,\n value: totalFee,\n account: this.config.ethWallet.account,\n chain: this.config.ethChain,\n gas: gasEstimate,\n });\n } catch (error) {\n handleContractError(error); // always throws (return type: never)\n }\n\n // Step 9: Wait for receipt\n // Use the smart-account-aware wrapper so Safe-style wallets (whose\n // `eth_sendTransaction` returns a `safeTxHash`, not a real tx hash) work\n // alongside Externally Owned Accounts (EOAs — wallets controlled by a\n // single private key, e.g. MetaMask). The EOA path is unchanged.\n const receipt = await waitForTransactionReceiptSmartAware({\n publicClient,\n walletAddress: this.config.ethWallet.account.address,\n hash: ethTxHash,\n timeout: RECEIPT_TIMEOUT_MS,\n });\n if (receipt.status === \"reverted\") {\n handleContractError(\n new Error(\n `Batch transaction reverted. Hash: ${receipt.transactionHash}. ` +\n `Check the transaction on block explorer for details.`,\n ),\n );\n }\n\n return {\n ethTxHash: receipt.transactionHash,\n vaults: vaultResults,\n };\n }\n\n /**\n * Check if a vault already exists for a given vault ID.\n *\n * The contract returns a default struct (with `depositor === zeroAddress`)\n * when no vault is registered, so existence is signalled in the response,\n * not via a thrown error. RPC/network failures are propagated rather than\n * silently treated as \"vault doesn't exist\", which would otherwise let\n * downstream calls run with stale assumptions.\n *\n * @param vaultId - The Bitcoin transaction hash (vault ID)\n * @returns True if vault exists, false otherwise\n * @throws If the underlying RPC read fails\n */\n private async checkVaultExists(vaultId: Hex): Promise<boolean> {\n const publicClient = this.config.publicClient;\n\n const result = (await publicClient.readContract({\n address: this.config.vaultContracts.btcVaultRegistry,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n })) as { depositor: Address };\n\n return result.depositor !== zeroAddress;\n }\n\n /**\n * Resolve the BTC scriptPubKey to register as the depositor's payout sink.\n *\n * `address` is validated against the verified depositor pubkey, sourced\n * from `assertPopMatchesBtcWallet`'s return value rather than\n * `popSignature.depositorBtcPubkey` (which is x-only, parity stripped).\n * For wallets that expose a compressed key this preserves y-parity end to\n * end. For Taproot wallets that only expose an x-only key, the helper\n * itself fails closed for P2WPKH — the parity is unknowable, so the\n * payout sink must be a P2TR address derived from that same x.\n *\n * The helper does not call into the wallet so the batch path can resolve\n * many requests without any extra adapter reads. Threat closed: a\n * state-race or stale FE state that lets a non-wallet address reach the\n * on-chain payout-script registration.\n */\n private resolvePayoutScriptPubKey(\n verifiedDepositorBtcPubkeyRaw: string,\n address: string,\n ): Hex {\n if (\n !isAddressFromPublicKey(\n address,\n verifiedDepositorBtcPubkeyRaw,\n this.config.btcNetwork,\n )\n ) {\n throw new Error(\n `BTC payout address \"${address}\" is not derived from the connected ` +\n `wallet's public key. The payout sink must be controlled by the same ` +\n `key that signs the pegin; refusing to register a mismatched address.`,\n );\n }\n\n const network = getNetwork(this.config.btcNetwork);\n try {\n return `0x${bitcoin.address.toOutputScript(address, network).toString(\"hex\")}` as Hex;\n } catch {\n throw new Error(\n `Invalid BTC payout address: \"${address}\". ` +\n `Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`,\n );\n }\n }\n\n /**\n * Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC\n * wallet to the connected ETH account for this chain and vault\n * registry. The returned {@link PopSignature} can be reused across\n * every register call in the same session.\n */\n async signProofOfPossession(): Promise<PopSignature> {\n if (!this.config.ethWallet.account) {\n throw new Error(\"Ethereum wallet account not found\");\n }\n const depositorEthAddress = this.config.ethWallet.account.address;\n\n const depositorBtcPubkey = normalizeXOnlyPubkey(\n await this.config.btcWallet.getPublicKeyHex(),\n );\n\n // Message format matches BTCProofOfPossession.sol buildMessage()\n const verifyingContract = this.config.vaultContracts.btcVaultRegistry;\n const popMessage = `${depositorEthAddress.toLowerCase()}:${this.config.ethChain.id}:pegin:${verifyingContract.toLowerCase()}`;\n const raw = await this.config.btcWallet.signMessage(\n popMessage,\n \"bip322-simple\",\n );\n\n return {\n btcPopSignature: normalizePopSignature(raw),\n depositorEthAddress,\n depositorBtcPubkey,\n };\n }\n\n /**\n * Confirm the connected BTC wallet still matches the PoP it produced, and\n * return the wallet's *raw* pubkey hex (parity-preserving form, as the\n * wallet adapter returns it). The raw form is required by callers that\n * validate Native SegWit / P2WPKH addresses, since P2WPKH is derived from\n * a parity-bearing compressed key — an x-only form would let an attacker\n * substitute the opposite-parity P2WPKH address.\n */\n private async assertPopMatchesBtcWallet(\n popSignature: PopSignature,\n ): Promise<string> {\n const currentBtcPubkeyRaw = await this.config.btcWallet.getPublicKeyHex();\n const currentBtcPubkey = normalizeXOnlyPubkey(currentBtcPubkeyRaw);\n // Normalize the PoP-embedded key the same way in case a consumer\n // serialized it through a path that changed casing or re-added 0x.\n const popBtcPubkey = normalizeXOnlyPubkey(popSignature.depositorBtcPubkey);\n if (currentBtcPubkey !== popBtcPubkey) {\n throw new Error(\n `Proof of possession was signed with BTC pubkey ${popBtcPubkey} ` +\n `but the BTC wallet is currently connected to ${currentBtcPubkey}. ` +\n `Reconnect the original wallet or call signProofOfPossession() again.`,\n );\n }\n return currentBtcPubkeyRaw;\n }\n\n /**\n * Gets the configured Bitcoin network.\n *\n * @returns The Bitcoin network (mainnet, testnet, signet, regtest)\n */\n getNetwork(): Network {\n return this.config.btcNetwork;\n }\n\n /**\n * Gets the configured BTCVaultRegistry contract address.\n *\n * @returns The Ethereum address of the BTCVaultRegistry contract\n */\n getVaultContractAddress(): Address {\n return this.config.vaultContracts.btcVaultRegistry;\n }\n}\n"],"names":["U32_MASK64","_32n","fromBig","le","split","lst","len","Ah","Al","i","h","l","rotlSH","s","rotlSL","rotlBH","rotlBL","OP_RETURN","OP_PUSH32","OP_RETURN_PUSH32_SCRIPT_LEN","assertAuthAnchorOpReturn","fundedPrePeginTxHex","vaultCount","expectedAuthAnchorHashHex","cleanHex","stripHexPrefix","tx","bitcoin","opReturnOutput","script","pushedHex","DEPOSITOR_PUBKEY_SIZE","TXID_SIZE","OUTPOINT_SIZE","COMMITMENT_SIZE","FIELD_LEN_PREFIX_SIZE","VAULT_CONTEXT_SIZE","writeUint32BE","out","offset","value","serializeOutpoint","outpoint","compareBytes","a","b","buildFundingOutpointsCommitment","outpoints","serialized","flat","sha256","buildVaultContext","input","commitment","VAULT_APP_NAME","ROOT_OUTPUT_BYTES","ROOT_OUTPUT_HEX_LEN","LOWERCASE_HEX_RE","deriveVaultRoot","wallet","vaultContext","contextHex","uint8ArrayToHex","rootHex","hexToUint8Array","Rho160","Id160","_","Pi160","idxLR","res","j","k","idxL","idxR","shifts160","shiftsL160","idx","shiftsR160","Kl160","Kr160","ripemd_f","group","x","y","z","BUF_160","_RIPEMD160","HashMD","__publicField","h0","h1","h2","h3","h4","view","al","ar","bl","br","cl","cr","dl","dr","el","er","rGroup","hbl","hbr","rl","rr","sl","sr","tl","rotl","tr","clean","ripemd160","createHasher","_0n","_1n","_2n","_7n","_256n","_0x71n","SHA3_PI","SHA3_ROTL","_SHA3_IOTA","round","R","t","IOTAS","SHA3_IOTA_H","SHA3_IOTA_L","rotlH","rotlL","keccakP","rounds","B","idx1","idx0","B0","B1","Th","Tl","curH","curL","shift","PI","Keccak","blockLen","suffix","outputLen","enableXOF","anumber","u32","swap32IfBE","data","aexists","abytes","state","pos","take","bufferOut","bytes","aoutput","to","genKeccak","info","keccak_256","WOTS_SEED_SIZE","CHAIN_ELEMENT_SIZE","WOTS_DIGIT_BITS","WOTS_CHECKSUM_DIGITS","CHECKSUM_MINOR_DIGIT_INDEX","CHECKSUM_MAJOR_DIGIT_INDEX","ASSERT_WOTS_BLOCK_DIGIT_COUNTS","toHex","hash160","maxDigitValue","d","defaultChecksumRadix","wMax","radix","createWotsConfig","chainStartForDigit","seed","digitIndex","suffixBytes","preimage","computeChainTerminal","start","steps","current","deriveBlockPublicKey","blockSeed","config","checksumMinorMax","checksumMajorMax","messageTerminals","digit","terminal","checksumMinorStart","checksumMinorTerminal","checksumMajorStart","checksumMajorTerminal","deriveWotsBlocksFromSeed","blocks","blockIdx","n","blockSeedInput","block","validateTerminal","label","computeWotsBlockPublicKeysHash","publicKeys","pk","totalTips","buffer","digest","expandPerVaultSecrets","root","perVaultWotsKeys","wotsPkHashes","htlcSecretHexes","hashlocks","wotsSeed","expandWotsSeed","wotsPublicKeys","secretBytes","expandHashlockSecret","secretHex","computeHashlock","ensureHexPrefix","HEX_SIGNATURE_REGEX","UNPREFIXED_HEX_SIGNATURE_REGEX","BASE64_SIGNATURE_REGEX","normalizeXOnlyPubkey","raw","processPublicKeyToXOnly","normalizePopSignature","Buffer","signPsbtsWithFallback","psbtsHexes","options","signedPsbts","signed","NO_REFERRAL_CODE","SIZING_PASS_PLACEHOLDER_BYTES32_HEX","resolveUtxoInfo","txid","vout","localPrevouts","apiUrl","local","getUtxoInfo","RECEIPT_TIMEOUT_MS","PeginManager","params","depositorBtcPubkeyRaw","depositorBtcPubkey","isAddressFromPublicKey","sizing","fundingOutpoints","u","authAnchorHex","authAnchorHash","authAnchorBytes","expandAuthAnchor","err","derived","commit","placeholderHashlocks","numLocalChallengers","prePegin","buildPrePeginPsbt","selection","selectUtxosForPegin","peginOutputCount","args","placeholderLower","vaultProviderBtcPubkey","vaultKeeperBtcPubkeys","universalChallengerBtcPubkeys","prePeginParams","prePeginResult","network","getNetwork","fundPeginTransaction","prePeginTxid","calculateBtcTxHash","peginTxResults","psbtsToSign","signOptions","peginTxResult","buildPeginTxFromFundedPrePegin","peginInputPsbtResult","buildPeginInputPsbt","createTaprootScriptPathSignOptions","perVault","assertPsbtUnsignedTxMatches","peginInputSignature","extractPeginInputSignature","depositorSignedPeginTxHex","finalizePeginInputPsbt","Transaction","psbt","Psbt","publicKeyNoCoord","utxoDataPromises","utxoData","inputsWithUtxoData","totalInputValue","sum","totalOutputValue","impliedFee","MAX_REASONABLE_FEE_SATS","psbtInputFields","getPsbtInputFields","output","requestedPsbtHex","signedPsbtHex","signedPsbt","e","inp","signedTxHex","pushTx","unsignedPrePeginTx","depositorSignedPeginTx","vaultProvider","hashlock","htlcVout","depositorPayoutBtcAddress","depositorWotsPkHash","popSignature","depositorEthAddress","isAddressEqual","verifiedBtcPubkeyRaw","btcPopSignature","depositorBtcPubkeyHex","unsignedPrePeginTxHex","resolvedPayoutAddress","payoutScriptPubKey","peginTxHash","derivedVaultIdHex","deriveVaultId","vaultId","publicClient","peginFee","BTCVaultRegistryABI","error","callData","encodeFunctionData","gasEstimate","handleContractError","ethTxHash","receipt","waitForTransactionReceiptSmartAware","requests","resolvedPayoutScripts","req","vaultResults","totalFee","batchRequests","zeroAddress","verifiedDepositorBtcPubkeyRaw","address","verifyingContract","popMessage","currentBtcPubkeyRaw","currentBtcPubkey","popBtcPubkey"],"mappings":"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","x_google_ignoreList":[0,4,5]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const B=require("@babylonlabs-io/babylon-tbv-rust-wasm"),f=require("buffer"),p=require("bitcoinjs-lib"),a=require("./bitcoin-CHfKAhcI.cjs");async function m(t){const r=await B.createPayoutConnector({depositor:t.depositor,vaultProvider:t.vaultProvider,vaultKeepers:t.vaultKeepers,universalChallengers:t.universalChallengers,timelockPegin:t.timelockPegin},t.network);return{payoutScript:r.payoutScript,taprootScriptHash:r.taprootScriptHash,scriptPubKey:r.scriptPubKey,address:r.address,payoutControlBlock:r.payoutControlBlock}}const E=3;async function I(t){const r=a.stripHexPrefix(t.payoutTxHex),e=a.stripHexPrefix(t.peginTxHex),n=a.stripHexPrefix(t.assertTxHex),o=await m({depositor:t.depositorBtcPubkey,vaultProvider:t.vaultProviderBtcPubkey,vaultKeepers:t.vaultKeeperBtcPubkeys,universalChallengers:t.universalChallengerBtcPubkeys,timelockPegin:t.timelockPegin,network:t.network}),s=a.hexToUint8Array(o.payoutScript),i=a.hexToUint8Array(o.payoutControlBlock),u=p.Transaction.fromHex(r),$=p.Transaction.fromHex(e),v=p.Transaction.fromHex(n),l=new p.Psbt;if(l.setVersion(u.version),l.setLocktime(u.locktime),u.ins.length!==2)throw new Error(`Payout transaction must have exactly 2 inputs, got ${u.ins.length}`);const d=u.ins[0],h=u.ins[1],x=a.uint8ArrayToHex(new Uint8Array(d.hash).slice().reverse()),S=$.getId();if(x!==S)throw new Error(`Input 0 does not reference pegin transaction. Expected ${S}, got ${x}`);const g=a.uint8ArrayToHex(new Uint8Array(h.hash).slice().reverse()),b=v.getId();if(g!==b)throw new Error(`Input 1 does not reference assert transaction. Expected ${b}, got ${g}`);const y=$.outs[d.index];if(!y)throw new Error(`Previous output not found for input 0 (txid: ${x}, index: ${d.index})`);const w=v.outs[h.index];if(!w)throw new Error(`Previous output not found for input 1 (txid: ${g}, index: ${h.index})`);l.addInput({hash:d.hash,index:d.index,sequence:d.sequence,witnessUtxo:{script:y.script,value:y.value},tapLeafScript:[{leafVersion:a.TAPSCRIPT_LEAF_VERSION,script:f.Buffer.from(s),controlBlock:f.Buffer.from(i)}],tapInternalKey:f.Buffer.from(B.tapInternalPubkey)}),l.addInput({hash:h.hash,index:h.index,sequence:h.sequence,witnessUtxo:{script:w.script,value:w.value}});for(const T of u.outs)l.addOutput({script:T.script,value:T.value});return{psbtHex:l.toHex()}}function O(t,r){if(!a.isValidHex(r))throw new Error("Invalid registeredPayoutScriptPubKey: not valid hex");const e=f.Buffer.from(a.stripHexPrefix(r),"hex"),n=p.Transaction.fromHex(a.stripHexPrefix(t));if(n.outs.length===0)throw new Error("Payout transaction has no outputs");if(!n.outs.reduce((s,i)=>i.value>s.value?i:s).script.equals(e))throw new Error("Payout transaction does not pay to the registered depositor payout address")}function A(t,r,e=0){const n=p.Psbt.fromHex(t);if(e>=n.data.inputs.length)throw new Error(`Input index ${e} out of range (${n.data.inputs.length} inputs)`);const o=n.data.inputs[e];if(o.tapScriptSig&&o.tapScriptSig.length>0){const s=a.hexToUint8Array(r);for(const i of o.tapScriptSig)if(i.pubkey.equals(f.Buffer.from(s)))return H(i.signature,e);throw new Error(`No signature found for depositor pubkey: ${r} at input ${e}`)}if(o.finalScriptWitness&&o.finalScriptWitness.length>0){const s=U(o.finalScriptWitness);if(s.length!==E)throw new Error(`Unexpected finalized witness stack size at input ${e}: expected ${E} items (signature, script, controlBlock), got ${s.length}`);return H(s[0],e)}throw new Error(`No tapScriptSig or finalScriptWitness found in signed PSBT at input ${e}`)}function H(t,r){if(t.length===64)return a.uint8ArrayToHex(new Uint8Array(t));throw t.length===65?new Error(`Unexpected sighash byte 0x${t[64].toString(16).padStart(2,"0")} at input ${r}. Expected implicit SIGHASH_DEFAULT as a 64-byte signature.`):new Error(`Unexpected signature length at input ${r}: ${t.length}`)}function U(t){const r=[];let e=0;const n=i=>{if(e+i>t.length)throw new Error(`Malformed witness data: need ${i} byte(s) at offset ${e}, only ${t.length-e} remaining`)},o=()=>{n(1);const i=t[e++];if(i<253)return i;if(i===253){n(2);const u=(t[e]|t[e+1]<<8)>>>0;return e+=2,u}if(i===254){n(4);const u=(t[e]|t[e+1]<<8|t[e+2]<<16|t[e+3]<<24)>>>0;return e+=4,u}throw new Error(`Malformed witness data: 8-byte varint (0xff) not supported at offset ${e-1}`)},s=o();for(let i=0;i<s;i++){const u=o();n(u),r.push(f.Buffer.from(t.subarray(e,e+u))),e+=u}if(e!==t.length)throw new Error(`Malformed witness data: ${t.length-e} trailing byte(s) after parsing ${s} item(s)`);return r}class c extends Error{constructor(r){super(`Wallet returned a PSBT for a different transaction: ${r}`),this.name="PsbtSubstitutionError"}}function k(t,r){try{return p.Psbt.fromHex(r)}catch(e){const n=e instanceof Error?e.message:String(e);throw new Error(`Failed to parse ${t} PSBT: ${n}`)}}const C=8;function P(t){return`${t.toString("hex").slice(0,C)}…`}function q(t){const r=f.Buffer.from(t).reverse();return P(r)}function _(t){const r=k("requested",t.requestedPsbtHex),e=k("returned",t.returnedPsbtHex);if(r.version!==e.version)throw new c(`tx version differs (requested=${r.version}, returned=${e.version})`);if(r.locktime!==e.locktime)throw new c(`tx locktime differs (requested=${r.locktime}, returned=${e.locktime})`);if(r.txInputs.length!==e.txInputs.length)throw new c(`input count differs (requested=${r.txInputs.length}, returned=${e.txInputs.length})`);if(r.txOutputs.length!==e.txOutputs.length)throw new c(`output count differs (requested=${r.txOutputs.length}, returned=${e.txOutputs.length})`);for(let n=0;n<r.txInputs.length;n++){const o=r.txInputs[n],s=e.txInputs[n];if(!o.hash.equals(s.hash))throw new c(`input ${n} prevout txid differs (requested=${q(o.hash)}, returned=${q(s.hash)})`);if(o.index!==s.index)throw new c(`input ${n} prevout vout differs (requested=${o.index}, returned=${s.index})`);if(o.sequence!==s.sequence)throw new c(`input ${n} sequence differs (requested=${o.sequence}, returned=${s.sequence})`)}for(let n=0;n<r.txOutputs.length;n++){const o=r.txOutputs[n],s=e.txOutputs[n];if(!o.script.equals(s.script))throw new c(`output ${n} scriptPubKey differs (requested=${P(o.script)}, returned=${P(s.script)})`);if(o.value!==s.value)throw new c(`output ${n} value differs (requested=${o.value}, returned=${s.value})`)}}exports.PsbtSubstitutionError=c;exports.assertPayoutOutputMatchesRegistered=O;exports.assertPsbtUnsignedTxMatches=_;exports.buildPayoutPsbt=I;exports.createPayoutScript=m;exports.extractPayoutSignature=A;
|
|
2
|
+
//# sourceMappingURL=assertPsbtUnsignedTxMatches-BoHwgW30.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertPsbtUnsignedTxMatches-BoHwgW30.cjs","sources":["../src/tbv/core/primitives/scripts/payout.ts","../src/tbv/core/primitives/psbt/payout.ts","../src/tbv/core/primitives/psbt/assertPsbtUnsignedTxMatches.ts"],"sourcesContent":["/**\n * Payout Script Generator Primitive\n *\n * This module provides pure functions for generating payout scripts and taproot information\n * by wrapping the WASM implementation from @babylonlabs-io/babylon-tbv-rust-wasm.\n *\n * The payout script is used for signing payout transactions in the vault system.\n * It defines the spending conditions for the vault output, enabling the depositor\n * to authorize payouts during the peg-in flow (Step 3).\n *\n * @remarks\n * This is a low-level primitive. For most use cases, prefer using {@link buildPayoutPsbt}\n * which handles script creation internally. For high-level wallet orchestration, use\n * PayoutManager from the managers module.\n *\n * @see {@link buildPayoutPsbt} - Higher-level function that uses this internally\n *\n * @module primitives/scripts/payout\n */\n\nimport {\n createPayoutConnector,\n type Network,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\n\n/**\n * Parameters for creating a payout script.\n *\n * These parameters define the participants in a vault and are used to generate\n * the taproot script that controls how funds can be spent from the vault.\n */\nexport interface PayoutScriptParams {\n /**\n * Depositor's BTC public key (x-only, 64-char hex without 0x prefix).\n *\n * This is the user depositing BTC into the vault. The depositor must sign\n * payout transactions to authorize fund distribution.\n */\n depositor: string;\n\n /**\n * Vault provider's BTC public key (x-only, 64-char hex without 0x prefix).\n *\n * The service provider managing vault operations. Also referred to as\n * \"claimer\" in the WASM layer.\n */\n vaultProvider: string;\n\n /**\n * Array of vault keeper BTC public keys (x-only, 64-char hex without 0x prefix).\n *\n * Vault keepers participate in vault operations and script spending conditions.\n */\n vaultKeepers: string[];\n\n /**\n * Array of universal challenger BTC public keys (x-only, 64-char hex without 0x prefix).\n *\n * These parties can challenge the vault under certain conditions.\n */\n universalChallengers: string[];\n\n /**\n * CSV timelock in blocks for the PegIn output.\n */\n timelockPegin: number;\n\n /**\n * Bitcoin network for script generation.\n *\n * Must match the network used for all other vault operations to ensure\n * address encoding compatibility.\n */\n network: Network;\n}\n\n/**\n * Result of creating a payout script.\n *\n * Contains all the taproot-related data needed for constructing and signing\n * payout transactions from the vault.\n */\nexport interface PayoutScriptResult {\n /**\n * The payout script hex used in taproot script path spending.\n *\n * This is the raw script bytes that define the spending conditions,\n * encoded as a hexadecimal string. Used when constructing the\n * tapLeafScript for PSBT signing.\n */\n payoutScript: string;\n\n /**\n * The taproot script hash (leaf hash) for the payout script.\n *\n * This is the tagged hash of the script used in taproot tree construction.\n * Required for computing the control block during script path spending.\n */\n taprootScriptHash: string;\n\n /**\n * The full scriptPubKey for the vault output address.\n *\n * This is the complete output script (OP_1 <32-byte-key>) that should be\n * used when creating the vault output in a peg-in transaction.\n */\n scriptPubKey: string;\n\n /**\n * The vault Bitcoin address derived from the script.\n *\n * A human-readable bech32m address (bc1p... for mainnet, tb1p... for testnet/signet)\n * that can be used to receive funds into the vault.\n */\n address: string;\n\n /**\n * Serialized control block for Taproot script path spend (hex encoded).\n *\n * Computed by the Rust WASM PeginPayoutConnector. Used directly in\n * tapLeafScript when building payout PSBTs.\n */\n payoutControlBlock: string;\n}\n\n/**\n * Create payout script and taproot information using WASM.\n *\n * This is a pure function that wraps the Rust WASM implementation.\n * The payout connector generates the necessary taproot scripts and information\n * required for signing payout transactions.\n *\n * @remarks\n * The generated script encodes spending conditions that require signatures from\n * the depositor and vault provider (or liquidators in challenge scenarios).\n * This script is used internally by {@link buildPayoutPsbt}.\n *\n * @param params - Payout script parameters defining vault participants and network\n * @returns Payout script and taproot information for PSBT construction\n *\n * @see {@link buildPayoutPsbt} - Use this for building complete payout PSBTs\n */\nexport async function createPayoutScript(\n params: PayoutScriptParams,\n): Promise<PayoutScriptResult> {\n // Call the WASM wrapper with the correct parameter structure\n const connector = await createPayoutConnector(\n {\n depositor: params.depositor,\n vaultProvider: params.vaultProvider,\n vaultKeepers: params.vaultKeepers,\n universalChallengers: params.universalChallengers,\n timelockPegin: params.timelockPegin,\n },\n params.network,\n );\n\n return {\n payoutScript: connector.payoutScript,\n taprootScriptHash: connector.taprootScriptHash,\n scriptPubKey: connector.scriptPubKey,\n address: connector.address,\n payoutControlBlock: connector.payoutControlBlock,\n };\n}\n","/**\n * Payout PSBT Builder Primitives\n *\n * This module provides pure functions for building unsigned payout PSBTs and extracting\n * Schnorr signatures from signed PSBTs. It uses WASM-generated scripts from the payout\n * connector and bitcoinjs-lib for PSBT construction.\n *\n * The Payout transaction references the Assert transaction (input 1).\n *\n * @module primitives/psbt/payout\n */\n\nimport {\n type Network,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\nimport { createPayoutScript } from \"../scripts/payout\";\nimport {\n TAPSCRIPT_LEAF_VERSION,\n hexToUint8Array,\n isValidHex,\n stripHexPrefix,\n uint8ArrayToHex,\n} from \"../utils/bitcoin\";\n\n/**\n * Number of items in a Taproot script-path spend witness stack for a\n * single-signature script: [signature, script, controlBlock].\n *\n * The current payout script requires exactly one depositor signature. If the\n * protocol evolves to require multiple signatures in the payout script, this\n * invariant and the finalized-PSBT extraction path must be revisited because\n * the first witness item would no longer necessarily be the depositor's.\n */\nconst TAPROOT_SINGLE_SIG_WITNESS_STACK_SIZE = 3;\n\n/**\n * Parameters for building an unsigned Payout PSBT\n *\n * Payout is used in the challenge path after Assert, when the claimer proves validity.\n * Input 1 references the Assert transaction.\n */\nexport interface PayoutParams {\n /**\n * Payout transaction hex (unsigned)\n * This is the transaction that needs to be signed by the depositor\n */\n payoutTxHex: string;\n\n /**\n * Assert transaction hex\n * Payout input 1 references Assert output 0\n */\n assertTxHex: string;\n\n /**\n * Peg-in transaction hex\n * This transaction created the vault output that we're spending\n */\n peginTxHex: string;\n\n /**\n * Depositor's BTC public key (x-only, 64-char hex without 0x prefix)\n */\n depositorBtcPubkey: string;\n\n /**\n * Vault provider's BTC public key (x-only, 64-char hex)\n */\n vaultProviderBtcPubkey: string;\n\n /**\n * Vault keeper BTC public keys (x-only, 64-char hex)\n */\n vaultKeeperBtcPubkeys: string[];\n\n /**\n * Universal challenger BTC public keys (x-only, 64-char hex)\n */\n universalChallengerBtcPubkeys: string[];\n\n /**\n * CSV timelock in blocks for the PegIn output.\n */\n timelockPegin: number;\n\n /**\n * Bitcoin network\n */\n network: Network;\n}\n\n/**\n * Result of building an unsigned payout PSBT\n */\nexport interface PayoutPsbtResult {\n /**\n * Unsigned PSBT hex ready for signing\n */\n psbtHex: string;\n}\n\n/**\n * Build unsigned Payout PSBT for depositor to sign.\n *\n * Payout is used in the **challenge path** when the claimer proves validity:\n * 1. Vault provider submits Claim transaction\n * 2. Challenge is raised during challenge period\n * 3. Claimer submits Assert transaction to prove validity\n * 4. Payout can be executed (references Assert tx)\n *\n * Payout transactions have the following structure:\n * - Input 0: from PeginTx output0 (signed by depositor)\n * - Input 1: from Assert output0 (NOT signed by depositor)\n *\n * @param params - Payout parameters\n * @returns Unsigned PSBT ready for depositor to sign\n *\n * @throws If payout transaction does not have exactly 2 inputs\n * @throws If input 0 does not reference the pegin transaction\n * @throws If input 1 does not reference the assert transaction\n * @throws If previous output is not found for either input\n */\nexport async function buildPayoutPsbt(\n params: PayoutParams,\n): Promise<PayoutPsbtResult> {\n // Normalize hex inputs (strip 0x prefix if present)\n const payoutTxHex = stripHexPrefix(params.payoutTxHex);\n const peginTxHex = stripHexPrefix(params.peginTxHex);\n const assertTxHex = stripHexPrefix(params.assertTxHex);\n\n // Get payout script from WASM\n const payoutConnector = await createPayoutScript({\n depositor: params.depositorBtcPubkey,\n vaultProvider: params.vaultProviderBtcPubkey,\n vaultKeepers: params.vaultKeeperBtcPubkeys,\n universalChallengers: params.universalChallengerBtcPubkeys,\n timelockPegin: params.timelockPegin,\n network: params.network,\n });\n\n const payoutScriptBytes = hexToUint8Array(payoutConnector.payoutScript);\n const controlBlock = hexToUint8Array(payoutConnector.payoutControlBlock);\n\n // Parse transactions\n const payoutTx = Transaction.fromHex(payoutTxHex);\n const peginTx = Transaction.fromHex(peginTxHex);\n const assertTx = Transaction.fromHex(assertTxHex);\n\n // Create PSBT\n const psbt = new Psbt();\n psbt.setVersion(payoutTx.version);\n psbt.setLocktime(payoutTx.locktime);\n\n // PayoutTx has exactly 2 inputs:\n // - Input 0: from PeginTx output0 (signed by depositor using taproot script path)\n // - Input 1: from Assert output0 (signed by claimer/challengers, not depositor)\n //\n // IMPORTANT: For Taproot SIGHASH_DEFAULT (0x00), the sighash commits to ALL inputs'\n // prevouts, not just the one being signed. Therefore, we must include BOTH inputs\n // in the PSBT so the wallet computes the correct sighash that the VP expects.\n\n // Verify payout transaction has expected structure\n if (payoutTx.ins.length !== 2) {\n throw new Error(\n `Payout transaction must have exactly 2 inputs, got ${payoutTx.ins.length}`,\n );\n }\n\n const input0 = payoutTx.ins[0];\n const input1 = payoutTx.ins[1];\n\n // Verify input 0 references the pegin transaction\n const input0Txid = uint8ArrayToHex(\n new Uint8Array(input0.hash).slice().reverse(),\n );\n const peginTxid = peginTx.getId();\n\n if (input0Txid !== peginTxid) {\n throw new Error(\n `Input 0 does not reference pegin transaction. ` +\n `Expected ${peginTxid}, got ${input0Txid}`,\n );\n }\n\n // Verify input 1 references the assert transaction\n const input1Txid = uint8ArrayToHex(\n new Uint8Array(input1.hash).slice().reverse(),\n );\n const expectedInput1Txid = assertTx.getId();\n\n if (input1Txid !== expectedInput1Txid) {\n throw new Error(\n `Input 1 does not reference assert transaction. ` +\n `Expected ${expectedInput1Txid}, got ${input1Txid}`,\n );\n }\n\n const peginPrevOut = peginTx.outs[input0.index];\n if (!peginPrevOut) {\n throw new Error(\n `Previous output not found for input 0 (txid: ${input0Txid}, index: ${input0.index})`,\n );\n }\n\n const input1PrevOut = assertTx.outs[input1.index];\n if (!input1PrevOut) {\n throw new Error(\n `Previous output not found for input 1 (txid: ${input1Txid}, index: ${input1.index})`,\n );\n }\n\n // Input 0: Depositor signs using Taproot script path spend\n // This input includes tapLeafScript for signing\n psbt.addInput({\n hash: input0.hash,\n index: input0.index,\n sequence: input0.sequence,\n witnessUtxo: {\n script: peginPrevOut.script,\n value: peginPrevOut.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(payoutScriptBytes),\n controlBlock: Buffer.from(controlBlock),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n // sighashType omitted - defaults to SIGHASH_DEFAULT (0x00) for Taproot\n });\n\n // Input 1: From Assert transaction (NOT signed by depositor)\n // We include this with witnessUtxo so the sighash is computed correctly,\n // but we do NOT include tapLeafScript since the depositor doesn't sign it.\n psbt.addInput({\n hash: input1.hash,\n index: input1.index,\n sequence: input1.sequence,\n witnessUtxo: {\n script: input1PrevOut.script,\n value: input1PrevOut.value,\n },\n // No tapLeafScript - depositor doesn't sign this input\n });\n\n // Add outputs\n for (const output of payoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return {\n psbtHex: psbt.toHex(),\n };\n}\n\n/**\n * Validate that a payout transaction's largest output pays to the registered\n * depositor payout scriptPubKey.\n *\n * Prevents a malicious vault provider from substituting the payout destination\n * (or routing funds through a dust output to the correct address while sending\n * the actual value to an attacker-controlled script).\n *\n * @param payoutTxHex - Raw payout transaction hex\n * @param registeredPayoutScriptPubKey - On-chain registered scriptPubKey (hex, with or without 0x prefix)\n * @throws If scriptPubKey is invalid hex\n * @throws If the transaction has no outputs\n * @throws If the largest output does not pay to the registered scriptPubKey\n */\nexport function assertPayoutOutputMatchesRegistered(\n payoutTxHex: string,\n registeredPayoutScriptPubKey: string,\n): void {\n if (!isValidHex(registeredPayoutScriptPubKey)) {\n throw new Error(\"Invalid registeredPayoutScriptPubKey: not valid hex\");\n }\n\n const expectedScript = Buffer.from(\n stripHexPrefix(registeredPayoutScriptPubKey),\n \"hex\",\n );\n const payoutTx = Transaction.fromHex(stripHexPrefix(payoutTxHex));\n\n if (payoutTx.outs.length === 0) {\n throw new Error(\"Payout transaction has no outputs\");\n }\n\n const largestOutput = payoutTx.outs.reduce((max, output) =>\n output.value > max.value ? output : max,\n );\n\n if (!largestOutput.script.equals(expectedScript)) {\n throw new Error(\n \"Payout transaction does not pay to the registered depositor payout address\",\n );\n }\n}\n\n/**\n * Extract Schnorr signature from signed payout PSBT.\n *\n * This function supports two cases:\n * 1. Non-finalized PSBT: Extracts from tapScriptSig field\n * 2. Finalized PSBT: Extracts from witness data\n *\n * The signature is returned as a 64-byte hex string (128 hex characters).\n * Payout signatures must use implicit Taproot SIGHASH_DEFAULT, which is\n * encoded by omitting the sighash byte.\n *\n * @param signedPsbtHex - Signed PSBT hex\n * @param depositorPubkey - Depositor's public key (x-only, 64-char hex)\n * @param inputIndex - Input index to extract signature from (default: 0)\n * @returns 64-byte Schnorr signature (128 hex characters, no sighash flag)\n *\n * @throws If no signature is found in the PSBT\n * @throws If the signature has an unexpected length\n */\nexport function extractPayoutSignature(\n signedPsbtHex: string,\n depositorPubkey: string,\n inputIndex = 0,\n): string {\n const signedPsbt = Psbt.fromHex(signedPsbtHex);\n\n if (inputIndex >= signedPsbt.data.inputs.length) {\n throw new Error(\n `Input index ${inputIndex} out of range (${signedPsbt.data.inputs.length} inputs)`,\n );\n }\n\n const input = signedPsbt.data.inputs[inputIndex];\n\n // Case 1: Non-finalized PSBT — extract from tapScriptSig\n if (input.tapScriptSig && input.tapScriptSig.length > 0) {\n const depositorPubkeyBytes = hexToUint8Array(depositorPubkey);\n\n for (const sigEntry of input.tapScriptSig) {\n if (sigEntry.pubkey.equals(Buffer.from(depositorPubkeyBytes))) {\n return extractSchnorrSig(sigEntry.signature, inputIndex);\n }\n }\n\n throw new Error(\n `No signature found for depositor pubkey: ${depositorPubkey} at input ${inputIndex}`,\n );\n }\n\n // Case 2: Finalized PSBT — extract from finalScriptWitness\n // Taproot single-signature script-path witness: [signature, script, controlBlock].\n // Enforce the exact stack size so that if a wallet produces an unexpected\n // finalization (e.g. a multi-signature stack, an annex, or malformed data),\n // we fail loudly instead of silently returning witnessStack[0] which may\n // not be the depositor's signature.\n if (input.finalScriptWitness && input.finalScriptWitness.length > 0) {\n const witnessStack = parseWitnessStack(input.finalScriptWitness);\n if (witnessStack.length !== TAPROOT_SINGLE_SIG_WITNESS_STACK_SIZE) {\n throw new Error(\n `Unexpected finalized witness stack size at input ${inputIndex}: ` +\n `expected ${TAPROOT_SINGLE_SIG_WITNESS_STACK_SIZE} items (signature, script, controlBlock), ` +\n `got ${witnessStack.length}`,\n );\n }\n return extractSchnorrSig(witnessStack[0], inputIndex);\n }\n\n throw new Error(\n `No tapScriptSig or finalScriptWitness found in signed PSBT at input ${inputIndex}`,\n );\n}\n\n/**\n * Extract and validate a 64-byte Schnorr signature.\n * Rejects 65-byte signatures because the appended sighash byte changes the\n * Taproot message being signed; stripping it would produce an unverifiable\n * SIGHASH_DEFAULT signature.\n * @internal\n */\nfunction extractSchnorrSig(sig: Uint8Array, inputIndex: number): string {\n if (sig.length === 64) {\n return uint8ArrayToHex(new Uint8Array(sig));\n }\n if (sig.length === 65) {\n throw new Error(\n `Unexpected sighash byte 0x${sig[64].toString(16).padStart(2, \"0\")} at input ${inputIndex}. ` +\n \"Expected implicit SIGHASH_DEFAULT as a 64-byte signature.\",\n );\n }\n throw new Error(\n `Unexpected signature length at input ${inputIndex}: ${sig.length}`,\n );\n}\n\n/**\n * Parse a BIP-141 serialized witness stack into individual stack items.\n * Format: [varint item_count] [varint len, data]...\n *\n * Throws on malformed input (truncated buffer, 8-byte varints, or trailing\n * bytes) so callers never receive silently-corrupted witness items.\n * @internal\n */\nfunction parseWitnessStack(witness: Buffer): Buffer[] {\n const items: Buffer[] = [];\n let offset = 0;\n\n const requireBytes = (n: number): void => {\n if (offset + n > witness.length) {\n throw new Error(\n `Malformed witness data: need ${n} byte(s) at offset ${offset}, only ${witness.length - offset} remaining`,\n );\n }\n };\n\n const readVarInt = (): number => {\n requireBytes(1);\n const first = witness[offset++];\n if (first < 0xfd) return first;\n if (first === 0xfd) {\n requireBytes(2);\n const val = (witness[offset] | (witness[offset + 1] << 8)) >>> 0;\n offset += 2;\n return val;\n }\n if (first === 0xfe) {\n requireBytes(4);\n const val =\n (witness[offset] |\n (witness[offset + 1] << 8) |\n (witness[offset + 2] << 16) |\n (witness[offset + 3] << 24)) >>>\n 0;\n offset += 4;\n return val;\n }\n // 0xff — 8-byte varint. Not used for witness sizes in practice and JS\n // numbers cannot represent all 64-bit values exactly, so reject rather\n // than risk silent truncation.\n throw new Error(\n `Malformed witness data: 8-byte varint (0xff) not supported at offset ${offset - 1}`,\n );\n };\n\n const count = readVarInt();\n for (let i = 0; i < count; i++) {\n const len = readVarInt();\n requireBytes(len);\n items.push(Buffer.from(witness.subarray(offset, offset + len)));\n offset += len;\n }\n\n if (offset !== witness.length) {\n throw new Error(\n `Malformed witness data: ${witness.length - offset} trailing byte(s) after parsing ${count} item(s)`,\n );\n }\n\n return items;\n}\n\n","/**\n * Asserts a wallet-returned PSBT encodes the same unsigned transaction\n * as the locally-built PSBT we asked the wallet to sign. Per-input PSBT\n * metadata (witnessUtxo, tapLeafScript, sighashType) is intentionally NOT\n * compared — those fields are committed to the Schnorr sighash and the\n * vault provider's `verify_depositor_signature` rejects mismatches there.\n * This primitive defends the path where a colluding VP would otherwise\n * accept a wallet-substituted signature.\n */\n\nimport { Buffer } from \"buffer\";\n\nimport { Psbt } from \"bitcoinjs-lib\";\n\n/**\n * Thrown when a wallet-returned PSBT encodes a different unsigned\n * transaction than the one the caller asked the wallet to sign.\n */\nexport class PsbtSubstitutionError extends Error {\n constructor(detail: string) {\n super(\n `Wallet returned a PSBT for a different transaction: ${detail}`,\n );\n this.name = \"PsbtSubstitutionError\";\n }\n}\n\nexport interface AssertPsbtUnsignedTxMatchesParams {\n /** PSBT we built locally and asked the wallet to sign. */\n requestedPsbtHex: string;\n /** PSBT the wallet returned after signing. */\n returnedPsbtHex: string;\n}\n\nfunction parsePsbt(label: \"requested\" | \"returned\", hex: string): Psbt {\n try {\n return Psbt.fromHex(hex);\n } catch (cause) {\n const reason = cause instanceof Error ? cause.message : String(cause);\n throw new Error(`Failed to parse ${label} PSBT: ${reason}`);\n }\n}\n\n/**\n * Length of the hex prefix included in mismatch errors. Short enough that\n * full prevout txids and output scriptPubKeys never reach logs / error\n * trackers, long enough to disambiguate during forensic triage.\n */\nconst REDACTED_HEX_PREFIX_LEN = 8;\n\nfunction redactHex(buf: Buffer): string {\n return `${buf.toString(\"hex\").slice(0, REDACTED_HEX_PREFIX_LEN)}…`;\n}\n\n/**\n * `bitcoinjs-lib` exposes `txInputs[i].hash` in internal little-endian form;\n * a human reading logs expects the big-endian txid an explorer would show.\n * Reverse before truncating so the surfaced prefix matches what an operator\n * can search for.\n */\nfunction redactTxid(internalHash: Buffer): string {\n const reversed = Buffer.from(internalHash).reverse();\n return redactHex(reversed);\n}\n\n/**\n * Compare two PSBTs and throw `PsbtSubstitutionError` unless they encode\n * the same unsigned transaction (version, locktime, inputs, outputs).\n *\n * @throws PsbtSubstitutionError on any mismatch in the unsigned tx\n * @throws Error if either PSBT cannot be parsed\n */\nexport function assertPsbtUnsignedTxMatches(\n params: AssertPsbtUnsignedTxMatchesParams,\n): void {\n const requested = parsePsbt(\"requested\", params.requestedPsbtHex);\n const returned = parsePsbt(\"returned\", params.returnedPsbtHex);\n\n if (requested.version !== returned.version) {\n throw new PsbtSubstitutionError(\n `tx version differs (requested=${requested.version}, returned=${returned.version})`,\n );\n }\n if (requested.locktime !== returned.locktime) {\n throw new PsbtSubstitutionError(\n `tx locktime differs (requested=${requested.locktime}, returned=${returned.locktime})`,\n );\n }\n if (requested.txInputs.length !== returned.txInputs.length) {\n throw new PsbtSubstitutionError(\n `input count differs (requested=${requested.txInputs.length}, returned=${returned.txInputs.length})`,\n );\n }\n if (requested.txOutputs.length !== returned.txOutputs.length) {\n throw new PsbtSubstitutionError(\n `output count differs (requested=${requested.txOutputs.length}, returned=${returned.txOutputs.length})`,\n );\n }\n for (let i = 0; i < requested.txInputs.length; i++) {\n const r = requested.txInputs[i];\n const s = returned.txInputs[i];\n if (!r.hash.equals(s.hash)) {\n throw new PsbtSubstitutionError(\n `input ${i} prevout txid differs (requested=${redactTxid(r.hash)}, returned=${redactTxid(s.hash)})`,\n );\n }\n if (r.index !== s.index) {\n throw new PsbtSubstitutionError(\n `input ${i} prevout vout differs (requested=${r.index}, returned=${s.index})`,\n );\n }\n if (r.sequence !== s.sequence) {\n throw new PsbtSubstitutionError(\n `input ${i} sequence differs (requested=${r.sequence}, returned=${s.sequence})`,\n );\n }\n }\n for (let i = 0; i < requested.txOutputs.length; i++) {\n const r = requested.txOutputs[i];\n const s = returned.txOutputs[i];\n if (!r.script.equals(s.script)) {\n throw new PsbtSubstitutionError(\n `output ${i} scriptPubKey differs (requested=${redactHex(r.script)}, returned=${redactHex(s.script)})`,\n );\n }\n if (r.value !== s.value) {\n throw new PsbtSubstitutionError(\n `output ${i} value differs (requested=${r.value}, returned=${s.value})`,\n );\n }\n }\n}\n"],"names":["createPayoutScript","params","connector","createPayoutConnector","TAPROOT_SINGLE_SIG_WITNESS_STACK_SIZE","buildPayoutPsbt","payoutTxHex","stripHexPrefix","peginTxHex","assertTxHex","payoutConnector","payoutScriptBytes","hexToUint8Array","controlBlock","payoutTx","Transaction","peginTx","assertTx","psbt","Psbt","input0","input1","input0Txid","uint8ArrayToHex","peginTxid","input1Txid","expectedInput1Txid","peginPrevOut","input1PrevOut","TAPSCRIPT_LEAF_VERSION","Buffer","tapInternalPubkey","output","assertPayoutOutputMatchesRegistered","registeredPayoutScriptPubKey","isValidHex","expectedScript","max","extractPayoutSignature","signedPsbtHex","depositorPubkey","inputIndex","signedPsbt","input","depositorPubkeyBytes","sigEntry","extractSchnorrSig","witnessStack","parseWitnessStack","sig","witness","items","offset","requireBytes","n","readVarInt","first","val","count","len","PsbtSubstitutionError","detail","parsePsbt","label","hex","cause","reason","REDACTED_HEX_PREFIX_LEN","redactHex","buf","redactTxid","internalHash","reversed","assertPsbtUnsignedTxMatches","requested","returned","i","r"],"mappings":"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"}
|