@babylonlabs-io/ts-sdk 0.55.1 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/{PayoutManager-BJmPnyRP.js → PayoutManager-BVgmuKuK.js} +117 -105
- package/dist/PayoutManager-BVgmuKuK.js.map +1 -0
- package/dist/PayoutManager-Cu4_l-_Y.cjs +2 -0
- package/dist/PayoutManager-Cu4_l-_Y.cjs.map +1 -0
- package/dist/PeginManager-BkWdZI7P.cjs +2 -0
- package/dist/PeginManager-BkWdZI7P.cjs.map +1 -0
- package/dist/PeginManager-aYBkb-Qx.js +1289 -0
- package/dist/PeginManager-aYBkb-Qx.js.map +1 -0
- package/dist/{buildAndBroadcastRefund-BiSO4zg2.js → buildAndBroadcastRefund-BtXUqBkb.js} +444 -430
- package/dist/buildAndBroadcastRefund-BtXUqBkb.js.map +1 -0
- package/dist/buildAndBroadcastRefund-Cq01wyZX.cjs +2 -0
- package/dist/buildAndBroadcastRefund-Cq01wyZX.cjs.map +1 -0
- package/dist/challengeAssert-BVQq50su.js +75 -0
- package/dist/challengeAssert-BVQq50su.js.map +1 -0
- package/dist/challengeAssert-Cu-PtJ1g.cjs +2 -0
- package/dist/challengeAssert-Cu-PtJ1g.cjs.map +1 -0
- package/dist/constants-BqU1Uz15.cjs +2 -0
- package/dist/{constants-CvbARMl-.cjs.map → constants-BqU1Uz15.cjs.map} +1 -1
- package/dist/{constants-BhclpREj.js → constants-CDQE812z.js} +8 -6
- package/dist/{constants-BhclpREj.js.map → constants-CDQE812z.js.map} +1 -1
- package/dist/deriveVaultRoot-B_gEOTD6.js +72 -0
- package/dist/deriveVaultRoot-B_gEOTD6.js.map +1 -0
- package/dist/deriveVaultRoot-CebLadyJ.cjs +2 -0
- package/dist/deriveVaultRoot-CebLadyJ.cjs.map +1 -0
- package/dist/errors-B-H0seUG.js +8 -0
- package/dist/errors-B-H0seUG.js.map +1 -0
- package/dist/errors-Bfjxg_iJ.cjs +2 -0
- package/dist/errors-Bfjxg_iJ.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +197 -193
- package/dist/index.js.map +1 -1
- package/dist/{mempoolApi-CB7bHuwi.js → mempoolApi-P_ApODLd.js} +2 -2
- package/dist/{mempoolApi-CB7bHuwi.js.map → mempoolApi-P_ApODLd.js.map} +1 -1
- package/dist/{mempoolApi-DqJByvqR.cjs → mempoolApi-emec8bHK.cjs} +2 -2
- package/dist/{mempoolApi-DqJByvqR.cjs.map → mempoolApi-emec8bHK.cjs.map} +1 -1
- package/dist/{noPayout-CNMqNNpc.cjs → noPayout-Cb8vFrkY.cjs} +2 -2
- package/dist/{noPayout-CNMqNNpc.cjs.map → noPayout-Cb8vFrkY.cjs.map} +1 -1
- package/dist/{noPayout-CfBg3HzC.js → noPayout-CihCk1HE.js} +2 -2
- package/dist/{noPayout-CfBg3HzC.js.map → noPayout-CihCk1HE.js.map} +1 -1
- package/dist/parseFundingOutpoints-C_-PT9BT.cjs +2 -0
- package/dist/parseFundingOutpoints-C_-PT9BT.cjs.map +1 -0
- package/dist/parseFundingOutpoints-GSM-IaaK.js +17 -0
- package/dist/parseFundingOutpoints-GSM-IaaK.js.map +1 -0
- package/dist/{primeVpAuth-l-5x_2UV.js → primeVpAuth-DZOaC_Ui.js} +3 -3
- package/dist/{primeVpAuth-l-5x_2UV.js.map → primeVpAuth-DZOaC_Ui.js.map} +1 -1
- package/dist/{primeVpAuth-CF4cH5_e.cjs → primeVpAuth-j2getl3f.cjs} +2 -2
- package/dist/{primeVpAuth-CF4cH5_e.cjs.map → primeVpAuth-j2getl3f.cjs.map} +1 -1
- package/dist/tbv/core/clients/index.cjs +1 -1
- package/dist/tbv/core/clients/index.js +2 -2
- package/dist/tbv/core/deposit-terms/__tests__/buildDepositTerms.test.d.ts +2 -0
- package/dist/tbv/core/deposit-terms/__tests__/buildDepositTerms.test.d.ts.map +1 -0
- package/dist/tbv/core/deposit-terms/buildDepositTerms.d.ts +8 -0
- package/dist/tbv/core/deposit-terms/buildDepositTerms.d.ts.map +1 -0
- package/dist/tbv/core/deposit-terms/depositTerms.d.ts +92 -0
- package/dist/tbv/core/deposit-terms/depositTerms.d.ts.map +1 -0
- package/dist/tbv/core/deposit-terms/index.d.ts +12 -0
- package/dist/tbv/core/deposit-terms/index.d.ts.map +1 -0
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.d.ts +1 -0
- package/dist/tbv/core/index.d.ts.map +1 -1
- package/dist/tbv/core/index.js +195 -191
- package/dist/tbv/core/index.js.map +1 -1
- package/dist/tbv/core/managers/PayoutManager.d.ts +7 -0
- package/dist/tbv/core/managers/PayoutManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/PeginManager.d.ts +13 -0
- package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.d.ts +0 -3
- package/dist/tbv/core/primitives/index.d.ts.map +1 -1
- package/dist/tbv/core/primitives/index.js +37 -38
- package/dist/tbv/core/primitives/psbt/__tests__/assertPayoutFeeBand.test.d.ts +7 -0
- package/dist/tbv/core/primitives/psbt/__tests__/assertPayoutFeeBand.test.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/assertPayoutFeeBand.d.ts +63 -0
- package/dist/tbv/core/primitives/psbt/assertPayoutFeeBand.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/assertWasmPeginSizing.d.ts +4 -1
- package/dist/tbv/core/primitives/psbt/assertWasmPeginSizing.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/constants.d.ts +18 -4
- package/dist/tbv/core/primitives/psbt/constants.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/payout.d.ts +21 -2
- package/dist/tbv/core/primitives/psbt/payout.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/pegin.d.ts +6 -0
- package/dist/tbv/core/primitives/psbt/pegin.d.ts.map +1 -1
- package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts +12 -0
- package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts.map +1 -1
- package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts +5 -0
- package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts.map +1 -1
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +2 -2
- package/dist/tbv/core/vault-secrets/index.cjs +2 -0
- package/dist/tbv/core/vault-secrets/index.cjs.map +1 -0
- package/dist/tbv/core/vault-secrets/index.js +14 -0
- package/dist/tbv/core/vault-secrets/index.js.map +1 -0
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +195 -191
- package/dist/tbv/index.js.map +1 -1
- package/dist/tbv/integrations/aave/clients/index.d.ts +1 -1
- package/dist/tbv/integrations/aave/clients/index.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/clients/spoke.d.ts +0 -20
- package/dist/tbv/integrations/aave/clients/spoke.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/constants.d.ts +0 -22
- package/dist/tbv/integrations/aave/constants.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/index.cjs +1 -1
- package/dist/tbv/integrations/aave/index.cjs.map +1 -1
- package/dist/tbv/integrations/aave/index.d.ts +5 -6
- package/dist/tbv/integrations/aave/index.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/index.js +236 -339
- package/dist/tbv/integrations/aave/index.js.map +1 -1
- package/dist/tbv/integrations/aave/types.d.ts +0 -7
- package/dist/tbv/integrations/aave/types.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/utils/healthFactor.d.ts +0 -7
- package/dist/tbv/integrations/aave/utils/healthFactor.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/utils/index.d.ts +3 -8
- package/dist/tbv/integrations/aave/utils/index.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/utils/vaultSplit.d.ts +0 -65
- package/dist/tbv/integrations/aave/utils/vaultSplit.d.ts.map +1 -1
- package/dist/verifyScriptPathSchnorrSignature-BZhX-SOd.cjs +2 -0
- package/dist/verifyScriptPathSchnorrSignature-BZhX-SOd.cjs.map +1 -0
- package/dist/verifyScriptPathSchnorrSignature-CgrnAjMW.js +724 -0
- package/dist/verifyScriptPathSchnorrSignature-CgrnAjMW.js.map +1 -0
- package/package.json +4 -4
- package/dist/PayoutManager-BJmPnyRP.js.map +0 -1
- package/dist/PayoutManager-aqtsj60t.cjs +0 -2
- package/dist/PayoutManager-aqtsj60t.cjs.map +0 -1
- package/dist/PeginManager-D22MLWfM.js +0 -1295
- package/dist/PeginManager-D22MLWfM.js.map +0 -1
- package/dist/PeginManager-vUUfZCzj.cjs +0 -2
- package/dist/PeginManager-vUUfZCzj.cjs.map +0 -1
- package/dist/buildAndBroadcastRefund-BiSO4zg2.js.map +0 -1
- package/dist/buildAndBroadcastRefund-Bwi1I5we.cjs +0 -2
- package/dist/buildAndBroadcastRefund-Bwi1I5we.cjs.map +0 -1
- package/dist/challengeAssert-DLQfNcfU.cjs +0 -2
- package/dist/challengeAssert-DLQfNcfU.cjs.map +0 -1
- package/dist/challengeAssert-DvdbpEDY.js +0 -128
- package/dist/challengeAssert-DvdbpEDY.js.map +0 -1
- package/dist/constants-CvbARMl-.cjs +0 -2
- package/dist/errors-9AkghWyk.js +0 -22
- package/dist/errors-9AkghWyk.js.map +0 -1
- package/dist/errors-Bu0H-dZD.cjs +0 -2
- package/dist/errors-Bu0H-dZD.cjs.map +0 -1
- package/dist/tbv/core/primitives/psbt/depositorPayout.d.ts +0 -34
- package/dist/tbv/core/primitives/psbt/depositorPayout.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/__tests__/borrowRatio.test.d.ts +0 -5
- package/dist/tbv/integrations/aave/utils/__tests__/borrowRatio.test.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/__tests__/seizureSimulation.test.d.ts +0 -5
- package/dist/tbv/integrations/aave/utils/__tests__/seizureSimulation.test.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/__tests__/vaultSelection.test.d.ts +0 -2
- package/dist/tbv/integrations/aave/utils/__tests__/vaultSelection.test.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/borrowRatio.d.ts +0 -15
- package/dist/tbv/integrations/aave/utils/borrowRatio.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/seizureSimulation.d.ts +0 -109
- package/dist/tbv/integrations/aave/utils/seizureSimulation.d.ts.map +0 -1
- package/dist/tbv/integrations/aave/utils/vaultSelection.d.ts +0 -33
- package/dist/tbv/integrations/aave/utils/vaultSelection.d.ts.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-BDznSCOR.cjs +0 -2
- package/dist/verifyScriptPathSchnorrSignature-BDznSCOR.cjs.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-DA4Z4yZ3.js +0 -658
- package/dist/verifyScriptPathSchnorrSignature-DA4Z4yZ3.js.map +0 -1
|
@@ -0,0 +1,1289 @@
|
|
|
1
|
+
var Ft = Object.defineProperty;
|
|
2
|
+
var Nt = (s, e, t) => e in s ? Ft(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t;
|
|
3
|
+
var y = (s, e, t) => Nt(s, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { c as Tt, H as Wt, r as M, a as L, b as st, u as Lt, d as ot, e as nt, f as rt, g as Dt, s as Bt } from "./sha2-BYVxyZzX.js";
|
|
5
|
+
import * as Et from "bitcoinjs-lib";
|
|
6
|
+
import { Transaction as Xt, Psbt as it } from "bitcoinjs-lib";
|
|
7
|
+
import { Buffer as Y } from "buffer";
|
|
8
|
+
import { isAddressEqual as at, encodeFunctionData as j, zeroAddress as Kt } from "viem";
|
|
9
|
+
import { B as H } from "./BTCVaultRegistry.abi-Chs4AFBj.js";
|
|
10
|
+
import { h as R } from "./errors-Blc-JWnI.js";
|
|
11
|
+
import { expandWotsSeed as Gt, expandHashlockSecret as qt, expandAuthAnchor as zt, deriveVaultId as ct } from "@babylonlabs-io/babylon-tbv-rust-wasm";
|
|
12
|
+
import { a as lt, b as Yt, d as ut, f as jt } from "./verifyScriptPathSchnorrSignature-CgrnAjMW.js";
|
|
13
|
+
import { b as Qt, e as Zt, f as Jt } from "./peginInput-BKD_b3gq.js";
|
|
14
|
+
import { u as Q, e as A, p as te, i as ht, h as dt, s as v, j as gt, X as ee } from "./bitcoin-B5aNKtsk.js";
|
|
15
|
+
import { c as se } from "./signing-DaLvGwQe.js";
|
|
16
|
+
import { M as ft } from "./validation-CxqROCno.js";
|
|
17
|
+
import { d as oe } from "./deriveVaultRoot-B_gEOTD6.js";
|
|
18
|
+
import { c as ne, a as re, s as ie, b as ae } from "./PayoutManager-BVgmuKuK.js";
|
|
19
|
+
import { s as ce, f as X, i as le, w as pt } from "./waitForTransactionReceiptSmartAware-lobLm0q0.js";
|
|
20
|
+
import { p as ue, f as he } from "./fundPeginTransaction-B2wyjqp0.js";
|
|
21
|
+
import { M as mt, B as de } from "./constants-CDQE812z.js";
|
|
22
|
+
import { p as ge, V as fe, i as pe } from "./mempoolApi-P_ApODLd.js";
|
|
23
|
+
const U = /* @__PURE__ */ BigInt(2 ** 32 - 1), Pt = /* @__PURE__ */ BigInt(32);
|
|
24
|
+
function me(s, e = !1) {
|
|
25
|
+
return e ? { h: Number(s & U), l: Number(s >> Pt & U) } : { h: Number(s >> Pt & U) | 0, l: Number(s & U) | 0 };
|
|
26
|
+
}
|
|
27
|
+
function Pe(s, e = !1) {
|
|
28
|
+
const t = s.length;
|
|
29
|
+
let o = new Uint32Array(t), n = new Uint32Array(t);
|
|
30
|
+
for (let r = 0; r < t; r++) {
|
|
31
|
+
const { h: i, l: a } = me(s[r], e);
|
|
32
|
+
[o[r], n[r]] = [i, a];
|
|
33
|
+
}
|
|
34
|
+
return [o, n];
|
|
35
|
+
}
|
|
36
|
+
const be = (s, e, t) => s << t | e >>> 32 - t, we = (s, e, t) => e << t | s >>> 32 - t, xe = (s, e, t) => e << t - 32 | s >>> 64 - t, ye = (s, e, t) => s << t - 32 | e >>> 64 - t, ke = 64;
|
|
37
|
+
function Te(s) {
|
|
38
|
+
const e = s.prepeginTxid.toLowerCase();
|
|
39
|
+
if (!/^[0-9a-f]+$/.test(e) || e.length !== ke)
|
|
40
|
+
throw new Error(`buildDepositTerms: prepeginTxid must be 64 hex chars, got "${s.prepeginTxid}"`);
|
|
41
|
+
if (s.vaultAmounts.length === 0)
|
|
42
|
+
throw new Error("buildDepositTerms: at least one vault amount is required");
|
|
43
|
+
if (s.timelockPegin <= 0 || s.timelockRefund <= 0)
|
|
44
|
+
throw new Error("buildDepositTerms: timelocks must be positive");
|
|
45
|
+
if (!Number.isInteger(s.commissionBps) || s.commissionBps < 0 || s.commissionBps >= mt)
|
|
46
|
+
throw new Error(
|
|
47
|
+
`buildDepositTerms: commissionBps must be an integer in [0, ${mt}), got ${s.commissionBps}`
|
|
48
|
+
);
|
|
49
|
+
const t = BigInt(de), o = s.vaultAmounts.map((n, r) => ({
|
|
50
|
+
htlcVout: r,
|
|
51
|
+
vaultProviderPk: s.vaultProviderPk,
|
|
52
|
+
vaultAmount: n,
|
|
53
|
+
// floor(vaultAmount * bps / 10_000) — matches the vault provider's commission math.
|
|
54
|
+
commissionFee: n * BigInt(s.commissionBps) / t,
|
|
55
|
+
depositorClaimValue: s.depositorClaimValue,
|
|
56
|
+
peginMaxFee: s.peginMaxFee
|
|
57
|
+
}));
|
|
58
|
+
return {
|
|
59
|
+
baseFeeRate: s.protocolFeeRate,
|
|
60
|
+
peginCsvTimelock: s.timelockPegin,
|
|
61
|
+
payoutTimelock: s.timelockPegin,
|
|
62
|
+
htlcRefundTimelock: s.timelockRefund,
|
|
63
|
+
prepeginTxid: e,
|
|
64
|
+
prepeginMaxFee: s.prepeginMaxFee,
|
|
65
|
+
keeperPks: [...s.keeperPks],
|
|
66
|
+
challengerPks: [...s.challengerPks],
|
|
67
|
+
vaults: o
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
const Be = /* @__PURE__ */ Uint8Array.from([
|
|
71
|
+
7,
|
|
72
|
+
4,
|
|
73
|
+
13,
|
|
74
|
+
1,
|
|
75
|
+
10,
|
|
76
|
+
6,
|
|
77
|
+
15,
|
|
78
|
+
3,
|
|
79
|
+
12,
|
|
80
|
+
0,
|
|
81
|
+
9,
|
|
82
|
+
5,
|
|
83
|
+
2,
|
|
84
|
+
14,
|
|
85
|
+
11,
|
|
86
|
+
8
|
|
87
|
+
]), vt = Uint8Array.from(new Array(16).fill(0).map((s, e) => e)), Ee = vt.map((s) => (9 * s + 5) % 16), _t = /* @__PURE__ */ (() => {
|
|
88
|
+
const t = [[vt], [Ee]];
|
|
89
|
+
for (let o = 0; o < 4; o++)
|
|
90
|
+
for (let n of t)
|
|
91
|
+
n.push(n[o].map((r) => Be[r]));
|
|
92
|
+
return t;
|
|
93
|
+
})(), St = _t[0], At = _t[1], It = /* @__PURE__ */ [
|
|
94
|
+
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
|
|
95
|
+
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
|
|
96
|
+
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
|
|
97
|
+
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
|
|
98
|
+
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
|
|
99
|
+
].map((s) => Uint8Array.from(s)), ve = /* @__PURE__ */ St.map((s, e) => s.map((t) => It[e][t])), _e = /* @__PURE__ */ At.map((s, e) => s.map((t) => It[e][t])), Se = /* @__PURE__ */ Uint32Array.from([
|
|
100
|
+
0,
|
|
101
|
+
1518500249,
|
|
102
|
+
1859775393,
|
|
103
|
+
2400959708,
|
|
104
|
+
2840853838
|
|
105
|
+
]), Ae = /* @__PURE__ */ Uint32Array.from([
|
|
106
|
+
1352829926,
|
|
107
|
+
1548603684,
|
|
108
|
+
1836072691,
|
|
109
|
+
2053994217,
|
|
110
|
+
0
|
|
111
|
+
]);
|
|
112
|
+
function bt(s, e, t, o) {
|
|
113
|
+
return s === 0 ? e ^ t ^ o : s === 1 ? e & t | ~e & o : s === 2 ? (e | ~t) ^ o : s === 3 ? e & o | t & ~o : e ^ (t | ~o);
|
|
114
|
+
}
|
|
115
|
+
const F = /* @__PURE__ */ new Uint32Array(16);
|
|
116
|
+
class Ie extends Wt {
|
|
117
|
+
constructor() {
|
|
118
|
+
super(64, 20, 8, !0);
|
|
119
|
+
y(this, "h0", 1732584193);
|
|
120
|
+
y(this, "h1", -271733879);
|
|
121
|
+
y(this, "h2", -1732584194);
|
|
122
|
+
y(this, "h3", 271733878);
|
|
123
|
+
y(this, "h4", -1009589776);
|
|
124
|
+
}
|
|
125
|
+
get() {
|
|
126
|
+
const { h0: t, h1: o, h2: n, h3: r, h4: i } = this;
|
|
127
|
+
return [t, o, n, r, i];
|
|
128
|
+
}
|
|
129
|
+
set(t, o, n, r, i) {
|
|
130
|
+
this.h0 = t | 0, this.h1 = o | 0, this.h2 = n | 0, this.h3 = r | 0, this.h4 = i | 0;
|
|
131
|
+
}
|
|
132
|
+
process(t, o) {
|
|
133
|
+
for (let d = 0; d < 16; d++, o += 4)
|
|
134
|
+
F[d] = t.getUint32(o, !0);
|
|
135
|
+
let n = this.h0 | 0, r = n, i = this.h1 | 0, a = i, c = this.h2 | 0, u = c, l = this.h3 | 0, m = l, b = this.h4 | 0, w = b;
|
|
136
|
+
for (let d = 0; d < 5; d++) {
|
|
137
|
+
const E = 4 - d, k = Se[d], f = Ae[d], _ = St[d], p = At[d], P = ve[d], T = _e[d];
|
|
138
|
+
for (let h = 0; h < 16; h++) {
|
|
139
|
+
const x = M(n + bt(d, i, c, l) + F[_[h]] + k, P[h]) + b | 0;
|
|
140
|
+
n = b, b = l, l = M(c, 10) | 0, c = i, i = x;
|
|
141
|
+
}
|
|
142
|
+
for (let h = 0; h < 16; h++) {
|
|
143
|
+
const x = M(r + bt(E, a, u, m) + F[p[h]] + f, T[h]) + w | 0;
|
|
144
|
+
r = w, w = m, m = M(u, 10) | 0, u = a, a = x;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
this.set(this.h1 + c + m | 0, this.h2 + l + w | 0, this.h3 + b + r | 0, this.h4 + n + a | 0, this.h0 + i + u | 0);
|
|
148
|
+
}
|
|
149
|
+
roundClean() {
|
|
150
|
+
L(F);
|
|
151
|
+
}
|
|
152
|
+
destroy() {
|
|
153
|
+
this.destroyed = !0, L(this.buffer), this.set(0, 0, 0, 0, 0);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const Ce = /* @__PURE__ */ Tt(() => new Ie()), He = BigInt(0), $ = BigInt(1), Re = BigInt(2), Oe = BigInt(7), $e = BigInt(256), Ve = BigInt(113), Ct = [], Ht = [], Rt = [];
|
|
157
|
+
for (let s = 0, e = $, t = 1, o = 0; s < 24; s++) {
|
|
158
|
+
[t, o] = [o, (2 * t + 3 * o) % 5], Ct.push(2 * (5 * o + t)), Ht.push((s + 1) * (s + 2) / 2 % 64);
|
|
159
|
+
let n = He;
|
|
160
|
+
for (let r = 0; r < 7; r++)
|
|
161
|
+
e = (e << $ ^ (e >> Oe) * Ve) % $e, e & Re && (n ^= $ << ($ << BigInt(r)) - $);
|
|
162
|
+
Rt.push(n);
|
|
163
|
+
}
|
|
164
|
+
const Ot = Pe(Rt, !0), Me = Ot[0], Ue = Ot[1], wt = (s, e, t) => t > 32 ? xe(s, e, t) : be(s, e, t), xt = (s, e, t) => t > 32 ? ye(s, e, t) : we(s, e, t);
|
|
165
|
+
function Fe(s, e = 24) {
|
|
166
|
+
const t = new Uint32Array(10);
|
|
167
|
+
for (let o = 24 - e; o < 24; o++) {
|
|
168
|
+
for (let i = 0; i < 10; i++)
|
|
169
|
+
t[i] = s[i] ^ s[i + 10] ^ s[i + 20] ^ s[i + 30] ^ s[i + 40];
|
|
170
|
+
for (let i = 0; i < 10; i += 2) {
|
|
171
|
+
const a = (i + 8) % 10, c = (i + 2) % 10, u = t[c], l = t[c + 1], m = wt(u, l, 1) ^ t[a], b = xt(u, l, 1) ^ t[a + 1];
|
|
172
|
+
for (let w = 0; w < 50; w += 10)
|
|
173
|
+
s[i + w] ^= m, s[i + w + 1] ^= b;
|
|
174
|
+
}
|
|
175
|
+
let n = s[2], r = s[3];
|
|
176
|
+
for (let i = 0; i < 24; i++) {
|
|
177
|
+
const a = Ht[i], c = wt(n, r, a), u = xt(n, r, a), l = Ct[i];
|
|
178
|
+
n = s[l], r = s[l + 1], s[l] = c, s[l + 1] = u;
|
|
179
|
+
}
|
|
180
|
+
for (let i = 0; i < 50; i += 10) {
|
|
181
|
+
for (let a = 0; a < 10; a++)
|
|
182
|
+
t[a] = s[i + a];
|
|
183
|
+
for (let a = 0; a < 10; a++)
|
|
184
|
+
s[i + a] ^= ~t[(a + 2) % 10] & t[(a + 4) % 10];
|
|
185
|
+
}
|
|
186
|
+
s[0] ^= Me[o], s[1] ^= Ue[o];
|
|
187
|
+
}
|
|
188
|
+
L(t);
|
|
189
|
+
}
|
|
190
|
+
class tt {
|
|
191
|
+
// NOTE: we accept arguments in bytes instead of bits here.
|
|
192
|
+
constructor(e, t, o, n = !1, r = 24) {
|
|
193
|
+
y(this, "state");
|
|
194
|
+
y(this, "pos", 0);
|
|
195
|
+
y(this, "posOut", 0);
|
|
196
|
+
y(this, "finished", !1);
|
|
197
|
+
y(this, "state32");
|
|
198
|
+
y(this, "destroyed", !1);
|
|
199
|
+
y(this, "blockLen");
|
|
200
|
+
y(this, "suffix");
|
|
201
|
+
y(this, "outputLen");
|
|
202
|
+
y(this, "enableXOF", !1);
|
|
203
|
+
y(this, "rounds");
|
|
204
|
+
if (this.blockLen = e, this.suffix = t, this.outputLen = o, this.enableXOF = n, this.rounds = r, st(o, "outputLen"), !(0 < e && e < 200))
|
|
205
|
+
throw new Error("only keccak-f1600 function is supported");
|
|
206
|
+
this.state = new Uint8Array(200), this.state32 = Lt(this.state);
|
|
207
|
+
}
|
|
208
|
+
clone() {
|
|
209
|
+
return this._cloneInto();
|
|
210
|
+
}
|
|
211
|
+
keccak() {
|
|
212
|
+
ot(this.state32), Fe(this.state32, this.rounds), ot(this.state32), this.posOut = 0, this.pos = 0;
|
|
213
|
+
}
|
|
214
|
+
update(e) {
|
|
215
|
+
nt(this), rt(e);
|
|
216
|
+
const { blockLen: t, state: o } = this, n = e.length;
|
|
217
|
+
for (let r = 0; r < n; ) {
|
|
218
|
+
const i = Math.min(t - this.pos, n - r);
|
|
219
|
+
for (let a = 0; a < i; a++)
|
|
220
|
+
o[this.pos++] ^= e[r++];
|
|
221
|
+
this.pos === t && this.keccak();
|
|
222
|
+
}
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
finish() {
|
|
226
|
+
if (this.finished)
|
|
227
|
+
return;
|
|
228
|
+
this.finished = !0;
|
|
229
|
+
const { state: e, suffix: t, pos: o, blockLen: n } = this;
|
|
230
|
+
e[o] ^= t, (t & 128) !== 0 && o === n - 1 && this.keccak(), e[n - 1] ^= 128, this.keccak();
|
|
231
|
+
}
|
|
232
|
+
writeInto(e) {
|
|
233
|
+
nt(this, !1), rt(e), this.finish();
|
|
234
|
+
const t = this.state, { blockLen: o } = this;
|
|
235
|
+
for (let n = 0, r = e.length; n < r; ) {
|
|
236
|
+
this.posOut >= o && this.keccak();
|
|
237
|
+
const i = Math.min(o - this.posOut, r - n);
|
|
238
|
+
e.set(t.subarray(this.posOut, this.posOut + i), n), this.posOut += i, n += i;
|
|
239
|
+
}
|
|
240
|
+
return e;
|
|
241
|
+
}
|
|
242
|
+
xofInto(e) {
|
|
243
|
+
if (!this.enableXOF)
|
|
244
|
+
throw new Error("XOF is not possible for this instance");
|
|
245
|
+
return this.writeInto(e);
|
|
246
|
+
}
|
|
247
|
+
xof(e) {
|
|
248
|
+
return st(e), this.xofInto(new Uint8Array(e));
|
|
249
|
+
}
|
|
250
|
+
digestInto(e) {
|
|
251
|
+
if (Dt(e, this), this.finished)
|
|
252
|
+
throw new Error("digest() was already called");
|
|
253
|
+
return this.writeInto(e), this.destroy(), e;
|
|
254
|
+
}
|
|
255
|
+
digest() {
|
|
256
|
+
return this.digestInto(new Uint8Array(this.outputLen));
|
|
257
|
+
}
|
|
258
|
+
destroy() {
|
|
259
|
+
this.destroyed = !0, L(this.state);
|
|
260
|
+
}
|
|
261
|
+
_cloneInto(e) {
|
|
262
|
+
const { blockLen: t, suffix: o, outputLen: n, rounds: r, enableXOF: i } = this;
|
|
263
|
+
return e || (e = new tt(t, o, n, i, r)), e.state32.set(this.state32), e.pos = this.pos, e.posOut = this.posOut, e.finished = this.finished, e.rounds = r, e.suffix = o, e.outputLen = n, e.enableXOF = i, e.destroyed = this.destroyed, e;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
const Ne = (s, e, t, o = {}) => Tt(() => new tt(e, s, t), o), We = /* @__PURE__ */ Ne(1, 136, 32), yt = 64, S = 20, Z = 4, $t = 2, Le = 0, De = 1, N = [64, 64], Xe = (s) => Array.from(s).map((e) => e.toString(16).padStart(2, "0")).join("");
|
|
267
|
+
function et(s) {
|
|
268
|
+
return Ce(Bt(s));
|
|
269
|
+
}
|
|
270
|
+
function Vt(s) {
|
|
271
|
+
return (1 << s) - 1;
|
|
272
|
+
}
|
|
273
|
+
function Ke(s) {
|
|
274
|
+
let e = 1;
|
|
275
|
+
for (; e * e < s + 1; ) e++;
|
|
276
|
+
return Math.max(e, 2);
|
|
277
|
+
}
|
|
278
|
+
function Ge(s) {
|
|
279
|
+
const e = Z, t = s * Vt(e);
|
|
280
|
+
return { d: e, n: s, checksum_radix: Ke(t) };
|
|
281
|
+
}
|
|
282
|
+
function K(s, e) {
|
|
283
|
+
const t = [];
|
|
284
|
+
let o = e;
|
|
285
|
+
for (; o > 0; )
|
|
286
|
+
t.push(o & 255), o >>>= 8;
|
|
287
|
+
const n = new Uint8Array(s.length + t.length);
|
|
288
|
+
n.set(s);
|
|
289
|
+
for (let r = 0; r < t.length; r++)
|
|
290
|
+
n[s.length + r] = t[r];
|
|
291
|
+
return et(n);
|
|
292
|
+
}
|
|
293
|
+
function G(s, e) {
|
|
294
|
+
let t = s;
|
|
295
|
+
for (let o = 0; o < e; o++)
|
|
296
|
+
t = et(t);
|
|
297
|
+
return t;
|
|
298
|
+
}
|
|
299
|
+
function qe(s, e) {
|
|
300
|
+
const t = Vt(e.d), o = e.checksum_radix - 1, n = Math.floor(e.n * t / e.checksum_radix), r = [];
|
|
301
|
+
for (let l = 0; l < e.n; l++) {
|
|
302
|
+
const m = K(s, l + $t), b = G(m, t);
|
|
303
|
+
r.push(Array.from(b));
|
|
304
|
+
}
|
|
305
|
+
const i = K(
|
|
306
|
+
s,
|
|
307
|
+
Le
|
|
308
|
+
), a = G(
|
|
309
|
+
i,
|
|
310
|
+
o
|
|
311
|
+
), c = K(
|
|
312
|
+
s,
|
|
313
|
+
De
|
|
314
|
+
), u = G(
|
|
315
|
+
c,
|
|
316
|
+
n
|
|
317
|
+
);
|
|
318
|
+
return {
|
|
319
|
+
config: e,
|
|
320
|
+
message_terminals: r,
|
|
321
|
+
checksum_major_terminal: Array.from(u),
|
|
322
|
+
checksum_minor_terminal: Array.from(a)
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
async function ze(s) {
|
|
326
|
+
try {
|
|
327
|
+
if (s.length !== yt)
|
|
328
|
+
throw new Error(
|
|
329
|
+
`WOTS seed must be exactly ${yt} bytes, got ${s.length}`
|
|
330
|
+
);
|
|
331
|
+
const e = [];
|
|
332
|
+
for (let t = 0; t < N.length; t++) {
|
|
333
|
+
const o = N[t], n = Ge(o), r = new Uint8Array(s.length + 1);
|
|
334
|
+
r.set(s), r[s.length] = t;
|
|
335
|
+
const i = et(r);
|
|
336
|
+
try {
|
|
337
|
+
const a = qe(i, n);
|
|
338
|
+
if (a.config.d !== Z)
|
|
339
|
+
throw new Error(
|
|
340
|
+
`Block ${t}: expected d=${Z}, got d=${a.config.d}`
|
|
341
|
+
);
|
|
342
|
+
if (a.config.n !== o)
|
|
343
|
+
throw new Error(
|
|
344
|
+
`Block ${t}: expected n=${o}, got n=${a.config.n}`
|
|
345
|
+
);
|
|
346
|
+
if (a.message_terminals.length !== o)
|
|
347
|
+
throw new Error(
|
|
348
|
+
`Block ${t}: expected ${o} message terminals, got ${a.message_terminals.length}`
|
|
349
|
+
);
|
|
350
|
+
for (let c = 0; c < a.message_terminals.length; c++)
|
|
351
|
+
if (a.message_terminals[c].length !== S)
|
|
352
|
+
throw new Error(
|
|
353
|
+
`Block ${t} terminal ${c}: expected ${S} bytes, got ${a.message_terminals[c].length}`
|
|
354
|
+
);
|
|
355
|
+
if (a.checksum_minor_terminal.length !== S)
|
|
356
|
+
throw new Error(
|
|
357
|
+
`Block ${t} checksum_minor: expected ${S} bytes`
|
|
358
|
+
);
|
|
359
|
+
if (a.checksum_major_terminal.length !== S)
|
|
360
|
+
throw new Error(
|
|
361
|
+
`Block ${t} checksum_major: expected ${S} bytes`
|
|
362
|
+
);
|
|
363
|
+
e.push(a);
|
|
364
|
+
} finally {
|
|
365
|
+
r.fill(0), i.fill(0);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
if (e.length !== N.length)
|
|
369
|
+
throw new Error(
|
|
370
|
+
`Expected ${N.length} blocks, got ${e.length}`
|
|
371
|
+
);
|
|
372
|
+
return e;
|
|
373
|
+
} finally {
|
|
374
|
+
s.fill(0);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function q(s, e, t) {
|
|
378
|
+
if (s.length !== S)
|
|
379
|
+
throw new Error(
|
|
380
|
+
`Block ${e} ${t}: expected ${S} bytes, got ${s.length}`
|
|
381
|
+
);
|
|
382
|
+
for (let o = 0; o < s.length; o++) {
|
|
383
|
+
const n = s[o];
|
|
384
|
+
if (!Number.isInteger(n) || n < 0 || n > 255)
|
|
385
|
+
throw new Error(
|
|
386
|
+
`Block ${e} ${t}[${o}]: invalid byte value ${n}`
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
function Ye(s) {
|
|
391
|
+
if (s.length === 0)
|
|
392
|
+
throw new Error("Public keys array must not be empty");
|
|
393
|
+
for (let r = 0; r < s.length; r++) {
|
|
394
|
+
const i = s[r];
|
|
395
|
+
q(i.checksum_minor_terminal, r, "checksum_minor_terminal"), q(i.checksum_major_terminal, r, "checksum_major_terminal");
|
|
396
|
+
for (let a = 0; a < i.message_terminals.length; a++)
|
|
397
|
+
q(i.message_terminals[a], r, `message_terminal[${a}]`);
|
|
398
|
+
}
|
|
399
|
+
let e = 0;
|
|
400
|
+
for (const r of s)
|
|
401
|
+
e += $t + r.message_terminals.length;
|
|
402
|
+
const t = new Uint8Array(e * S);
|
|
403
|
+
let o = 0;
|
|
404
|
+
for (const r of s) {
|
|
405
|
+
t.set(r.checksum_minor_terminal, o), o += S, t.set(r.checksum_major_terminal, o), o += S;
|
|
406
|
+
for (const i of r.message_terminals)
|
|
407
|
+
t.set(i, o), o += S;
|
|
408
|
+
}
|
|
409
|
+
const n = We(t);
|
|
410
|
+
return `0x${Xe(n)}`;
|
|
411
|
+
}
|
|
412
|
+
async function je(s, e) {
|
|
413
|
+
const t = [], o = [], n = [], r = [];
|
|
414
|
+
try {
|
|
415
|
+
for (let i = 0; i < e; i++) {
|
|
416
|
+
const a = await Gt(s, i);
|
|
417
|
+
try {
|
|
418
|
+
const u = await ze(a);
|
|
419
|
+
t.push(u), o.push(Ye(u));
|
|
420
|
+
} finally {
|
|
421
|
+
a.fill(0);
|
|
422
|
+
}
|
|
423
|
+
const c = await qt(s, i);
|
|
424
|
+
try {
|
|
425
|
+
const u = Q(c);
|
|
426
|
+
n.push(u), r.push(ne(A(u)).slice(2));
|
|
427
|
+
} finally {
|
|
428
|
+
c.fill(0);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
} finally {
|
|
432
|
+
s.fill(0);
|
|
433
|
+
}
|
|
434
|
+
return { perVaultWotsKeys: t, wotsPkHashes: o, htlcSecretHexes: n, hashlocks: r };
|
|
435
|
+
}
|
|
436
|
+
const Qe = /^0x[0-9a-f]+$/i, Ze = /^[0-9a-f]+$/i, Je = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
437
|
+
function V(s) {
|
|
438
|
+
if (typeof s != "string" || s.length === 0)
|
|
439
|
+
throw new Error("BTC wallet returned empty public key");
|
|
440
|
+
return te(s).toLowerCase();
|
|
441
|
+
}
|
|
442
|
+
function ts(s) {
|
|
443
|
+
if (typeof s != "string" || s.length === 0)
|
|
444
|
+
throw new Error("BTC wallet returned empty BIP-322 signature");
|
|
445
|
+
if (s.startsWith("0x") || s.startsWith("0X")) {
|
|
446
|
+
if (!Qe.test(s) || s.length < 4 || s.length % 2 !== 0)
|
|
447
|
+
throw new Error("BTC wallet returned malformed hex BIP-322 signature");
|
|
448
|
+
return s.toLowerCase();
|
|
449
|
+
}
|
|
450
|
+
if (Ze.test(s)) {
|
|
451
|
+
if (s.length % 2 !== 0)
|
|
452
|
+
throw new Error("BTC wallet returned malformed hex BIP-322 signature");
|
|
453
|
+
return `0x${s.toLowerCase()}`;
|
|
454
|
+
}
|
|
455
|
+
if (!Je.test(s) || s.length % 4 !== 0)
|
|
456
|
+
throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
|
|
457
|
+
const e = Y.from(s, "base64");
|
|
458
|
+
if (e.length === 0 || e.toString("base64") !== s)
|
|
459
|
+
throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
|
|
460
|
+
return `0x${e.toString("hex")}`;
|
|
461
|
+
}
|
|
462
|
+
const Mt = 0, W = 25, J = 9999, z = "00".repeat(32);
|
|
463
|
+
function es(s, e) {
|
|
464
|
+
const t = {
|
|
465
|
+
bitcoin: "bc",
|
|
466
|
+
testnet: "tb",
|
|
467
|
+
signet: "tb",
|
|
468
|
+
regtest: "bcrt"
|
|
469
|
+
};
|
|
470
|
+
try {
|
|
471
|
+
const o = Et.address.fromBech32(s);
|
|
472
|
+
return o.prefix === t[e] && o.version === 0 && o.data.length === 20;
|
|
473
|
+
} catch {
|
|
474
|
+
return !1;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
function ss(s, e, t, o) {
|
|
478
|
+
const n = t == null ? void 0 : t[`${s}:${e}`];
|
|
479
|
+
return n ? Promise.resolve({
|
|
480
|
+
txid: s,
|
|
481
|
+
vout: e,
|
|
482
|
+
value: n.value,
|
|
483
|
+
scriptPubKey: n.scriptPubKey
|
|
484
|
+
}) : pe(s, e, o);
|
|
485
|
+
}
|
|
486
|
+
const kt = 12e4;
|
|
487
|
+
class Ss {
|
|
488
|
+
/**
|
|
489
|
+
* Creates a new PeginManager instance.
|
|
490
|
+
*
|
|
491
|
+
* @param config - Manager configuration including wallets and contract addresses
|
|
492
|
+
*/
|
|
493
|
+
constructor(e) {
|
|
494
|
+
y(this, "config");
|
|
495
|
+
this.config = e;
|
|
496
|
+
}
|
|
497
|
+
/**
|
|
498
|
+
* Prepare a peg-in: sizing pass → vault-root derivation (one wallet
|
|
499
|
+
* popup) → per-vault WOTS / hashlock derivation → commit pass with
|
|
500
|
+
* PSBT signing (signPsbt for a single vault, one batch popup for a
|
|
501
|
+
* split). Returns broadcast-ready txs, the pubkey snapshot, and the
|
|
502
|
+
* sensitive derived material.
|
|
503
|
+
*
|
|
504
|
+
* @throws If the wallet rejects, insufficient funds, or an internal
|
|
505
|
+
* invariant violation.
|
|
506
|
+
*/
|
|
507
|
+
async preparePegin(e) {
|
|
508
|
+
if (e.amounts.length === 0)
|
|
509
|
+
throw new Error("amounts must contain at least one entry");
|
|
510
|
+
const t = await this.config.btcWallet.getPublicKeyHex(), o = V(t);
|
|
511
|
+
if (!ht(
|
|
512
|
+
e.changeAddress,
|
|
513
|
+
t,
|
|
514
|
+
this.config.btcNetwork
|
|
515
|
+
))
|
|
516
|
+
throw new Error(
|
|
517
|
+
`Pre-PegIn changeAddress "${e.changeAddress}" is not derived from the connected wallet's public key. Refusing to build a tx that would send change to an address the signing key doesn't control.`
|
|
518
|
+
);
|
|
519
|
+
const n = await this.prepareSizing(o, e), r = n.selectedUTXOs.map(
|
|
520
|
+
(f) => ({
|
|
521
|
+
txid: dt(f.txid),
|
|
522
|
+
vout: f.vout
|
|
523
|
+
})
|
|
524
|
+
), i = await oe(this.config.btcWallet, {
|
|
525
|
+
depositorBtcPubkey: dt(o),
|
|
526
|
+
fundingOutpoints: r
|
|
527
|
+
});
|
|
528
|
+
let a, c;
|
|
529
|
+
try {
|
|
530
|
+
const f = await zt(i);
|
|
531
|
+
try {
|
|
532
|
+
a = Q(f), c = Q(Bt(f));
|
|
533
|
+
} finally {
|
|
534
|
+
f.fill(0);
|
|
535
|
+
}
|
|
536
|
+
} catch (f) {
|
|
537
|
+
throw i.fill(0), f;
|
|
538
|
+
}
|
|
539
|
+
const u = await je(i, e.amounts.length), { perVaultWotsKeys: l, wotsPkHashes: m, htlcSecretHexes: b, hashlocks: w } = u, d = await this.preparePeginCommit({
|
|
540
|
+
depositorBtcPubkeyRaw: t,
|
|
541
|
+
depositorBtcPubkey: o,
|
|
542
|
+
hashlocks: w,
|
|
543
|
+
authAnchorHash: c,
|
|
544
|
+
sizing: n,
|
|
545
|
+
params: e
|
|
546
|
+
});
|
|
547
|
+
for (let f = 0; f < d.perVault.length; f++)
|
|
548
|
+
if (d.perVault[f].htlcVout !== f)
|
|
549
|
+
throw new Error(
|
|
550
|
+
`Internal invariant violation: htlcVout/index mismatch at vault ${f} (expected ${f}, got ${d.perVault[f].htlcVout})`
|
|
551
|
+
);
|
|
552
|
+
re(
|
|
553
|
+
d.fundedPrePeginTxHex,
|
|
554
|
+
e.amounts.length,
|
|
555
|
+
c
|
|
556
|
+
);
|
|
557
|
+
const { depositTerms: E, ...k } = d;
|
|
558
|
+
return {
|
|
559
|
+
transaction: {
|
|
560
|
+
...k,
|
|
561
|
+
selectedUTXOs: n.selectedUTXOs,
|
|
562
|
+
fee: n.fee,
|
|
563
|
+
changeAmount: n.changeAmount
|
|
564
|
+
},
|
|
565
|
+
depositorBtcPubkey: o,
|
|
566
|
+
derivedSecrets: {
|
|
567
|
+
perVaultWotsKeys: l,
|
|
568
|
+
wotsPkHashes: m,
|
|
569
|
+
htlcSecretHexes: b,
|
|
570
|
+
authAnchorHex: a
|
|
571
|
+
},
|
|
572
|
+
depositTerms: E
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Build unfunded Pre-PegIn + select UTXOs. No PSBT signing.
|
|
577
|
+
*
|
|
578
|
+
* Returns the full selection result (UTXOs, fee, changeAmount) so the
|
|
579
|
+
* commit pass funds the broadcast tx with the exact same set used to
|
|
580
|
+
* build the vault-context funding-outpoints commitment. Re-running
|
|
581
|
+
* `selectUtxosForPegin` in the commit pass would be deterministic given
|
|
582
|
+
* the same inputs, but threading the result through guarantees the
|
|
583
|
+
* domain separator structurally matches the funded tx inputs.
|
|
584
|
+
*
|
|
585
|
+
* Sizing runs before the wallet popup, so neither the real per-vault
|
|
586
|
+
* hashlocks nor the real `authAnchorHash` are known yet. Both slots
|
|
587
|
+
* are filled with a 32-byte placeholder; the commit pass swaps in the
|
|
588
|
+
* real values. Output budget is identical (32-byte push regardless of
|
|
589
|
+
* content), so UTXO selection is invariant under substitution.
|
|
590
|
+
*/
|
|
591
|
+
async prepareSizing(e, t) {
|
|
592
|
+
const o = t.amounts.map(
|
|
593
|
+
() => z
|
|
594
|
+
), n = t.vaultKeeperBtcPubkeys.length, r = await lt({
|
|
595
|
+
vaultCoreVersion: t.vaultCoreVersion,
|
|
596
|
+
depositorPubkey: e,
|
|
597
|
+
vaultProviderPubkey: v(t.vaultProviderBtcPubkey),
|
|
598
|
+
vaultKeeperPubkeys: t.vaultKeeperBtcPubkeys.map(v),
|
|
599
|
+
universalChallengerPubkeys: t.universalChallengerBtcPubkeys.map(v),
|
|
600
|
+
hashlocks: o,
|
|
601
|
+
timelockRefund: t.timelockRefund,
|
|
602
|
+
pegInAmounts: t.amounts,
|
|
603
|
+
feeRate: t.protocolFeeRate,
|
|
604
|
+
minPeginFeeRate: t.minPeginFeeRate,
|
|
605
|
+
numLocalChallengers: n,
|
|
606
|
+
councilQuorum: t.councilQuorum,
|
|
607
|
+
councilSize: t.councilSize,
|
|
608
|
+
network: this.config.btcNetwork,
|
|
609
|
+
authAnchorHash: z
|
|
610
|
+
}), i = ce(
|
|
611
|
+
[...t.availableUTXOs],
|
|
612
|
+
r.totalOutputValue,
|
|
613
|
+
t.mempoolFeeRate,
|
|
614
|
+
ue(r.htlcValues.length, !0)
|
|
615
|
+
);
|
|
616
|
+
return {
|
|
617
|
+
selectedUTXOs: i.selectedUTXOs,
|
|
618
|
+
fee: i.fee,
|
|
619
|
+
changeAmount: i.changeAmount
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
/** Build PegIn txs and batch-sign their inputs with real hashlocks. */
|
|
623
|
+
async preparePeginCommit(e) {
|
|
624
|
+
const {
|
|
625
|
+
depositorBtcPubkeyRaw: t,
|
|
626
|
+
depositorBtcPubkey: o,
|
|
627
|
+
hashlocks: n,
|
|
628
|
+
authAnchorHash: r,
|
|
629
|
+
sizing: i,
|
|
630
|
+
params: a
|
|
631
|
+
} = e, c = z.toLowerCase();
|
|
632
|
+
for (let g = 0; g < n.length; g++)
|
|
633
|
+
if (n[g].toLowerCase() === c)
|
|
634
|
+
throw new Error(
|
|
635
|
+
`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${g} — internal substitution bug`
|
|
636
|
+
);
|
|
637
|
+
if (r.toLowerCase() === c)
|
|
638
|
+
throw new Error(
|
|
639
|
+
"preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug"
|
|
640
|
+
);
|
|
641
|
+
const u = v(
|
|
642
|
+
a.vaultProviderBtcPubkey
|
|
643
|
+
), l = a.vaultKeeperBtcPubkeys.map(v), m = a.universalChallengerBtcPubkeys.map(v), b = l.length, w = {
|
|
644
|
+
vaultCoreVersion: a.vaultCoreVersion,
|
|
645
|
+
depositorPubkey: o,
|
|
646
|
+
vaultProviderPubkey: u,
|
|
647
|
+
vaultKeeperPubkeys: l,
|
|
648
|
+
universalChallengerPubkeys: m,
|
|
649
|
+
hashlocks: n,
|
|
650
|
+
timelockRefund: a.timelockRefund,
|
|
651
|
+
pegInAmounts: a.amounts,
|
|
652
|
+
feeRate: a.protocolFeeRate,
|
|
653
|
+
minPeginFeeRate: a.minPeginFeeRate,
|
|
654
|
+
numLocalChallengers: b,
|
|
655
|
+
councilQuorum: a.councilQuorum,
|
|
656
|
+
councilSize: a.councilSize,
|
|
657
|
+
network: this.config.btcNetwork,
|
|
658
|
+
authAnchorHash: r
|
|
659
|
+
}, d = await lt(w), E = gt(this.config.btcNetwork), k = he({
|
|
660
|
+
unfundedTxHex: d.psbtHex,
|
|
661
|
+
selectedUTXOs: i.selectedUTXOs,
|
|
662
|
+
changeAddress: a.changeAddress,
|
|
663
|
+
changeAmount: i.changeAmount,
|
|
664
|
+
network: E
|
|
665
|
+
}), f = i.selectedUTXOs.reduce((g, B) => g + BigInt(B.value), 0n) - d.totalOutputValue - i.changeAmount;
|
|
666
|
+
if (f !== i.fee)
|
|
667
|
+
throw new Error(
|
|
668
|
+
`Pre-PegIn funded fee ${f} does not match the sizing-pass fee ${i.fee}; refusing to publish a deposit-terms fee bound the funded transaction does not pay.`
|
|
669
|
+
);
|
|
670
|
+
const _ = v(
|
|
671
|
+
X(k)
|
|
672
|
+
), p = [], P = [], T = [];
|
|
673
|
+
for (let g = 0; g < n.length; g++) {
|
|
674
|
+
const B = await Yt({
|
|
675
|
+
prePeginParams: w,
|
|
676
|
+
timelockPegin: a.timelockPegin,
|
|
677
|
+
fundedPrePeginTxHex: k,
|
|
678
|
+
htlcVout: g
|
|
679
|
+
}), C = await Qt({
|
|
680
|
+
vaultCoreVersion: a.vaultCoreVersion,
|
|
681
|
+
peginTxHex: B.txHex,
|
|
682
|
+
fundedPrePeginTxHex: k,
|
|
683
|
+
depositorPubkey: o,
|
|
684
|
+
vaultProviderPubkey: u,
|
|
685
|
+
vaultKeeperPubkeys: l,
|
|
686
|
+
universalChallengerPubkeys: m,
|
|
687
|
+
hashlock: n[g],
|
|
688
|
+
timelockRefund: a.timelockRefund,
|
|
689
|
+
network: this.config.btcNetwork
|
|
690
|
+
});
|
|
691
|
+
p.push(B), P.push(C.psbtHex), T.push(
|
|
692
|
+
se(t, 1)
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
const h = Te({
|
|
696
|
+
protocolFeeRate: a.protocolFeeRate,
|
|
697
|
+
timelockPegin: a.timelockPegin,
|
|
698
|
+
timelockRefund: a.timelockRefund,
|
|
699
|
+
prepeginTxid: _,
|
|
700
|
+
prepeginMaxFee: i.fee,
|
|
701
|
+
vaultProviderPk: u,
|
|
702
|
+
keeperPks: l,
|
|
703
|
+
challengerPks: m,
|
|
704
|
+
commissionBps: a.commissionBps,
|
|
705
|
+
vaultAmounts: a.amounts,
|
|
706
|
+
depositorClaimValue: d.depositorClaimValue,
|
|
707
|
+
peginMaxFee: d.minPeginFee
|
|
708
|
+
});
|
|
709
|
+
ie(this.config.btcWallet) && await this.config.btcWallet.approveDepositTerms(h);
|
|
710
|
+
const x = await ae(
|
|
711
|
+
this.config.btcWallet,
|
|
712
|
+
P,
|
|
713
|
+
T
|
|
714
|
+
), I = [];
|
|
715
|
+
for (let g = 0; g < x.length; g++) {
|
|
716
|
+
ut({
|
|
717
|
+
requestedPsbtHex: P[g],
|
|
718
|
+
returnedPsbtHex: x[g]
|
|
719
|
+
});
|
|
720
|
+
const B = Zt(
|
|
721
|
+
x[g],
|
|
722
|
+
o
|
|
723
|
+
);
|
|
724
|
+
jt({
|
|
725
|
+
requestedPsbtHex: P[g],
|
|
726
|
+
signatureHex: B,
|
|
727
|
+
signerXOnlyPubkeyHex: o,
|
|
728
|
+
inputIndex: 0
|
|
729
|
+
});
|
|
730
|
+
const C = Jt(x[g]);
|
|
731
|
+
I.push({
|
|
732
|
+
htlcVout: g,
|
|
733
|
+
htlcValue: d.htlcValues[g],
|
|
734
|
+
peginTxHex: C,
|
|
735
|
+
peginTxid: p[g].txid,
|
|
736
|
+
peginInputSignature: B,
|
|
737
|
+
vaultScriptPubKey: p[g].vaultScriptPubKey
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
return {
|
|
741
|
+
fundedPrePeginTxHex: k,
|
|
742
|
+
prePeginTxid: _,
|
|
743
|
+
perVault: I,
|
|
744
|
+
depositTerms: h
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Signs and broadcasts a funded peg-in transaction to the Bitcoin network.
|
|
749
|
+
*
|
|
750
|
+
* This method:
|
|
751
|
+
* 1. Parses the funded transaction hex
|
|
752
|
+
* 2. Fetches UTXO data from mempool for each input
|
|
753
|
+
* 3. Creates a PSBT with proper witnessUtxo/tapInternalKey
|
|
754
|
+
* 4. Signs via btcWallet.signPsbt()
|
|
755
|
+
* 5. Finalizes and extracts the transaction
|
|
756
|
+
* 6. Broadcasts via mempool API
|
|
757
|
+
*
|
|
758
|
+
* @param params - Transaction hex and depositor public key
|
|
759
|
+
* @returns The broadcasted Bitcoin transaction ID
|
|
760
|
+
* @throws Error if signing or broadcasting fails
|
|
761
|
+
*/
|
|
762
|
+
async signAndBroadcast(e) {
|
|
763
|
+
const { fundedPrePeginTxHex: t, depositorBtcPubkey: o } = e, n = t.startsWith("0x") ? t.slice(2) : t, r = Xt.fromHex(n);
|
|
764
|
+
if (r.ins.length === 0)
|
|
765
|
+
throw new Error("Transaction has no inputs");
|
|
766
|
+
const i = new it();
|
|
767
|
+
i.setVersion(r.version), i.setLocktime(r.locktime);
|
|
768
|
+
const a = Y.from(
|
|
769
|
+
V(o),
|
|
770
|
+
"hex"
|
|
771
|
+
), c = this.config.mempoolApiUrl, u = r.ins.map((p) => {
|
|
772
|
+
const P = Y.from(p.hash).reverse().toString("hex"), T = p.index;
|
|
773
|
+
return ss(P, T, e.localPrevouts, c).then(
|
|
774
|
+
(h) => ({ input: p, utxoData: h, txid: P, vout: T })
|
|
775
|
+
);
|
|
776
|
+
}), l = await Promise.all(u), m = l.reduce(
|
|
777
|
+
(p, P) => p + BigInt(P.utxoData.value),
|
|
778
|
+
0n
|
|
779
|
+
), b = r.outs.reduce(
|
|
780
|
+
(p, P) => p + BigInt(P.value),
|
|
781
|
+
0n
|
|
782
|
+
);
|
|
783
|
+
if (m < b)
|
|
784
|
+
throw new Error(
|
|
785
|
+
`UTXO value mismatch: total input value (${m} sat) is less than total output value (${b} sat). This may indicate the mempool API returned manipulated UTXO data.`
|
|
786
|
+
);
|
|
787
|
+
const w = m - b;
|
|
788
|
+
if (w > ft)
|
|
789
|
+
throw new Error(
|
|
790
|
+
`Implied transaction fee (${w} sat) exceeds maximum reasonable fee (${ft} sat). This may indicate manipulated UTXO data.`
|
|
791
|
+
);
|
|
792
|
+
for (const { input: p, utxoData: P, txid: T, vout: h } of l) {
|
|
793
|
+
const x = le(
|
|
794
|
+
{
|
|
795
|
+
value: P.value,
|
|
796
|
+
scriptPubKey: P.scriptPubKey
|
|
797
|
+
},
|
|
798
|
+
a
|
|
799
|
+
);
|
|
800
|
+
i.addInput({
|
|
801
|
+
hash: p.hash,
|
|
802
|
+
index: p.index,
|
|
803
|
+
sequence: p.sequence,
|
|
804
|
+
...x
|
|
805
|
+
});
|
|
806
|
+
}
|
|
807
|
+
for (const p of r.outs)
|
|
808
|
+
i.addOutput({
|
|
809
|
+
script: p.script,
|
|
810
|
+
value: p.value
|
|
811
|
+
});
|
|
812
|
+
const d = i.toHex(), E = await this.config.btcWallet.signPsbt(d);
|
|
813
|
+
ut({
|
|
814
|
+
requestedPsbtHex: d,
|
|
815
|
+
returnedPsbtHex: E
|
|
816
|
+
});
|
|
817
|
+
const k = it.fromHex(E);
|
|
818
|
+
try {
|
|
819
|
+
k.finalizeAllInputs();
|
|
820
|
+
} catch (p) {
|
|
821
|
+
if (!k.data.inputs.every(
|
|
822
|
+
(T) => T.finalScriptWitness || T.finalScriptSig
|
|
823
|
+
))
|
|
824
|
+
throw new Error(
|
|
825
|
+
`PSBT finalization failed and wallet did not auto-finalize: ${p}`
|
|
826
|
+
);
|
|
827
|
+
}
|
|
828
|
+
const f = k.extractTransaction().toHex();
|
|
829
|
+
return await ge(f, c);
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.
|
|
833
|
+
*
|
|
834
|
+
* This method:
|
|
835
|
+
* 1. Re-verifies the PopSignature against the currently connected ETH
|
|
836
|
+
* and BTC wallets — refuses to proceed if either has changed
|
|
837
|
+
* 2. Derives vault ID and checks if it already exists (pre-flight)
|
|
838
|
+
* 3. Encodes the contract call using viem
|
|
839
|
+
* 4. Estimates gas (catches contract errors early with proper revert
|
|
840
|
+
* reasons)
|
|
841
|
+
* 5. Sends transaction with pre-estimated gas via
|
|
842
|
+
* ethWallet.sendTransaction()
|
|
843
|
+
*
|
|
844
|
+
* The PopSignature must be obtained via
|
|
845
|
+
* {@link signProofOfPossession} before this call.
|
|
846
|
+
*
|
|
847
|
+
* @param params - Registration parameters including the PopSignature
|
|
848
|
+
* and the prepared Pre-PegIn / PegIn transactions
|
|
849
|
+
* @returns Result containing Ethereum transaction hash and vault ID
|
|
850
|
+
* @throws Error if the PopSignature does not match the connected wallets
|
|
851
|
+
* @throws Error if the vault already exists
|
|
852
|
+
* @throws Error if contract simulation fails (e.g., invalid signature,
|
|
853
|
+
* unauthorized)
|
|
854
|
+
*/
|
|
855
|
+
async registerPeginOnChain(e) {
|
|
856
|
+
const {
|
|
857
|
+
unsignedPrePeginTx: t,
|
|
858
|
+
depositorSignedPeginTx: o,
|
|
859
|
+
vaultProvider: n,
|
|
860
|
+
hashlock: r,
|
|
861
|
+
htlcVout: i,
|
|
862
|
+
depositorPayoutBtcAddress: a,
|
|
863
|
+
depositorWotsPkHash: c,
|
|
864
|
+
popSignature: u
|
|
865
|
+
} = e;
|
|
866
|
+
if (!this.config.ethWallet.account)
|
|
867
|
+
throw new Error("Ethereum wallet account not found");
|
|
868
|
+
const l = this.config.ethWallet.account.address;
|
|
869
|
+
if (!at(u.depositorEthAddress, l))
|
|
870
|
+
throw new Error(
|
|
871
|
+
`Proof of possession was signed for ${u.depositorEthAddress} but the Ethereum wallet is currently connected to ${l}. Reconnect the original account or call signProofOfPossession() again.`
|
|
872
|
+
);
|
|
873
|
+
const m = await this.assertPopMatchesBtcWallet(u), b = u.btcPopSignature, w = A(
|
|
874
|
+
u.depositorBtcPubkey
|
|
875
|
+
), d = A(t), E = A(o), k = a ?? await this.config.btcWallet.getAddress(), f = this.resolvePayoutScriptPubKey(
|
|
876
|
+
m,
|
|
877
|
+
k
|
|
878
|
+
), _ = X(E), p = await ct(
|
|
879
|
+
v(_),
|
|
880
|
+
v(l)
|
|
881
|
+
), P = A(p);
|
|
882
|
+
if (await this.checkVaultExists(P))
|
|
883
|
+
throw new Error(
|
|
884
|
+
`Vault already exists (ID: ${P}, peginTxHash: ${_}). 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.`
|
|
885
|
+
);
|
|
886
|
+
const h = this.config.publicClient;
|
|
887
|
+
let x;
|
|
888
|
+
try {
|
|
889
|
+
x = await h.readContract({
|
|
890
|
+
address: this.config.vaultContracts.btcVaultRegistry,
|
|
891
|
+
abi: H,
|
|
892
|
+
functionName: "getPegInFee",
|
|
893
|
+
args: [n]
|
|
894
|
+
});
|
|
895
|
+
} catch (O) {
|
|
896
|
+
throw new Error(
|
|
897
|
+
"Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct.",
|
|
898
|
+
{ cause: O }
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
const I = await this.resolveMaxAcceptableCommissionBps(
|
|
902
|
+
n,
|
|
903
|
+
e.quotedCommissionBps
|
|
904
|
+
), g = j({
|
|
905
|
+
abi: H,
|
|
906
|
+
functionName: "submitPeginRequest",
|
|
907
|
+
args: [
|
|
908
|
+
l,
|
|
909
|
+
w,
|
|
910
|
+
b,
|
|
911
|
+
d,
|
|
912
|
+
E,
|
|
913
|
+
n,
|
|
914
|
+
I,
|
|
915
|
+
r,
|
|
916
|
+
i,
|
|
917
|
+
f,
|
|
918
|
+
c
|
|
919
|
+
]
|
|
920
|
+
});
|
|
921
|
+
let B;
|
|
922
|
+
try {
|
|
923
|
+
B = await h.estimateGas({
|
|
924
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
925
|
+
data: g,
|
|
926
|
+
value: x,
|
|
927
|
+
account: this.config.ethWallet.account.address
|
|
928
|
+
});
|
|
929
|
+
} catch (O) {
|
|
930
|
+
R(O);
|
|
931
|
+
}
|
|
932
|
+
let C;
|
|
933
|
+
try {
|
|
934
|
+
C = await this.config.ethWallet.sendTransaction({
|
|
935
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
936
|
+
data: g,
|
|
937
|
+
value: x,
|
|
938
|
+
account: this.config.ethWallet.account,
|
|
939
|
+
chain: this.config.ethChain,
|
|
940
|
+
gas: B
|
|
941
|
+
});
|
|
942
|
+
} catch (O) {
|
|
943
|
+
R(O);
|
|
944
|
+
}
|
|
945
|
+
const D = await pt({
|
|
946
|
+
publicClient: h,
|
|
947
|
+
walletAddress: this.config.ethWallet.account.address,
|
|
948
|
+
hash: C,
|
|
949
|
+
timeout: kt
|
|
950
|
+
});
|
|
951
|
+
return D.status === "reverted" && R(
|
|
952
|
+
new Error(
|
|
953
|
+
`Transaction reverted. Hash: ${D.transactionHash}. Check the transaction on block explorer for details.`
|
|
954
|
+
)
|
|
955
|
+
), {
|
|
956
|
+
ethTxHash: D.transactionHash,
|
|
957
|
+
vaultId: P,
|
|
958
|
+
peginTxHash: _
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
/**
|
|
962
|
+
* Register multiple pegins on Ethereum in a single transaction.
|
|
963
|
+
*
|
|
964
|
+
* Uses the contract's submitPeginRequestBatch() to submit all vault
|
|
965
|
+
* registrations atomically. All vaults must share the same vault provider.
|
|
966
|
+
* The PoP signature is signed once and included in each request.
|
|
967
|
+
*
|
|
968
|
+
* @param params - Batch registration parameters
|
|
969
|
+
* @returns Batch result with per-vault IDs and single ETH tx hash
|
|
970
|
+
*/
|
|
971
|
+
async registerPeginBatchOnChain(e) {
|
|
972
|
+
const { vaultProvider: t, unsignedPrePeginTx: o, requests: n, popSignature: r } = e;
|
|
973
|
+
if (n.length === 0)
|
|
974
|
+
throw new Error("Batch pegin requires at least one request");
|
|
975
|
+
if (!this.config.ethWallet.account)
|
|
976
|
+
throw new Error("Ethereum wallet account not found");
|
|
977
|
+
const i = this.config.ethWallet.account.address;
|
|
978
|
+
if (!at(r.depositorEthAddress, i))
|
|
979
|
+
throw new Error(
|
|
980
|
+
`Proof of possession was signed for ${r.depositorEthAddress} but the Ethereum wallet is currently connected to ${i}. Reconnect the original account or call signProofOfPossession() again.`
|
|
981
|
+
);
|
|
982
|
+
const a = await this.assertPopMatchesBtcWallet(r), c = r.btcPopSignature, u = n.map(
|
|
983
|
+
(h) => this.resolvePayoutScriptPubKey(
|
|
984
|
+
a,
|
|
985
|
+
h.depositorPayoutBtcAddress
|
|
986
|
+
)
|
|
987
|
+
), l = [];
|
|
988
|
+
for (const h of n) {
|
|
989
|
+
const x = A(
|
|
990
|
+
h.depositorSignedPeginTx
|
|
991
|
+
), I = X(x), g = await ct(
|
|
992
|
+
v(I),
|
|
993
|
+
v(i)
|
|
994
|
+
), B = A(g);
|
|
995
|
+
if (await this.checkVaultExists(B))
|
|
996
|
+
throw new Error(
|
|
997
|
+
`Vault already exists (ID: ${B}, peginTxHash: ${I}). To create a new vault, use different UTXOs or a different amount.`
|
|
998
|
+
);
|
|
999
|
+
l.push({ vaultId: B, peginTxHash: I });
|
|
1000
|
+
}
|
|
1001
|
+
const m = this.config.publicClient;
|
|
1002
|
+
let b;
|
|
1003
|
+
try {
|
|
1004
|
+
b = await m.readContract({
|
|
1005
|
+
address: this.config.vaultContracts.btcVaultRegistry,
|
|
1006
|
+
abi: H,
|
|
1007
|
+
functionName: "getPegInFee",
|
|
1008
|
+
args: [t]
|
|
1009
|
+
});
|
|
1010
|
+
} catch (h) {
|
|
1011
|
+
throw new Error(
|
|
1012
|
+
"Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct.",
|
|
1013
|
+
{ cause: h }
|
|
1014
|
+
);
|
|
1015
|
+
}
|
|
1016
|
+
const w = b * BigInt(n.length), d = await this.resolveMaxAcceptableCommissionBps(
|
|
1017
|
+
t,
|
|
1018
|
+
e.quotedCommissionBps
|
|
1019
|
+
), E = A(
|
|
1020
|
+
r.depositorBtcPubkey
|
|
1021
|
+
), k = A(o), f = n.map((h, x) => ({
|
|
1022
|
+
depositorBtcPubKey: E,
|
|
1023
|
+
btcPopSignature: c,
|
|
1024
|
+
unsignedPrePeginTx: k,
|
|
1025
|
+
depositorSignedPeginTx: A(
|
|
1026
|
+
h.depositorSignedPeginTx
|
|
1027
|
+
),
|
|
1028
|
+
hashlock: h.hashlock,
|
|
1029
|
+
htlcVout: h.htlcVout,
|
|
1030
|
+
referralCode: Mt,
|
|
1031
|
+
depositorPayoutBtcAddress: u[x],
|
|
1032
|
+
depositorWotsPkHash: h.depositorWotsPkHash
|
|
1033
|
+
})), _ = j({
|
|
1034
|
+
abi: H,
|
|
1035
|
+
functionName: "submitPeginRequestBatch",
|
|
1036
|
+
args: [
|
|
1037
|
+
i,
|
|
1038
|
+
t,
|
|
1039
|
+
d,
|
|
1040
|
+
f
|
|
1041
|
+
]
|
|
1042
|
+
});
|
|
1043
|
+
let p;
|
|
1044
|
+
try {
|
|
1045
|
+
p = await m.estimateGas({
|
|
1046
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1047
|
+
data: _,
|
|
1048
|
+
value: w,
|
|
1049
|
+
account: this.config.ethWallet.account.address
|
|
1050
|
+
});
|
|
1051
|
+
} catch (h) {
|
|
1052
|
+
R(h);
|
|
1053
|
+
}
|
|
1054
|
+
let P;
|
|
1055
|
+
try {
|
|
1056
|
+
P = await this.config.ethWallet.sendTransaction({
|
|
1057
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1058
|
+
data: _,
|
|
1059
|
+
value: w,
|
|
1060
|
+
account: this.config.ethWallet.account,
|
|
1061
|
+
chain: this.config.ethChain,
|
|
1062
|
+
gas: p
|
|
1063
|
+
});
|
|
1064
|
+
} catch (h) {
|
|
1065
|
+
R(h);
|
|
1066
|
+
}
|
|
1067
|
+
const T = await pt({
|
|
1068
|
+
publicClient: m,
|
|
1069
|
+
walletAddress: this.config.ethWallet.account.address,
|
|
1070
|
+
hash: P,
|
|
1071
|
+
timeout: kt
|
|
1072
|
+
});
|
|
1073
|
+
return T.status === "reverted" && R(
|
|
1074
|
+
new Error(
|
|
1075
|
+
`Batch transaction reverted. Hash: ${T.transactionHash}. Check the transaction on block explorer for details.`
|
|
1076
|
+
)
|
|
1077
|
+
), {
|
|
1078
|
+
ethTxHash: T.transactionHash,
|
|
1079
|
+
vaults: l
|
|
1080
|
+
};
|
|
1081
|
+
}
|
|
1082
|
+
// Anchor to quoted+headroom when supplied (refuse if chain drifted past it);
|
|
1083
|
+
// otherwise fall back to chain-current+headroom — see #1691.
|
|
1084
|
+
async resolveMaxAcceptableCommissionBps(e, t) {
|
|
1085
|
+
let o;
|
|
1086
|
+
try {
|
|
1087
|
+
o = await new fe(
|
|
1088
|
+
this.config.publicClient,
|
|
1089
|
+
this.config.vaultContracts.btcVaultRegistry
|
|
1090
|
+
).getVaultProviderCommission(e);
|
|
1091
|
+
} catch (n) {
|
|
1092
|
+
throw new Error(
|
|
1093
|
+
"Failed to query vault provider commission from the contract. Please check your network connection and that the contract address is correct.",
|
|
1094
|
+
{ cause: n }
|
|
1095
|
+
);
|
|
1096
|
+
}
|
|
1097
|
+
if (t !== void 0) {
|
|
1098
|
+
if (o > t + W)
|
|
1099
|
+
throw new Error(
|
|
1100
|
+
`Vault provider commission changed since quote: quoted ${t} bps, chain currently reports ${o} bps (allowed drift ${W} bps). Please refresh to see the new commission and try again.`
|
|
1101
|
+
);
|
|
1102
|
+
return Math.min(
|
|
1103
|
+
t + W,
|
|
1104
|
+
J
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
return Math.min(
|
|
1108
|
+
o + W,
|
|
1109
|
+
J
|
|
1110
|
+
);
|
|
1111
|
+
}
|
|
1112
|
+
/**
|
|
1113
|
+
* Check if a vault already exists for a given vault ID.
|
|
1114
|
+
*
|
|
1115
|
+
* The contract returns a default struct (with `depositor === zeroAddress`)
|
|
1116
|
+
* when no vault is registered, so existence is signalled in the response,
|
|
1117
|
+
* not via a thrown error. RPC/network failures are propagated rather than
|
|
1118
|
+
* silently treated as "vault doesn't exist", which would otherwise let
|
|
1119
|
+
* downstream calls run with stale assumptions.
|
|
1120
|
+
*
|
|
1121
|
+
* @param vaultId - The Bitcoin transaction hash (vault ID)
|
|
1122
|
+
* @returns True if vault exists, false otherwise
|
|
1123
|
+
* @throws If the underlying RPC read fails
|
|
1124
|
+
*/
|
|
1125
|
+
async checkVaultExists(e) {
|
|
1126
|
+
return (await this.config.publicClient.readContract({
|
|
1127
|
+
address: this.config.vaultContracts.btcVaultRegistry,
|
|
1128
|
+
abi: H,
|
|
1129
|
+
functionName: "getBtcVaultBasicInfo",
|
|
1130
|
+
args: [e]
|
|
1131
|
+
})).depositor !== Kt;
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Resolve the BTC scriptPubKey to register as the depositor's payout sink.
|
|
1135
|
+
*
|
|
1136
|
+
* `address` is validated against the verified depositor pubkey, sourced
|
|
1137
|
+
* from `assertPopMatchesBtcWallet`'s return value rather than
|
|
1138
|
+
* `popSignature.depositorBtcPubkey` (which is x-only, parity stripped).
|
|
1139
|
+
* For wallets that expose a compressed key this preserves y-parity end to
|
|
1140
|
+
* end. For Taproot wallets that only expose an x-only key, the helper
|
|
1141
|
+
* itself fails closed for P2WPKH — the parity is unknowable, so the
|
|
1142
|
+
* payout sink must be a P2TR address derived from that same x.
|
|
1143
|
+
*
|
|
1144
|
+
* The helper does not call into the wallet so the batch path can resolve
|
|
1145
|
+
* many requests without any extra adapter reads. Threat closed: a
|
|
1146
|
+
* state-race or stale FE state that lets a non-wallet address reach the
|
|
1147
|
+
* on-chain payout-script registration.
|
|
1148
|
+
*/
|
|
1149
|
+
resolvePayoutScriptPubKey(e, t) {
|
|
1150
|
+
if (!ht(
|
|
1151
|
+
t,
|
|
1152
|
+
e,
|
|
1153
|
+
this.config.btcNetwork
|
|
1154
|
+
))
|
|
1155
|
+
throw v(e).length === ee && es(t, this.config.btcNetwork) ? new Error(
|
|
1156
|
+
`BTC payout address "${t}" is a P2WPKH (Native SegWit) address, but the connected wallet only exposes an x-only public key. P2WPKH validation requires a compressed key with known y-parity. Use a P2TR (Taproot) payout address instead.`
|
|
1157
|
+
) : new Error(
|
|
1158
|
+
`BTC payout address "${t}" is not derived from the connected wallet's public key. The payout sink must be controlled by the same key that signs the pegin; refusing to register a mismatched address.`
|
|
1159
|
+
);
|
|
1160
|
+
const o = gt(this.config.btcNetwork);
|
|
1161
|
+
try {
|
|
1162
|
+
return `0x${Et.address.toOutputScript(t, o).toString("hex")}`;
|
|
1163
|
+
} catch {
|
|
1164
|
+
throw new Error(
|
|
1165
|
+
`Invalid BTC payout address: "${t}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC
|
|
1171
|
+
* wallet to the connected ETH account for this chain and vault
|
|
1172
|
+
* registry. The returned {@link PopSignature} can be reused across
|
|
1173
|
+
* every register call in the same session.
|
|
1174
|
+
*/
|
|
1175
|
+
async signProofOfPossession() {
|
|
1176
|
+
if (!this.config.ethWallet.account)
|
|
1177
|
+
throw new Error("Ethereum wallet account not found");
|
|
1178
|
+
const e = this.config.ethWallet.account.address, t = V(
|
|
1179
|
+
await this.config.btcWallet.getPublicKeyHex()
|
|
1180
|
+
), o = this.config.vaultContracts.btcVaultRegistry, n = `${e.toLowerCase()}:${this.config.ethChain.id}:pegin:${o.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
|
|
1181
|
+
n,
|
|
1182
|
+
"bip322-simple"
|
|
1183
|
+
);
|
|
1184
|
+
return {
|
|
1185
|
+
btcPopSignature: ts(r),
|
|
1186
|
+
depositorEthAddress: e,
|
|
1187
|
+
depositorBtcPubkey: t
|
|
1188
|
+
};
|
|
1189
|
+
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Confirm the connected BTC wallet still matches the PoP it produced, and
|
|
1192
|
+
* return the wallet's *raw* pubkey hex (parity-preserving form, as the
|
|
1193
|
+
* wallet adapter returns it). The raw form is required by callers that
|
|
1194
|
+
* validate Native SegWit / P2WPKH addresses, since P2WPKH is derived from
|
|
1195
|
+
* a parity-bearing compressed key — an x-only form would let an attacker
|
|
1196
|
+
* substitute the opposite-parity P2WPKH address.
|
|
1197
|
+
*/
|
|
1198
|
+
async assertPopMatchesBtcWallet(e) {
|
|
1199
|
+
const t = await this.config.btcWallet.getPublicKeyHex(), o = V(t), n = V(e.depositorBtcPubkey);
|
|
1200
|
+
if (o !== n)
|
|
1201
|
+
throw new Error(
|
|
1202
|
+
`Proof of possession was signed with BTC pubkey ${n} but the BTC wallet is currently connected to ${o}. Reconnect the original wallet or call signProofOfPossession() again.`
|
|
1203
|
+
);
|
|
1204
|
+
return t;
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Gets the configured Bitcoin network.
|
|
1208
|
+
*
|
|
1209
|
+
* @returns The Bitcoin network (mainnet, testnet, signet, regtest)
|
|
1210
|
+
*/
|
|
1211
|
+
getNetwork() {
|
|
1212
|
+
return this.config.btcNetwork;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Gets the configured BTCVaultRegistry contract address.
|
|
1216
|
+
*
|
|
1217
|
+
* @returns The Ethereum address of the BTCVaultRegistry contract
|
|
1218
|
+
*/
|
|
1219
|
+
getVaultContractAddress() {
|
|
1220
|
+
return this.config.vaultContracts.btcVaultRegistry;
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
const os = 80, ns = 250, rs = 300, is = 22, Ut = "ab";
|
|
1224
|
+
function as(s, e) {
|
|
1225
|
+
const t = Ut.repeat(rs), o = v(s).toLowerCase(), n = e.toString(16).padStart(8, "0"), r = `${o}${n}`, i = t.slice(r.length);
|
|
1226
|
+
return `0x${r}${i}`;
|
|
1227
|
+
}
|
|
1228
|
+
function cs(s, e) {
|
|
1229
|
+
const t = (o) => `0x${Ut.repeat(o)}`;
|
|
1230
|
+
return {
|
|
1231
|
+
depositorBtcPubKey: t(32),
|
|
1232
|
+
btcPopSignature: t(os),
|
|
1233
|
+
unsignedPrePeginTx: t(ns),
|
|
1234
|
+
depositorSignedPeginTx: as(
|
|
1235
|
+
s,
|
|
1236
|
+
e
|
|
1237
|
+
),
|
|
1238
|
+
hashlock: t(32),
|
|
1239
|
+
htlcVout: e,
|
|
1240
|
+
referralCode: Mt,
|
|
1241
|
+
depositorPayoutBtcAddress: t(is),
|
|
1242
|
+
depositorWotsPkHash: t(32)
|
|
1243
|
+
};
|
|
1244
|
+
}
|
|
1245
|
+
async function As(s) {
|
|
1246
|
+
const {
|
|
1247
|
+
publicClient: e,
|
|
1248
|
+
btcVaultRegistry: t,
|
|
1249
|
+
depositorEthAddress: o,
|
|
1250
|
+
vaultProvider: n,
|
|
1251
|
+
batchSize: r
|
|
1252
|
+
} = s;
|
|
1253
|
+
if (r <= 0)
|
|
1254
|
+
throw new Error(
|
|
1255
|
+
`estimateSubmitPeginRequestBatchGas requires batchSize >= 1 (received ${r})`
|
|
1256
|
+
);
|
|
1257
|
+
const a = await e.readContract({
|
|
1258
|
+
address: t,
|
|
1259
|
+
abi: H,
|
|
1260
|
+
functionName: "getPegInFee",
|
|
1261
|
+
args: [n]
|
|
1262
|
+
}) * BigInt(r), c = Array.from(
|
|
1263
|
+
{ length: r },
|
|
1264
|
+
(l, m) => cs(o, m)
|
|
1265
|
+
), u = j({
|
|
1266
|
+
abi: H,
|
|
1267
|
+
functionName: "submitPeginRequestBatch",
|
|
1268
|
+
args: [
|
|
1269
|
+
o,
|
|
1270
|
+
n,
|
|
1271
|
+
J,
|
|
1272
|
+
c
|
|
1273
|
+
]
|
|
1274
|
+
});
|
|
1275
|
+
return e.estimateGas({
|
|
1276
|
+
to: t,
|
|
1277
|
+
data: u,
|
|
1278
|
+
value: a,
|
|
1279
|
+
account: o
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
export {
|
|
1283
|
+
Ss as P,
|
|
1284
|
+
Te as b,
|
|
1285
|
+
Ye as c,
|
|
1286
|
+
ze as d,
|
|
1287
|
+
As as e
|
|
1288
|
+
};
|
|
1289
|
+
//# sourceMappingURL=PeginManager-aYBkb-Qx.js.map
|