@babylonlabs-io/ts-sdk 0.28.0 → 0.29.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/dist/PeginManager-DcjXiKYC.cjs +2 -0
- package/dist/PeginManager-DcjXiKYC.cjs.map +1 -0
- package/dist/{deriveVaultRoot-DAMZDqg-.js → PeginManager-Dj6oDaH5.js} +1275 -1145
- package/dist/PeginManager-Dj6oDaH5.js.map +1 -0
- package/dist/buildAndBroadcastRefund-DkEpTFkv.cjs +2 -0
- package/dist/buildAndBroadcastRefund-DkEpTFkv.cjs.map +1 -0
- package/dist/{buildAndBroadcastRefund-Cc4-L7gX.js → buildAndBroadcastRefund-xWS8frc6.js} +318 -329
- package/dist/buildAndBroadcastRefund-xWS8frc6.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +4 -4
- package/dist/{sha2-CPdTLk1u.js → sha2-6wN58S6R.js} +9 -9
- package/dist/{sha2-CPdTLk1u.js.map → sha2-6wN58S6R.js.map} +1 -1
- package/dist/tbv/core/clients/eth/vault-registry-reader.d.ts.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/contracts/abis/BTCVaultRegistry.abi.d.ts +80 -70
- package/dist/tbv/core/contracts/abis/BTCVaultRegistry.abi.d.ts.map +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.js +4 -4
- package/dist/tbv/core/managers/PeginManager.d.ts +73 -33
- package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/index.d.ts +1 -1
- package/dist/tbv/core/managers/index.d.ts.map +1 -1
- package/dist/tbv/core/managers/pegin/__tests__/assertAuthAnchorOpReturn.test.d.ts +2 -0
- package/dist/tbv/core/managers/pegin/__tests__/assertAuthAnchorOpReturn.test.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/__tests__/expandPerVaultSecrets.test.d.ts +2 -0
- package/dist/tbv/core/managers/pegin/__tests__/expandPerVaultSecrets.test.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/__tests__/normalizeWalletInputs.test.d.ts +2 -0
- package/dist/tbv/core/managers/pegin/__tests__/normalizeWalletInputs.test.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/__tests__/signPsbtsWithFallback.test.d.ts +2 -0
- package/dist/tbv/core/managers/pegin/__tests__/signPsbtsWithFallback.test.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/assertAuthAnchorOpReturn.d.ts +25 -0
- package/dist/tbv/core/managers/pegin/assertAuthAnchorOpReturn.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/expandPerVaultSecrets.d.ts +25 -0
- package/dist/tbv/core/managers/pegin/expandPerVaultSecrets.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/index.d.ts +12 -0
- package/dist/tbv/core/managers/pegin/index.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/normalizeWalletInputs.d.ts +23 -0
- package/dist/tbv/core/managers/pegin/normalizeWalletInputs.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/signPsbtsWithFallback.d.ts +12 -0
- package/dist/tbv/core/managers/pegin/signPsbtsWithFallback.d.ts.map +1 -0
- package/dist/tbv/core/services/deposit/validation.d.ts +0 -4
- package/dist/tbv/core/services/deposit/validation.d.ts.map +1 -1
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +1 -1
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +4 -4
- package/dist/testing/MockBitcoinWallet.d.ts +1 -0
- package/dist/testing/MockBitcoinWallet.d.ts.map +1 -1
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +35 -34
- package/dist/testing/index.js.map +1 -1
- package/dist/{types-CQ86O7NX.js → types-CnG3JsRs.js} +111 -81
- package/dist/types-CnG3JsRs.js.map +1 -0
- package/dist/types-jmEyzzhY.cjs +2 -0
- package/dist/types-jmEyzzhY.cjs.map +1 -0
- package/dist/{vault-registry-reader-CshEgmS0.js → vault-registry-reader-BywZhqJL.js} +37 -37
- package/dist/{vault-registry-reader-CshEgmS0.js.map → vault-registry-reader-BywZhqJL.js.map} +1 -1
- package/dist/{vault-registry-reader-_2BjSjoN.cjs → vault-registry-reader-DdruADqa.cjs} +2 -2
- package/dist/{vault-registry-reader-_2BjSjoN.cjs.map → vault-registry-reader-DdruADqa.cjs.map} +1 -1
- package/package.json +1 -1
- package/dist/buildAndBroadcastRefund-Cc4-L7gX.js.map +0 -1
- package/dist/buildAndBroadcastRefund-OoaQaNqn.cjs +0 -2
- package/dist/buildAndBroadcastRefund-OoaQaNqn.cjs.map +0 -1
- package/dist/deriveVaultRoot-B4gnRbW_.cjs +0 -2
- package/dist/deriveVaultRoot-B4gnRbW_.cjs.map +0 -1
- package/dist/deriveVaultRoot-DAMZDqg-.js.map +0 -1
- package/dist/types-CQ86O7NX.js.map +0 -1
- package/dist/types-CcwaEPE1.cjs +0 -2
- package/dist/types-CcwaEPE1.cjs.map +0 -1
|
@@ -1,365 +1,1026 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { deriveVaultId as
|
|
10
|
-
import { b as
|
|
11
|
-
import { s as
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"0x4fec082d": "Script mismatch: The Bitcoin transaction's taproot output does not match the expected vault script. This may be caused by incorrect vault participants or key configuration.",
|
|
23
|
-
// InvalidBTCProofOfPossession()
|
|
24
|
-
"0x6cc363a5": "Invalid BTC proof of possession: The signature could not be verified. Please ensure you're signing with the correct Bitcoin wallet.",
|
|
25
|
-
// InvalidBTCPublicKey()
|
|
26
|
-
"0x6c3f2bf6": "Invalid BTC public key: The Bitcoin public key format is invalid.",
|
|
27
|
-
// InvalidAmount()
|
|
28
|
-
"0x2c5211c6": "Invalid amount: The deposit amount is invalid or below the minimum required.",
|
|
29
|
-
// ApplicationNotRegistered()
|
|
30
|
-
"0x0405f772": "Application not registered: The application controller is not registered in the system.",
|
|
31
|
-
// InvalidProviderStatus()
|
|
32
|
-
"0x24e165cc": "Invalid provider status: The vault provider is not in a valid state to accept deposits.",
|
|
33
|
-
// ZeroAddress()
|
|
34
|
-
"0xd92e233d": "Zero address: One of the required addresses is the zero address.",
|
|
35
|
-
// BtcKeyMismatch()
|
|
36
|
-
"0x65aa7007": "BTC key mismatch: The Bitcoin public key does not match the expected key.",
|
|
37
|
-
// Unauthorized()
|
|
38
|
-
"0x82b42900": "Unauthorized: You must be the depositor or vault provider to submit this transaction.",
|
|
39
|
-
// InvalidSignature() - common signature verification error
|
|
40
|
-
"0x8baa579f": "Invalid signature: The BTC proof of possession signature could not be verified.",
|
|
41
|
-
// InvalidBtcTransaction()
|
|
42
|
-
"0x2f9d01e9": "Invalid BTC transaction: The Bitcoin transaction format is invalid.",
|
|
43
|
-
// VaultProviderNotRegistered()
|
|
44
|
-
"0x5a3c6b3e": "Vault provider not registered: The selected vault provider is not registered.",
|
|
45
|
-
// InvalidPeginFee(uint256,uint256)
|
|
46
|
-
"0x979f4518": "Invalid pegin fee: The ETH fee sent does not match the required amount. This may indicate a fee rate change during the transaction.",
|
|
47
|
-
// PrePeginOutputAlreadyUsed()
|
|
48
|
-
"0x5fad9694": "This pre-pegin output has already been used to activate another vault.",
|
|
49
|
-
// PeginTransactionAlreadyUsed()
|
|
50
|
-
"0x7ed061c9": "This pegin transaction has already been used to activate another vault."
|
|
51
|
-
};
|
|
52
|
-
function it(e) {
|
|
53
|
-
if (!e || typeof e != "object") return;
|
|
54
|
-
const t = e;
|
|
55
|
-
if (typeof t.data == "string" && t.data.startsWith("0x"))
|
|
56
|
-
return t.data;
|
|
57
|
-
if (typeof t.details == "string" && t.details.startsWith("0x"))
|
|
58
|
-
return t.details;
|
|
59
|
-
let n = t.cause, s = 0;
|
|
60
|
-
const o = 5;
|
|
61
|
-
for (; n && typeof n == "object" && s < o; ) {
|
|
62
|
-
const a = n;
|
|
63
|
-
if (typeof a.data == "string" && a.data.startsWith("0x"))
|
|
64
|
-
return a.data;
|
|
65
|
-
n = a.cause, s++;
|
|
66
|
-
}
|
|
67
|
-
const i = (typeof t.message == "string" ? t.message : "").match(/\b(0x[a-fA-F0-9]{8})\b/);
|
|
68
|
-
if (i)
|
|
69
|
-
return i[1];
|
|
1
|
+
var ne = Object.defineProperty;
|
|
2
|
+
var se = (e, t, n) => t in e ? ne(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
|
|
3
|
+
var m = (e, t, n) => se(e, typeof t != "symbol" ? t + "" : t, n);
|
|
4
|
+
import { a as Lt, b as N, c as A, d as K, e as st, s as O, f as Nt, H as oe, r as V, u as re, g as pt, h as ie } from "./sha2-6wN58S6R.js";
|
|
5
|
+
import * as Vt from "bitcoinjs-lib";
|
|
6
|
+
import { Transaction as ae, Psbt as mt } from "bitcoinjs-lib";
|
|
7
|
+
import { Buffer as ot } from "buffer";
|
|
8
|
+
import { isAddressEqual as wt, createPublicClient as G, http as Z, encodeFunctionData as bt, zeroAddress as ce } from "viem";
|
|
9
|
+
import { deriveVaultId as yt } from "@babylonlabs-io/babylon-tbv-rust-wasm";
|
|
10
|
+
import { b as xt, a as le, d as ue, e as he, f as de } from "./challengeAssert-j2Vwqo0-.js";
|
|
11
|
+
import { s as _, u as D, h as rt, e as I, p as fe, g as Pt, i as ge } from "./bitcoin-B-Y0DlqR.js";
|
|
12
|
+
import { c as pe } from "./signing-BZigafm0.js";
|
|
13
|
+
import { M as Et } from "./validation-CxqROCno.js";
|
|
14
|
+
import { h as me } from "./buildAndBroadcastRefund-xWS8frc6.js";
|
|
15
|
+
import { b as we, f as q, i as be } from "./psbtInputFields-DeTFSJOq.js";
|
|
16
|
+
import { p as ye, f as xe } from "./fundPeginTransaction-oV-dNJOU.js";
|
|
17
|
+
import { p as Pe, f as Ee } from "./vault-registry-reader-BywZhqJL.js";
|
|
18
|
+
import { B as R } from "./types-CnG3JsRs.js";
|
|
19
|
+
const W = /* @__PURE__ */ BigInt(2 ** 32 - 1), Tt = /* @__PURE__ */ BigInt(32);
|
|
20
|
+
function Te(e, t = !1) {
|
|
21
|
+
return t ? { h: Number(e & W), l: Number(e >> Tt & W) } : { h: Number(e >> Tt & W) | 0, l: Number(e & W) | 0 };
|
|
70
22
|
}
|
|
71
|
-
function
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
23
|
+
function ke(e, t = !1) {
|
|
24
|
+
const n = e.length;
|
|
25
|
+
let s = new Uint32Array(n), o = new Uint32Array(n);
|
|
26
|
+
for (let r = 0; r < n; r++) {
|
|
27
|
+
const { h: i, l: a } = Te(e[r], t);
|
|
28
|
+
[s[r], o[r]] = [i, a];
|
|
76
29
|
}
|
|
30
|
+
return [s, o];
|
|
77
31
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
32
|
+
const _e = (e, t, n) => e << n | t >>> 32 - n, ve = (e, t, n) => t << n | e >>> 32 - n, Ie = (e, t, n) => t << n - 32 | e >>> 64 - n, He = (e, t, n) => e << n - 32 | t >>> 64 - n, Be = 106, Se = 32, kt = 34;
|
|
33
|
+
function Ae(e, t, n) {
|
|
34
|
+
const s = _(e), o = Vt.Transaction.fromHex(s);
|
|
35
|
+
if (o.outs.length <= t)
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Pre-PegIn auth-anchor OP_RETURN missing: tx has ${o.outs.length} outputs, expected at least ${t + 1} (vault outputs + OP_RETURN)`
|
|
38
|
+
);
|
|
39
|
+
const r = o.outs[t], i = r.script;
|
|
40
|
+
if (i.length !== kt || i[0] !== Be || i[1] !== Se)
|
|
41
|
+
throw new Error(
|
|
42
|
+
`Pre-PegIn auth-anchor OP_RETURN at vout ${t} has unexpected script encoding (got ${i.length}-byte script with prefix 0x${i.slice(0, Math.min(2, i.length)).toString("hex")}; expected ${kt}-byte OP_RETURN + PUSH32 layout)`
|
|
43
|
+
);
|
|
44
|
+
const a = i.slice(2).toString("hex").toLowerCase();
|
|
45
|
+
if (a !== n.toLowerCase())
|
|
46
|
+
throw new Error(
|
|
47
|
+
`Pre-PegIn auth-anchor OP_RETURN payload mismatch at vout ${t}: tx pushes ${a}, expected ${n}`
|
|
48
|
+
);
|
|
49
|
+
if (r.value !== 0)
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Pre-PegIn auth-anchor OP_RETURN at vout ${t} has non-zero value ${r.value}; OP_RETURN outputs must be 0-value`
|
|
52
|
+
);
|
|
83
53
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
54
|
+
class Wt {
|
|
55
|
+
constructor(t, n) {
|
|
56
|
+
m(this, "oHash");
|
|
57
|
+
m(this, "iHash");
|
|
58
|
+
m(this, "blockLen");
|
|
59
|
+
m(this, "outputLen");
|
|
60
|
+
m(this, "finished", !1);
|
|
61
|
+
m(this, "destroyed", !1);
|
|
62
|
+
if (Lt(t), N(n, void 0, "key"), this.iHash = t.create(), typeof this.iHash.update != "function")
|
|
63
|
+
throw new Error("Expected instance of class which extends utils.Hash");
|
|
64
|
+
this.blockLen = this.iHash.blockLen, this.outputLen = this.iHash.outputLen;
|
|
65
|
+
const s = this.blockLen, o = new Uint8Array(s);
|
|
66
|
+
o.set(n.length > s ? t.create().update(n).digest() : n);
|
|
67
|
+
for (let r = 0; r < o.length; r++)
|
|
68
|
+
o[r] ^= 54;
|
|
69
|
+
this.iHash.update(o), this.oHash = t.create();
|
|
70
|
+
for (let r = 0; r < o.length; r++)
|
|
71
|
+
o[r] ^= 106;
|
|
72
|
+
this.oHash.update(o), A(o);
|
|
91
73
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
const s = t ? ` (error code: ${t})` : "";
|
|
95
|
-
throw console.error(
|
|
96
|
-
"[Contract Error] Transaction rejected. Error code:",
|
|
97
|
-
t,
|
|
98
|
-
"Message:",
|
|
99
|
-
n
|
|
100
|
-
), new Error(
|
|
101
|
-
`Transaction failed: The contract rejected this transaction${s}. Possible causes: (1) Vault already exists for this transaction, (2) Invalid signature, (3) Unauthorized caller. Please check your transaction parameters and try again.`
|
|
102
|
-
);
|
|
74
|
+
update(t) {
|
|
75
|
+
return K(this), this.iHash.update(t), this;
|
|
103
76
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
const xe = 0, Pe = /^0x[0-9a-f]+$/i, Ee = /^[0-9a-f]+$/i, Te = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
107
|
-
function O(e) {
|
|
108
|
-
if (typeof e != "string" || e.length === 0)
|
|
109
|
-
throw new Error("BTC wallet returned empty public key");
|
|
110
|
-
return ce(e).toLowerCase();
|
|
111
|
-
}
|
|
112
|
-
function ke(e) {
|
|
113
|
-
if (typeof e != "string" || e.length === 0)
|
|
114
|
-
throw new Error("BTC wallet returned empty BIP-322 signature");
|
|
115
|
-
if (e.startsWith("0x") || e.startsWith("0X")) {
|
|
116
|
-
if (!Pe.test(e) || e.length < 4 || e.length % 2 !== 0)
|
|
117
|
-
throw new Error("BTC wallet returned malformed hex BIP-322 signature");
|
|
118
|
-
return e.toLowerCase();
|
|
77
|
+
digestInto(t) {
|
|
78
|
+
K(this), N(t, this.outputLen, "output"), this.finished = !0, this.iHash.digestInto(t), this.oHash.update(t), this.oHash.digestInto(t), this.destroy();
|
|
119
79
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return `0x${e.toLowerCase()}`;
|
|
80
|
+
digest() {
|
|
81
|
+
const t = new Uint8Array(this.oHash.outputLen);
|
|
82
|
+
return this.digestInto(t), t;
|
|
124
83
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
|
|
130
|
-
return `0x${t.toString("hex")}`;
|
|
131
|
-
}
|
|
132
|
-
function _e(e, t, n, s) {
|
|
133
|
-
const o = n == null ? void 0 : n[`${e}:${t}`];
|
|
134
|
-
return o ? Promise.resolve({
|
|
135
|
-
txid: e,
|
|
136
|
-
vout: t,
|
|
137
|
-
value: o.value,
|
|
138
|
-
scriptPubKey: o.scriptPubKey
|
|
139
|
-
}) : me(e, t, s);
|
|
140
|
-
}
|
|
141
|
-
const yt = 12e4;
|
|
142
|
-
class Cn {
|
|
143
|
-
/**
|
|
144
|
-
* Creates a new PeginManager instance.
|
|
145
|
-
*
|
|
146
|
-
* @param config - Manager configuration including wallets and contract addresses
|
|
147
|
-
*/
|
|
148
|
-
constructor(t) {
|
|
149
|
-
p(this, "config");
|
|
150
|
-
this.config = t;
|
|
84
|
+
_cloneInto(t) {
|
|
85
|
+
t || (t = Object.create(Object.getPrototypeOf(this), {}));
|
|
86
|
+
const { oHash: n, iHash: s, finished: o, destroyed: r, blockLen: i, outputLen: a } = this;
|
|
87
|
+
return t = t, t.finished = o, t.destroyed = r, t.blockLen = i, t.outputLen = a, t.oHash = n._cloneInto(t.oHash), t.iHash = s._cloneInto(t.iHash), t;
|
|
151
88
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
* funding it, constructing the PegIn transaction, and signing the PegIn input.
|
|
155
|
-
*
|
|
156
|
-
* This method orchestrates the following steps:
|
|
157
|
-
* 1. Get depositor BTC public key from wallet
|
|
158
|
-
* 2. Build unfunded Pre-PegIn transaction (HTLC output) using primitives
|
|
159
|
-
* 3. Select UTXOs to cover the HTLC value
|
|
160
|
-
* 4. Fund the Pre-PegIn transaction
|
|
161
|
-
* 5. Derive the PegIn transaction from the funded Pre-PegIn tx
|
|
162
|
-
* 6. Build PSBT for signing the PegIn input (HTLC leaf 0)
|
|
163
|
-
* 7. Sign via BTC wallet and extract depositor signature
|
|
164
|
-
*
|
|
165
|
-
* The returned `fundedPrePeginTxHex` is funded but unsigned (inputs unsigned).
|
|
166
|
-
* Use `signAndBroadcast()` AFTER registering on Ethereum to broadcast it.
|
|
167
|
-
*
|
|
168
|
-
* @param params - Pegin parameters including amount, HTLC params, UTXOs
|
|
169
|
-
* @returns Pegin result with funded Pre-PegIn tx, signed PegIn input, and signatures
|
|
170
|
-
* @throws Error if wallet operations fail or insufficient funds
|
|
171
|
-
*/
|
|
172
|
-
async preparePegin(t) {
|
|
173
|
-
const n = await this.config.btcWallet.getPublicKeyHex(), s = O(n), o = v(t.vaultProviderBtcPubkey), r = t.vaultKeeperBtcPubkeys.map(v), i = t.universalChallengerBtcPubkeys.map(v);
|
|
174
|
-
if (t.hashlocks.length !== t.amounts.length)
|
|
175
|
-
throw new Error(
|
|
176
|
-
`hashlocks.length (${t.hashlocks.length}) must equal amounts.length (${t.amounts.length})`
|
|
177
|
-
);
|
|
178
|
-
if (t.hashlocks.length === 0)
|
|
179
|
-
throw new Error("hashlocks must contain at least one entry");
|
|
180
|
-
const a = r.length, l = {
|
|
181
|
-
depositorPubkey: s,
|
|
182
|
-
vaultProviderPubkey: o,
|
|
183
|
-
vaultKeeperPubkeys: r,
|
|
184
|
-
universalChallengerPubkeys: i,
|
|
185
|
-
hashlocks: t.hashlocks,
|
|
186
|
-
timelockRefund: t.timelockRefund,
|
|
187
|
-
pegInAmounts: t.amounts,
|
|
188
|
-
feeRate: t.protocolFeeRate,
|
|
189
|
-
numLocalChallengers: a,
|
|
190
|
-
councilQuorum: t.councilQuorum,
|
|
191
|
-
councilSize: t.councilSize,
|
|
192
|
-
network: this.config.btcNetwork
|
|
193
|
-
}, h = await ne(l), c = ue(
|
|
194
|
-
[...t.availableUTXOs],
|
|
195
|
-
h.totalOutputValue,
|
|
196
|
-
t.mempoolFeeRate,
|
|
197
|
-
fe(
|
|
198
|
-
h.htlcValues.length,
|
|
199
|
-
l.authAnchorHash
|
|
200
|
-
)
|
|
201
|
-
), b = mt(this.config.btcNetwork), m = ge({
|
|
202
|
-
unfundedTxHex: h.psbtHex,
|
|
203
|
-
selectedUTXOs: c.selectedUTXOs,
|
|
204
|
-
changeAddress: t.changeAddress,
|
|
205
|
-
changeAmount: c.changeAmount,
|
|
206
|
-
network: b
|
|
207
|
-
}), w = v(G(m)), g = [], E = [], P = [];
|
|
208
|
-
for (let u = 0; u < t.hashlocks.length; u++) {
|
|
209
|
-
const d = await se({
|
|
210
|
-
prePeginParams: l,
|
|
211
|
-
timelockPegin: t.timelockPegin,
|
|
212
|
-
fundedPrePeginTxHex: m,
|
|
213
|
-
htlcVout: u
|
|
214
|
-
}), x = await oe({
|
|
215
|
-
peginTxHex: d.txHex,
|
|
216
|
-
fundedPrePeginTxHex: m,
|
|
217
|
-
depositorPubkey: s,
|
|
218
|
-
vaultProviderPubkey: o,
|
|
219
|
-
vaultKeeperPubkeys: r,
|
|
220
|
-
universalChallengerPubkeys: i,
|
|
221
|
-
hashlock: t.hashlocks[u],
|
|
222
|
-
timelockRefund: t.timelockRefund,
|
|
223
|
-
network: this.config.btcNetwork
|
|
224
|
-
});
|
|
225
|
-
g.push(d), E.push(x.psbtHex), P.push(
|
|
226
|
-
ee(n, 1)
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
const k = await this.signPsbtsWithFallback(
|
|
230
|
-
E,
|
|
231
|
-
P
|
|
232
|
-
), f = [];
|
|
233
|
-
for (let u = 0; u < k.length; u++) {
|
|
234
|
-
const d = re(
|
|
235
|
-
k[u],
|
|
236
|
-
s
|
|
237
|
-
), x = ie(k[u]);
|
|
238
|
-
f.push({
|
|
239
|
-
htlcVout: u,
|
|
240
|
-
htlcValue: h.htlcValues[u],
|
|
241
|
-
peginTxHex: x,
|
|
242
|
-
peginTxid: g[u].txid,
|
|
243
|
-
peginInputSignature: d,
|
|
244
|
-
vaultScriptPubKey: g[u].vaultScriptPubKey
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
return {
|
|
248
|
-
fundedPrePeginTxHex: m,
|
|
249
|
-
prePeginTxid: w,
|
|
250
|
-
perVault: f,
|
|
251
|
-
selectedUTXOs: c.selectedUTXOs,
|
|
252
|
-
fee: c.fee,
|
|
253
|
-
changeAmount: c.changeAmount
|
|
254
|
-
};
|
|
89
|
+
clone() {
|
|
90
|
+
return this._cloneInto();
|
|
255
91
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
*
|
|
259
|
-
* Wallets that support native batch signing (e.g. UniSat) will sign all PSBTs
|
|
260
|
-
* in a single interaction. Others (e.g. Ledger, AppKit) implement signPsbts
|
|
261
|
-
* by looping signPsbt internally, so the UX depends on the wallet adapter.
|
|
262
|
-
*/
|
|
263
|
-
async signPsbtsWithFallback(t, n) {
|
|
264
|
-
if (typeof this.config.btcWallet.signPsbts == "function") {
|
|
265
|
-
const o = await this.config.btcWallet.signPsbts(
|
|
266
|
-
t,
|
|
267
|
-
n
|
|
268
|
-
);
|
|
269
|
-
if (o.length !== t.length)
|
|
270
|
-
throw new Error(
|
|
271
|
-
`Expected ${t.length} signed PSBTs but received ${o.length}`
|
|
272
|
-
);
|
|
273
|
-
return o;
|
|
274
|
-
}
|
|
275
|
-
const s = [];
|
|
276
|
-
for (let o = 0; o < t.length; o++) {
|
|
277
|
-
const r = await this.config.btcWallet.signPsbt(
|
|
278
|
-
t[o],
|
|
279
|
-
n[o]
|
|
280
|
-
);
|
|
281
|
-
s.push(r);
|
|
282
|
-
}
|
|
283
|
-
return s;
|
|
92
|
+
destroy() {
|
|
93
|
+
this.destroyed = !0, this.oHash.destroy(), this.iHash.destroy();
|
|
284
94
|
}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
);
|
|
314
|
-
}), c = await Promise.all(h), b = c.reduce(
|
|
315
|
-
(f, u) => f + BigInt(u.utxoData.value),
|
|
316
|
-
0n
|
|
317
|
-
), m = r.outs.reduce(
|
|
318
|
-
(f, u) => f + BigInt(u.value),
|
|
319
|
-
0n
|
|
95
|
+
}
|
|
96
|
+
const Mt = (e, t, n) => new Wt(e, t).update(n).digest();
|
|
97
|
+
Mt.create = (e, t) => new Wt(e, t);
|
|
98
|
+
const Y = /* @__PURE__ */ Uint8Array.of(0), _t = /* @__PURE__ */ Uint8Array.of();
|
|
99
|
+
function lt(e, t, n, s = 32) {
|
|
100
|
+
Lt(e), st(s, "length");
|
|
101
|
+
const o = e.outputLen;
|
|
102
|
+
if (s > 255 * o)
|
|
103
|
+
throw new Error("Length must be <= 255*HashLen");
|
|
104
|
+
const r = Math.ceil(s / o);
|
|
105
|
+
n === void 0 ? n = _t : N(n, void 0, "info");
|
|
106
|
+
const i = new Uint8Array(r * o), a = Mt.create(e, t), l = a._cloneInto(), u = new Uint8Array(a.outputLen);
|
|
107
|
+
for (let c = 0; c < r; c++)
|
|
108
|
+
Y[0] = c + 1, l.update(c === 0 ? _t : u).update(n).update(Y).digestInto(u), i.set(u, o * c), a._cloneInto(l);
|
|
109
|
+
return a.destroy(), l.destroy(), A(u, Y), i.slice(0, s);
|
|
110
|
+
}
|
|
111
|
+
const Q = new TextEncoder().encode("babylonvault"), vt = 255, It = 65535, Ht = 2, Ce = "hashlock", Oe = "auth-anchor", Re = "wots-seed";
|
|
112
|
+
function Ft(e) {
|
|
113
|
+
if (!Number.isInteger(e) || e < 0 || e > 4294967295)
|
|
114
|
+
throw new Error(`i2osp4: value must be a u32, got ${e}`);
|
|
115
|
+
const t = new Uint8Array(4);
|
|
116
|
+
return t[0] = e >>> 24 & 255, t[1] = e >>> 16 & 255, t[2] = e >>> 8 & 255, t[3] = e & 255, t;
|
|
117
|
+
}
|
|
118
|
+
function ut(e, t = new Uint8Array(0)) {
|
|
119
|
+
const n = new TextEncoder().encode(e);
|
|
120
|
+
if (n.length === 0 || n.length > vt)
|
|
121
|
+
throw new Error(
|
|
122
|
+
`info: label length must be in [1, ${vt}], got ${n.length}`
|
|
320
123
|
);
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
124
|
+
if (t.length > It)
|
|
125
|
+
throw new Error(
|
|
126
|
+
`info: ctx length must be in [0, ${It}], got ${t.length}`
|
|
127
|
+
);
|
|
128
|
+
const s = Q.length + 1 + n.length + Ht + t.length, o = new Uint8Array(s);
|
|
129
|
+
let r = 0;
|
|
130
|
+
return o.set(Q, r), r += Q.length, o[r] = n.length, r += 1, o.set(n, r), r += n.length, o[r] = t.length >>> 8 & 255, o[r + 1] = t.length & 255, r += Ht, o.set(t, r), o;
|
|
131
|
+
}
|
|
132
|
+
const Bt = 32, $e = 32, Ue = 32, Le = 64;
|
|
133
|
+
function ht(e) {
|
|
134
|
+
if (e.length !== Bt)
|
|
135
|
+
throw new Error(
|
|
136
|
+
`vault-secrets: root must be exactly ${Bt} bytes, got ${e.length}`
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
function Ne(e) {
|
|
140
|
+
return ht(e), lt(
|
|
141
|
+
O,
|
|
142
|
+
e,
|
|
143
|
+
ut(Oe),
|
|
144
|
+
$e
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function Ve(e, t) {
|
|
148
|
+
return ht(e), lt(
|
|
149
|
+
O,
|
|
150
|
+
e,
|
|
151
|
+
ut(Ce, Ft(t)),
|
|
152
|
+
Ue
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
function We(e, t) {
|
|
156
|
+
return ht(e), lt(
|
|
157
|
+
O,
|
|
158
|
+
e,
|
|
159
|
+
ut(Re, Ft(t)),
|
|
160
|
+
Le
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
const L = 32, J = 32, it = 36, Xt = 32, z = 4, Me = z + L + z + Xt;
|
|
164
|
+
function at(e, t, n) {
|
|
165
|
+
e[t] = n >>> 24 & 255, e[t + 1] = n >>> 16 & 255, e[t + 2] = n >>> 8 & 255, e[t + 3] = n & 255;
|
|
166
|
+
}
|
|
167
|
+
function Fe(e) {
|
|
168
|
+
if (e.txid.length !== J)
|
|
169
|
+
throw new Error(
|
|
170
|
+
`outpoint.txid must be exactly ${J} bytes, got ${e.txid.length}`
|
|
171
|
+
);
|
|
172
|
+
if (!Number.isInteger(e.vout) || e.vout < 0 || e.vout > 4294967295)
|
|
173
|
+
throw new Error(`outpoint.vout must be a u32, got ${e.vout}`);
|
|
174
|
+
const t = new Uint8Array(it);
|
|
175
|
+
return t.set(e.txid, 0), at(t, J, e.vout), t;
|
|
176
|
+
}
|
|
177
|
+
function St(e, t) {
|
|
178
|
+
const n = Math.min(e.length, t.length);
|
|
179
|
+
for (let s = 0; s < n; s++)
|
|
180
|
+
if (e[s] !== t[s]) return e[s] - t[s];
|
|
181
|
+
return e.length - t.length;
|
|
182
|
+
}
|
|
183
|
+
function Xe(e) {
|
|
184
|
+
if (e.length === 0)
|
|
185
|
+
throw new Error(
|
|
186
|
+
"buildFundingOutpointsCommitment: outpoints must be non-empty"
|
|
187
|
+
);
|
|
188
|
+
const t = e.map(Fe);
|
|
189
|
+
t.sort(St);
|
|
190
|
+
for (let s = 1; s < t.length; s++)
|
|
191
|
+
if (St(t[s - 1], t[s]) === 0)
|
|
327
192
|
throw new Error(
|
|
328
|
-
|
|
329
|
-
);
|
|
330
|
-
for (const { input: f, utxoData: u, txid: d, vout: x } of c) {
|
|
331
|
-
const y = de(
|
|
332
|
-
{
|
|
333
|
-
value: u.value,
|
|
334
|
-
scriptPubKey: u.scriptPubKey
|
|
335
|
-
},
|
|
336
|
-
a
|
|
193
|
+
"buildFundingOutpointsCommitment: duplicate outpoint detected"
|
|
337
194
|
);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
195
|
+
const n = new Uint8Array(t.length * it);
|
|
196
|
+
for (let s = 0; s < t.length; s++)
|
|
197
|
+
n.set(t[s], s * it);
|
|
198
|
+
return O(n);
|
|
199
|
+
}
|
|
200
|
+
function Ke(e) {
|
|
201
|
+
if (e.depositorBtcPubkey.length !== L)
|
|
202
|
+
throw new Error(
|
|
203
|
+
`vaultContext: depositorBtcPubkey must be exactly ${L} bytes, got ${e.depositorBtcPubkey.length}`
|
|
204
|
+
);
|
|
205
|
+
const t = Xe(e.fundingOutpoints), n = new Uint8Array(Me);
|
|
206
|
+
let s = 0;
|
|
207
|
+
return at(n, s, L), s += z, n.set(e.depositorBtcPubkey, s), s += L, at(n, s, Xt), s += z, n.set(t, s), n;
|
|
208
|
+
}
|
|
209
|
+
const De = "babylon-vault", Kt = 32, At = Kt * 2, ze = /^[0-9a-f]+$/;
|
|
210
|
+
async function je(e, t) {
|
|
211
|
+
const n = Ke(t), s = D(n), o = await e.deriveContextHash(De, s);
|
|
212
|
+
if (typeof o != "string")
|
|
213
|
+
throw new Error(
|
|
214
|
+
`deriveVaultRoot: wallet must return a string, got ${typeof o}`
|
|
215
|
+
);
|
|
216
|
+
if (o.length !== At)
|
|
217
|
+
throw new Error(
|
|
218
|
+
`deriveVaultRoot: wallet must return a ${At}-character hex string (${Kt} bytes), got length ${o.length}`
|
|
219
|
+
);
|
|
220
|
+
if (!ze.test(o))
|
|
221
|
+
throw new Error(
|
|
222
|
+
"deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters"
|
|
223
|
+
);
|
|
224
|
+
return rt(o);
|
|
225
|
+
}
|
|
226
|
+
const Ge = /* @__PURE__ */ Uint8Array.from([
|
|
227
|
+
7,
|
|
228
|
+
4,
|
|
229
|
+
13,
|
|
230
|
+
1,
|
|
231
|
+
10,
|
|
232
|
+
6,
|
|
233
|
+
15,
|
|
234
|
+
3,
|
|
235
|
+
12,
|
|
236
|
+
0,
|
|
237
|
+
9,
|
|
238
|
+
5,
|
|
239
|
+
2,
|
|
240
|
+
14,
|
|
241
|
+
11,
|
|
242
|
+
8
|
|
243
|
+
]), Dt = Uint8Array.from(new Array(16).fill(0).map((e, t) => t)), Ze = Dt.map((e) => (9 * e + 5) % 16), zt = /* @__PURE__ */ (() => {
|
|
244
|
+
const n = [[Dt], [Ze]];
|
|
245
|
+
for (let s = 0; s < 4; s++)
|
|
246
|
+
for (let o of n)
|
|
247
|
+
o.push(o[s].map((r) => Ge[r]));
|
|
248
|
+
return n;
|
|
249
|
+
})(), jt = zt[0], Gt = zt[1], Zt = /* @__PURE__ */ [
|
|
250
|
+
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
|
|
251
|
+
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
|
|
252
|
+
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
|
|
253
|
+
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
|
|
254
|
+
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
|
|
255
|
+
].map((e) => Uint8Array.from(e)), qe = /* @__PURE__ */ jt.map((e, t) => e.map((n) => Zt[t][n])), Ye = /* @__PURE__ */ Gt.map((e, t) => e.map((n) => Zt[t][n])), Qe = /* @__PURE__ */ Uint32Array.from([
|
|
256
|
+
0,
|
|
257
|
+
1518500249,
|
|
258
|
+
1859775393,
|
|
259
|
+
2400959708,
|
|
260
|
+
2840853838
|
|
261
|
+
]), Je = /* @__PURE__ */ Uint32Array.from([
|
|
262
|
+
1352829926,
|
|
263
|
+
1548603684,
|
|
264
|
+
1836072691,
|
|
265
|
+
2053994217,
|
|
266
|
+
0
|
|
267
|
+
]);
|
|
268
|
+
function Ct(e, t, n, s) {
|
|
269
|
+
return e === 0 ? t ^ n ^ s : e === 1 ? t & n | ~t & s : e === 2 ? (t | ~n) ^ s : e === 3 ? t & s | n & ~s : t ^ (n | ~s);
|
|
270
|
+
}
|
|
271
|
+
const M = /* @__PURE__ */ new Uint32Array(16);
|
|
272
|
+
class tn extends oe {
|
|
273
|
+
constructor() {
|
|
274
|
+
super(64, 20, 8, !0);
|
|
275
|
+
m(this, "h0", 1732584193);
|
|
276
|
+
m(this, "h1", -271733879);
|
|
277
|
+
m(this, "h2", -1732584194);
|
|
278
|
+
m(this, "h3", 271733878);
|
|
279
|
+
m(this, "h4", -1009589776);
|
|
280
|
+
}
|
|
281
|
+
get() {
|
|
282
|
+
const { h0: n, h1: s, h2: o, h3: r, h4: i } = this;
|
|
283
|
+
return [n, s, o, r, i];
|
|
284
|
+
}
|
|
285
|
+
set(n, s, o, r, i) {
|
|
286
|
+
this.h0 = n | 0, this.h1 = s | 0, this.h2 = o | 0, this.h3 = r | 0, this.h4 = i | 0;
|
|
287
|
+
}
|
|
288
|
+
process(n, s) {
|
|
289
|
+
for (let h = 0; h < 16; h++, s += 4)
|
|
290
|
+
M[h] = n.getUint32(s, !0);
|
|
291
|
+
let o = this.h0 | 0, r = o, i = this.h1 | 0, a = i, l = this.h2 | 0, u = l, c = this.h3 | 0, w = c, b = this.h4 | 0, y = b;
|
|
292
|
+
for (let h = 0; h < 5; h++) {
|
|
293
|
+
const f = 4 - h, T = Qe[h], H = Je[h], d = jt[h], P = Gt[h], g = qe[h], E = Ye[h];
|
|
294
|
+
for (let x = 0; x < 16; x++) {
|
|
295
|
+
const p = V(o + Ct(h, i, l, c) + M[d[x]] + T, g[x]) + b | 0;
|
|
296
|
+
o = b, b = c, c = V(l, 10) | 0, l = i, i = p;
|
|
297
|
+
}
|
|
298
|
+
for (let x = 0; x < 16; x++) {
|
|
299
|
+
const p = V(r + Ct(f, a, u, w) + M[P[x]] + H, E[x]) + y | 0;
|
|
300
|
+
r = y, y = w, w = V(u, 10) | 0, u = a, a = p;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
this.set(this.h1 + l + w | 0, this.h2 + c + y | 0, this.h3 + b + r | 0, this.h4 + o + a | 0, this.h0 + i + u | 0);
|
|
304
|
+
}
|
|
305
|
+
roundClean() {
|
|
306
|
+
A(M);
|
|
307
|
+
}
|
|
308
|
+
destroy() {
|
|
309
|
+
this.destroyed = !0, A(this.buffer), this.set(0, 0, 0, 0, 0);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const en = /* @__PURE__ */ Nt(() => new tn()), nn = BigInt(0), $ = BigInt(1), sn = BigInt(2), on = BigInt(7), rn = BigInt(256), an = BigInt(113), qt = [], Yt = [], Qt = [];
|
|
313
|
+
for (let e = 0, t = $, n = 1, s = 0; e < 24; e++) {
|
|
314
|
+
[n, s] = [s, (2 * n + 3 * s) % 5], qt.push(2 * (5 * s + n)), Yt.push((e + 1) * (e + 2) / 2 % 64);
|
|
315
|
+
let o = nn;
|
|
316
|
+
for (let r = 0; r < 7; r++)
|
|
317
|
+
t = (t << $ ^ (t >> on) * an) % rn, t & sn && (o ^= $ << ($ << BigInt(r)) - $);
|
|
318
|
+
Qt.push(o);
|
|
319
|
+
}
|
|
320
|
+
const Jt = ke(Qt, !0), cn = Jt[0], ln = Jt[1], Ot = (e, t, n) => n > 32 ? Ie(e, t, n) : _e(e, t, n), Rt = (e, t, n) => n > 32 ? He(e, t, n) : ve(e, t, n);
|
|
321
|
+
function un(e, t = 24) {
|
|
322
|
+
const n = new Uint32Array(10);
|
|
323
|
+
for (let s = 24 - t; s < 24; s++) {
|
|
324
|
+
for (let i = 0; i < 10; i++)
|
|
325
|
+
n[i] = e[i] ^ e[i + 10] ^ e[i + 20] ^ e[i + 30] ^ e[i + 40];
|
|
326
|
+
for (let i = 0; i < 10; i += 2) {
|
|
327
|
+
const a = (i + 8) % 10, l = (i + 2) % 10, u = n[l], c = n[l + 1], w = Ot(u, c, 1) ^ n[a], b = Rt(u, c, 1) ^ n[a + 1];
|
|
328
|
+
for (let y = 0; y < 50; y += 10)
|
|
329
|
+
e[i + y] ^= w, e[i + y + 1] ^= b;
|
|
330
|
+
}
|
|
331
|
+
let o = e[2], r = e[3];
|
|
332
|
+
for (let i = 0; i < 24; i++) {
|
|
333
|
+
const a = Yt[i], l = Ot(o, r, a), u = Rt(o, r, a), c = qt[i];
|
|
334
|
+
o = e[c], r = e[c + 1], e[c] = l, e[c + 1] = u;
|
|
335
|
+
}
|
|
336
|
+
for (let i = 0; i < 50; i += 10) {
|
|
337
|
+
for (let a = 0; a < 10; a++)
|
|
338
|
+
n[a] = e[i + a];
|
|
339
|
+
for (let a = 0; a < 10; a++)
|
|
340
|
+
e[i + a] ^= ~n[(a + 2) % 10] & n[(a + 4) % 10];
|
|
341
|
+
}
|
|
342
|
+
e[0] ^= cn[s], e[1] ^= ln[s];
|
|
343
|
+
}
|
|
344
|
+
A(n);
|
|
345
|
+
}
|
|
346
|
+
class dt {
|
|
347
|
+
// NOTE: we accept arguments in bytes instead of bits here.
|
|
348
|
+
constructor(t, n, s, o = !1, r = 24) {
|
|
349
|
+
m(this, "state");
|
|
350
|
+
m(this, "pos", 0);
|
|
351
|
+
m(this, "posOut", 0);
|
|
352
|
+
m(this, "finished", !1);
|
|
353
|
+
m(this, "state32");
|
|
354
|
+
m(this, "destroyed", !1);
|
|
355
|
+
m(this, "blockLen");
|
|
356
|
+
m(this, "suffix");
|
|
357
|
+
m(this, "outputLen");
|
|
358
|
+
m(this, "enableXOF", !1);
|
|
359
|
+
m(this, "rounds");
|
|
360
|
+
if (this.blockLen = t, this.suffix = n, this.outputLen = s, this.enableXOF = o, this.rounds = r, st(s, "outputLen"), !(0 < t && t < 200))
|
|
361
|
+
throw new Error("only keccak-f1600 function is supported");
|
|
362
|
+
this.state = new Uint8Array(200), this.state32 = re(this.state);
|
|
363
|
+
}
|
|
364
|
+
clone() {
|
|
365
|
+
return this._cloneInto();
|
|
366
|
+
}
|
|
367
|
+
keccak() {
|
|
368
|
+
pt(this.state32), un(this.state32, this.rounds), pt(this.state32), this.posOut = 0, this.pos = 0;
|
|
369
|
+
}
|
|
370
|
+
update(t) {
|
|
371
|
+
K(this), N(t);
|
|
372
|
+
const { blockLen: n, state: s } = this, o = t.length;
|
|
373
|
+
for (let r = 0; r < o; ) {
|
|
374
|
+
const i = Math.min(n - this.pos, o - r);
|
|
375
|
+
for (let a = 0; a < i; a++)
|
|
376
|
+
s[this.pos++] ^= t[r++];
|
|
377
|
+
this.pos === n && this.keccak();
|
|
378
|
+
}
|
|
379
|
+
return this;
|
|
380
|
+
}
|
|
381
|
+
finish() {
|
|
382
|
+
if (this.finished)
|
|
383
|
+
return;
|
|
384
|
+
this.finished = !0;
|
|
385
|
+
const { state: t, suffix: n, pos: s, blockLen: o } = this;
|
|
386
|
+
t[s] ^= n, (n & 128) !== 0 && s === o - 1 && this.keccak(), t[o - 1] ^= 128, this.keccak();
|
|
387
|
+
}
|
|
388
|
+
writeInto(t) {
|
|
389
|
+
K(this, !1), N(t), this.finish();
|
|
390
|
+
const n = this.state, { blockLen: s } = this;
|
|
391
|
+
for (let o = 0, r = t.length; o < r; ) {
|
|
392
|
+
this.posOut >= s && this.keccak();
|
|
393
|
+
const i = Math.min(s - this.posOut, r - o);
|
|
394
|
+
t.set(n.subarray(this.posOut, this.posOut + i), o), this.posOut += i, o += i;
|
|
395
|
+
}
|
|
396
|
+
return t;
|
|
397
|
+
}
|
|
398
|
+
xofInto(t) {
|
|
399
|
+
if (!this.enableXOF)
|
|
400
|
+
throw new Error("XOF is not possible for this instance");
|
|
401
|
+
return this.writeInto(t);
|
|
402
|
+
}
|
|
403
|
+
xof(t) {
|
|
404
|
+
return st(t), this.xofInto(new Uint8Array(t));
|
|
405
|
+
}
|
|
406
|
+
digestInto(t) {
|
|
407
|
+
if (ie(t, this), this.finished)
|
|
408
|
+
throw new Error("digest() was already called");
|
|
409
|
+
return this.writeInto(t), this.destroy(), t;
|
|
410
|
+
}
|
|
411
|
+
digest() {
|
|
412
|
+
return this.digestInto(new Uint8Array(this.outputLen));
|
|
413
|
+
}
|
|
414
|
+
destroy() {
|
|
415
|
+
this.destroyed = !0, A(this.state);
|
|
416
|
+
}
|
|
417
|
+
_cloneInto(t) {
|
|
418
|
+
const { blockLen: n, suffix: s, outputLen: o, rounds: r, enableXOF: i } = this;
|
|
419
|
+
return t || (t = new dt(n, s, o, i, r)), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = r, t.suffix = s, t.outputLen = o, t.enableXOF = i, t.destroyed = this.destroyed, t;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const hn = (e, t, n, s = {}) => Nt(() => new dt(t, e, n), s), dn = /* @__PURE__ */ hn(1, 136, 32), $t = 64, v = 20, ct = 4, te = 2, fn = 0, gn = 1, F = [64, 64], pn = (e) => Array.from(e).map((t) => t.toString(16).padStart(2, "0")).join("");
|
|
423
|
+
function ft(e) {
|
|
424
|
+
return en(O(e));
|
|
425
|
+
}
|
|
426
|
+
function ee(e) {
|
|
427
|
+
return (1 << e) - 1;
|
|
428
|
+
}
|
|
429
|
+
function mn(e) {
|
|
430
|
+
let t = 1;
|
|
431
|
+
for (; t * t < e + 1; ) t++;
|
|
432
|
+
return Math.max(t, 2);
|
|
433
|
+
}
|
|
434
|
+
function wn(e) {
|
|
435
|
+
const t = ct, n = e * ee(t);
|
|
436
|
+
return { d: t, n: e, checksum_radix: mn(n) };
|
|
437
|
+
}
|
|
438
|
+
function tt(e, t) {
|
|
439
|
+
const n = [];
|
|
440
|
+
let s = t;
|
|
441
|
+
for (; s > 0; )
|
|
442
|
+
n.push(s & 255), s >>>= 8;
|
|
443
|
+
const o = new Uint8Array(e.length + n.length);
|
|
444
|
+
o.set(e);
|
|
445
|
+
for (let r = 0; r < n.length; r++)
|
|
446
|
+
o[e.length + r] = n[r];
|
|
447
|
+
return ft(o);
|
|
448
|
+
}
|
|
449
|
+
function et(e, t) {
|
|
450
|
+
let n = e;
|
|
451
|
+
for (let s = 0; s < t; s++)
|
|
452
|
+
n = ft(n);
|
|
453
|
+
return n;
|
|
454
|
+
}
|
|
455
|
+
function bn(e, t) {
|
|
456
|
+
const n = ee(t.d), s = t.checksum_radix - 1, o = Math.floor(t.n * n / t.checksum_radix), r = [];
|
|
457
|
+
for (let c = 0; c < t.n; c++) {
|
|
458
|
+
const w = tt(e, c + te), b = et(w, n);
|
|
459
|
+
r.push(Array.from(b));
|
|
460
|
+
}
|
|
461
|
+
const i = tt(
|
|
462
|
+
e,
|
|
463
|
+
fn
|
|
464
|
+
), a = et(
|
|
465
|
+
i,
|
|
466
|
+
s
|
|
467
|
+
), l = tt(
|
|
468
|
+
e,
|
|
469
|
+
gn
|
|
470
|
+
), u = et(
|
|
471
|
+
l,
|
|
472
|
+
o
|
|
473
|
+
);
|
|
474
|
+
return {
|
|
475
|
+
config: t,
|
|
476
|
+
message_terminals: r,
|
|
477
|
+
checksum_major_terminal: Array.from(u),
|
|
478
|
+
checksum_minor_terminal: Array.from(a)
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
async function yn(e) {
|
|
482
|
+
try {
|
|
483
|
+
if (e.length !== $t)
|
|
484
|
+
throw new Error(
|
|
485
|
+
`WOTS seed must be exactly ${$t} bytes, got ${e.length}`
|
|
486
|
+
);
|
|
487
|
+
const t = [];
|
|
488
|
+
for (let n = 0; n < F.length; n++) {
|
|
489
|
+
const s = F[n], o = wn(s), r = new Uint8Array(e.length + 1);
|
|
490
|
+
r.set(e), r[e.length] = n;
|
|
491
|
+
const i = ft(r);
|
|
492
|
+
try {
|
|
493
|
+
const a = bn(i, o);
|
|
494
|
+
if (a.config.d !== ct)
|
|
495
|
+
throw new Error(
|
|
496
|
+
`Block ${n}: expected d=${ct}, got d=${a.config.d}`
|
|
497
|
+
);
|
|
498
|
+
if (a.config.n !== s)
|
|
499
|
+
throw new Error(
|
|
500
|
+
`Block ${n}: expected n=${s}, got n=${a.config.n}`
|
|
501
|
+
);
|
|
502
|
+
if (a.message_terminals.length !== s)
|
|
503
|
+
throw new Error(
|
|
504
|
+
`Block ${n}: expected ${s} message terminals, got ${a.message_terminals.length}`
|
|
505
|
+
);
|
|
506
|
+
for (let l = 0; l < a.message_terminals.length; l++)
|
|
507
|
+
if (a.message_terminals[l].length !== v)
|
|
508
|
+
throw new Error(
|
|
509
|
+
`Block ${n} terminal ${l}: expected ${v} bytes, got ${a.message_terminals[l].length}`
|
|
510
|
+
);
|
|
511
|
+
if (a.checksum_minor_terminal.length !== v)
|
|
512
|
+
throw new Error(
|
|
513
|
+
`Block ${n} checksum_minor: expected ${v} bytes`
|
|
514
|
+
);
|
|
515
|
+
if (a.checksum_major_terminal.length !== v)
|
|
516
|
+
throw new Error(
|
|
517
|
+
`Block ${n} checksum_major: expected ${v} bytes`
|
|
518
|
+
);
|
|
519
|
+
t.push(a);
|
|
520
|
+
} finally {
|
|
521
|
+
r.fill(0), i.fill(0);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (t.length !== F.length)
|
|
525
|
+
throw new Error(
|
|
526
|
+
`Expected ${F.length} blocks, got ${t.length}`
|
|
527
|
+
);
|
|
528
|
+
return t;
|
|
529
|
+
} finally {
|
|
530
|
+
e.fill(0);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
function nt(e, t, n) {
|
|
534
|
+
if (e.length !== v)
|
|
535
|
+
throw new Error(
|
|
536
|
+
`Block ${t} ${n}: expected ${v} bytes, got ${e.length}`
|
|
537
|
+
);
|
|
538
|
+
for (let s = 0; s < e.length; s++) {
|
|
539
|
+
const o = e[s];
|
|
540
|
+
if (!Number.isInteger(o) || o < 0 || o > 255)
|
|
541
|
+
throw new Error(
|
|
542
|
+
`Block ${t} ${n}[${s}]: invalid byte value ${o}`
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
function xn(e) {
|
|
547
|
+
if (e.length === 0)
|
|
548
|
+
throw new Error("Public keys array must not be empty");
|
|
549
|
+
for (let r = 0; r < e.length; r++) {
|
|
550
|
+
const i = e[r];
|
|
551
|
+
nt(i.checksum_minor_terminal, r, "checksum_minor_terminal"), nt(i.checksum_major_terminal, r, "checksum_major_terminal");
|
|
552
|
+
for (let a = 0; a < i.message_terminals.length; a++)
|
|
553
|
+
nt(i.message_terminals[a], r, `message_terminal[${a}]`);
|
|
554
|
+
}
|
|
555
|
+
let t = 0;
|
|
556
|
+
for (const r of e)
|
|
557
|
+
t += te + r.message_terminals.length;
|
|
558
|
+
const n = new Uint8Array(t * v);
|
|
559
|
+
let s = 0;
|
|
560
|
+
for (const r of e) {
|
|
561
|
+
n.set(r.checksum_minor_terminal, s), s += v, n.set(r.checksum_major_terminal, s), s += v;
|
|
562
|
+
for (const i of r.message_terminals)
|
|
563
|
+
n.set(i, s), s += v;
|
|
564
|
+
}
|
|
565
|
+
const o = dn(n);
|
|
566
|
+
return `0x${pn(o)}`;
|
|
567
|
+
}
|
|
568
|
+
function Kn(e) {
|
|
569
|
+
const t = (e instanceof Error ? e.message : typeof e == "string" ? e : "").toLowerCase();
|
|
570
|
+
return t.includes("wots") && t.includes("hash") && t.includes("does not match");
|
|
571
|
+
}
|
|
572
|
+
async function Pn(e, t) {
|
|
573
|
+
const n = [], s = [], o = [], r = [];
|
|
574
|
+
try {
|
|
575
|
+
for (let i = 0; i < t; i++) {
|
|
576
|
+
const a = We(e, i);
|
|
577
|
+
try {
|
|
578
|
+
const u = await yn(a);
|
|
579
|
+
n.push(u), s.push(xn(u));
|
|
580
|
+
} finally {
|
|
581
|
+
a.fill(0);
|
|
582
|
+
}
|
|
583
|
+
const l = Ve(e, i);
|
|
584
|
+
try {
|
|
585
|
+
const u = D(l);
|
|
586
|
+
o.push(u), r.push(me(I(u)).slice(2));
|
|
587
|
+
} finally {
|
|
588
|
+
l.fill(0);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
} finally {
|
|
592
|
+
e.fill(0);
|
|
593
|
+
}
|
|
594
|
+
return { perVaultWotsKeys: n, wotsPkHashes: s, htlcSecretHexes: o, hashlocks: r };
|
|
595
|
+
}
|
|
596
|
+
const En = /^0x[0-9a-f]+$/i, Tn = /^[0-9a-f]+$/i, kn = /^[A-Za-z0-9+/]+={0,2}$/;
|
|
597
|
+
function U(e) {
|
|
598
|
+
if (typeof e != "string" || e.length === 0)
|
|
599
|
+
throw new Error("BTC wallet returned empty public key");
|
|
600
|
+
return fe(e).toLowerCase();
|
|
601
|
+
}
|
|
602
|
+
function _n(e) {
|
|
603
|
+
if (typeof e != "string" || e.length === 0)
|
|
604
|
+
throw new Error("BTC wallet returned empty BIP-322 signature");
|
|
605
|
+
if (e.startsWith("0x") || e.startsWith("0X")) {
|
|
606
|
+
if (!En.test(e) || e.length < 4 || e.length % 2 !== 0)
|
|
607
|
+
throw new Error("BTC wallet returned malformed hex BIP-322 signature");
|
|
608
|
+
return e.toLowerCase();
|
|
609
|
+
}
|
|
610
|
+
if (Tn.test(e)) {
|
|
611
|
+
if (e.length % 2 !== 0)
|
|
612
|
+
throw new Error("BTC wallet returned malformed hex BIP-322 signature");
|
|
613
|
+
return `0x${e.toLowerCase()}`;
|
|
614
|
+
}
|
|
615
|
+
if (!kn.test(e) || e.length % 4 !== 0)
|
|
616
|
+
throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
|
|
617
|
+
const t = ot.from(e, "base64");
|
|
618
|
+
if (t.length === 0 || t.toString("base64") !== e)
|
|
619
|
+
throw new Error("BTC wallet returned malformed base64 BIP-322 signature");
|
|
620
|
+
return `0x${t.toString("hex")}`;
|
|
621
|
+
}
|
|
622
|
+
async function vn(e, t, n) {
|
|
623
|
+
if (typeof e.signPsbts == "function") {
|
|
624
|
+
const o = await e.signPsbts(t, n);
|
|
625
|
+
if (o.length !== t.length)
|
|
626
|
+
throw new Error(
|
|
627
|
+
`Expected ${t.length} signed PSBTs but received ${o.length}`
|
|
628
|
+
);
|
|
629
|
+
return o;
|
|
630
|
+
}
|
|
631
|
+
const s = [];
|
|
632
|
+
for (let o = 0; o < t.length; o++) {
|
|
633
|
+
const r = await e.signPsbt(t[o], n[o]);
|
|
634
|
+
s.push(r);
|
|
635
|
+
}
|
|
636
|
+
return s;
|
|
637
|
+
}
|
|
638
|
+
const C = {
|
|
639
|
+
// VaultAlreadyExists()
|
|
640
|
+
"0x04aabf33": "Vault already exists: This Bitcoin transaction has already been registered. Please select different UTXOs or use a different amount to create a unique transaction.",
|
|
641
|
+
// ScriptPubKeyMismatch() - taproot output doesn't match expected script
|
|
642
|
+
"0x4fec082d": "Script mismatch: The Bitcoin transaction's taproot output does not match the expected vault script. This may be caused by incorrect vault participants or key configuration.",
|
|
643
|
+
// InvalidBTCProofOfPossession()
|
|
644
|
+
"0x6cc363a5": "Invalid BTC proof of possession: The signature could not be verified. Please ensure you're signing with the correct Bitcoin wallet.",
|
|
645
|
+
// InvalidBTCPublicKey()
|
|
646
|
+
"0x6c3f2bf6": "Invalid BTC public key: The Bitcoin public key format is invalid.",
|
|
647
|
+
// InvalidAmount()
|
|
648
|
+
"0x2c5211c6": "Invalid amount: The deposit amount is invalid or below the minimum required.",
|
|
649
|
+
// ApplicationNotRegistered()
|
|
650
|
+
"0x0405f772": "Application not registered: The application controller is not registered in the system.",
|
|
651
|
+
// InvalidProviderStatus()
|
|
652
|
+
"0x24e165cc": "Invalid provider status: The vault provider is not in a valid state to accept deposits.",
|
|
653
|
+
// ZeroAddress()
|
|
654
|
+
"0xd92e233d": "Zero address: One of the required addresses is the zero address.",
|
|
655
|
+
// BtcKeyMismatch()
|
|
656
|
+
"0x65aa7007": "BTC key mismatch: The Bitcoin public key does not match the expected key.",
|
|
657
|
+
// Unauthorized()
|
|
658
|
+
"0x82b42900": "Unauthorized: You must be the depositor or vault provider to submit this transaction.",
|
|
659
|
+
// InvalidSignature() - common signature verification error
|
|
660
|
+
"0x8baa579f": "Invalid signature: The BTC proof of possession signature could not be verified.",
|
|
661
|
+
// InvalidBtcTransaction()
|
|
662
|
+
"0x2f9d01e9": "Invalid BTC transaction: The Bitcoin transaction format is invalid.",
|
|
663
|
+
// VaultProviderNotRegistered()
|
|
664
|
+
"0x5a3c6b3e": "Vault provider not registered: The selected vault provider is not registered.",
|
|
665
|
+
// InvalidPeginFee(uint256,uint256)
|
|
666
|
+
"0x979f4518": "Invalid pegin fee: The ETH fee sent does not match the required amount. This may indicate a fee rate change during the transaction.",
|
|
667
|
+
// PrePeginOutputAlreadyUsed()
|
|
668
|
+
"0x5fad9694": "This pre-pegin output has already been used to activate another vault.",
|
|
669
|
+
// PeginTransactionAlreadyUsed()
|
|
670
|
+
"0x7ed061c9": "This pegin transaction has already been used to activate another vault."
|
|
671
|
+
};
|
|
672
|
+
function gt(e) {
|
|
673
|
+
if (!e || typeof e != "object") return;
|
|
674
|
+
const t = e;
|
|
675
|
+
if (typeof t.data == "string" && t.data.startsWith("0x"))
|
|
676
|
+
return t.data;
|
|
677
|
+
if (typeof t.details == "string" && t.details.startsWith("0x"))
|
|
678
|
+
return t.details;
|
|
679
|
+
let n = t.cause, s = 0;
|
|
680
|
+
const o = 5;
|
|
681
|
+
for (; n && typeof n == "object" && s < o; ) {
|
|
682
|
+
const a = n;
|
|
683
|
+
if (typeof a.data == "string" && a.data.startsWith("0x"))
|
|
684
|
+
return a.data;
|
|
685
|
+
n = a.cause, s++;
|
|
686
|
+
}
|
|
687
|
+
const i = (typeof t.message == "string" ? t.message : "").match(/\b(0x[a-fA-F0-9]{8})\b/);
|
|
688
|
+
if (i)
|
|
689
|
+
return i[1];
|
|
690
|
+
}
|
|
691
|
+
function Dn(e) {
|
|
692
|
+
const t = gt(e);
|
|
693
|
+
if (t) {
|
|
694
|
+
const n = t.substring(0, 10);
|
|
695
|
+
return C[t] ?? C[n];
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
function zn(e) {
|
|
699
|
+
const t = gt(e);
|
|
700
|
+
if (t === void 0) return !1;
|
|
701
|
+
const n = t.substring(0, 10);
|
|
702
|
+
return t in C || n in C;
|
|
703
|
+
}
|
|
704
|
+
function S(e) {
|
|
705
|
+
console.error("[Contract Error] Raw error:", e);
|
|
706
|
+
const t = gt(e);
|
|
707
|
+
if (console.error("[Contract Error] Extracted error data:", t), t) {
|
|
708
|
+
const s = t.substring(0, 10), o = C[t] ?? C[s];
|
|
709
|
+
if (o)
|
|
710
|
+
throw console.error("[Contract Error] Known error:", o), new Error(o);
|
|
711
|
+
}
|
|
712
|
+
const n = (e == null ? void 0 : e.message) || "";
|
|
713
|
+
if (n.includes("gas limit too high") || n.includes("21000000") || n.includes("Internal JSON-RPC error")) {
|
|
714
|
+
const s = t ? ` (error code: ${t})` : "";
|
|
715
|
+
throw console.error(
|
|
716
|
+
"[Contract Error] Transaction rejected. Error code:",
|
|
717
|
+
t,
|
|
718
|
+
"Message:",
|
|
719
|
+
n
|
|
720
|
+
), new Error(
|
|
721
|
+
`Transaction failed: The contract rejected this transaction${s}. Possible causes: (1) Vault already exists for this transaction, (2) Invalid signature, (3) Unauthorized caller. Please check your transaction parameters and try again.`
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
throw e instanceof Error ? (console.error("[Contract Error] Unhandled error:", e.message), e) : new Error(`Contract call failed: ${String(e)}`);
|
|
725
|
+
}
|
|
726
|
+
const In = 0, X = "00".repeat(32);
|
|
727
|
+
function Hn(e, t, n, s) {
|
|
728
|
+
const o = n == null ? void 0 : n[`${e}:${t}`];
|
|
729
|
+
return o ? Promise.resolve({
|
|
730
|
+
txid: e,
|
|
731
|
+
vout: t,
|
|
732
|
+
value: o.value,
|
|
733
|
+
scriptPubKey: o.scriptPubKey
|
|
734
|
+
}) : Ee(e, t, s);
|
|
735
|
+
}
|
|
736
|
+
const Ut = 12e4;
|
|
737
|
+
class jn {
|
|
738
|
+
/**
|
|
739
|
+
* Creates a new PeginManager instance.
|
|
740
|
+
*
|
|
741
|
+
* @param config - Manager configuration including wallets and contract addresses
|
|
742
|
+
*/
|
|
743
|
+
constructor(t) {
|
|
744
|
+
m(this, "config");
|
|
745
|
+
this.config = t;
|
|
746
|
+
}
|
|
747
|
+
/**
|
|
748
|
+
* Prepare a peg-in: sizing pass → vault-root derivation (one wallet
|
|
749
|
+
* popup) → per-vault WOTS / hashlock derivation → commit pass with
|
|
750
|
+
* batch PSBT signing (one popup). Returns broadcast-ready txs, the
|
|
751
|
+
* pubkey snapshot, and the sensitive derived material.
|
|
752
|
+
*
|
|
753
|
+
* @throws If the wallet rejects, insufficient funds, or an internal
|
|
754
|
+
* invariant violation.
|
|
755
|
+
*/
|
|
756
|
+
async preparePegin(t) {
|
|
757
|
+
if (t.amounts.length === 0)
|
|
758
|
+
throw new Error("amounts must contain at least one entry");
|
|
759
|
+
const n = await this.config.btcWallet.getPublicKeyHex(), s = U(n), o = await this.prepareSizing(s, t), r = o.selectedUTXOs.map(
|
|
760
|
+
(f) => ({
|
|
761
|
+
txid: rt(f.txid),
|
|
762
|
+
vout: f.vout
|
|
763
|
+
})
|
|
764
|
+
), i = await je(this.config.btcWallet, {
|
|
765
|
+
depositorBtcPubkey: rt(s),
|
|
766
|
+
fundingOutpoints: r
|
|
767
|
+
});
|
|
768
|
+
let a, l;
|
|
769
|
+
try {
|
|
770
|
+
const f = Ne(i);
|
|
771
|
+
try {
|
|
772
|
+
a = D(f), l = D(O(f));
|
|
773
|
+
} finally {
|
|
774
|
+
f.fill(0);
|
|
775
|
+
}
|
|
776
|
+
} catch (f) {
|
|
777
|
+
throw i.fill(0), f;
|
|
778
|
+
}
|
|
779
|
+
const u = await Pn(i, t.amounts.length), { perVaultWotsKeys: c, wotsPkHashes: w, htlcSecretHexes: b, hashlocks: y } = u, h = await this.preparePeginCommit({
|
|
780
|
+
depositorBtcPubkeyRaw: n,
|
|
781
|
+
depositorBtcPubkey: s,
|
|
782
|
+
hashlocks: y,
|
|
783
|
+
authAnchorHash: l,
|
|
784
|
+
sizing: o,
|
|
785
|
+
params: t
|
|
786
|
+
});
|
|
787
|
+
for (let f = 0; f < h.perVault.length; f++)
|
|
788
|
+
if (h.perVault[f].htlcVout !== f)
|
|
789
|
+
throw new Error(
|
|
790
|
+
`Internal invariant violation: htlcVout/index mismatch at vault ${f} (expected ${f}, got ${h.perVault[f].htlcVout})`
|
|
791
|
+
);
|
|
792
|
+
return Ae(
|
|
793
|
+
h.fundedPrePeginTxHex,
|
|
794
|
+
t.amounts.length,
|
|
795
|
+
l
|
|
796
|
+
), {
|
|
797
|
+
transaction: {
|
|
798
|
+
...h,
|
|
799
|
+
selectedUTXOs: o.selectedUTXOs,
|
|
800
|
+
fee: o.fee,
|
|
801
|
+
changeAmount: o.changeAmount
|
|
802
|
+
},
|
|
803
|
+
depositorBtcPubkey: s,
|
|
804
|
+
derivedSecrets: {
|
|
805
|
+
perVaultWotsKeys: c,
|
|
806
|
+
wotsPkHashes: w,
|
|
807
|
+
htlcSecretHexes: b,
|
|
808
|
+
authAnchorHex: a
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
/**
|
|
813
|
+
* Build unfunded Pre-PegIn + select UTXOs. No PSBT signing.
|
|
814
|
+
*
|
|
815
|
+
* Returns the full selection result (UTXOs, fee, changeAmount) so the
|
|
816
|
+
* commit pass funds the broadcast tx with the exact same set used to
|
|
817
|
+
* build the vault-context funding-outpoints commitment. Re-running
|
|
818
|
+
* `selectUtxosForPegin` in the commit pass would be deterministic given
|
|
819
|
+
* the same inputs, but threading the result through guarantees the
|
|
820
|
+
* domain separator structurally matches the funded tx inputs.
|
|
821
|
+
*
|
|
822
|
+
* Sizing runs before the wallet popup, so neither the real per-vault
|
|
823
|
+
* hashlocks nor the real `authAnchorHash` are known yet. Both slots
|
|
824
|
+
* are filled with a 32-byte placeholder; the commit pass swaps in the
|
|
825
|
+
* real values. Output budget is identical (32-byte push regardless of
|
|
826
|
+
* content), so UTXO selection is invariant under substitution.
|
|
827
|
+
*/
|
|
828
|
+
async prepareSizing(t, n) {
|
|
829
|
+
const s = n.amounts.map(
|
|
830
|
+
() => X
|
|
831
|
+
), o = n.vaultKeeperBtcPubkeys.length, r = await xt({
|
|
832
|
+
depositorPubkey: t,
|
|
833
|
+
vaultProviderPubkey: _(n.vaultProviderBtcPubkey),
|
|
834
|
+
vaultKeeperPubkeys: n.vaultKeeperBtcPubkeys.map(_),
|
|
835
|
+
universalChallengerPubkeys: n.universalChallengerBtcPubkeys.map(_),
|
|
836
|
+
hashlocks: s,
|
|
837
|
+
timelockRefund: n.timelockRefund,
|
|
838
|
+
pegInAmounts: n.amounts,
|
|
839
|
+
feeRate: n.protocolFeeRate,
|
|
840
|
+
numLocalChallengers: o,
|
|
841
|
+
councilQuorum: n.councilQuorum,
|
|
842
|
+
councilSize: n.councilSize,
|
|
843
|
+
network: this.config.btcNetwork,
|
|
844
|
+
authAnchorHash: X
|
|
845
|
+
}), i = we(
|
|
846
|
+
[...n.availableUTXOs],
|
|
847
|
+
r.totalOutputValue,
|
|
848
|
+
n.mempoolFeeRate,
|
|
849
|
+
ye(
|
|
850
|
+
r.htlcValues.length,
|
|
851
|
+
X
|
|
852
|
+
)
|
|
853
|
+
);
|
|
854
|
+
return {
|
|
855
|
+
selectedUTXOs: i.selectedUTXOs,
|
|
856
|
+
fee: i.fee,
|
|
857
|
+
changeAmount: i.changeAmount
|
|
858
|
+
};
|
|
859
|
+
}
|
|
860
|
+
/** Build PegIn txs and batch-sign their inputs with real hashlocks. */
|
|
861
|
+
async preparePeginCommit(t) {
|
|
862
|
+
const {
|
|
863
|
+
depositorBtcPubkeyRaw: n,
|
|
864
|
+
depositorBtcPubkey: s,
|
|
865
|
+
hashlocks: o,
|
|
866
|
+
authAnchorHash: r,
|
|
867
|
+
sizing: i,
|
|
868
|
+
params: a
|
|
869
|
+
} = t, l = X.toLowerCase();
|
|
870
|
+
for (let p = 0; p < o.length; p++)
|
|
871
|
+
if (o[p].toLowerCase() === l)
|
|
872
|
+
throw new Error(
|
|
873
|
+
`preparePeginCommit refusing to build with sizing-pass placeholder hashlock at vault ${p} — internal substitution bug`
|
|
874
|
+
);
|
|
875
|
+
if (r.toLowerCase() === l)
|
|
876
|
+
throw new Error(
|
|
877
|
+
"preparePeginCommit refusing to build with sizing-pass placeholder auth-anchor hash — internal substitution bug"
|
|
878
|
+
);
|
|
879
|
+
const u = _(a.vaultProviderBtcPubkey), c = a.vaultKeeperBtcPubkeys.map(_), w = a.universalChallengerBtcPubkeys.map(_), b = c.length, y = {
|
|
880
|
+
depositorPubkey: s,
|
|
881
|
+
vaultProviderPubkey: u,
|
|
882
|
+
vaultKeeperPubkeys: c,
|
|
883
|
+
universalChallengerPubkeys: w,
|
|
884
|
+
hashlocks: o,
|
|
885
|
+
timelockRefund: a.timelockRefund,
|
|
886
|
+
pegInAmounts: a.amounts,
|
|
887
|
+
feeRate: a.protocolFeeRate,
|
|
888
|
+
numLocalChallengers: b,
|
|
889
|
+
councilQuorum: a.councilQuorum,
|
|
890
|
+
councilSize: a.councilSize,
|
|
891
|
+
network: this.config.btcNetwork,
|
|
892
|
+
authAnchorHash: r
|
|
893
|
+
}, h = await xt(y), f = Pt(this.config.btcNetwork), T = xe({
|
|
894
|
+
unfundedTxHex: h.psbtHex,
|
|
895
|
+
selectedUTXOs: i.selectedUTXOs,
|
|
896
|
+
changeAddress: a.changeAddress,
|
|
897
|
+
changeAmount: i.changeAmount,
|
|
898
|
+
network: f
|
|
899
|
+
}), H = _(q(T)), d = [], P = [], g = [];
|
|
900
|
+
for (let p = 0; p < o.length; p++) {
|
|
901
|
+
const k = await le({
|
|
902
|
+
prePeginParams: y,
|
|
903
|
+
timelockPegin: a.timelockPegin,
|
|
904
|
+
fundedPrePeginTxHex: T,
|
|
905
|
+
htlcVout: p
|
|
906
|
+
}), B = await ue({
|
|
907
|
+
peginTxHex: k.txHex,
|
|
908
|
+
fundedPrePeginTxHex: T,
|
|
909
|
+
depositorPubkey: s,
|
|
910
|
+
vaultProviderPubkey: u,
|
|
911
|
+
vaultKeeperPubkeys: c,
|
|
912
|
+
universalChallengerPubkeys: w,
|
|
913
|
+
hashlock: o[p],
|
|
914
|
+
timelockRefund: a.timelockRefund,
|
|
915
|
+
network: this.config.btcNetwork
|
|
916
|
+
});
|
|
917
|
+
d.push(k), P.push(B.psbtHex), g.push(
|
|
918
|
+
pe(n, 1)
|
|
919
|
+
);
|
|
920
|
+
}
|
|
921
|
+
const E = await vn(
|
|
922
|
+
this.config.btcWallet,
|
|
923
|
+
P,
|
|
924
|
+
g
|
|
925
|
+
), x = [];
|
|
926
|
+
for (let p = 0; p < E.length; p++) {
|
|
927
|
+
const k = he(
|
|
928
|
+
E[p],
|
|
929
|
+
s
|
|
930
|
+
), B = de(E[p]);
|
|
931
|
+
x.push({
|
|
932
|
+
htlcVout: p,
|
|
933
|
+
htlcValue: h.htlcValues[p],
|
|
934
|
+
peginTxHex: B,
|
|
935
|
+
peginTxid: d[p].txid,
|
|
936
|
+
peginInputSignature: k,
|
|
937
|
+
vaultScriptPubKey: d[p].vaultScriptPubKey
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
return {
|
|
941
|
+
fundedPrePeginTxHex: T,
|
|
942
|
+
prePeginTxid: H,
|
|
943
|
+
perVault: x
|
|
944
|
+
};
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Signs and broadcasts a funded peg-in transaction to the Bitcoin network.
|
|
948
|
+
*
|
|
949
|
+
* This method:
|
|
950
|
+
* 1. Parses the funded transaction hex
|
|
951
|
+
* 2. Fetches UTXO data from mempool for each input
|
|
952
|
+
* 3. Creates a PSBT with proper witnessUtxo/tapInternalKey
|
|
953
|
+
* 4. Signs via btcWallet.signPsbt()
|
|
954
|
+
* 5. Finalizes and extracts the transaction
|
|
955
|
+
* 6. Broadcasts via mempool API
|
|
956
|
+
*
|
|
957
|
+
* @param params - Transaction hex and depositor public key
|
|
958
|
+
* @returns The broadcasted Bitcoin transaction ID
|
|
959
|
+
* @throws Error if signing or broadcasting fails
|
|
960
|
+
*/
|
|
961
|
+
async signAndBroadcast(t) {
|
|
962
|
+
const { fundedPrePeginTxHex: n, depositorBtcPubkey: s } = t, o = n.startsWith("0x") ? n.slice(2) : n, r = ae.fromHex(o);
|
|
963
|
+
if (r.ins.length === 0)
|
|
964
|
+
throw new Error("Transaction has no inputs");
|
|
965
|
+
const i = new mt();
|
|
966
|
+
i.setVersion(r.version), i.setLocktime(r.locktime);
|
|
967
|
+
const a = ot.from(
|
|
968
|
+
U(s),
|
|
969
|
+
"hex"
|
|
970
|
+
), l = this.config.mempoolApiUrl, u = r.ins.map((d) => {
|
|
971
|
+
const P = ot.from(d.hash).reverse().toString("hex"), g = d.index;
|
|
972
|
+
return Hn(P, g, t.localPrevouts, l).then(
|
|
973
|
+
(E) => ({ input: d, utxoData: E, txid: P, vout: g })
|
|
974
|
+
);
|
|
975
|
+
}), c = await Promise.all(u), w = c.reduce(
|
|
976
|
+
(d, P) => d + BigInt(P.utxoData.value),
|
|
977
|
+
0n
|
|
978
|
+
), b = r.outs.reduce(
|
|
979
|
+
(d, P) => d + BigInt(P.value),
|
|
980
|
+
0n
|
|
981
|
+
);
|
|
982
|
+
if (w < b)
|
|
983
|
+
throw new Error(
|
|
984
|
+
`UTXO value mismatch: total input value (${w} sat) is less than total output value (${b} sat). This may indicate the mempool API returned manipulated UTXO data.`
|
|
985
|
+
);
|
|
986
|
+
const y = w - b;
|
|
987
|
+
if (y > Et)
|
|
988
|
+
throw new Error(
|
|
989
|
+
`Implied transaction fee (${y} sat) exceeds maximum reasonable fee (${Et} sat). This may indicate manipulated UTXO data.`
|
|
990
|
+
);
|
|
991
|
+
for (const { input: d, utxoData: P, txid: g, vout: E } of c) {
|
|
992
|
+
const x = be(
|
|
993
|
+
{
|
|
994
|
+
value: P.value,
|
|
995
|
+
scriptPubKey: P.scriptPubKey
|
|
996
|
+
},
|
|
997
|
+
a
|
|
998
|
+
);
|
|
999
|
+
i.addInput({
|
|
1000
|
+
hash: d.hash,
|
|
1001
|
+
index: d.index,
|
|
1002
|
+
sequence: d.sequence,
|
|
1003
|
+
...x
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
for (const d of r.outs)
|
|
1007
|
+
i.addOutput({
|
|
1008
|
+
script: d.script,
|
|
1009
|
+
value: d.value
|
|
1010
|
+
});
|
|
1011
|
+
const h = await this.config.btcWallet.signPsbt(i.toHex()), f = mt.fromHex(h);
|
|
1012
|
+
try {
|
|
1013
|
+
f.finalizeAllInputs();
|
|
1014
|
+
} catch (d) {
|
|
1015
|
+
if (!f.data.inputs.every(
|
|
1016
|
+
(g) => g.finalScriptWitness || g.finalScriptSig
|
|
356
1017
|
))
|
|
357
1018
|
throw new Error(
|
|
358
|
-
`PSBT finalization failed and wallet did not auto-finalize: ${
|
|
1019
|
+
`PSBT finalization failed and wallet did not auto-finalize: ${d}`
|
|
359
1020
|
);
|
|
360
1021
|
}
|
|
361
|
-
const
|
|
362
|
-
return await
|
|
1022
|
+
const T = f.extractTransaction().toHex();
|
|
1023
|
+
return await Pe(T, l);
|
|
363
1024
|
}
|
|
364
1025
|
/**
|
|
365
1026
|
* Registers a peg-in on Ethereum by calling the BTCVaultRegistry contract.
|
|
@@ -394,35 +1055,35 @@ class Cn {
|
|
|
394
1055
|
htlcVout: i,
|
|
395
1056
|
depositorPayoutBtcAddress: a,
|
|
396
1057
|
depositorWotsPkHash: l,
|
|
397
|
-
popSignature:
|
|
1058
|
+
popSignature: u
|
|
398
1059
|
} = t;
|
|
399
1060
|
if (!this.config.ethWallet.account)
|
|
400
1061
|
throw new Error("Ethereum wallet account not found");
|
|
401
1062
|
const c = this.config.ethWallet.account.address;
|
|
402
|
-
if (!
|
|
1063
|
+
if (!wt(u.depositorEthAddress, c))
|
|
403
1064
|
throw new Error(
|
|
404
|
-
`Proof of possession was signed for ${
|
|
1065
|
+
`Proof of possession was signed for ${u.depositorEthAddress} but the Ethereum wallet is currently connected to ${c}. Reconnect the original account or call signProofOfPossession() again.`
|
|
405
1066
|
);
|
|
406
|
-
await this.assertPopMatchesBtcWallet(
|
|
407
|
-
const
|
|
1067
|
+
await this.assertPopMatchesBtcWallet(u);
|
|
1068
|
+
const w = u.btcPopSignature, b = I(u.depositorBtcPubkey), y = I(n), h = I(s), f = await this.resolvePayoutScriptPubKey(
|
|
408
1069
|
a
|
|
409
|
-
),
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
),
|
|
413
|
-
if (await this.checkVaultExists(
|
|
1070
|
+
), T = q(h), H = await yt(
|
|
1071
|
+
_(T),
|
|
1072
|
+
_(c)
|
|
1073
|
+
), d = I(H);
|
|
1074
|
+
if (await this.checkVaultExists(d))
|
|
414
1075
|
throw new Error(
|
|
415
|
-
`Vault already exists (ID: ${
|
|
1076
|
+
`Vault already exists (ID: ${d}, peginTxHash: ${T}). 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.`
|
|
416
1077
|
);
|
|
417
|
-
const
|
|
1078
|
+
const g = G({
|
|
418
1079
|
chain: this.config.ethChain,
|
|
419
|
-
transport:
|
|
1080
|
+
transport: Z()
|
|
420
1081
|
});
|
|
421
|
-
let
|
|
1082
|
+
let E;
|
|
422
1083
|
try {
|
|
423
|
-
|
|
1084
|
+
E = await g.readContract({
|
|
424
1085
|
address: this.config.vaultContracts.btcVaultRegistry,
|
|
425
|
-
abi:
|
|
1086
|
+
abi: R,
|
|
426
1087
|
functionName: "getPegInFee",
|
|
427
1088
|
args: [o]
|
|
428
1089
|
});
|
|
@@ -431,821 +1092,290 @@ class Cn {
|
|
|
431
1092
|
"Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct."
|
|
432
1093
|
);
|
|
433
1094
|
}
|
|
434
|
-
const
|
|
435
|
-
abi:
|
|
1095
|
+
const x = bt({
|
|
1096
|
+
abi: R,
|
|
436
1097
|
functionName: "submitPeginRequest",
|
|
437
1098
|
args: [
|
|
438
1099
|
c,
|
|
439
|
-
m,
|
|
440
1100
|
b,
|
|
441
1101
|
w,
|
|
442
|
-
|
|
1102
|
+
y,
|
|
1103
|
+
h,
|
|
443
1104
|
o,
|
|
444
1105
|
r,
|
|
445
|
-
i,
|
|
446
|
-
|
|
447
|
-
l
|
|
448
|
-
]
|
|
449
|
-
});
|
|
450
|
-
let
|
|
451
|
-
try {
|
|
452
|
-
|
|
453
|
-
to: this.config.vaultContracts.btcVaultRegistry,
|
|
454
|
-
data:
|
|
455
|
-
value:
|
|
456
|
-
account: this.config.ethWallet.account.address
|
|
457
|
-
});
|
|
458
|
-
} catch (
|
|
459
|
-
|
|
460
|
-
}
|
|
461
|
-
let B;
|
|
462
|
-
try {
|
|
463
|
-
B = await this.config.ethWallet.sendTransaction({
|
|
464
|
-
to: this.config.vaultContracts.btcVaultRegistry,
|
|
465
|
-
data: y,
|
|
466
|
-
value: x,
|
|
467
|
-
account: this.config.ethWallet.account,
|
|
468
|
-
chain: this.config.ethChain,
|
|
469
|
-
gas: I
|
|
470
|
-
});
|
|
471
|
-
} catch (K) {
|
|
472
|
-
A(K);
|
|
473
|
-
}
|
|
474
|
-
const D = await d.waitForTransactionReceipt({
|
|
475
|
-
hash: B,
|
|
476
|
-
timeout: yt
|
|
477
|
-
});
|
|
478
|
-
return D.status === "reverted" && A(
|
|
479
|
-
new Error(
|
|
480
|
-
`Transaction reverted. Hash: ${B}. Check the transaction on block explorer for details.`
|
|
481
|
-
)
|
|
482
|
-
), {
|
|
483
|
-
ethTxHash: D.transactionHash,
|
|
484
|
-
vaultId: f,
|
|
485
|
-
peginTxHash: P
|
|
486
|
-
};
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Register multiple pegins on Ethereum in a single transaction.
|
|
490
|
-
*
|
|
491
|
-
* Uses the contract's submitPeginRequestBatch() to submit all vault
|
|
492
|
-
* registrations atomically. All vaults must share the same vault provider.
|
|
493
|
-
* The PoP signature is signed once and included in each request.
|
|
494
|
-
*
|
|
495
|
-
* @param params - Batch registration parameters
|
|
496
|
-
* @returns Batch result with per-vault IDs and single ETH tx hash
|
|
497
|
-
*/
|
|
498
|
-
async registerPeginBatchOnChain(t) {
|
|
499
|
-
const { vaultProvider: n, unsignedPrePeginTx: s, requests: o, popSignature: r } = t;
|
|
500
|
-
if (o.length === 0)
|
|
501
|
-
throw new Error("Batch pegin requires at least one request");
|
|
502
|
-
if (!this.config.ethWallet.account)
|
|
503
|
-
throw new Error("Ethereum wallet account not found");
|
|
504
|
-
const i = this.config.ethWallet.account.address;
|
|
505
|
-
if (!ft(r.depositorEthAddress, i))
|
|
506
|
-
throw new Error(
|
|
507
|
-
`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.`
|
|
508
|
-
);
|
|
509
|
-
await this.assertPopMatchesBtcWallet(r);
|
|
510
|
-
const a = r.btcPopSignature, l = [];
|
|
511
|
-
for (const d of o)
|
|
512
|
-
l.push(
|
|
513
|
-
await this.resolvePayoutScriptPubKey(d.depositorPayoutBtcAddress)
|
|
514
|
-
);
|
|
515
|
-
const h = [];
|
|
516
|
-
for (const d of o) {
|
|
517
|
-
const x = _(
|
|
518
|
-
d.depositorSignedPeginTx
|
|
519
|
-
), y = G(x), I = await pt(
|
|
520
|
-
v(y),
|
|
521
|
-
v(i)
|
|
522
|
-
), B = _(I);
|
|
523
|
-
if (await this.checkVaultExists(B))
|
|
524
|
-
throw new Error(
|
|
525
|
-
`Vault already exists (ID: ${B}, peginTxHash: ${y}). To create a new vault, use different UTXOs or a different amount.`
|
|
526
|
-
);
|
|
527
|
-
h.push({ vaultId: B, peginTxHash: y });
|
|
528
|
-
}
|
|
529
|
-
const c = j({
|
|
530
|
-
chain: this.config.ethChain,
|
|
531
|
-
transport: q()
|
|
532
|
-
});
|
|
533
|
-
let b;
|
|
534
|
-
try {
|
|
535
|
-
b = await c.readContract({
|
|
536
|
-
address: this.config.vaultContracts.btcVaultRegistry,
|
|
537
|
-
abi: S,
|
|
538
|
-
functionName: "getPegInFee",
|
|
539
|
-
args: [n]
|
|
540
|
-
});
|
|
541
|
-
} catch {
|
|
542
|
-
throw new Error(
|
|
543
|
-
"Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct."
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
const m = b * BigInt(o.length), w = _(
|
|
547
|
-
r.depositorBtcPubkey
|
|
548
|
-
), g = _(s), E = o.map((d, x) => ({
|
|
549
|
-
depositorBtcPubKey: w,
|
|
550
|
-
btcPopSignature: a,
|
|
551
|
-
unsignedPrePeginTx: g,
|
|
552
|
-
depositorSignedPeginTx: _(
|
|
553
|
-
d.depositorSignedPeginTx
|
|
554
|
-
),
|
|
555
|
-
hashlock: d.hashlock,
|
|
556
|
-
htlcVout: d.htlcVout,
|
|
557
|
-
referralCode: xe,
|
|
558
|
-
depositorPayoutBtcAddress: l[x],
|
|
559
|
-
depositorWotsPkHash: d.depositorWotsPkHash
|
|
560
|
-
})), P = gt({
|
|
561
|
-
abi: S,
|
|
562
|
-
functionName: "submitPeginRequestBatch",
|
|
563
|
-
args: [i, n, E]
|
|
564
|
-
});
|
|
565
|
-
let k;
|
|
566
|
-
try {
|
|
567
|
-
k = await c.estimateGas({
|
|
568
|
-
to: this.config.vaultContracts.btcVaultRegistry,
|
|
569
|
-
data: P,
|
|
570
|
-
value: m,
|
|
571
|
-
account: this.config.ethWallet.account.address
|
|
572
|
-
});
|
|
573
|
-
} catch (d) {
|
|
574
|
-
A(d);
|
|
575
|
-
}
|
|
576
|
-
let f;
|
|
577
|
-
try {
|
|
578
|
-
f = await this.config.ethWallet.sendTransaction({
|
|
579
|
-
to: this.config.vaultContracts.btcVaultRegistry,
|
|
580
|
-
data: P,
|
|
581
|
-
value: m,
|
|
582
|
-
account: this.config.ethWallet.account,
|
|
583
|
-
chain: this.config.ethChain,
|
|
584
|
-
gas: k
|
|
585
|
-
});
|
|
586
|
-
} catch (d) {
|
|
587
|
-
A(d);
|
|
588
|
-
}
|
|
589
|
-
const u = await c.waitForTransactionReceipt({
|
|
590
|
-
hash: f,
|
|
591
|
-
timeout: yt
|
|
592
|
-
});
|
|
593
|
-
return u.status === "reverted" && A(
|
|
594
|
-
new Error(
|
|
595
|
-
`Batch transaction reverted. Hash: ${f}. Check the transaction on block explorer for details.`
|
|
596
|
-
)
|
|
597
|
-
), {
|
|
598
|
-
ethTxHash: u.transactionHash,
|
|
599
|
-
vaults: h
|
|
600
|
-
};
|
|
601
|
-
}
|
|
602
|
-
/**
|
|
603
|
-
* Check if a vault already exists for a given vault ID.
|
|
604
|
-
*
|
|
605
|
-
* @param vaultId - The Bitcoin transaction hash (vault ID)
|
|
606
|
-
* @returns True if vault exists, false otherwise
|
|
607
|
-
*/
|
|
608
|
-
async checkVaultExists(t) {
|
|
609
|
-
try {
|
|
610
|
-
return (await j({
|
|
611
|
-
chain: this.config.ethChain,
|
|
612
|
-
transport: q()
|
|
613
|
-
}).readContract({
|
|
614
|
-
address: this.config.vaultContracts.btcVaultRegistry,
|
|
615
|
-
abi: S,
|
|
616
|
-
functionName: "getBtcVaultBasicInfo",
|
|
617
|
-
args: [t]
|
|
618
|
-
}))[0] !== te;
|
|
619
|
-
} catch {
|
|
620
|
-
return !1;
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
/**
|
|
624
|
-
* Resolve the BTC payout address to a scriptPubKey hex for the contract.
|
|
625
|
-
*
|
|
626
|
-
* If a payout address is provided, converts it directly.
|
|
627
|
-
* If omitted, uses the wallet's address and validates it against the
|
|
628
|
-
* wallet's public key to guard against a compromised wallet provider.
|
|
629
|
-
*/
|
|
630
|
-
async resolvePayoutScriptPubKey(t) {
|
|
631
|
-
let n;
|
|
632
|
-
if (t)
|
|
633
|
-
n = t;
|
|
634
|
-
else {
|
|
635
|
-
n = await this.config.btcWallet.getAddress();
|
|
636
|
-
const o = await this.config.btcWallet.getPublicKeyHex();
|
|
637
|
-
if (!ae(
|
|
638
|
-
n,
|
|
639
|
-
o,
|
|
640
|
-
this.config.btcNetwork
|
|
641
|
-
))
|
|
642
|
-
throw new Error(
|
|
643
|
-
"The BTC address from your wallet does not match the wallet's public key. Please ensure your wallet is using a supported address type (Taproot or Native SegWit)."
|
|
644
|
-
);
|
|
1106
|
+
i,
|
|
1107
|
+
f,
|
|
1108
|
+
l
|
|
1109
|
+
]
|
|
1110
|
+
});
|
|
1111
|
+
let p;
|
|
1112
|
+
try {
|
|
1113
|
+
p = await g.estimateGas({
|
|
1114
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1115
|
+
data: x,
|
|
1116
|
+
value: E,
|
|
1117
|
+
account: this.config.ethWallet.account.address
|
|
1118
|
+
});
|
|
1119
|
+
} catch (j) {
|
|
1120
|
+
S(j);
|
|
645
1121
|
}
|
|
646
|
-
|
|
1122
|
+
let k;
|
|
647
1123
|
try {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
1124
|
+
k = await this.config.ethWallet.sendTransaction({
|
|
1125
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1126
|
+
data: x,
|
|
1127
|
+
value: E,
|
|
1128
|
+
account: this.config.ethWallet.account,
|
|
1129
|
+
chain: this.config.ethChain,
|
|
1130
|
+
gas: p
|
|
1131
|
+
});
|
|
1132
|
+
} catch (j) {
|
|
1133
|
+
S(j);
|
|
653
1134
|
}
|
|
1135
|
+
const B = await g.waitForTransactionReceipt({
|
|
1136
|
+
hash: k,
|
|
1137
|
+
timeout: Ut
|
|
1138
|
+
});
|
|
1139
|
+
return B.status === "reverted" && S(
|
|
1140
|
+
new Error(
|
|
1141
|
+
`Transaction reverted. Hash: ${k}. Check the transaction on block explorer for details.`
|
|
1142
|
+
)
|
|
1143
|
+
), {
|
|
1144
|
+
ethTxHash: B.transactionHash,
|
|
1145
|
+
vaultId: d,
|
|
1146
|
+
peginTxHash: T
|
|
1147
|
+
};
|
|
654
1148
|
}
|
|
655
1149
|
/**
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
*
|
|
1150
|
+
* Register multiple pegins on Ethereum in a single transaction.
|
|
1151
|
+
*
|
|
1152
|
+
* Uses the contract's submitPeginRequestBatch() to submit all vault
|
|
1153
|
+
* registrations atomically. All vaults must share the same vault provider.
|
|
1154
|
+
* The PoP signature is signed once and included in each request.
|
|
1155
|
+
*
|
|
1156
|
+
* @param params - Batch registration parameters
|
|
1157
|
+
* @returns Batch result with per-vault IDs and single ETH tx hash
|
|
660
1158
|
*/
|
|
661
|
-
async
|
|
1159
|
+
async registerPeginBatchOnChain(t) {
|
|
1160
|
+
const { vaultProvider: n, unsignedPrePeginTx: s, requests: o, popSignature: r } = t;
|
|
1161
|
+
if (o.length === 0)
|
|
1162
|
+
throw new Error("Batch pegin requires at least one request");
|
|
662
1163
|
if (!this.config.ethWallet.account)
|
|
663
1164
|
throw new Error("Ethereum wallet account not found");
|
|
664
|
-
const
|
|
665
|
-
|
|
666
|
-
), s = this.config.vaultContracts.btcVaultRegistry, o = `${t.toLowerCase()}:${this.config.ethChain.id}:pegin:${s.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
|
|
667
|
-
o,
|
|
668
|
-
"bip322-simple"
|
|
669
|
-
);
|
|
670
|
-
return {
|
|
671
|
-
btcPopSignature: ke(r),
|
|
672
|
-
depositorEthAddress: t,
|
|
673
|
-
depositorBtcPubkey: n
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
async assertPopMatchesBtcWallet(t) {
|
|
677
|
-
const n = O(
|
|
678
|
-
await this.config.btcWallet.getPublicKeyHex()
|
|
679
|
-
), s = O(t.depositorBtcPubkey);
|
|
680
|
-
if (n !== s)
|
|
1165
|
+
const i = this.config.ethWallet.account.address;
|
|
1166
|
+
if (!wt(r.depositorEthAddress, i))
|
|
681
1167
|
throw new Error(
|
|
682
|
-
`Proof of possession was signed
|
|
1168
|
+
`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.`
|
|
683
1169
|
);
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
4,
|
|
718
|
-
13,
|
|
719
|
-
1,
|
|
720
|
-
10,
|
|
721
|
-
6,
|
|
722
|
-
15,
|
|
723
|
-
3,
|
|
724
|
-
12,
|
|
725
|
-
0,
|
|
726
|
-
9,
|
|
727
|
-
5,
|
|
728
|
-
2,
|
|
729
|
-
14,
|
|
730
|
-
11,
|
|
731
|
-
8
|
|
732
|
-
]), $t = Uint8Array.from(new Array(16).fill(0).map((e, t) => t)), Oe = $t.map((e) => (9 * e + 5) % 16), Rt = /* @__PURE__ */ (() => {
|
|
733
|
-
const n = [[$t], [Oe]];
|
|
734
|
-
for (let s = 0; s < 4; s++)
|
|
735
|
-
for (let o of n)
|
|
736
|
-
o.push(o[s].map((r) => Se[r]));
|
|
737
|
-
return n;
|
|
738
|
-
})(), Ut = Rt[0], Lt = Rt[1], Wt = /* @__PURE__ */ [
|
|
739
|
-
[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8],
|
|
740
|
-
[12, 13, 11, 15, 6, 9, 9, 7, 12, 15, 11, 13, 7, 8, 7, 7],
|
|
741
|
-
[13, 15, 14, 11, 7, 7, 6, 8, 13, 14, 13, 12, 5, 5, 6, 9],
|
|
742
|
-
[14, 11, 12, 14, 8, 6, 5, 5, 15, 12, 15, 14, 9, 9, 8, 6],
|
|
743
|
-
[15, 12, 13, 13, 9, 5, 8, 6, 14, 11, 12, 11, 8, 6, 5, 5]
|
|
744
|
-
].map((e) => Uint8Array.from(e)), $e = /* @__PURE__ */ Ut.map((e, t) => e.map((n) => Wt[t][n])), Re = /* @__PURE__ */ Lt.map((e, t) => e.map((n) => Wt[t][n])), Ue = /* @__PURE__ */ Uint32Array.from([
|
|
745
|
-
0,
|
|
746
|
-
1518500249,
|
|
747
|
-
1859775393,
|
|
748
|
-
2400959708,
|
|
749
|
-
2840853838
|
|
750
|
-
]), Le = /* @__PURE__ */ Uint32Array.from([
|
|
751
|
-
1352829926,
|
|
752
|
-
1548603684,
|
|
753
|
-
1836072691,
|
|
754
|
-
2053994217,
|
|
755
|
-
0
|
|
756
|
-
]);
|
|
757
|
-
function Pt(e, t, n, s) {
|
|
758
|
-
return e === 0 ? t ^ n ^ s : e === 1 ? t & n | ~t & s : e === 2 ? (t | ~n) ^ s : e === 3 ? t & s | n & ~s : t ^ (n | ~s);
|
|
759
|
-
}
|
|
760
|
-
const N = /* @__PURE__ */ new Uint32Array(16);
|
|
761
|
-
class We extends be {
|
|
762
|
-
constructor() {
|
|
763
|
-
super(64, 20, 8, !0);
|
|
764
|
-
p(this, "h0", 1732584193);
|
|
765
|
-
p(this, "h1", -271733879);
|
|
766
|
-
p(this, "h2", -1732584194);
|
|
767
|
-
p(this, "h3", 271733878);
|
|
768
|
-
p(this, "h4", -1009589776);
|
|
769
|
-
}
|
|
770
|
-
get() {
|
|
771
|
-
const { h0: n, h1: s, h2: o, h3: r, h4: i } = this;
|
|
772
|
-
return [n, s, o, r, i];
|
|
773
|
-
}
|
|
774
|
-
set(n, s, o, r, i) {
|
|
775
|
-
this.h0 = n | 0, this.h1 = s | 0, this.h2 = o | 0, this.h3 = r | 0, this.h4 = i | 0;
|
|
776
|
-
}
|
|
777
|
-
process(n, s) {
|
|
778
|
-
for (let g = 0; g < 16; g++, s += 4)
|
|
779
|
-
N[g] = n.getUint32(s, !0);
|
|
780
|
-
let o = this.h0 | 0, r = o, i = this.h1 | 0, a = i, l = this.h2 | 0, h = l, c = this.h3 | 0, b = c, m = this.h4 | 0, w = m;
|
|
781
|
-
for (let g = 0; g < 5; g++) {
|
|
782
|
-
const E = 4 - g, P = Ue[g], k = Le[g], f = Ut[g], u = Lt[g], d = $e[g], x = Re[g];
|
|
783
|
-
for (let y = 0; y < 16; y++) {
|
|
784
|
-
const I = W(o + Pt(g, i, l, c) + N[f[y]] + P, d[y]) + m | 0;
|
|
785
|
-
o = m, m = c, c = W(l, 10) | 0, l = i, i = I;
|
|
786
|
-
}
|
|
787
|
-
for (let y = 0; y < 16; y++) {
|
|
788
|
-
const I = W(r + Pt(E, a, h, b) + N[u[y]] + k, x[y]) + w | 0;
|
|
789
|
-
r = w, w = b, b = W(h, 10) | 0, h = a, a = I;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
this.set(this.h1 + l + b | 0, this.h2 + c + w | 0, this.h3 + m + r | 0, this.h4 + o + a | 0, this.h0 + i + h | 0);
|
|
793
|
-
}
|
|
794
|
-
roundClean() {
|
|
795
|
-
H(N);
|
|
796
|
-
}
|
|
797
|
-
destroy() {
|
|
798
|
-
this.destroyed = !0, H(this.buffer), this.set(0, 0, 0, 0, 0);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
const Me = /* @__PURE__ */ St(() => new We()), Ne = BigInt(0), $ = BigInt(1), Ve = BigInt(2), Fe = BigInt(7), Xe = BigInt(256), De = BigInt(113), Mt = [], Nt = [], Vt = [];
|
|
802
|
-
for (let e = 0, t = $, n = 1, s = 0; e < 24; e++) {
|
|
803
|
-
[n, s] = [s, (2 * n + 3 * s) % 5], Mt.push(2 * (5 * s + n)), Nt.push((e + 1) * (e + 2) / 2 % 64);
|
|
804
|
-
let o = Ne;
|
|
805
|
-
for (let r = 0; r < 7; r++)
|
|
806
|
-
t = (t << $ ^ (t >> Fe) * De) % Xe, t & Ve && (o ^= $ << ($ << BigInt(r)) - $);
|
|
807
|
-
Vt.push(o);
|
|
808
|
-
}
|
|
809
|
-
const Ft = ve(Vt, !0), Ke = Ft[0], je = Ft[1], Et = (e, t, n) => n > 32 ? He(e, t, n) : Be(e, t, n), Tt = (e, t, n) => n > 32 ? Ce(e, t, n) : Ae(e, t, n);
|
|
810
|
-
function qe(e, t = 24) {
|
|
811
|
-
const n = new Uint32Array(10);
|
|
812
|
-
for (let s = 24 - t; s < 24; s++) {
|
|
813
|
-
for (let i = 0; i < 10; i++)
|
|
814
|
-
n[i] = e[i] ^ e[i + 10] ^ e[i + 20] ^ e[i + 30] ^ e[i + 40];
|
|
815
|
-
for (let i = 0; i < 10; i += 2) {
|
|
816
|
-
const a = (i + 8) % 10, l = (i + 2) % 10, h = n[l], c = n[l + 1], b = Et(h, c, 1) ^ n[a], m = Tt(h, c, 1) ^ n[a + 1];
|
|
817
|
-
for (let w = 0; w < 50; w += 10)
|
|
818
|
-
e[i + w] ^= b, e[i + w + 1] ^= m;
|
|
819
|
-
}
|
|
820
|
-
let o = e[2], r = e[3];
|
|
821
|
-
for (let i = 0; i < 24; i++) {
|
|
822
|
-
const a = Nt[i], l = Et(o, r, a), h = Tt(o, r, a), c = Mt[i];
|
|
823
|
-
o = e[c], r = e[c + 1], e[c] = l, e[c + 1] = h;
|
|
824
|
-
}
|
|
825
|
-
for (let i = 0; i < 50; i += 10) {
|
|
826
|
-
for (let a = 0; a < 10; a++)
|
|
827
|
-
n[a] = e[i + a];
|
|
828
|
-
for (let a = 0; a < 10; a++)
|
|
829
|
-
e[i + a] ^= ~n[(a + 2) % 10] & n[(a + 4) % 10];
|
|
830
|
-
}
|
|
831
|
-
e[0] ^= Ke[s], e[1] ^= je[s];
|
|
832
|
-
}
|
|
833
|
-
H(n);
|
|
834
|
-
}
|
|
835
|
-
class at {
|
|
836
|
-
// NOTE: we accept arguments in bytes instead of bits here.
|
|
837
|
-
constructor(t, n, s, o = !1, r = 24) {
|
|
838
|
-
p(this, "state");
|
|
839
|
-
p(this, "pos", 0);
|
|
840
|
-
p(this, "posOut", 0);
|
|
841
|
-
p(this, "finished", !1);
|
|
842
|
-
p(this, "state32");
|
|
843
|
-
p(this, "destroyed", !1);
|
|
844
|
-
p(this, "blockLen");
|
|
845
|
-
p(this, "suffix");
|
|
846
|
-
p(this, "outputLen");
|
|
847
|
-
p(this, "enableXOF", !1);
|
|
848
|
-
p(this, "rounds");
|
|
849
|
-
if (this.blockLen = t, this.suffix = n, this.outputLen = s, this.enableXOF = o, this.rounds = r, nt(s, "outputLen"), !(0 < t && t < 200))
|
|
850
|
-
throw new Error("only keccak-f1600 function is supported");
|
|
851
|
-
this.state = new Uint8Array(200), this.state32 = we(this.state);
|
|
852
|
-
}
|
|
853
|
-
clone() {
|
|
854
|
-
return this._cloneInto();
|
|
855
|
-
}
|
|
856
|
-
keccak() {
|
|
857
|
-
wt(this.state32), qe(this.state32, this.rounds), wt(this.state32), this.posOut = 0, this.pos = 0;
|
|
858
|
-
}
|
|
859
|
-
update(t) {
|
|
860
|
-
F(this), U(t);
|
|
861
|
-
const { blockLen: n, state: s } = this, o = t.length;
|
|
862
|
-
for (let r = 0; r < o; ) {
|
|
863
|
-
const i = Math.min(n - this.pos, o - r);
|
|
864
|
-
for (let a = 0; a < i; a++)
|
|
865
|
-
s[this.pos++] ^= t[r++];
|
|
866
|
-
this.pos === n && this.keccak();
|
|
867
|
-
}
|
|
868
|
-
return this;
|
|
869
|
-
}
|
|
870
|
-
finish() {
|
|
871
|
-
if (this.finished)
|
|
872
|
-
return;
|
|
873
|
-
this.finished = !0;
|
|
874
|
-
const { state: t, suffix: n, pos: s, blockLen: o } = this;
|
|
875
|
-
t[s] ^= n, (n & 128) !== 0 && s === o - 1 && this.keccak(), t[o - 1] ^= 128, this.keccak();
|
|
876
|
-
}
|
|
877
|
-
writeInto(t) {
|
|
878
|
-
F(this, !1), U(t), this.finish();
|
|
879
|
-
const n = this.state, { blockLen: s } = this;
|
|
880
|
-
for (let o = 0, r = t.length; o < r; ) {
|
|
881
|
-
this.posOut >= s && this.keccak();
|
|
882
|
-
const i = Math.min(s - this.posOut, r - o);
|
|
883
|
-
t.set(n.subarray(this.posOut, this.posOut + i), o), this.posOut += i, o += i;
|
|
884
|
-
}
|
|
885
|
-
return t;
|
|
886
|
-
}
|
|
887
|
-
xofInto(t) {
|
|
888
|
-
if (!this.enableXOF)
|
|
889
|
-
throw new Error("XOF is not possible for this instance");
|
|
890
|
-
return this.writeInto(t);
|
|
891
|
-
}
|
|
892
|
-
xof(t) {
|
|
893
|
-
return nt(t), this.xofInto(new Uint8Array(t));
|
|
894
|
-
}
|
|
895
|
-
digestInto(t) {
|
|
896
|
-
if (ye(t, this), this.finished)
|
|
897
|
-
throw new Error("digest() was already called");
|
|
898
|
-
return this.writeInto(t), this.destroy(), t;
|
|
899
|
-
}
|
|
900
|
-
digest() {
|
|
901
|
-
return this.digestInto(new Uint8Array(this.outputLen));
|
|
902
|
-
}
|
|
903
|
-
destroy() {
|
|
904
|
-
this.destroyed = !0, H(this.state);
|
|
905
|
-
}
|
|
906
|
-
_cloneInto(t) {
|
|
907
|
-
const { blockLen: n, suffix: s, outputLen: o, rounds: r, enableXOF: i } = this;
|
|
908
|
-
return t || (t = new at(n, s, o, i, r)), t.state32.set(this.state32), t.pos = this.pos, t.posOut = this.posOut, t.finished = this.finished, t.rounds = r, t.suffix = s, t.outputLen = o, t.enableXOF = i, t.destroyed = this.destroyed, t;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
const Ge = (e, t, n, s = {}) => St(() => new at(t, e, n), s), Ze = /* @__PURE__ */ Ge(1, 136, 32), kt = 64, T = 20, st = 4, Xt = 2, ze = 0, Ye = 1, V = [64, 64], Je = (e) => Array.from(e).map((t) => t.toString(16).padStart(2, "0")).join("");
|
|
912
|
-
function ct(e) {
|
|
913
|
-
return Me(L(e));
|
|
914
|
-
}
|
|
915
|
-
function Dt(e) {
|
|
916
|
-
return (1 << e) - 1;
|
|
917
|
-
}
|
|
918
|
-
function Qe(e) {
|
|
919
|
-
let t = 1;
|
|
920
|
-
for (; t * t < e + 1; ) t++;
|
|
921
|
-
return Math.max(t, 2);
|
|
922
|
-
}
|
|
923
|
-
function tn(e) {
|
|
924
|
-
const t = st, n = e * Dt(t);
|
|
925
|
-
return { d: t, n: e, checksum_radix: Qe(n) };
|
|
926
|
-
}
|
|
927
|
-
function Z(e, t) {
|
|
928
|
-
const n = [];
|
|
929
|
-
let s = t;
|
|
930
|
-
for (; s > 0; )
|
|
931
|
-
n.push(s & 255), s >>>= 8;
|
|
932
|
-
const o = new Uint8Array(e.length + n.length);
|
|
933
|
-
o.set(e);
|
|
934
|
-
for (let r = 0; r < n.length; r++)
|
|
935
|
-
o[e.length + r] = n[r];
|
|
936
|
-
return ct(o);
|
|
937
|
-
}
|
|
938
|
-
function z(e, t) {
|
|
939
|
-
let n = e;
|
|
940
|
-
for (let s = 0; s < t; s++)
|
|
941
|
-
n = ct(n);
|
|
942
|
-
return n;
|
|
943
|
-
}
|
|
944
|
-
function en(e, t) {
|
|
945
|
-
const n = Dt(t.d), s = t.checksum_radix - 1, o = Math.floor(t.n * n / t.checksum_radix), r = [];
|
|
946
|
-
for (let c = 0; c < t.n; c++) {
|
|
947
|
-
const b = Z(e, c + Xt), m = z(b, n);
|
|
948
|
-
r.push(Array.from(m));
|
|
949
|
-
}
|
|
950
|
-
const i = Z(
|
|
951
|
-
e,
|
|
952
|
-
ze
|
|
953
|
-
), a = z(
|
|
954
|
-
i,
|
|
955
|
-
s
|
|
956
|
-
), l = Z(
|
|
957
|
-
e,
|
|
958
|
-
Ye
|
|
959
|
-
), h = z(
|
|
960
|
-
l,
|
|
961
|
-
o
|
|
962
|
-
);
|
|
963
|
-
return {
|
|
964
|
-
config: t,
|
|
965
|
-
message_terminals: r,
|
|
966
|
-
checksum_major_terminal: Array.from(h),
|
|
967
|
-
checksum_minor_terminal: Array.from(a)
|
|
968
|
-
};
|
|
969
|
-
}
|
|
970
|
-
async function Sn(e) {
|
|
971
|
-
try {
|
|
972
|
-
if (e.length !== kt)
|
|
1170
|
+
await this.assertPopMatchesBtcWallet(r);
|
|
1171
|
+
const a = r.btcPopSignature, l = [];
|
|
1172
|
+
for (const g of o)
|
|
1173
|
+
l.push(
|
|
1174
|
+
await this.resolvePayoutScriptPubKey(g.depositorPayoutBtcAddress)
|
|
1175
|
+
);
|
|
1176
|
+
const u = [];
|
|
1177
|
+
for (const g of o) {
|
|
1178
|
+
const E = I(
|
|
1179
|
+
g.depositorSignedPeginTx
|
|
1180
|
+
), x = q(E), p = await yt(
|
|
1181
|
+
_(x),
|
|
1182
|
+
_(i)
|
|
1183
|
+
), k = I(p);
|
|
1184
|
+
if (await this.checkVaultExists(k))
|
|
1185
|
+
throw new Error(
|
|
1186
|
+
`Vault already exists (ID: ${k}, peginTxHash: ${x}). To create a new vault, use different UTXOs or a different amount.`
|
|
1187
|
+
);
|
|
1188
|
+
u.push({ vaultId: k, peginTxHash: x });
|
|
1189
|
+
}
|
|
1190
|
+
const c = G({
|
|
1191
|
+
chain: this.config.ethChain,
|
|
1192
|
+
transport: Z()
|
|
1193
|
+
});
|
|
1194
|
+
let w;
|
|
1195
|
+
try {
|
|
1196
|
+
w = await c.readContract({
|
|
1197
|
+
address: this.config.vaultContracts.btcVaultRegistry,
|
|
1198
|
+
abi: R,
|
|
1199
|
+
functionName: "getPegInFee",
|
|
1200
|
+
args: [n]
|
|
1201
|
+
});
|
|
1202
|
+
} catch {
|
|
973
1203
|
throw new Error(
|
|
974
|
-
|
|
1204
|
+
"Failed to query pegin fee from the contract. Please check your network connection and that the contract address is correct."
|
|
975
1205
|
);
|
|
976
|
-
const t = [];
|
|
977
|
-
for (let n = 0; n < V.length; n++) {
|
|
978
|
-
const s = V[n], o = tn(s), r = new Uint8Array(e.length + 1);
|
|
979
|
-
r.set(e), r[e.length] = n;
|
|
980
|
-
const i = ct(r);
|
|
981
|
-
try {
|
|
982
|
-
const a = en(i, o);
|
|
983
|
-
if (a.config.d !== st)
|
|
984
|
-
throw new Error(
|
|
985
|
-
`Block ${n}: expected d=${st}, got d=${a.config.d}`
|
|
986
|
-
);
|
|
987
|
-
if (a.config.n !== s)
|
|
988
|
-
throw new Error(
|
|
989
|
-
`Block ${n}: expected n=${s}, got n=${a.config.n}`
|
|
990
|
-
);
|
|
991
|
-
if (a.message_terminals.length !== s)
|
|
992
|
-
throw new Error(
|
|
993
|
-
`Block ${n}: expected ${s} message terminals, got ${a.message_terminals.length}`
|
|
994
|
-
);
|
|
995
|
-
for (let l = 0; l < a.message_terminals.length; l++)
|
|
996
|
-
if (a.message_terminals[l].length !== T)
|
|
997
|
-
throw new Error(
|
|
998
|
-
`Block ${n} terminal ${l}: expected ${T} bytes, got ${a.message_terminals[l].length}`
|
|
999
|
-
);
|
|
1000
|
-
if (a.checksum_minor_terminal.length !== T)
|
|
1001
|
-
throw new Error(
|
|
1002
|
-
`Block ${n} checksum_minor: expected ${T} bytes`
|
|
1003
|
-
);
|
|
1004
|
-
if (a.checksum_major_terminal.length !== T)
|
|
1005
|
-
throw new Error(
|
|
1006
|
-
`Block ${n} checksum_major: expected ${T} bytes`
|
|
1007
|
-
);
|
|
1008
|
-
t.push(a);
|
|
1009
|
-
} finally {
|
|
1010
|
-
r.fill(0), i.fill(0);
|
|
1011
|
-
}
|
|
1012
1206
|
}
|
|
1013
|
-
|
|
1207
|
+
const b = w * BigInt(o.length), y = I(
|
|
1208
|
+
r.depositorBtcPubkey
|
|
1209
|
+
), h = I(s), f = o.map((g, E) => ({
|
|
1210
|
+
depositorBtcPubKey: y,
|
|
1211
|
+
btcPopSignature: a,
|
|
1212
|
+
unsignedPrePeginTx: h,
|
|
1213
|
+
depositorSignedPeginTx: I(
|
|
1214
|
+
g.depositorSignedPeginTx
|
|
1215
|
+
),
|
|
1216
|
+
hashlock: g.hashlock,
|
|
1217
|
+
htlcVout: g.htlcVout,
|
|
1218
|
+
referralCode: In,
|
|
1219
|
+
depositorPayoutBtcAddress: l[E],
|
|
1220
|
+
depositorWotsPkHash: g.depositorWotsPkHash
|
|
1221
|
+
})), T = bt({
|
|
1222
|
+
abi: R,
|
|
1223
|
+
functionName: "submitPeginRequestBatch",
|
|
1224
|
+
args: [i, n, f]
|
|
1225
|
+
});
|
|
1226
|
+
let H;
|
|
1227
|
+
try {
|
|
1228
|
+
H = await c.estimateGas({
|
|
1229
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1230
|
+
data: T,
|
|
1231
|
+
value: b,
|
|
1232
|
+
account: this.config.ethWallet.account.address
|
|
1233
|
+
});
|
|
1234
|
+
} catch (g) {
|
|
1235
|
+
S(g);
|
|
1236
|
+
}
|
|
1237
|
+
let d;
|
|
1238
|
+
try {
|
|
1239
|
+
d = await this.config.ethWallet.sendTransaction({
|
|
1240
|
+
to: this.config.vaultContracts.btcVaultRegistry,
|
|
1241
|
+
data: T,
|
|
1242
|
+
value: b,
|
|
1243
|
+
account: this.config.ethWallet.account,
|
|
1244
|
+
chain: this.config.ethChain,
|
|
1245
|
+
gas: H
|
|
1246
|
+
});
|
|
1247
|
+
} catch (g) {
|
|
1248
|
+
S(g);
|
|
1249
|
+
}
|
|
1250
|
+
const P = await c.waitForTransactionReceipt({
|
|
1251
|
+
hash: d,
|
|
1252
|
+
timeout: Ut
|
|
1253
|
+
});
|
|
1254
|
+
return P.status === "reverted" && S(
|
|
1255
|
+
new Error(
|
|
1256
|
+
`Batch transaction reverted. Hash: ${d}. Check the transaction on block explorer for details.`
|
|
1257
|
+
)
|
|
1258
|
+
), {
|
|
1259
|
+
ethTxHash: P.transactionHash,
|
|
1260
|
+
vaults: u
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
/**
|
|
1264
|
+
* Check if a vault already exists for a given vault ID.
|
|
1265
|
+
*
|
|
1266
|
+
* @param vaultId - The Bitcoin transaction hash (vault ID)
|
|
1267
|
+
* @returns True if vault exists, false otherwise
|
|
1268
|
+
*/
|
|
1269
|
+
async checkVaultExists(t) {
|
|
1270
|
+
try {
|
|
1271
|
+
return (await G({
|
|
1272
|
+
chain: this.config.ethChain,
|
|
1273
|
+
transport: Z()
|
|
1274
|
+
}).readContract({
|
|
1275
|
+
address: this.config.vaultContracts.btcVaultRegistry,
|
|
1276
|
+
abi: R,
|
|
1277
|
+
functionName: "getBtcVaultBasicInfo",
|
|
1278
|
+
args: [t]
|
|
1279
|
+
})).depositor !== ce;
|
|
1280
|
+
} catch {
|
|
1281
|
+
return !1;
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Resolve the BTC payout address to a scriptPubKey hex for the contract.
|
|
1286
|
+
*
|
|
1287
|
+
* If a payout address is provided, converts it directly.
|
|
1288
|
+
* If omitted, uses the wallet's address and validates it against the
|
|
1289
|
+
* wallet's public key to guard against a compromised wallet provider.
|
|
1290
|
+
*/
|
|
1291
|
+
async resolvePayoutScriptPubKey(t) {
|
|
1292
|
+
let n;
|
|
1293
|
+
if (t)
|
|
1294
|
+
n = t;
|
|
1295
|
+
else {
|
|
1296
|
+
n = await this.config.btcWallet.getAddress();
|
|
1297
|
+
const o = await this.config.btcWallet.getPublicKeyHex();
|
|
1298
|
+
if (!ge(
|
|
1299
|
+
n,
|
|
1300
|
+
o,
|
|
1301
|
+
this.config.btcNetwork
|
|
1302
|
+
))
|
|
1303
|
+
throw new Error(
|
|
1304
|
+
"The BTC address from your wallet does not match the wallet's public key. Please ensure your wallet is using a supported address type (Taproot or Native SegWit)."
|
|
1305
|
+
);
|
|
1306
|
+
}
|
|
1307
|
+
const s = Pt(this.config.btcNetwork);
|
|
1308
|
+
try {
|
|
1309
|
+
return `0x${Vt.address.toOutputScript(n, s).toString("hex")}`;
|
|
1310
|
+
} catch {
|
|
1014
1311
|
throw new Error(
|
|
1015
|
-
`
|
|
1312
|
+
`Invalid BTC payout address: "${n}". Please provide a valid Bitcoin address for the ${this.config.btcNetwork} network.`
|
|
1016
1313
|
);
|
|
1017
|
-
|
|
1018
|
-
} finally {
|
|
1019
|
-
e.fill(0);
|
|
1314
|
+
}
|
|
1020
1315
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1316
|
+
/**
|
|
1317
|
+
* Sign a BIP-322 BTC Proof-of-Possession binding the connected BTC
|
|
1318
|
+
* wallet to the connected ETH account for this chain and vault
|
|
1319
|
+
* registry. The returned {@link PopSignature} can be reused across
|
|
1320
|
+
* every register call in the same session.
|
|
1321
|
+
*/
|
|
1322
|
+
async signProofOfPossession() {
|
|
1323
|
+
if (!this.config.ethWallet.account)
|
|
1324
|
+
throw new Error("Ethereum wallet account not found");
|
|
1325
|
+
const t = this.config.ethWallet.account.address, n = U(
|
|
1326
|
+
await this.config.btcWallet.getPublicKeyHex()
|
|
1327
|
+
), s = this.config.vaultContracts.btcVaultRegistry, o = `${t.toLowerCase()}:${this.config.ethChain.id}:pegin:${s.toLowerCase()}`, r = await this.config.btcWallet.signMessage(
|
|
1328
|
+
o,
|
|
1329
|
+
"bip322-simple"
|
|
1026
1330
|
);
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1331
|
+
return {
|
|
1332
|
+
btcPopSignature: _n(r),
|
|
1333
|
+
depositorEthAddress: t,
|
|
1334
|
+
depositorBtcPubkey: n
|
|
1335
|
+
};
|
|
1336
|
+
}
|
|
1337
|
+
async assertPopMatchesBtcWallet(t) {
|
|
1338
|
+
const n = U(
|
|
1339
|
+
await this.config.btcWallet.getPublicKeyHex()
|
|
1340
|
+
), s = U(t.depositorBtcPubkey);
|
|
1341
|
+
if (n !== s)
|
|
1030
1342
|
throw new Error(
|
|
1031
|
-
`
|
|
1343
|
+
`Proof of possession was signed with BTC pubkey ${s} but the BTC wallet is currently connected to ${n}. Reconnect the original wallet or call signProofOfPossession() again.`
|
|
1032
1344
|
);
|
|
1033
1345
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
for (let a = 0; a < i.message_terminals.length; a++)
|
|
1042
|
-
Y(i.message_terminals[a], r, `message_terminal[${a}]`);
|
|
1043
|
-
}
|
|
1044
|
-
let t = 0;
|
|
1045
|
-
for (const r of e)
|
|
1046
|
-
t += Xt + r.message_terminals.length;
|
|
1047
|
-
const n = new Uint8Array(t * T);
|
|
1048
|
-
let s = 0;
|
|
1049
|
-
for (const r of e) {
|
|
1050
|
-
n.set(r.checksum_minor_terminal, s), s += T, n.set(r.checksum_major_terminal, s), s += T;
|
|
1051
|
-
for (const i of r.message_terminals)
|
|
1052
|
-
n.set(i, s), s += T;
|
|
1053
|
-
}
|
|
1054
|
-
const o = Ze(n);
|
|
1055
|
-
return `0x${Je(o)}`;
|
|
1056
|
-
}
|
|
1057
|
-
function $n(e) {
|
|
1058
|
-
const t = (e instanceof Error ? e.message : typeof e == "string" ? e : "").toLowerCase();
|
|
1059
|
-
return t.includes("wots") && t.includes("hash") && t.includes("does not match");
|
|
1060
|
-
}
|
|
1061
|
-
class Kt {
|
|
1062
|
-
constructor(t, n) {
|
|
1063
|
-
p(this, "oHash");
|
|
1064
|
-
p(this, "iHash");
|
|
1065
|
-
p(this, "blockLen");
|
|
1066
|
-
p(this, "outputLen");
|
|
1067
|
-
p(this, "finished", !1);
|
|
1068
|
-
p(this, "destroyed", !1);
|
|
1069
|
-
if (Ot(t), U(n, void 0, "key"), this.iHash = t.create(), typeof this.iHash.update != "function")
|
|
1070
|
-
throw new Error("Expected instance of class which extends utils.Hash");
|
|
1071
|
-
this.blockLen = this.iHash.blockLen, this.outputLen = this.iHash.outputLen;
|
|
1072
|
-
const s = this.blockLen, o = new Uint8Array(s);
|
|
1073
|
-
o.set(n.length > s ? t.create().update(n).digest() : n);
|
|
1074
|
-
for (let r = 0; r < o.length; r++)
|
|
1075
|
-
o[r] ^= 54;
|
|
1076
|
-
this.iHash.update(o), this.oHash = t.create();
|
|
1077
|
-
for (let r = 0; r < o.length; r++)
|
|
1078
|
-
o[r] ^= 106;
|
|
1079
|
-
this.oHash.update(o), H(o);
|
|
1080
|
-
}
|
|
1081
|
-
update(t) {
|
|
1082
|
-
return F(this), this.iHash.update(t), this;
|
|
1083
|
-
}
|
|
1084
|
-
digestInto(t) {
|
|
1085
|
-
F(this), U(t, this.outputLen, "output"), this.finished = !0, this.iHash.digestInto(t), this.oHash.update(t), this.oHash.digestInto(t), this.destroy();
|
|
1086
|
-
}
|
|
1087
|
-
digest() {
|
|
1088
|
-
const t = new Uint8Array(this.oHash.outputLen);
|
|
1089
|
-
return this.digestInto(t), t;
|
|
1090
|
-
}
|
|
1091
|
-
_cloneInto(t) {
|
|
1092
|
-
t || (t = Object.create(Object.getPrototypeOf(this), {}));
|
|
1093
|
-
const { oHash: n, iHash: s, finished: o, destroyed: r, blockLen: i, outputLen: a } = this;
|
|
1094
|
-
return t = t, t.finished = o, t.destroyed = r, t.blockLen = i, t.outputLen = a, t.oHash = n._cloneInto(t.oHash), t.iHash = s._cloneInto(t.iHash), t;
|
|
1095
|
-
}
|
|
1096
|
-
clone() {
|
|
1097
|
-
return this._cloneInto();
|
|
1346
|
+
/**
|
|
1347
|
+
* Gets the configured Bitcoin network.
|
|
1348
|
+
*
|
|
1349
|
+
* @returns The Bitcoin network (mainnet, testnet, signet, regtest)
|
|
1350
|
+
*/
|
|
1351
|
+
getNetwork() {
|
|
1352
|
+
return this.config.btcNetwork;
|
|
1098
1353
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1354
|
+
/**
|
|
1355
|
+
* Gets the configured BTCVaultRegistry contract address.
|
|
1356
|
+
*
|
|
1357
|
+
* @returns The Ethereum address of the BTCVaultRegistry contract
|
|
1358
|
+
*/
|
|
1359
|
+
getVaultContractAddress() {
|
|
1360
|
+
return this.config.vaultContracts.btcVaultRegistry;
|
|
1101
1361
|
}
|
|
1102
1362
|
}
|
|
1103
|
-
const jt = (e, t, n) => new Kt(e, t).update(n).digest();
|
|
1104
|
-
jt.create = (e, t) => new Kt(e, t);
|
|
1105
|
-
const J = /* @__PURE__ */ Uint8Array.of(0), _t = /* @__PURE__ */ Uint8Array.of();
|
|
1106
|
-
function lt(e, t, n, s = 32) {
|
|
1107
|
-
Ot(e), nt(s, "length");
|
|
1108
|
-
const o = e.outputLen;
|
|
1109
|
-
if (s > 255 * o)
|
|
1110
|
-
throw new Error("Length must be <= 255*HashLen");
|
|
1111
|
-
const r = Math.ceil(s / o);
|
|
1112
|
-
n === void 0 ? n = _t : U(n, void 0, "info");
|
|
1113
|
-
const i = new Uint8Array(r * o), a = jt.create(e, t), l = a._cloneInto(), h = new Uint8Array(a.outputLen);
|
|
1114
|
-
for (let c = 0; c < r; c++)
|
|
1115
|
-
J[0] = c + 1, l.update(c === 0 ? _t : h).update(n).update(J).digestInto(h), i.set(h, o * c), a._cloneInto(l);
|
|
1116
|
-
return a.destroy(), l.destroy(), H(h, J), i.slice(0, s);
|
|
1117
|
-
}
|
|
1118
|
-
const Q = new TextEncoder().encode("babylonvault"), It = 255, vt = 65535, Bt = 2, nn = "hashlock", sn = "auth-anchor", on = "wots-seed";
|
|
1119
|
-
function qt(e) {
|
|
1120
|
-
if (!Number.isInteger(e) || e < 0 || e > 4294967295)
|
|
1121
|
-
throw new Error(`i2osp4: value must be a u32, got ${e}`);
|
|
1122
|
-
const t = new Uint8Array(4);
|
|
1123
|
-
return t[0] = e >>> 24 & 255, t[1] = e >>> 16 & 255, t[2] = e >>> 8 & 255, t[3] = e & 255, t;
|
|
1124
|
-
}
|
|
1125
|
-
function ht(e, t = new Uint8Array(0)) {
|
|
1126
|
-
const n = new TextEncoder().encode(e);
|
|
1127
|
-
if (n.length === 0 || n.length > It)
|
|
1128
|
-
throw new Error(
|
|
1129
|
-
`info: label length must be in [1, ${It}], got ${n.length}`
|
|
1130
|
-
);
|
|
1131
|
-
if (t.length > vt)
|
|
1132
|
-
throw new Error(
|
|
1133
|
-
`info: ctx length must be in [0, ${vt}], got ${t.length}`
|
|
1134
|
-
);
|
|
1135
|
-
const s = Q.length + 1 + n.length + Bt + t.length, o = new Uint8Array(s);
|
|
1136
|
-
let r = 0;
|
|
1137
|
-
return o.set(Q, r), r += Q.length, o[r] = n.length, r += 1, o.set(n, r), r += n.length, o[r] = t.length >>> 8 & 255, o[r + 1] = t.length & 255, r += Bt, o.set(t, r), o;
|
|
1138
|
-
}
|
|
1139
|
-
const At = 32, rn = 32, an = 32, cn = 64;
|
|
1140
|
-
function ut(e) {
|
|
1141
|
-
if (e.length !== At)
|
|
1142
|
-
throw new Error(
|
|
1143
|
-
`vault-secrets: root must be exactly ${At} bytes, got ${e.length}`
|
|
1144
|
-
);
|
|
1145
|
-
}
|
|
1146
|
-
function Rn(e) {
|
|
1147
|
-
return ut(e), lt(
|
|
1148
|
-
L,
|
|
1149
|
-
e,
|
|
1150
|
-
ht(sn),
|
|
1151
|
-
rn
|
|
1152
|
-
);
|
|
1153
|
-
}
|
|
1154
|
-
function Un(e, t) {
|
|
1155
|
-
return ut(e), lt(
|
|
1156
|
-
L,
|
|
1157
|
-
e,
|
|
1158
|
-
ht(nn, qt(t)),
|
|
1159
|
-
an
|
|
1160
|
-
);
|
|
1161
|
-
}
|
|
1162
|
-
function Ln(e, t) {
|
|
1163
|
-
return ut(e), lt(
|
|
1164
|
-
L,
|
|
1165
|
-
e,
|
|
1166
|
-
ht(on, qt(t)),
|
|
1167
|
-
cn
|
|
1168
|
-
);
|
|
1169
|
-
}
|
|
1170
|
-
const R = 32, tt = 32, ot = 36, Gt = 32, X = 4, ln = X + R + X + Gt;
|
|
1171
|
-
function rt(e, t, n) {
|
|
1172
|
-
e[t] = n >>> 24 & 255, e[t + 1] = n >>> 16 & 255, e[t + 2] = n >>> 8 & 255, e[t + 3] = n & 255;
|
|
1173
|
-
}
|
|
1174
|
-
function hn(e) {
|
|
1175
|
-
if (e.txid.length !== tt)
|
|
1176
|
-
throw new Error(
|
|
1177
|
-
`outpoint.txid must be exactly ${tt} bytes, got ${e.txid.length}`
|
|
1178
|
-
);
|
|
1179
|
-
if (!Number.isInteger(e.vout) || e.vout < 0 || e.vout > 4294967295)
|
|
1180
|
-
throw new Error(`outpoint.vout must be a u32, got ${e.vout}`);
|
|
1181
|
-
const t = new Uint8Array(ot);
|
|
1182
|
-
return t.set(e.txid, 0), rt(t, tt, e.vout), t;
|
|
1183
|
-
}
|
|
1184
|
-
function Ht(e, t) {
|
|
1185
|
-
const n = Math.min(e.length, t.length);
|
|
1186
|
-
for (let s = 0; s < n; s++)
|
|
1187
|
-
if (e[s] !== t[s]) return e[s] - t[s];
|
|
1188
|
-
return e.length - t.length;
|
|
1189
|
-
}
|
|
1190
|
-
function un(e) {
|
|
1191
|
-
if (e.length === 0)
|
|
1192
|
-
throw new Error(
|
|
1193
|
-
"buildFundingOutpointsCommitment: outpoints must be non-empty"
|
|
1194
|
-
);
|
|
1195
|
-
const t = e.map(hn);
|
|
1196
|
-
t.sort(Ht);
|
|
1197
|
-
for (let s = 1; s < t.length; s++)
|
|
1198
|
-
if (Ht(t[s - 1], t[s]) === 0)
|
|
1199
|
-
throw new Error(
|
|
1200
|
-
"buildFundingOutpointsCommitment: duplicate outpoint detected"
|
|
1201
|
-
);
|
|
1202
|
-
const n = new Uint8Array(t.length * ot);
|
|
1203
|
-
for (let s = 0; s < t.length; s++)
|
|
1204
|
-
n.set(t[s], s * ot);
|
|
1205
|
-
return L(n);
|
|
1206
|
-
}
|
|
1207
|
-
function dn(e) {
|
|
1208
|
-
if (e.depositorBtcPubkey.length !== R)
|
|
1209
|
-
throw new Error(
|
|
1210
|
-
`vaultContext: depositorBtcPubkey must be exactly ${R} bytes, got ${e.depositorBtcPubkey.length}`
|
|
1211
|
-
);
|
|
1212
|
-
const t = un(e.fundingOutpoints), n = new Uint8Array(ln);
|
|
1213
|
-
let s = 0;
|
|
1214
|
-
return rt(n, s, R), s += X, n.set(e.depositorBtcPubkey, s), s += R, rt(n, s, Gt), s += X, n.set(t, s), n;
|
|
1215
|
-
}
|
|
1216
|
-
const fn = "babylon-vault", Zt = 32, Ct = Zt * 2, gn = /^[0-9a-f]+$/;
|
|
1217
|
-
async function Wn(e, t) {
|
|
1218
|
-
const n = dn(t), s = le(n), o = await e.deriveContextHash(fn, s);
|
|
1219
|
-
if (typeof o != "string")
|
|
1220
|
-
throw new Error(
|
|
1221
|
-
`deriveVaultRoot: wallet must return a string, got ${typeof o}`
|
|
1222
|
-
);
|
|
1223
|
-
if (o.length !== Ct)
|
|
1224
|
-
throw new Error(
|
|
1225
|
-
`deriveVaultRoot: wallet must return a ${Ct}-character hex string (${Zt} bytes), got length ${o.length}`
|
|
1226
|
-
);
|
|
1227
|
-
if (!gn.test(o))
|
|
1228
|
-
throw new Error(
|
|
1229
|
-
"deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters"
|
|
1230
|
-
);
|
|
1231
|
-
return he(o);
|
|
1232
|
-
}
|
|
1233
1363
|
export {
|
|
1234
1364
|
C,
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1365
|
+
jn as P,
|
|
1366
|
+
De as V,
|
|
1367
|
+
Kn as a,
|
|
1368
|
+
Ne as b,
|
|
1369
|
+
xn as c,
|
|
1370
|
+
yn as d,
|
|
1371
|
+
gt as e,
|
|
1372
|
+
Ve as f,
|
|
1373
|
+
Dn as g,
|
|
1374
|
+
S as h,
|
|
1375
|
+
zn as i,
|
|
1376
|
+
We as j,
|
|
1377
|
+
Xe as k,
|
|
1378
|
+
Ke as l,
|
|
1379
|
+
je as m
|
|
1250
1380
|
};
|
|
1251
|
-
//# sourceMappingURL=
|
|
1381
|
+
//# sourceMappingURL=PeginManager-Dj6oDaH5.js.map
|