@babylonlabs-io/ts-sdk 0.41.0 → 0.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PayoutManager-B5bovfkD.cjs → PayoutManager-BwYlPF2C.cjs} +2 -2
- package/dist/{PayoutManager-B5bovfkD.cjs.map → PayoutManager-BwYlPF2C.cjs.map} +1 -1
- package/dist/{PayoutManager-DChODEOJ.js → PayoutManager-CXDccwDN.js} +2 -2
- package/dist/{PayoutManager-DChODEOJ.js.map → PayoutManager-CXDccwDN.js.map} +1 -1
- package/dist/PeginManager-BOuzU8Zo.cjs +2 -0
- package/dist/PeginManager-BOuzU8Zo.cjs.map +1 -0
- package/dist/{PeginManager-D9ZZ8wx2.js → PeginManager-Bsou6AQV.js} +44 -47
- package/dist/PeginManager-Bsou6AQV.js.map +1 -0
- package/dist/{assertPsbtUnsignedTxMatches-r1svclbd.cjs → assertPsbtUnsignedTxMatches-CABhEADu.cjs} +2 -2
- package/dist/{assertPsbtUnsignedTxMatches-r1svclbd.cjs.map → assertPsbtUnsignedTxMatches-CABhEADu.cjs.map} +1 -1
- package/dist/{assertPsbtUnsignedTxMatches-CzVv57QF.js → assertPsbtUnsignedTxMatches-GHobJP-d.js} +2 -2
- package/dist/{assertPsbtUnsignedTxMatches-CzVv57QF.js.map → assertPsbtUnsignedTxMatches-GHobJP-d.js.map} +1 -1
- package/dist/{buildAndBroadcastRefund-fIHDHiFh.js → buildAndBroadcastRefund-37Bs7-V1.js} +4 -4
- package/dist/{buildAndBroadcastRefund-fIHDHiFh.js.map → buildAndBroadcastRefund-37Bs7-V1.js.map} +1 -1
- package/dist/{buildAndBroadcastRefund-Cj8JDI7F.cjs → buildAndBroadcastRefund-DbcNEsOv.cjs} +2 -2
- package/dist/{buildAndBroadcastRefund-Cj8JDI7F.cjs.map → buildAndBroadcastRefund-DbcNEsOv.cjs.map} +1 -1
- package/dist/{challengeAssert-DLEmAhT0.js → challengeAssert-ChqnvtRg.js} +2 -2
- package/dist/{challengeAssert-DLEmAhT0.js.map → challengeAssert-ChqnvtRg.js.map} +1 -1
- package/dist/{challengeAssert-rpDaS3fH.cjs → challengeAssert-Cmj_OG6V.cjs} +2 -2
- package/dist/{challengeAssert-rpDaS3fH.cjs.map → challengeAssert-Cmj_OG6V.cjs.map} +1 -1
- package/dist/{fundPeginTransaction-t-6TsHAY.js → fundPeginTransaction-C11tYf6I.js} +32 -33
- package/dist/fundPeginTransaction-C11tYf6I.js.map +1 -0
- package/dist/fundPeginTransaction-C8qsXxNV.cjs +2 -0
- package/dist/fundPeginTransaction-C8qsXxNV.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +9 -9
- package/dist/{noPayout-CS2wnluA.js → noPayout-BtP-R-b-.js} +2 -2
- package/dist/{noPayout-CS2wnluA.js.map → noPayout-BtP-R-b-.js.map} +1 -1
- package/dist/{noPayout-B06Z9RTe.cjs → noPayout-DliaHuc6.cjs} +2 -2
- package/dist/{noPayout-B06Z9RTe.cjs.map → noPayout-DliaHuc6.cjs.map} +1 -1
- package/dist/{reservation-hjXStM03.cjs → reservation-Cwf2u4vu.cjs} +2 -2
- package/dist/{reservation-hjXStM03.cjs.map → reservation-Cwf2u4vu.cjs.map} +1 -1
- package/dist/{reservation-CB-4FBPk.js → reservation-DNOGLBt4.js} +2 -2
- package/dist/{reservation-CB-4FBPk.js.map → reservation-DNOGLBt4.js.map} +1 -1
- package/dist/tbv/core/index.cjs +1 -1
- package/dist/tbv/core/index.js +9 -9
- package/dist/tbv/core/managers/PeginManager.d.ts.map +1 -1
- package/dist/tbv/core/managers/index.cjs +1 -1
- package/dist/tbv/core/managers/index.js +2 -2
- package/dist/tbv/core/primitives/index.cjs +1 -1
- package/dist/tbv/core/primitives/index.js +3 -3
- package/dist/tbv/core/services/index.cjs +1 -1
- package/dist/tbv/core/services/index.js +2 -2
- package/dist/tbv/core/utils/fee/constants.d.ts +8 -12
- package/dist/tbv/core/utils/fee/constants.d.ts.map +1 -1
- package/dist/tbv/core/utils/index.cjs +1 -1
- package/dist/tbv/core/utils/index.js +3 -3
- package/dist/tbv/index.cjs +1 -1
- package/dist/tbv/index.js +9 -9
- package/dist/{waitForTransactionReceiptSmartAware-tv1mtSIY.cjs → waitForTransactionReceiptSmartAware-BFMQFEzj.cjs} +2 -2
- package/dist/{waitForTransactionReceiptSmartAware-tv1mtSIY.cjs.map → waitForTransactionReceiptSmartAware-BFMQFEzj.cjs.map} +1 -1
- package/dist/{waitForTransactionReceiptSmartAware-CmgFXFza.js → waitForTransactionReceiptSmartAware-Dt5VcMK0.js} +2 -2
- package/dist/{waitForTransactionReceiptSmartAware-CmgFXFza.js.map → waitForTransactionReceiptSmartAware-Dt5VcMK0.js.map} +1 -1
- package/package.json +1 -1
- package/dist/PeginManager-D9ZZ8wx2.js.map +0 -1
- package/dist/PeginManager-UqbOj2oV.cjs +0 -2
- package/dist/PeginManager-UqbOj2oV.cjs.map +0 -1
- package/dist/fundPeginTransaction-BBE3wTjR.cjs +0 -2
- package/dist/fundPeginTransaction-BBE3wTjR.cjs.map +0 -1
- package/dist/fundPeginTransaction-t-6TsHAY.js.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";const h=require("@babylonlabs-io/babylon-tbv-rust-wasm"),i=require("buffer"),a=require("bitcoinjs-lib"),n=require("./bitcoin-CHfKAhcI.cjs"),A=require("./assertPsbtUnsignedTxMatches-
|
|
2
|
-
//# sourceMappingURL=noPayout-
|
|
1
|
+
"use strict";const h=require("@babylonlabs-io/babylon-tbv-rust-wasm"),i=require("buffer"),a=require("bitcoinjs-lib"),n=require("./bitcoin-CHfKAhcI.cjs"),A=require("./assertPsbtUnsignedTxMatches-CABhEADu.cjs");async function I(u){await h.initWasm();const{prePeginParams:e,fundedPrePeginTxHex:r,htlcVout:o,refundFee:P,hashlock:c}=u,m=A.normalizeAuthAnchorHash(e.authAnchorHash),s=new h.WasmPrePeginTx(e.depositorPubkey,e.vaultProviderPubkey,e.vaultKeeperPubkeys,e.universalChallengerPubkeys,[...e.hashlocks],new BigUint64Array(e.pegInAmounts),e.timelockRefund,e.feeRate,e.minPeginFeeRate,e.numLocalChallengers,e.councilQuorum,e.councilSize,e.network,m);let t=null;try{const l=s.getHtlcScriptPubKey(o).toLowerCase();t=s.fromFundedTransaction(r);const y=t.buildRefundTx(P,o),f=await h.getPrePeginHtlcConnectorInfo({depositorPubkey:e.depositorPubkey,vaultProviderPubkey:e.vaultProviderPubkey,vaultKeeperPubkeys:e.vaultKeeperPubkeys,universalChallengerPubkeys:e.universalChallengerPubkeys,hashlock:c,timelockRefund:e.timelockRefund,network:e.network}),H=r.startsWith("0x")?r.slice(2):r,g=a.Transaction.fromHex(H),b=g.outs[o];if(!b)throw new Error(`HTLC output at vout ${o} not found in funded Pre-PegIn tx (tx has ${g.outs.length} outputs)`);const k=n.uint8ArrayToHex(new Uint8Array(b.script)).toLowerCase();if(k!==l)throw new Error(`HTLC scriptPubKey mismatch at vout ${o}: reconstructed template expects ${l}, funded tx carries ${k}. Refund refused — the (hashlocks, pegInAmounts) vector does not match the on-chain commitment.`);const p=a.Transaction.fromHex(y);if(p.ins.length!==1)throw new Error(`Refund transaction must have exactly 1 input, got ${p.ins.length}`);const d=p.ins[0],w=g.getId(),T=n.uint8ArrayToHex(new Uint8Array(d.hash).slice().reverse());if(T!==w)throw new Error(`Refund input does not reference the Pre-PegIn transaction. Expected ${w}, got ${T}`);if(d.index!==o)throw new Error(`Refund input index ${d.index} does not match expected htlcVout ${o}`);const x=new a.Psbt;x.setVersion(p.version),x.setLocktime(p.locktime),x.addInput({hash:d.hash,index:d.index,sequence:d.sequence,witnessUtxo:{script:b.script,value:b.value},tapLeafScript:[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:i.Buffer.from(n.hexToUint8Array(f.refundScript)),controlBlock:i.Buffer.from(n.hexToUint8Array(f.refundControlBlock))}],tapInternalKey:i.Buffer.from(h.tapInternalPubkey)});for(const v of p.outs)x.addOutput({script:v.script,value:v.value});return{psbtHex:x.toHex()}}finally{t==null||t.free(),s.free()}}async function R(u){const e=n.stripHexPrefix(u.noPayoutTxHex),r=a.Transaction.fromHex(e),{noPayoutScript:o,noPayoutControlBlock:P}=await h.getAssertNoPayoutScriptInfo(u.connectorParams,u.challengerPubkey),c=n.hexToUint8Array(o),m=n.hexToUint8Array(P),s=new a.Psbt;s.setVersion(r.version),s.setLocktime(r.locktime);for(let t=0;t<r.ins.length;t++){const l=r.ins[t],y=u.prevouts[t];if(!y)throw new Error(`Missing prevout data for input ${t}`);const f={hash:l.hash,index:l.index,sequence:l.sequence,witnessUtxo:{script:i.Buffer.from(n.hexToUint8Array(n.stripHexPrefix(y.script_pubkey))),value:y.value}};t===0&&(f.tapLeafScript=[{leafVersion:n.TAPSCRIPT_LEAF_VERSION,script:i.Buffer.from(c),controlBlock:i.Buffer.from(m)}],f.tapInternalKey=i.Buffer.from(h.tapInternalPubkey)),s.addInput(f)}for(const t of r.outs)s.addOutput({script:t.script,value:t.value});return s.toHex()}function B(u,e,r){const o=a.Transaction.fromHex(n.stripHexPrefix(u));if(o.outs.length!==1)throw new Error(`NoPayout transaction must have exactly 1 output, got ${o.outs.length}`);const P=n.hexToUint8Array(n.processPublicKeyToXOnly(e)),{output:c}=a.payments.p2tr({internalPubkey:i.Buffer.from(P),network:n.getNetwork(r)});if(!c)throw new Error("Failed to derive challenger BIP-86 P2TR scriptPubKey for NoPayout output validation");if(!o.outs[0].script.equals(c))throw new Error("NoPayout transaction does not pay to the expected challenger BIP-86 P2TR address")}exports.assertNoPayoutOutputMatchesChallenger=B;exports.buildNoPayoutPsbt=R;exports.buildRefundPsbt=I;
|
|
2
|
+
//# sourceMappingURL=noPayout-DliaHuc6.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"noPayout-B06Z9RTe.cjs","sources":["../src/tbv/core/primitives/psbt/refund.ts","../src/tbv/core/primitives/psbt/noPayout.ts"],"sourcesContent":["/**\n * Refund PSBT Builder Primitive\n *\n * Builds an unsigned refund PSBT for a depositor to reclaim BTC from\n * a timed-out Pre-PegIn HTLC output via the refund script (leaf 1).\n *\n * The refund script enforces a CSV timelock (timelockRefund blocks) and\n * requires only the depositor's Schnorr signature — no vault provider or\n * keeper involvement.\n *\n * @module primitives/psbt/refund\n */\n\nimport {\n getPrePeginHtlcConnectorInfo,\n initWasm,\n tapInternalPubkey,\n WasmPrePeginTx,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport { TAPSCRIPT_LEAF_VERSION, hexToUint8Array, uint8ArrayToHex } from \"../utils/bitcoin\";\nimport { normalizeAuthAnchorHash, type PrePeginParams } from \"./pegin\";\n\n/**\n * Parameters for building a refund PSBT\n */\nexport interface BuildRefundPsbtParams {\n /** Same PrePeginParams used when the original Pre-PegIn tx was created */\n prePeginParams: PrePeginParams;\n /** Funded Pre-PegIn transaction hex (the tx whose HTLC output is being refunded) */\n fundedPrePeginTxHex: string;\n /** Index of the HTLC output in the Pre-PegIn transaction */\n htlcVout: number;\n /** Transaction fee in satoshis for the refund transaction */\n refundFee: bigint;\n /** SHA256 hash commitment for the HTLC (64 hex chars, no 0x prefix) */\n hashlock: string;\n}\n\n/**\n * Result of building a refund PSBT\n */\nexport interface BuildRefundPsbtResult {\n /** PSBT hex ready for depositor signing */\n psbtHex: string;\n}\n\n/**\n * Build a PSBT for signing the refund transaction.\n *\n * The refund transaction spends the Pre-PegIn HTLC output via leaf 1\n * (the refund script: `<timelockRefund> CSV DROP <depositorPubkey> CHECKSIG`).\n * The PSBT includes the tapLeafScript entry so the depositor's wallet can\n * sign using Taproot script-path spending.\n *\n * The input's sequence is set to `timelockRefund` by the WASM, enforcing\n * the Bitcoin CSV timelock. The refund broadcast will be rejected by the\n * network if the timelock has not yet expired.\n *\n * @param params - Refund PSBT parameters\n * @returns PSBT hex for depositor signing\n * @throws If the HTLC output at htlcVout is not found\n * @throws If the refund transaction does not have exactly 1 input\n */\nexport async function buildRefundPsbt(\n params: BuildRefundPsbtParams,\n): Promise<BuildRefundPsbtResult> {\n await initWasm();\n\n const { prePeginParams, fundedPrePeginTxHex, htlcVout, refundFee, hashlock } =\n params;\n\n // The 14th positional arg `auth_anchor_hash` is `Option<String>` in\n // the Rust WASM constructor (the 9th arg `min_pegin_fee_rate` requires\n // the two-rate constructor from btc-vault #1930). Production peg-ins\n // (PeginManager) always commit an OP_RETURN <PUSH32 SHA256(authAnchor)>\n // output at `vout = hashlocks.length`; the unfunded template must\n // include it so `fromFundedTransaction` aligns with the funded tx.\n // Normalize identically to the peg-in primitives (`0x` strip,\n // lowercase, length/charset validation) so a direct primitive caller\n // reusing successful peg-in params doesn't hand unnormalized bytes to\n // WASM. Pass `undefined` for legacy non-auth-anchored Pre-PegIns.\n const normalizedAuthAnchorHash = normalizeAuthAnchorHash(\n prePeginParams.authAnchorHash,\n );\n const unfundedTx = new (WasmPrePeginTx as unknown as new (\n depositor: string,\n vault_provider: string,\n vault_keepers: string[],\n universal_challengers: string[],\n hashlocks: string[],\n pegin_amounts: BigUint64Array,\n timelock_refund: number,\n fee_rate: bigint,\n min_pegin_fee_rate: bigint,\n num_local_challengers: number,\n council_quorum: number,\n council_size: number,\n network: string,\n auth_anchor_hash?: string,\n ) => typeof WasmPrePeginTx.prototype)(\n prePeginParams.depositorPubkey,\n prePeginParams.vaultProviderPubkey,\n prePeginParams.vaultKeeperPubkeys,\n prePeginParams.universalChallengerPubkeys,\n [...prePeginParams.hashlocks],\n new BigUint64Array(prePeginParams.pegInAmounts),\n prePeginParams.timelockRefund,\n prePeginParams.feeRate,\n prePeginParams.minPeginFeeRate,\n prePeginParams.numLocalChallengers,\n prePeginParams.councilQuorum,\n prePeginParams.councilSize,\n prePeginParams.network,\n normalizedAuthAnchorHash,\n );\n\n let fundedTx: WasmPrePeginTx | null = null;\n try {\n // Cross-check the reconstructed unfunded template against the funded\n // transaction: the WASM template's HTLC scriptPubKey at `htlcVout`\n // must equal the bytes the funded tx carries at the same output.\n // If they disagree, the template was reconstructed from the wrong\n // (hashlocks, amounts) vector — signing it would produce a refund\n // that does not spend the on-chain HTLC the depositor expects.\n // This is the explicit invariant the audit recommends: never sign a\n // refund whose template doesn't match the on-chain output bytes.\n const expectedHtlcScriptPubKey = unfundedTx\n .getHtlcScriptPubKey(htlcVout)\n .toLowerCase();\n\n fundedTx = unfundedTx.fromFundedTransaction(fundedPrePeginTxHex);\n\n const refundTxHex = fundedTx.buildRefundTx(refundFee, htlcVout);\n\n const htlcConnector = await getPrePeginHtlcConnectorInfo({\n depositorPubkey: prePeginParams.depositorPubkey,\n vaultProviderPubkey: prePeginParams.vaultProviderPubkey,\n vaultKeeperPubkeys: prePeginParams.vaultKeeperPubkeys,\n universalChallengerPubkeys: prePeginParams.universalChallengerPubkeys,\n hashlock,\n timelockRefund: prePeginParams.timelockRefund,\n network: prePeginParams.network,\n });\n\n const cleanPrePeginHex = fundedPrePeginTxHex.startsWith(\"0x\")\n ? fundedPrePeginTxHex.slice(2)\n : fundedPrePeginTxHex;\n const prePeginTx = Transaction.fromHex(cleanPrePeginHex);\n\n const htlcOutput = prePeginTx.outs[htlcVout];\n if (!htlcOutput) {\n throw new Error(\n `HTLC output at vout ${htlcVout} not found in funded Pre-PegIn tx ` +\n `(tx has ${prePeginTx.outs.length} outputs)`,\n );\n }\n\n const actualHtlcScriptPubKey = uint8ArrayToHex(\n new Uint8Array(htlcOutput.script),\n ).toLowerCase();\n if (actualHtlcScriptPubKey !== expectedHtlcScriptPubKey) {\n throw new Error(\n `HTLC scriptPubKey mismatch at vout ${htlcVout}: reconstructed ` +\n `template expects ${expectedHtlcScriptPubKey}, funded tx carries ` +\n `${actualHtlcScriptPubKey}. Refund refused — the (hashlocks, ` +\n `pegInAmounts) vector does not match the on-chain commitment.`,\n );\n }\n\n const refundTx = Transaction.fromHex(refundTxHex);\n\n if (refundTx.ins.length !== 1) {\n throw new Error(\n `Refund transaction must have exactly 1 input, got ${refundTx.ins.length}`,\n );\n }\n\n const refundInput = refundTx.ins[0];\n\n // Verify the refund input spends the correct Pre-PegIn HTLC output\n const prePeginTxid = prePeginTx.getId();\n const refundInputTxid = uint8ArrayToHex(\n new Uint8Array(refundInput.hash).slice().reverse(),\n );\n if (refundInputTxid !== prePeginTxid) {\n throw new Error(\n `Refund input does not reference the Pre-PegIn transaction. ` +\n `Expected ${prePeginTxid}, got ${refundInputTxid}`,\n );\n }\n if (refundInput.index !== htlcVout) {\n throw new Error(\n `Refund input index ${refundInput.index} does not match expected htlcVout ${htlcVout}`,\n );\n }\n\n const psbt = new Psbt();\n psbt.setVersion(refundTx.version);\n psbt.setLocktime(refundTx.locktime);\n\n psbt.addInput({\n hash: refundInput.hash,\n index: refundInput.index,\n sequence: refundInput.sequence,\n witnessUtxo: {\n script: htlcOutput.script,\n value: htlcOutput.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(hexToUint8Array(htlcConnector.refundScript)),\n controlBlock: Buffer.from(\n hexToUint8Array(htlcConnector.refundControlBlock),\n ),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n for (const output of refundTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return { psbtHex: psbt.toHex() };\n } finally {\n fundedTx?.free();\n unfundedTx.free();\n }\n}\n","/**\n * NoPayout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's NoPayout transaction\n * (depositor-as-claimer path, per challenger). The depositor signs input 0\n * using the NoPayout taproot script from WasmAssertPayoutNoPayoutConnector.\n *\n * @module primitives/psbt/noPayout\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — Assert output 0 NoPayout connector\n */\n\nimport {\n type AssertPayoutNoPayoutConnectorParams,\n type Network,\n getAssertNoPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction, payments } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n getNetwork,\n hexToUint8Array,\n processPublicKeyToXOnly,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a NoPayout PSBT\n */\nexport interface NoPayoutParams {\n /** NoPayout transaction hex (unsigned) from VP */\n noPayoutTxHex: string;\n /** Challenger's x-only public key (hex encoded) */\n challengerPubkey: string;\n /** Prevouts for all inputs [{script_pubkey, value}] from VP */\n prevouts: Array<{ script_pubkey: string; value: number }>;\n /** Parameters for the Assert Payout/NoPayout connector */\n connectorParams: AssertPayoutNoPayoutConnectorParams;\n}\n\n/**\n * Build unsigned NoPayout PSBT.\n *\n * The NoPayout transaction is specific to each challenger.\n * Input 0 is the one the depositor signs using the NoPayout taproot script path.\n *\n * @param params - NoPayout parameters\n * @returns Unsigned PSBT hex ready for signing\n */\nexport async function buildNoPayoutPsbt(\n params: NoPayoutParams,\n): Promise<string> {\n const noPayoutTxHex = stripHexPrefix(params.noPayoutTxHex);\n const noPayoutTx = Transaction.fromHex(noPayoutTxHex);\n\n // Get NoPayout script and control block for this challenger\n const { noPayoutScript, noPayoutControlBlock } =\n await getAssertNoPayoutScriptInfo(\n params.connectorParams,\n params.challengerPubkey,\n );\n\n const scriptBytes = hexToUint8Array(noPayoutScript);\n const controlBlockBytes = hexToUint8Array(noPayoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(noPayoutTx.version);\n psbt.setLocktime(noPayoutTx.locktime);\n\n // Add all inputs - depositor signs input 0 only\n for (let i = 0; i < noPayoutTx.ins.length; i++) {\n const input = noPayoutTx.ins[i];\n const prevout = params.prevouts[i];\n\n if (!prevout) {\n throw new Error(`Missing prevout data for input ${i}`);\n }\n\n const inputData: Parameters<typeof psbt.addInput>[0] = {\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: Buffer.from(hexToUint8Array(stripHexPrefix(prevout.script_pubkey))),\n value: prevout.value,\n },\n };\n\n // Input 0: depositor signs using taproot script path\n if (i === 0) {\n inputData.tapLeafScript = [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ];\n inputData.tapInternalKey = Buffer.from(tapInternalPubkey);\n }\n\n psbt.addInput(inputData);\n }\n\n // Add outputs\n for (const output of noPayoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n\n/**\n * Validate that a NoPayout transaction pays to the challenger via the\n * protocol-defined output structure: a single BIP-86 P2TR output derived from\n * the challenger's x-only pubkey.\n *\n * Mirrors the per-role payout output validation now inlined in\n * `buildPayoutPsbt` for the NoPayout path, where the sink is fixed by the\n * protocol rather than read from on-chain registration\n * (see `crates/vault/src/transactions/nopayout.rs::NoPayoutTx::new`).\n *\n * @param noPayoutTxHex - Raw NoPayout transaction hex\n * @param challengerPubkey - Challenger's x-only public key (hex)\n * @param network - Bitcoin network used to derive the P2TR scriptPubKey\n * @throws If the transaction does not have exactly one output\n * @throws If the single output's scriptPubKey does not equal the BIP-86 P2TR\n * scriptPubKey for the challenger\n */\nexport function assertNoPayoutOutputMatchesChallenger(\n noPayoutTxHex: string,\n challengerPubkey: string,\n network: Network,\n): void {\n const tx = Transaction.fromHex(stripHexPrefix(noPayoutTxHex));\n\n if (tx.outs.length !== 1) {\n throw new Error(\n `NoPayout transaction must have exactly 1 output, got ${tx.outs.length}`,\n );\n }\n\n const xOnly = hexToUint8Array(processPublicKeyToXOnly(challengerPubkey));\n const { output: expectedScript } = payments.p2tr({\n internalPubkey: Buffer.from(xOnly),\n network: getNetwork(network),\n });\n if (!expectedScript) {\n throw new Error(\n \"Failed to derive challenger BIP-86 P2TR scriptPubKey for NoPayout output validation\",\n );\n }\n\n if (!tx.outs[0].script.equals(expectedScript)) {\n throw new Error(\n \"NoPayout transaction does not pay to the expected challenger BIP-86 P2TR address\",\n );\n }\n}\n"],"names":["buildRefundPsbt","params","initWasm","prePeginParams","fundedPrePeginTxHex","htlcVout","refundFee","hashlock","normalizedAuthAnchorHash","normalizeAuthAnchorHash","unfundedTx","WasmPrePeginTx","fundedTx","expectedHtlcScriptPubKey","refundTxHex","htlcConnector","getPrePeginHtlcConnectorInfo","cleanPrePeginHex","prePeginTx","Transaction","htlcOutput","actualHtlcScriptPubKey","uint8ArrayToHex","refundTx","refundInput","prePeginTxid","refundInputTxid","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","hexToUint8Array","tapInternalPubkey","output","buildNoPayoutPsbt","noPayoutTxHex","stripHexPrefix","noPayoutTx","noPayoutScript","noPayoutControlBlock","getAssertNoPayoutScriptInfo","scriptBytes","controlBlockBytes","i","input","prevout","inputData","assertNoPayoutOutputMatchesChallenger","challengerPubkey","network","tx","xOnly","processPublicKeyToXOnly","expectedScript","payments","getNetwork"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"noPayout-DliaHuc6.cjs","sources":["../src/tbv/core/primitives/psbt/refund.ts","../src/tbv/core/primitives/psbt/noPayout.ts"],"sourcesContent":["/**\n * Refund PSBT Builder Primitive\n *\n * Builds an unsigned refund PSBT for a depositor to reclaim BTC from\n * a timed-out Pre-PegIn HTLC output via the refund script (leaf 1).\n *\n * The refund script enforces a CSV timelock (timelockRefund blocks) and\n * requires only the depositor's Schnorr signature — no vault provider or\n * keeper involvement.\n *\n * @module primitives/psbt/refund\n */\n\nimport {\n getPrePeginHtlcConnectorInfo,\n initWasm,\n tapInternalPubkey,\n WasmPrePeginTx,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction } from \"bitcoinjs-lib\";\n\nimport { TAPSCRIPT_LEAF_VERSION, hexToUint8Array, uint8ArrayToHex } from \"../utils/bitcoin\";\nimport { normalizeAuthAnchorHash, type PrePeginParams } from \"./pegin\";\n\n/**\n * Parameters for building a refund PSBT\n */\nexport interface BuildRefundPsbtParams {\n /** Same PrePeginParams used when the original Pre-PegIn tx was created */\n prePeginParams: PrePeginParams;\n /** Funded Pre-PegIn transaction hex (the tx whose HTLC output is being refunded) */\n fundedPrePeginTxHex: string;\n /** Index of the HTLC output in the Pre-PegIn transaction */\n htlcVout: number;\n /** Transaction fee in satoshis for the refund transaction */\n refundFee: bigint;\n /** SHA256 hash commitment for the HTLC (64 hex chars, no 0x prefix) */\n hashlock: string;\n}\n\n/**\n * Result of building a refund PSBT\n */\nexport interface BuildRefundPsbtResult {\n /** PSBT hex ready for depositor signing */\n psbtHex: string;\n}\n\n/**\n * Build a PSBT for signing the refund transaction.\n *\n * The refund transaction spends the Pre-PegIn HTLC output via leaf 1\n * (the refund script: `<timelockRefund> CSV DROP <depositorPubkey> CHECKSIG`).\n * The PSBT includes the tapLeafScript entry so the depositor's wallet can\n * sign using Taproot script-path spending.\n *\n * The input's sequence is set to `timelockRefund` by the WASM, enforcing\n * the Bitcoin CSV timelock. The refund broadcast will be rejected by the\n * network if the timelock has not yet expired.\n *\n * @param params - Refund PSBT parameters\n * @returns PSBT hex for depositor signing\n * @throws If the HTLC output at htlcVout is not found\n * @throws If the refund transaction does not have exactly 1 input\n */\nexport async function buildRefundPsbt(\n params: BuildRefundPsbtParams,\n): Promise<BuildRefundPsbtResult> {\n await initWasm();\n\n const { prePeginParams, fundedPrePeginTxHex, htlcVout, refundFee, hashlock } =\n params;\n\n // The 14th positional arg `auth_anchor_hash` is `Option<String>` in\n // the Rust WASM constructor (the 9th arg `min_pegin_fee_rate` requires\n // the two-rate constructor from btc-vault #1930). Production peg-ins\n // (PeginManager) always commit an OP_RETURN <PUSH32 SHA256(authAnchor)>\n // output at `vout = hashlocks.length`; the unfunded template must\n // include it so `fromFundedTransaction` aligns with the funded tx.\n // Normalize identically to the peg-in primitives (`0x` strip,\n // lowercase, length/charset validation) so a direct primitive caller\n // reusing successful peg-in params doesn't hand unnormalized bytes to\n // WASM. Pass `undefined` for legacy non-auth-anchored Pre-PegIns.\n const normalizedAuthAnchorHash = normalizeAuthAnchorHash(\n prePeginParams.authAnchorHash,\n );\n const unfundedTx = new (WasmPrePeginTx as unknown as new (\n depositor: string,\n vault_provider: string,\n vault_keepers: string[],\n universal_challengers: string[],\n hashlocks: string[],\n pegin_amounts: BigUint64Array,\n timelock_refund: number,\n fee_rate: bigint,\n min_pegin_fee_rate: bigint,\n num_local_challengers: number,\n council_quorum: number,\n council_size: number,\n network: string,\n auth_anchor_hash?: string,\n ) => typeof WasmPrePeginTx.prototype)(\n prePeginParams.depositorPubkey,\n prePeginParams.vaultProviderPubkey,\n prePeginParams.vaultKeeperPubkeys,\n prePeginParams.universalChallengerPubkeys,\n [...prePeginParams.hashlocks],\n new BigUint64Array(prePeginParams.pegInAmounts),\n prePeginParams.timelockRefund,\n prePeginParams.feeRate,\n prePeginParams.minPeginFeeRate,\n prePeginParams.numLocalChallengers,\n prePeginParams.councilQuorum,\n prePeginParams.councilSize,\n prePeginParams.network,\n normalizedAuthAnchorHash,\n );\n\n let fundedTx: WasmPrePeginTx | null = null;\n try {\n // Cross-check the reconstructed unfunded template against the funded\n // transaction: the WASM template's HTLC scriptPubKey at `htlcVout`\n // must equal the bytes the funded tx carries at the same output.\n // If they disagree, the template was reconstructed from the wrong\n // (hashlocks, amounts) vector — signing it would produce a refund\n // that does not spend the on-chain HTLC the depositor expects.\n // This is the explicit invariant the audit recommends: never sign a\n // refund whose template doesn't match the on-chain output bytes.\n const expectedHtlcScriptPubKey = unfundedTx\n .getHtlcScriptPubKey(htlcVout)\n .toLowerCase();\n\n fundedTx = unfundedTx.fromFundedTransaction(fundedPrePeginTxHex);\n\n const refundTxHex = fundedTx.buildRefundTx(refundFee, htlcVout);\n\n const htlcConnector = await getPrePeginHtlcConnectorInfo({\n depositorPubkey: prePeginParams.depositorPubkey,\n vaultProviderPubkey: prePeginParams.vaultProviderPubkey,\n vaultKeeperPubkeys: prePeginParams.vaultKeeperPubkeys,\n universalChallengerPubkeys: prePeginParams.universalChallengerPubkeys,\n hashlock,\n timelockRefund: prePeginParams.timelockRefund,\n network: prePeginParams.network,\n });\n\n const cleanPrePeginHex = fundedPrePeginTxHex.startsWith(\"0x\")\n ? fundedPrePeginTxHex.slice(2)\n : fundedPrePeginTxHex;\n const prePeginTx = Transaction.fromHex(cleanPrePeginHex);\n\n const htlcOutput = prePeginTx.outs[htlcVout];\n if (!htlcOutput) {\n throw new Error(\n `HTLC output at vout ${htlcVout} not found in funded Pre-PegIn tx ` +\n `(tx has ${prePeginTx.outs.length} outputs)`,\n );\n }\n\n const actualHtlcScriptPubKey = uint8ArrayToHex(\n new Uint8Array(htlcOutput.script),\n ).toLowerCase();\n if (actualHtlcScriptPubKey !== expectedHtlcScriptPubKey) {\n throw new Error(\n `HTLC scriptPubKey mismatch at vout ${htlcVout}: reconstructed ` +\n `template expects ${expectedHtlcScriptPubKey}, funded tx carries ` +\n `${actualHtlcScriptPubKey}. Refund refused — the (hashlocks, ` +\n `pegInAmounts) vector does not match the on-chain commitment.`,\n );\n }\n\n const refundTx = Transaction.fromHex(refundTxHex);\n\n if (refundTx.ins.length !== 1) {\n throw new Error(\n `Refund transaction must have exactly 1 input, got ${refundTx.ins.length}`,\n );\n }\n\n const refundInput = refundTx.ins[0];\n\n // Verify the refund input spends the correct Pre-PegIn HTLC output\n const prePeginTxid = prePeginTx.getId();\n const refundInputTxid = uint8ArrayToHex(\n new Uint8Array(refundInput.hash).slice().reverse(),\n );\n if (refundInputTxid !== prePeginTxid) {\n throw new Error(\n `Refund input does not reference the Pre-PegIn transaction. ` +\n `Expected ${prePeginTxid}, got ${refundInputTxid}`,\n );\n }\n if (refundInput.index !== htlcVout) {\n throw new Error(\n `Refund input index ${refundInput.index} does not match expected htlcVout ${htlcVout}`,\n );\n }\n\n const psbt = new Psbt();\n psbt.setVersion(refundTx.version);\n psbt.setLocktime(refundTx.locktime);\n\n psbt.addInput({\n hash: refundInput.hash,\n index: refundInput.index,\n sequence: refundInput.sequence,\n witnessUtxo: {\n script: htlcOutput.script,\n value: htlcOutput.value,\n },\n tapLeafScript: [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(hexToUint8Array(htlcConnector.refundScript)),\n controlBlock: Buffer.from(\n hexToUint8Array(htlcConnector.refundControlBlock),\n ),\n },\n ],\n tapInternalKey: Buffer.from(tapInternalPubkey),\n });\n\n for (const output of refundTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return { psbtHex: psbt.toHex() };\n } finally {\n fundedTx?.free();\n unfundedTx.free();\n }\n}\n","/**\n * NoPayout PSBT Builder\n *\n * Builds unsigned PSBTs for the depositor's NoPayout transaction\n * (depositor-as-claimer path, per challenger). The depositor signs input 0\n * using the NoPayout taproot script from WasmAssertPayoutNoPayoutConnector.\n *\n * @module primitives/psbt/noPayout\n * @see btc-vault crates/vault/docs/btc-transactions-spec.md — Assert output 0 NoPayout connector\n */\n\nimport {\n type AssertPayoutNoPayoutConnectorParams,\n type Network,\n getAssertNoPayoutScriptInfo,\n tapInternalPubkey,\n} from \"@babylonlabs-io/babylon-tbv-rust-wasm\";\nimport { Buffer } from \"buffer\";\nimport { Psbt, Transaction, payments } from \"bitcoinjs-lib\";\n\nimport {\n TAPSCRIPT_LEAF_VERSION,\n getNetwork,\n hexToUint8Array,\n processPublicKeyToXOnly,\n stripHexPrefix,\n} from \"../utils/bitcoin\";\n\n/**\n * Parameters for building a NoPayout PSBT\n */\nexport interface NoPayoutParams {\n /** NoPayout transaction hex (unsigned) from VP */\n noPayoutTxHex: string;\n /** Challenger's x-only public key (hex encoded) */\n challengerPubkey: string;\n /** Prevouts for all inputs [{script_pubkey, value}] from VP */\n prevouts: Array<{ script_pubkey: string; value: number }>;\n /** Parameters for the Assert Payout/NoPayout connector */\n connectorParams: AssertPayoutNoPayoutConnectorParams;\n}\n\n/**\n * Build unsigned NoPayout PSBT.\n *\n * The NoPayout transaction is specific to each challenger.\n * Input 0 is the one the depositor signs using the NoPayout taproot script path.\n *\n * @param params - NoPayout parameters\n * @returns Unsigned PSBT hex ready for signing\n */\nexport async function buildNoPayoutPsbt(\n params: NoPayoutParams,\n): Promise<string> {\n const noPayoutTxHex = stripHexPrefix(params.noPayoutTxHex);\n const noPayoutTx = Transaction.fromHex(noPayoutTxHex);\n\n // Get NoPayout script and control block for this challenger\n const { noPayoutScript, noPayoutControlBlock } =\n await getAssertNoPayoutScriptInfo(\n params.connectorParams,\n params.challengerPubkey,\n );\n\n const scriptBytes = hexToUint8Array(noPayoutScript);\n const controlBlockBytes = hexToUint8Array(noPayoutControlBlock);\n\n const psbt = new Psbt();\n psbt.setVersion(noPayoutTx.version);\n psbt.setLocktime(noPayoutTx.locktime);\n\n // Add all inputs - depositor signs input 0 only\n for (let i = 0; i < noPayoutTx.ins.length; i++) {\n const input = noPayoutTx.ins[i];\n const prevout = params.prevouts[i];\n\n if (!prevout) {\n throw new Error(`Missing prevout data for input ${i}`);\n }\n\n const inputData: Parameters<typeof psbt.addInput>[0] = {\n hash: input.hash,\n index: input.index,\n sequence: input.sequence,\n witnessUtxo: {\n script: Buffer.from(hexToUint8Array(stripHexPrefix(prevout.script_pubkey))),\n value: prevout.value,\n },\n };\n\n // Input 0: depositor signs using taproot script path\n if (i === 0) {\n inputData.tapLeafScript = [\n {\n leafVersion: TAPSCRIPT_LEAF_VERSION,\n script: Buffer.from(scriptBytes),\n controlBlock: Buffer.from(controlBlockBytes),\n },\n ];\n inputData.tapInternalKey = Buffer.from(tapInternalPubkey);\n }\n\n psbt.addInput(inputData);\n }\n\n // Add outputs\n for (const output of noPayoutTx.outs) {\n psbt.addOutput({\n script: output.script,\n value: output.value,\n });\n }\n\n return psbt.toHex();\n}\n\n/**\n * Validate that a NoPayout transaction pays to the challenger via the\n * protocol-defined output structure: a single BIP-86 P2TR output derived from\n * the challenger's x-only pubkey.\n *\n * Mirrors the per-role payout output validation now inlined in\n * `buildPayoutPsbt` for the NoPayout path, where the sink is fixed by the\n * protocol rather than read from on-chain registration\n * (see `crates/vault/src/transactions/nopayout.rs::NoPayoutTx::new`).\n *\n * @param noPayoutTxHex - Raw NoPayout transaction hex\n * @param challengerPubkey - Challenger's x-only public key (hex)\n * @param network - Bitcoin network used to derive the P2TR scriptPubKey\n * @throws If the transaction does not have exactly one output\n * @throws If the single output's scriptPubKey does not equal the BIP-86 P2TR\n * scriptPubKey for the challenger\n */\nexport function assertNoPayoutOutputMatchesChallenger(\n noPayoutTxHex: string,\n challengerPubkey: string,\n network: Network,\n): void {\n const tx = Transaction.fromHex(stripHexPrefix(noPayoutTxHex));\n\n if (tx.outs.length !== 1) {\n throw new Error(\n `NoPayout transaction must have exactly 1 output, got ${tx.outs.length}`,\n );\n }\n\n const xOnly = hexToUint8Array(processPublicKeyToXOnly(challengerPubkey));\n const { output: expectedScript } = payments.p2tr({\n internalPubkey: Buffer.from(xOnly),\n network: getNetwork(network),\n });\n if (!expectedScript) {\n throw new Error(\n \"Failed to derive challenger BIP-86 P2TR scriptPubKey for NoPayout output validation\",\n );\n }\n\n if (!tx.outs[0].script.equals(expectedScript)) {\n throw new Error(\n \"NoPayout transaction does not pay to the expected challenger BIP-86 P2TR address\",\n );\n }\n}\n"],"names":["buildRefundPsbt","params","initWasm","prePeginParams","fundedPrePeginTxHex","htlcVout","refundFee","hashlock","normalizedAuthAnchorHash","normalizeAuthAnchorHash","unfundedTx","WasmPrePeginTx","fundedTx","expectedHtlcScriptPubKey","refundTxHex","htlcConnector","getPrePeginHtlcConnectorInfo","cleanPrePeginHex","prePeginTx","Transaction","htlcOutput","actualHtlcScriptPubKey","uint8ArrayToHex","refundTx","refundInput","prePeginTxid","refundInputTxid","psbt","Psbt","TAPSCRIPT_LEAF_VERSION","Buffer","hexToUint8Array","tapInternalPubkey","output","buildNoPayoutPsbt","noPayoutTxHex","stripHexPrefix","noPayoutTx","noPayoutScript","noPayoutControlBlock","getAssertNoPayoutScriptInfo","scriptBytes","controlBlockBytes","i","input","prevout","inputData","assertNoPayoutOutputMatchesChallenger","challengerPubkey","network","tx","xOnly","processPublicKeyToXOnly","expectedScript","payments","getNetwork"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var m=Object.defineProperty;var T=(n,t,e)=>t in n?m(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var l=(n,t,e)=>T(n,typeof t!="symbol"?t+"":t,e);const x=require("bitcoinjs-lib"),v=require("buffer"),w=require("./bitcoin-CHfKAhcI.cjs"),f=require("./peginState-BijNNT15.cjs"),c=require("./fundPeginTransaction-
|
|
2
|
-
//# sourceMappingURL=reservation-
|
|
1
|
+
"use strict";var m=Object.defineProperty;var T=(n,t,e)=>t in n?m(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var l=(n,t,e)=>T(n,typeof t!="symbol"?t+"":t,e);const x=require("bitcoinjs-lib"),v=require("buffer"),w=require("./bitcoin-CHfKAhcI.cjs"),f=require("./peginState-BijNNT15.cjs"),c=require("./fundPeginTransaction-C8qsXxNV.cjs");class h extends Error{constructor(e){const r=e.length,a=r===1?"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.":`${r} UTXOs for this peg-in are no longer available. They may have been spent. Please create a new peg-in request with different UTXOs.`;super(a);l(this,"missingUtxos");this.name="UtxoNotAvailableError",this.missingUtxos=e}}function p(n){const t=n.startsWith("0x")?n.slice(2):n;let e;try{e=x.Transaction.fromHex(t)}catch(r){throw new Error(`Failed to parse BTC transaction: ${r instanceof Error?r.message:String(r)}`)}return e.ins.map(r=>({txid:v.Buffer.from(r.hash).reverse().toString("hex"),vout:r.index}))}function g(n,t){const e=p(n);if(e.length===0)throw new Error("Transaction has no inputs");const r=new Set;for(const o of e){const s=`${o.txid.toLowerCase()}:${o.vout}`;if(r.has(s))throw new Error(`Transaction contains duplicate input ${o.txid}:${o.vout}. This would produce an invalid Bitcoin transaction.`);r.add(s)}const a=new Set(t.map(o=>`${o.txid.toLowerCase()}:${o.vout}`)),i=[];for(const o of e){const s=`${o.txid.toLowerCase()}:${o.vout}`;a.has(s)||i.push({txid:o.txid,vout:o.vout})}return{allAvailable:i.length===0,missingUtxos:i,totalInputs:e.length}}function E(n,t){const e=g(n,t);if(!e.allAvailable)throw new h(e.missingUtxos)}function d(n){try{return x.Transaction.fromHex(w.stripHexPrefix(n)).ins.map(e=>({txid:v.Buffer.from(e.hash).reverse().toString("hex"),vout:e.index}))}catch(t){return console.warn("[utxoReservation] Failed to parse transaction hex; skipping inputs",{category:"utxoReservation",error:t instanceof Error?t.message:String(t)}),[]}}function S(n,t){const e=n.txid.toLowerCase();return t.some(r=>r.txid.toLowerCase()===e&&r.vout===n.vout)}function b(n){const e=2*c.P2TR_INPUT_SIZE+c.MAX_NON_LEGACY_OUTPUT_SIZE+c.MAX_NON_LEGACY_OUTPUT_SIZE+c.TX_BUFFER_SIZE_OVERHEAD,r=Math.ceil(e*n*c.FEE_SAFETY_MARGIN);return BigInt(r)}function A(n){const t=[],{vaults:e=[],pendingPegins:r=[],utxoReservations:a=[]}=n,i=new Set(e.map(o=>{var s;return(s=o.id)==null?void 0:s.toLowerCase()}).filter(o=>o!==void 0));for(const o of r)o.id&&i.has(o.id.toLowerCase())||o.unsignedTxHex&&t.push(...d(o.unsignedTxHex));for(const o of e)o.status!==f.ContractStatus.PENDING&&o.status!==f.ContractStatus.VERIFIED||t.push(...d(o.unsignedPrePeginTx));for(const o of a)for(const s of o.outpoints)t.push({txid:s.txid,vout:s.vout});return t}function I(n){const{availableUtxos:t,reservedUtxoRefs:e,requiredAmount:r,feeRate:a}=n;if(!t||t.length===0)return[];if(e.length===0)return t;const i=t.filter(u=>!S(u,e));if(i.length===0)throw new Error("All available UTXOs are reserved by pending deposits. Wait for pending deposits to confirm or cancel them before starting a new deposit.");const o=b(a),s=r+o;if(i.reduce((u,U)=>u+BigInt(U.value),0n)<s)throw new Error("Insufficient unreserved UTXOs for this deposit amount. Wait for pending deposits to confirm or cancel them.");return i}exports.UtxoNotAvailableError=h;exports.assertUtxosAvailable=E;exports.collectReservedUtxoRefs=A;exports.extractInputsFromTransaction=p;exports.selectUtxosForDeposit=I;exports.validateUtxosAvailable=g;
|
|
2
|
+
//# sourceMappingURL=reservation-Cwf2u4vu.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reservation-hjXStM03.cjs","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\nimport type { UtxoRef } from \"./reservation\";\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 // Create a set of available UTXOs for O(1) lookup (lowercase for consistency with reservation.ts)\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 * UTXO reservation utilities for vault deposits.\n *\n * Handles tracking which UTXOs are already in use by pending deposits\n * and selecting available UTXOs with smart fallback logic.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\nimport {\n FEE_SAFETY_MARGIN,\n MAX_NON_LEGACY_OUTPUT_SIZE,\n P2TR_INPUT_SIZE,\n TX_BUFFER_SIZE_OVERHEAD,\n} from \"../fee/constants\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A txid:vout pair uniquely identifying a UTXO (outpoint). */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/** Narrow structural type for pending pegin data. */\nexport interface PendingPeginLike {\n /**\n * Optional vault id. When present, used to skip pending pegins that are\n * already indexed on-chain so the canonical vault copy wins over a\n * tamperable off-chain entry.\n */\n id?: string;\n selectedUTXOs?: Array<{ txid: string; vout: number }>;\n unsignedTxHex?: string;\n}\n\n/** Narrow structural type for vault data. */\nexport interface VaultLike {\n /**\n * Optional vault id. When present, enables on-chain correlation with\n * pending pegins sharing the same id.\n */\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface SelectUtxosForDepositParams<\n T extends { txid: string; vout: number; value: number },\n> {\n /** All available UTXOs from the wallet. */\n availableUtxos: T[];\n /** UTXOs that are reserved/in-flight and should be avoided if possible. */\n reservedUtxoRefs: UtxoRef[];\n /** Required deposit amount in satoshis (excluding fees). */\n requiredAmount: bigint;\n /** Fee rate in sat/vB. Used to estimate fee buffer for sufficiency check. */\n feeRate: number;\n}\n\n/** Narrow structural type for early UTXO reservations (pre-ETH-registration). */\nexport interface UtxoReservationLike {\n outpoints: ReadonlyArray<{ txid: string; vout: number }>;\n}\n\nexport interface CollectReservedUtxoRefsParams {\n vaults?: VaultLike[];\n pendingPegins?: PendingPeginLike[];\n utxoReservations?: UtxoReservationLike[];\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Parse a transaction hex and return the UTXO references of all inputs.\n *\n * Parse failures are logged and yield no refs. A malformed hex from an\n * untrusted source (e.g. off-chain storage) must not silently collapse the\n * reservation set — logging makes tampering visible in telemetry instead\n * of swallowing the error.\n */\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => {\n const txid = Buffer.from(input.hash).reverse().toString(\"hex\");\n return { txid, vout: input.index };\n });\n } catch (error) {\n console.warn(\n \"[utxoReservation] Failed to parse transaction hex; skipping inputs\",\n {\n category: \"utxoReservation\",\n error: error instanceof Error ? error.message : String(error),\n },\n );\n return [];\n }\n}\n\n/** Check if a UTXO matches any reserved ref (case-insensitive txid comparison). */\nfunction isUtxoReserved(\n utxo: { txid: string; vout: number },\n reservedRefs: UtxoRef[],\n): boolean {\n const txidLower = utxo.txid.toLowerCase();\n return reservedRefs.some(\n (ref) => ref.txid.toLowerCase() === txidLower && ref.vout === utxo.vout,\n );\n}\n\n/**\n * Estimate minimum fee buffer for UTXO pre-selection.\n *\n * WARNING: This is a ROUGH ESTIMATE used only to check if unreserved UTXOs\n * are likely sufficient BEFORE the actual signing flow begins. The actual\n * fee calculation happens in the SDK's `selectUtxosForPegin` during signing.\n *\n * Assumptions:\n * - 2 inputs (conservative estimate for most deposits)\n * - 1 vault output (P2TR, 43 vBytes)\n * - 1 change output (P2TR, 43 vBytes)\n * - Transaction overhead (11 vBytes)\n * - 10% safety margin\n */\nfunction estimateMinimumFeeBuffer(feeRate: number): bigint {\n const ASSUMED_INPUTS = 2;\n\n const estimatedTxSize =\n ASSUMED_INPUTS * P2TR_INPUT_SIZE +\n MAX_NON_LEGACY_OUTPUT_SIZE + // vault output\n MAX_NON_LEGACY_OUTPUT_SIZE + // change output\n TX_BUFFER_SIZE_OVERHEAD;\n\n const estimatedFee = Math.ceil(estimatedTxSize * feeRate * FEE_SAFETY_MARGIN);\n return BigInt(estimatedFee);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Collect UTXO refs from in-flight deposits (PENDING/VERIFIED vaults and\n * pending pegins).\n *\n * On-chain vault data is canonical: for any pending pegin whose `id` matches\n * an indexed on-chain vault, the pending-pegin copy is ignored entirely —\n * the `vaults` branch below extracts refs from the indexer-supplied\n * `unsignedPrePeginTx` so tampered off-chain data cannot poison the\n * reservation set once the vault is indexed.\n *\n * For pegins not yet indexed, refs are derived from the stored\n * `unsignedTxHex` only. The `selectedUTXOs` sidecar is NOT used for\n * reservation: if it disagreed with the transaction's inputs (e.g. because\n * the off-chain source was tampered), trusting it would poison the reserved\n * set. The transaction hex must be validated at the source boundary before\n * being handed to this function; parsing and using its inputs is the single\n * source of truth here.\n */\nexport function collectReservedUtxoRefs(\n params: CollectReservedUtxoRefsParams,\n): UtxoRef[] {\n const reserved: UtxoRef[] = [];\n const {\n vaults = [],\n pendingPegins = [],\n utxoReservations = [],\n } = params;\n\n const onChainVaultIds = new Set(\n vaults\n .map((v) => v.id?.toLowerCase())\n .filter((id): id is string => id !== undefined),\n );\n\n for (const pending of pendingPegins) {\n if (pending.id && onChainVaultIds.has(pending.id.toLowerCase())) {\n continue;\n }\n if (pending.unsignedTxHex) {\n reserved.push(...extractInputUtxoRefs(pending.unsignedTxHex));\n }\n }\n\n for (const vault of vaults) {\n if (\n vault.status !== ContractStatus.PENDING &&\n vault.status !== ContractStatus.VERIFIED\n ) {\n continue;\n }\n reserved.push(...extractInputUtxoRefs(vault.unsignedPrePeginTx));\n }\n\n // Early reservations written before ETH registration to prevent cross-tab\n // UTXO conflicts. These are cleaned up when the deposit completes or fails.\n for (const reservation of utxoReservations) {\n for (const op of reservation.outpoints) {\n reserved.push({ txid: op.txid, vout: op.vout });\n }\n }\n\n return reserved;\n}\n\n/**\n * Select UTXOs for a deposit, filtering out reserved ones.\n *\n * Logic:\n * 1. Filter out reserved UTXOs from the available pool\n * 2. If unreserved UTXOs are sufficient for the required amount + estimated fee, return them\n * 3. Otherwise, throw — never silently reuse reserved UTXOs, as this risks double-spend\n * failures that strand registered-but-unbroadcastable vaults\n *\n * @param params - Selection parameters\n * @returns Array of unreserved UTXOs to use for the deposit\n * @throws When all UTXOs are reserved or unreserved UTXOs are insufficient\n */\nexport function selectUtxosForDeposit<\n T extends { txid: string; vout: number; value: number },\n>(params: SelectUtxosForDepositParams<T>): T[] {\n const { availableUtxos, reservedUtxoRefs, requiredAmount, feeRate } = params;\n\n // Edge case: no UTXOs available\n if (!availableUtxos || availableUtxos.length === 0) {\n return [];\n }\n\n // Edge case: no reservations, return all\n if (reservedUtxoRefs.length === 0) {\n return availableUtxos;\n }\n\n // Filter out reserved UTXOs\n const unreserved = availableUtxos.filter(\n (utxo) => !isUtxoReserved(utxo, reservedUtxoRefs),\n );\n\n if (unreserved.length === 0) {\n throw new Error(\n \"All available UTXOs are reserved by pending deposits. \" +\n \"Wait for pending deposits to confirm or cancel them before starting a new deposit.\",\n );\n }\n\n const feeBuffer = estimateMinimumFeeBuffer(feeRate);\n const totalRequired = requiredAmount + feeBuffer;\n const unreservedTotal = unreserved.reduce(\n (sum, u) => sum + BigInt(u.value),\n 0n,\n );\n if (unreservedTotal < totalRequired) {\n throw new Error(\n \"Insufficient unreserved UTXOs for this deposit amount. \" +\n \"Wait for pending deposits to confirm or cancel them.\",\n );\n }\n\n return unreserved;\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","isUtxoReserved","reservedRefs","txidLower","ref","estimateMinimumFeeBuffer","feeRate","estimatedTxSize","P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","estimatedFee","FEE_SAFETY_MARGIN","collectReservedUtxoRefs","params","reserved","vaults","pendingPegins","utxoReservations","onChainVaultIds","v","_a","id","pending","vault","ContractStatus","reservation","op","selectUtxosForDeposit","reservedUtxoRefs","requiredAmount","unreserved","feeBuffer","totalRequired","sum","u"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reservation-Cwf2u4vu.cjs","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\nimport type { UtxoRef } from \"./reservation\";\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 // Create a set of available UTXOs for O(1) lookup (lowercase for consistency with reservation.ts)\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 * UTXO reservation utilities for vault deposits.\n *\n * Handles tracking which UTXOs are already in use by pending deposits\n * and selecting available UTXOs with smart fallback logic.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\nimport {\n FEE_SAFETY_MARGIN,\n MAX_NON_LEGACY_OUTPUT_SIZE,\n P2TR_INPUT_SIZE,\n TX_BUFFER_SIZE_OVERHEAD,\n} from \"../fee/constants\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A txid:vout pair uniquely identifying a UTXO (outpoint). */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/** Narrow structural type for pending pegin data. */\nexport interface PendingPeginLike {\n /**\n * Optional vault id. When present, used to skip pending pegins that are\n * already indexed on-chain so the canonical vault copy wins over a\n * tamperable off-chain entry.\n */\n id?: string;\n selectedUTXOs?: Array<{ txid: string; vout: number }>;\n unsignedTxHex?: string;\n}\n\n/** Narrow structural type for vault data. */\nexport interface VaultLike {\n /**\n * Optional vault id. When present, enables on-chain correlation with\n * pending pegins sharing the same id.\n */\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface SelectUtxosForDepositParams<\n T extends { txid: string; vout: number; value: number },\n> {\n /** All available UTXOs from the wallet. */\n availableUtxos: T[];\n /** UTXOs that are reserved/in-flight and should be avoided if possible. */\n reservedUtxoRefs: UtxoRef[];\n /** Required deposit amount in satoshis (excluding fees). */\n requiredAmount: bigint;\n /** Fee rate in sat/vB. Used to estimate fee buffer for sufficiency check. */\n feeRate: number;\n}\n\n/** Narrow structural type for early UTXO reservations (pre-ETH-registration). */\nexport interface UtxoReservationLike {\n outpoints: ReadonlyArray<{ txid: string; vout: number }>;\n}\n\nexport interface CollectReservedUtxoRefsParams {\n vaults?: VaultLike[];\n pendingPegins?: PendingPeginLike[];\n utxoReservations?: UtxoReservationLike[];\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Parse a transaction hex and return the UTXO references of all inputs.\n *\n * Parse failures are logged and yield no refs. A malformed hex from an\n * untrusted source (e.g. off-chain storage) must not silently collapse the\n * reservation set — logging makes tampering visible in telemetry instead\n * of swallowing the error.\n */\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => {\n const txid = Buffer.from(input.hash).reverse().toString(\"hex\");\n return { txid, vout: input.index };\n });\n } catch (error) {\n console.warn(\n \"[utxoReservation] Failed to parse transaction hex; skipping inputs\",\n {\n category: \"utxoReservation\",\n error: error instanceof Error ? error.message : String(error),\n },\n );\n return [];\n }\n}\n\n/** Check if a UTXO matches any reserved ref (case-insensitive txid comparison). */\nfunction isUtxoReserved(\n utxo: { txid: string; vout: number },\n reservedRefs: UtxoRef[],\n): boolean {\n const txidLower = utxo.txid.toLowerCase();\n return reservedRefs.some(\n (ref) => ref.txid.toLowerCase() === txidLower && ref.vout === utxo.vout,\n );\n}\n\n/**\n * Estimate minimum fee buffer for UTXO pre-selection.\n *\n * WARNING: This is a ROUGH ESTIMATE used only to check if unreserved UTXOs\n * are likely sufficient BEFORE the actual signing flow begins. The actual\n * fee calculation happens in the SDK's `selectUtxosForPegin` during signing.\n *\n * Assumptions:\n * - 2 inputs (conservative estimate for most deposits)\n * - 1 vault output (P2TR, 43 vBytes)\n * - 1 change output (P2TR, 43 vBytes)\n * - Transaction overhead (11 vBytes)\n * - 10% safety margin\n */\nfunction estimateMinimumFeeBuffer(feeRate: number): bigint {\n const ASSUMED_INPUTS = 2;\n\n const estimatedTxSize =\n ASSUMED_INPUTS * P2TR_INPUT_SIZE +\n MAX_NON_LEGACY_OUTPUT_SIZE + // vault output\n MAX_NON_LEGACY_OUTPUT_SIZE + // change output\n TX_BUFFER_SIZE_OVERHEAD;\n\n const estimatedFee = Math.ceil(estimatedTxSize * feeRate * FEE_SAFETY_MARGIN);\n return BigInt(estimatedFee);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Collect UTXO refs from in-flight deposits (PENDING/VERIFIED vaults and\n * pending pegins).\n *\n * On-chain vault data is canonical: for any pending pegin whose `id` matches\n * an indexed on-chain vault, the pending-pegin copy is ignored entirely —\n * the `vaults` branch below extracts refs from the indexer-supplied\n * `unsignedPrePeginTx` so tampered off-chain data cannot poison the\n * reservation set once the vault is indexed.\n *\n * For pegins not yet indexed, refs are derived from the stored\n * `unsignedTxHex` only. The `selectedUTXOs` sidecar is NOT used for\n * reservation: if it disagreed with the transaction's inputs (e.g. because\n * the off-chain source was tampered), trusting it would poison the reserved\n * set. The transaction hex must be validated at the source boundary before\n * being handed to this function; parsing and using its inputs is the single\n * source of truth here.\n */\nexport function collectReservedUtxoRefs(\n params: CollectReservedUtxoRefsParams,\n): UtxoRef[] {\n const reserved: UtxoRef[] = [];\n const {\n vaults = [],\n pendingPegins = [],\n utxoReservations = [],\n } = params;\n\n const onChainVaultIds = new Set(\n vaults\n .map((v) => v.id?.toLowerCase())\n .filter((id): id is string => id !== undefined),\n );\n\n for (const pending of pendingPegins) {\n if (pending.id && onChainVaultIds.has(pending.id.toLowerCase())) {\n continue;\n }\n if (pending.unsignedTxHex) {\n reserved.push(...extractInputUtxoRefs(pending.unsignedTxHex));\n }\n }\n\n for (const vault of vaults) {\n if (\n vault.status !== ContractStatus.PENDING &&\n vault.status !== ContractStatus.VERIFIED\n ) {\n continue;\n }\n reserved.push(...extractInputUtxoRefs(vault.unsignedPrePeginTx));\n }\n\n // Early reservations written before ETH registration to prevent cross-tab\n // UTXO conflicts. These are cleaned up when the deposit completes or fails.\n for (const reservation of utxoReservations) {\n for (const op of reservation.outpoints) {\n reserved.push({ txid: op.txid, vout: op.vout });\n }\n }\n\n return reserved;\n}\n\n/**\n * Select UTXOs for a deposit, filtering out reserved ones.\n *\n * Logic:\n * 1. Filter out reserved UTXOs from the available pool\n * 2. If unreserved UTXOs are sufficient for the required amount + estimated fee, return them\n * 3. Otherwise, throw — never silently reuse reserved UTXOs, as this risks double-spend\n * failures that strand registered-but-unbroadcastable vaults\n *\n * @param params - Selection parameters\n * @returns Array of unreserved UTXOs to use for the deposit\n * @throws When all UTXOs are reserved or unreserved UTXOs are insufficient\n */\nexport function selectUtxosForDeposit<\n T extends { txid: string; vout: number; value: number },\n>(params: SelectUtxosForDepositParams<T>): T[] {\n const { availableUtxos, reservedUtxoRefs, requiredAmount, feeRate } = params;\n\n // Edge case: no UTXOs available\n if (!availableUtxos || availableUtxos.length === 0) {\n return [];\n }\n\n // Edge case: no reservations, return all\n if (reservedUtxoRefs.length === 0) {\n return availableUtxos;\n }\n\n // Filter out reserved UTXOs\n const unreserved = availableUtxos.filter(\n (utxo) => !isUtxoReserved(utxo, reservedUtxoRefs),\n );\n\n if (unreserved.length === 0) {\n throw new Error(\n \"All available UTXOs are reserved by pending deposits. \" +\n \"Wait for pending deposits to confirm or cancel them before starting a new deposit.\",\n );\n }\n\n const feeBuffer = estimateMinimumFeeBuffer(feeRate);\n const totalRequired = requiredAmount + feeBuffer;\n const unreservedTotal = unreserved.reduce(\n (sum, u) => sum + BigInt(u.value),\n 0n,\n );\n if (unreservedTotal < totalRequired) {\n throw new Error(\n \"Insufficient unreserved UTXOs for this deposit amount. \" +\n \"Wait for pending deposits to confirm or cancel them.\",\n );\n }\n\n return unreserved;\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","isUtxoReserved","reservedRefs","txidLower","ref","estimateMinimumFeeBuffer","feeRate","estimatedTxSize","P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","estimatedFee","FEE_SAFETY_MARGIN","collectReservedUtxoRefs","params","reserved","vaults","pendingPegins","utxoReservations","onChainVaultIds","v","_a","id","pending","vault","ContractStatus","reservation","op","selectUtxosForDeposit","reservedUtxoRefs","requiredAmount","unreserved","feeBuffer","totalRequired","sum","u"],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ import { Transaction as p } from "bitcoinjs-lib";
|
|
|
5
5
|
import { Buffer as h } from "buffer";
|
|
6
6
|
import { s as g } from "./bitcoin-B5aNKtsk.js";
|
|
7
7
|
import { C as f } from "./peginState-CBAlxgXk.js";
|
|
8
|
-
import { F as w, P as U, M as l, T } from "./fundPeginTransaction-
|
|
8
|
+
import { F as w, P as U, M as l, T } from "./fundPeginTransaction-C11tYf6I.js";
|
|
9
9
|
class E extends Error {
|
|
10
10
|
constructor(e) {
|
|
11
11
|
const r = e.length, a = r === 1 ? "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." : `${r} UTXOs for this peg-in are no longer available. They may have been spent. Please create a new peg-in request with different UTXOs.`;
|
|
@@ -140,4 +140,4 @@ export {
|
|
|
140
140
|
O as s,
|
|
141
141
|
I as v
|
|
142
142
|
};
|
|
143
|
-
//# sourceMappingURL=reservation-
|
|
143
|
+
//# sourceMappingURL=reservation-DNOGLBt4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reservation-CB-4FBPk.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\nimport type { UtxoRef } from \"./reservation\";\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 // Create a set of available UTXOs for O(1) lookup (lowercase for consistency with reservation.ts)\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 * UTXO reservation utilities for vault deposits.\n *\n * Handles tracking which UTXOs are already in use by pending deposits\n * and selecting available UTXOs with smart fallback logic.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\nimport {\n FEE_SAFETY_MARGIN,\n MAX_NON_LEGACY_OUTPUT_SIZE,\n P2TR_INPUT_SIZE,\n TX_BUFFER_SIZE_OVERHEAD,\n} from \"../fee/constants\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A txid:vout pair uniquely identifying a UTXO (outpoint). */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/** Narrow structural type for pending pegin data. */\nexport interface PendingPeginLike {\n /**\n * Optional vault id. When present, used to skip pending pegins that are\n * already indexed on-chain so the canonical vault copy wins over a\n * tamperable off-chain entry.\n */\n id?: string;\n selectedUTXOs?: Array<{ txid: string; vout: number }>;\n unsignedTxHex?: string;\n}\n\n/** Narrow structural type for vault data. */\nexport interface VaultLike {\n /**\n * Optional vault id. When present, enables on-chain correlation with\n * pending pegins sharing the same id.\n */\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface SelectUtxosForDepositParams<\n T extends { txid: string; vout: number; value: number },\n> {\n /** All available UTXOs from the wallet. */\n availableUtxos: T[];\n /** UTXOs that are reserved/in-flight and should be avoided if possible. */\n reservedUtxoRefs: UtxoRef[];\n /** Required deposit amount in satoshis (excluding fees). */\n requiredAmount: bigint;\n /** Fee rate in sat/vB. Used to estimate fee buffer for sufficiency check. */\n feeRate: number;\n}\n\n/** Narrow structural type for early UTXO reservations (pre-ETH-registration). */\nexport interface UtxoReservationLike {\n outpoints: ReadonlyArray<{ txid: string; vout: number }>;\n}\n\nexport interface CollectReservedUtxoRefsParams {\n vaults?: VaultLike[];\n pendingPegins?: PendingPeginLike[];\n utxoReservations?: UtxoReservationLike[];\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Parse a transaction hex and return the UTXO references of all inputs.\n *\n * Parse failures are logged and yield no refs. A malformed hex from an\n * untrusted source (e.g. off-chain storage) must not silently collapse the\n * reservation set — logging makes tampering visible in telemetry instead\n * of swallowing the error.\n */\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => {\n const txid = Buffer.from(input.hash).reverse().toString(\"hex\");\n return { txid, vout: input.index };\n });\n } catch (error) {\n console.warn(\n \"[utxoReservation] Failed to parse transaction hex; skipping inputs\",\n {\n category: \"utxoReservation\",\n error: error instanceof Error ? error.message : String(error),\n },\n );\n return [];\n }\n}\n\n/** Check if a UTXO matches any reserved ref (case-insensitive txid comparison). */\nfunction isUtxoReserved(\n utxo: { txid: string; vout: number },\n reservedRefs: UtxoRef[],\n): boolean {\n const txidLower = utxo.txid.toLowerCase();\n return reservedRefs.some(\n (ref) => ref.txid.toLowerCase() === txidLower && ref.vout === utxo.vout,\n );\n}\n\n/**\n * Estimate minimum fee buffer for UTXO pre-selection.\n *\n * WARNING: This is a ROUGH ESTIMATE used only to check if unreserved UTXOs\n * are likely sufficient BEFORE the actual signing flow begins. The actual\n * fee calculation happens in the SDK's `selectUtxosForPegin` during signing.\n *\n * Assumptions:\n * - 2 inputs (conservative estimate for most deposits)\n * - 1 vault output (P2TR, 43 vBytes)\n * - 1 change output (P2TR, 43 vBytes)\n * - Transaction overhead (11 vBytes)\n * - 10% safety margin\n */\nfunction estimateMinimumFeeBuffer(feeRate: number): bigint {\n const ASSUMED_INPUTS = 2;\n\n const estimatedTxSize =\n ASSUMED_INPUTS * P2TR_INPUT_SIZE +\n MAX_NON_LEGACY_OUTPUT_SIZE + // vault output\n MAX_NON_LEGACY_OUTPUT_SIZE + // change output\n TX_BUFFER_SIZE_OVERHEAD;\n\n const estimatedFee = Math.ceil(estimatedTxSize * feeRate * FEE_SAFETY_MARGIN);\n return BigInt(estimatedFee);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Collect UTXO refs from in-flight deposits (PENDING/VERIFIED vaults and\n * pending pegins).\n *\n * On-chain vault data is canonical: for any pending pegin whose `id` matches\n * an indexed on-chain vault, the pending-pegin copy is ignored entirely —\n * the `vaults` branch below extracts refs from the indexer-supplied\n * `unsignedPrePeginTx` so tampered off-chain data cannot poison the\n * reservation set once the vault is indexed.\n *\n * For pegins not yet indexed, refs are derived from the stored\n * `unsignedTxHex` only. The `selectedUTXOs` sidecar is NOT used for\n * reservation: if it disagreed with the transaction's inputs (e.g. because\n * the off-chain source was tampered), trusting it would poison the reserved\n * set. The transaction hex must be validated at the source boundary before\n * being handed to this function; parsing and using its inputs is the single\n * source of truth here.\n */\nexport function collectReservedUtxoRefs(\n params: CollectReservedUtxoRefsParams,\n): UtxoRef[] {\n const reserved: UtxoRef[] = [];\n const {\n vaults = [],\n pendingPegins = [],\n utxoReservations = [],\n } = params;\n\n const onChainVaultIds = new Set(\n vaults\n .map((v) => v.id?.toLowerCase())\n .filter((id): id is string => id !== undefined),\n );\n\n for (const pending of pendingPegins) {\n if (pending.id && onChainVaultIds.has(pending.id.toLowerCase())) {\n continue;\n }\n if (pending.unsignedTxHex) {\n reserved.push(...extractInputUtxoRefs(pending.unsignedTxHex));\n }\n }\n\n for (const vault of vaults) {\n if (\n vault.status !== ContractStatus.PENDING &&\n vault.status !== ContractStatus.VERIFIED\n ) {\n continue;\n }\n reserved.push(...extractInputUtxoRefs(vault.unsignedPrePeginTx));\n }\n\n // Early reservations written before ETH registration to prevent cross-tab\n // UTXO conflicts. These are cleaned up when the deposit completes or fails.\n for (const reservation of utxoReservations) {\n for (const op of reservation.outpoints) {\n reserved.push({ txid: op.txid, vout: op.vout });\n }\n }\n\n return reserved;\n}\n\n/**\n * Select UTXOs for a deposit, filtering out reserved ones.\n *\n * Logic:\n * 1. Filter out reserved UTXOs from the available pool\n * 2. If unreserved UTXOs are sufficient for the required amount + estimated fee, return them\n * 3. Otherwise, throw — never silently reuse reserved UTXOs, as this risks double-spend\n * failures that strand registered-but-unbroadcastable vaults\n *\n * @param params - Selection parameters\n * @returns Array of unreserved UTXOs to use for the deposit\n * @throws When all UTXOs are reserved or unreserved UTXOs are insufficient\n */\nexport function selectUtxosForDeposit<\n T extends { txid: string; vout: number; value: number },\n>(params: SelectUtxosForDepositParams<T>): T[] {\n const { availableUtxos, reservedUtxoRefs, requiredAmount, feeRate } = params;\n\n // Edge case: no UTXOs available\n if (!availableUtxos || availableUtxos.length === 0) {\n return [];\n }\n\n // Edge case: no reservations, return all\n if (reservedUtxoRefs.length === 0) {\n return availableUtxos;\n }\n\n // Filter out reserved UTXOs\n const unreserved = availableUtxos.filter(\n (utxo) => !isUtxoReserved(utxo, reservedUtxoRefs),\n );\n\n if (unreserved.length === 0) {\n throw new Error(\n \"All available UTXOs are reserved by pending deposits. \" +\n \"Wait for pending deposits to confirm or cancel them before starting a new deposit.\",\n );\n }\n\n const feeBuffer = estimateMinimumFeeBuffer(feeRate);\n const totalRequired = requiredAmount + feeBuffer;\n const unreservedTotal = unreserved.reduce(\n (sum, u) => sum + BigInt(u.value),\n 0n,\n );\n if (unreservedTotal < totalRequired) {\n throw new Error(\n \"Insufficient unreserved UTXOs for this deposit amount. \" +\n \"Wait for pending deposits to confirm or cancel them.\",\n );\n }\n\n return unreserved;\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","isUtxoReserved","reservedRefs","txidLower","ref","estimateMinimumFeeBuffer","feeRate","estimatedTxSize","P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","estimatedFee","FEE_SAFETY_MARGIN","collectReservedUtxoRefs","params","reserved","vaults","pendingPegins","utxoReservations","onChainVaultIds","v","_a","id","pending","vault","ContractStatus","reservation","op","selectUtxosForDeposit","reservedUtxoRefs","requiredAmount","unreserved","feeBuffer","totalRequired","sum","u"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reservation-DNOGLBt4.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\nimport type { UtxoRef } from \"./reservation\";\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 // Create a set of available UTXOs for O(1) lookup (lowercase for consistency with reservation.ts)\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 * UTXO reservation utilities for vault deposits.\n *\n * Handles tracking which UTXOs are already in use by pending deposits\n * and selecting available UTXOs with smart fallback logic.\n */\n\nimport { Transaction } from \"bitcoinjs-lib\";\nimport { Buffer } from \"buffer\";\n\nimport { stripHexPrefix } from \"../../primitives/utils/bitcoin\";\nimport { ContractStatus } from \"../../services/deposit/peginState\";\nimport {\n FEE_SAFETY_MARGIN,\n MAX_NON_LEGACY_OUTPUT_SIZE,\n P2TR_INPUT_SIZE,\n TX_BUFFER_SIZE_OVERHEAD,\n} from \"../fee/constants\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** A txid:vout pair uniquely identifying a UTXO (outpoint). */\nexport interface UtxoRef {\n txid: string;\n vout: number;\n}\n\n/** Narrow structural type for pending pegin data. */\nexport interface PendingPeginLike {\n /**\n * Optional vault id. When present, used to skip pending pegins that are\n * already indexed on-chain so the canonical vault copy wins over a\n * tamperable off-chain entry.\n */\n id?: string;\n selectedUTXOs?: Array<{ txid: string; vout: number }>;\n unsignedTxHex?: string;\n}\n\n/** Narrow structural type for vault data. */\nexport interface VaultLike {\n /**\n * Optional vault id. When present, enables on-chain correlation with\n * pending pegins sharing the same id.\n */\n id?: string;\n status: number;\n unsignedPrePeginTx: string;\n}\n\nexport interface SelectUtxosForDepositParams<\n T extends { txid: string; vout: number; value: number },\n> {\n /** All available UTXOs from the wallet. */\n availableUtxos: T[];\n /** UTXOs that are reserved/in-flight and should be avoided if possible. */\n reservedUtxoRefs: UtxoRef[];\n /** Required deposit amount in satoshis (excluding fees). */\n requiredAmount: bigint;\n /** Fee rate in sat/vB. Used to estimate fee buffer for sufficiency check. */\n feeRate: number;\n}\n\n/** Narrow structural type for early UTXO reservations (pre-ETH-registration). */\nexport interface UtxoReservationLike {\n outpoints: ReadonlyArray<{ txid: string; vout: number }>;\n}\n\nexport interface CollectReservedUtxoRefsParams {\n vaults?: VaultLike[];\n pendingPegins?: PendingPeginLike[];\n utxoReservations?: UtxoReservationLike[];\n}\n\n// ============================================================================\n// Internal Helpers\n// ============================================================================\n\n/**\n * Parse a transaction hex and return the UTXO references of all inputs.\n *\n * Parse failures are logged and yield no refs. A malformed hex from an\n * untrusted source (e.g. off-chain storage) must not silently collapse the\n * reservation set — logging makes tampering visible in telemetry instead\n * of swallowing the error.\n */\nfunction extractInputUtxoRefs(txHex: string): UtxoRef[] {\n try {\n const tx = Transaction.fromHex(stripHexPrefix(txHex));\n return tx.ins.map((input) => {\n const txid = Buffer.from(input.hash).reverse().toString(\"hex\");\n return { txid, vout: input.index };\n });\n } catch (error) {\n console.warn(\n \"[utxoReservation] Failed to parse transaction hex; skipping inputs\",\n {\n category: \"utxoReservation\",\n error: error instanceof Error ? error.message : String(error),\n },\n );\n return [];\n }\n}\n\n/** Check if a UTXO matches any reserved ref (case-insensitive txid comparison). */\nfunction isUtxoReserved(\n utxo: { txid: string; vout: number },\n reservedRefs: UtxoRef[],\n): boolean {\n const txidLower = utxo.txid.toLowerCase();\n return reservedRefs.some(\n (ref) => ref.txid.toLowerCase() === txidLower && ref.vout === utxo.vout,\n );\n}\n\n/**\n * Estimate minimum fee buffer for UTXO pre-selection.\n *\n * WARNING: This is a ROUGH ESTIMATE used only to check if unreserved UTXOs\n * are likely sufficient BEFORE the actual signing flow begins. The actual\n * fee calculation happens in the SDK's `selectUtxosForPegin` during signing.\n *\n * Assumptions:\n * - 2 inputs (conservative estimate for most deposits)\n * - 1 vault output (P2TR, 43 vBytes)\n * - 1 change output (P2TR, 43 vBytes)\n * - Transaction overhead (11 vBytes)\n * - 10% safety margin\n */\nfunction estimateMinimumFeeBuffer(feeRate: number): bigint {\n const ASSUMED_INPUTS = 2;\n\n const estimatedTxSize =\n ASSUMED_INPUTS * P2TR_INPUT_SIZE +\n MAX_NON_LEGACY_OUTPUT_SIZE + // vault output\n MAX_NON_LEGACY_OUTPUT_SIZE + // change output\n TX_BUFFER_SIZE_OVERHEAD;\n\n const estimatedFee = Math.ceil(estimatedTxSize * feeRate * FEE_SAFETY_MARGIN);\n return BigInt(estimatedFee);\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Collect UTXO refs from in-flight deposits (PENDING/VERIFIED vaults and\n * pending pegins).\n *\n * On-chain vault data is canonical: for any pending pegin whose `id` matches\n * an indexed on-chain vault, the pending-pegin copy is ignored entirely —\n * the `vaults` branch below extracts refs from the indexer-supplied\n * `unsignedPrePeginTx` so tampered off-chain data cannot poison the\n * reservation set once the vault is indexed.\n *\n * For pegins not yet indexed, refs are derived from the stored\n * `unsignedTxHex` only. The `selectedUTXOs` sidecar is NOT used for\n * reservation: if it disagreed with the transaction's inputs (e.g. because\n * the off-chain source was tampered), trusting it would poison the reserved\n * set. The transaction hex must be validated at the source boundary before\n * being handed to this function; parsing and using its inputs is the single\n * source of truth here.\n */\nexport function collectReservedUtxoRefs(\n params: CollectReservedUtxoRefsParams,\n): UtxoRef[] {\n const reserved: UtxoRef[] = [];\n const {\n vaults = [],\n pendingPegins = [],\n utxoReservations = [],\n } = params;\n\n const onChainVaultIds = new Set(\n vaults\n .map((v) => v.id?.toLowerCase())\n .filter((id): id is string => id !== undefined),\n );\n\n for (const pending of pendingPegins) {\n if (pending.id && onChainVaultIds.has(pending.id.toLowerCase())) {\n continue;\n }\n if (pending.unsignedTxHex) {\n reserved.push(...extractInputUtxoRefs(pending.unsignedTxHex));\n }\n }\n\n for (const vault of vaults) {\n if (\n vault.status !== ContractStatus.PENDING &&\n vault.status !== ContractStatus.VERIFIED\n ) {\n continue;\n }\n reserved.push(...extractInputUtxoRefs(vault.unsignedPrePeginTx));\n }\n\n // Early reservations written before ETH registration to prevent cross-tab\n // UTXO conflicts. These are cleaned up when the deposit completes or fails.\n for (const reservation of utxoReservations) {\n for (const op of reservation.outpoints) {\n reserved.push({ txid: op.txid, vout: op.vout });\n }\n }\n\n return reserved;\n}\n\n/**\n * Select UTXOs for a deposit, filtering out reserved ones.\n *\n * Logic:\n * 1. Filter out reserved UTXOs from the available pool\n * 2. If unreserved UTXOs are sufficient for the required amount + estimated fee, return them\n * 3. Otherwise, throw — never silently reuse reserved UTXOs, as this risks double-spend\n * failures that strand registered-but-unbroadcastable vaults\n *\n * @param params - Selection parameters\n * @returns Array of unreserved UTXOs to use for the deposit\n * @throws When all UTXOs are reserved or unreserved UTXOs are insufficient\n */\nexport function selectUtxosForDeposit<\n T extends { txid: string; vout: number; value: number },\n>(params: SelectUtxosForDepositParams<T>): T[] {\n const { availableUtxos, reservedUtxoRefs, requiredAmount, feeRate } = params;\n\n // Edge case: no UTXOs available\n if (!availableUtxos || availableUtxos.length === 0) {\n return [];\n }\n\n // Edge case: no reservations, return all\n if (reservedUtxoRefs.length === 0) {\n return availableUtxos;\n }\n\n // Filter out reserved UTXOs\n const unreserved = availableUtxos.filter(\n (utxo) => !isUtxoReserved(utxo, reservedUtxoRefs),\n );\n\n if (unreserved.length === 0) {\n throw new Error(\n \"All available UTXOs are reserved by pending deposits. \" +\n \"Wait for pending deposits to confirm or cancel them before starting a new deposit.\",\n );\n }\n\n const feeBuffer = estimateMinimumFeeBuffer(feeRate);\n const totalRequired = requiredAmount + feeBuffer;\n const unreservedTotal = unreserved.reduce(\n (sum, u) => sum + BigInt(u.value),\n 0n,\n );\n if (unreservedTotal < totalRequired) {\n throw new Error(\n \"Insufficient unreserved UTXOs for this deposit amount. \" +\n \"Wait for pending deposits to confirm or cancel them.\",\n );\n }\n\n return unreserved;\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","isUtxoReserved","reservedRefs","txidLower","ref","estimateMinimumFeeBuffer","feeRate","estimatedTxSize","P2TR_INPUT_SIZE","MAX_NON_LEGACY_OUTPUT_SIZE","TX_BUFFER_SIZE_OVERHEAD","estimatedFee","FEE_SAFETY_MARGIN","collectReservedUtxoRefs","params","reserved","vaults","pendingPegins","utxoReservations","onChainVaultIds","v","_a","id","pending","vault","ContractStatus","reservation","op","selectUtxosForDeposit","reservedUtxoRefs","requiredAmount","unreserved","feeBuffer","totalRequired","sum","u"],"mappings":"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"}
|
package/dist/tbv/core/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../../challengeAssert-rpDaS3fH.cjs"),c=require("@babylonlabs-io/babylon-tbv-rust-wasm"),u=require("../../assertPsbtUnsignedTxMatches-r1svclbd.cjs"),A=require("../../peginInput-DH6X4ITS.cjs"),p=require("../../noPayout-B06Z9RTe.cjs"),r=require("../../bitcoin-CHfKAhcI.cjs"),g=require("../../signing-Bnsro0hE.cjs"),d=require("../../validation-u8W7Lp2x.cjs"),n=require("../../PeginManager-UqbOj2oV.cjs"),S=require("../../PayoutManager-B5bovfkD.cjs"),_=require("../../ProtocolParams.abi-DQhcqsNr.cjs"),m=require("../../BTCVaultRegistry.abi-CHFGevwa.cjs"),P=require("../../errors-BP73_stm.cjs"),i=require("../../waitForTransactionReceiptSmartAware-tv1mtSIY.cjs"),a=require("../../fundPeginTransaction-BBE3wTjR.cjs"),l=require("../../reservation-hjXStM03.cjs"),s=require("../../mempoolApi-DEAS9wVa.cjs"),t=require("../../types-Be3sAYzr.cjs"),o=require("../../types-eYlq0p1o.cjs"),R=require("../../errors-Bu0H-dZD.cjs"),e=require("../../buildAndBroadcastRefund-Cj8JDI7F.cjs"),T=require("../../peginState-BijNNT15.cjs");exports.buildChallengeAssertPsbt=E.buildChallengeAssertPsbt;exports.buildDepositorPayoutPsbt=E.buildDepositorPayoutPsbt;exports.computeNumLocalChallengers=E.computeNumLocalChallengers;Object.defineProperty(exports,"computeMinClaimValue",{enumerable:!0,get:()=>c.computeMinClaimValue});Object.defineProperty(exports,"deriveVaultId",{enumerable:!0,get:()=>c.deriveVaultId});Object.defineProperty(exports,"expandAuthAnchor",{enumerable:!0,get:()=>c.expandAuthAnchor});Object.defineProperty(exports,"expandHashlockSecret",{enumerable:!0,get:()=>c.expandHashlockSecret});Object.defineProperty(exports,"expandWotsSeed",{enumerable:!0,get:()=>c.expandWotsSeed});exports.PsbtSubstitutionError=u.PsbtSubstitutionError;exports.assertPsbtUnsignedTxMatches=u.assertPsbtUnsignedTxMatches;exports.buildPayoutPsbt=u.buildPayoutPsbt;exports.buildPeginTxFromFundedPrePegin=u.buildPeginTxFromFundedPrePegin;exports.buildPrePeginPsbt=u.buildPrePeginPsbt;exports.createPayoutScript=u.createPayoutScript;exports.extractPayoutSignature=u.extractPayoutSignature;exports.buildPeginInputPsbt=A.buildPeginInputPsbt;exports.extractPeginInputSignature=A.extractPeginInputSignature;exports.finalizePeginInputPsbt=A.finalizePeginInputPsbt;exports.buildNoPayoutPsbt=p.buildNoPayoutPsbt;exports.buildRefundPsbt=p.buildRefundPsbt;exports.deriveBip86ScriptPubKeyHex=r.deriveBip86ScriptPubKeyHex;exports.deriveNativeSegwitAddress=r.deriveNativeSegwitAddress;exports.deriveTaprootAddress=r.deriveTaprootAddress;exports.ensureHexPrefix=r.ensureHexPrefix;exports.formatSatoshisToBtc=r.formatSatoshisToBtc;exports.getNetwork=r.getNetwork;exports.getSortedXOnlyPubkeys=r.getSortedXOnlyPubkeys;exports.hexToUint8Array=r.hexToUint8Array;exports.isAddressFromPublicKey=r.isAddressFromPublicKey;exports.isValidHex=r.isValidHex;exports.processPublicKeyToXOnly=r.processPublicKeyToXOnly;exports.stripHexPrefix=r.stripHexPrefix;exports.toXOnly=r.toXOnly;exports.uint8ArrayToHex=r.uint8ArrayToHex;exports.validateWalletPubkey=r.validateWalletPubkey;exports.createTaprootScriptPathSignOptions=g.createTaprootScriptPathSignOptions;exports.BITCOIN_ADDRESS_RE=d.BITCOIN_ADDRESS_RE;exports.HEX_RE=d.HEX_RE;exports.KNOWN_SCRIPT_PREFIXES=d.KNOWN_SCRIPT_PREFIXES;exports.MAX_REASONABLE_FEE_SATS=d.MAX_REASONABLE_FEE_SATS;exports.TXID_RE=d.TXID_RE;exports.PeginManager=n.PeginManager;exports.VAULT_APP_NAME=n.VAULT_APP_NAME;exports.buildFundingOutpointsCommitment=n.buildFundingOutpointsCommitment;exports.buildVaultContext=n.buildVaultContext;exports.computeWotsBlockPublicKeysHash=n.computeWotsBlockPublicKeysHash;exports.deriveVaultRoot=n.deriveVaultRoot;exports.deriveWotsBlocksFromSeed=n.deriveWotsBlocksFromSeed;exports.estimateSubmitPeginRequestBatchGas=n.estimateSubmitPeginRequestBatchGas;exports.PayoutManager=S.PayoutManager;exports.computeHashlock=S.computeHashlock;exports.validateSecretAgainstHashlock=S.validateSecretAgainstHashlock;exports.ApplicationRegistryABI=_.ApplicationRegistryABI;exports.ProtocolParamsABI=_.ProtocolParamsABI;exports.BTCVaultRegistryABI=m.BTCVaultRegistryABI;exports.CONTRACT_ERRORS=P.CONTRACT_ERRORS;exports.extractErrorData=P.extractErrorData;exports.getContractErrorMessage=P.getContractErrorMessage;exports.handleContractError=P.handleContractError;exports.isKnownContractError=P.isKnownContractError;exports.BitcoinScriptType=i.BitcoinScriptType;exports.applyChangeOutputPolicy=i.applyChangeOutputPolicy;exports.calculateBtcTxHash=i.calculateBtcTxHash;exports.computeChangeOutputFeeSats=i.computeChangeOutputFeeSats;exports.computeMaxDeposit=i.computeMaxDeposit;exports.computePeginBaseFeeSats=i.computePeginBaseFeeSats;exports.getDustThreshold=i.getDustThreshold;exports.getPsbtInputFields=i.getPsbtInputFields;exports.getScriptType=i.getScriptType;exports.selectUtxosForPegin=i.selectUtxosForPegin;exports.shouldAddChangeOutput=i.shouldAddChangeOutput;exports.waitForTransactionReceiptSmartAware=i.waitForTransactionReceiptSmartAware;exports.BTC_DUST_SAT=a.BTC_DUST_SAT;exports.DUST_THRESHOLD=a.DUST_THRESHOLD;exports.FEE_SAFETY_MARGIN=a.FEE_SAFETY_MARGIN;exports.LOW_RATE_ESTIMATION_ACCURACY_BUFFER=a.LOW_RATE_ESTIMATION_ACCURACY_BUFFER;exports.MAX_NON_LEGACY_OUTPUT_SIZE=a.MAX_NON_LEGACY_OUTPUT_SIZE;exports.P2TR_INPUT_SIZE=a.P2TR_INPUT_SIZE;exports.PEGIN_AUTH_ANCHOR_OUTPUTS=a.PEGIN_AUTH_ANCHOR_OUTPUTS;exports.PEGIN_FIXED_OUTPUTS=a.PEGIN_FIXED_OUTPUTS;exports.SPLIT_TX_FEE_SAFETY_MULTIPLIER=a.SPLIT_TX_FEE_SAFETY_MULTIPLIER;exports.TX_BUFFER_SIZE_OVERHEAD=a.TX_BUFFER_SIZE_OVERHEAD;exports.WALLET_RELAY_FEE_RATE_THRESHOLD=a.WALLET_RELAY_FEE_RATE_THRESHOLD;exports.fundPeginTransaction=a.fundPeginTransaction;exports.parseUnfundedWasmTransaction=a.parseUnfundedWasmTransaction;exports.peginOutputCount=a.peginOutputCount;exports.rateBasedTxBufferFee=a.rateBasedTxBufferFee;exports.UtxoNotAvailableError=l.UtxoNotAvailableError;exports.assertUtxosAvailable=l.assertUtxosAvailable;exports.collectReservedUtxoRefs=l.collectReservedUtxoRefs;exports.extractInputsFromTransaction=l.extractInputsFromTransaction;exports.selectUtxosForDeposit=l.selectUtxosForDeposit;exports.validateUtxosAvailable=l.validateUtxosAvailable;exports.MEMPOOL_API_URLS=s.MEMPOOL_API_URLS;exports.getAddressTxs=s.getAddressTxs;exports.getAddressUtxos=s.getAddressUtxos;exports.getMempoolApiUrl=s.getMempoolApiUrl;exports.getNetworkFees=s.getNetworkFees;exports.getTipHeight=s.getTipHeight;exports.getTxHex=s.getTxHex;exports.getTxInfo=s.getTxInfo;exports.getUtxoInfo=s.getUtxoInfo;exports.pushTx=s.pushTx;exports.OnChainBtcVaultStatus=t.OnChainBtcVaultStatus;exports.ServerIdentityError=t.ServerIdentityError;exports.VaultProviderRpcClient=t.VaultProviderRpcClient;exports.ViemProtocolParamsReader=t.ViemProtocolParamsReader;exports.ViemUniversalChallengerReader=t.ViemUniversalChallengerReader;exports.ViemVaultKeeperReader=t.ViemVaultKeeperReader;exports.ViemVaultRegistryReader=t.ViemVaultRegistryReader;exports.VpResponseValidationError=t.VpResponseValidationError;exports.VpTokenRegistry=t.VpTokenRegistry;exports.batchPollByProvider=t.batchPollByProvider;exports.createAuthenticatedVpClient=t.createAuthenticatedVpClient;exports.primeVpTokenRegistry=t.primeVpTokenRegistry;exports.resolveProtocolAddresses=t.resolveProtocolAddresses;exports.validateOffchainParams=t.validateOffchainParams;exports.validatePegInConfiguration=t.validatePegInConfiguration;exports.validateRequestDepositorClaimerArtifactsResponse=t.validateRequestDepositorClaimerArtifactsResponse;exports.validateTBVProtocolParams=t.validateTBVProtocolParams;exports.verifyServerIdentity=t.verifyServerIdentity;exports.vpTokenRegistry=t.vpTokenRegistry;exports.AUTH_EXPIRED_DATA_KIND=o.AUTH_EXPIRED_DATA_KIND;exports.DaemonStatus=o.DaemonStatus;exports.JSON_RPC_ERROR_CODES=o.JSON_RPC_ERROR_CODES;exports.JsonRpcClient=o.JsonRpcClient;exports.JsonRpcError=o.JsonRpcError;exports.POST_WOTS_STATUSES=o.POST_WOTS_STATUSES;exports.PRE_DEPOSITOR_SIGNATURES_STATES=o.PRE_DEPOSITOR_SIGNATURES_STATES;exports.RpcErrorCode=o.RpcErrorCode;exports.VP_BATCH_MAX_SIZE=o.VP_BATCH_MAX_SIZE;exports.VP_TERMINAL_FAILURE_STATUSES=o.VP_TERMINAL_FAILURE_STATUSES;exports.VP_TRANSIENT_STATUSES=o.VP_TRANSIENT_STATUSES;exports.isWotsMismatchError=R.isWotsMismatchError;exports.parseFundingOutpointsFromTx=R.parseFundingOutpointsFromTx;exports.BIP68NotMatureError=e.BIP68NotMatureError;exports.ClaimerPegoutStatusValue=e.ClaimerPegoutStatusValue;exports.REFUND_MAX_FEE_FRACTION_DENOMINATOR=e.REFUND_MAX_FEE_FRACTION_DENOMINATOR;exports.REFUND_MAX_FEE_FRACTION_NUMERATOR=e.REFUND_MAX_FEE_FRACTION_NUMERATOR;exports.REFUND_MAX_FEE_RATE_SATS_VB=e.REFUND_MAX_FEE_RATE_SATS_VB;exports.REFUND_VSIZE=e.REFUND_VSIZE;exports.RegisteredVaultVersionMismatchError=e.RegisteredVaultVersionMismatchError;exports.activateVault=e.activateVault;exports.buildAndBroadcastRefund=e.buildAndBroadcastRefund;exports.estimateRefundFeeSats=e.estimateRefundFeeSats;exports.isDepositAmountValid=e.isDepositAmountValid;exports.isPegoutTerminalStatus=e.isPegoutTerminalStatus;exports.isRecognizedPegoutStatus=e.isRecognizedPegoutStatus;exports.isRegisteredVaultVersionMismatchError=e.isRegisteredVaultVersionMismatchError;exports.runDepositorPresignFlow=e.runDepositorPresignFlow;exports.signDepositorGraph=e.signDepositorGraph;exports.submitWotsPublicKey=e.submitWotsPublicKey;exports.validateDepositAmount=e.validateDepositAmount;exports.validateMultiVaultDepositInputs=e.validateMultiVaultDepositInputs;exports.validateOnChainParticipantKeys=e.validateOnChainParticipantKeys;exports.validateProviderSelection=e.validateProviderSelection;exports.validateRemainingCapacity=e.validateRemainingCapacity;exports.validateVaultAmounts=e.validateVaultAmounts;exports.validateVaultProviderPubkey=e.validateVaultProviderPubkey;exports.verifyRegisteredVaultVersions=e.verifyRegisteredVaultVersions;exports.waitForPeginStatus=e.waitForPeginStatus;exports.ContractStatus=T.ContractStatus;exports.PeginAction=T.PeginAction;exports.canPerformAction=T.canPerformAction;exports.getPeginProtocolState=T.getPeginProtocolState;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const E=require("../../challengeAssert-Cmj_OG6V.cjs"),c=require("@babylonlabs-io/babylon-tbv-rust-wasm"),u=require("../../assertPsbtUnsignedTxMatches-CABhEADu.cjs"),A=require("../../peginInput-DH6X4ITS.cjs"),p=require("../../noPayout-DliaHuc6.cjs"),r=require("../../bitcoin-CHfKAhcI.cjs"),g=require("../../signing-Bnsro0hE.cjs"),d=require("../../validation-u8W7Lp2x.cjs"),n=require("../../PeginManager-BOuzU8Zo.cjs"),S=require("../../PayoutManager-BwYlPF2C.cjs"),_=require("../../ProtocolParams.abi-DQhcqsNr.cjs"),m=require("../../BTCVaultRegistry.abi-CHFGevwa.cjs"),P=require("../../errors-BP73_stm.cjs"),i=require("../../waitForTransactionReceiptSmartAware-BFMQFEzj.cjs"),a=require("../../fundPeginTransaction-C8qsXxNV.cjs"),l=require("../../reservation-Cwf2u4vu.cjs"),s=require("../../mempoolApi-DEAS9wVa.cjs"),t=require("../../types-Be3sAYzr.cjs"),o=require("../../types-eYlq0p1o.cjs"),R=require("../../errors-Bu0H-dZD.cjs"),e=require("../../buildAndBroadcastRefund-DbcNEsOv.cjs"),T=require("../../peginState-BijNNT15.cjs");exports.buildChallengeAssertPsbt=E.buildChallengeAssertPsbt;exports.buildDepositorPayoutPsbt=E.buildDepositorPayoutPsbt;exports.computeNumLocalChallengers=E.computeNumLocalChallengers;Object.defineProperty(exports,"computeMinClaimValue",{enumerable:!0,get:()=>c.computeMinClaimValue});Object.defineProperty(exports,"deriveVaultId",{enumerable:!0,get:()=>c.deriveVaultId});Object.defineProperty(exports,"expandAuthAnchor",{enumerable:!0,get:()=>c.expandAuthAnchor});Object.defineProperty(exports,"expandHashlockSecret",{enumerable:!0,get:()=>c.expandHashlockSecret});Object.defineProperty(exports,"expandWotsSeed",{enumerable:!0,get:()=>c.expandWotsSeed});exports.PsbtSubstitutionError=u.PsbtSubstitutionError;exports.assertPsbtUnsignedTxMatches=u.assertPsbtUnsignedTxMatches;exports.buildPayoutPsbt=u.buildPayoutPsbt;exports.buildPeginTxFromFundedPrePegin=u.buildPeginTxFromFundedPrePegin;exports.buildPrePeginPsbt=u.buildPrePeginPsbt;exports.createPayoutScript=u.createPayoutScript;exports.extractPayoutSignature=u.extractPayoutSignature;exports.buildPeginInputPsbt=A.buildPeginInputPsbt;exports.extractPeginInputSignature=A.extractPeginInputSignature;exports.finalizePeginInputPsbt=A.finalizePeginInputPsbt;exports.buildNoPayoutPsbt=p.buildNoPayoutPsbt;exports.buildRefundPsbt=p.buildRefundPsbt;exports.deriveBip86ScriptPubKeyHex=r.deriveBip86ScriptPubKeyHex;exports.deriveNativeSegwitAddress=r.deriveNativeSegwitAddress;exports.deriveTaprootAddress=r.deriveTaprootAddress;exports.ensureHexPrefix=r.ensureHexPrefix;exports.formatSatoshisToBtc=r.formatSatoshisToBtc;exports.getNetwork=r.getNetwork;exports.getSortedXOnlyPubkeys=r.getSortedXOnlyPubkeys;exports.hexToUint8Array=r.hexToUint8Array;exports.isAddressFromPublicKey=r.isAddressFromPublicKey;exports.isValidHex=r.isValidHex;exports.processPublicKeyToXOnly=r.processPublicKeyToXOnly;exports.stripHexPrefix=r.stripHexPrefix;exports.toXOnly=r.toXOnly;exports.uint8ArrayToHex=r.uint8ArrayToHex;exports.validateWalletPubkey=r.validateWalletPubkey;exports.createTaprootScriptPathSignOptions=g.createTaprootScriptPathSignOptions;exports.BITCOIN_ADDRESS_RE=d.BITCOIN_ADDRESS_RE;exports.HEX_RE=d.HEX_RE;exports.KNOWN_SCRIPT_PREFIXES=d.KNOWN_SCRIPT_PREFIXES;exports.MAX_REASONABLE_FEE_SATS=d.MAX_REASONABLE_FEE_SATS;exports.TXID_RE=d.TXID_RE;exports.PeginManager=n.PeginManager;exports.VAULT_APP_NAME=n.VAULT_APP_NAME;exports.buildFundingOutpointsCommitment=n.buildFundingOutpointsCommitment;exports.buildVaultContext=n.buildVaultContext;exports.computeWotsBlockPublicKeysHash=n.computeWotsBlockPublicKeysHash;exports.deriveVaultRoot=n.deriveVaultRoot;exports.deriveWotsBlocksFromSeed=n.deriveWotsBlocksFromSeed;exports.estimateSubmitPeginRequestBatchGas=n.estimateSubmitPeginRequestBatchGas;exports.PayoutManager=S.PayoutManager;exports.computeHashlock=S.computeHashlock;exports.validateSecretAgainstHashlock=S.validateSecretAgainstHashlock;exports.ApplicationRegistryABI=_.ApplicationRegistryABI;exports.ProtocolParamsABI=_.ProtocolParamsABI;exports.BTCVaultRegistryABI=m.BTCVaultRegistryABI;exports.CONTRACT_ERRORS=P.CONTRACT_ERRORS;exports.extractErrorData=P.extractErrorData;exports.getContractErrorMessage=P.getContractErrorMessage;exports.handleContractError=P.handleContractError;exports.isKnownContractError=P.isKnownContractError;exports.BitcoinScriptType=i.BitcoinScriptType;exports.applyChangeOutputPolicy=i.applyChangeOutputPolicy;exports.calculateBtcTxHash=i.calculateBtcTxHash;exports.computeChangeOutputFeeSats=i.computeChangeOutputFeeSats;exports.computeMaxDeposit=i.computeMaxDeposit;exports.computePeginBaseFeeSats=i.computePeginBaseFeeSats;exports.getDustThreshold=i.getDustThreshold;exports.getPsbtInputFields=i.getPsbtInputFields;exports.getScriptType=i.getScriptType;exports.selectUtxosForPegin=i.selectUtxosForPegin;exports.shouldAddChangeOutput=i.shouldAddChangeOutput;exports.waitForTransactionReceiptSmartAware=i.waitForTransactionReceiptSmartAware;exports.BTC_DUST_SAT=a.BTC_DUST_SAT;exports.DUST_THRESHOLD=a.DUST_THRESHOLD;exports.FEE_SAFETY_MARGIN=a.FEE_SAFETY_MARGIN;exports.LOW_RATE_ESTIMATION_ACCURACY_BUFFER=a.LOW_RATE_ESTIMATION_ACCURACY_BUFFER;exports.MAX_NON_LEGACY_OUTPUT_SIZE=a.MAX_NON_LEGACY_OUTPUT_SIZE;exports.P2TR_INPUT_SIZE=a.P2TR_INPUT_SIZE;exports.PEGIN_AUTH_ANCHOR_OUTPUTS=a.PEGIN_AUTH_ANCHOR_OUTPUTS;exports.PEGIN_FIXED_OUTPUTS=a.PEGIN_FIXED_OUTPUTS;exports.SPLIT_TX_FEE_SAFETY_MULTIPLIER=a.SPLIT_TX_FEE_SAFETY_MULTIPLIER;exports.TX_BUFFER_SIZE_OVERHEAD=a.TX_BUFFER_SIZE_OVERHEAD;exports.WALLET_RELAY_FEE_RATE_THRESHOLD=a.WALLET_RELAY_FEE_RATE_THRESHOLD;exports.fundPeginTransaction=a.fundPeginTransaction;exports.parseUnfundedWasmTransaction=a.parseUnfundedWasmTransaction;exports.peginOutputCount=a.peginOutputCount;exports.rateBasedTxBufferFee=a.rateBasedTxBufferFee;exports.UtxoNotAvailableError=l.UtxoNotAvailableError;exports.assertUtxosAvailable=l.assertUtxosAvailable;exports.collectReservedUtxoRefs=l.collectReservedUtxoRefs;exports.extractInputsFromTransaction=l.extractInputsFromTransaction;exports.selectUtxosForDeposit=l.selectUtxosForDeposit;exports.validateUtxosAvailable=l.validateUtxosAvailable;exports.MEMPOOL_API_URLS=s.MEMPOOL_API_URLS;exports.getAddressTxs=s.getAddressTxs;exports.getAddressUtxos=s.getAddressUtxos;exports.getMempoolApiUrl=s.getMempoolApiUrl;exports.getNetworkFees=s.getNetworkFees;exports.getTipHeight=s.getTipHeight;exports.getTxHex=s.getTxHex;exports.getTxInfo=s.getTxInfo;exports.getUtxoInfo=s.getUtxoInfo;exports.pushTx=s.pushTx;exports.OnChainBtcVaultStatus=t.OnChainBtcVaultStatus;exports.ServerIdentityError=t.ServerIdentityError;exports.VaultProviderRpcClient=t.VaultProviderRpcClient;exports.ViemProtocolParamsReader=t.ViemProtocolParamsReader;exports.ViemUniversalChallengerReader=t.ViemUniversalChallengerReader;exports.ViemVaultKeeperReader=t.ViemVaultKeeperReader;exports.ViemVaultRegistryReader=t.ViemVaultRegistryReader;exports.VpResponseValidationError=t.VpResponseValidationError;exports.VpTokenRegistry=t.VpTokenRegistry;exports.batchPollByProvider=t.batchPollByProvider;exports.createAuthenticatedVpClient=t.createAuthenticatedVpClient;exports.primeVpTokenRegistry=t.primeVpTokenRegistry;exports.resolveProtocolAddresses=t.resolveProtocolAddresses;exports.validateOffchainParams=t.validateOffchainParams;exports.validatePegInConfiguration=t.validatePegInConfiguration;exports.validateRequestDepositorClaimerArtifactsResponse=t.validateRequestDepositorClaimerArtifactsResponse;exports.validateTBVProtocolParams=t.validateTBVProtocolParams;exports.verifyServerIdentity=t.verifyServerIdentity;exports.vpTokenRegistry=t.vpTokenRegistry;exports.AUTH_EXPIRED_DATA_KIND=o.AUTH_EXPIRED_DATA_KIND;exports.DaemonStatus=o.DaemonStatus;exports.JSON_RPC_ERROR_CODES=o.JSON_RPC_ERROR_CODES;exports.JsonRpcClient=o.JsonRpcClient;exports.JsonRpcError=o.JsonRpcError;exports.POST_WOTS_STATUSES=o.POST_WOTS_STATUSES;exports.PRE_DEPOSITOR_SIGNATURES_STATES=o.PRE_DEPOSITOR_SIGNATURES_STATES;exports.RpcErrorCode=o.RpcErrorCode;exports.VP_BATCH_MAX_SIZE=o.VP_BATCH_MAX_SIZE;exports.VP_TERMINAL_FAILURE_STATUSES=o.VP_TERMINAL_FAILURE_STATUSES;exports.VP_TRANSIENT_STATUSES=o.VP_TRANSIENT_STATUSES;exports.isWotsMismatchError=R.isWotsMismatchError;exports.parseFundingOutpointsFromTx=R.parseFundingOutpointsFromTx;exports.BIP68NotMatureError=e.BIP68NotMatureError;exports.ClaimerPegoutStatusValue=e.ClaimerPegoutStatusValue;exports.REFUND_MAX_FEE_FRACTION_DENOMINATOR=e.REFUND_MAX_FEE_FRACTION_DENOMINATOR;exports.REFUND_MAX_FEE_FRACTION_NUMERATOR=e.REFUND_MAX_FEE_FRACTION_NUMERATOR;exports.REFUND_MAX_FEE_RATE_SATS_VB=e.REFUND_MAX_FEE_RATE_SATS_VB;exports.REFUND_VSIZE=e.REFUND_VSIZE;exports.RegisteredVaultVersionMismatchError=e.RegisteredVaultVersionMismatchError;exports.activateVault=e.activateVault;exports.buildAndBroadcastRefund=e.buildAndBroadcastRefund;exports.estimateRefundFeeSats=e.estimateRefundFeeSats;exports.isDepositAmountValid=e.isDepositAmountValid;exports.isPegoutTerminalStatus=e.isPegoutTerminalStatus;exports.isRecognizedPegoutStatus=e.isRecognizedPegoutStatus;exports.isRegisteredVaultVersionMismatchError=e.isRegisteredVaultVersionMismatchError;exports.runDepositorPresignFlow=e.runDepositorPresignFlow;exports.signDepositorGraph=e.signDepositorGraph;exports.submitWotsPublicKey=e.submitWotsPublicKey;exports.validateDepositAmount=e.validateDepositAmount;exports.validateMultiVaultDepositInputs=e.validateMultiVaultDepositInputs;exports.validateOnChainParticipantKeys=e.validateOnChainParticipantKeys;exports.validateProviderSelection=e.validateProviderSelection;exports.validateRemainingCapacity=e.validateRemainingCapacity;exports.validateVaultAmounts=e.validateVaultAmounts;exports.validateVaultProviderPubkey=e.validateVaultProviderPubkey;exports.verifyRegisteredVaultVersions=e.verifyRegisteredVaultVersions;exports.waitForPeginStatus=e.waitForPeginStatus;exports.ContractStatus=T.ContractStatus;exports.PeginAction=T.PeginAction;exports.canPerformAction=T.canPerformAction;exports.getPeginProtocolState=T.getPeginProtocolState;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/tbv/core/index.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { a as s, b as t, c as r } from "../../challengeAssert-
|
|
1
|
+
import { a as s, b as t, c as r } from "../../challengeAssert-ChqnvtRg.js";
|
|
2
2
|
import { computeMinClaimValue as i, deriveVaultId as n, expandAuthAnchor as u, expandHashlockSecret as l, expandWotsSeed as p } from "@babylonlabs-io/babylon-tbv-rust-wasm";
|
|
3
|
-
import { P, d as c, c as T, a as E, b as A, f as S, e as R } from "../../assertPsbtUnsignedTxMatches-
|
|
3
|
+
import { P, d as c, c as T, a as E, b as A, f as S, e as R } from "../../assertPsbtUnsignedTxMatches-GHobJP-d.js";
|
|
4
4
|
import { b as g, e as m, f as x } from "../../peginInput-BPRB9tUi.js";
|
|
5
|
-
import { a as b, b as I } from "../../noPayout-
|
|
5
|
+
import { a as b, b as I } from "../../noPayout-BtP-R-b-.js";
|
|
6
6
|
import { d as O, a as v, b as F, e as V, f as U, j as h, g as y, h as N, i as D, c as B, p as M, s as H, t as L, u as X, v as k } from "../../bitcoin-B5aNKtsk.js";
|
|
7
7
|
import { c as K } from "../../signing-DaLvGwQe.js";
|
|
8
8
|
import { B as G, H as Y, K as Z, M as J, T as j } from "../../validation-CxqROCno.js";
|
|
9
|
-
import { P as z, V as Q, b as $, a as aa, c as ea, f as sa, d as ta, e as ra } from "../../PeginManager-
|
|
10
|
-
import { P as ia, c as na, v as ua } from "../../PayoutManager-
|
|
9
|
+
import { P as z, V as Q, b as $, a as aa, c as ea, f as sa, d as ta, e as ra } from "../../PeginManager-Bsou6AQV.js";
|
|
10
|
+
import { P as ia, c as na, v as ua } from "../../PayoutManager-CXDccwDN.js";
|
|
11
11
|
import { A as pa, P as da } from "../../ProtocolParams.abi-C2brDWTI.js";
|
|
12
12
|
import { B as ca } from "../../BTCVaultRegistry.abi-Cq9-JlqT.js";
|
|
13
13
|
import { C as Ea, e as Aa, g as Sa, h as Ra, i as _a } from "../../errors-CznAK5NB.js";
|
|
14
|
-
import { B as ma, a as xa, f as fa, c as ba, b as Ia, d as Ca, g as Oa, i as va, h as Fa, s as Va, e as Ua, w as ha } from "../../waitForTransactionReceiptSmartAware-
|
|
15
|
-
import { B as Na, D as Da, F as Ba, L as Ma, M as Ha, P as La, b as Xa, a as ka, S as Wa, T as Ka, W as wa, f as Ga, c as Ya, p as Za, r as Ja } from "../../fundPeginTransaction-
|
|
16
|
-
import { U as qa, a as za, c as Qa, e as $a, s as ae, v as ee } from "../../reservation-
|
|
14
|
+
import { B as ma, a as xa, f as fa, c as ba, b as Ia, d as Ca, g as Oa, i as va, h as Fa, s as Va, e as Ua, w as ha } from "../../waitForTransactionReceiptSmartAware-Dt5VcMK0.js";
|
|
15
|
+
import { B as Na, D as Da, F as Ba, L as Ma, M as Ha, P as La, b as Xa, a as ka, S as Wa, T as Ka, W as wa, f as Ga, c as Ya, p as Za, r as Ja } from "../../fundPeginTransaction-C11tYf6I.js";
|
|
16
|
+
import { U as qa, a as za, c as Qa, e as $a, s as ae, v as ee } from "../../reservation-DNOGLBt4.js";
|
|
17
17
|
import { M as te, g as re, a as oe, b as ie, c as ne, d as ue, e as le, f as pe, h as de, p as Pe } from "../../mempoolApi-C7hkVkym.js";
|
|
18
18
|
import { O as Te, S as Ee, V as Ae, j as Se, k as Re, l as _e, m as ge, a as me, d as xe, b as fe, f as be, p as Ie, r as Ce, g as Oe, h as ve, v as Fe, i as Ve, c as Ue, e as he } from "../../types-0bvDGR4x.js";
|
|
19
19
|
import { A as Ne, D as De, b as Be, J as Me, a as He, d as Le, P as Xe, R as ke, e as We, c as Ke, V as we } from "../../types-BqGAMOZM.js";
|
|
20
20
|
import { i as Ye, p as Ze } from "../../errors-9AkghWyk.js";
|
|
21
|
-
import { B as je, C as qe, p as ze, q as Qe, t as $e, u as as, R as es, a as ss, n as ts, o as rs, i as os, m as is, l as ns, j as us, r as ls, b as ps, s as ds, v as Ps, g as cs, h as Ts, d as Es, c as As, e as Ss, f as Rs, k as _s, w as gs } from "../../buildAndBroadcastRefund-
|
|
21
|
+
import { B as je, C as qe, p as ze, q as Qe, t as $e, u as as, R as es, a as ss, n as ts, o as rs, i as os, m as is, l as ns, j as us, r as ls, b as ps, s as ds, v as Ps, g as cs, h as Ts, d as Es, c as As, e as Ss, f as Rs, k as _s, w as gs } from "../../buildAndBroadcastRefund-37Bs7-V1.js";
|
|
22
22
|
import { C as xs, P as fs, c as bs, g as Is } from "../../peginState-CBAlxgXk.js";
|
|
23
23
|
export {
|
|
24
24
|
Ne as AUTH_EXPIRED_DATA_KIND,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PeginManager.d.ts","sourceRoot":"","sources":["../../../../src/tbv/core/managers/PeginManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAcH,OAAO,EAIL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,GAAG,EACR,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,aAAa,EAAE,IAAI,EAAmB,MAAM,yBAAyB,CAAC;AACpF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAG1E,OAAO,EASL,KAAK,OAAO,EACb,MAAM,eAAe,CAAC;AASvB,OAAO,EAOL,KAAK,IAAI,EAGV,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"PeginManager.d.ts","sourceRoot":"","sources":["../../../../src/tbv/core/managers/PeginManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../../PeginManager-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("../../../PeginManager-BOuzU8Zo.cjs"),a=require("../../../PayoutManager-BwYlPF2C.cjs");exports.PeginManager=e.PeginManager;exports.estimateSubmitPeginRequestBatchGas=e.estimateSubmitPeginRequestBatchGas;exports.PayoutManager=a.PayoutManager;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as t, e as r } from "../../../PeginManager-
|
|
2
|
-
import { P as o } from "../../../PayoutManager-
|
|
1
|
+
import { P as t, e as r } from "../../../PeginManager-Bsou6AQV.js";
|
|
2
|
+
import { P as o } from "../../../PayoutManager-CXDccwDN.js";
|
|
3
3
|
export {
|
|
4
4
|
o as PayoutManager,
|
|
5
5
|
t as PeginManager,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../../../challengeAssert-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const i=require("../../../challengeAssert-Cmj_OG6V.cjs"),s=require("@babylonlabs-io/babylon-tbv-rust-wasm"),t=require("../../../assertPsbtUnsignedTxMatches-CABhEADu.cjs"),r=require("../../../peginInput-DH6X4ITS.cjs"),u=require("../../../noPayout-DliaHuc6.cjs"),e=require("../../../bitcoin-CHfKAhcI.cjs");exports.buildChallengeAssertPsbt=i.buildChallengeAssertPsbt;exports.buildDepositorPayoutPsbt=i.buildDepositorPayoutPsbt;exports.computeNumLocalChallengers=i.computeNumLocalChallengers;Object.defineProperty(exports,"computeMinClaimValue",{enumerable:!0,get:()=>s.computeMinClaimValue});Object.defineProperty(exports,"deriveVaultId",{enumerable:!0,get:()=>s.deriveVaultId});exports.PsbtSubstitutionError=t.PsbtSubstitutionError;exports.assertPsbtUnsignedTxMatches=t.assertPsbtUnsignedTxMatches;exports.buildPayoutPsbt=t.buildPayoutPsbt;exports.buildPeginTxFromFundedPrePegin=t.buildPeginTxFromFundedPrePegin;exports.buildPrePeginPsbt=t.buildPrePeginPsbt;exports.createPayoutScript=t.createPayoutScript;exports.extractPayoutSignature=t.extractPayoutSignature;exports.buildPeginInputPsbt=r.buildPeginInputPsbt;exports.extractPeginInputSignature=r.extractPeginInputSignature;exports.finalizePeginInputPsbt=r.finalizePeginInputPsbt;exports.buildNoPayoutPsbt=u.buildNoPayoutPsbt;exports.buildRefundPsbt=u.buildRefundPsbt;exports.deriveBip86ScriptPubKeyHex=e.deriveBip86ScriptPubKeyHex;exports.deriveNativeSegwitAddress=e.deriveNativeSegwitAddress;exports.deriveTaprootAddress=e.deriveTaprootAddress;exports.ensureHexPrefix=e.ensureHexPrefix;exports.formatSatoshisToBtc=e.formatSatoshisToBtc;exports.getSortedXOnlyPubkeys=e.getSortedXOnlyPubkeys;exports.hexToUint8Array=e.hexToUint8Array;exports.isAddressFromPublicKey=e.isAddressFromPublicKey;exports.isValidHex=e.isValidHex;exports.processPublicKeyToXOnly=e.processPublicKeyToXOnly;exports.stripHexPrefix=e.stripHexPrefix;exports.toXOnly=e.toXOnly;exports.uint8ArrayToHex=e.uint8ArrayToHex;exports.validateWalletPubkey=e.validateWalletPubkey;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a, b as t, c as r } from "../../../challengeAssert-
|
|
1
|
+
import { a, b as t, c as r } from "../../../challengeAssert-ChqnvtRg.js";
|
|
2
2
|
import { computeMinClaimValue as o, deriveVaultId as u } from "@babylonlabs-io/babylon-tbv-rust-wasm";
|
|
3
|
-
import { P as b, d, c as l, a as n, b as p, f as x, e as c } from "../../../assertPsbtUnsignedTxMatches-
|
|
3
|
+
import { P as b, d, c as l, a as n, b as p, f as x, e as c } from "../../../assertPsbtUnsignedTxMatches-GHobJP-d.js";
|
|
4
4
|
import { b as f, e as g, f as m } from "../../../peginInput-BPRB9tUi.js";
|
|
5
|
-
import { a as v, b as T } from "../../../noPayout-
|
|
5
|
+
import { a as v, b as T } from "../../../noPayout-BtP-R-b-.js";
|
|
6
6
|
import { d as A, a as H, b as I, e as C, f as F, g as K, h as N, i as O, c as V, p as X, s as k, t as B, u as M, v as U } from "../../../bitcoin-B5aNKtsk.js";
|
|
7
7
|
export {
|
|
8
8
|
b as PsbtSubstitutionError,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../../../PayoutManager-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("../../../PayoutManager-BwYlPF2C.cjs"),t=require("../../../buildAndBroadcastRefund-DbcNEsOv.cjs"),e=require("../../../peginState-BijNNT15.cjs");exports.computeHashlock=a.computeHashlock;exports.validateSecretAgainstHashlock=a.validateSecretAgainstHashlock;exports.BIP68NotMatureError=t.BIP68NotMatureError;exports.ClaimerPegoutStatusValue=t.ClaimerPegoutStatusValue;exports.REFUND_MAX_FEE_FRACTION_DENOMINATOR=t.REFUND_MAX_FEE_FRACTION_DENOMINATOR;exports.REFUND_MAX_FEE_FRACTION_NUMERATOR=t.REFUND_MAX_FEE_FRACTION_NUMERATOR;exports.REFUND_MAX_FEE_RATE_SATS_VB=t.REFUND_MAX_FEE_RATE_SATS_VB;exports.REFUND_VSIZE=t.REFUND_VSIZE;exports.RegisteredVaultVersionMismatchError=t.RegisteredVaultVersionMismatchError;exports.activateVault=t.activateVault;exports.buildAndBroadcastRefund=t.buildAndBroadcastRefund;exports.estimateRefundFeeSats=t.estimateRefundFeeSats;exports.isDepositAmountValid=t.isDepositAmountValid;exports.isPegoutTerminalStatus=t.isPegoutTerminalStatus;exports.isRecognizedPegoutStatus=t.isRecognizedPegoutStatus;exports.isRegisteredVaultVersionMismatchError=t.isRegisteredVaultVersionMismatchError;exports.runDepositorPresignFlow=t.runDepositorPresignFlow;exports.signDepositorGraph=t.signDepositorGraph;exports.submitWotsPublicKey=t.submitWotsPublicKey;exports.validateDepositAmount=t.validateDepositAmount;exports.validateMultiVaultDepositInputs=t.validateMultiVaultDepositInputs;exports.validateOnChainParticipantKeys=t.validateOnChainParticipantKeys;exports.validateProviderSelection=t.validateProviderSelection;exports.validateRemainingCapacity=t.validateRemainingCapacity;exports.validateVaultAmounts=t.validateVaultAmounts;exports.validateVaultProviderPubkey=t.validateVaultProviderPubkey;exports.verifyRegisteredVaultVersions=t.verifyRegisteredVaultVersions;exports.waitForPeginStatus=t.waitForPeginStatus;exports.ContractStatus=e.ContractStatus;exports.PeginAction=e.PeginAction;exports.canPerformAction=e.canPerformAction;exports.getPeginProtocolState=e.getPeginProtocolState;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { c as s, v as e } from "../../../PayoutManager-
|
|
2
|
-
import { B as o, C as r, p as u, q as n, t as l, u as c, R as d, a as R, n as g, o as E, i as m, m as A, l as P, j as p, r as v, b as V, s as _, v as F, g as S, h as D, d as N, c as M, e as f, f as C, k as h, w as T } from "../../../buildAndBroadcastRefund-
|
|
1
|
+
import { c as s, v as e } from "../../../PayoutManager-CXDccwDN.js";
|
|
2
|
+
import { B as o, C as r, p as u, q as n, t as l, u as c, R as d, a as R, n as g, o as E, i as m, m as A, l as P, j as p, r as v, b as V, s as _, v as F, g as S, h as D, d as N, c as M, e as f, f as C, k as h, w as T } from "../../../buildAndBroadcastRefund-37Bs7-V1.js";
|
|
3
3
|
import { C as O, P as b, c as y, g as U } from "../../../peginState-CBAlxgXk.js";
|
|
4
4
|
export {
|
|
5
5
|
o as BIP68NotMatureError,
|
|
@@ -41,24 +41,20 @@ export declare const PEGIN_AUTH_ANCHOR_OUTPUTS = 1;
|
|
|
41
41
|
*
|
|
42
42
|
* A Pre-PegIn tx has: N HTLC outputs (one per vault) + optional
|
|
43
43
|
* auth-anchor OP_RETURN output + fixed outputs (CPFP anchor). This
|
|
44
|
-
* count is used for fee estimation — the change output is handled
|
|
44
|
+
* count is used for fee estimation only — the change output is handled
|
|
45
45
|
* separately by `selectUtxosForPegin` when the change amount exceeds
|
|
46
46
|
* the dust threshold.
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* @param vaultCount - Number of vaults in the batch (≥1).
|
|
55
|
-
* @param authAnchorHash - The same auth-anchor commitment passed to
|
|
56
|
-
* `buildPrePeginPsbt`. Truthy → counts the
|
|
57
|
-
* OP_RETURN output in the budget.
|
|
48
|
+
* @param vaultCount - Number of vaults in the batch (≥1).
|
|
49
|
+
* @param hasAuthAnchor - Whether the Pre-PegIn will carry an auth-anchor
|
|
50
|
+
* OP_RETURN output. Pass the same value the
|
|
51
|
+
* caller will hand to `buildPrePeginPsbt`'s
|
|
52
|
+
* `authAnchorHash` (truthy ↔ true) so the fee
|
|
53
|
+
* budget stays in lockstep with the output set.
|
|
58
54
|
* @returns Total output count before change.
|
|
59
55
|
* @throws If `vaultCount` is not a positive integer.
|
|
60
56
|
*/
|
|
61
|
-
export declare function peginOutputCount(vaultCount: number,
|
|
57
|
+
export declare function peginOutputCount(vaultCount: number, hasAuthAnchor: boolean): number;
|
|
62
58
|
/**
|
|
63
59
|
* Safety multiplier for split transaction fee validation.
|
|
64
60
|
* The signed PSBT's fee rate and absolute fee must not exceed this multiple
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../src/tbv/core/utils/fee/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,KAAK,CAAC;AAGlC,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAG7C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAG1C,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC,oFAAoF;AACpF,eAAO,MAAM,cAAc,QAAuB,CAAC;AAGnD,eAAO,MAAM,mCAAmC,KAAK,CAAC;AAGtD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAGjD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../src/tbv/core/utils/fee/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,eAAO,MAAM,eAAe,KAAK,CAAC;AAGlC,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAG7C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAG1C,eAAO,MAAM,YAAY,MAAM,CAAC;AAEhC,oFAAoF;AACpF,eAAO,MAAM,cAAc,QAAuB,CAAC;AAGnD,eAAO,MAAM,mCAAmC,KAAK,CAAC;AAGtD,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAGjD,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAC;AAE3C;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,OAAO,GACrB,MAAM,CAWR;AAED;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,IAAI,CAAC"}
|