@babylonlabs-io/ts-sdk 0.73.0 → 0.74.1
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/{PeginManager-E-UHA1un.cjs → PeginManager-DEByBX5R.cjs} +2 -2
- package/dist/{PeginManager-E-UHA1un.cjs.map → PeginManager-DEByBX5R.cjs.map} +1 -1
- package/dist/{PeginManager-C9RPOd0L.js → PeginManager-DNimKlmw.js} +11 -11
- package/dist/{PeginManager-C9RPOd0L.js.map → PeginManager-DNimKlmw.js.map} +1 -1
- package/dist/{bip322Verify-D6sBBUHE.js → bip322Verify-DSco3Yhl.js} +2 -2
- package/dist/{bip322Verify-D6sBBUHE.js.map → bip322Verify-DSco3Yhl.js.map} +1 -1
- package/dist/buildAndBroadcastReclaim-Cqc6Jiqk.cjs +2 -0
- package/dist/{buildAndBroadcastReclaim-U-PyFfDg.cjs.map → buildAndBroadcastReclaim-Cqc6Jiqk.cjs.map} +1 -1
- package/dist/{buildAndBroadcastReclaim-BXclIcu_.js → buildAndBroadcastReclaim-DCGcupg7.js} +6 -6
- package/dist/{buildAndBroadcastReclaim-BXclIcu_.js.map → buildAndBroadcastReclaim-DCGcupg7.js.map} +1 -1
- package/dist/constants-BTZdyOuk.cjs +2 -0
- package/dist/constants-BTZdyOuk.cjs.map +1 -0
- package/dist/constants-D5vORbQE.js +29 -0
- package/dist/constants-D5vORbQE.js.map +1 -0
- package/dist/fundPeginTransaction-54-Rwb2k.cjs +2 -0
- package/dist/fundPeginTransaction-54-Rwb2k.cjs.map +1 -0
- package/dist/fundPeginTransaction-CwhRbCQC.js +88 -0
- package/dist/fundPeginTransaction-CwhRbCQC.js.map +1 -0
- package/dist/{index-Cs7_Evtk.cjs → index-CK1Xvq4K.cjs} +2 -2
- package/dist/{index-Cs7_Evtk.cjs.map → index-CK1Xvq4K.cjs.map} +1 -1
- package/dist/{index-LgmJhdEN.js → index-DQ5bfoT3.js} +2 -2
- package/dist/{index-LgmJhdEN.js.map → index-DQ5bfoT3.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +166 -161
- package/dist/noPayout-4RZB2g1e.cjs +2 -0
- package/dist/noPayout-4RZB2g1e.cjs.map +1 -0
- package/dist/noPayout-DiGr4eas.js +361 -0
- package/dist/noPayout-DiGr4eas.js.map +1 -0
- package/dist/{parseFundingOutpoints-B67CoXpF.js → parseFundingOutpoints-BQWvINfm.js} +2 -2
- package/dist/{parseFundingOutpoints-B67CoXpF.js.map → parseFundingOutpoints-BQWvINfm.js.map} +1 -1
- package/dist/pegin-registration-client-CXK3B_D1.js +882 -0
- package/dist/pegin-registration-client-CXK3B_D1.js.map +1 -0
- package/dist/pegin-registration-client-DLsMNm8Z.cjs +2 -0
- package/dist/pegin-registration-client-DLsMNm8Z.cjs.map +1 -0
- package/dist/{primeVpAuth-DBHohVKM.cjs → primeVpAuth-BOGKniTl.cjs} +2 -2
- package/dist/{primeVpAuth-DBHohVKM.cjs.map → primeVpAuth-BOGKniTl.cjs.map} +1 -1
- package/dist/{primeVpAuth-DvaD45q_.js → primeVpAuth-DdfHSC53.js} +4 -4
- package/dist/{primeVpAuth-DvaD45q_.js.map → primeVpAuth-DdfHSC53.js.map} +1 -1
- package/dist/{psbtInputFields-BIxBpPj2.cjs → psbtInputFields-BrV_ZfL_.cjs} +2 -2
- package/dist/{psbtInputFields-BIxBpPj2.cjs.map → psbtInputFields-BrV_ZfL_.cjs.map} +1 -1
- package/dist/{psbtInputFields-B3e05Xe6.js → psbtInputFields-CCVyaQMi.js} +2 -2
- package/dist/{psbtInputFields-B3e05Xe6.js.map → psbtInputFields-CCVyaQMi.js.map} +1 -1
- package/dist/secp256k1-D-H9jmd7.js +1766 -0
- package/dist/secp256k1-D-H9jmd7.js.map +1 -0
- package/dist/secp256k1-DDHQ1_za.cjs +2 -0
- package/dist/secp256k1-DDHQ1_za.cjs.map +1 -0
- package/dist/{sha2-CrlWM5S8.js → sha2-CLpQd0Rd.js} +8 -8
- package/dist/{sha2-CrlWM5S8.js.map → sha2-CLpQd0Rd.js.map} +1 -1
- package/dist/{signPsbtsWithFallback-DMSpIQWH.cjs → signPsbtsWithFallback-DtwzL5AA.cjs} +2 -2
- package/dist/{signPsbtsWithFallback-DMSpIQWH.cjs.map → signPsbtsWithFallback-DtwzL5AA.cjs.map} +1 -1
- package/dist/{signPsbtsWithFallback-0VBALhjS.js → signPsbtsWithFallback-f7QLp0q8.js} +4 -4
- package/dist/{signPsbtsWithFallback-0VBALhjS.js.map → signPsbtsWithFallback-f7QLp0q8.js.map} +1 -1
- package/dist/tbv/core/clients/eth/index.cjs +1 -1
- package/dist/tbv/core/clients/eth/index.js +3 -3
- package/dist/tbv/core/clients/index.cjs +1 -1
- package/dist/tbv/core/clients/index.js +5 -5
- package/dist/tbv/core/clients/vault-provider/status/index.cjs +1 -1
- package/dist/tbv/core/clients/vault-provider/status/index.js +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.d.ts +3 -0
- package/dist/tbv/core/index.d.ts.map +1 -1
- package/dist/tbv/core/index.js +159 -154
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/pegin-fingerprint/__tests__/peginFingerprint.golden.test.d.ts +62 -0
- package/dist/tbv/core/pegin-fingerprint/__tests__/peginFingerprint.golden.test.d.ts.map +1 -0
- package/dist/tbv/core/pegin-fingerprint/__tests__/peginFingerprint.test.d.ts +15 -0
- package/dist/tbv/core/pegin-fingerprint/__tests__/peginFingerprint.test.d.ts.map +1 -0
- package/dist/tbv/core/pegin-fingerprint/index.d.ts +14 -0
- package/dist/tbv/core/pegin-fingerprint/index.d.ts.map +1 -0
- package/dist/tbv/core/pegin-fingerprint/peginFingerprint.d.ts +141 -0
- package/dist/tbv/core/pegin-fingerprint/peginFingerprint.d.ts.map +1 -0
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.js +4 -4
- package/dist/tbv/core/primitives/psbt/__tests__/assertPeginTxShape.test.d.ts +5 -6
- package/dist/tbv/core/primitives/psbt/__tests__/assertPeginTxShape.test.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/__tests__/assertWasmPeginSizing.test.d.ts +2 -2
- package/dist/tbv/core/primitives/psbt/assertWasmPeginSizing.d.ts +36 -14
- package/dist/tbv/core/primitives/psbt/assertWasmPeginSizing.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/constants.d.ts +39 -0
- package/dist/tbv/core/primitives/psbt/constants.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/pegin.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/peginInput.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/refund.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/utils/fee/constants.d.ts +4 -4
- package/dist/tbv/core/utils/index.cjs +1 -1
- package/dist/tbv/core/utils/index.js +2 -2
- package/dist/tbv/core/utils/transaction/fundPeginTransaction.d.ts.map +1 -1
- package/dist/tbv/core/vault-secrets/index.js +1 -1
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +159 -154
- package/dist/test/setup.browser.d.ts +2 -0
- package/dist/test/setup.browser.d.ts.map +1 -0
- package/dist/testing/index.js +1 -1
- package/dist/{toRefundInputs-BkcFhvDp.js → toRefundInputs-BNSXIymn.js} +238 -140
- package/dist/toRefundInputs-BNSXIymn.js.map +1 -0
- package/dist/toRefundInputs-meTyor7r.cjs +2 -0
- package/dist/toRefundInputs-meTyor7r.cjs.map +1 -0
- package/dist/{types-DSlcXtog.cjs → types-BzSOthHH.cjs} +2 -2
- package/dist/{types-DSlcXtog.cjs.map → types-BzSOthHH.cjs.map} +1 -1
- package/dist/{types-CPDLZm3l.js → types-C5DyrC8F.js} +2 -2
- package/dist/{types-CPDLZm3l.js.map → types-C5DyrC8F.js.map} +1 -1
- package/dist/verifyKeyPathSchnorrSignature-BVtNwgK6.js +360 -0
- package/dist/verifyKeyPathSchnorrSignature-BVtNwgK6.js.map +1 -0
- package/dist/verifyKeyPathSchnorrSignature-BjB8Znly.cjs +2 -0
- package/dist/verifyKeyPathSchnorrSignature-BjB8Znly.cjs.map +1 -0
- package/dist/verifyScriptPathSchnorrSignature-D_epga4j.js +1140 -0
- package/dist/verifyScriptPathSchnorrSignature-D_epga4j.js.map +1 -0
- package/dist/verifyScriptPathSchnorrSignature-DaRqvEgW.cjs +2 -0
- package/dist/verifyScriptPathSchnorrSignature-DaRqvEgW.cjs.map +1 -0
- package/package.json +5 -2
- package/dist/buildAndBroadcastReclaim-U-PyFfDg.cjs +0 -2
- package/dist/constants-Bh38W9mq.cjs +0 -2
- package/dist/constants-Bh38W9mq.cjs.map +0 -1
- package/dist/constants-CPzppOdq.js +0 -17
- package/dist/constants-CPzppOdq.js.map +0 -1
- package/dist/fundPeginTransaction-B2wyjqp0.js +0 -83
- package/dist/fundPeginTransaction-B2wyjqp0.js.map +0 -1
- package/dist/fundPeginTransaction-BLD8FRL9.cjs +0 -2
- package/dist/fundPeginTransaction-BLD8FRL9.cjs.map +0 -1
- package/dist/noPayout-DpGRzidi.js +0 -353
- package/dist/noPayout-DpGRzidi.js.map +0 -1
- package/dist/noPayout-zEifyecV.cjs +0 -2
- package/dist/noPayout-zEifyecV.cjs.map +0 -1
- package/dist/pegin-registration-client-6vLk2itL.cjs +0 -2
- package/dist/pegin-registration-client-6vLk2itL.cjs.map +0 -1
- package/dist/pegin-registration-client-BdRiR8br.js +0 -2635
- package/dist/pegin-registration-client-BdRiR8br.js.map +0 -1
- package/dist/toRefundInputs-BkcFhvDp.js.map +0 -1
- package/dist/toRefundInputs-CatCKniS.cjs +0 -2
- package/dist/toRefundInputs-CatCKniS.cjs.map +0 -1
- package/dist/vaultCoreVersion-DYfw3qed.cjs +0 -2
- package/dist/vaultCoreVersion-DYfw3qed.cjs.map +0 -1
- package/dist/vaultCoreVersion-D_fP9P3C.js +0 -10
- package/dist/vaultCoreVersion-D_fP9P3C.js.map +0 -1
- package/dist/verifyKeyPathSchnorrSignature-BedSbH2D.cjs +0 -2
- package/dist/verifyKeyPathSchnorrSignature-BedSbH2D.cjs.map +0 -1
- package/dist/verifyKeyPathSchnorrSignature-BrgUJmV0.js +0 -372
- package/dist/verifyKeyPathSchnorrSignature-BrgUJmV0.js.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-BfNUSgA7.cjs +0 -2
- package/dist/verifyScriptPathSchnorrSignature-BfNUSgA7.cjs.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-Ciq_xZhw.js +0 -951
- package/dist/verifyScriptPathSchnorrSignature-Ciq_xZhw.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pegin-registration-client-CXK3B_D1.js","sources":["../src/tbv/core/deposit-terms/commissionCeiling.ts","../../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/legacy.js","../src/tbv/core/clients/eth/payout-script.ts","../src/tbv/core/clients/eth/pegin-transaction.ts","../src/tbv/core/clients/eth/protocol-params-validation.ts","../src/tbv/core/clients/eth/vault-registry-reader.ts","../src/tbv/core/clients/eth/pegin-registration-client.ts"],"sourcesContent":["/**\n * The depositor's commission ceiling (`maxAcceptableCommissionBps`) policy:\n * quoted VP commission + drift headroom, capped below the contract's\n * exclusive bound. Shared by the fresh path (`PeginManager`) and the\n * resume-rebuild path so both compute the same ceiling.\n *\n * @module deposit-terms/commissionCeiling\n */\n\n/*\n * Commission-check map (each guards a DIFFERENT boundary — do not consolidate):\n * 1. assertVpCommissionInProtocolRange (vault app, vaultPayoutSignatureService)\n * — chain-read trust boundary; mirrors VPKeyRegistryLogic.sol bounds.\n * 2. capMaxAcceptableCommissionBps (here) — depositor quote → ceiling policy;\n * mirrors PeginLogic.sol's strict > check via the +25bps headroom.\n * 3. buildDepositTerms range check — public-API precondition on the projection\n * that mints the device-enforced commissionFee.\n * 4. payout.ts commission cap — the VP-built tx's output value vs bps at the\n * signing site (CLAUDE.md Critical Path #3).\n * 5. envelope.ts dust/cross-field gates (ledger-vault-signer) — firmware-only\n * constants, pre-device-I/O (Critical Path #7).\n */\n\nimport { MAX_VP_COMMISSION_BPS_EXCLUSIVE } from \"../primitives/psbt/constants\";\n\n/**\n * Headroom (in basis points) added to the current VP commission to compute\n * `maxAcceptableCommissionBps` at submit time. Lets the VP raise its\n * commission by up to this amount between read and submit without forcing\n * a re-quote. Capped by {@link MAX_ACCEPTABLE_COMMISSION_BPS_CAP}.\n *\n * Contract check is strict `>` (PeginLogic.sol `VaultProviderCommissionExceeded`\n * revert), so +25 allows up\n * to +25 bps of drift.\n */\nexport const COMMISSION_BPS_HEADROOM = 25;\n\n/**\n * Hard ceiling for `maxAcceptableCommissionBps`. The contract enforces\n * `commissionBps < 10000`, so any value at/above that is unreachable;\n * `9999` is the maximum useful cap.\n */\nexport const MAX_ACCEPTABLE_COMMISSION_BPS_CAP = 9999;\n\n/**\n * The commission ceiling submitted as registration calldata and mirrored\n * into `DepositTerms.commissionFee`: quoted + drift headroom, capped.\n * Single source for both consumers — feed it the SAME quoted bps at prepare\n * and register time so device-accept stays coextensive with contract-accept.\n */\nexport function capMaxAcceptableCommissionBps(bps: number): number {\n // Validate the raw quote before headroom shifts its domain — a negative\n // quote must throw here, not become a small \"legal\" ceiling.\n // Reject an out-of-range quote outright — clamping it to 9999 would turn a\n // bad read into a 99.99% ceiling, the exact failure the cap exists to stop.\n if (\n !Number.isInteger(bps) ||\n bps < 0 ||\n bps >= MAX_VP_COMMISSION_BPS_EXCLUSIVE\n ) {\n throw new Error(\n `Quoted commissionBps must be an integer in ` +\n `[0, ${MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${bps}`,\n );\n }\n return Math.min(\n bps + COMMISSION_BPS_HEADROOM,\n MAX_ACCEPTABLE_COMMISSION_BPS_CAP,\n );\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","import { schnorr, secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { ripemd160 } from \"@noble/hashes/legacy.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\";\nimport type { Hex } from \"viem\";\n\nimport { MAX_PAYOUT_SCRIPT_LEN } from \"../../primitives/psbt/constants\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\n\nconst P2TR_SCRIPT_PREFIX = \"5120\";\nconst P2WPKH_SCRIPT_PREFIX = \"0014\";\nconst HASH160_BYTES = 20;\nconst COMPRESSED_PUBKEY_BYTES = 33;\nconst UNCOMPRESSED_PUBKEY_BYTES = 65;\nconst SEC1_EVEN_Y_PREFIX = 0x02;\nconst SEC1_ODD_Y_PREFIX = 0x03;\nconst SEC1_UNCOMPRESSED_PREFIX = 0x04;\n\nfunction normalizeHex(value: string, label: string): Hex {\n const body =\n value.startsWith(\"0x\") || value.startsWith(\"0X\") ? value.slice(2) : value;\n if (!/^(?:[0-9a-fA-F]{2})+$/.test(body)) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n return `0x${body.toLowerCase()}`;\n}\n\nfunction deriveP2trScript(xOnlyPubkey: string): Hex {\n const pubkeyBytes = hexToBytes(xOnlyPubkey);\n const internalKey = schnorr.utils.lift_x(BigInt(`0x${xOnlyPubkey}`));\n const tweak = schnorr.utils.bytesToNumberBE(\n schnorr.utils.taggedHash(\"TapTweak\", pubkeyBytes),\n );\n if (tweak >= secp256k1.CURVE.n) {\n throw new Error(\"Proof of possession BTC pubkey has an invalid TapTweak\");\n }\n const outputKey =\n tweak === 0n\n ? internalKey\n : internalKey.add(schnorr.Point.BASE.multiply(tweak));\n return `0x${P2TR_SCRIPT_PREFIX}${bytesToHex(\n schnorr.utils.pointToBytes(outputKey),\n )}`;\n}\n\nfunction normalizePayoutPubkey(value: string): {\n xOnlyPubkey: string;\n compressedPubkey?: Uint8Array;\n} {\n const normalized = normalizeHex(value, \"depositorBtcPubkeyRaw\");\n const pubkey = hexToBytes(normalized.slice(2));\n if (pubkey.length === 32) {\n return {\n xOnlyPubkey: assertOnChainBtcPubkey(normalized, \"Payout BTC pubkey\"),\n };\n }\n const isCompressed =\n pubkey.length === COMPRESSED_PUBKEY_BYTES &&\n (pubkey[0] === SEC1_EVEN_Y_PREFIX || pubkey[0] === SEC1_ODD_Y_PREFIX);\n const isUncompressed =\n pubkey.length === UNCOMPRESSED_PUBKEY_BYTES &&\n pubkey[0] === SEC1_UNCOMPRESSED_PREFIX;\n if (!isCompressed && !isUncompressed) {\n throw new Error(\n \"depositorBtcPubkeyRaw must be x-only, compressed, or uncompressed\",\n );\n }\n try {\n secp256k1.Point.fromBytes(pubkey);\n } catch {\n throw new Error(\"depositorBtcPubkeyRaw is not a valid BTC pubkey\");\n }\n return {\n xOnlyPubkey: bytesToHex(pubkey.subarray(1, COMPRESSED_PUBKEY_BYTES)),\n compressedPubkey: isCompressed ? pubkey : undefined,\n };\n}\n\nfunction deriveP2wpkhScript(pubkey: Uint8Array): Hex {\n return `0x${P2WPKH_SCRIPT_PREFIX}${bytesToHex(ripemd160(sha256(pubkey)))}`;\n}\n\n/** Verify the irreversible payout script at the final submission boundary. */\nexport function assertPayoutScriptMatchesPopKey(\n scriptPubKey: string,\n depositorBtcPubkey: string,\n depositorBtcPubkeyRaw: string,\n): Hex {\n const payoutScript = normalizeHex(\n scriptPubKey,\n \"depositorPayoutScriptPubKey\",\n );\n if ((payoutScript.length - 2) / 2 > MAX_PAYOUT_SCRIPT_LEN) {\n throw new Error(\n `depositorPayoutScriptPubKey exceeds ${MAX_PAYOUT_SCRIPT_LEN} bytes`,\n );\n }\n const keyBody =\n depositorBtcPubkey.startsWith(\"0x\") || depositorBtcPubkey.startsWith(\"0X\")\n ? depositorBtcPubkey.slice(2)\n : depositorBtcPubkey;\n const xOnlyPubkey = assertOnChainBtcPubkey(\n `0x${keyBody}` as Hex,\n \"Proof of possession BTC pubkey\",\n );\n const payoutPubkey = normalizePayoutPubkey(depositorBtcPubkeyRaw);\n if (payoutPubkey.xOnlyPubkey !== xOnlyPubkey) {\n throw new Error(\n \"depositorBtcPubkeyRaw does not match the proof of possession BTC pubkey\",\n );\n }\n\n if (payoutScript === deriveP2trScript(xOnlyPubkey)) {\n return payoutScript;\n }\n if (\n payoutScript.startsWith(`0x${P2WPKH_SCRIPT_PREFIX}`) &&\n payoutScript.length ===\n 2 + P2WPKH_SCRIPT_PREFIX.length + HASH160_BYTES * 2\n ) {\n if (!payoutPubkey.compressedPubkey) {\n throw new Error(\"A P2WPKH payout requires a compressed BTC pubkey\");\n }\n if (payoutScript === deriveP2wpkhScript(payoutPubkey.compressedPubkey)) {\n return payoutScript;\n }\n }\n throw new Error(\n \"depositorPayoutScriptPubKey does not match the proof of possession BTC pubkey\",\n );\n}\n","/**\n * Dependency-free Bitcoin txid and vault-ID helpers for Ethereum-only clients.\n * Transaction hex and vault-ID inputs accept an optional `0x` prefix.\n * Depositor addresses use strict EIP-55 validation.\n * Txids use a `0x` prefix. Vault IDs use no prefix. Both use lowercase hex.\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport {\n encodeAbiParameters,\n isAddress,\n keccak256,\n type Address,\n type Hex,\n} from \"viem\";\n\n/** Decode an optional-prefixed, even-length hex string. */\nfunction decodeHex(value: string, label: string): Uint8Array {\n const clean = value.startsWith(\"0x\") ? value.slice(2) : value;\n if (clean.length === 0 || clean.length % 2 !== 0) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n if (!/^[0-9a-fA-F]+$/.test(clean)) {\n throw new Error(`${label} contains non-hex characters`);\n }\n\n const bytes = new Uint8Array(clean.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/** Encode bytes as lowercase hex without a prefix. */\nfunction encodeHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n}\n\n/** Concatenate byte chunks without a buffer dependency. */\nfunction concatBytes(chunks: readonly Uint8Array[]): Uint8Array {\n const result = new Uint8Array(\n chunks.reduce((length, chunk) => length + chunk.length, 0),\n );\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\n/**\n * Parse enough of Bitcoin's consensus transaction encoding to serialize the\n * no-witness form used for txid calculation. Every length is bounds-checked;\n * malformed/trailing data is rejected rather than hashed as an opaque blob.\n */\nfunction serializeWithoutWitness(transaction: Uint8Array): Uint8Array {\n let offset = 0;\n\n const take = (length: number, label: string): Uint8Array => {\n if (!Number.isSafeInteger(length) || length < 0) {\n throw new Error(`Invalid ${label} length ${length}`);\n }\n if (offset + length > transaction.length) {\n throw new Error(`Truncated Bitcoin transaction while reading ${label}`);\n }\n const value = transaction.slice(offset, offset + length);\n offset += length;\n return value;\n };\n\n const readLittleEndian = (length: number, label: string): bigint => {\n const bytes = take(length, label);\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) {\n value = (value << 8n) | BigInt(bytes[i]);\n }\n return value;\n };\n\n const readCompactSize = (\n label: string,\n ): { encoded: Uint8Array; value: number } => {\n const start = offset;\n const prefix = take(1, label)[0];\n let value: bigint;\n if (prefix < 0xfd) {\n value = BigInt(prefix);\n } else if (prefix === 0xfd) {\n value = readLittleEndian(2, label);\n if (value < 0xfdn) throw new Error(`Non-canonical ${label}`);\n } else if (prefix === 0xfe) {\n value = readLittleEndian(4, label);\n if (value <= 0xffffn) throw new Error(`Non-canonical ${label}`);\n } else {\n value = readLittleEndian(8, label);\n if (value <= 0xffffffffn) throw new Error(`Non-canonical ${label}`);\n }\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(`${label} exceeds JavaScript's safe integer range`);\n }\n return {\n encoded: transaction.slice(start, offset),\n value: Number(value),\n };\n };\n\n const version = take(4, \"version\");\n const hasWitness =\n transaction[offset] === 0x00 && transaction[offset + 1] === 0x01;\n if (hasWitness) offset += 2;\n\n const inputCount = readCompactSize(\"input count\");\n const inputs: Uint8Array[] = [];\n for (let i = 0; i < inputCount.value; i++) {\n const start = offset;\n take(32, `input ${i} previous transaction hash`);\n take(4, `input ${i} previous output index`);\n const scriptLength = readCompactSize(`input ${i} script length`);\n take(scriptLength.value, `input ${i} script`);\n take(4, `input ${i} sequence`);\n inputs.push(transaction.slice(start, offset));\n }\n\n const outputCount = readCompactSize(\"output count\");\n const outputs: Uint8Array[] = [];\n for (let i = 0; i < outputCount.value; i++) {\n const start = offset;\n take(8, `output ${i} value`);\n const scriptLength = readCompactSize(`output ${i} script length`);\n take(scriptLength.value, `output ${i} script`);\n outputs.push(transaction.slice(start, offset));\n }\n\n if (hasWitness) {\n let hasWitnessData = false;\n for (let i = 0; i < inputCount.value; i++) {\n const itemCount = readCompactSize(`input ${i} witness item count`);\n hasWitnessData ||= itemCount.value > 0;\n for (let j = 0; j < itemCount.value; j++) {\n const itemLength = readCompactSize(\n `input ${i} witness item ${j} length`,\n );\n take(itemLength.value, `input ${i} witness item ${j}`);\n }\n }\n if (!hasWitnessData) {\n throw new Error(\"Bitcoin transaction has superfluous witness marker\");\n }\n }\n\n const locktime = take(4, \"locktime\");\n if (offset !== transaction.length) {\n throw new Error(\n `Bitcoin transaction has ${transaction.length - offset} trailing byte(s)`,\n );\n }\n\n return concatBytes([\n version,\n inputCount.encoded,\n ...inputs,\n outputCount.encoded,\n ...outputs,\n locktime,\n ]);\n}\n\n/** Calculate a Bitcoin txid without importing bitcoinjs-lib. */\nexport function calculateBtcTxHash(transactionHex: string): Hex {\n const serialized = serializeWithoutWitness(\n decodeHex(transactionHex, \"transactionHex\"),\n );\n const digest = sha256(sha256(serialized));\n digest.reverse();\n return `0x${encodeHex(digest)}`;\n}\n\n/**\n * Derive the Solidity vault ID without loading the Rust/WASM package.\n *\n * Inputs accept an optional `0x` prefix to match the current PeginManager\n * call sites. Address validation stays strict: lowercase and valid EIP-55\n * addresses pass, while uppercase and incorrectly checksummed mixed-case\n * addresses fail. The synchronous result is lowercase hex without a prefix,\n * matching the WASM helper that this function replaces.\n */\nexport function derivePeginVaultId(\n peginTxHash: string,\n depositor: string,\n): string {\n const normalizedPeginTxHash = peginTxHash.startsWith(\"0x\")\n ? peginTxHash\n : `0x${peginTxHash}`;\n if (!/^0x[0-9a-fA-F]{64}$/.test(normalizedPeginTxHash)) {\n throw new Error(\"peginTxHash must be a 32-byte hex value\");\n }\n const normalizedDepositor = depositor.startsWith(\"0x\")\n ? depositor\n : `0x${depositor}`;\n if (!isAddress(normalizedDepositor, { strict: true })) {\n throw new Error(`Invalid depositor Ethereum address: ${depositor}`);\n }\n return keccak256(\n encodeAbiParameters(\n [{ type: \"bytes32\" }, { type: \"address\" }],\n [normalizedPeginTxHash as Hex, normalizedDepositor as Address],\n ),\n ).slice(2);\n}\n","/**\n * Validation for protocol parameters fetched from the ProtocolParams contract.\n *\n * These values feed Bitcoin script construction and deposit validation.\n * Invalid params must be caught before they reach transaction-building code,\n * since errors after wallet signing prompts are unrecoverable.\n *\n * The {@link ViemProtocolParamsReader} runs these on every read; consumers\n * implementing their own reader against the same `ProtocolParamsReader`\n * interface should call them too.\n */\n\nimport { assertValidVaultCoreVersion } from \"../../primitives/vaultCoreVersion\";\n\nimport type {\n PegInConfiguration,\n TBVProtocolParams,\n VersionedOffchainParams,\n} from \"./types\";\n\n/**\n * Maximum value for a Solidity uint16.\n * PeginLogic.sol casts timelockAssert to uint16, so values above this are invalid.\n */\nconst UINT16_MAX = 65535;\n\n/** Maximum valid value for basis points (100%) */\nconst MAX_BASIS_POINTS = 10000;\n\n/** Maximum value for a Solidity uint32. */\nconst UINT32_MAX = 4_294_967_295;\n\n/** Maximum valid value for a uint8 (e.g. maxHtlcOutputCount). */\nconst UINT8_MAX = 255;\n\n/**\n * Validate an `offchainParamsVersion` value sourced from a contract read.\n * `Number()` on a malformed payload yields `NaN` or a non-integer; both\n * silently break consumers that loop `1..version` or use the value as a\n * map key. Used by reader entry points that surface the version to JS.\n */\nexport function assertValidOffchainParamsVersion(version: number): void {\n if (\n !Number.isInteger(version) ||\n version < 0 ||\n version > UINT32_MAX\n ) {\n throw new Error(\n `Invalid offchainParamsVersion from contract: must be a uint32, got ${version}`,\n );\n }\n}\n\n/**\n * Validate offchain params consistency and bounds.\n * @throws Error on invalid values to prevent constructing invalid Bitcoin scripts.\n */\nexport function validateOffchainParams(params: VersionedOffchainParams): void {\n const errors: string[] = [];\n\n if (params.timelockAssert <= 0n) {\n errors.push(\n `timelockAssert must be positive, got ${params.timelockAssert}`,\n );\n }\n if (params.timelockAssert > BigInt(UINT16_MAX)) {\n errors.push(\n `timelockAssert ${params.timelockAssert} exceeds uint16 max (${UINT16_MAX})`,\n );\n }\n\n if (params.timelockChallengeAssert <= 0n) {\n errors.push(\n `timelockChallengeAssert must be positive, got ${params.timelockChallengeAssert}`,\n );\n }\n\n if (params.tRefund <= 0) {\n errors.push(`tRefund must be positive, got ${params.tRefund}`);\n }\n\n if (params.tStale <= 0) {\n errors.push(`tStale must be positive, got ${params.tStale}`);\n }\n\n if (params.securityCouncilKeys.length === 0) {\n errors.push(\"securityCouncilKeys must not be empty\");\n }\n\n if (params.councilQuorum <= 0) {\n errors.push(`councilQuorum must be positive, got ${params.councilQuorum}`);\n }\n if (params.councilQuorum > params.securityCouncilKeys.length) {\n errors.push(\n `councilQuorum (${params.councilQuorum}) exceeds securityCouncilKeys count (${params.securityCouncilKeys.length})`,\n );\n }\n\n if (params.feeRate <= 0n) {\n errors.push(`feeRate must be positive, got ${params.feeRate}`);\n }\n\n if (params.minPeginFeeRate <= 0n) {\n errors.push(\n `minPeginFeeRate must be positive, got ${params.minPeginFeeRate}`,\n );\n }\n\n if (\n !Number.isInteger(params.proverCircuitVersion) ||\n params.proverCircuitVersion < 0 ||\n params.proverCircuitVersion > UINT16_MAX\n ) {\n errors.push(\n `proverCircuitVersion must be a uint16, got ${params.proverCircuitVersion}`,\n );\n }\n\n if (\n !Number.isInteger(params.minPrepeginDepth) ||\n params.minPrepeginDepth <= 0 ||\n params.minPrepeginDepth > UINT32_MAX\n ) {\n errors.push(\n `minPrepeginDepth must be a uint32 in [1, ${UINT32_MAX}], got ${params.minPrepeginDepth}`,\n );\n }\n\n if (params.babeTotalInstances <= 0) {\n errors.push(\n `babeTotalInstances must be positive, got ${params.babeTotalInstances}`,\n );\n }\n if (params.babeInstancesToFinalize <= 0) {\n errors.push(\n `babeInstancesToFinalize must be positive, got ${params.babeInstancesToFinalize}`,\n );\n }\n if (params.babeInstancesToFinalize > params.babeTotalInstances) {\n errors.push(\n `babeInstancesToFinalize (${params.babeInstancesToFinalize}) exceeds babeTotalInstances (${params.babeTotalInstances})`,\n );\n }\n\n if (\n params.minVpCommissionBps < 0 ||\n params.minVpCommissionBps > MAX_BASIS_POINTS\n ) {\n errors.push(\n `minVpCommissionBps must be in [0, ${MAX_BASIS_POINTS}], got ${params.minVpCommissionBps}`,\n );\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Invalid offchain protocol parameters: ${errors.join(\"; \")}`,\n );\n }\n}\n\n/**\n * Validate TBV protocol params returned from the contract.\n * @throws Error on invalid amounts or out-of-range bounded fields.\n */\nexport function validateTBVProtocolParams(params: TBVProtocolParams): void {\n const errors: string[] = [];\n\n if (params.minimumPegInAmount <= 0n) {\n errors.push(\n `minimumPegInAmount must be positive, got ${params.minimumPegInAmount}`,\n );\n }\n\n if (params.maxPegInAmount < params.minimumPegInAmount) {\n errors.push(\n `maxPegInAmount (${params.maxPegInAmount}) must be >= minimumPegInAmount (${params.minimumPegInAmount})`,\n );\n }\n\n if (params.pegInAckTimeout <= 0n) {\n errors.push(\n `pegInAckTimeout must be positive, got ${params.pegInAckTimeout}`,\n );\n }\n\n if (params.pegInActivationTimeout <= 0n) {\n errors.push(\n `pegInActivationTimeout must be positive, got ${params.pegInActivationTimeout}`,\n );\n }\n\n if (\n !Number.isInteger(params.maxHtlcOutputCount) ||\n params.maxHtlcOutputCount <= 0 ||\n params.maxHtlcOutputCount > UINT8_MAX\n ) {\n errors.push(\n `maxHtlcOutputCount must be an integer in [1, ${UINT8_MAX}], got ${params.maxHtlcOutputCount}`,\n );\n }\n\n if (\n typeof params.expiredPegInGraceBlocks !== \"bigint\" ||\n params.expiredPegInGraceBlocks <= 0n\n ) {\n errors.push(\n `expiredPegInGraceBlocks must be a positive bigint, got ${params.expiredPegInGraceBlocks}`,\n );\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid TBV protocol parameters: ${errors.join(\"; \")}`);\n }\n}\n\n/**\n * Validate the full peg-in configuration after assembly.\n * Checks both TBV params and offchain params consistency, and the\n * top-level `offchainParamsVersion` (which originates from a separate\n * multicall result and so must be range-checked alongside the params it\n * names).\n */\nexport function validatePegInConfiguration(config: PegInConfiguration): void {\n validateTBVProtocolParams(config);\n validateOffchainParams(config.offchainParams);\n\n if (\n !Number.isInteger(config.offchainParamsVersion) ||\n config.offchainParamsVersion < 0 ||\n config.offchainParamsVersion > UINT32_MAX\n ) {\n throw new Error(\n `Invalid peg-in configuration: offchainParamsVersion must be a uint32, got ${config.offchainParamsVersion}`,\n );\n }\n\n // The contract enforces ≥ 1 (setter rejects 0); a 0 here means a\n // mis-decoded read or a pre-vaultCoreVersion contract — fail closed.\n assertValidVaultCoreVersion(\n config.activeVaultCoreVersion,\n \"ProtocolParams.activeVaultCoreVersion()\",\n );\n}\n","/**\n * Concrete BTCVaultRegistry reader using viem's readContract.\n *\n * This is an optional utility — callers can use their own implementation\n * of the VaultRegistryReader interface.\n */\n\nimport type { Abi, Address, Hex, PublicClient } from \"viem\";\n\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { BTCVaultRegistryKeyEpochsABI } from \"../../contracts/abis/BTCVaultRegistryKeyEpochs.abi\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\nimport { assertValidOffchainParamsVersion } from \"./protocol-params-validation\";\nimport type {\n KeyEpochs,\n OnChainBtcPubkey,\n VaultBasicInfo,\n VaultData,\n VaultProtocolInfo,\n VaultRegistryReader,\n} from \"./types\";\n\n/**\n * Inclusive upper bound the BTCVaultRegistry contract enforces on a vault\n * provider's commission (the contract check is `< 10000`).\n */\nconst MAX_VP_COMMISSION_BPS = 9999;\n\n/** Raw `getBtcVaultBasicInfo` tuple as decoded by viem. */\ntype RawVaultBasicInfo = {\n depositor: Address;\n depositorBtcPubKey: Hex;\n amount: bigint;\n vaultProvider: Address;\n status: number;\n applicationEntryPoint: Address;\n createdAt: bigint;\n};\n\n/**\n * Raw `getBtcVaultProtocolInfo` tuple as decoded by viem.\n *\n * Mirrors the ABI's components except `claimExpiredUntil`, which nothing\n * consumes: it is the post-expiry grace deadline for `claimExpired`, scoped to\n * vaults that expired without activating, and it is not a deadline on the\n * depositor's claim right. The ABI still declares it — the decode is\n * positional, so removing it there would shift `vaultCoreVersion`.\n */\ntype RawVaultProtocolInfo = {\n depositorSignedPeginTx: Hex;\n universalChallengersVersion: number;\n appVaultKeepersVersion: number;\n offchainParamsVersion: number;\n verifiedAt: bigint;\n depositorWotsPkHash: Hex;\n hashlock: Hex;\n htlcVout: number;\n depositorPopSignature: Hex;\n prePeginTxHash: Hex;\n vaultProviderCommissionBps: number;\n vaultCoreVersion: number;\n};\n\nfunction mapVaultBasicInfo(result: RawVaultBasicInfo): VaultBasicInfo {\n return {\n depositor: result.depositor,\n depositorBtcPubKey: result.depositorBtcPubKey,\n amount: result.amount,\n vaultProvider: result.vaultProvider,\n status: result.status,\n applicationEntryPoint: result.applicationEntryPoint,\n createdAt: result.createdAt,\n };\n}\n\nfunction mapVaultProtocolInfo(result: RawVaultProtocolInfo): VaultProtocolInfo {\n const offchainParamsVersion = Number(result.offchainParamsVersion);\n assertValidOffchainParamsVersion(offchainParamsVersion);\n return {\n depositorSignedPeginTx: result.depositorSignedPeginTx,\n universalChallengersVersion: result.universalChallengersVersion,\n appVaultKeepersVersion: result.appVaultKeepersVersion,\n offchainParamsVersion,\n verifiedAt: result.verifiedAt,\n depositorWotsPkHash: result.depositorWotsPkHash,\n hashlock: result.hashlock,\n htlcVout: result.htlcVout,\n depositorPopSignature: result.depositorPopSignature,\n prePeginTxHash: result.prePeginTxHash,\n vaultProviderCommissionBps: result.vaultProviderCommissionBps,\n vaultCoreVersion: result.vaultCoreVersion,\n };\n}\n\n/**\n * Exclusive upper bound for a `uint64` epoch.\n *\n * viem does not range-check a decoded `uint64`, so a misaligned decode can\n * hand back a value far larger than the field can hold. Rejecting those is\n * cheap defence in depth against a mis-decode of the extended ABI.\n *\n * The state this is load-bearing for is narrower than \"a registry that predates\n * RFC-006\". Against a *fully* pre-RFC-006 registry the path fails closed on its\n * own: `resolveParticipantKeysAtEpochs` goes on to call\n * `getOperationBtcKeyAtEpochOrGenesis` on ApplicationRegistry and\n * ProtocolParams, which do not exist there, so the multicall reverts and these\n * epochs are never used. The reachable gap is a registry that *has* the\n * operation-key getters but whose `BTCVaultProtocolInfo` struct is not\n * extended — there the tail-data epochs resolve with no error at all, and this\n * range check is the only thing looking at them.\n *\n * Even for that case it is only a backstop, and a weak one: a misaligned decode\n * can land on a small, plausible-looking integer this range accepts. Correctness\n * rests on only ever pointing at an RFC-006 registry, which is a deployment\n * precondition rather than something this call can establish — see\n * https://github.com/babylonlabs-io/babylon-toolkit/issues/2192 for where that\n * check is owned, and `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n */\nconst UINT64_EXCLUSIVE_UPPER_BOUND = 1n << 64n;\n\n/**\n * The epoch a vault provider's registration key is bonded at.\n *\n * A provider's operation-key history is append-only and every appended version\n * is stamped at epoch 1 or later, so epoch 0 always resolves to the key set at\n * registration. This is what lets `getOperationBtcKeyAtEpoch` stand in for the\n * removed `getVaultProviderBTCKey` getter.\n */\nconst VP_GENESIS_KEY_EPOCH = 0n;\n\nfunction assertEpochInRange(\n value: bigint,\n field: string,\n vaultId: Hex,\n): bigint {\n if (value < 0n || value >= UINT64_EXCLUSIVE_UPPER_BOUND) {\n throw new Error(\n `getBtcVaultProtocolInfo returned ${field}=${value} for vault ${vaultId}, ` +\n `outside the uint64 range — the registry may predate RFC-006`,\n );\n }\n return value;\n}\n\nfunction mapKeyEpochs(result: KeyEpochs, vaultId: Hex): KeyEpochs {\n return {\n vpKeyEpoch: assertEpochInRange(result.vpKeyEpoch, \"vpKeyEpoch\", vaultId),\n appKeeperKeyEpoch: assertEpochInRange(\n result.appKeeperKeyEpoch,\n \"appKeeperKeyEpoch\",\n vaultId,\n ),\n ucKeyEpoch: assertEpochInRange(result.ucKeyEpoch, \"ucKeyEpoch\", vaultId),\n };\n}\n\n/**\n * Concrete vault registry reader using viem.\n *\n * Usage:\n * ```ts\n * const reader = new ViemVaultRegistryReader(publicClient, registryAddress);\n * const data = await reader.getVaultData(vaultId);\n * ```\n */\nexport class ViemVaultRegistryReader implements VaultRegistryReader {\n constructor(\n private publicClient: PublicClient,\n private contractAddress: Address,\n ) {}\n\n /**\n * Read the VP's **genesis** (registration) x-only BTC pubkey — the key bonded\n * at version 0, which never moves when the operator rotates.\n *\n * Resolved as \"the operation key at epoch 0\" rather than through the\n * dedicated `getVaultProviderBTCKey` getter, which\n * https://github.com/babylonlabs-io/vault-contracts-aave-v4/pull/539 removes.\n * Epoch 0 predates any rotation — appended versions are stamped at epoch 1 or\n * later — so it resolves to the registration key, and the contracts team has\n * confirmed that is a property we can rely on rather than an implementation\n * detail. The devnet comparison behind that claim — both getters returning the\n * identical key for a provider that *has* rotated, while\n * `getCurrentOperationBtcKey` differed — is recorded in\n * https://github.com/babylonlabs-io/babylon-toolkit/issues/2188.\n *\n * This makes the read RFC-006-only, where the removed getter also existed on a\n * legacy registry. That costs nothing: every caller of this method already\n * resolves participant keys through `OperationKeyReader`, so all of them\n * require an RFC-006 registry regardless.\n *\n * Validates length, hex form, and secp256k1 curve membership before minting\n * the brand. Returns 64-char lowercase hex without the `0x` prefix.\n */\n async getVaultProviderGenesisBtcPubKey(\n vpAddress: Address,\n blockNumber?: bigint,\n ): Promise<OnChainBtcPubkey> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getOperationBtcKeyAtEpoch\",\n args: [vpAddress, VP_GENESIS_KEY_EPOCH],\n blockNumber,\n })) as Hex;\n return assertOnChainBtcPubkey(\n result,\n `getOperationBtcKeyAtEpoch (vp=${vpAddress}, epoch=${VP_GENESIS_KEY_EPOCH})`,\n );\n }\n\n /**\n * Read a vault provider's *current* RFC-006 operation BTC key.\n *\n * Falls back on-chain to the registration key when the provider has never\n * rotated, so this returns the same value as\n * `getVaultProviderGenesisBtcPubKey` until the first rotation.\n *\n * This is the key the VP's server signs its BIP-322 auth tokens with — a\n * live per-operator identity, not a per-vault binding, so the auth pin uses\n * the current key rather than any vault's frozen epoch.\n */\n async getCurrentVaultProviderOperationBtcKey(\n vpAddress: Address,\n ): Promise<OnChainBtcPubkey> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getCurrentOperationBtcKey\",\n args: [vpAddress],\n })) as Hex;\n return assertOnChainBtcPubkey(\n result,\n `getCurrentOperationBtcKey (vp=${vpAddress})`,\n );\n }\n\n /**\n * Read a vault's frozen RFC-006 operation-key epochs.\n *\n * Reads `getBtcVaultProtocolInfo` through the **extended** ABI, which is only\n * valid against an RFC-006 registry: against one whose `BTCVaultProtocolInfo`\n * struct is not extended this call does not fail for a populated vault, it\n * silently returns three words of tail data as epochs. Nothing here can detect\n * that, so the guarantee is a deployment one — every network this ships to has\n * the RFC-006 getters, and mainnet is a fresh RFC-006 deploy.\n *\n * A registry missing the operation-key getters entirely is the *safer* of the\n * two cases: `resolveParticipantKeysAtEpochs` reverts downstream and these\n * epochs never reach key resolution. See {@link UINT64_EXCLUSIVE_UPPER_BOUND}\n * for which state the range check actually guards, and\n * `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n */\n async getVaultKeyEpochs(vaultId: Hex): Promise<KeyEpochs> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryKeyEpochsABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n })) as unknown as KeyEpochs;\n\n return mapKeyEpochs(result, vaultId);\n }\n\n async getVaultKeyEpochsBatch(vaultIds: readonly Hex[]): Promise<KeyEpochs[]> {\n if (vaultIds.length === 0) return [];\n\n const results = await this.publicClient.multicall({\n contracts: vaultIds.map((vaultId) => ({\n address: this.contractAddress,\n abi: BTCVaultRegistryKeyEpochsABI as Abi,\n functionName: \"getBtcVaultProtocolInfo\" as const,\n args: [vaultId] as const,\n })),\n allowFailure: false,\n });\n\n return results.map((info, i) =>\n mapKeyEpochs(info as unknown as KeyEpochs, vaultIds[i]),\n );\n }\n\n async getVaultBasicInfo(vaultId: Hex): Promise<VaultBasicInfo> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n })) as RawVaultBasicInfo;\n\n return mapVaultBasicInfo(result);\n }\n\n async getVaultProtocolInfo(vaultId: Hex): Promise<VaultProtocolInfo> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n })) as RawVaultProtocolInfo;\n\n return mapVaultProtocolInfo(result);\n }\n\n async getProtocolInfoBatch(\n vaultIds: readonly Hex[],\n ): Promise<VaultProtocolInfo[]> {\n if (vaultIds.length === 0) return [];\n\n const results = await this.publicClient.multicall({\n contracts: vaultIds.map((vaultId) => ({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI as Abi,\n functionName: \"getBtcVaultProtocolInfo\" as const,\n args: [vaultId] as const,\n })),\n allowFailure: false,\n });\n\n return results.map((info, i) => {\n const result = info as unknown as RawVaultProtocolInfo;\n if (\n !result.depositorSignedPeginTx ||\n result.depositorSignedPeginTx === \"0x\"\n ) {\n // An empty record is not proof the vault is absent: a lagging RPC\n // node returns HTTP 200 with a zero struct, so no retry below this\n // layer can see it. Single-shot is only safe because the finality\n // gate (`waitForPeginRegistrationDepth`) runs first on the deposit\n // path — move this ahead of it and the read-after-write race returns.\n // The vault app matches this message to render \"still confirming\".\n throw new Error(\n `Vault ${vaultIds[i]} not found on-chain or has no pegin transaction`,\n );\n }\n return mapVaultProtocolInfo(result);\n });\n }\n\n /**\n * Read the protocol pegin fee (in wei) for a given vault provider.\n * Mirrors the `getPegInFee(address)` view on BTCVaultRegistry.\n */\n async getPegInFee(vaultProvider: Address): Promise<bigint> {\n return (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getPegInFee\",\n args: [vaultProvider],\n })) as bigint;\n }\n\n /**\n * Read a vault provider's current commission in basis points from\n * BTCVaultRegistry. The contract enforces `commissionBps < 10000`, so the\n * legitimate range is `[0, 9999]`; anything outside indicates a wrong\n * contract address or ABI drift and is surfaced as an error rather than\n * trusted.\n */\n async getVaultProviderCommission(vaultProvider: Address): Promise<number> {\n // viem infers `number` from the `uint16` return in the `as const` ABI.\n const bps = await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getVaultProviderCommission\",\n args: [vaultProvider],\n });\n\n if (!Number.isInteger(bps) || bps < 0 || bps > MAX_VP_COMMISSION_BPS) {\n throw new Error(\n `getVaultProviderCommission returned ${bps} bps for ${vaultProvider}, ` +\n `outside the protocol range [0, ${MAX_VP_COMMISSION_BPS}]`,\n );\n }\n\n return bps;\n }\n\n async getVaultData(vaultId: Hex): Promise<VaultData> {\n // One round-trip for both structs (hard-fail): they feed signing/refund/\n // broadcast rebinds, so reading them in a single multicall also pins both\n // to the same block — no basic/protocol skew across two `eth_call`s.\n const [basicRaw, protocolRaw] = await this.publicClient.multicall({\n contracts: [\n {\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n },\n {\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n },\n ],\n allowFailure: false,\n });\n\n const basic = mapVaultBasicInfo(basicRaw);\n const protocol = mapVaultProtocolInfo(protocolRaw);\n\n if (\n !protocol.depositorSignedPeginTx ||\n protocol.depositorSignedPeginTx === \"0x\"\n ) {\n throw new Error(\n `Vault ${vaultId} not found on-chain or has no pegin transaction`,\n );\n }\n\n return { basic, protocol };\n }\n\n}\n","import {\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 { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { handleContractError } from \"../../contracts/errors\";\nimport {\n capMaxAcceptableCommissionBps,\n COMMISSION_BPS_HEADROOM,\n} from \"../../deposit-terms/commissionCeiling\";\nimport { waitForTransactionReceiptSmartAware } from \"../../utils/eth\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\nimport { assertPayoutScriptMatchesPopKey } from \"./payout-script\";\nimport { calculateBtcTxHash, derivePeginVaultId } from \"./pegin-transaction\";\nimport { ViemVaultRegistryReader } from \"./vault-registry-reader\";\n\n/** Referral code sent with peg-in registration. Zero means no referral. */\nexport const NO_REFERRAL_CODE = 0;\nconst UINT8_MAX = 255;\n// Match the prior vault-service timeout. A dropped transaction must not wait forever.\nconst RECEIPT_TIMEOUT_MS = 120_000;\n\nfunction ensureHex(value: string, label: string): Hex {\n const prefixed = value.startsWith(\"0x\")\n ? value\n : value.startsWith(\"0X\")\n ? `0x${value.slice(2)}`\n : `0x${value}`;\n if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(prefixed)) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n return prefixed as Hex;\n}\n\nfunction assertBytes32(value: Hex, label: string): void {\n if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {\n throw new Error(`${label} must be a 32-byte hex value`);\n }\n}\n\nfunction assertHtlcVout(value: number): void {\n if (!Number.isInteger(value) || value < 0 || value > UINT8_MAX) {\n throw new Error(`htlcVout must be a uint8, got ${value}`);\n }\n}\n\n/** A PoP prepared by a Bitcoin wallet, reusable by the ETH submit client. */\nexport interface PopSignature {\n btcPopSignature: Hex;\n depositorEthAddress: Address;\n /** x-only secp256k1 public key, 64 hex chars without `0x`. */\n depositorBtcPubkey: string;\n}\n\nexport interface ViemPeginRegistrationClientConfig {\n ethWallet: WalletClient;\n ethChain: Chain;\n publicClient: PublicClient;\n btcVaultRegistry: Address;\n receiptTimeoutMs?: number;\n /**\n * Refuse to register without a `quotedCommissionBps`. Set it to `true` when\n * the depositor approved deposit terms on a device: approval froze the\n * commission ceiling from the quote, so the chain-current fallback could\n * admit a commission the device would later refuse to pay out.\n *\n * Required, with no default: an omitted flag would silently pick the unsafe\n * direction for the integrator least able to probe the wallet capability.\n */\n requireQuotedCommissionBps: boolean;\n}\n\nexport interface RegisterPeginOnChainParams {\n unsignedPrePeginTx: string;\n depositorSignedPeginTx: string;\n vaultProvider: Address;\n hashlock: Hex;\n depositorWotsPkHash: Hex;\n popSignature: PopSignature;\n /** Raw x-only, compressed, or uncompressed BTC pubkey from the PoP wallet. */\n depositorBtcPubkeyRaw: string;\n htlcVout: number;\n /**\n * Bitcoin output script bytes, not an address. The client verifies that the\n * script pays the proof-of-possession key before it submits the transaction.\n */\n depositorPayoutScriptPubKey: string;\n quotedCommissionBps?: number;\n}\n\nexport interface PeginRegistrationResult {\n ethTxHash: Hex;\n vaultId: Hex;\n peginTxHash: Hex;\n}\n\nexport interface BatchPeginRegistrationItem {\n depositorSignedPeginTx: string;\n hashlock: Hex;\n htlcVout: number;\n /**\n * Bitcoin output script bytes, not an address. The client verifies that the\n * script pays the proof-of-possession key before it submits the transaction.\n */\n depositorPayoutScriptPubKey: string;\n depositorWotsPkHash: Hex;\n}\n\nexport interface RegisterPeginBatchOnChainParams {\n vaultProvider: Address;\n unsignedPrePeginTx: string;\n requests: BatchPeginRegistrationItem[];\n popSignature: PopSignature;\n /** Raw x-only, compressed, or uncompressed BTC pubkey from the PoP wallet. */\n depositorBtcPubkeyRaw: string;\n quotedCommissionBps?: number;\n}\n\nexport interface BatchPeginRegistrationResultItem {\n vaultId: Hex;\n peginTxHash: Hex;\n}\n\nexport interface PeginBatchRegistrationResult {\n ethTxHash: Hex;\n vaults: BatchPeginRegistrationResultItem[];\n}\n\n/**\n * Ethereum-only client for the on-chain half of peg-in registration.\n *\n * It consumes Bitcoin artifacts that were prepared earlier, but owns no BTC\n * wallet and imports neither Bitcoin libraries nor the Rust/WASM package.\n */\nexport class ViemPeginRegistrationClient {\n constructor(private readonly config: ViemPeginRegistrationClientConfig) {}\n\n async registerPeginOnChain(\n params: RegisterPeginOnChainParams,\n ): Promise<PeginRegistrationResult> {\n const request = {\n ...params,\n popSignature: { ...params.popSignature },\n };\n this.assertQuotedCommissionPresentWhenRequired(request.quotedCommissionBps);\n const depositor = this.assertPopMatchesEthAccount(request.popSignature);\n const depositorBtcPubkey = this.normalizeBtcPubkey(request.popSignature);\n const btcPopSignature = ensureHex(\n request.popSignature.btcPopSignature,\n \"btcPopSignature\",\n );\n const normalized = this.normalizeRequest(\n request,\n depositor,\n depositorBtcPubkey,\n );\n\n await this.assertVaultDoesNotExist(\n normalized.vaultId,\n normalized.peginTxHash,\n );\n const peginFee = await this.readPeginFee(request.vaultProvider);\n const maxCommission = await this.resolveMaxAcceptableCommissionBps(\n request.vaultProvider,\n request.quotedCommissionBps,\n );\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequest\",\n args: [\n depositor,\n depositorBtcPubkey,\n btcPopSignature,\n normalized.unsignedPrePeginTx,\n normalized.depositorSignedPeginTx,\n request.vaultProvider,\n maxCommission,\n request.hashlock,\n request.htlcVout,\n normalized.payoutScript,\n request.depositorWotsPkHash,\n ],\n });\n\n const ethTxHash = await this.sendAndWait(\n callData,\n peginFee,\n false,\n depositor,\n );\n return {\n ethTxHash,\n vaultId: normalized.vaultId,\n peginTxHash: normalized.peginTxHash,\n };\n }\n\n async registerPeginBatchOnChain(\n params: RegisterPeginBatchOnChainParams,\n ): Promise<PeginBatchRegistrationResult> {\n const batch = {\n ...params,\n popSignature: { ...params.popSignature },\n requests: params.requests.map((request) => ({ ...request })),\n };\n if (batch.requests.length === 0) {\n throw new Error(\"Batch pegin requires at least one request\");\n }\n this.assertQuotedCommissionPresentWhenRequired(batch.quotedCommissionBps);\n const depositor = this.assertPopMatchesEthAccount(batch.popSignature);\n const unsignedPrePeginTx = ensureHex(\n batch.unsignedPrePeginTx,\n \"unsignedPrePeginTx\",\n );\n const depositorBtcPubkey = this.normalizeBtcPubkey(batch.popSignature);\n const btcPopSignature = ensureHex(\n batch.popSignature.btcPopSignature,\n \"btcPopSignature\",\n );\n\n const vaults: BatchPeginRegistrationResultItem[] = [];\n const requests = [];\n const seenVaultIds = new Set<string>();\n for (const request of batch.requests) {\n const normalized = this.normalizeRequest(\n {\n ...request,\n unsignedPrePeginTx: batch.unsignedPrePeginTx,\n vaultProvider: batch.vaultProvider,\n depositorBtcPubkeyRaw: batch.depositorBtcPubkeyRaw,\n },\n depositor,\n depositorBtcPubkey,\n );\n if (seenVaultIds.has(normalized.vaultId)) {\n throw new Error(`Duplicate vault in batch: ${normalized.vaultId}`);\n }\n seenVaultIds.add(normalized.vaultId);\n vaults.push({\n vaultId: normalized.vaultId,\n peginTxHash: normalized.peginTxHash,\n });\n requests.push({\n depositorBtcPubKey: depositorBtcPubkey,\n btcPopSignature,\n unsignedPrePeginTx,\n depositorSignedPeginTx: normalized.depositorSignedPeginTx,\n hashlock: request.hashlock,\n htlcVout: request.htlcVout,\n referralCode: NO_REFERRAL_CODE,\n depositorPayoutBtcAddress: normalized.payoutScript,\n depositorWotsPkHash: request.depositorWotsPkHash,\n });\n }\n for (const vault of vaults) {\n await this.assertVaultDoesNotExist(vault.vaultId, vault.peginTxHash);\n }\n\n const peginFee = await this.readPeginFee(batch.vaultProvider);\n const maxCommission = await this.resolveMaxAcceptableCommissionBps(\n batch.vaultProvider,\n batch.quotedCommissionBps,\n );\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequestBatch\",\n args: [depositor, batch.vaultProvider, maxCommission, requests],\n });\n const ethTxHash = await this.sendAndWait(\n callData,\n peginFee * BigInt(batch.requests.length),\n true,\n depositor,\n );\n return { ethTxHash, vaults };\n }\n\n private assertQuotedCommissionPresentWhenRequired(\n quotedCommissionBps?: number,\n ): void {\n if (\n quotedCommissionBps === undefined &&\n this.config.requireQuotedCommissionBps\n ) {\n throw new Error(\n \"quotedCommissionBps is required when the wallet approved deposit \" +\n \"terms: the registration ceiling must anchor to the approved quote.\",\n );\n }\n }\n\n private assertPopMatchesEthAccount(pop: PopSignature): Address {\n return this.assertEthAccount(pop.depositorEthAddress);\n }\n\n private assertEthAccount(expectedDepositor: Address): Address {\n const account = this.config.ethWallet.account;\n if (!account) throw new Error(\"Ethereum wallet account not found\");\n if (!isAddressEqual(expectedDepositor, account.address)) {\n throw new Error(\n `Proof of possession was signed for ${expectedDepositor} ` +\n `but the Ethereum wallet is currently connected to ${account.address}. ` +\n `Reconnect the original account or sign a new proof of possession.`,\n );\n }\n return account.address;\n }\n\n private normalizeBtcPubkey(pop: PopSignature): Hex {\n return `0x${assertOnChainBtcPubkey(\n ensureHex(pop.depositorBtcPubkey, \"Proof of possession BTC pubkey\"),\n \"Proof of possession BTC pubkey\",\n )}`;\n }\n\n private normalizeRequest(\n params: Omit<RegisterPeginOnChainParams, \"popSignature\">,\n depositor: Address,\n depositorBtcPubkey: Hex,\n ) {\n assertBytes32(params.hashlock, \"hashlock\");\n assertBytes32(params.depositorWotsPkHash, \"depositorWotsPkHash\");\n assertHtlcVout(params.htlcVout);\n const unsignedPrePeginTx = ensureHex(\n params.unsignedPrePeginTx,\n \"unsignedPrePeginTx\",\n );\n const depositorSignedPeginTx = ensureHex(\n params.depositorSignedPeginTx,\n \"depositorSignedPeginTx\",\n );\n const peginTxHash = calculateBtcTxHash(depositorSignedPeginTx);\n return {\n unsignedPrePeginTx,\n depositorSignedPeginTx,\n payoutScript: assertPayoutScriptMatchesPopKey(\n params.depositorPayoutScriptPubKey,\n depositorBtcPubkey,\n params.depositorBtcPubkeyRaw,\n ),\n peginTxHash,\n vaultId: ensureHex(derivePeginVaultId(peginTxHash, depositor), \"vaultId\"),\n };\n }\n\n private async assertVaultDoesNotExist(\n vaultId: Hex,\n peginTxHash: Hex,\n ): Promise<void> {\n const result = (await this.config.publicClient.readContract({\n address: this.config.btcVaultRegistry,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n })) as { depositor: Address };\n if (result.depositor !== zeroAddress) {\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\n private async readPeginFee(vaultProvider: Address): Promise<bigint> {\n try {\n return (await this.config.publicClient.readContract({\n address: this.config.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 contract address.\",\n { cause: error },\n );\n }\n }\n\n private async resolveMaxAcceptableCommissionBps(\n vaultProvider: Address,\n quotedCommissionBps?: number,\n ): Promise<number> {\n let currentBps: number;\n try {\n currentBps = await new ViemVaultRegistryReader(\n this.config.publicClient,\n this.config.btcVaultRegistry,\n ).getVaultProviderCommission(vaultProvider);\n } catch (error) {\n throw new Error(\n \"Failed to query vault provider commission from the contract. \" +\n \"Please check your network connection and contract address.\",\n { cause: error },\n );\n }\n if (quotedCommissionBps !== undefined) {\n if (currentBps > quotedCommissionBps + COMMISSION_BPS_HEADROOM) {\n throw new Error(\n `Vault provider commission changed since quote: quoted ${quotedCommissionBps} bps, ` +\n `chain currently reports ${currentBps} bps (allowed drift ${COMMISSION_BPS_HEADROOM} bps). ` +\n `Please refresh and try again.`,\n );\n }\n return capMaxAcceptableCommissionBps(quotedCommissionBps);\n }\n return capMaxAcceptableCommissionBps(currentBps);\n }\n\n private async sendAndWait(\n data: Hex,\n value: bigint,\n batch: boolean,\n depositor: Address,\n ): Promise<Hex> {\n let account = this.assertEthAccount(depositor);\n let gas: bigint;\n try {\n gas = await this.config.publicClient.estimateGas({\n to: this.config.btcVaultRegistry,\n data,\n value,\n account,\n });\n } catch (error) {\n handleContractError(error);\n }\n\n account = this.assertEthAccount(depositor);\n let submittedHash: Hex;\n try {\n submittedHash = await this.config.ethWallet.sendTransaction({\n to: this.config.btcVaultRegistry,\n data,\n value,\n gas,\n account,\n chain: this.config.ethChain,\n });\n } catch (error) {\n handleContractError(error);\n }\n const receipt = await waitForTransactionReceiptSmartAware({\n publicClient: this.config.publicClient,\n walletAddress: depositor,\n hash: submittedHash,\n timeout: this.config.receiptTimeoutMs ?? RECEIPT_TIMEOUT_MS,\n });\n if (receipt.status === \"reverted\") {\n handleContractError(\n new Error(\n `${batch ? \"Batch transaction\" : \"Transaction\"} reverted. ` +\n `Hash: ${receipt.transactionHash}. Check a block explorer for details.`,\n ),\n );\n }\n return receipt.transactionHash;\n }\n}\n"],"names":["COMMISSION_BPS_HEADROOM","MAX_ACCEPTABLE_COMMISSION_BPS_CAP","capMaxAcceptableCommissionBps","bps","MAX_VP_COMMISSION_BPS_EXCLUSIVE","Rho160","Id160","_","i","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","offset","al","ar","bl","br","cl","cr","dl","dr","el","er","rGroup","hbl","hbr","rl","rr","sl","sr","tl","rotl","tr","clean","ripemd160","createHasher","P2TR_SCRIPT_PREFIX","P2WPKH_SCRIPT_PREFIX","HASH160_BYTES","COMPRESSED_PUBKEY_BYTES","UNCOMPRESSED_PUBKEY_BYTES","SEC1_EVEN_Y_PREFIX","SEC1_ODD_Y_PREFIX","SEC1_UNCOMPRESSED_PREFIX","normalizeHex","value","label","body","deriveP2trScript","xOnlyPubkey","pubkeyBytes","hexToBytes","internalKey","schnorr","tweak","secp256k1","outputKey","bytesToHex","normalizePayoutPubkey","normalized","pubkey","assertOnChainBtcPubkey","isCompressed","isUncompressed","deriveP2wpkhScript","sha256","assertPayoutScriptMatchesPopKey","scriptPubKey","depositorBtcPubkey","depositorBtcPubkeyRaw","payoutScript","MAX_PAYOUT_SCRIPT_LEN","keyBody","payoutPubkey","decodeHex","bytes","encodeHex","byte","concatBytes","chunks","result","length","chunk","serializeWithoutWitness","transaction","take","readLittleEndian","readCompactSize","start","prefix","version","hasWitness","inputCount","inputs","scriptLength","outputCount","outputs","hasWitnessData","itemCount","itemLength","locktime","calculateBtcTxHash","transactionHex","serialized","digest","derivePeginVaultId","peginTxHash","depositor","normalizedPeginTxHash","normalizedDepositor","isAddress","keccak256","encodeAbiParameters","UINT16_MAX","MAX_BASIS_POINTS","UINT32_MAX","UINT8_MAX","assertValidOffchainParamsVersion","validateOffchainParams","params","errors","validateTBVProtocolParams","validatePegInConfiguration","config","assertValidVaultCoreVersion","MAX_VP_COMMISSION_BPS","mapVaultBasicInfo","mapVaultProtocolInfo","offchainParamsVersion","UINT64_EXCLUSIVE_UPPER_BOUND","VP_GENESIS_KEY_EPOCH","assertEpochInRange","field","vaultId","mapKeyEpochs","ViemVaultRegistryReader","publicClient","contractAddress","vpAddress","blockNumber","BTCVaultRegistryABI","BTCVaultRegistryKeyEpochsABI","vaultIds","info","vaultProvider","basicRaw","protocolRaw","basic","protocol","NO_REFERRAL_CODE","RECEIPT_TIMEOUT_MS","ensureHex","prefixed","assertBytes32","assertHtlcVout","ViemPeginRegistrationClient","request","btcPopSignature","peginFee","maxCommission","callData","encodeFunctionData","batch","unsignedPrePeginTx","vaults","requests","seenVaultIds","vault","quotedCommissionBps","pop","expectedDepositor","account","isAddressEqual","depositorSignedPeginTx","zeroAddress","error","currentBps","data","gas","handleContractError","submittedHash","receipt","waitForTransactionReceiptSmartAware"],"mappings":"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","x_google_ignoreList":[1]}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var lt=Object.defineProperty;var dt=(t,e,n)=>e in t?lt(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var E=(t,e,n)=>dt(t,typeof e!="symbol"?e+"":e,n);const B=require("viem"),f=require("./BTCVaultRegistry.abi-z7d_eP22.cjs"),I=require("./BTCVaultRegistryKeyEpochs.abi-CrQiTLfA.cjs"),A=require("./constants-BTZdyOuk.cjs"),pt=require("./tbv/core/utils/eth/index.cjs"),x=require("./onChainBtcPubkey-BbxRrbvg.cjs"),y=require("./secp256k1-DDHQ1_za.cjs"),g=require("./sha2-DI0-0SHr.cjs"),V=25,X=9999;function _(t){if(!Number.isInteger(t)||t<0||t>=A.MAX_VP_COMMISSION_BPS_EXCLUSIVE)throw new Error(`Quoted commissionBps must be an integer in [0, ${A.MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${t}`);return Math.min(t+V,X)}const gt=Uint8Array.from([7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8]),L=Uint8Array.from(new Array(16).fill(0).map((t,e)=>e)),ft=L.map(t=>(9*t+5)%16),z=(()=>{const n=[[L],[ft]];for(let o=0;o<4;o++)for(let i of n)i.push(i[o].map(a=>gt[a]));return n})(),Q=z[0],Y=z[1],G=[[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8],[12,13,11,15,6,9,9,7,12,15,11,13,7,8,7,7],[13,15,14,11,7,7,6,8,13,14,13,12,5,5,6,9],[14,11,12,14,8,6,5,5,15,12,15,14,9,9,8,6],[15,12,13,13,9,5,8,6,14,11,12,11,8,6,5,5]].map(t=>Uint8Array.from(t)),Pt=Q.map((t,e)=>t.map(n=>G[e][n])),mt=Y.map((t,e)=>t.map(n=>G[e][n])),bt=Uint32Array.from([0,1518500249,1859775393,2400959708,2840853838]),yt=Uint32Array.from([1352829926,1548603684,1836072691,2053994217,0]);function O(t,e,n,o){return t===0?e^n^o:t===1?e&n|~e&o:t===2?(e|~n)^o:t===3?e&o|n&~o:e^(n|~o)}const T=new Uint32Array(16);class Ct extends g.HashMD{constructor(){super(64,20,8,!0);E(this,"h0",1732584193);E(this,"h1",-271733879);E(this,"h2",-1732584194);E(this,"h3",271733878);E(this,"h4",-1009589776)}get(){const{h0:n,h1:o,h2:i,h3:a,h4:c}=this;return[n,o,i,a,c]}set(n,o,i,a,c){this.h0=n|0,this.h1=o|0,this.h2=i|0,this.h3=a|0,this.h4=c|0}process(n,o){for(let r=0;r<16;r++,o+=4)T[r]=n.getUint32(o,!0);let i=this.h0|0,a=i,c=this.h1|0,l=c,d=this.h2|0,p=d,P=this.h3|0,b=P,s=this.h4|0,h=s;for(let r=0;r<5;r++){const u=4-r,C=bt[r],rt=yt[r],at=Q[r],ct=Y[r],ut=Pt[r],ht=mt[r];for(let m=0;m<16;m++){const $=g.rotl(i+O(r,c,d,P)+T[at[m]]+C,ut[m])+s|0;i=s,s=P,P=g.rotl(d,10)|0,d=c,c=$}for(let m=0;m<16;m++){const $=g.rotl(a+O(u,l,p,b)+T[ct[m]]+rt,ht[m])+h|0;a=h,h=b,b=g.rotl(p,10)|0,p=l,l=$}}this.set(this.h1+d+b|0,this.h2+P+h|0,this.h3+s+a|0,this.h4+i+l|0,this.h0+c+p|0)}roundClean(){g.clean(T)}destroy(){this.destroyed=!0,g.clean(this.buffer),this.set(0,0,0,0,0)}}const j=g.createHasher(()=>new Ct),wt="5120",N="0014",Bt=20,H=33,Et=65,It=2,xt=3,Tt=4;function J(t,e){const n=t.startsWith("0x")||t.startsWith("0X")?t.slice(2):t;if(!/^(?:[0-9a-fA-F]{2})+$/.test(n))throw new Error(`${e} must be non-empty, even-length hex`);return`0x${n.toLowerCase()}`}function At(t){const e=g.hexToBytes(t),n=y.schnorr.utils.lift_x(BigInt(`0x${t}`)),o=y.schnorr.utils.bytesToNumberBE(y.schnorr.utils.taggedHash("TapTweak",e));if(o>=y.secp256k1.CURVE.n)throw new Error("Proof of possession BTC pubkey has an invalid TapTweak");const i=o===0n?n:n.add(y.schnorr.Point.BASE.multiply(o));return`0x${wt}${g.bytesToHex(y.schnorr.utils.pointToBytes(i))}`}function Vt(t){const e=J(t,"depositorBtcPubkeyRaw"),n=g.hexToBytes(e.slice(2));if(n.length===32)return{xOnlyPubkey:x.assertOnChainBtcPubkey(e,"Payout BTC pubkey")};const o=n.length===H&&(n[0]===It||n[0]===xt),i=n.length===Et&&n[0]===Tt;if(!o&&!i)throw new Error("depositorBtcPubkeyRaw must be x-only, compressed, or uncompressed");try{y.secp256k1.Point.fromBytes(n)}catch{throw new Error("depositorBtcPubkeyRaw is not a valid BTC pubkey")}return{xOnlyPubkey:g.bytesToHex(n.subarray(1,H)),compressedPubkey:o?n:void 0}}function vt(t){return`0x${N}${g.bytesToHex(j(g.sha256(t)))}`}function $t(t,e,n){const o=J(t,"depositorPayoutScriptPubKey");if((o.length-2)/2>A.MAX_PAYOUT_SCRIPT_LEN)throw new Error(`depositorPayoutScriptPubKey exceeds ${A.MAX_PAYOUT_SCRIPT_LEN} bytes`);const i=e.startsWith("0x")||e.startsWith("0X")?e.slice(2):e,a=x.assertOnChainBtcPubkey(`0x${i}`,"Proof of possession BTC pubkey"),c=Vt(n);if(c.xOnlyPubkey!==a)throw new Error("depositorBtcPubkeyRaw does not match the proof of possession BTC pubkey");if(o===At(a))return o;if(o.startsWith(`0x${N}`)&&o.length===2+N.length+Bt*2){if(!c.compressedPubkey)throw new Error("A P2WPKH payout requires a compressed BTC pubkey");if(o===vt(c.compressedPubkey))return o}throw new Error("depositorPayoutScriptPubKey does not match the proof of possession BTC pubkey")}function St(t,e){const n=t.startsWith("0x")?t.slice(2):t;if(n.length===0||n.length%2!==0)throw new Error(`${e} must be non-empty, even-length hex`);if(!/^[0-9a-fA-F]+$/.test(n))throw new Error(`${e} contains non-hex characters`);const o=new Uint8Array(n.length/2);for(let i=0;i<o.length;i++)o[i]=Number.parseInt(n.slice(i*2,i*2+2),16);return o}function Rt(t){return Array.from(t,e=>e.toString(16).padStart(2,"0")).join("")}function kt(t){const e=new Uint8Array(t.reduce((o,i)=>o+i.length,0));let n=0;for(const o of t)e.set(o,n),n+=o.length;return e}function _t(t){let e=0;const n=(s,h)=>{if(!Number.isSafeInteger(s)||s<0)throw new Error(`Invalid ${h} length ${s}`);if(e+s>t.length)throw new Error(`Truncated Bitcoin transaction while reading ${h}`);const r=t.slice(e,e+s);return e+=s,r},o=(s,h)=>{const r=n(s,h);let u=0n;for(let C=r.length-1;C>=0;C--)u=u<<8n|BigInt(r[C]);return u},i=s=>{const h=e,r=n(1,s)[0];let u;if(r<253)u=BigInt(r);else if(r===253){if(u=o(2,s),u<0xfdn)throw new Error(`Non-canonical ${s}`)}else if(r===254){if(u=o(4,s),u<=0xffffn)throw new Error(`Non-canonical ${s}`)}else if(u=o(8,s),u<=0xffffffffn)throw new Error(`Non-canonical ${s}`);if(u>BigInt(Number.MAX_SAFE_INTEGER))throw new Error(`${s} exceeds JavaScript's safe integer range`);return{encoded:t.slice(h,e),value:Number(u)}},a=n(4,"version"),c=t[e]===0&&t[e+1]===1;c&&(e+=2);const l=i("input count"),d=[];for(let s=0;s<l.value;s++){const h=e;n(32,`input ${s} previous transaction hash`),n(4,`input ${s} previous output index`);const r=i(`input ${s} script length`);n(r.value,`input ${s} script`),n(4,`input ${s} sequence`),d.push(t.slice(h,e))}const p=i("output count"),P=[];for(let s=0;s<p.value;s++){const h=e;n(8,`output ${s} value`);const r=i(`output ${s} script length`);n(r.value,`output ${s} script`),P.push(t.slice(h,e))}if(c){let s=!1;for(let h=0;h<l.value;h++){const r=i(`input ${h} witness item count`);s||(s=r.value>0);for(let u=0;u<r.value;u++){const C=i(`input ${h} witness item ${u} length`);n(C.value,`input ${h} witness item ${u}`)}}if(!s)throw new Error("Bitcoin transaction has superfluous witness marker")}const b=n(4,"locktime");if(e!==t.length)throw new Error(`Bitcoin transaction has ${t.length-e} trailing byte(s)`);return kt([a,l.encoded,...d,p.encoded,...P,b])}function Z(t){const e=_t(St(t,"transactionHex")),n=g.sha256(g.sha256(e));return n.reverse(),`0x${Rt(n)}`}function tt(t,e){const n=t.startsWith("0x")?t:`0x${t}`;if(!/^0x[0-9a-fA-F]{64}$/.test(n))throw new Error("peginTxHash must be a 32-byte hex value");const o=e.startsWith("0x")?e:`0x${e}`;if(!B.isAddress(o,{strict:!0}))throw new Error(`Invalid depositor Ethereum address: ${e}`);return B.keccak256(B.encodeAbiParameters([{type:"bytes32"},{type:"address"}],[n,o])).slice(2)}const S=65535,K=1e4,v=4294967295,M=255;function et(t){if(!Number.isInteger(t)||t<0||t>v)throw new Error(`Invalid offchainParamsVersion from contract: must be a uint32, got ${t}`)}function nt(t){const e=[];if(t.timelockAssert<=0n&&e.push(`timelockAssert must be positive, got ${t.timelockAssert}`),t.timelockAssert>BigInt(S)&&e.push(`timelockAssert ${t.timelockAssert} exceeds uint16 max (${S})`),t.timelockChallengeAssert<=0n&&e.push(`timelockChallengeAssert must be positive, got ${t.timelockChallengeAssert}`),t.tRefund<=0&&e.push(`tRefund must be positive, got ${t.tRefund}`),t.tStale<=0&&e.push(`tStale must be positive, got ${t.tStale}`),t.securityCouncilKeys.length===0&&e.push("securityCouncilKeys must not be empty"),t.councilQuorum<=0&&e.push(`councilQuorum must be positive, got ${t.councilQuorum}`),t.councilQuorum>t.securityCouncilKeys.length&&e.push(`councilQuorum (${t.councilQuorum}) exceeds securityCouncilKeys count (${t.securityCouncilKeys.length})`),t.feeRate<=0n&&e.push(`feeRate must be positive, got ${t.feeRate}`),t.minPeginFeeRate<=0n&&e.push(`minPeginFeeRate must be positive, got ${t.minPeginFeeRate}`),(!Number.isInteger(t.proverCircuitVersion)||t.proverCircuitVersion<0||t.proverCircuitVersion>S)&&e.push(`proverCircuitVersion must be a uint16, got ${t.proverCircuitVersion}`),(!Number.isInteger(t.minPrepeginDepth)||t.minPrepeginDepth<=0||t.minPrepeginDepth>v)&&e.push(`minPrepeginDepth must be a uint32 in [1, ${v}], got ${t.minPrepeginDepth}`),t.babeTotalInstances<=0&&e.push(`babeTotalInstances must be positive, got ${t.babeTotalInstances}`),t.babeInstancesToFinalize<=0&&e.push(`babeInstancesToFinalize must be positive, got ${t.babeInstancesToFinalize}`),t.babeInstancesToFinalize>t.babeTotalInstances&&e.push(`babeInstancesToFinalize (${t.babeInstancesToFinalize}) exceeds babeTotalInstances (${t.babeTotalInstances})`),(t.minVpCommissionBps<0||t.minVpCommissionBps>K)&&e.push(`minVpCommissionBps must be in [0, ${K}], got ${t.minVpCommissionBps}`),e.length>0)throw new Error(`Invalid offchain protocol parameters: ${e.join("; ")}`)}function ot(t){const e=[];if(t.minimumPegInAmount<=0n&&e.push(`minimumPegInAmount must be positive, got ${t.minimumPegInAmount}`),t.maxPegInAmount<t.minimumPegInAmount&&e.push(`maxPegInAmount (${t.maxPegInAmount}) must be >= minimumPegInAmount (${t.minimumPegInAmount})`),t.pegInAckTimeout<=0n&&e.push(`pegInAckTimeout must be positive, got ${t.pegInAckTimeout}`),t.pegInActivationTimeout<=0n&&e.push(`pegInActivationTimeout must be positive, got ${t.pegInActivationTimeout}`),(!Number.isInteger(t.maxHtlcOutputCount)||t.maxHtlcOutputCount<=0||t.maxHtlcOutputCount>M)&&e.push(`maxHtlcOutputCount must be an integer in [1, ${M}], got ${t.maxHtlcOutputCount}`),(typeof t.expiredPegInGraceBlocks!="bigint"||t.expiredPegInGraceBlocks<=0n)&&e.push(`expiredPegInGraceBlocks must be a positive bigint, got ${t.expiredPegInGraceBlocks}`),e.length>0)throw new Error(`Invalid TBV protocol parameters: ${e.join("; ")}`)}function Nt(t){if(ot(t),nt(t.offchainParams),!Number.isInteger(t.offchainParamsVersion)||t.offchainParamsVersion<0||t.offchainParamsVersion>v)throw new Error(`Invalid peg-in configuration: offchainParamsVersion must be a uint32, got ${t.offchainParamsVersion}`);y.assertValidVaultCoreVersion(t.activeVaultCoreVersion,"ProtocolParams.activeVaultCoreVersion()")}const F=9999;function q(t){return{depositor:t.depositor,depositorBtcPubKey:t.depositorBtcPubKey,amount:t.amount,vaultProvider:t.vaultProvider,status:t.status,applicationEntryPoint:t.applicationEntryPoint,createdAt:t.createdAt}}function R(t){const e=Number(t.offchainParamsVersion);return et(e),{depositorSignedPeginTx:t.depositorSignedPeginTx,universalChallengersVersion:t.universalChallengersVersion,appVaultKeepersVersion:t.appVaultKeepersVersion,offchainParamsVersion:e,verifiedAt:t.verifiedAt,depositorWotsPkHash:t.depositorWotsPkHash,hashlock:t.hashlock,htlcVout:t.htlcVout,depositorPopSignature:t.depositorPopSignature,prePeginTxHash:t.prePeginTxHash,vaultProviderCommissionBps:t.vaultProviderCommissionBps,vaultCoreVersion:t.vaultCoreVersion}}const Ot=1n<<64n,W=0n;function k(t,e,n){if(t<0n||t>=Ot)throw new Error(`getBtcVaultProtocolInfo returned ${e}=${t} for vault ${n}, outside the uint64 range — the registry may predate RFC-006`);return t}function U(t,e){return{vpKeyEpoch:k(t.vpKeyEpoch,"vpKeyEpoch",e),appKeeperKeyEpoch:k(t.appKeeperKeyEpoch,"appKeeperKeyEpoch",e),ucKeyEpoch:k(t.ucKeyEpoch,"ucKeyEpoch",e)}}class it{constructor(e,n){this.publicClient=e,this.contractAddress=n}async getVaultProviderGenesisBtcPubKey(e,n){const o=await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getOperationBtcKeyAtEpoch",args:[e,W],blockNumber:n});return x.assertOnChainBtcPubkey(o,`getOperationBtcKeyAtEpoch (vp=${e}, epoch=${W})`)}async getCurrentVaultProviderOperationBtcKey(e){const n=await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getCurrentOperationBtcKey",args:[e]});return x.assertOnChainBtcPubkey(n,`getCurrentOperationBtcKey (vp=${e})`)}async getVaultKeyEpochs(e){const n=await this.publicClient.readContract({address:this.contractAddress,abi:I.BTCVaultRegistryKeyEpochsABI,functionName:"getBtcVaultProtocolInfo",args:[e]});return U(n,e)}async getVaultKeyEpochsBatch(e){return e.length===0?[]:(await this.publicClient.multicall({contracts:e.map(o=>({address:this.contractAddress,abi:I.BTCVaultRegistryKeyEpochsABI,functionName:"getBtcVaultProtocolInfo",args:[o]})),allowFailure:!1})).map((o,i)=>U(o,e[i]))}async getVaultBasicInfo(e){const n=await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultBasicInfo",args:[e]});return q(n)}async getVaultProtocolInfo(e){const n=await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultProtocolInfo",args:[e]});return R(n)}async getProtocolInfoBatch(e){return e.length===0?[]:(await this.publicClient.multicall({contracts:e.map(o=>({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultProtocolInfo",args:[o]})),allowFailure:!1})).map((o,i)=>{const a=o;if(!a.depositorSignedPeginTx||a.depositorSignedPeginTx==="0x")throw new Error(`Vault ${e[i]} not found on-chain or has no pegin transaction`);return R(a)})}async getPegInFee(e){return await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getPegInFee",args:[e]})}async getVaultProviderCommission(e){const n=await this.publicClient.readContract({address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getVaultProviderCommission",args:[e]});if(!Number.isInteger(n)||n<0||n>F)throw new Error(`getVaultProviderCommission returned ${n} bps for ${e}, outside the protocol range [0, ${F}]`);return n}async getVaultData(e){const[n,o]=await this.publicClient.multicall({contracts:[{address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultBasicInfo",args:[e]},{address:this.contractAddress,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultProtocolInfo",args:[e]}],allowFailure:!1}),i=q(n),a=R(o);if(!a.depositorSignedPeginTx||a.depositorSignedPeginTx==="0x")throw new Error(`Vault ${e} not found on-chain or has no pegin transaction`);return{basic:i,protocol:a}}}const st=0,Ht=255,Kt=12e4;function w(t,e){const n=t.startsWith("0x")?t:t.startsWith("0X")?`0x${t.slice(2)}`:`0x${t}`;if(!/^0x(?:[0-9a-fA-F]{2})+$/.test(n))throw new Error(`${e} must be non-empty, even-length hex`);return n}function D(t,e){if(!/^0x[0-9a-fA-F]{64}$/.test(t))throw new Error(`${e} must be a 32-byte hex value`)}function Mt(t){if(!Number.isInteger(t)||t<0||t>Ht)throw new Error(`htlcVout must be a uint8, got ${t}`)}class Ft{constructor(e){this.config=e}async registerPeginOnChain(e){const n={...e,popSignature:{...e.popSignature}};this.assertQuotedCommissionPresentWhenRequired(n.quotedCommissionBps);const o=this.assertPopMatchesEthAccount(n.popSignature),i=this.normalizeBtcPubkey(n.popSignature),a=w(n.popSignature.btcPopSignature,"btcPopSignature"),c=this.normalizeRequest(n,o,i);await this.assertVaultDoesNotExist(c.vaultId,c.peginTxHash);const l=await this.readPeginFee(n.vaultProvider),d=await this.resolveMaxAcceptableCommissionBps(n.vaultProvider,n.quotedCommissionBps),p=B.encodeFunctionData({abi:f.BTCVaultRegistryABI,functionName:"submitPeginRequest",args:[o,i,a,c.unsignedPrePeginTx,c.depositorSignedPeginTx,n.vaultProvider,d,n.hashlock,n.htlcVout,c.payoutScript,n.depositorWotsPkHash]});return{ethTxHash:await this.sendAndWait(p,l,!1,o),vaultId:c.vaultId,peginTxHash:c.peginTxHash}}async registerPeginBatchOnChain(e){const n={...e,popSignature:{...e.popSignature},requests:e.requests.map(r=>({...r}))};if(n.requests.length===0)throw new Error("Batch pegin requires at least one request");this.assertQuotedCommissionPresentWhenRequired(n.quotedCommissionBps);const o=this.assertPopMatchesEthAccount(n.popSignature),i=w(n.unsignedPrePeginTx,"unsignedPrePeginTx"),a=this.normalizeBtcPubkey(n.popSignature),c=w(n.popSignature.btcPopSignature,"btcPopSignature"),l=[],d=[],p=new Set;for(const r of n.requests){const u=this.normalizeRequest({...r,unsignedPrePeginTx:n.unsignedPrePeginTx,vaultProvider:n.vaultProvider,depositorBtcPubkeyRaw:n.depositorBtcPubkeyRaw},o,a);if(p.has(u.vaultId))throw new Error(`Duplicate vault in batch: ${u.vaultId}`);p.add(u.vaultId),l.push({vaultId:u.vaultId,peginTxHash:u.peginTxHash}),d.push({depositorBtcPubKey:a,btcPopSignature:c,unsignedPrePeginTx:i,depositorSignedPeginTx:u.depositorSignedPeginTx,hashlock:r.hashlock,htlcVout:r.htlcVout,referralCode:st,depositorPayoutBtcAddress:u.payoutScript,depositorWotsPkHash:r.depositorWotsPkHash})}for(const r of l)await this.assertVaultDoesNotExist(r.vaultId,r.peginTxHash);const P=await this.readPeginFee(n.vaultProvider),b=await this.resolveMaxAcceptableCommissionBps(n.vaultProvider,n.quotedCommissionBps),s=B.encodeFunctionData({abi:f.BTCVaultRegistryABI,functionName:"submitPeginRequestBatch",args:[o,n.vaultProvider,b,d]});return{ethTxHash:await this.sendAndWait(s,P*BigInt(n.requests.length),!0,o),vaults:l}}assertQuotedCommissionPresentWhenRequired(e){if(e===void 0&&this.config.requireQuotedCommissionBps)throw new Error("quotedCommissionBps is required when the wallet approved deposit terms: the registration ceiling must anchor to the approved quote.")}assertPopMatchesEthAccount(e){return this.assertEthAccount(e.depositorEthAddress)}assertEthAccount(e){const n=this.config.ethWallet.account;if(!n)throw new Error("Ethereum wallet account not found");if(!B.isAddressEqual(e,n.address))throw new Error(`Proof of possession was signed for ${e} but the Ethereum wallet is currently connected to ${n.address}. Reconnect the original account or sign a new proof of possession.`);return n.address}normalizeBtcPubkey(e){return`0x${x.assertOnChainBtcPubkey(w(e.depositorBtcPubkey,"Proof of possession BTC pubkey"),"Proof of possession BTC pubkey")}`}normalizeRequest(e,n,o){D(e.hashlock,"hashlock"),D(e.depositorWotsPkHash,"depositorWotsPkHash"),Mt(e.htlcVout);const i=w(e.unsignedPrePeginTx,"unsignedPrePeginTx"),a=w(e.depositorSignedPeginTx,"depositorSignedPeginTx"),c=Z(a);return{unsignedPrePeginTx:i,depositorSignedPeginTx:a,payoutScript:$t(e.depositorPayoutScriptPubKey,o,e.depositorBtcPubkeyRaw),peginTxHash:c,vaultId:w(tt(c,n),"vaultId")}}async assertVaultDoesNotExist(e,n){if((await this.config.publicClient.readContract({address:this.config.btcVaultRegistry,abi:f.BTCVaultRegistryABI,functionName:"getBtcVaultBasicInfo",args:[e]})).depositor!==B.zeroAddress)throw new Error(`Vault already exists (ID: ${e}, peginTxHash: ${n}). Vault IDs are derived from the pegin transaction hash and depositor address. To create a new vault, use different UTXOs or a different amount to generate a unique transaction.`)}async readPeginFee(e){try{return await this.config.publicClient.readContract({address:this.config.btcVaultRegistry,abi:f.BTCVaultRegistryABI,functionName:"getPegInFee",args:[e]})}catch(n){throw new Error("Failed to query pegin fee from the contract. Please check your network connection and contract address.",{cause:n})}}async resolveMaxAcceptableCommissionBps(e,n){let o;try{o=await new it(this.config.publicClient,this.config.btcVaultRegistry).getVaultProviderCommission(e)}catch(i){throw new Error("Failed to query vault provider commission from the contract. Please check your network connection and contract address.",{cause:i})}if(n!==void 0){if(o>n+V)throw new Error(`Vault provider commission changed since quote: quoted ${n} bps, chain currently reports ${o} bps (allowed drift ${V} bps). Please refresh and try again.`);return _(n)}return _(o)}async sendAndWait(e,n,o,i){let a=this.assertEthAccount(i),c;try{c=await this.config.publicClient.estimateGas({to:this.config.btcVaultRegistry,data:e,value:n,account:a})}catch(p){I.handleContractError(p)}a=this.assertEthAccount(i);let l;try{l=await this.config.ethWallet.sendTransaction({to:this.config.btcVaultRegistry,data:e,value:n,gas:c,account:a,chain:this.config.ethChain})}catch(p){I.handleContractError(p)}const d=await pt.waitForTransactionReceiptSmartAware({publicClient:this.config.publicClient,walletAddress:i,hash:l,timeout:this.config.receiptTimeoutMs??Kt});return d.status==="reverted"&&I.handleContractError(new Error(`${o?"Batch transaction":"Transaction"} reverted. Hash: ${d.transactionHash}. Check a block explorer for details.`)),d.transactionHash}}exports.COMMISSION_BPS_HEADROOM=V;exports.MAX_ACCEPTABLE_COMMISSION_BPS_CAP=X;exports.NO_REFERRAL_CODE=st;exports.ViemPeginRegistrationClient=Ft;exports.ViemVaultRegistryReader=it;exports.assertValidOffchainParamsVersion=et;exports.calculateBtcTxHash=Z;exports.capMaxAcceptableCommissionBps=_;exports.derivePeginVaultId=tt;exports.ripemd160=j;exports.validateOffchainParams=nt;exports.validatePegInConfiguration=Nt;exports.validateTBVProtocolParams=ot;
|
|
2
|
+
//# sourceMappingURL=pegin-registration-client-DLsMNm8Z.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pegin-registration-client-DLsMNm8Z.cjs","sources":["../src/tbv/core/deposit-terms/commissionCeiling.ts","../../../node_modules/.pnpm/@noble+hashes@2.0.1/node_modules/@noble/hashes/legacy.js","../src/tbv/core/clients/eth/payout-script.ts","../src/tbv/core/clients/eth/pegin-transaction.ts","../src/tbv/core/clients/eth/protocol-params-validation.ts","../src/tbv/core/clients/eth/vault-registry-reader.ts","../src/tbv/core/clients/eth/pegin-registration-client.ts"],"sourcesContent":["/**\n * The depositor's commission ceiling (`maxAcceptableCommissionBps`) policy:\n * quoted VP commission + drift headroom, capped below the contract's\n * exclusive bound. Shared by the fresh path (`PeginManager`) and the\n * resume-rebuild path so both compute the same ceiling.\n *\n * @module deposit-terms/commissionCeiling\n */\n\n/*\n * Commission-check map (each guards a DIFFERENT boundary — do not consolidate):\n * 1. assertVpCommissionInProtocolRange (vault app, vaultPayoutSignatureService)\n * — chain-read trust boundary; mirrors VPKeyRegistryLogic.sol bounds.\n * 2. capMaxAcceptableCommissionBps (here) — depositor quote → ceiling policy;\n * mirrors PeginLogic.sol's strict > check via the +25bps headroom.\n * 3. buildDepositTerms range check — public-API precondition on the projection\n * that mints the device-enforced commissionFee.\n * 4. payout.ts commission cap — the VP-built tx's output value vs bps at the\n * signing site (CLAUDE.md Critical Path #3).\n * 5. envelope.ts dust/cross-field gates (ledger-vault-signer) — firmware-only\n * constants, pre-device-I/O (Critical Path #7).\n */\n\nimport { MAX_VP_COMMISSION_BPS_EXCLUSIVE } from \"../primitives/psbt/constants\";\n\n/**\n * Headroom (in basis points) added to the current VP commission to compute\n * `maxAcceptableCommissionBps` at submit time. Lets the VP raise its\n * commission by up to this amount between read and submit without forcing\n * a re-quote. Capped by {@link MAX_ACCEPTABLE_COMMISSION_BPS_CAP}.\n *\n * Contract check is strict `>` (PeginLogic.sol `VaultProviderCommissionExceeded`\n * revert), so +25 allows up\n * to +25 bps of drift.\n */\nexport const COMMISSION_BPS_HEADROOM = 25;\n\n/**\n * Hard ceiling for `maxAcceptableCommissionBps`. The contract enforces\n * `commissionBps < 10000`, so any value at/above that is unreachable;\n * `9999` is the maximum useful cap.\n */\nexport const MAX_ACCEPTABLE_COMMISSION_BPS_CAP = 9999;\n\n/**\n * The commission ceiling submitted as registration calldata and mirrored\n * into `DepositTerms.commissionFee`: quoted + drift headroom, capped.\n * Single source for both consumers — feed it the SAME quoted bps at prepare\n * and register time so device-accept stays coextensive with contract-accept.\n */\nexport function capMaxAcceptableCommissionBps(bps: number): number {\n // Validate the raw quote before headroom shifts its domain — a negative\n // quote must throw here, not become a small \"legal\" ceiling.\n // Reject an out-of-range quote outright — clamping it to 9999 would turn a\n // bad read into a 99.99% ceiling, the exact failure the cap exists to stop.\n if (\n !Number.isInteger(bps) ||\n bps < 0 ||\n bps >= MAX_VP_COMMISSION_BPS_EXCLUSIVE\n ) {\n throw new Error(\n `Quoted commissionBps must be an integer in ` +\n `[0, ${MAX_VP_COMMISSION_BPS_EXCLUSIVE}), got ${bps}`,\n );\n }\n return Math.min(\n bps + COMMISSION_BPS_HEADROOM,\n MAX_ACCEPTABLE_COMMISSION_BPS_CAP,\n );\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","import { schnorr, secp256k1 } from \"@noble/curves/secp256k1.js\";\nimport { ripemd160 } from \"@noble/hashes/legacy.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\";\nimport type { Hex } from \"viem\";\n\nimport { MAX_PAYOUT_SCRIPT_LEN } from \"../../primitives/psbt/constants\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\n\nconst P2TR_SCRIPT_PREFIX = \"5120\";\nconst P2WPKH_SCRIPT_PREFIX = \"0014\";\nconst HASH160_BYTES = 20;\nconst COMPRESSED_PUBKEY_BYTES = 33;\nconst UNCOMPRESSED_PUBKEY_BYTES = 65;\nconst SEC1_EVEN_Y_PREFIX = 0x02;\nconst SEC1_ODD_Y_PREFIX = 0x03;\nconst SEC1_UNCOMPRESSED_PREFIX = 0x04;\n\nfunction normalizeHex(value: string, label: string): Hex {\n const body =\n value.startsWith(\"0x\") || value.startsWith(\"0X\") ? value.slice(2) : value;\n if (!/^(?:[0-9a-fA-F]{2})+$/.test(body)) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n return `0x${body.toLowerCase()}`;\n}\n\nfunction deriveP2trScript(xOnlyPubkey: string): Hex {\n const pubkeyBytes = hexToBytes(xOnlyPubkey);\n const internalKey = schnorr.utils.lift_x(BigInt(`0x${xOnlyPubkey}`));\n const tweak = schnorr.utils.bytesToNumberBE(\n schnorr.utils.taggedHash(\"TapTweak\", pubkeyBytes),\n );\n if (tweak >= secp256k1.CURVE.n) {\n throw new Error(\"Proof of possession BTC pubkey has an invalid TapTweak\");\n }\n const outputKey =\n tweak === 0n\n ? internalKey\n : internalKey.add(schnorr.Point.BASE.multiply(tweak));\n return `0x${P2TR_SCRIPT_PREFIX}${bytesToHex(\n schnorr.utils.pointToBytes(outputKey),\n )}`;\n}\n\nfunction normalizePayoutPubkey(value: string): {\n xOnlyPubkey: string;\n compressedPubkey?: Uint8Array;\n} {\n const normalized = normalizeHex(value, \"depositorBtcPubkeyRaw\");\n const pubkey = hexToBytes(normalized.slice(2));\n if (pubkey.length === 32) {\n return {\n xOnlyPubkey: assertOnChainBtcPubkey(normalized, \"Payout BTC pubkey\"),\n };\n }\n const isCompressed =\n pubkey.length === COMPRESSED_PUBKEY_BYTES &&\n (pubkey[0] === SEC1_EVEN_Y_PREFIX || pubkey[0] === SEC1_ODD_Y_PREFIX);\n const isUncompressed =\n pubkey.length === UNCOMPRESSED_PUBKEY_BYTES &&\n pubkey[0] === SEC1_UNCOMPRESSED_PREFIX;\n if (!isCompressed && !isUncompressed) {\n throw new Error(\n \"depositorBtcPubkeyRaw must be x-only, compressed, or uncompressed\",\n );\n }\n try {\n secp256k1.Point.fromBytes(pubkey);\n } catch {\n throw new Error(\"depositorBtcPubkeyRaw is not a valid BTC pubkey\");\n }\n return {\n xOnlyPubkey: bytesToHex(pubkey.subarray(1, COMPRESSED_PUBKEY_BYTES)),\n compressedPubkey: isCompressed ? pubkey : undefined,\n };\n}\n\nfunction deriveP2wpkhScript(pubkey: Uint8Array): Hex {\n return `0x${P2WPKH_SCRIPT_PREFIX}${bytesToHex(ripemd160(sha256(pubkey)))}`;\n}\n\n/** Verify the irreversible payout script at the final submission boundary. */\nexport function assertPayoutScriptMatchesPopKey(\n scriptPubKey: string,\n depositorBtcPubkey: string,\n depositorBtcPubkeyRaw: string,\n): Hex {\n const payoutScript = normalizeHex(\n scriptPubKey,\n \"depositorPayoutScriptPubKey\",\n );\n if ((payoutScript.length - 2) / 2 > MAX_PAYOUT_SCRIPT_LEN) {\n throw new Error(\n `depositorPayoutScriptPubKey exceeds ${MAX_PAYOUT_SCRIPT_LEN} bytes`,\n );\n }\n const keyBody =\n depositorBtcPubkey.startsWith(\"0x\") || depositorBtcPubkey.startsWith(\"0X\")\n ? depositorBtcPubkey.slice(2)\n : depositorBtcPubkey;\n const xOnlyPubkey = assertOnChainBtcPubkey(\n `0x${keyBody}` as Hex,\n \"Proof of possession BTC pubkey\",\n );\n const payoutPubkey = normalizePayoutPubkey(depositorBtcPubkeyRaw);\n if (payoutPubkey.xOnlyPubkey !== xOnlyPubkey) {\n throw new Error(\n \"depositorBtcPubkeyRaw does not match the proof of possession BTC pubkey\",\n );\n }\n\n if (payoutScript === deriveP2trScript(xOnlyPubkey)) {\n return payoutScript;\n }\n if (\n payoutScript.startsWith(`0x${P2WPKH_SCRIPT_PREFIX}`) &&\n payoutScript.length ===\n 2 + P2WPKH_SCRIPT_PREFIX.length + HASH160_BYTES * 2\n ) {\n if (!payoutPubkey.compressedPubkey) {\n throw new Error(\"A P2WPKH payout requires a compressed BTC pubkey\");\n }\n if (payoutScript === deriveP2wpkhScript(payoutPubkey.compressedPubkey)) {\n return payoutScript;\n }\n }\n throw new Error(\n \"depositorPayoutScriptPubKey does not match the proof of possession BTC pubkey\",\n );\n}\n","/**\n * Dependency-free Bitcoin txid and vault-ID helpers for Ethereum-only clients.\n * Transaction hex and vault-ID inputs accept an optional `0x` prefix.\n * Depositor addresses use strict EIP-55 validation.\n * Txids use a `0x` prefix. Vault IDs use no prefix. Both use lowercase hex.\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport {\n encodeAbiParameters,\n isAddress,\n keccak256,\n type Address,\n type Hex,\n} from \"viem\";\n\n/** Decode an optional-prefixed, even-length hex string. */\nfunction decodeHex(value: string, label: string): Uint8Array {\n const clean = value.startsWith(\"0x\") ? value.slice(2) : value;\n if (clean.length === 0 || clean.length % 2 !== 0) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n if (!/^[0-9a-fA-F]+$/.test(clean)) {\n throw new Error(`${label} contains non-hex characters`);\n }\n\n const bytes = new Uint8Array(clean.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Number.parseInt(clean.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/** Encode bytes as lowercase hex without a prefix. */\nfunction encodeHex(bytes: Uint8Array): string {\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\n \"\",\n );\n}\n\n/** Concatenate byte chunks without a buffer dependency. */\nfunction concatBytes(chunks: readonly Uint8Array[]): Uint8Array {\n const result = new Uint8Array(\n chunks.reduce((length, chunk) => length + chunk.length, 0),\n );\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\n\n/**\n * Parse enough of Bitcoin's consensus transaction encoding to serialize the\n * no-witness form used for txid calculation. Every length is bounds-checked;\n * malformed/trailing data is rejected rather than hashed as an opaque blob.\n */\nfunction serializeWithoutWitness(transaction: Uint8Array): Uint8Array {\n let offset = 0;\n\n const take = (length: number, label: string): Uint8Array => {\n if (!Number.isSafeInteger(length) || length < 0) {\n throw new Error(`Invalid ${label} length ${length}`);\n }\n if (offset + length > transaction.length) {\n throw new Error(`Truncated Bitcoin transaction while reading ${label}`);\n }\n const value = transaction.slice(offset, offset + length);\n offset += length;\n return value;\n };\n\n const readLittleEndian = (length: number, label: string): bigint => {\n const bytes = take(length, label);\n let value = 0n;\n for (let i = bytes.length - 1; i >= 0; i--) {\n value = (value << 8n) | BigInt(bytes[i]);\n }\n return value;\n };\n\n const readCompactSize = (\n label: string,\n ): { encoded: Uint8Array; value: number } => {\n const start = offset;\n const prefix = take(1, label)[0];\n let value: bigint;\n if (prefix < 0xfd) {\n value = BigInt(prefix);\n } else if (prefix === 0xfd) {\n value = readLittleEndian(2, label);\n if (value < 0xfdn) throw new Error(`Non-canonical ${label}`);\n } else if (prefix === 0xfe) {\n value = readLittleEndian(4, label);\n if (value <= 0xffffn) throw new Error(`Non-canonical ${label}`);\n } else {\n value = readLittleEndian(8, label);\n if (value <= 0xffffffffn) throw new Error(`Non-canonical ${label}`);\n }\n if (value > BigInt(Number.MAX_SAFE_INTEGER)) {\n throw new Error(`${label} exceeds JavaScript's safe integer range`);\n }\n return {\n encoded: transaction.slice(start, offset),\n value: Number(value),\n };\n };\n\n const version = take(4, \"version\");\n const hasWitness =\n transaction[offset] === 0x00 && transaction[offset + 1] === 0x01;\n if (hasWitness) offset += 2;\n\n const inputCount = readCompactSize(\"input count\");\n const inputs: Uint8Array[] = [];\n for (let i = 0; i < inputCount.value; i++) {\n const start = offset;\n take(32, `input ${i} previous transaction hash`);\n take(4, `input ${i} previous output index`);\n const scriptLength = readCompactSize(`input ${i} script length`);\n take(scriptLength.value, `input ${i} script`);\n take(4, `input ${i} sequence`);\n inputs.push(transaction.slice(start, offset));\n }\n\n const outputCount = readCompactSize(\"output count\");\n const outputs: Uint8Array[] = [];\n for (let i = 0; i < outputCount.value; i++) {\n const start = offset;\n take(8, `output ${i} value`);\n const scriptLength = readCompactSize(`output ${i} script length`);\n take(scriptLength.value, `output ${i} script`);\n outputs.push(transaction.slice(start, offset));\n }\n\n if (hasWitness) {\n let hasWitnessData = false;\n for (let i = 0; i < inputCount.value; i++) {\n const itemCount = readCompactSize(`input ${i} witness item count`);\n hasWitnessData ||= itemCount.value > 0;\n for (let j = 0; j < itemCount.value; j++) {\n const itemLength = readCompactSize(\n `input ${i} witness item ${j} length`,\n );\n take(itemLength.value, `input ${i} witness item ${j}`);\n }\n }\n if (!hasWitnessData) {\n throw new Error(\"Bitcoin transaction has superfluous witness marker\");\n }\n }\n\n const locktime = take(4, \"locktime\");\n if (offset !== transaction.length) {\n throw new Error(\n `Bitcoin transaction has ${transaction.length - offset} trailing byte(s)`,\n );\n }\n\n return concatBytes([\n version,\n inputCount.encoded,\n ...inputs,\n outputCount.encoded,\n ...outputs,\n locktime,\n ]);\n}\n\n/** Calculate a Bitcoin txid without importing bitcoinjs-lib. */\nexport function calculateBtcTxHash(transactionHex: string): Hex {\n const serialized = serializeWithoutWitness(\n decodeHex(transactionHex, \"transactionHex\"),\n );\n const digest = sha256(sha256(serialized));\n digest.reverse();\n return `0x${encodeHex(digest)}`;\n}\n\n/**\n * Derive the Solidity vault ID without loading the Rust/WASM package.\n *\n * Inputs accept an optional `0x` prefix to match the current PeginManager\n * call sites. Address validation stays strict: lowercase and valid EIP-55\n * addresses pass, while uppercase and incorrectly checksummed mixed-case\n * addresses fail. The synchronous result is lowercase hex without a prefix,\n * matching the WASM helper that this function replaces.\n */\nexport function derivePeginVaultId(\n peginTxHash: string,\n depositor: string,\n): string {\n const normalizedPeginTxHash = peginTxHash.startsWith(\"0x\")\n ? peginTxHash\n : `0x${peginTxHash}`;\n if (!/^0x[0-9a-fA-F]{64}$/.test(normalizedPeginTxHash)) {\n throw new Error(\"peginTxHash must be a 32-byte hex value\");\n }\n const normalizedDepositor = depositor.startsWith(\"0x\")\n ? depositor\n : `0x${depositor}`;\n if (!isAddress(normalizedDepositor, { strict: true })) {\n throw new Error(`Invalid depositor Ethereum address: ${depositor}`);\n }\n return keccak256(\n encodeAbiParameters(\n [{ type: \"bytes32\" }, { type: \"address\" }],\n [normalizedPeginTxHash as Hex, normalizedDepositor as Address],\n ),\n ).slice(2);\n}\n","/**\n * Validation for protocol parameters fetched from the ProtocolParams contract.\n *\n * These values feed Bitcoin script construction and deposit validation.\n * Invalid params must be caught before they reach transaction-building code,\n * since errors after wallet signing prompts are unrecoverable.\n *\n * The {@link ViemProtocolParamsReader} runs these on every read; consumers\n * implementing their own reader against the same `ProtocolParamsReader`\n * interface should call them too.\n */\n\nimport { assertValidVaultCoreVersion } from \"../../primitives/vaultCoreVersion\";\n\nimport type {\n PegInConfiguration,\n TBVProtocolParams,\n VersionedOffchainParams,\n} from \"./types\";\n\n/**\n * Maximum value for a Solidity uint16.\n * PeginLogic.sol casts timelockAssert to uint16, so values above this are invalid.\n */\nconst UINT16_MAX = 65535;\n\n/** Maximum valid value for basis points (100%) */\nconst MAX_BASIS_POINTS = 10000;\n\n/** Maximum value for a Solidity uint32. */\nconst UINT32_MAX = 4_294_967_295;\n\n/** Maximum valid value for a uint8 (e.g. maxHtlcOutputCount). */\nconst UINT8_MAX = 255;\n\n/**\n * Validate an `offchainParamsVersion` value sourced from a contract read.\n * `Number()` on a malformed payload yields `NaN` or a non-integer; both\n * silently break consumers that loop `1..version` or use the value as a\n * map key. Used by reader entry points that surface the version to JS.\n */\nexport function assertValidOffchainParamsVersion(version: number): void {\n if (\n !Number.isInteger(version) ||\n version < 0 ||\n version > UINT32_MAX\n ) {\n throw new Error(\n `Invalid offchainParamsVersion from contract: must be a uint32, got ${version}`,\n );\n }\n}\n\n/**\n * Validate offchain params consistency and bounds.\n * @throws Error on invalid values to prevent constructing invalid Bitcoin scripts.\n */\nexport function validateOffchainParams(params: VersionedOffchainParams): void {\n const errors: string[] = [];\n\n if (params.timelockAssert <= 0n) {\n errors.push(\n `timelockAssert must be positive, got ${params.timelockAssert}`,\n );\n }\n if (params.timelockAssert > BigInt(UINT16_MAX)) {\n errors.push(\n `timelockAssert ${params.timelockAssert} exceeds uint16 max (${UINT16_MAX})`,\n );\n }\n\n if (params.timelockChallengeAssert <= 0n) {\n errors.push(\n `timelockChallengeAssert must be positive, got ${params.timelockChallengeAssert}`,\n );\n }\n\n if (params.tRefund <= 0) {\n errors.push(`tRefund must be positive, got ${params.tRefund}`);\n }\n\n if (params.tStale <= 0) {\n errors.push(`tStale must be positive, got ${params.tStale}`);\n }\n\n if (params.securityCouncilKeys.length === 0) {\n errors.push(\"securityCouncilKeys must not be empty\");\n }\n\n if (params.councilQuorum <= 0) {\n errors.push(`councilQuorum must be positive, got ${params.councilQuorum}`);\n }\n if (params.councilQuorum > params.securityCouncilKeys.length) {\n errors.push(\n `councilQuorum (${params.councilQuorum}) exceeds securityCouncilKeys count (${params.securityCouncilKeys.length})`,\n );\n }\n\n if (params.feeRate <= 0n) {\n errors.push(`feeRate must be positive, got ${params.feeRate}`);\n }\n\n if (params.minPeginFeeRate <= 0n) {\n errors.push(\n `minPeginFeeRate must be positive, got ${params.minPeginFeeRate}`,\n );\n }\n\n if (\n !Number.isInteger(params.proverCircuitVersion) ||\n params.proverCircuitVersion < 0 ||\n params.proverCircuitVersion > UINT16_MAX\n ) {\n errors.push(\n `proverCircuitVersion must be a uint16, got ${params.proverCircuitVersion}`,\n );\n }\n\n if (\n !Number.isInteger(params.minPrepeginDepth) ||\n params.minPrepeginDepth <= 0 ||\n params.minPrepeginDepth > UINT32_MAX\n ) {\n errors.push(\n `minPrepeginDepth must be a uint32 in [1, ${UINT32_MAX}], got ${params.minPrepeginDepth}`,\n );\n }\n\n if (params.babeTotalInstances <= 0) {\n errors.push(\n `babeTotalInstances must be positive, got ${params.babeTotalInstances}`,\n );\n }\n if (params.babeInstancesToFinalize <= 0) {\n errors.push(\n `babeInstancesToFinalize must be positive, got ${params.babeInstancesToFinalize}`,\n );\n }\n if (params.babeInstancesToFinalize > params.babeTotalInstances) {\n errors.push(\n `babeInstancesToFinalize (${params.babeInstancesToFinalize}) exceeds babeTotalInstances (${params.babeTotalInstances})`,\n );\n }\n\n if (\n params.minVpCommissionBps < 0 ||\n params.minVpCommissionBps > MAX_BASIS_POINTS\n ) {\n errors.push(\n `minVpCommissionBps must be in [0, ${MAX_BASIS_POINTS}], got ${params.minVpCommissionBps}`,\n );\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Invalid offchain protocol parameters: ${errors.join(\"; \")}`,\n );\n }\n}\n\n/**\n * Validate TBV protocol params returned from the contract.\n * @throws Error on invalid amounts or out-of-range bounded fields.\n */\nexport function validateTBVProtocolParams(params: TBVProtocolParams): void {\n const errors: string[] = [];\n\n if (params.minimumPegInAmount <= 0n) {\n errors.push(\n `minimumPegInAmount must be positive, got ${params.minimumPegInAmount}`,\n );\n }\n\n if (params.maxPegInAmount < params.minimumPegInAmount) {\n errors.push(\n `maxPegInAmount (${params.maxPegInAmount}) must be >= minimumPegInAmount (${params.minimumPegInAmount})`,\n );\n }\n\n if (params.pegInAckTimeout <= 0n) {\n errors.push(\n `pegInAckTimeout must be positive, got ${params.pegInAckTimeout}`,\n );\n }\n\n if (params.pegInActivationTimeout <= 0n) {\n errors.push(\n `pegInActivationTimeout must be positive, got ${params.pegInActivationTimeout}`,\n );\n }\n\n if (\n !Number.isInteger(params.maxHtlcOutputCount) ||\n params.maxHtlcOutputCount <= 0 ||\n params.maxHtlcOutputCount > UINT8_MAX\n ) {\n errors.push(\n `maxHtlcOutputCount must be an integer in [1, ${UINT8_MAX}], got ${params.maxHtlcOutputCount}`,\n );\n }\n\n if (\n typeof params.expiredPegInGraceBlocks !== \"bigint\" ||\n params.expiredPegInGraceBlocks <= 0n\n ) {\n errors.push(\n `expiredPegInGraceBlocks must be a positive bigint, got ${params.expiredPegInGraceBlocks}`,\n );\n }\n\n if (errors.length > 0) {\n throw new Error(`Invalid TBV protocol parameters: ${errors.join(\"; \")}`);\n }\n}\n\n/**\n * Validate the full peg-in configuration after assembly.\n * Checks both TBV params and offchain params consistency, and the\n * top-level `offchainParamsVersion` (which originates from a separate\n * multicall result and so must be range-checked alongside the params it\n * names).\n */\nexport function validatePegInConfiguration(config: PegInConfiguration): void {\n validateTBVProtocolParams(config);\n validateOffchainParams(config.offchainParams);\n\n if (\n !Number.isInteger(config.offchainParamsVersion) ||\n config.offchainParamsVersion < 0 ||\n config.offchainParamsVersion > UINT32_MAX\n ) {\n throw new Error(\n `Invalid peg-in configuration: offchainParamsVersion must be a uint32, got ${config.offchainParamsVersion}`,\n );\n }\n\n // The contract enforces ≥ 1 (setter rejects 0); a 0 here means a\n // mis-decoded read or a pre-vaultCoreVersion contract — fail closed.\n assertValidVaultCoreVersion(\n config.activeVaultCoreVersion,\n \"ProtocolParams.activeVaultCoreVersion()\",\n );\n}\n","/**\n * Concrete BTCVaultRegistry reader using viem's readContract.\n *\n * This is an optional utility — callers can use their own implementation\n * of the VaultRegistryReader interface.\n */\n\nimport type { Abi, Address, Hex, PublicClient } from \"viem\";\n\nimport { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { BTCVaultRegistryKeyEpochsABI } from \"../../contracts/abis/BTCVaultRegistryKeyEpochs.abi\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\nimport { assertValidOffchainParamsVersion } from \"./protocol-params-validation\";\nimport type {\n KeyEpochs,\n OnChainBtcPubkey,\n VaultBasicInfo,\n VaultData,\n VaultProtocolInfo,\n VaultRegistryReader,\n} from \"./types\";\n\n/**\n * Inclusive upper bound the BTCVaultRegistry contract enforces on a vault\n * provider's commission (the contract check is `< 10000`).\n */\nconst MAX_VP_COMMISSION_BPS = 9999;\n\n/** Raw `getBtcVaultBasicInfo` tuple as decoded by viem. */\ntype RawVaultBasicInfo = {\n depositor: Address;\n depositorBtcPubKey: Hex;\n amount: bigint;\n vaultProvider: Address;\n status: number;\n applicationEntryPoint: Address;\n createdAt: bigint;\n};\n\n/**\n * Raw `getBtcVaultProtocolInfo` tuple as decoded by viem.\n *\n * Mirrors the ABI's components except `claimExpiredUntil`, which nothing\n * consumes: it is the post-expiry grace deadline for `claimExpired`, scoped to\n * vaults that expired without activating, and it is not a deadline on the\n * depositor's claim right. The ABI still declares it — the decode is\n * positional, so removing it there would shift `vaultCoreVersion`.\n */\ntype RawVaultProtocolInfo = {\n depositorSignedPeginTx: Hex;\n universalChallengersVersion: number;\n appVaultKeepersVersion: number;\n offchainParamsVersion: number;\n verifiedAt: bigint;\n depositorWotsPkHash: Hex;\n hashlock: Hex;\n htlcVout: number;\n depositorPopSignature: Hex;\n prePeginTxHash: Hex;\n vaultProviderCommissionBps: number;\n vaultCoreVersion: number;\n};\n\nfunction mapVaultBasicInfo(result: RawVaultBasicInfo): VaultBasicInfo {\n return {\n depositor: result.depositor,\n depositorBtcPubKey: result.depositorBtcPubKey,\n amount: result.amount,\n vaultProvider: result.vaultProvider,\n status: result.status,\n applicationEntryPoint: result.applicationEntryPoint,\n createdAt: result.createdAt,\n };\n}\n\nfunction mapVaultProtocolInfo(result: RawVaultProtocolInfo): VaultProtocolInfo {\n const offchainParamsVersion = Number(result.offchainParamsVersion);\n assertValidOffchainParamsVersion(offchainParamsVersion);\n return {\n depositorSignedPeginTx: result.depositorSignedPeginTx,\n universalChallengersVersion: result.universalChallengersVersion,\n appVaultKeepersVersion: result.appVaultKeepersVersion,\n offchainParamsVersion,\n verifiedAt: result.verifiedAt,\n depositorWotsPkHash: result.depositorWotsPkHash,\n hashlock: result.hashlock,\n htlcVout: result.htlcVout,\n depositorPopSignature: result.depositorPopSignature,\n prePeginTxHash: result.prePeginTxHash,\n vaultProviderCommissionBps: result.vaultProviderCommissionBps,\n vaultCoreVersion: result.vaultCoreVersion,\n };\n}\n\n/**\n * Exclusive upper bound for a `uint64` epoch.\n *\n * viem does not range-check a decoded `uint64`, so a misaligned decode can\n * hand back a value far larger than the field can hold. Rejecting those is\n * cheap defence in depth against a mis-decode of the extended ABI.\n *\n * The state this is load-bearing for is narrower than \"a registry that predates\n * RFC-006\". Against a *fully* pre-RFC-006 registry the path fails closed on its\n * own: `resolveParticipantKeysAtEpochs` goes on to call\n * `getOperationBtcKeyAtEpochOrGenesis` on ApplicationRegistry and\n * ProtocolParams, which do not exist there, so the multicall reverts and these\n * epochs are never used. The reachable gap is a registry that *has* the\n * operation-key getters but whose `BTCVaultProtocolInfo` struct is not\n * extended — there the tail-data epochs resolve with no error at all, and this\n * range check is the only thing looking at them.\n *\n * Even for that case it is only a backstop, and a weak one: a misaligned decode\n * can land on a small, plausible-looking integer this range accepts. Correctness\n * rests on only ever pointing at an RFC-006 registry, which is a deployment\n * precondition rather than something this call can establish — see\n * https://github.com/babylonlabs-io/babylon-toolkit/issues/2192 for where that\n * check is owned, and `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n */\nconst UINT64_EXCLUSIVE_UPPER_BOUND = 1n << 64n;\n\n/**\n * The epoch a vault provider's registration key is bonded at.\n *\n * A provider's operation-key history is append-only and every appended version\n * is stamped at epoch 1 or later, so epoch 0 always resolves to the key set at\n * registration. This is what lets `getOperationBtcKeyAtEpoch` stand in for the\n * removed `getVaultProviderBTCKey` getter.\n */\nconst VP_GENESIS_KEY_EPOCH = 0n;\n\nfunction assertEpochInRange(\n value: bigint,\n field: string,\n vaultId: Hex,\n): bigint {\n if (value < 0n || value >= UINT64_EXCLUSIVE_UPPER_BOUND) {\n throw new Error(\n `getBtcVaultProtocolInfo returned ${field}=${value} for vault ${vaultId}, ` +\n `outside the uint64 range — the registry may predate RFC-006`,\n );\n }\n return value;\n}\n\nfunction mapKeyEpochs(result: KeyEpochs, vaultId: Hex): KeyEpochs {\n return {\n vpKeyEpoch: assertEpochInRange(result.vpKeyEpoch, \"vpKeyEpoch\", vaultId),\n appKeeperKeyEpoch: assertEpochInRange(\n result.appKeeperKeyEpoch,\n \"appKeeperKeyEpoch\",\n vaultId,\n ),\n ucKeyEpoch: assertEpochInRange(result.ucKeyEpoch, \"ucKeyEpoch\", vaultId),\n };\n}\n\n/**\n * Concrete vault registry reader using viem.\n *\n * Usage:\n * ```ts\n * const reader = new ViemVaultRegistryReader(publicClient, registryAddress);\n * const data = await reader.getVaultData(vaultId);\n * ```\n */\nexport class ViemVaultRegistryReader implements VaultRegistryReader {\n constructor(\n private publicClient: PublicClient,\n private contractAddress: Address,\n ) {}\n\n /**\n * Read the VP's **genesis** (registration) x-only BTC pubkey — the key bonded\n * at version 0, which never moves when the operator rotates.\n *\n * Resolved as \"the operation key at epoch 0\" rather than through the\n * dedicated `getVaultProviderBTCKey` getter, which\n * https://github.com/babylonlabs-io/vault-contracts-aave-v4/pull/539 removes.\n * Epoch 0 predates any rotation — appended versions are stamped at epoch 1 or\n * later — so it resolves to the registration key, and the contracts team has\n * confirmed that is a property we can rely on rather than an implementation\n * detail. The devnet comparison behind that claim — both getters returning the\n * identical key for a provider that *has* rotated, while\n * `getCurrentOperationBtcKey` differed — is recorded in\n * https://github.com/babylonlabs-io/babylon-toolkit/issues/2188.\n *\n * This makes the read RFC-006-only, where the removed getter also existed on a\n * legacy registry. That costs nothing: every caller of this method already\n * resolves participant keys through `OperationKeyReader`, so all of them\n * require an RFC-006 registry regardless.\n *\n * Validates length, hex form, and secp256k1 curve membership before minting\n * the brand. Returns 64-char lowercase hex without the `0x` prefix.\n */\n async getVaultProviderGenesisBtcPubKey(\n vpAddress: Address,\n blockNumber?: bigint,\n ): Promise<OnChainBtcPubkey> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getOperationBtcKeyAtEpoch\",\n args: [vpAddress, VP_GENESIS_KEY_EPOCH],\n blockNumber,\n })) as Hex;\n return assertOnChainBtcPubkey(\n result,\n `getOperationBtcKeyAtEpoch (vp=${vpAddress}, epoch=${VP_GENESIS_KEY_EPOCH})`,\n );\n }\n\n /**\n * Read a vault provider's *current* RFC-006 operation BTC key.\n *\n * Falls back on-chain to the registration key when the provider has never\n * rotated, so this returns the same value as\n * `getVaultProviderGenesisBtcPubKey` until the first rotation.\n *\n * This is the key the VP's server signs its BIP-322 auth tokens with — a\n * live per-operator identity, not a per-vault binding, so the auth pin uses\n * the current key rather than any vault's frozen epoch.\n */\n async getCurrentVaultProviderOperationBtcKey(\n vpAddress: Address,\n ): Promise<OnChainBtcPubkey> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getCurrentOperationBtcKey\",\n args: [vpAddress],\n })) as Hex;\n return assertOnChainBtcPubkey(\n result,\n `getCurrentOperationBtcKey (vp=${vpAddress})`,\n );\n }\n\n /**\n * Read a vault's frozen RFC-006 operation-key epochs.\n *\n * Reads `getBtcVaultProtocolInfo` through the **extended** ABI, which is only\n * valid against an RFC-006 registry: against one whose `BTCVaultProtocolInfo`\n * struct is not extended this call does not fail for a populated vault, it\n * silently returns three words of tail data as epochs. Nothing here can detect\n * that, so the guarantee is a deployment one — every network this ships to has\n * the RFC-006 getters, and mainnet is a fresh RFC-006 deploy.\n *\n * A registry missing the operation-key getters entirely is the *safer* of the\n * two cases: `resolveParticipantKeysAtEpochs` reverts downstream and these\n * epochs never reach key resolution. See {@link UINT64_EXCLUSIVE_UPPER_BOUND}\n * for which state the range check actually guards, and\n * `BTCVaultRegistryKeyEpochs.abi.ts` for the decode hazard.\n */\n async getVaultKeyEpochs(vaultId: Hex): Promise<KeyEpochs> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryKeyEpochsABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n })) as unknown as KeyEpochs;\n\n return mapKeyEpochs(result, vaultId);\n }\n\n async getVaultKeyEpochsBatch(vaultIds: readonly Hex[]): Promise<KeyEpochs[]> {\n if (vaultIds.length === 0) return [];\n\n const results = await this.publicClient.multicall({\n contracts: vaultIds.map((vaultId) => ({\n address: this.contractAddress,\n abi: BTCVaultRegistryKeyEpochsABI as Abi,\n functionName: \"getBtcVaultProtocolInfo\" as const,\n args: [vaultId] as const,\n })),\n allowFailure: false,\n });\n\n return results.map((info, i) =>\n mapKeyEpochs(info as unknown as KeyEpochs, vaultIds[i]),\n );\n }\n\n async getVaultBasicInfo(vaultId: Hex): Promise<VaultBasicInfo> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n })) as RawVaultBasicInfo;\n\n return mapVaultBasicInfo(result);\n }\n\n async getVaultProtocolInfo(vaultId: Hex): Promise<VaultProtocolInfo> {\n const result = (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n })) as RawVaultProtocolInfo;\n\n return mapVaultProtocolInfo(result);\n }\n\n async getProtocolInfoBatch(\n vaultIds: readonly Hex[],\n ): Promise<VaultProtocolInfo[]> {\n if (vaultIds.length === 0) return [];\n\n const results = await this.publicClient.multicall({\n contracts: vaultIds.map((vaultId) => ({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI as Abi,\n functionName: \"getBtcVaultProtocolInfo\" as const,\n args: [vaultId] as const,\n })),\n allowFailure: false,\n });\n\n return results.map((info, i) => {\n const result = info as unknown as RawVaultProtocolInfo;\n if (\n !result.depositorSignedPeginTx ||\n result.depositorSignedPeginTx === \"0x\"\n ) {\n // An empty record is not proof the vault is absent: a lagging RPC\n // node returns HTTP 200 with a zero struct, so no retry below this\n // layer can see it. Single-shot is only safe because the finality\n // gate (`waitForPeginRegistrationDepth`) runs first on the deposit\n // path — move this ahead of it and the read-after-write race returns.\n // The vault app matches this message to render \"still confirming\".\n throw new Error(\n `Vault ${vaultIds[i]} not found on-chain or has no pegin transaction`,\n );\n }\n return mapVaultProtocolInfo(result);\n });\n }\n\n /**\n * Read the protocol pegin fee (in wei) for a given vault provider.\n * Mirrors the `getPegInFee(address)` view on BTCVaultRegistry.\n */\n async getPegInFee(vaultProvider: Address): Promise<bigint> {\n return (await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getPegInFee\",\n args: [vaultProvider],\n })) as bigint;\n }\n\n /**\n * Read a vault provider's current commission in basis points from\n * BTCVaultRegistry. The contract enforces `commissionBps < 10000`, so the\n * legitimate range is `[0, 9999]`; anything outside indicates a wrong\n * contract address or ABI drift and is surfaced as an error rather than\n * trusted.\n */\n async getVaultProviderCommission(vaultProvider: Address): Promise<number> {\n // viem infers `number` from the `uint16` return in the `as const` ABI.\n const bps = await this.publicClient.readContract({\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getVaultProviderCommission\",\n args: [vaultProvider],\n });\n\n if (!Number.isInteger(bps) || bps < 0 || bps > MAX_VP_COMMISSION_BPS) {\n throw new Error(\n `getVaultProviderCommission returned ${bps} bps for ${vaultProvider}, ` +\n `outside the protocol range [0, ${MAX_VP_COMMISSION_BPS}]`,\n );\n }\n\n return bps;\n }\n\n async getVaultData(vaultId: Hex): Promise<VaultData> {\n // One round-trip for both structs (hard-fail): they feed signing/refund/\n // broadcast rebinds, so reading them in a single multicall also pins both\n // to the same block — no basic/protocol skew across two `eth_call`s.\n const [basicRaw, protocolRaw] = await this.publicClient.multicall({\n contracts: [\n {\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n },\n {\n address: this.contractAddress,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultProtocolInfo\",\n args: [vaultId],\n },\n ],\n allowFailure: false,\n });\n\n const basic = mapVaultBasicInfo(basicRaw);\n const protocol = mapVaultProtocolInfo(protocolRaw);\n\n if (\n !protocol.depositorSignedPeginTx ||\n protocol.depositorSignedPeginTx === \"0x\"\n ) {\n throw new Error(\n `Vault ${vaultId} not found on-chain or has no pegin transaction`,\n );\n }\n\n return { basic, protocol };\n }\n\n}\n","import {\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 { BTCVaultRegistryABI } from \"../../contracts/abis/BTCVaultRegistry.abi\";\nimport { handleContractError } from \"../../contracts/errors\";\nimport {\n capMaxAcceptableCommissionBps,\n COMMISSION_BPS_HEADROOM,\n} from \"../../deposit-terms/commissionCeiling\";\nimport { waitForTransactionReceiptSmartAware } from \"../../utils/eth\";\nimport { assertOnChainBtcPubkey } from \"./onChainBtcPubkey\";\nimport { assertPayoutScriptMatchesPopKey } from \"./payout-script\";\nimport { calculateBtcTxHash, derivePeginVaultId } from \"./pegin-transaction\";\nimport { ViemVaultRegistryReader } from \"./vault-registry-reader\";\n\n/** Referral code sent with peg-in registration. Zero means no referral. */\nexport const NO_REFERRAL_CODE = 0;\nconst UINT8_MAX = 255;\n// Match the prior vault-service timeout. A dropped transaction must not wait forever.\nconst RECEIPT_TIMEOUT_MS = 120_000;\n\nfunction ensureHex(value: string, label: string): Hex {\n const prefixed = value.startsWith(\"0x\")\n ? value\n : value.startsWith(\"0X\")\n ? `0x${value.slice(2)}`\n : `0x${value}`;\n if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(prefixed)) {\n throw new Error(`${label} must be non-empty, even-length hex`);\n }\n return prefixed as Hex;\n}\n\nfunction assertBytes32(value: Hex, label: string): void {\n if (!/^0x[0-9a-fA-F]{64}$/.test(value)) {\n throw new Error(`${label} must be a 32-byte hex value`);\n }\n}\n\nfunction assertHtlcVout(value: number): void {\n if (!Number.isInteger(value) || value < 0 || value > UINT8_MAX) {\n throw new Error(`htlcVout must be a uint8, got ${value}`);\n }\n}\n\n/** A PoP prepared by a Bitcoin wallet, reusable by the ETH submit client. */\nexport interface PopSignature {\n btcPopSignature: Hex;\n depositorEthAddress: Address;\n /** x-only secp256k1 public key, 64 hex chars without `0x`. */\n depositorBtcPubkey: string;\n}\n\nexport interface ViemPeginRegistrationClientConfig {\n ethWallet: WalletClient;\n ethChain: Chain;\n publicClient: PublicClient;\n btcVaultRegistry: Address;\n receiptTimeoutMs?: number;\n /**\n * Refuse to register without a `quotedCommissionBps`. Set it to `true` when\n * the depositor approved deposit terms on a device: approval froze the\n * commission ceiling from the quote, so the chain-current fallback could\n * admit a commission the device would later refuse to pay out.\n *\n * Required, with no default: an omitted flag would silently pick the unsafe\n * direction for the integrator least able to probe the wallet capability.\n */\n requireQuotedCommissionBps: boolean;\n}\n\nexport interface RegisterPeginOnChainParams {\n unsignedPrePeginTx: string;\n depositorSignedPeginTx: string;\n vaultProvider: Address;\n hashlock: Hex;\n depositorWotsPkHash: Hex;\n popSignature: PopSignature;\n /** Raw x-only, compressed, or uncompressed BTC pubkey from the PoP wallet. */\n depositorBtcPubkeyRaw: string;\n htlcVout: number;\n /**\n * Bitcoin output script bytes, not an address. The client verifies that the\n * script pays the proof-of-possession key before it submits the transaction.\n */\n depositorPayoutScriptPubKey: string;\n quotedCommissionBps?: number;\n}\n\nexport interface PeginRegistrationResult {\n ethTxHash: Hex;\n vaultId: Hex;\n peginTxHash: Hex;\n}\n\nexport interface BatchPeginRegistrationItem {\n depositorSignedPeginTx: string;\n hashlock: Hex;\n htlcVout: number;\n /**\n * Bitcoin output script bytes, not an address. The client verifies that the\n * script pays the proof-of-possession key before it submits the transaction.\n */\n depositorPayoutScriptPubKey: string;\n depositorWotsPkHash: Hex;\n}\n\nexport interface RegisterPeginBatchOnChainParams {\n vaultProvider: Address;\n unsignedPrePeginTx: string;\n requests: BatchPeginRegistrationItem[];\n popSignature: PopSignature;\n /** Raw x-only, compressed, or uncompressed BTC pubkey from the PoP wallet. */\n depositorBtcPubkeyRaw: string;\n quotedCommissionBps?: number;\n}\n\nexport interface BatchPeginRegistrationResultItem {\n vaultId: Hex;\n peginTxHash: Hex;\n}\n\nexport interface PeginBatchRegistrationResult {\n ethTxHash: Hex;\n vaults: BatchPeginRegistrationResultItem[];\n}\n\n/**\n * Ethereum-only client for the on-chain half of peg-in registration.\n *\n * It consumes Bitcoin artifacts that were prepared earlier, but owns no BTC\n * wallet and imports neither Bitcoin libraries nor the Rust/WASM package.\n */\nexport class ViemPeginRegistrationClient {\n constructor(private readonly config: ViemPeginRegistrationClientConfig) {}\n\n async registerPeginOnChain(\n params: RegisterPeginOnChainParams,\n ): Promise<PeginRegistrationResult> {\n const request = {\n ...params,\n popSignature: { ...params.popSignature },\n };\n this.assertQuotedCommissionPresentWhenRequired(request.quotedCommissionBps);\n const depositor = this.assertPopMatchesEthAccount(request.popSignature);\n const depositorBtcPubkey = this.normalizeBtcPubkey(request.popSignature);\n const btcPopSignature = ensureHex(\n request.popSignature.btcPopSignature,\n \"btcPopSignature\",\n );\n const normalized = this.normalizeRequest(\n request,\n depositor,\n depositorBtcPubkey,\n );\n\n await this.assertVaultDoesNotExist(\n normalized.vaultId,\n normalized.peginTxHash,\n );\n const peginFee = await this.readPeginFee(request.vaultProvider);\n const maxCommission = await this.resolveMaxAcceptableCommissionBps(\n request.vaultProvider,\n request.quotedCommissionBps,\n );\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequest\",\n args: [\n depositor,\n depositorBtcPubkey,\n btcPopSignature,\n normalized.unsignedPrePeginTx,\n normalized.depositorSignedPeginTx,\n request.vaultProvider,\n maxCommission,\n request.hashlock,\n request.htlcVout,\n normalized.payoutScript,\n request.depositorWotsPkHash,\n ],\n });\n\n const ethTxHash = await this.sendAndWait(\n callData,\n peginFee,\n false,\n depositor,\n );\n return {\n ethTxHash,\n vaultId: normalized.vaultId,\n peginTxHash: normalized.peginTxHash,\n };\n }\n\n async registerPeginBatchOnChain(\n params: RegisterPeginBatchOnChainParams,\n ): Promise<PeginBatchRegistrationResult> {\n const batch = {\n ...params,\n popSignature: { ...params.popSignature },\n requests: params.requests.map((request) => ({ ...request })),\n };\n if (batch.requests.length === 0) {\n throw new Error(\"Batch pegin requires at least one request\");\n }\n this.assertQuotedCommissionPresentWhenRequired(batch.quotedCommissionBps);\n const depositor = this.assertPopMatchesEthAccount(batch.popSignature);\n const unsignedPrePeginTx = ensureHex(\n batch.unsignedPrePeginTx,\n \"unsignedPrePeginTx\",\n );\n const depositorBtcPubkey = this.normalizeBtcPubkey(batch.popSignature);\n const btcPopSignature = ensureHex(\n batch.popSignature.btcPopSignature,\n \"btcPopSignature\",\n );\n\n const vaults: BatchPeginRegistrationResultItem[] = [];\n const requests = [];\n const seenVaultIds = new Set<string>();\n for (const request of batch.requests) {\n const normalized = this.normalizeRequest(\n {\n ...request,\n unsignedPrePeginTx: batch.unsignedPrePeginTx,\n vaultProvider: batch.vaultProvider,\n depositorBtcPubkeyRaw: batch.depositorBtcPubkeyRaw,\n },\n depositor,\n depositorBtcPubkey,\n );\n if (seenVaultIds.has(normalized.vaultId)) {\n throw new Error(`Duplicate vault in batch: ${normalized.vaultId}`);\n }\n seenVaultIds.add(normalized.vaultId);\n vaults.push({\n vaultId: normalized.vaultId,\n peginTxHash: normalized.peginTxHash,\n });\n requests.push({\n depositorBtcPubKey: depositorBtcPubkey,\n btcPopSignature,\n unsignedPrePeginTx,\n depositorSignedPeginTx: normalized.depositorSignedPeginTx,\n hashlock: request.hashlock,\n htlcVout: request.htlcVout,\n referralCode: NO_REFERRAL_CODE,\n depositorPayoutBtcAddress: normalized.payoutScript,\n depositorWotsPkHash: request.depositorWotsPkHash,\n });\n }\n for (const vault of vaults) {\n await this.assertVaultDoesNotExist(vault.vaultId, vault.peginTxHash);\n }\n\n const peginFee = await this.readPeginFee(batch.vaultProvider);\n const maxCommission = await this.resolveMaxAcceptableCommissionBps(\n batch.vaultProvider,\n batch.quotedCommissionBps,\n );\n const callData = encodeFunctionData({\n abi: BTCVaultRegistryABI,\n functionName: \"submitPeginRequestBatch\",\n args: [depositor, batch.vaultProvider, maxCommission, requests],\n });\n const ethTxHash = await this.sendAndWait(\n callData,\n peginFee * BigInt(batch.requests.length),\n true,\n depositor,\n );\n return { ethTxHash, vaults };\n }\n\n private assertQuotedCommissionPresentWhenRequired(\n quotedCommissionBps?: number,\n ): void {\n if (\n quotedCommissionBps === undefined &&\n this.config.requireQuotedCommissionBps\n ) {\n throw new Error(\n \"quotedCommissionBps is required when the wallet approved deposit \" +\n \"terms: the registration ceiling must anchor to the approved quote.\",\n );\n }\n }\n\n private assertPopMatchesEthAccount(pop: PopSignature): Address {\n return this.assertEthAccount(pop.depositorEthAddress);\n }\n\n private assertEthAccount(expectedDepositor: Address): Address {\n const account = this.config.ethWallet.account;\n if (!account) throw new Error(\"Ethereum wallet account not found\");\n if (!isAddressEqual(expectedDepositor, account.address)) {\n throw new Error(\n `Proof of possession was signed for ${expectedDepositor} ` +\n `but the Ethereum wallet is currently connected to ${account.address}. ` +\n `Reconnect the original account or sign a new proof of possession.`,\n );\n }\n return account.address;\n }\n\n private normalizeBtcPubkey(pop: PopSignature): Hex {\n return `0x${assertOnChainBtcPubkey(\n ensureHex(pop.depositorBtcPubkey, \"Proof of possession BTC pubkey\"),\n \"Proof of possession BTC pubkey\",\n )}`;\n }\n\n private normalizeRequest(\n params: Omit<RegisterPeginOnChainParams, \"popSignature\">,\n depositor: Address,\n depositorBtcPubkey: Hex,\n ) {\n assertBytes32(params.hashlock, \"hashlock\");\n assertBytes32(params.depositorWotsPkHash, \"depositorWotsPkHash\");\n assertHtlcVout(params.htlcVout);\n const unsignedPrePeginTx = ensureHex(\n params.unsignedPrePeginTx,\n \"unsignedPrePeginTx\",\n );\n const depositorSignedPeginTx = ensureHex(\n params.depositorSignedPeginTx,\n \"depositorSignedPeginTx\",\n );\n const peginTxHash = calculateBtcTxHash(depositorSignedPeginTx);\n return {\n unsignedPrePeginTx,\n depositorSignedPeginTx,\n payoutScript: assertPayoutScriptMatchesPopKey(\n params.depositorPayoutScriptPubKey,\n depositorBtcPubkey,\n params.depositorBtcPubkeyRaw,\n ),\n peginTxHash,\n vaultId: ensureHex(derivePeginVaultId(peginTxHash, depositor), \"vaultId\"),\n };\n }\n\n private async assertVaultDoesNotExist(\n vaultId: Hex,\n peginTxHash: Hex,\n ): Promise<void> {\n const result = (await this.config.publicClient.readContract({\n address: this.config.btcVaultRegistry,\n abi: BTCVaultRegistryABI,\n functionName: \"getBtcVaultBasicInfo\",\n args: [vaultId],\n })) as { depositor: Address };\n if (result.depositor !== zeroAddress) {\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\n private async readPeginFee(vaultProvider: Address): Promise<bigint> {\n try {\n return (await this.config.publicClient.readContract({\n address: this.config.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 contract address.\",\n { cause: error },\n );\n }\n }\n\n private async resolveMaxAcceptableCommissionBps(\n vaultProvider: Address,\n quotedCommissionBps?: number,\n ): Promise<number> {\n let currentBps: number;\n try {\n currentBps = await new ViemVaultRegistryReader(\n this.config.publicClient,\n this.config.btcVaultRegistry,\n ).getVaultProviderCommission(vaultProvider);\n } catch (error) {\n throw new Error(\n \"Failed to query vault provider commission from the contract. \" +\n \"Please check your network connection and contract address.\",\n { cause: error },\n );\n }\n if (quotedCommissionBps !== undefined) {\n if (currentBps > quotedCommissionBps + COMMISSION_BPS_HEADROOM) {\n throw new Error(\n `Vault provider commission changed since quote: quoted ${quotedCommissionBps} bps, ` +\n `chain currently reports ${currentBps} bps (allowed drift ${COMMISSION_BPS_HEADROOM} bps). ` +\n `Please refresh and try again.`,\n );\n }\n return capMaxAcceptableCommissionBps(quotedCommissionBps);\n }\n return capMaxAcceptableCommissionBps(currentBps);\n }\n\n private async sendAndWait(\n data: Hex,\n value: bigint,\n batch: boolean,\n depositor: Address,\n ): Promise<Hex> {\n let account = this.assertEthAccount(depositor);\n let gas: bigint;\n try {\n gas = await this.config.publicClient.estimateGas({\n to: this.config.btcVaultRegistry,\n data,\n value,\n account,\n });\n } catch (error) {\n handleContractError(error);\n }\n\n account = this.assertEthAccount(depositor);\n let submittedHash: Hex;\n try {\n submittedHash = await this.config.ethWallet.sendTransaction({\n to: this.config.btcVaultRegistry,\n data,\n value,\n gas,\n account,\n chain: this.config.ethChain,\n });\n } catch (error) {\n handleContractError(error);\n }\n const receipt = await waitForTransactionReceiptSmartAware({\n publicClient: this.config.publicClient,\n walletAddress: depositor,\n hash: submittedHash,\n timeout: this.config.receiptTimeoutMs ?? RECEIPT_TIMEOUT_MS,\n });\n if (receipt.status === \"reverted\") {\n handleContractError(\n new Error(\n `${batch ? \"Batch transaction\" : \"Transaction\"} reverted. ` +\n `Hash: ${receipt.transactionHash}. Check a block explorer for details.`,\n ),\n );\n }\n return receipt.transactionHash;\n }\n}\n"],"names":["COMMISSION_BPS_HEADROOM","MAX_ACCEPTABLE_COMMISSION_BPS_CAP","capMaxAcceptableCommissionBps","bps","MAX_VP_COMMISSION_BPS_EXCLUSIVE","Rho160","Id160","_","i","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","offset","al","ar","bl","br","cl","cr","dl","dr","el","er","rGroup","hbl","hbr","rl","rr","sl","sr","tl","rotl","tr","clean","ripemd160","createHasher","P2TR_SCRIPT_PREFIX","P2WPKH_SCRIPT_PREFIX","HASH160_BYTES","COMPRESSED_PUBKEY_BYTES","UNCOMPRESSED_PUBKEY_BYTES","SEC1_EVEN_Y_PREFIX","SEC1_ODD_Y_PREFIX","SEC1_UNCOMPRESSED_PREFIX","normalizeHex","value","label","body","deriveP2trScript","xOnlyPubkey","pubkeyBytes","hexToBytes","internalKey","schnorr","tweak","secp256k1","outputKey","bytesToHex","normalizePayoutPubkey","normalized","pubkey","assertOnChainBtcPubkey","isCompressed","isUncompressed","deriveP2wpkhScript","sha256","assertPayoutScriptMatchesPopKey","scriptPubKey","depositorBtcPubkey","depositorBtcPubkeyRaw","payoutScript","MAX_PAYOUT_SCRIPT_LEN","keyBody","payoutPubkey","decodeHex","bytes","encodeHex","byte","concatBytes","chunks","result","length","chunk","serializeWithoutWitness","transaction","take","readLittleEndian","readCompactSize","start","prefix","version","hasWitness","inputCount","inputs","scriptLength","outputCount","outputs","hasWitnessData","itemCount","itemLength","locktime","calculateBtcTxHash","transactionHex","serialized","digest","derivePeginVaultId","peginTxHash","depositor","normalizedPeginTxHash","normalizedDepositor","isAddress","keccak256","encodeAbiParameters","UINT16_MAX","MAX_BASIS_POINTS","UINT32_MAX","UINT8_MAX","assertValidOffchainParamsVersion","validateOffchainParams","params","errors","validateTBVProtocolParams","validatePegInConfiguration","config","assertValidVaultCoreVersion","MAX_VP_COMMISSION_BPS","mapVaultBasicInfo","mapVaultProtocolInfo","offchainParamsVersion","UINT64_EXCLUSIVE_UPPER_BOUND","VP_GENESIS_KEY_EPOCH","assertEpochInRange","field","vaultId","mapKeyEpochs","ViemVaultRegistryReader","publicClient","contractAddress","vpAddress","blockNumber","BTCVaultRegistryABI","BTCVaultRegistryKeyEpochsABI","vaultIds","info","vaultProvider","basicRaw","protocolRaw","basic","protocol","NO_REFERRAL_CODE","RECEIPT_TIMEOUT_MS","ensureHex","prefixed","assertBytes32","assertHtlcVout","ViemPeginRegistrationClient","request","btcPopSignature","peginFee","maxCommission","callData","encodeFunctionData","batch","unsignedPrePeginTx","vaults","requests","seenVaultIds","vault","quotedCommissionBps","pop","expectedDepositor","account","isAddressEqual","depositorSignedPeginTx","zeroAddress","error","currentBps","data","gas","handleContractError","submittedHash","receipt","waitForTransactionReceiptSmartAware"],"mappings":"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","x_google_ignoreList":[1]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var z=Object.defineProperty;var Q=(r,e,t)=>e in r?z(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var d=(r,e,t)=>Q(r,typeof e!="symbol"?e+"":e,t);const g=require("./bitcoin-D-O2GjbC.cjs"),Z=require("./index-Cs7_Evtk.cjs"),ee=require("./json-rpc-client-BiAmg_ho.cjs"),te=require("@bitcoin-js/tiny-secp256k1-asmjs"),_=require("./validation-C6XTfZak.cjs"),re=require("./bip322Verify-B7_gIhRk.cjs"),ne=require("./sha2-DI0-0SHr.cjs");function ie(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const D=ie(te);function m(r,e){const t=(r&7)<<5,n=typeof e=="bigint"?e:BigInt(e);if(n<0n)throw new Error("cborHead: negative argument");if(n<24n)return new Uint8Array([t|Number(n)]);if(n<0x100n)return new Uint8Array([t|24,Number(n)]);if(n<0x10000n){const i=Number(n);return new Uint8Array([t|25,i>>>8&255,i&255])}if(n<0x100000000n){const i=Number(n);return new Uint8Array([t|26,i>>>24&255,i>>>16&255,i>>>8&255,i&255])}const s=new Uint8Array(9);s[0]=t|27;for(let i=7;i>=0;i--)s[1+i]=Number(n>>BigInt((7-i)*8))&255;return s}function V(...r){const e=r.reduce((s,i)=>s+i.length,0),t=new Uint8Array(e);let n=0;for(const s of r)t.set(s,n),n+=s.length;return t}function $(r){const t=[m(4,r.length)];for(const n of r)t.push(m(0,n));return V(...t)}function se(r,e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error(`encodeServerIdentityPayload: expires_at must be a non-negative safe integer, got ${t}`);const n=m(4,3),s=$(r),i=$(e),o=m(0,t);return V(n,s,i,o)}const oe=new TextEncoder().encode("btc-auth.server-identity.v1"),ae=2*3600;class l extends Error{constructor(e,t){super(e),this.reason=t,this.name="ServerIdentityError"}}function E(r){const e=new Uint8Array(r.length/2);for(let t=0;t<e.length;t++)e[t]=parseInt(r.slice(t*2,t*2+2),16);return e}function j(r){const{proof:e,pinnedServerPubkey:t,now:n}=r,s=r.maxLifetimeSecs??ae,i=g.stripHexPrefix(t).toLowerCase();if(i.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(i))throw new l(`pinnedServerPubkey must be 32-byte hex; got ${i.length} chars`,"invalid_pubkey_encoding");const o=g.stripHexPrefix(e.server_pubkey).toLowerCase();if(o.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(o))throw new l(`server_pubkey must be 32-byte hex; got ${o.length} chars`,"invalid_pubkey_encoding");if(o!==i)throw new l(`server_pubkey does not match pinned value: expected ${i}, got ${o}`,"pinned_pubkey_mismatch");if(!Number.isSafeInteger(e.expires_at))throw new l(`expires_at must be a finite integer; got ${JSON.stringify(e.expires_at)}`,"invalid_expires_at");if(!Number.isSafeInteger(n))throw new l(`now must be a finite integer; got ${JSON.stringify(n)}`,"invalid_expires_at");if(e.expires_at<=n)throw new l(`server identity proof expired at ${e.expires_at}, now ${n}`,"expired");if(!Number.isSafeInteger(s)||s<=0)throw new l(`maxLifetimeSecs must be a positive safe integer; got ${JSON.stringify(s)}`,"invalid_max_lifetime");if(e.expires_at-n>s)throw new l(`server identity proof expires too far in the future: expires_at=${e.expires_at}, now=${n}, max lifetime=${s}s`,"expires_too_far");const c=g.stripHexPrefix(e.ephemeral_pubkey).toLowerCase();if(c.length!==_.COMPRESSED_PUBKEY_HEX_LEN||!_.HEX_RE.test(c))throw new l(`ephemeral_pubkey must be 33-byte compressed hex; got ${c.length} chars`,"invalid_ephemeral_pubkey");const y=c.slice(0,2);if(y!=="02"&&y!=="03")throw new l(`ephemeral_pubkey must be compressed (prefix 02/03); got ${y}`,"invalid_ephemeral_pubkey");const p=E(c);if(!D.isPoint(p))throw new l("ephemeral_pubkey is not a valid secp256k1 point","invalid_ephemeral_pubkey");const h=g.stripHexPrefix(e.signature).toLowerCase();if(h.length!==g.SCHNORR_SIG_HEX_LEN||!_.HEX_RE.test(h))throw new l(`signature must be 64-byte Schnorr hex; got ${h.length} chars`,"invalid_signature_encoding");const x=se(oe,E(c),e.expires_at);if(!re.verifyBip322Simple(x,E(o),E(h)))throw new l("BIP-322 signature verification failed — ephemeral key is not attested by pinned server pubkey","signature_verification_failed")}const ce=new Set(["vaultProvider_submitDepositorWotsKey","vaultProvider_submitDepositorPresignatures","vaultProvider_requestDepositorPresignTransactions"]),ue=new Set(["vaultProvider_requestDepositorClaimerArtifacts"]),de=6e4,P="auth_createDepositorToken",C="auth_createDepositorTokenGrpc";function J(r,e){return new ee.JsonRpcClient({baseUrl:r,timeout:de,headers:e,retryableFor:t=>t===P||t===C})}const he=0,le=1,k=2,pe=3,_e=4,ye=5,ge=6,fe=7,H=24,xe=28,be=20,we=21,Ee=22,N=256;class f extends Error{constructor(e){super(`CBOR decode: ${e}`),this.name="CborDecodeError"}}class F{constructor(e){d(this,"buf");d(this,"pos",0);this.buf=e}nextByte(){if(this.pos>=this.buf.length)throw new f("unexpected end of input");return this.buf[this.pos++]}readHead(){const e=this.nextByte(),t=e>>5,n=e&31;if(n<H)return{major:t,arg:n};if(n>=xe)throw new f(`unsupported additional info ${n} (indefinite-length or reserved)`);const s=1<<n-H;let i=0n;for(let o=0;o<s;o++)i=i<<8n|BigInt(this.nextByte());if(i>BigInt(Number.MAX_SAFE_INTEGER))throw new f(`argument ${i} exceeds safe integer range`);return{major:t,arg:Number(i)}}readBytes(e){if(this.pos+e>this.buf.length)throw new f("length overruns end of input");const t=this.buf.subarray(this.pos,this.pos+e);return this.pos+=e,t}readByteString(){const e=this.readHead();if(e.major!==k)throw new f(`expected byte string (major ${k}), got major ${e.major}`);return this.readBytes(e.arg)}readValue(e=0){if(e>N)throw new f(`nesting exceeds maximum depth ${N}`);const t=this.readHead();switch(t.major){case he:return t.arg;case le:return-1-t.arg;case k:return this.readBytes(t.arg);case pe:return new TextDecoder("utf-8",{fatal:!0}).decode(this.readBytes(t.arg));case _e:{const n=[];for(let s=0;s<t.arg;s++)n.push(this.readValue(e+1));return n}case ye:{const n=new Map;for(let s=0;s<t.arg;s++){const i=this.readValue(e+1),o=this.readValue(e+1);n.set(i,o)}return n}case ge:return{tag:t.arg,value:this.readValue(e+1)};case fe:if(t.arg===be)return!1;if(t.arg===we)return!0;if(t.arg===Ee)return null;throw new f(`unsupported simple/float value ${t.arg}`);default:throw new f(`unsupported major type ${t.major}`)}}}function Y(r){const e=new F(r),t=e.readValue();if(e.pos!==r.length)throw new f("trailing bytes after top-level item");return t}const me="vaultd-jsonrpc",Ae="vaultd-grpc",M=18,O=4,B=-47,Se=1,X=64,ke=128,ve=96,Te=64,Pe=1,Ce=2,Oe=3,Re=4,Ie=5,$e=6,He=7,L=new TextEncoder().encode("Signature1");class a extends Error{constructor(e,t){super(e),this.reason=t,this.name="CwtVerificationError"}}function Ne(r){const e=G(r.expectedIssuerXOnlyPubkey,"expectedIssuerXOnlyPubkey"),t=G(r.expectedAudienceXOnlyPubkey,"expectedAudienceXOnlyPubkey"),n=Ge(r.ephemeralPubkeyHex),s=De(r.token),i=new F(s),o=i.readHead();if(o.major!==6||o.arg!==M)throw new a(`token is not a COSE Sign1 tagged value (tag ${M})`,"invalid_token_structure");const c=i.readHead();if(c.major!==4||c.arg!==O)throw new a(`COSE Sign1 must be a ${O}-element array`,"invalid_token_structure");const y=i.pos,p=i.readByteString(),h=s.subarray(y,i.pos);i.readValue();const x=i.pos,b=i.readByteString(),A=s.subarray(x,i.pos),S=i.readByteString();if(S.length!==X)throw new a(`COSE signature must be ${X} bytes, got ${S.length}`,"invalid_token_structure");if(i.pos!==s.length)throw new a("COSE Sign1 token has trailing bytes after the signature","invalid_token_structure");const I=Me(p);if(I!==B)throw new a(`unexpected COSE algorithm ${I} (expected ES256K ${B})`,"unexpected_algorithm");const K=Be(h,A),W=ne.sha256(K);if(!D.verify(W,n,S,!0))throw new a("COSE signature does not verify against the server's ephemeral key","signature_verification_failed");const u=Xe(b),w=u.audience.toLowerCase();if(w.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(w))throw new a("token `aud` is not a 32-byte x-only pubkey hex","invalid_claims");if(u.issuedAt>u.expiresAt)throw new a(`token iat (${u.issuedAt}) is after exp (${u.expiresAt})`,"invalid_claims");if(u.issuer.toLowerCase()!==e)throw new a(`token issuer does not match pinned server pubkey: expected ${e}, got ${u.issuer.toLowerCase()}`,"issuer_mismatch");if(u.subject!==r.expectedSubject)throw new a(`token subject mismatch: expected ${r.expectedSubject}, got ${u.subject}`,"subject_mismatch");if(w!==t)throw new a(`token audience does not match depositor pubkey: expected ${t}, got ${w}`,"audience_mismatch");if(u.expiresAt<=r.now)throw new a(`token expired: exp ${u.expiresAt} <= now ${r.now}`,"token_expired");if(r.responseExpiresAt!==u.expiresAt)throw new a(`response expires_at (${r.responseExpiresAt}) does not equal token exp (${u.expiresAt})`,"expiry_mismatch");if(r.serverIdentityExpiresAt<u.expiresAt)throw new a(`server identity expires (${r.serverIdentityExpiresAt}) before token exp (${u.expiresAt})`,"server_identity_expires_before_token");return{issuer:u.issuer,subject:u.subject,audience:w,expiresAt:u.expiresAt,notBefore:u.notBefore,issuedAt:u.issuedAt}}function Me(r){if(r.length===0)throw new a("empty COSE protected header (no algorithm)","unexpected_algorithm");const e=Y(r);if(!(e instanceof Map))throw new a("COSE protected header is not a map","invalid_token_structure");const t=e.get(Se);if(typeof t!="number")throw new a("COSE protected header missing integer algorithm label","unexpected_algorithm");return t}function Be(r,e){return Ve(Uint8Array.of(ke|O),Uint8Array.of(ve|L.length),L,r,Uint8Array.of(Te),e)}function Xe(r){const e=Y(r);if(!(e instanceof Map))throw new a("CWT claims root is not a map","invalid_claims");if(Le(e,He,"cti").length===0)throw new a("token cti is empty","invalid_claims");return{issuer:v(e,Pe,"iss"),subject:v(e,Ce,"sub"),audience:v(e,Oe,"aud"),expiresAt:T(e,Re,"exp"),notBefore:T(e,Ie,"nbf"),issuedAt:T(e,$e,"iat")}}function v(r,e,t){const n=r.get(e);if(typeof n!="string")throw new a(`token claim ${t} is missing or not a text string`,"invalid_claims");return n}function Le(r,e,t){const n=r.get(e);if(!(n instanceof Uint8Array))throw new a(`token claim ${t} is missing or not a byte string`,"invalid_claims");return n}function T(r,e,t){const n=r.get(e);if(typeof n!="number"||!Number.isSafeInteger(n)||n<0)throw new a(`token claim ${t} is missing or not a non-negative integer timestamp`,"invalid_claims");return n}function G(r,e){const t=g.stripHexPrefix(r).toLowerCase();if(t.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(t))throw new a(`${e} must be 32-byte x-only hex; got ${t.length} chars`,"invalid_input");return t}function Ge(r){const e=g.stripHexPrefix(r).toLowerCase(),t=e.slice(0,2);if(e.length!==_.COMPRESSED_PUBKEY_HEX_LEN||!_.HEX_RE.test(e)||t!=="02"&&t!=="03")throw new a("ephemeralPubkeyHex must be 33-byte compressed pubkey hex (prefix 02/03)","invalid_input");return g.hexToUint8Array(e)}const Ue=(()=>{const r=new Int16Array(128).fill(-1),e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";for(let t=0;t<e.length;t++)r[e.charCodeAt(t)]=t;return r})();function De(r){const e=r.length,t=Math.floor(e/4),n=e%4;if(n===1)throw new a("invalid base64url length","invalid_token_structure");const s=t*3+(n===0?0:n-1),i=new Uint8Array(s),o=p=>{const h=p<128?Ue[p]:-1;if(h<0)throw new a("invalid base64url character","invalid_token_structure");return h};let c=0,y=0;for(let p=0;p<t;p++){const h=o(r.charCodeAt(c++)),x=o(r.charCodeAt(c++)),b=o(r.charCodeAt(c++)),A=o(r.charCodeAt(c++));i[y++]=h<<2|x>>4,i[y++]=(x&15)<<4|b>>2,i[y++]=(b&3)<<6|A}if(n===2){const p=o(r.charCodeAt(c++)),h=o(r.charCodeAt(c++));i[y++]=p<<2|h>>4}else if(n===3){const p=o(r.charCodeAt(c++)),h=o(r.charCodeAt(c++)),x=o(r.charCodeAt(c++));i[y++]=p<<2|h>>4,i[y++]=(h&15)<<4|x>>2}return i}function Ve(...r){const e=r.reduce((s,i)=>s+i.length,0),t=new Uint8Array(e);let n=0;for(const s of r)t.set(s,n),n+=s.length;return t}const U=4102444800,je=30;class Je{constructor(e){d(this,"client");d(this,"peginTxid");d(this,"authAnchorHex");d(this,"pinnedServerPubkey");d(this,"expectedAudienceXOnlyPubkey");d(this,"authGatedMethods");d(this,"grpcGatedMethods");d(this,"refreshSkewSecs");d(this,"now");d(this,"cachedJsonRpc",null);d(this,"inFlightJsonRpc",null);d(this,"cachedGrpc",null);d(this,"inFlightGrpc",null);this.client=e.client,this.peginTxid=e.peginTxid,this.authAnchorHex=e.authAnchorHex,this.pinnedServerPubkey=e.pinnedServerPubkey,this.expectedAudienceXOnlyPubkey=e.expectedAudienceXOnlyPubkey,this.authGatedMethods=e.authGatedMethods,this.grpcGatedMethods=e.grpcGatedMethods,this.refreshSkewSecs=e.refreshSkewSecs??je,this.now=e.now??(()=>Math.floor(Date.now()/1e3))}async getToken(e){return e===P||e===C?null:this.grpcGatedMethods.has(e)?this.getTokenForSubject("grpc"):this.authGatedMethods.has(e)?this.getTokenForSubject("jsonrpc"):null}invalidate(){this.cachedJsonRpc=null,this.cachedGrpc=null}async getTokenForSubject(e){const t=e==="grpc"?this.cachedGrpc:this.cachedJsonRpc;return t&&this.now()+this.refreshSkewSecs<t.expiresAt?t.token:(await this.acquireSingleFlight(e)).token}setClient(e){this.client=e}acquireSingleFlight(e){const t=e==="grpc"?this.inFlightGrpc:this.inFlightJsonRpc;if(t)return t;const n=e==="grpc"?C:P,s=(async()=>{try{const i=await this.client.call(n,{pegin_txid:this.peginTxid,auth_anchor:this.authAnchorHex});if(j({proof:i.server_identity,pinnedServerPubkey:this.pinnedServerPubkey,now:this.now()}),typeof i.token!="string"||i.token.length===0)throw new Error(`VpTokenProvider: invalid token in acquire response (expected non-empty string, got ${typeof i.token})`);const o=this.now();if(!Number.isSafeInteger(i.expires_at)||i.expires_at<=o||i.expires_at>U)throw new Error(`VpTokenProvider: invalid expires_at in acquire response (got ${JSON.stringify(i.expires_at)}; must be a safe integer in (${o}, ${U}])`);Ne({token:i.token,ephemeralPubkeyHex:i.server_identity.ephemeral_pubkey,expectedIssuerXOnlyPubkey:this.pinnedServerPubkey,expectedSubject:e==="grpc"?Ae:me,expectedAudienceXOnlyPubkey:this.expectedAudienceXOnlyPubkey,responseExpiresAt:i.expires_at,serverIdentityExpiresAt:i.server_identity.expires_at,now:o});const c={token:i.token,expiresAt:i.expires_at};return e==="grpc"?this.cachedGrpc=c:this.cachedJsonRpc=c,c}finally{e==="grpc"?this.inFlightGrpc=null:this.inFlightJsonRpc=null}})();return e==="grpc"?this.inFlightGrpc=s:this.inFlightJsonRpc=s,s}}class q{constructor(){d(this,"entries",new Map)}getOrCreate(e){const t=this.entries.get(e.peginTxid);if(t){if(t.authAnchorHex!==e.authAnchorHex)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to authAnchorHex ${t.authAnchorHex.slice(0,8)}…; got ${e.authAnchorHex.slice(0,8)}…`);if(t.pinnedServerPubkey!==e.pinnedServerPubkey)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to pinnedServerPubkey ${t.pinnedServerPubkey.slice(0,8)}…; got ${e.pinnedServerPubkey.slice(0,8)}…`);if(t.expectedAudienceXOnlyPubkey!==e.expectedAudienceXOnlyPubkey)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to expectedAudienceXOnlyPubkey ${t.expectedAudienceXOnlyPubkey.slice(0,8)}…; got ${e.expectedAudienceXOnlyPubkey.slice(0,8)}…`);return t.provider.setClient(e.client),t.provider}const n=new Je({client:e.client,peginTxid:e.peginTxid,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey,expectedAudienceXOnlyPubkey:e.expectedAudienceXOnlyPubkey,authGatedMethods:ce,grpcGatedMethods:ue});return this.entries.set(e.peginTxid,{provider:n,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey,expectedAudienceXOnlyPubkey:e.expectedAudienceXOnlyPubkey}),n}peek(e){var t;return(t=this.entries.get(e))==null?void 0:t.provider}release(e){this.entries.delete(e)}clear(){this.entries.clear()}get size(){return this.entries.size}}const R=new q;function Fe(r){var n;const e=J(r.baseUrl,(n=r.options)==null?void 0:n.headers),t=R.getOrCreate({client:e,peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey,expectedAudienceXOnlyPubkey:g.processPublicKeyToXOnly(r.depositorBtcPubkey)});return new Z.VaultProviderRpcClient(r.baseUrl,{...r.options,tokenProvider:t})}function Ye(r){R.getOrCreate({client:J(r.baseUrl,r.headers),peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey,expectedAudienceXOnlyPubkey:g.processPublicKeyToXOnly(r.depositorBtcPubkey)})}exports.ServerIdentityError=l;exports.VpTokenRegistry=q;exports.createAuthenticatedVpClient=Fe;exports.primeVpTokenRegistry=Ye;exports.verifyServerIdentity=j;exports.vpTokenRegistry=R;
|
|
2
|
-
//# sourceMappingURL=primeVpAuth-
|
|
1
|
+
"use strict";var z=Object.defineProperty;var Q=(r,e,t)=>e in r?z(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var d=(r,e,t)=>Q(r,typeof e!="symbol"?e+"":e,t);const g=require("./bitcoin-D-O2GjbC.cjs"),Z=require("./index-CK1Xvq4K.cjs"),ee=require("./json-rpc-client-BiAmg_ho.cjs"),te=require("@bitcoin-js/tiny-secp256k1-asmjs"),_=require("./validation-C6XTfZak.cjs"),re=require("./bip322Verify-B7_gIhRk.cjs"),ne=require("./sha2-DI0-0SHr.cjs");function ie(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const n=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,n.get?n:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const D=ie(te);function m(r,e){const t=(r&7)<<5,n=typeof e=="bigint"?e:BigInt(e);if(n<0n)throw new Error("cborHead: negative argument");if(n<24n)return new Uint8Array([t|Number(n)]);if(n<0x100n)return new Uint8Array([t|24,Number(n)]);if(n<0x10000n){const i=Number(n);return new Uint8Array([t|25,i>>>8&255,i&255])}if(n<0x100000000n){const i=Number(n);return new Uint8Array([t|26,i>>>24&255,i>>>16&255,i>>>8&255,i&255])}const s=new Uint8Array(9);s[0]=t|27;for(let i=7;i>=0;i--)s[1+i]=Number(n>>BigInt((7-i)*8))&255;return s}function V(...r){const e=r.reduce((s,i)=>s+i.length,0),t=new Uint8Array(e);let n=0;for(const s of r)t.set(s,n),n+=s.length;return t}function $(r){const t=[m(4,r.length)];for(const n of r)t.push(m(0,n));return V(...t)}function se(r,e,t){if(!Number.isSafeInteger(t)||t<0)throw new Error(`encodeServerIdentityPayload: expires_at must be a non-negative safe integer, got ${t}`);const n=m(4,3),s=$(r),i=$(e),o=m(0,t);return V(n,s,i,o)}const oe=new TextEncoder().encode("btc-auth.server-identity.v1"),ae=2*3600;class l extends Error{constructor(e,t){super(e),this.reason=t,this.name="ServerIdentityError"}}function E(r){const e=new Uint8Array(r.length/2);for(let t=0;t<e.length;t++)e[t]=parseInt(r.slice(t*2,t*2+2),16);return e}function j(r){const{proof:e,pinnedServerPubkey:t,now:n}=r,s=r.maxLifetimeSecs??ae,i=g.stripHexPrefix(t).toLowerCase();if(i.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(i))throw new l(`pinnedServerPubkey must be 32-byte hex; got ${i.length} chars`,"invalid_pubkey_encoding");const o=g.stripHexPrefix(e.server_pubkey).toLowerCase();if(o.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(o))throw new l(`server_pubkey must be 32-byte hex; got ${o.length} chars`,"invalid_pubkey_encoding");if(o!==i)throw new l(`server_pubkey does not match pinned value: expected ${i}, got ${o}`,"pinned_pubkey_mismatch");if(!Number.isSafeInteger(e.expires_at))throw new l(`expires_at must be a finite integer; got ${JSON.stringify(e.expires_at)}`,"invalid_expires_at");if(!Number.isSafeInteger(n))throw new l(`now must be a finite integer; got ${JSON.stringify(n)}`,"invalid_expires_at");if(e.expires_at<=n)throw new l(`server identity proof expired at ${e.expires_at}, now ${n}`,"expired");if(!Number.isSafeInteger(s)||s<=0)throw new l(`maxLifetimeSecs must be a positive safe integer; got ${JSON.stringify(s)}`,"invalid_max_lifetime");if(e.expires_at-n>s)throw new l(`server identity proof expires too far in the future: expires_at=${e.expires_at}, now=${n}, max lifetime=${s}s`,"expires_too_far");const c=g.stripHexPrefix(e.ephemeral_pubkey).toLowerCase();if(c.length!==_.COMPRESSED_PUBKEY_HEX_LEN||!_.HEX_RE.test(c))throw new l(`ephemeral_pubkey must be 33-byte compressed hex; got ${c.length} chars`,"invalid_ephemeral_pubkey");const y=c.slice(0,2);if(y!=="02"&&y!=="03")throw new l(`ephemeral_pubkey must be compressed (prefix 02/03); got ${y}`,"invalid_ephemeral_pubkey");const p=E(c);if(!D.isPoint(p))throw new l("ephemeral_pubkey is not a valid secp256k1 point","invalid_ephemeral_pubkey");const h=g.stripHexPrefix(e.signature).toLowerCase();if(h.length!==g.SCHNORR_SIG_HEX_LEN||!_.HEX_RE.test(h))throw new l(`signature must be 64-byte Schnorr hex; got ${h.length} chars`,"invalid_signature_encoding");const x=se(oe,E(c),e.expires_at);if(!re.verifyBip322Simple(x,E(o),E(h)))throw new l("BIP-322 signature verification failed — ephemeral key is not attested by pinned server pubkey","signature_verification_failed")}const ce=new Set(["vaultProvider_submitDepositorWotsKey","vaultProvider_submitDepositorPresignatures","vaultProvider_requestDepositorPresignTransactions"]),ue=new Set(["vaultProvider_requestDepositorClaimerArtifacts"]),de=6e4,P="auth_createDepositorToken",C="auth_createDepositorTokenGrpc";function J(r,e){return new ee.JsonRpcClient({baseUrl:r,timeout:de,headers:e,retryableFor:t=>t===P||t===C})}const he=0,le=1,k=2,pe=3,_e=4,ye=5,ge=6,fe=7,H=24,xe=28,be=20,we=21,Ee=22,N=256;class f extends Error{constructor(e){super(`CBOR decode: ${e}`),this.name="CborDecodeError"}}class F{constructor(e){d(this,"buf");d(this,"pos",0);this.buf=e}nextByte(){if(this.pos>=this.buf.length)throw new f("unexpected end of input");return this.buf[this.pos++]}readHead(){const e=this.nextByte(),t=e>>5,n=e&31;if(n<H)return{major:t,arg:n};if(n>=xe)throw new f(`unsupported additional info ${n} (indefinite-length or reserved)`);const s=1<<n-H;let i=0n;for(let o=0;o<s;o++)i=i<<8n|BigInt(this.nextByte());if(i>BigInt(Number.MAX_SAFE_INTEGER))throw new f(`argument ${i} exceeds safe integer range`);return{major:t,arg:Number(i)}}readBytes(e){if(this.pos+e>this.buf.length)throw new f("length overruns end of input");const t=this.buf.subarray(this.pos,this.pos+e);return this.pos+=e,t}readByteString(){const e=this.readHead();if(e.major!==k)throw new f(`expected byte string (major ${k}), got major ${e.major}`);return this.readBytes(e.arg)}readValue(e=0){if(e>N)throw new f(`nesting exceeds maximum depth ${N}`);const t=this.readHead();switch(t.major){case he:return t.arg;case le:return-1-t.arg;case k:return this.readBytes(t.arg);case pe:return new TextDecoder("utf-8",{fatal:!0}).decode(this.readBytes(t.arg));case _e:{const n=[];for(let s=0;s<t.arg;s++)n.push(this.readValue(e+1));return n}case ye:{const n=new Map;for(let s=0;s<t.arg;s++){const i=this.readValue(e+1),o=this.readValue(e+1);n.set(i,o)}return n}case ge:return{tag:t.arg,value:this.readValue(e+1)};case fe:if(t.arg===be)return!1;if(t.arg===we)return!0;if(t.arg===Ee)return null;throw new f(`unsupported simple/float value ${t.arg}`);default:throw new f(`unsupported major type ${t.major}`)}}}function Y(r){const e=new F(r),t=e.readValue();if(e.pos!==r.length)throw new f("trailing bytes after top-level item");return t}const me="vaultd-jsonrpc",Ae="vaultd-grpc",M=18,O=4,B=-47,Se=1,X=64,ke=128,ve=96,Te=64,Pe=1,Ce=2,Oe=3,Re=4,Ie=5,$e=6,He=7,L=new TextEncoder().encode("Signature1");class a extends Error{constructor(e,t){super(e),this.reason=t,this.name="CwtVerificationError"}}function Ne(r){const e=G(r.expectedIssuerXOnlyPubkey,"expectedIssuerXOnlyPubkey"),t=G(r.expectedAudienceXOnlyPubkey,"expectedAudienceXOnlyPubkey"),n=Ge(r.ephemeralPubkeyHex),s=De(r.token),i=new F(s),o=i.readHead();if(o.major!==6||o.arg!==M)throw new a(`token is not a COSE Sign1 tagged value (tag ${M})`,"invalid_token_structure");const c=i.readHead();if(c.major!==4||c.arg!==O)throw new a(`COSE Sign1 must be a ${O}-element array`,"invalid_token_structure");const y=i.pos,p=i.readByteString(),h=s.subarray(y,i.pos);i.readValue();const x=i.pos,b=i.readByteString(),A=s.subarray(x,i.pos),S=i.readByteString();if(S.length!==X)throw new a(`COSE signature must be ${X} bytes, got ${S.length}`,"invalid_token_structure");if(i.pos!==s.length)throw new a("COSE Sign1 token has trailing bytes after the signature","invalid_token_structure");const I=Me(p);if(I!==B)throw new a(`unexpected COSE algorithm ${I} (expected ES256K ${B})`,"unexpected_algorithm");const K=Be(h,A),W=ne.sha256(K);if(!D.verify(W,n,S,!0))throw new a("COSE signature does not verify against the server's ephemeral key","signature_verification_failed");const u=Xe(b),w=u.audience.toLowerCase();if(w.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(w))throw new a("token `aud` is not a 32-byte x-only pubkey hex","invalid_claims");if(u.issuedAt>u.expiresAt)throw new a(`token iat (${u.issuedAt}) is after exp (${u.expiresAt})`,"invalid_claims");if(u.issuer.toLowerCase()!==e)throw new a(`token issuer does not match pinned server pubkey: expected ${e}, got ${u.issuer.toLowerCase()}`,"issuer_mismatch");if(u.subject!==r.expectedSubject)throw new a(`token subject mismatch: expected ${r.expectedSubject}, got ${u.subject}`,"subject_mismatch");if(w!==t)throw new a(`token audience does not match depositor pubkey: expected ${t}, got ${w}`,"audience_mismatch");if(u.expiresAt<=r.now)throw new a(`token expired: exp ${u.expiresAt} <= now ${r.now}`,"token_expired");if(r.responseExpiresAt!==u.expiresAt)throw new a(`response expires_at (${r.responseExpiresAt}) does not equal token exp (${u.expiresAt})`,"expiry_mismatch");if(r.serverIdentityExpiresAt<u.expiresAt)throw new a(`server identity expires (${r.serverIdentityExpiresAt}) before token exp (${u.expiresAt})`,"server_identity_expires_before_token");return{issuer:u.issuer,subject:u.subject,audience:w,expiresAt:u.expiresAt,notBefore:u.notBefore,issuedAt:u.issuedAt}}function Me(r){if(r.length===0)throw new a("empty COSE protected header (no algorithm)","unexpected_algorithm");const e=Y(r);if(!(e instanceof Map))throw new a("COSE protected header is not a map","invalid_token_structure");const t=e.get(Se);if(typeof t!="number")throw new a("COSE protected header missing integer algorithm label","unexpected_algorithm");return t}function Be(r,e){return Ve(Uint8Array.of(ke|O),Uint8Array.of(ve|L.length),L,r,Uint8Array.of(Te),e)}function Xe(r){const e=Y(r);if(!(e instanceof Map))throw new a("CWT claims root is not a map","invalid_claims");if(Le(e,He,"cti").length===0)throw new a("token cti is empty","invalid_claims");return{issuer:v(e,Pe,"iss"),subject:v(e,Ce,"sub"),audience:v(e,Oe,"aud"),expiresAt:T(e,Re,"exp"),notBefore:T(e,Ie,"nbf"),issuedAt:T(e,$e,"iat")}}function v(r,e,t){const n=r.get(e);if(typeof n!="string")throw new a(`token claim ${t} is missing or not a text string`,"invalid_claims");return n}function Le(r,e,t){const n=r.get(e);if(!(n instanceof Uint8Array))throw new a(`token claim ${t} is missing or not a byte string`,"invalid_claims");return n}function T(r,e,t){const n=r.get(e);if(typeof n!="number"||!Number.isSafeInteger(n)||n<0)throw new a(`token claim ${t} is missing or not a non-negative integer timestamp`,"invalid_claims");return n}function G(r,e){const t=g.stripHexPrefix(r).toLowerCase();if(t.length!==_.X_ONLY_PUBKEY_HEX_LEN||!_.HEX_RE.test(t))throw new a(`${e} must be 32-byte x-only hex; got ${t.length} chars`,"invalid_input");return t}function Ge(r){const e=g.stripHexPrefix(r).toLowerCase(),t=e.slice(0,2);if(e.length!==_.COMPRESSED_PUBKEY_HEX_LEN||!_.HEX_RE.test(e)||t!=="02"&&t!=="03")throw new a("ephemeralPubkeyHex must be 33-byte compressed pubkey hex (prefix 02/03)","invalid_input");return g.hexToUint8Array(e)}const Ue=(()=>{const r=new Int16Array(128).fill(-1),e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";for(let t=0;t<e.length;t++)r[e.charCodeAt(t)]=t;return r})();function De(r){const e=r.length,t=Math.floor(e/4),n=e%4;if(n===1)throw new a("invalid base64url length","invalid_token_structure");const s=t*3+(n===0?0:n-1),i=new Uint8Array(s),o=p=>{const h=p<128?Ue[p]:-1;if(h<0)throw new a("invalid base64url character","invalid_token_structure");return h};let c=0,y=0;for(let p=0;p<t;p++){const h=o(r.charCodeAt(c++)),x=o(r.charCodeAt(c++)),b=o(r.charCodeAt(c++)),A=o(r.charCodeAt(c++));i[y++]=h<<2|x>>4,i[y++]=(x&15)<<4|b>>2,i[y++]=(b&3)<<6|A}if(n===2){const p=o(r.charCodeAt(c++)),h=o(r.charCodeAt(c++));i[y++]=p<<2|h>>4}else if(n===3){const p=o(r.charCodeAt(c++)),h=o(r.charCodeAt(c++)),x=o(r.charCodeAt(c++));i[y++]=p<<2|h>>4,i[y++]=(h&15)<<4|x>>2}return i}function Ve(...r){const e=r.reduce((s,i)=>s+i.length,0),t=new Uint8Array(e);let n=0;for(const s of r)t.set(s,n),n+=s.length;return t}const U=4102444800,je=30;class Je{constructor(e){d(this,"client");d(this,"peginTxid");d(this,"authAnchorHex");d(this,"pinnedServerPubkey");d(this,"expectedAudienceXOnlyPubkey");d(this,"authGatedMethods");d(this,"grpcGatedMethods");d(this,"refreshSkewSecs");d(this,"now");d(this,"cachedJsonRpc",null);d(this,"inFlightJsonRpc",null);d(this,"cachedGrpc",null);d(this,"inFlightGrpc",null);this.client=e.client,this.peginTxid=e.peginTxid,this.authAnchorHex=e.authAnchorHex,this.pinnedServerPubkey=e.pinnedServerPubkey,this.expectedAudienceXOnlyPubkey=e.expectedAudienceXOnlyPubkey,this.authGatedMethods=e.authGatedMethods,this.grpcGatedMethods=e.grpcGatedMethods,this.refreshSkewSecs=e.refreshSkewSecs??je,this.now=e.now??(()=>Math.floor(Date.now()/1e3))}async getToken(e){return e===P||e===C?null:this.grpcGatedMethods.has(e)?this.getTokenForSubject("grpc"):this.authGatedMethods.has(e)?this.getTokenForSubject("jsonrpc"):null}invalidate(){this.cachedJsonRpc=null,this.cachedGrpc=null}async getTokenForSubject(e){const t=e==="grpc"?this.cachedGrpc:this.cachedJsonRpc;return t&&this.now()+this.refreshSkewSecs<t.expiresAt?t.token:(await this.acquireSingleFlight(e)).token}setClient(e){this.client=e}acquireSingleFlight(e){const t=e==="grpc"?this.inFlightGrpc:this.inFlightJsonRpc;if(t)return t;const n=e==="grpc"?C:P,s=(async()=>{try{const i=await this.client.call(n,{pegin_txid:this.peginTxid,auth_anchor:this.authAnchorHex});if(j({proof:i.server_identity,pinnedServerPubkey:this.pinnedServerPubkey,now:this.now()}),typeof i.token!="string"||i.token.length===0)throw new Error(`VpTokenProvider: invalid token in acquire response (expected non-empty string, got ${typeof i.token})`);const o=this.now();if(!Number.isSafeInteger(i.expires_at)||i.expires_at<=o||i.expires_at>U)throw new Error(`VpTokenProvider: invalid expires_at in acquire response (got ${JSON.stringify(i.expires_at)}; must be a safe integer in (${o}, ${U}])`);Ne({token:i.token,ephemeralPubkeyHex:i.server_identity.ephemeral_pubkey,expectedIssuerXOnlyPubkey:this.pinnedServerPubkey,expectedSubject:e==="grpc"?Ae:me,expectedAudienceXOnlyPubkey:this.expectedAudienceXOnlyPubkey,responseExpiresAt:i.expires_at,serverIdentityExpiresAt:i.server_identity.expires_at,now:o});const c={token:i.token,expiresAt:i.expires_at};return e==="grpc"?this.cachedGrpc=c:this.cachedJsonRpc=c,c}finally{e==="grpc"?this.inFlightGrpc=null:this.inFlightJsonRpc=null}})();return e==="grpc"?this.inFlightGrpc=s:this.inFlightJsonRpc=s,s}}class q{constructor(){d(this,"entries",new Map)}getOrCreate(e){const t=this.entries.get(e.peginTxid);if(t){if(t.authAnchorHex!==e.authAnchorHex)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to authAnchorHex ${t.authAnchorHex.slice(0,8)}…; got ${e.authAnchorHex.slice(0,8)}…`);if(t.pinnedServerPubkey!==e.pinnedServerPubkey)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to pinnedServerPubkey ${t.pinnedServerPubkey.slice(0,8)}…; got ${e.pinnedServerPubkey.slice(0,8)}…`);if(t.expectedAudienceXOnlyPubkey!==e.expectedAudienceXOnlyPubkey)throw new Error(`VpTokenRegistry: peginTxid ${e.peginTxid} already bound to expectedAudienceXOnlyPubkey ${t.expectedAudienceXOnlyPubkey.slice(0,8)}…; got ${e.expectedAudienceXOnlyPubkey.slice(0,8)}…`);return t.provider.setClient(e.client),t.provider}const n=new Je({client:e.client,peginTxid:e.peginTxid,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey,expectedAudienceXOnlyPubkey:e.expectedAudienceXOnlyPubkey,authGatedMethods:ce,grpcGatedMethods:ue});return this.entries.set(e.peginTxid,{provider:n,authAnchorHex:e.authAnchorHex,pinnedServerPubkey:e.pinnedServerPubkey,expectedAudienceXOnlyPubkey:e.expectedAudienceXOnlyPubkey}),n}peek(e){var t;return(t=this.entries.get(e))==null?void 0:t.provider}release(e){this.entries.delete(e)}clear(){this.entries.clear()}get size(){return this.entries.size}}const R=new q;function Fe(r){var n;const e=J(r.baseUrl,(n=r.options)==null?void 0:n.headers),t=R.getOrCreate({client:e,peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey,expectedAudienceXOnlyPubkey:g.processPublicKeyToXOnly(r.depositorBtcPubkey)});return new Z.VaultProviderRpcClient(r.baseUrl,{...r.options,tokenProvider:t})}function Ye(r){R.getOrCreate({client:J(r.baseUrl,r.headers),peginTxid:r.peginTxid,authAnchorHex:r.authAnchorHex,pinnedServerPubkey:r.pinnedServerPubkey,expectedAudienceXOnlyPubkey:g.processPublicKeyToXOnly(r.depositorBtcPubkey)})}exports.ServerIdentityError=l;exports.VpTokenRegistry=q;exports.createAuthenticatedVpClient=Fe;exports.primeVpTokenRegistry=Ye;exports.verifyServerIdentity=j;exports.vpTokenRegistry=R;
|
|
2
|
+
//# sourceMappingURL=primeVpAuth-BOGKniTl.cjs.map
|