@babylonlabs-io/ts-sdk 0.66.1 → 0.68.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--2R3T2S8.js +1458 -0
- package/dist/PeginManager--2R3T2S8.js.map +1 -0
- package/dist/PeginManager-CKWq8ouZ.cjs +2 -0
- package/dist/PeginManager-CKWq8ouZ.cjs.map +1 -0
- package/dist/{batchPoll-cIxrSLLJ.js → batchPoll-Cjj1du0i.js} +372 -421
- package/dist/batchPoll-Cjj1du0i.js.map +1 -0
- package/dist/batchPoll-REVZiE-M.cjs +2 -0
- package/dist/batchPoll-REVZiE-M.cjs.map +1 -0
- package/dist/{bitcoin-d9eaaZB_.js → bitcoin-Ch_jxnDa.js} +3 -3
- package/dist/{bitcoin-d9eaaZB_.js.map → bitcoin-Ch_jxnDa.js.map} +1 -1
- package/dist/{buildAndBroadcastRefund-C4LiPATK.js → buildAndBroadcastRefund-CpMDJ8up.js} +142 -150
- package/dist/buildAndBroadcastRefund-CpMDJ8up.js.map +1 -0
- package/dist/buildAndBroadcastRefund-DrXwxrW1.cjs +2 -0
- package/dist/buildAndBroadcastRefund-DrXwxrW1.cjs.map +1 -0
- package/dist/challengeAssert-BNQ8sToz.js +64 -0
- package/dist/challengeAssert-BNQ8sToz.js.map +1 -0
- package/dist/challengeAssert-BrpC3-cQ.cjs +2 -0
- package/dist/challengeAssert-BrpC3-cQ.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +246 -243
- package/dist/mempoolApi-EU1La9wk.cjs +2 -0
- package/dist/{mempoolApi-CXfr-L6x.cjs.map → mempoolApi-EU1La9wk.cjs.map} +1 -1
- package/dist/{mempoolApi-BxSINXIB.js → mempoolApi-_D-jvtj_.js} +191 -117
- package/dist/{mempoolApi-BxSINXIB.js.map → mempoolApi-_D-jvtj_.js.map} +1 -1
- package/dist/{noPayout-BaZGRLD2.js → noPayout-CXn-geIS.js} +3 -3
- package/dist/{noPayout-BaZGRLD2.js.map → noPayout-CXn-geIS.js.map} +1 -1
- package/dist/{noPayout-CnQ1WLtr.cjs → noPayout-Ox27Td9x.cjs} +2 -2
- package/dist/{noPayout-CnQ1WLtr.cjs.map → noPayout-Ox27Td9x.cjs.map} +1 -1
- package/dist/{onChainBtcPubkey-DeF4cKoO.js → onChainBtcPubkey-BAHZyKQL.js} +2 -2
- package/dist/{onChainBtcPubkey-DeF4cKoO.js.map → onChainBtcPubkey-BAHZyKQL.js.map} +1 -1
- package/dist/{parseFundingOutpoints-pBRE11Hr.js → parseFundingOutpoints-CO-f6IHK.js} +2 -2
- package/dist/{parseFundingOutpoints-pBRE11Hr.js.map → parseFundingOutpoints-CO-f6IHK.js.map} +1 -1
- package/dist/{reservation-B4i_PQhY.js → reservation-CBAvoF3U.js} +2 -2
- package/dist/{reservation-B4i_PQhY.js.map → reservation-CBAvoF3U.js.map} +1 -1
- package/dist/{signPsbtsWithFallback-Bb66DfY5.js → signPsbtsWithFallback-Bv79gLFe.js} +122 -100
- package/dist/signPsbtsWithFallback-Bv79gLFe.js.map +1 -0
- package/dist/signPsbtsWithFallback-DJ4kE9UI.cjs +2 -0
- package/dist/signPsbtsWithFallback-DJ4kE9UI.cjs.map +1 -0
- package/dist/tbv/core/clients/index.cjs +1 -1
- package/dist/tbv/core/clients/index.js +3 -3
- package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322P2wpkhVectors.d.ts +32 -0
- package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322P2wpkhVectors.d.ts.map +1 -0
- package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322Verify.test.d.ts +9 -6
- package/dist/tbv/core/clients/vault-provider/auth/__tests__/bip322Verify.test.d.ts.map +1 -1
- package/dist/tbv/core/clients/vault-provider/auth/bip322Verify.d.ts +45 -20
- package/dist/tbv/core/clients/vault-provider/auth/bip322Verify.d.ts.map +1 -1
- package/dist/tbv/core/deposit-terms/__tests__/depositTerms.test.d.ts +2 -0
- package/dist/tbv/core/deposit-terms/__tests__/depositTerms.test.d.ts.map +1 -0
- package/dist/tbv/core/deposit-terms/depositTerms.d.ts +42 -5
- package/dist/tbv/core/deposit-terms/depositTerms.d.ts.map +1 -1
- package/dist/tbv/core/deposit-terms/prePeginApproval.d.ts +10 -5
- package/dist/tbv/core/deposit-terms/prePeginApproval.d.ts.map +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.js +244 -241
- package/dist/tbv/core/managers/PayoutManager.d.ts +8 -2
- package/dist/tbv/core/managers/PayoutManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/PeginManager.d.ts +7 -0
- package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/managers/pegin/__tests__/verifyPopWitness.test.d.ts +11 -0
- package/dist/tbv/core/managers/pegin/__tests__/verifyPopWitness.test.d.ts.map +1 -0
- package/dist/tbv/core/managers/pegin/expandPerVaultSecrets.d.ts.map +1 -1
- package/dist/tbv/core/managers/pegin/index.d.ts +1 -0
- package/dist/tbv/core/managers/pegin/index.d.ts.map +1 -1
- package/dist/tbv/core/managers/pegin/verifyPopWitness.d.ts +21 -0
- package/dist/tbv/core/managers/pegin/verifyPopWitness.d.ts.map +1 -0
- package/dist/tbv/core/primitives/challengers.d.ts +31 -5
- package/dist/tbv/core/primitives/challengers.d.ts.map +1 -1
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.d.ts +2 -0
- package/dist/tbv/core/primitives/index.d.ts.map +1 -1
- package/dist/tbv/core/primitives/index.js +43 -41
- package/dist/tbv/core/primitives/psbt/__tests__/helpers.d.ts +5 -0
- package/dist/tbv/core/primitives/psbt/__tests__/helpers.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/__tests__/verifyKeyPathSchnorrSignature.test.d.ts +12 -0
- package/dist/tbv/core/primitives/psbt/__tests__/verifyKeyPathSchnorrSignature.test.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/payout.d.ts +19 -7
- package/dist/tbv/core/primitives/psbt/payout.d.ts.map +1 -1
- package/dist/tbv/core/primitives/psbt/pegin.d.ts +2 -2
- package/dist/tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature.d.ts +64 -0
- package/dist/tbv/core/primitives/psbt/verifyKeyPathSchnorrSignature.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature.d.ts +40 -0
- package/dist/tbv/core/primitives/psbt/verifyP2wpkhEcdsaSignature.d.ts.map +1 -0
- package/dist/tbv/core/primitives/psbt/verifyScriptPathSchnorrSignature.d.ts +2 -1
- package/dist/tbv/core/primitives/psbt/verifyScriptPathSchnorrSignature.d.ts.map +1 -1
- package/dist/tbv/core/primitives/utils/__tests__/taproot.test.d.ts +13 -0
- package/dist/tbv/core/primitives/utils/__tests__/taproot.test.d.ts.map +1 -0
- package/dist/tbv/core/primitives/utils/taproot.d.ts +29 -0
- package/dist/tbv/core/primitives/utils/taproot.d.ts.map +1 -0
- package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts +2 -2
- package/dist/tbv/core/services/deposit/runDepositorPresignFlow.d.ts.map +1 -1
- package/dist/tbv/core/services/deposit/signDepositorGraph.d.ts.map +1 -1
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +2 -2
- package/dist/tbv/core/utils/index.js +2 -2
- package/dist/tbv/core/utils/witness/witnessStack.d.ts +24 -0
- package/dist/tbv/core/utils/witness/witnessStack.d.ts.map +1 -0
- package/dist/tbv/core/vault-secrets/index.js +1 -1
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +244 -241
- package/dist/tbv/integrations/aave/clients/__tests__/query.test.d.ts +11 -0
- package/dist/tbv/integrations/aave/clients/__tests__/query.test.d.ts.map +1 -0
- package/dist/tbv/integrations/aave/clients/query.d.ts.map +1 -1
- package/dist/tbv/integrations/aave/index.cjs +1 -1
- package/dist/tbv/integrations/aave/index.cjs.map +1 -1
- package/dist/tbv/integrations/aave/index.js +132 -114
- package/dist/tbv/integrations/aave/index.js.map +1 -1
- package/dist/testing/MockBitcoinWallet.d.ts +10 -1
- package/dist/testing/MockBitcoinWallet.d.ts.map +1 -1
- package/dist/testing/__tests__/MockBitcoinWallet.test.d.ts +2 -0
- package/dist/testing/__tests__/MockBitcoinWallet.test.d.ts.map +1 -0
- package/dist/testing/index.cjs +1 -1
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.js +134 -47
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/signBip322P2wpkhWitness.d.ts +20 -0
- package/dist/testing/signBip322P2wpkhWitness.d.ts.map +1 -0
- package/dist/{toRefundInputs-BY_fcvrv.js → toRefundInputs-9hv_6k0E.js} +6 -6
- package/dist/{toRefundInputs-BY_fcvrv.js.map → toRefundInputs-9hv_6k0E.js.map} +1 -1
- package/dist/{toRefundInputs-DYL9C-aG.cjs → toRefundInputs-D8sFs44p.cjs} +2 -2
- package/dist/{toRefundInputs-DYL9C-aG.cjs.map → toRefundInputs-D8sFs44p.cjs.map} +1 -1
- package/dist/verifyKeyPathSchnorrSignature-DCOzQkDf.cjs +2 -0
- package/dist/verifyKeyPathSchnorrSignature-DCOzQkDf.cjs.map +1 -0
- package/dist/verifyKeyPathSchnorrSignature-oGCUbjjZ.js +363 -0
- package/dist/verifyKeyPathSchnorrSignature-oGCUbjjZ.js.map +1 -0
- package/dist/verifyScriptPathSchnorrSignature-Dy9gF5RF.js +931 -0
- package/dist/verifyScriptPathSchnorrSignature-Dy9gF5RF.js.map +1 -0
- package/dist/verifyScriptPathSchnorrSignature-la8XOAFm.cjs +2 -0
- package/dist/verifyScriptPathSchnorrSignature-la8XOAFm.cjs.map +1 -0
- package/package.json +2 -2
- package/dist/PeginManager-BBl4xkWz.js +0 -1359
- package/dist/PeginManager-BBl4xkWz.js.map +0 -1
- package/dist/PeginManager-p-ajwSxG.cjs +0 -2
- package/dist/PeginManager-p-ajwSxG.cjs.map +0 -1
- package/dist/batchPoll-6L5oToGr.cjs +0 -2
- package/dist/batchPoll-6L5oToGr.cjs.map +0 -1
- package/dist/batchPoll-cIxrSLLJ.js.map +0 -1
- package/dist/buildAndBroadcastRefund-C4LiPATK.js.map +0 -1
- package/dist/buildAndBroadcastRefund-Daw5ZUKR.cjs +0 -2
- package/dist/buildAndBroadcastRefund-Daw5ZUKR.cjs.map +0 -1
- package/dist/challengeAssert-BFRE2DM-.cjs +0 -2
- package/dist/challengeAssert-BFRE2DM-.cjs.map +0 -1
- package/dist/challengeAssert-C7PzyJ7g.js +0 -75
- package/dist/challengeAssert-C7PzyJ7g.js.map +0 -1
- package/dist/mempoolApi-CXfr-L6x.cjs +0 -2
- package/dist/peginInput-Ci921gTl.cjs +0 -2
- package/dist/peginInput-Ci921gTl.cjs.map +0 -1
- package/dist/peginInput-HQPWZfly.js +0 -123
- package/dist/peginInput-HQPWZfly.js.map +0 -1
- package/dist/signPsbtsWithFallback-Bb66DfY5.js.map +0 -1
- package/dist/signPsbtsWithFallback-PTgWxsG3.cjs +0 -2
- package/dist/signPsbtsWithFallback-PTgWxsG3.cjs.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-DPAd_qke.cjs +0 -2
- package/dist/verifyScriptPathSchnorrSignature-DPAd_qke.cjs.map +0 -1
- package/dist/verifyScriptPathSchnorrSignature-i-koT139.js +0 -817
- package/dist/verifyScriptPathSchnorrSignature-i-koT139.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onChainBtcPubkey-
|
|
1
|
+
{"version":3,"file":"onChainBtcPubkey-BAHZyKQL.js","sources":["../src/tbv/core/clients/eth/onChainBtcPubkey.ts"],"sourcesContent":["/**\n * The single validator that mints {@link OnChainBtcPubkey}.\n *\n * Extracted from `ViemVaultRegistryReader.getVaultProviderGenesisBtcPubKey` so that\n * RFC-006 operation-key resolution can produce branded keys through exactly\n * the same checks, rather than casting past the brand. Every producer of an\n * `OnChainBtcPubkey` must go through here.\n */\n\nimport * as ecc from \"@bitcoin-js/tiny-secp256k1-asmjs\";\nimport type { Hex } from \"viem\";\n\nimport { hexToUint8Array } from \"../../primitives/utils/bitcoin\";\nimport type { OnChainBtcPubkey } from \"./types\";\n\n/**\n * Validate a registry-returned `bytes32` as an x-only BTC pubkey and mint the\n * brand. Checks length, hex form, and secp256k1 curve membership. Returns\n * 64-char lowercase hex without the `0x` prefix.\n *\n * `label` identifies the read site in error messages (e.g.\n * `getOperationBtcKeyAtEpoch (vp=0x…, epoch=0)`), so a failure names which\n * participant and which getter produced it.\n *\n * A zero hash fails the curve check, so an unregistered operator or an epoch\n * with no bonded key surfaces as an error rather than a silent all-zero key.\n */\nexport function assertOnChainBtcPubkey(\n value: Hex,\n label: string,\n): OnChainBtcPubkey {\n const lowered = value.toLowerCase();\n if (!/^0x[0-9a-f]{64}$/.test(lowered)) {\n throw new Error(\n `${label} returned an unexpected value (length ${lowered.length}, prefix \"${lowered.slice(0, 2)}\")`,\n );\n }\n const stripped = lowered.slice(2);\n if (!ecc.isXOnlyPoint(hexToUint8Array(stripped))) {\n throw new Error(\n `${label} returned a value that is not on the secp256k1 curve`,\n );\n }\n return stripped as OnChainBtcPubkey;\n}\n"],"names":["assertOnChainBtcPubkey","value","label","lowered","stripped","ecc","hexToUint8Array"],"mappings":";;AA2BO,SAASA,EACdC,GACAC,GACkB;AAClB,QAAMC,IAAUF,EAAM,YAAA;AACtB,MAAI,CAAC,mBAAmB,KAAKE,CAAO;AAClC,UAAM,IAAI;AAAA,MACR,GAAGD,CAAK,yCAAyCC,EAAQ,MAAM,aAAaA,EAAQ,MAAM,GAAG,CAAC,CAAC;AAAA,IAAA;AAGnG,QAAMC,IAAWD,EAAQ,MAAM,CAAC;AAChC,MAAI,CAACE,EAAI,aAAaC,EAAgBF,CAAQ,CAAC;AAC7C,UAAM,IAAI;AAAA,MACR,GAAGF,CAAK;AAAA,IAAA;AAGZ,SAAOE;AACT;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { u as d, h as E } from "./bitcoin-
|
|
1
|
+
import { u as d, h as E } from "./bitcoin-Ch_jxnDa.js";
|
|
2
2
|
import { s as w } from "./sha2-BYVxyZzX.js";
|
|
3
3
|
import { Transaction as g } from "bitcoinjs-lib";
|
|
4
4
|
import { Buffer as x } from "buffer";
|
|
@@ -89,4 +89,4 @@ export {
|
|
|
89
89
|
I as f,
|
|
90
90
|
R as p
|
|
91
91
|
};
|
|
92
|
-
//# sourceMappingURL=parseFundingOutpoints-
|
|
92
|
+
//# sourceMappingURL=parseFundingOutpoints-CO-f6IHK.js.map
|
package/dist/{parseFundingOutpoints-pBRE11Hr.js.map → parseFundingOutpoints-CO-f6IHK.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parseFundingOutpoints-pBRE11Hr.js","sources":["../src/tbv/core/vault-secrets/context.ts","../src/tbv/core/vault-secrets/deriveVaultRoot.ts","../src/tbv/core/vault-secrets/parseFundingOutpoints.ts"],"sourcesContent":["/**\n * Canonical `vaultContext` byte encoding per\n * `derive-vault-secrets.md` §2.3.\n *\n * ```\n * vaultContext :=\n * I2OSP(32, 4) || depositorBtcPubkey // 32B x-only\n * || I2OSP(32, 4) || fundingOutpointsCommitment // 32B SHA-256\n * ```\n *\n * `fundingOutpointsCommitment` is SHA-256 over the canonically-sorted\n * funding outpoints of the Pre-PegIn transaction, serialized as\n * `txid (32B display/RPC order) || vout (4B u32 big-endian)` per\n * outpoint. Sorting by 36-byte lex order makes the commitment\n * invariant under tx-level input reordering, so same-inputs RBF and\n * reorg rebroadcasts yield the same context.\n *\n * @module vault-secrets/context\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\nconst DEPOSITOR_PUBKEY_SIZE = 32;\nconst TXID_SIZE = 32;\nconst OUTPOINT_SIZE = 36;\nconst COMMITMENT_SIZE = 32;\nconst FIELD_LEN_PREFIX_SIZE = 4;\nconst VAULT_CONTEXT_SIZE =\n FIELD_LEN_PREFIX_SIZE +\n DEPOSITOR_PUBKEY_SIZE +\n FIELD_LEN_PREFIX_SIZE +\n COMMITMENT_SIZE;\n\nexport interface FundingOutpoint {\n /**\n * Bitcoin txid in **display / RPC order** (byte-reversed from the\n * internal little-endian wire form used when hashing a raw tx).\n */\n txid: Uint8Array;\n /** Output index within the referenced transaction (u32). */\n vout: number;\n}\n\nexport interface VaultContextInput {\n /** Depositor's x-only BTC public key (32 bytes). */\n depositorBtcPubkey: Uint8Array;\n /** Funding outpoints of the Pre-PegIn transaction. MUST be non-empty. */\n fundingOutpoints: readonly FundingOutpoint[];\n}\n\nfunction writeUint32BE(out: Uint8Array, offset: number, value: number): void {\n out[offset] = (value >>> 24) & 0xff;\n out[offset + 1] = (value >>> 16) & 0xff;\n out[offset + 2] = (value >>> 8) & 0xff;\n out[offset + 3] = value & 0xff;\n}\n\nfunction serializeOutpoint(outpoint: FundingOutpoint): Uint8Array {\n if (outpoint.txid.length !== TXID_SIZE) {\n throw new Error(\n `outpoint.txid must be exactly ${TXID_SIZE} bytes, got ${outpoint.txid.length}`,\n );\n }\n if (\n !Number.isInteger(outpoint.vout) ||\n outpoint.vout < 0 ||\n outpoint.vout > 0xffffffff\n ) {\n throw new Error(`outpoint.vout must be a u32, got ${outpoint.vout}`);\n }\n const out = new Uint8Array(OUTPOINT_SIZE);\n out.set(outpoint.txid, 0);\n writeUint32BE(out, TXID_SIZE, outpoint.vout);\n return out;\n}\n\nfunction compareBytes(a: Uint8Array, b: Uint8Array): number {\n const len = Math.min(a.length, b.length);\n for (let i = 0; i < len; i++) {\n if (a[i] !== b[i]) return a[i] - b[i];\n }\n return a.length - b.length;\n}\n\n/**\n * Compute SHA-256 over canonically-sorted funding outpoints.\n *\n * Outpoints are serialized as 36-byte `txid || vout_BE`, sorted\n * ascending lexicographically, concatenated, then hashed.\n *\n * @stability frozen — on-chain-binding. Any change to layout, sort\n * order, or serialization is a hard fork; existing deposits would no\n * longer match their committed `depositorWotsPkHash`.\n *\n * @throws If `outpoints` is empty or contains duplicates.\n */\nexport function buildFundingOutpointsCommitment(\n outpoints: readonly FundingOutpoint[],\n): Uint8Array {\n if (outpoints.length === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: outpoints must be non-empty\",\n );\n }\n const serialized = outpoints.map(serializeOutpoint);\n serialized.sort(compareBytes);\n\n for (let i = 1; i < serialized.length; i++) {\n if (compareBytes(serialized[i - 1], serialized[i]) === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: duplicate outpoint detected\",\n );\n }\n }\n\n const flat = new Uint8Array(serialized.length * OUTPOINT_SIZE);\n for (let i = 0; i < serialized.length; i++) {\n flat.set(serialized[i], i * OUTPOINT_SIZE);\n }\n return sha256(flat);\n}\n\n/**\n * Build the canonical `vaultContext` byte string fed into the wallet's\n * `deriveContextHash` (or a locally-implemented equivalent on the\n * app side).\n *\n * Output length is always 72 bytes.\n *\n * @stability frozen — on-chain-binding. The 72-byte layout is the\n * input to `deriveContextHash`; any change rotates the vault root and\n * therefore every WOTS key, hashlock secret, and auth anchor derived\n * from it. Existing deposits cannot be recovered after a layout change.\n */\nexport function buildVaultContext(input: VaultContextInput): Uint8Array {\n if (input.depositorBtcPubkey.length !== DEPOSITOR_PUBKEY_SIZE) {\n throw new Error(\n `vaultContext: depositorBtcPubkey must be exactly ${DEPOSITOR_PUBKEY_SIZE} bytes, got ${input.depositorBtcPubkey.length}`,\n );\n }\n const commitment = buildFundingOutpointsCommitment(input.fundingOutpoints);\n\n const out = new Uint8Array(VAULT_CONTEXT_SIZE);\n let offset = 0;\n\n writeUint32BE(out, offset, DEPOSITOR_PUBKEY_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(input.depositorBtcPubkey, offset);\n offset += DEPOSITOR_PUBKEY_SIZE;\n\n writeUint32BE(out, offset, COMMITMENT_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(commitment, offset);\n\n return out;\n}\n","/**\n * Vault-root derivation via the wallet's `deriveContextHash` API.\n *\n * Implements the canonical root source from `derive-vault-secrets.md`\n * §2.2:\n *\n * ```\n * rootDerivation = deriveContextHash(\"babylon-btc-vault\", hex(vaultContext))\n * ```\n *\n * The 32-byte output is fed directly into the {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, and {@link expandWotsSeed} functions in\n * this module.\n *\n * @module vault-secrets/deriveVaultRoot\n */\n\nimport { hexToUint8Array, uint8ArrayToHex } from \"../primitives/utils/bitcoin\";\n\nimport { buildVaultContext, type VaultContextInput } from \"./context\";\n\n/**\n * The fixed `appName` passed to the wallet's `deriveContextHash` for\n * Babylon vault derivations. The wallet displays this in its approval\n * dialog. Defined by `derive-vault-secrets.md` §2.2 — must not be\n * changed without coordinating a spec revision and a downstream\n * migration plan, as it provides app-level domain separation across\n * applications using the same wallet.\n */\nexport const VAULT_APP_NAME = \"babylon-btc-vault\";\n\n/** Expected length of the wallet output in bytes per spec §2.1. */\nconst ROOT_OUTPUT_BYTES = 32;\n\n/** Expected length of the wallet output in lowercase hex chars. */\nconst ROOT_OUTPUT_HEX_LEN = ROOT_OUTPUT_BYTES * 2;\n\nconst LOWERCASE_HEX_RE = /^[0-9a-f]+$/;\n\n/**\n * Minimal structural shape for the wallet capability needed by this\n * helper. Typed against the method directly so callers can pass any\n * value that implements `deriveContextHash` — `BitcoinWallet` from\n * this SDK, `IBTCProvider` from `@babylonlabs-io/wallet-connector`,\n * or a test mock — without depending on the rest of either interface.\n */\nexport interface DeriveContextHashCapableWallet {\n deriveContextHash(appName: string, context: string): Promise<string>;\n}\n\n/** Forward the deriveContextHash capability only when the wallet actually has it,\n * so seam guards (ensurePrePeginTermsApproval) can fire their typed error instead\n * of a mid-ceremony TypeError. */\nexport function forwardDeriveContextHash(\n wallet: Partial<DeriveContextHashCapableWallet>,\n): Partial<DeriveContextHashCapableWallet> {\n return typeof wallet.deriveContextHash === \"function\"\n ? {\n deriveContextHash: (appName, context) =>\n wallet.deriveContextHash!(appName, context),\n }\n : {};\n}\n\n/**\n * Derive the 32-byte vault root from a wallet by encoding the\n * canonical {@link VaultContextInput} and forwarding to\n * `wallet.deriveContextHash`.\n *\n * Validates the wallet's output strictly: must be exactly 64\n * lowercase hex characters per `derive-context-hash.md` §2.1. A\n * conformant wallet always satisfies this, but we re-check at the\n * SDK boundary so a non-conformant wallet (or a wallet returning a\n * malformed value through a buggy adapter) fails loud here rather\n * than producing silently-wrong derived secrets downstream.\n *\n * The helper itself produces only valid spec inputs (`appName` is\n * the hardcoded `VAULT_APP_NAME`; `context` is hex of the 72-byte\n * `vaultContext`, always 144 chars lowercase), so input-side\n * validation is unnecessary.\n *\n * @param wallet - Any value implementing `deriveContextHash`.\n * @param input - The canonical {@link VaultContextInput} that\n * uniquely identifies the vault. Encoded by\n * {@link buildVaultContext} into a 72-byte structure\n * before being hex-encoded for the wallet.\n * @stability frozen — on-chain-binding. The pair (`VAULT_APP_NAME`,\n * `vaultContext` encoding) is the wallet's input space; changing\n * either rotates the root and invalidates every secret derived from\n * it. `VAULT_APP_NAME` is fixed by `derive-vault-secrets.md` §2.2\n * and must never change without a coordinated spec revision.\n *\n * @returns 32-byte root suitable for {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, {@link expandWotsSeed}.\n * @throws If the wallet returns a non-64-char or non-lowercase-hex\n * string. Errors from the wallet (user rejection,\n * method-not-supported, etc.) propagate unchanged.\n */\nexport async function deriveVaultRoot(\n wallet: DeriveContextHashCapableWallet,\n input: VaultContextInput,\n): Promise<Uint8Array> {\n const vaultContext = buildVaultContext(input);\n const contextHex = uint8ArrayToHex(vaultContext);\n\n const rootHex = await wallet.deriveContextHash(VAULT_APP_NAME, contextHex);\n\n if (typeof rootHex !== \"string\") {\n throw new Error(\n `deriveVaultRoot: wallet must return a string, got ${typeof rootHex}`,\n );\n }\n if (rootHex.length !== ROOT_OUTPUT_HEX_LEN) {\n throw new Error(\n `deriveVaultRoot: wallet must return a ${ROOT_OUTPUT_HEX_LEN}-character hex string (${ROOT_OUTPUT_BYTES} bytes), got length ${rootHex.length}`,\n );\n }\n if (!LOWERCASE_HEX_RE.test(rootHex)) {\n throw new Error(\n \"deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters\",\n );\n }\n\n return hexToUint8Array(rootHex);\n}\n","/**\n * Parse a Pre-PegIn transaction's inputs into the vault-context\n * `fundingOutpoints` shape consumed by `deriveVaultRoot`. Reverses\n * the prev-txid bytes from wire-internal little-endian to display\n * order so the derivation is byte-for-byte identical to the\n * deposit-time computation.\n *\n * @module vault-secrets/parseFundingOutpoints\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport type { FundingOutpoint } from \"./context\";\n\nexport function parseFundingOutpointsFromTx(\n unsignedTxHex: string,\n): FundingOutpoint[] {\n if (!unsignedTxHex) {\n throw new Error(\"Pre-pegin transaction hex is empty\");\n }\n const cleanHex = unsignedTxHex.startsWith(\"0x\")\n ? unsignedTxHex.slice(2)\n : unsignedTxHex;\n const tx = Transaction.fromHex(cleanHex);\n if (tx.ins.length === 0) {\n throw new Error(\"Pre-pegin transaction has no inputs\");\n }\n return tx.ins.map((input) => ({\n txid: Uint8Array.from(Buffer.from(input.hash).reverse()),\n vout: input.index,\n }));\n}\n"],"names":["DEPOSITOR_PUBKEY_SIZE","TXID_SIZE","OUTPOINT_SIZE","COMMITMENT_SIZE","FIELD_LEN_PREFIX_SIZE","VAULT_CONTEXT_SIZE","writeUint32BE","out","offset","value","serializeOutpoint","outpoint","compareBytes","a","b","len","i","buildFundingOutpointsCommitment","outpoints","serialized","flat","sha256","buildVaultContext","input","commitment","VAULT_APP_NAME","ROOT_OUTPUT_BYTES","ROOT_OUTPUT_HEX_LEN","LOWERCASE_HEX_RE","forwardDeriveContextHash","wallet","appName","context","deriveVaultRoot","vaultContext","contextHex","uint8ArrayToHex","rootHex","hexToUint8Array","parseFundingOutpointsFromTx","unsignedTxHex","cleanHex","tx","Transaction","Buffer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parseFundingOutpoints-CO-f6IHK.js","sources":["../src/tbv/core/vault-secrets/context.ts","../src/tbv/core/vault-secrets/deriveVaultRoot.ts","../src/tbv/core/vault-secrets/parseFundingOutpoints.ts"],"sourcesContent":["/**\n * Canonical `vaultContext` byte encoding per\n * `derive-vault-secrets.md` §2.3.\n *\n * ```\n * vaultContext :=\n * I2OSP(32, 4) || depositorBtcPubkey // 32B x-only\n * || I2OSP(32, 4) || fundingOutpointsCommitment // 32B SHA-256\n * ```\n *\n * `fundingOutpointsCommitment` is SHA-256 over the canonically-sorted\n * funding outpoints of the Pre-PegIn transaction, serialized as\n * `txid (32B display/RPC order) || vout (4B u32 big-endian)` per\n * outpoint. Sorting by 36-byte lex order makes the commitment\n * invariant under tx-level input reordering, so same-inputs RBF and\n * reorg rebroadcasts yield the same context.\n *\n * @module vault-secrets/context\n */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\";\n\nconst DEPOSITOR_PUBKEY_SIZE = 32;\nconst TXID_SIZE = 32;\nconst OUTPOINT_SIZE = 36;\nconst COMMITMENT_SIZE = 32;\nconst FIELD_LEN_PREFIX_SIZE = 4;\nconst VAULT_CONTEXT_SIZE =\n FIELD_LEN_PREFIX_SIZE +\n DEPOSITOR_PUBKEY_SIZE +\n FIELD_LEN_PREFIX_SIZE +\n COMMITMENT_SIZE;\n\nexport interface FundingOutpoint {\n /**\n * Bitcoin txid in **display / RPC order** (byte-reversed from the\n * internal little-endian wire form used when hashing a raw tx).\n */\n txid: Uint8Array;\n /** Output index within the referenced transaction (u32). */\n vout: number;\n}\n\nexport interface VaultContextInput {\n /** Depositor's x-only BTC public key (32 bytes). */\n depositorBtcPubkey: Uint8Array;\n /** Funding outpoints of the Pre-PegIn transaction. MUST be non-empty. */\n fundingOutpoints: readonly FundingOutpoint[];\n}\n\nfunction writeUint32BE(out: Uint8Array, offset: number, value: number): void {\n out[offset] = (value >>> 24) & 0xff;\n out[offset + 1] = (value >>> 16) & 0xff;\n out[offset + 2] = (value >>> 8) & 0xff;\n out[offset + 3] = value & 0xff;\n}\n\nfunction serializeOutpoint(outpoint: FundingOutpoint): Uint8Array {\n if (outpoint.txid.length !== TXID_SIZE) {\n throw new Error(\n `outpoint.txid must be exactly ${TXID_SIZE} bytes, got ${outpoint.txid.length}`,\n );\n }\n if (\n !Number.isInteger(outpoint.vout) ||\n outpoint.vout < 0 ||\n outpoint.vout > 0xffffffff\n ) {\n throw new Error(`outpoint.vout must be a u32, got ${outpoint.vout}`);\n }\n const out = new Uint8Array(OUTPOINT_SIZE);\n out.set(outpoint.txid, 0);\n writeUint32BE(out, TXID_SIZE, outpoint.vout);\n return out;\n}\n\nfunction compareBytes(a: Uint8Array, b: Uint8Array): number {\n const len = Math.min(a.length, b.length);\n for (let i = 0; i < len; i++) {\n if (a[i] !== b[i]) return a[i] - b[i];\n }\n return a.length - b.length;\n}\n\n/**\n * Compute SHA-256 over canonically-sorted funding outpoints.\n *\n * Outpoints are serialized as 36-byte `txid || vout_BE`, sorted\n * ascending lexicographically, concatenated, then hashed.\n *\n * @stability frozen — on-chain-binding. Any change to layout, sort\n * order, or serialization is a hard fork; existing deposits would no\n * longer match their committed `depositorWotsPkHash`.\n *\n * @throws If `outpoints` is empty or contains duplicates.\n */\nexport function buildFundingOutpointsCommitment(\n outpoints: readonly FundingOutpoint[],\n): Uint8Array {\n if (outpoints.length === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: outpoints must be non-empty\",\n );\n }\n const serialized = outpoints.map(serializeOutpoint);\n serialized.sort(compareBytes);\n\n for (let i = 1; i < serialized.length; i++) {\n if (compareBytes(serialized[i - 1], serialized[i]) === 0) {\n throw new Error(\n \"buildFundingOutpointsCommitment: duplicate outpoint detected\",\n );\n }\n }\n\n const flat = new Uint8Array(serialized.length * OUTPOINT_SIZE);\n for (let i = 0; i < serialized.length; i++) {\n flat.set(serialized[i], i * OUTPOINT_SIZE);\n }\n return sha256(flat);\n}\n\n/**\n * Build the canonical `vaultContext` byte string fed into the wallet's\n * `deriveContextHash` (or a locally-implemented equivalent on the\n * app side).\n *\n * Output length is always 72 bytes.\n *\n * @stability frozen — on-chain-binding. The 72-byte layout is the\n * input to `deriveContextHash`; any change rotates the vault root and\n * therefore every WOTS key, hashlock secret, and auth anchor derived\n * from it. Existing deposits cannot be recovered after a layout change.\n */\nexport function buildVaultContext(input: VaultContextInput): Uint8Array {\n if (input.depositorBtcPubkey.length !== DEPOSITOR_PUBKEY_SIZE) {\n throw new Error(\n `vaultContext: depositorBtcPubkey must be exactly ${DEPOSITOR_PUBKEY_SIZE} bytes, got ${input.depositorBtcPubkey.length}`,\n );\n }\n const commitment = buildFundingOutpointsCommitment(input.fundingOutpoints);\n\n const out = new Uint8Array(VAULT_CONTEXT_SIZE);\n let offset = 0;\n\n writeUint32BE(out, offset, DEPOSITOR_PUBKEY_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(input.depositorBtcPubkey, offset);\n offset += DEPOSITOR_PUBKEY_SIZE;\n\n writeUint32BE(out, offset, COMMITMENT_SIZE);\n offset += FIELD_LEN_PREFIX_SIZE;\n out.set(commitment, offset);\n\n return out;\n}\n","/**\n * Vault-root derivation via the wallet's `deriveContextHash` API.\n *\n * Implements the canonical root source from `derive-vault-secrets.md`\n * §2.2:\n *\n * ```\n * rootDerivation = deriveContextHash(\"babylon-btc-vault\", hex(vaultContext))\n * ```\n *\n * The 32-byte output is fed directly into the {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, and {@link expandWotsSeed} functions in\n * this module.\n *\n * @module vault-secrets/deriveVaultRoot\n */\n\nimport { hexToUint8Array, uint8ArrayToHex } from \"../primitives/utils/bitcoin\";\n\nimport { buildVaultContext, type VaultContextInput } from \"./context\";\n\n/**\n * The fixed `appName` passed to the wallet's `deriveContextHash` for\n * Babylon vault derivations. The wallet displays this in its approval\n * dialog. Defined by `derive-vault-secrets.md` §2.2 — must not be\n * changed without coordinating a spec revision and a downstream\n * migration plan, as it provides app-level domain separation across\n * applications using the same wallet.\n */\nexport const VAULT_APP_NAME = \"babylon-btc-vault\";\n\n/** Expected length of the wallet output in bytes per spec §2.1. */\nconst ROOT_OUTPUT_BYTES = 32;\n\n/** Expected length of the wallet output in lowercase hex chars. */\nconst ROOT_OUTPUT_HEX_LEN = ROOT_OUTPUT_BYTES * 2;\n\nconst LOWERCASE_HEX_RE = /^[0-9a-f]+$/;\n\n/**\n * Minimal structural shape for the wallet capability needed by this\n * helper. Typed against the method directly so callers can pass any\n * value that implements `deriveContextHash` — `BitcoinWallet` from\n * this SDK, `IBTCProvider` from `@babylonlabs-io/wallet-connector`,\n * or a test mock — without depending on the rest of either interface.\n */\nexport interface DeriveContextHashCapableWallet {\n deriveContextHash(appName: string, context: string): Promise<string>;\n}\n\n/** Forward the deriveContextHash capability only when the wallet actually has it,\n * so seam guards (ensurePrePeginTermsApproval) can fire their typed error instead\n * of a mid-ceremony TypeError. */\nexport function forwardDeriveContextHash(\n wallet: Partial<DeriveContextHashCapableWallet>,\n): Partial<DeriveContextHashCapableWallet> {\n return typeof wallet.deriveContextHash === \"function\"\n ? {\n deriveContextHash: (appName, context) =>\n wallet.deriveContextHash!(appName, context),\n }\n : {};\n}\n\n/**\n * Derive the 32-byte vault root from a wallet by encoding the\n * canonical {@link VaultContextInput} and forwarding to\n * `wallet.deriveContextHash`.\n *\n * Validates the wallet's output strictly: must be exactly 64\n * lowercase hex characters per `derive-context-hash.md` §2.1. A\n * conformant wallet always satisfies this, but we re-check at the\n * SDK boundary so a non-conformant wallet (or a wallet returning a\n * malformed value through a buggy adapter) fails loud here rather\n * than producing silently-wrong derived secrets downstream.\n *\n * The helper itself produces only valid spec inputs (`appName` is\n * the hardcoded `VAULT_APP_NAME`; `context` is hex of the 72-byte\n * `vaultContext`, always 144 chars lowercase), so input-side\n * validation is unnecessary.\n *\n * @param wallet - Any value implementing `deriveContextHash`.\n * @param input - The canonical {@link VaultContextInput} that\n * uniquely identifies the vault. Encoded by\n * {@link buildVaultContext} into a 72-byte structure\n * before being hex-encoded for the wallet.\n * @stability frozen — on-chain-binding. The pair (`VAULT_APP_NAME`,\n * `vaultContext` encoding) is the wallet's input space; changing\n * either rotates the root and invalidates every secret derived from\n * it. `VAULT_APP_NAME` is fixed by `derive-vault-secrets.md` §2.2\n * and must never change without a coordinated spec revision.\n *\n * @returns 32-byte root suitable for {@link expandAuthAnchor},\n * {@link expandHashlockSecret}, {@link expandWotsSeed}.\n * @throws If the wallet returns a non-64-char or non-lowercase-hex\n * string. Errors from the wallet (user rejection,\n * method-not-supported, etc.) propagate unchanged.\n */\nexport async function deriveVaultRoot(\n wallet: DeriveContextHashCapableWallet,\n input: VaultContextInput,\n): Promise<Uint8Array> {\n const vaultContext = buildVaultContext(input);\n const contextHex = uint8ArrayToHex(vaultContext);\n\n const rootHex = await wallet.deriveContextHash(VAULT_APP_NAME, contextHex);\n\n if (typeof rootHex !== \"string\") {\n throw new Error(\n `deriveVaultRoot: wallet must return a string, got ${typeof rootHex}`,\n );\n }\n if (rootHex.length !== ROOT_OUTPUT_HEX_LEN) {\n throw new Error(\n `deriveVaultRoot: wallet must return a ${ROOT_OUTPUT_HEX_LEN}-character hex string (${ROOT_OUTPUT_BYTES} bytes), got length ${rootHex.length}`,\n );\n }\n if (!LOWERCASE_HEX_RE.test(rootHex)) {\n throw new Error(\n \"deriveVaultRoot: wallet must return lowercase hex per derive-context-hash.md §2.1; got value with non-lowercase or non-hex characters\",\n );\n }\n\n return hexToUint8Array(rootHex);\n}\n","/**\n * Parse a Pre-PegIn transaction's inputs into the vault-context\n * `fundingOutpoints` shape consumed by `deriveVaultRoot`. Reverses\n * the prev-txid bytes from wire-internal little-endian to display\n * order so the derivation is byte-for-byte identical to the\n * deposit-time computation.\n *\n * @module vault-secrets/parseFundingOutpoints\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport type { FundingOutpoint } from \"./context\";\n\nexport function parseFundingOutpointsFromTx(\n unsignedTxHex: string,\n): FundingOutpoint[] {\n if (!unsignedTxHex) {\n throw new Error(\"Pre-pegin transaction hex is empty\");\n }\n const cleanHex = unsignedTxHex.startsWith(\"0x\")\n ? unsignedTxHex.slice(2)\n : unsignedTxHex;\n const tx = Transaction.fromHex(cleanHex);\n if (tx.ins.length === 0) {\n throw new Error(\"Pre-pegin transaction has no inputs\");\n }\n return tx.ins.map((input) => ({\n txid: Uint8Array.from(Buffer.from(input.hash).reverse()),\n vout: input.index,\n }));\n}\n"],"names":["DEPOSITOR_PUBKEY_SIZE","TXID_SIZE","OUTPOINT_SIZE","COMMITMENT_SIZE","FIELD_LEN_PREFIX_SIZE","VAULT_CONTEXT_SIZE","writeUint32BE","out","offset","value","serializeOutpoint","outpoint","compareBytes","a","b","len","i","buildFundingOutpointsCommitment","outpoints","serialized","flat","sha256","buildVaultContext","input","commitment","VAULT_APP_NAME","ROOT_OUTPUT_BYTES","ROOT_OUTPUT_HEX_LEN","LOWERCASE_HEX_RE","forwardDeriveContextHash","wallet","appName","context","deriveVaultRoot","vaultContext","contextHex","uint8ArrayToHex","rootHex","hexToUint8Array","parseFundingOutpointsFromTx","unsignedTxHex","cleanHex","tx","Transaction","Buffer"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ var g = (e, n, t) => n in e ? m(e, n, { enumerable: !0, configurable: !0, writab
|
|
|
3
3
|
var f = (e, n, t) => g(e, typeof n != "symbol" ? n + "" : n, t);
|
|
4
4
|
import { Transaction as p } from "bitcoinjs-lib";
|
|
5
5
|
import { Buffer as d } from "buffer";
|
|
6
|
-
import { s as w } from "./bitcoin-
|
|
6
|
+
import { s as w } from "./bitcoin-Ch_jxnDa.js";
|
|
7
7
|
import { C as T } from "./peginState-CxDiaKuk.js";
|
|
8
8
|
class U extends Error {
|
|
9
9
|
constructor(t) {
|
|
@@ -104,4 +104,4 @@ export {
|
|
|
104
104
|
L as f,
|
|
105
105
|
b as v
|
|
106
106
|
};
|
|
107
|
-
//# sourceMappingURL=reservation-
|
|
107
|
+
//# sourceMappingURL=reservation-CBAvoF3U.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reservation-B4i_PQhY.js","sources":["../src/tbv/core/utils/utxo/availability.ts","../src/tbv/core/utils/utxo/reservation.ts"],"sourcesContent":["/**\n * UTXO Availability Validation\n *\n * Validates that UTXOs referenced in a pre-pegin transaction are still unspent\n * BEFORE asking the user to sign. This prevents wasted signing effort when\n * UTXOs have already been spent by unrelated transactions.\n *\n * These functions are pure — they accept pre-fetched UTXOs and perform no I/O.\n * The vault service wrapper is responsible for fetching UTXOs from the mempool.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\n/**\n * Reference to a Bitcoin UTXO by its outpoint (txid + vout).\n *\n * Used by the availability check to compare a Pre-PegIn transaction's\n * declared inputs against the wallet's current spendable set. Txids are\n * compared case-insensitively; callers should treat the txid as opaque\n * lowercase hex.\n */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/**\n * Information about a missing/spent UTXO.\n */\nexport interface MissingUtxoInfo {\n /** Transaction ID of the missing UTXO */\n txid: string;\n /** Output index of the missing UTXO */\n vout: number;\n}\n\n/**\n * Result of UTXO validation.\n */\nexport interface UtxoValidationResult {\n /** Whether all UTXOs are still available */\n allAvailable: boolean;\n /** List of missing UTXOs (if any) */\n missingUtxos: MissingUtxoInfo[];\n /** Total number of inputs checked */\n totalInputs: number;\n}\n\n/**\n * Error thrown when UTXOs are not available.\n */\nexport class UtxoNotAvailableError extends Error {\n public readonly missingUtxos: MissingUtxoInfo[];\n\n constructor(missingUtxos: MissingUtxoInfo[]) {\n const count = missingUtxos.length;\n const message =\n count === 1\n ? \"The UTXO for this peg-in is no longer available. It may have been spent in another transaction. Please create a new peg-in request with a different UTXO.\"\n : `${count} UTXOs for this peg-in are no longer available. They may have been spent. Please create a new peg-in request with different UTXOs.`;\n\n super(message);\n this.name = \"UtxoNotAvailableError\";\n this.missingUtxos = missingUtxos;\n }\n}\n\n/**\n * Extract input references (txid:vout) from an unsigned transaction.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @returns Array of input references\n */\nexport function extractInputsFromTransaction(\n unsignedTxHex: string,\n): Array<{ txid: string; vout: number }> {\n const cleanHex = unsignedTxHex.startsWith(\"0x\")\n ? unsignedTxHex.slice(2)\n : unsignedTxHex;\n\n let tx: Transaction;\n try {\n tx = Transaction.fromHex(cleanHex);\n } catch (error) {\n throw new Error(\n `Failed to parse BTC transaction: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n return tx.ins.map((input) => ({\n // Bitcoin stores txid in reverse byte order\n txid: Buffer.from(input.hash).reverse().toString(\"hex\"),\n vout: input.index,\n }));\n}\n\n/**\n * Validate that all UTXOs in a transaction are still available.\n *\n * Pure function — accepts pre-fetched UTXOs instead of making network calls.\n * This should be called BEFORE signing to avoid wasting user effort\n * signing a transaction that will fail to broadcast.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @param availableUtxos - Pre-fetched list of available UTXOs for the depositor\n * @returns Validation result with missing UTXO details\n */\nexport function validateUtxosAvailable(\n unsignedTxHex: string,\n availableUtxos: UtxoRef[],\n): UtxoValidationResult {\n const inputs = extractInputsFromTransaction(unsignedTxHex);\n\n if (inputs.length === 0) {\n throw new Error(\"Transaction has no inputs\");\n }\n\n // Detect duplicate inputs (same txid:vout referenced more than once).\n // This would produce an invalid Bitcoin transaction.\n const inputKeys = new Set<string>();\n for (const input of inputs) {\n const key = `${input.txid.toLowerCase()}:${input.vout}`;\n if (inputKeys.has(key)) {\n throw new Error(\n `Transaction contains duplicate input ${input.txid}:${input.vout}. ` +\n `This would produce an invalid Bitcoin transaction.`,\n );\n }\n inputKeys.add(key);\n }\n\n // Set of available outpoints for O(1) lookup. Lowercased so the comparison\n // is case-insensitive against whatever case the wallet returned.\n const availableSet = new Set(\n availableUtxos.map((utxo) => `${utxo.txid.toLowerCase()}:${utxo.vout}`),\n );\n\n // Check which inputs are missing\n const missingUtxos: MissingUtxoInfo[] = [];\n for (const input of inputs) {\n const key = `${input.txid.toLowerCase()}:${input.vout}`;\n if (!availableSet.has(key)) {\n missingUtxos.push({\n txid: input.txid,\n vout: input.vout,\n });\n }\n }\n\n return {\n allAvailable: missingUtxos.length === 0,\n missingUtxos,\n totalInputs: inputs.length,\n };\n}\n\n/**\n * Validate UTXOs and throw if any are not available.\n *\n * Pure convenience function that combines validation and error throwing.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @param availableUtxos - Pre-fetched list of available UTXOs for the depositor\n * @throws UtxoNotAvailableError if any UTXOs are not available\n * @throws Error if validation fails\n */\nexport function assertUtxosAvailable(\n unsignedTxHex: string,\n availableUtxos: UtxoRef[],\n): void {\n const result = validateUtxosAvailable(unsignedTxHex, availableUtxos);\n\n if (!result.allAvailable) {\n throw new UtxoNotAvailableError(result.missingUtxos);\n }\n}\n","/**\n * Pending-vault outpoint overlap detection.\n *\n * Given the depositor's pending vaults (indexer + local cache) and the\n * outpoints a new deposit's coin selector picked, return the set of\n * pending vault ids whose Pre-PegIn BTC tx shares an input. Advisory\n * only — used to warn the user before signing.\n *\n * Only `PENDING` vaults contribute: VERIFIED+ have their Pre-PegIn\n * already confirmed on-chain, so those inputs cannot still appear in\n * the wallet's spendable set.\n */\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\n\nimport { type UtxoRef } from \"./availability\";\n\n/** Locally-known pending pegin. `id` is the bytes32 vault id. */\nexport interface PendingPeginLike {\n id?: string;\n unsignedTxHex?: string;\n}\n\n/** On-chain vault row from the indexer. */\nexport interface VaultLike {\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface FindOverlappingPendingVaultsParams {\n selectedOutpoints: ReadonlyArray<UtxoRef>;\n vaults?: ReadonlyArray<VaultLike>;\n pendingPegins?: ReadonlyArray<PendingPeginLike>;\n}\n\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => ({\n txid: Buffer.from(input.hash).reverse().toString(\"hex\"),\n vout: input.index,\n }));\n } catch {\n return [];\n }\n}\n\nfunction outpointKey(o: UtxoRef): string {\n return `${o.txid.toLowerCase()}:${o.vout}`;\n}\n\n/**\n * Return the ids of pending vaults whose committed Pre-PegIn inputs\n * overlap any of the just-selected outpoints. On-chain `PENDING` vaults\n * take precedence over a same-id local pegin entry.\n */\nexport function findOverlappingPendingVaults(\n params: FindOverlappingPendingVaultsParams,\n): string[] {\n const { selectedOutpoints, vaults = [], pendingPegins = [] } = params;\n\n const selectedSet = new Set(selectedOutpoints.map(outpointKey));\n if (selectedSet.size === 0) return [];\n\n const seenIds = new Set<string>();\n const impacted = new Set<string>();\n\n const consider = (id: string | undefined, txHex: string): void => {\n if (!id) return;\n const idLower = id.toLowerCase();\n if (seenIds.has(idLower)) return;\n seenIds.add(idLower);\n const inputs = extractInputUtxoRefs(txHex);\n for (const input of inputs) {\n if (selectedSet.has(outpointKey(input))) {\n impacted.add(id);\n return;\n }\n }\n };\n\n // On-chain wins on id collision.\n for (const v of vaults) {\n if (v.status !== ContractStatus.PENDING) continue;\n consider(v.id, v.unsignedPrePeginTx);\n }\n for (const p of pendingPegins) {\n if (!p.unsignedTxHex) continue;\n consider(p.id, p.unsignedTxHex);\n }\n\n return Array.from(impacted);\n}\n"],"names":["UtxoNotAvailableError","missingUtxos","count","message","__publicField","extractInputsFromTransaction","unsignedTxHex","cleanHex","tx","Transaction","error","input","Buffer","validateUtxosAvailable","availableUtxos","inputs","inputKeys","key","availableSet","utxo","assertUtxosAvailable","result","extractInputUtxoRefs","txHex","stripHexPrefix","outpointKey","o","findOverlappingPendingVaults","params","selectedOutpoints","vaults","pendingPegins","selectedSet","seenIds","impacted","consider","id","idLower","v","ContractStatus","p"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reservation-CBAvoF3U.js","sources":["../src/tbv/core/utils/utxo/availability.ts","../src/tbv/core/utils/utxo/reservation.ts"],"sourcesContent":["/**\n * UTXO Availability Validation\n *\n * Validates that UTXOs referenced in a pre-pegin transaction are still unspent\n * BEFORE asking the user to sign. This prevents wasted signing effort when\n * UTXOs have already been spent by unrelated transactions.\n *\n * These functions are pure — they accept pre-fetched UTXOs and perform no I/O.\n * The vault service wrapper is responsible for fetching UTXOs from the mempool.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\n/**\n * Reference to a Bitcoin UTXO by its outpoint (txid + vout).\n *\n * Used by the availability check to compare a Pre-PegIn transaction's\n * declared inputs against the wallet's current spendable set. Txids are\n * compared case-insensitively; callers should treat the txid as opaque\n * lowercase hex.\n */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/**\n * Information about a missing/spent UTXO.\n */\nexport interface MissingUtxoInfo {\n /** Transaction ID of the missing UTXO */\n txid: string;\n /** Output index of the missing UTXO */\n vout: number;\n}\n\n/**\n * Result of UTXO validation.\n */\nexport interface UtxoValidationResult {\n /** Whether all UTXOs are still available */\n allAvailable: boolean;\n /** List of missing UTXOs (if any) */\n missingUtxos: MissingUtxoInfo[];\n /** Total number of inputs checked */\n totalInputs: number;\n}\n\n/**\n * Error thrown when UTXOs are not available.\n */\nexport class UtxoNotAvailableError extends Error {\n public readonly missingUtxos: MissingUtxoInfo[];\n\n constructor(missingUtxos: MissingUtxoInfo[]) {\n const count = missingUtxos.length;\n const message =\n count === 1\n ? \"The UTXO for this peg-in is no longer available. It may have been spent in another transaction. Please create a new peg-in request with a different UTXO.\"\n : `${count} UTXOs for this peg-in are no longer available. They may have been spent. Please create a new peg-in request with different UTXOs.`;\n\n super(message);\n this.name = \"UtxoNotAvailableError\";\n this.missingUtxos = missingUtxos;\n }\n}\n\n/**\n * Extract input references (txid:vout) from an unsigned transaction.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @returns Array of input references\n */\nexport function extractInputsFromTransaction(\n unsignedTxHex: string,\n): Array<{ txid: string; vout: number }> {\n const cleanHex = unsignedTxHex.startsWith(\"0x\")\n ? unsignedTxHex.slice(2)\n : unsignedTxHex;\n\n let tx: Transaction;\n try {\n tx = Transaction.fromHex(cleanHex);\n } catch (error) {\n throw new Error(\n `Failed to parse BTC transaction: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n return tx.ins.map((input) => ({\n // Bitcoin stores txid in reverse byte order\n txid: Buffer.from(input.hash).reverse().toString(\"hex\"),\n vout: input.index,\n }));\n}\n\n/**\n * Validate that all UTXOs in a transaction are still available.\n *\n * Pure function — accepts pre-fetched UTXOs instead of making network calls.\n * This should be called BEFORE signing to avoid wasting user effort\n * signing a transaction that will fail to broadcast.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @param availableUtxos - Pre-fetched list of available UTXOs for the depositor\n * @returns Validation result with missing UTXO details\n */\nexport function validateUtxosAvailable(\n unsignedTxHex: string,\n availableUtxos: UtxoRef[],\n): UtxoValidationResult {\n const inputs = extractInputsFromTransaction(unsignedTxHex);\n\n if (inputs.length === 0) {\n throw new Error(\"Transaction has no inputs\");\n }\n\n // Detect duplicate inputs (same txid:vout referenced more than once).\n // This would produce an invalid Bitcoin transaction.\n const inputKeys = new Set<string>();\n for (const input of inputs) {\n const key = `${input.txid.toLowerCase()}:${input.vout}`;\n if (inputKeys.has(key)) {\n throw new Error(\n `Transaction contains duplicate input ${input.txid}:${input.vout}. ` +\n `This would produce an invalid Bitcoin transaction.`,\n );\n }\n inputKeys.add(key);\n }\n\n // Set of available outpoints for O(1) lookup. Lowercased so the comparison\n // is case-insensitive against whatever case the wallet returned.\n const availableSet = new Set(\n availableUtxos.map((utxo) => `${utxo.txid.toLowerCase()}:${utxo.vout}`),\n );\n\n // Check which inputs are missing\n const missingUtxos: MissingUtxoInfo[] = [];\n for (const input of inputs) {\n const key = `${input.txid.toLowerCase()}:${input.vout}`;\n if (!availableSet.has(key)) {\n missingUtxos.push({\n txid: input.txid,\n vout: input.vout,\n });\n }\n }\n\n return {\n allAvailable: missingUtxos.length === 0,\n missingUtxos,\n totalInputs: inputs.length,\n };\n}\n\n/**\n * Validate UTXOs and throw if any are not available.\n *\n * Pure convenience function that combines validation and error throwing.\n *\n * @param unsignedTxHex - Unsigned transaction hex\n * @param availableUtxos - Pre-fetched list of available UTXOs for the depositor\n * @throws UtxoNotAvailableError if any UTXOs are not available\n * @throws Error if validation fails\n */\nexport function assertUtxosAvailable(\n unsignedTxHex: string,\n availableUtxos: UtxoRef[],\n): void {\n const result = validateUtxosAvailable(unsignedTxHex, availableUtxos);\n\n if (!result.allAvailable) {\n throw new UtxoNotAvailableError(result.missingUtxos);\n }\n}\n","/**\n * Pending-vault outpoint overlap detection.\n *\n * Given the depositor's pending vaults (indexer + local cache) and the\n * outpoints a new deposit's coin selector picked, return the set of\n * pending vault ids whose Pre-PegIn BTC tx shares an input. Advisory\n * only — used to warn the user before signing.\n *\n * Only `PENDING` vaults contribute: VERIFIED+ have their Pre-PegIn\n * already confirmed on-chain, so those inputs cannot still appear in\n * the wallet's spendable set.\n */\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\n\nimport { type UtxoRef } from \"./availability\";\n\n/** Locally-known pending pegin. `id` is the bytes32 vault id. */\nexport interface PendingPeginLike {\n id?: string;\n unsignedTxHex?: string;\n}\n\n/** On-chain vault row from the indexer. */\nexport interface VaultLike {\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface FindOverlappingPendingVaultsParams {\n selectedOutpoints: ReadonlyArray<UtxoRef>;\n vaults?: ReadonlyArray<VaultLike>;\n pendingPegins?: ReadonlyArray<PendingPeginLike>;\n}\n\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => ({\n txid: Buffer.from(input.hash).reverse().toString(\"hex\"),\n vout: input.index,\n }));\n } catch {\n return [];\n }\n}\n\nfunction outpointKey(o: UtxoRef): string {\n return `${o.txid.toLowerCase()}:${o.vout}`;\n}\n\n/**\n * Return the ids of pending vaults whose committed Pre-PegIn inputs\n * overlap any of the just-selected outpoints. On-chain `PENDING` vaults\n * take precedence over a same-id local pegin entry.\n */\nexport function findOverlappingPendingVaults(\n params: FindOverlappingPendingVaultsParams,\n): string[] {\n const { selectedOutpoints, vaults = [], pendingPegins = [] } = params;\n\n const selectedSet = new Set(selectedOutpoints.map(outpointKey));\n if (selectedSet.size === 0) return [];\n\n const seenIds = new Set<string>();\n const impacted = new Set<string>();\n\n const consider = (id: string | undefined, txHex: string): void => {\n if (!id) return;\n const idLower = id.toLowerCase();\n if (seenIds.has(idLower)) return;\n seenIds.add(idLower);\n const inputs = extractInputUtxoRefs(txHex);\n for (const input of inputs) {\n if (selectedSet.has(outpointKey(input))) {\n impacted.add(id);\n return;\n }\n }\n };\n\n // On-chain wins on id collision.\n for (const v of vaults) {\n if (v.status !== ContractStatus.PENDING) continue;\n consider(v.id, v.unsignedPrePeginTx);\n }\n for (const p of pendingPegins) {\n if (!p.unsignedTxHex) continue;\n consider(p.id, p.unsignedTxHex);\n }\n\n return Array.from(impacted);\n}\n"],"names":["UtxoNotAvailableError","missingUtxos","count","message","__publicField","extractInputsFromTransaction","unsignedTxHex","cleanHex","tx","Transaction","error","input","Buffer","validateUtxosAvailable","availableUtxos","inputs","inputKeys","key","availableSet","utxo","assertUtxosAvailable","result","extractInputUtxoRefs","txHex","stripHexPrefix","outpointKey","o","findOverlappingPendingVaults","params","selectedOutpoints","vaults","pendingPegins","selectedSet","seenIds","impacted","consider","id","idLower","v","ContractStatus","p"],"mappings":"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"}
|
|
@@ -1,98 +1,117 @@
|
|
|
1
1
|
var B = Object.defineProperty;
|
|
2
|
-
var E = (
|
|
3
|
-
var h = (
|
|
4
|
-
import * as
|
|
5
|
-
import { s as
|
|
2
|
+
var E = (t, e, s) => e in t ? B(t, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : t[e] = s;
|
|
3
|
+
var h = (t, e, s) => E(t, typeof e != "symbol" ? e + "" : e, s);
|
|
4
|
+
import * as v from "bitcoinjs-lib";
|
|
5
|
+
import { s as w, v as p } from "./bitcoin-Ch_jxnDa.js";
|
|
6
6
|
import { s as R } from "./sha2-BYVxyZzX.js";
|
|
7
7
|
import "@babylonlabs-io/babylon-tbv-rust-wasm";
|
|
8
|
-
import {
|
|
9
|
-
import { c as
|
|
10
|
-
const
|
|
11
|
-
function
|
|
12
|
-
const r =
|
|
13
|
-
if (n.outs.length <=
|
|
8
|
+
import { d as b, f as y, e as d, g as x } from "./verifyScriptPathSchnorrSignature-Dy9gF5RF.js";
|
|
9
|
+
import { c as f } from "./signing-DaLvGwQe.js";
|
|
10
|
+
const T = 106, S = 32, l = 34;
|
|
11
|
+
function D(t, e, s) {
|
|
12
|
+
const r = w(t), n = v.Transaction.fromHex(r);
|
|
13
|
+
if (n.outs.length <= e)
|
|
14
14
|
throw new Error(
|
|
15
|
-
`Pre-PegIn auth-anchor OP_RETURN missing: tx has ${n.outs.length} outputs, expected at least ${
|
|
15
|
+
`Pre-PegIn auth-anchor OP_RETURN missing: tx has ${n.outs.length} outputs, expected at least ${e + 1} (vault outputs + OP_RETURN)`
|
|
16
16
|
);
|
|
17
|
-
const c = n.outs[
|
|
18
|
-
if (i.length !== l || i[0] !==
|
|
17
|
+
const c = n.outs[e], i = c.script;
|
|
18
|
+
if (i.length !== l || i[0] !== T || i[1] !== S)
|
|
19
19
|
throw new Error(
|
|
20
|
-
`Pre-PegIn auth-anchor OP_RETURN at vout ${
|
|
20
|
+
`Pre-PegIn auth-anchor OP_RETURN at vout ${e} has unexpected script encoding (got ${i.length}-byte script with prefix 0x${i.slice(0, Math.min(2, i.length)).toString("hex")}; expected ${l}-byte OP_RETURN + PUSH32 layout)`
|
|
21
21
|
);
|
|
22
22
|
const a = i.slice(2).toString("hex").toLowerCase();
|
|
23
23
|
if (a !== s.toLowerCase())
|
|
24
24
|
throw new Error(
|
|
25
|
-
`Pre-PegIn auth-anchor OP_RETURN payload mismatch at vout ${
|
|
25
|
+
`Pre-PegIn auth-anchor OP_RETURN payload mismatch at vout ${e}: tx pushes ${a}, expected ${s}`
|
|
26
26
|
);
|
|
27
27
|
if (c.value !== 0)
|
|
28
28
|
throw new Error(
|
|
29
|
-
`Pre-PegIn auth-anchor OP_RETURN at vout ${
|
|
29
|
+
`Pre-PegIn auth-anchor OP_RETURN at vout ${e} has non-zero value ${c.value}; OP_RETURN outputs must be 0-value`
|
|
30
30
|
);
|
|
31
31
|
}
|
|
32
|
-
function
|
|
33
|
-
let
|
|
32
|
+
function W(t) {
|
|
33
|
+
let e;
|
|
34
34
|
try {
|
|
35
|
-
|
|
35
|
+
e = v.Transaction.fromHex(w(t));
|
|
36
36
|
} catch {
|
|
37
37
|
return;
|
|
38
38
|
}
|
|
39
39
|
const s = [];
|
|
40
|
-
for (let r = 0; r <
|
|
41
|
-
const n =
|
|
42
|
-
c.length === l && c[0] ===
|
|
40
|
+
for (let r = 0; r < e.outs.length; r++) {
|
|
41
|
+
const n = e.outs[r], c = n.script;
|
|
42
|
+
c.length === l && c[0] === T && c[1] === S && n.value === 0 && s.push({
|
|
43
43
|
vout: r,
|
|
44
44
|
hash: c.slice(2).toString("hex").toLowerCase()
|
|
45
45
|
});
|
|
46
46
|
}
|
|
47
47
|
return s.length === 1 ? s[0] : void 0;
|
|
48
48
|
}
|
|
49
|
-
const
|
|
50
|
-
function H(
|
|
51
|
-
if (!
|
|
49
|
+
const m = 66;
|
|
50
|
+
function H(t) {
|
|
51
|
+
if (!t.startsWith("0x") && !t.startsWith("0X"))
|
|
52
52
|
throw new Error("Expected 0x-prefixed hex string");
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
throw new Error(`Hex string has odd length: ${
|
|
56
|
-
if (!/^[0-9a-fA-F]*$/.test(
|
|
53
|
+
const e = t.slice(2);
|
|
54
|
+
if (e.length % 2 !== 0)
|
|
55
|
+
throw new Error(`Hex string has odd length: ${e.length}`);
|
|
56
|
+
if (!/^[0-9a-fA-F]*$/.test(e))
|
|
57
57
|
throw new Error("Hex string contains non-hex characters");
|
|
58
|
-
const s = new Uint8Array(
|
|
58
|
+
const s = new Uint8Array(e.length / 2);
|
|
59
59
|
for (let r = 0; r < s.length; r++)
|
|
60
|
-
s[r] = parseInt(
|
|
60
|
+
s[r] = parseInt(e.slice(r * 2, r * 2 + 2), 16);
|
|
61
61
|
return s;
|
|
62
62
|
}
|
|
63
|
-
function
|
|
64
|
-
return `0x${Array.from(
|
|
63
|
+
function A(t) {
|
|
64
|
+
return `0x${Array.from(t).map((e) => e.toString(16).padStart(2, "0")).join("")}`;
|
|
65
65
|
}
|
|
66
|
-
function
|
|
67
|
-
if (
|
|
66
|
+
function P(t, e) {
|
|
67
|
+
if (t.length !== m)
|
|
68
68
|
throw new Error(
|
|
69
|
-
`${
|
|
69
|
+
`${e} must be exactly 32 bytes (${m} hex chars with 0x prefix), got ${t.length}`
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
return
|
|
72
|
+
function C(t) {
|
|
73
|
+
P(t, "Secret");
|
|
74
|
+
const e = H(t), s = R(e);
|
|
75
|
+
return A(s);
|
|
76
76
|
}
|
|
77
|
-
function L(
|
|
78
|
-
return
|
|
77
|
+
function L(t, e) {
|
|
78
|
+
return P(t, "Secret"), P(e, "Hashlock"), H(e), C(t).toLowerCase() === e.toLowerCase();
|
|
79
79
|
}
|
|
80
|
-
function
|
|
81
|
-
return typeof
|
|
80
|
+
function $(t) {
|
|
81
|
+
return typeof t.approveDepositTerms == "function";
|
|
82
82
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
83
|
+
async function M(t) {
|
|
84
|
+
const e = t;
|
|
85
|
+
if (typeof e.getChangeAddress != "function")
|
|
86
|
+
throw new Error(
|
|
87
|
+
"Approval wallet does not implement getChangeAddress; it must expose its change branch, because the signing device accepts Pre-PegIn change only there."
|
|
88
|
+
);
|
|
89
|
+
return e.getChangeAddress();
|
|
90
|
+
}
|
|
91
|
+
function F(t) {
|
|
92
|
+
if (!$(t))
|
|
93
|
+
return {};
|
|
94
|
+
const e = t.holdsApprovedDepositTerms, s = t.getChangeAddress;
|
|
95
|
+
return {
|
|
96
|
+
approveDepositTerms: (r) => t.approveDepositTerms(r),
|
|
97
|
+
// Both optional in the seam: forward only what the provider implements, so
|
|
98
|
+
// wrapper consumers can keep probing by typeof.
|
|
99
|
+
...typeof s == "function" ? { getChangeAddress: () => s.call(t) } : {},
|
|
100
|
+
...typeof e == "function" ? {
|
|
101
|
+
holdsApprovedDepositTerms: (r) => e.call(t, r)
|
|
102
|
+
} : {}
|
|
103
|
+
};
|
|
85
104
|
}
|
|
86
|
-
const
|
|
87
|
-
class
|
|
105
|
+
const k = 0;
|
|
106
|
+
class q {
|
|
88
107
|
/**
|
|
89
108
|
* Creates a new PayoutManager instance.
|
|
90
109
|
*
|
|
91
110
|
* @param config - Manager configuration including wallet
|
|
92
111
|
*/
|
|
93
|
-
constructor(
|
|
112
|
+
constructor(e) {
|
|
94
113
|
h(this, "config");
|
|
95
|
-
this.config =
|
|
114
|
+
this.config = e;
|
|
96
115
|
}
|
|
97
116
|
/**
|
|
98
117
|
* Signs a Payout transaction and extracts the Schnorr signature.
|
|
@@ -116,43 +135,44 @@ class z {
|
|
|
116
135
|
* @throws Error if wallet pubkey doesn't match depositor pubkey
|
|
117
136
|
* @throws Error if wallet operations fail or signature extraction fails
|
|
118
137
|
*/
|
|
119
|
-
async signPayoutTransaction(
|
|
138
|
+
async signPayoutTransaction(e) {
|
|
120
139
|
const s = await this.config.btcWallet.getPublicKeyHex(), { depositorPubkey: r } = p(
|
|
121
140
|
s,
|
|
122
|
-
|
|
141
|
+
e.depositorBtcPubkey
|
|
123
142
|
), n = await b({
|
|
124
|
-
vaultCoreVersion:
|
|
125
|
-
payoutTxHex:
|
|
126
|
-
peginTxHex:
|
|
127
|
-
assertTxHex:
|
|
143
|
+
vaultCoreVersion: e.vaultCoreVersion,
|
|
144
|
+
payoutTxHex: e.payoutTxHex,
|
|
145
|
+
peginTxHex: e.peginTxHex,
|
|
146
|
+
assertTxHex: e.assertTxHex,
|
|
128
147
|
depositorBtcPubkey: r,
|
|
129
|
-
vaultProviderBtcPubkey:
|
|
130
|
-
vaultKeeperBtcPubkeys:
|
|
131
|
-
universalChallengerBtcPubkeys:
|
|
132
|
-
timelockPegin:
|
|
133
|
-
timelockAssert:
|
|
148
|
+
vaultProviderBtcPubkey: e.vaultProviderBtcPubkey,
|
|
149
|
+
vaultKeeperBtcPubkeys: e.vaultKeeperBtcPubkeys,
|
|
150
|
+
universalChallengerBtcPubkeys: e.universalChallengerBtcPubkeys,
|
|
151
|
+
timelockPegin: e.timelockPegin,
|
|
152
|
+
timelockAssert: e.timelockAssert,
|
|
134
153
|
network: this.config.network,
|
|
135
|
-
claimerBtcPubkey:
|
|
136
|
-
registeredPayoutScriptPubKey:
|
|
137
|
-
commissionBps:
|
|
138
|
-
protocolFeeRate:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
154
|
+
claimerBtcPubkey: e.claimerBtcPubkey,
|
|
155
|
+
registeredPayoutScriptPubKey: e.registeredPayoutScriptPubKey,
|
|
156
|
+
commissionBps: e.commissionBps,
|
|
157
|
+
protocolFeeRate: e.protocolFeeRate,
|
|
158
|
+
councilMembers: e.councilMembers,
|
|
159
|
+
councilQuorum: e.councilQuorum,
|
|
160
|
+
vkClaimerPayoutScriptPubKeys: e.vkClaimerPayoutScriptPubKeys,
|
|
161
|
+
vpCommissionScriptPubKey: e.vpCommissionScriptPubKey
|
|
142
162
|
}), c = await this.config.btcWallet.signPsbt(
|
|
143
163
|
n.psbtHex,
|
|
144
|
-
|
|
164
|
+
f(s, 1)
|
|
145
165
|
);
|
|
146
166
|
y({
|
|
147
167
|
requestedPsbtHex: n.psbtHex,
|
|
148
168
|
returnedPsbtHex: c
|
|
149
169
|
});
|
|
150
|
-
const i =
|
|
151
|
-
return
|
|
170
|
+
const i = d(c, r);
|
|
171
|
+
return x({
|
|
152
172
|
requestedPsbtHex: n.psbtHex,
|
|
153
173
|
signatureHex: i,
|
|
154
174
|
signerXOnlyPubkeyHex: r,
|
|
155
|
-
inputIndex:
|
|
175
|
+
inputIndex: k
|
|
156
176
|
}), {
|
|
157
177
|
signature: i,
|
|
158
178
|
depositorBtcPubkey: r
|
|
@@ -183,19 +203,19 @@ class z {
|
|
|
183
203
|
* @throws Error if wallet doesn't support batch signing
|
|
184
204
|
* @throws Error if any signing operation fails
|
|
185
205
|
*/
|
|
186
|
-
async signPayoutTransactionsBatch(
|
|
206
|
+
async signPayoutTransactionsBatch(e) {
|
|
187
207
|
if (!this.supportsBatchSigning())
|
|
188
208
|
throw new Error(
|
|
189
209
|
"Wallet does not support batch signing (signPsbts method not available)"
|
|
190
210
|
);
|
|
191
211
|
const s = await this.config.btcWallet.getPublicKeyHex(), r = [], n = [], c = [];
|
|
192
|
-
for (const o of
|
|
212
|
+
for (const o of e) {
|
|
193
213
|
const { depositorPubkey: u } = p(
|
|
194
214
|
s,
|
|
195
215
|
o.depositorBtcPubkey
|
|
196
216
|
);
|
|
197
217
|
c.push(u);
|
|
198
|
-
const
|
|
218
|
+
const g = await b({
|
|
199
219
|
vaultCoreVersion: o.vaultCoreVersion,
|
|
200
220
|
payoutTxHex: o.payoutTxHex,
|
|
201
221
|
peginTxHex: o.peginTxHex,
|
|
@@ -211,68 +231,70 @@ class z {
|
|
|
211
231
|
registeredPayoutScriptPubKey: o.registeredPayoutScriptPubKey,
|
|
212
232
|
commissionBps: o.commissionBps,
|
|
213
233
|
protocolFeeRate: o.protocolFeeRate,
|
|
214
|
-
|
|
234
|
+
councilMembers: o.councilMembers,
|
|
235
|
+
councilQuorum: o.councilQuorum,
|
|
215
236
|
vkClaimerPayoutScriptPubKeys: o.vkClaimerPayoutScriptPubKeys,
|
|
216
237
|
vpCommissionScriptPubKey: o.vpCommissionScriptPubKey
|
|
217
238
|
});
|
|
218
|
-
r.push(
|
|
239
|
+
r.push(g.psbtHex), n.push(f(s, 1));
|
|
219
240
|
}
|
|
220
241
|
const i = await this.config.btcWallet.signPsbts(
|
|
221
242
|
r,
|
|
222
243
|
n
|
|
223
244
|
);
|
|
224
|
-
if (i.length !==
|
|
245
|
+
if (i.length !== e.length)
|
|
225
246
|
throw new Error(
|
|
226
|
-
`Expected ${
|
|
247
|
+
`Expected ${e.length} signed PSBTs but received ${i.length}`
|
|
227
248
|
);
|
|
228
249
|
const a = [];
|
|
229
|
-
for (let o = 0; o <
|
|
250
|
+
for (let o = 0; o < e.length; o++) {
|
|
230
251
|
const u = c[o];
|
|
231
252
|
y({
|
|
232
253
|
requestedPsbtHex: r[o],
|
|
233
254
|
returnedPsbtHex: i[o]
|
|
234
255
|
});
|
|
235
|
-
const
|
|
256
|
+
const g = d(
|
|
236
257
|
i[o],
|
|
237
258
|
u
|
|
238
259
|
);
|
|
239
|
-
|
|
260
|
+
x({
|
|
240
261
|
requestedPsbtHex: r[o],
|
|
241
|
-
signatureHex:
|
|
262
|
+
signatureHex: g,
|
|
242
263
|
signerXOnlyPubkeyHex: u,
|
|
243
|
-
inputIndex:
|
|
264
|
+
inputIndex: k
|
|
244
265
|
}), a.push({
|
|
245
|
-
payoutSignature:
|
|
266
|
+
payoutSignature: g,
|
|
246
267
|
depositorBtcPubkey: u
|
|
247
268
|
});
|
|
248
269
|
}
|
|
249
270
|
return a;
|
|
250
271
|
}
|
|
251
272
|
}
|
|
252
|
-
async function X(
|
|
253
|
-
if (
|
|
254
|
-
return [await
|
|
255
|
-
if (typeof
|
|
256
|
-
const n = await
|
|
257
|
-
if (n.length !==
|
|
273
|
+
async function X(t, e, s) {
|
|
274
|
+
if (e.length === 1)
|
|
275
|
+
return [await t.signPsbt(e[0], s == null ? void 0 : s[0])];
|
|
276
|
+
if (typeof t.signPsbts == "function") {
|
|
277
|
+
const n = await t.signPsbts(e, s);
|
|
278
|
+
if (n.length !== e.length)
|
|
258
279
|
throw new Error(
|
|
259
|
-
`Expected ${
|
|
280
|
+
`Expected ${e.length} signed PSBTs but received ${n.length}`
|
|
260
281
|
);
|
|
261
282
|
return n;
|
|
262
283
|
}
|
|
263
284
|
const r = [];
|
|
264
|
-
for (let n = 0; n <
|
|
265
|
-
r.push(await
|
|
285
|
+
for (let n = 0; n < e.length; n++)
|
|
286
|
+
r.push(await t.signPsbt(e[n], s == null ? void 0 : s[n]));
|
|
266
287
|
return r;
|
|
267
288
|
}
|
|
268
289
|
export {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
290
|
+
q as P,
|
|
291
|
+
W as a,
|
|
292
|
+
D as b,
|
|
293
|
+
C as c,
|
|
273
294
|
X as d,
|
|
274
295
|
F as f,
|
|
275
|
-
|
|
296
|
+
M as r,
|
|
297
|
+
$ as s,
|
|
276
298
|
L as v
|
|
277
299
|
};
|
|
278
|
-
//# sourceMappingURL=signPsbtsWithFallback-
|
|
300
|
+
//# sourceMappingURL=signPsbtsWithFallback-Bv79gLFe.js.map
|