@atomicfinance/bitcoin-wallet-provider 4.0.0 → 4.0.2
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/.turbo/turbo-lint.log +1 -0
- package/.yalc/@node-dlc/core/.nyc_output/687a3c14-9765-45fd-a1fe-f7db3d56fee4.json +1 -0
- package/.yalc/@node-dlc/core/.nyc_output/processinfo/687a3c14-9765-45fd-a1fe-f7db3d56fee4.json +1 -0
- package/.yalc/@node-dlc/core/.nyc_output/processinfo/index.json +1 -0
- package/.yalc/@node-dlc/core/README.md +11 -0
- package/.yalc/@node-dlc/core/__tests__/core.spec.ts +7 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/CETCalculator.spec.ts +1029 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/CoinSelect.spec.ts +179 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/PolynomialPayoutCurve.spec.ts +345 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/TxBuilder.spec.ts +424 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/Builder.spec.ts +492 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/CoveredCall.spec.ts +112 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/CsoInfo.spec.ts +1124 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/LongCall.spec.ts +55 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/LongPut.spec.ts +55 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/OptionInfo.spec.ts +226 -0
- package/.yalc/@node-dlc/core/__tests__/dlc/finance/ShortPut.spec.ts +62 -0
- package/.yalc/@node-dlc/core/__tests__/tsconfig.json +8 -0
- package/.yalc/@node-dlc/core/__tests__/utils/precision.spec.ts +40 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/base.css +224 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/block-navigation.js +79 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/favicon.png +0 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/index.html +171 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/AsyncProcessingQueue.ts.html +269 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/Base32.ts.html +86 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/BigIntUtils.ts.html +86 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/BitField.ts.html +86 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/ChannelId.ts.html +86 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/LinkedList.ts.html +413 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/LinkedListNode.ts.html +122 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/Queue.ts.html +188 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/ShortChannelId.ts.html +86 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/ShortChannelIdUtils.ts.html +107 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/CETCalculator.ts.html +1430 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/CoinSelect.ts.html +431 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/HyperbolaPayoutCurve.ts.html +644 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/PolynomialPayoutCurve.ts.html +878 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/TxBuilder.ts.html +1088 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/TxFinalizer.ts.html +731 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/Builder.ts.html +2270 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/CoveredCall.ts.html +410 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/CsoInfo.ts.html +1574 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/LinearPayout.ts.html +362 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/LongCall.ts.html +302 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/LongPut.ts.html +302 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/OptionInfo.ts.html +626 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/ShortPut.ts.html +305 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/finance/index.html +216 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/dlc/index.html +186 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/index.html +261 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/index.ts.html +278 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/ChannelId.ts.html +242 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/ChannelKeys.ts.html +407 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/CommitmentNumber.ts.html +362 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/CommitmentSecret.ts.html +203 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/CommitmentSecretStore.ts.html +332 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/Htlc.ts.html +236 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/HtlcDirection.ts.html +131 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/ScriptFactory.ts.html +530 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/TxFactory.ts.html +1094 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/lightning/index.html +231 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/utils/BigIntUtils.ts.html +272 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/utils/Precision.ts.html +149 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/lib/utils/index.html +126 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/prettify.css +1 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/prettify.js +2 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/.yalc/@node-dlc/core/coverage/lcov-report/sorter.js +170 -0
- package/.yalc/@node-dlc/core/coverage/lcov.info +2426 -0
- package/.yalc/@node-dlc/core/dist/AsyncProcessingQueue.d.ts +22 -0
- package/.yalc/@node-dlc/core/dist/AsyncProcessingQueue.js +55 -0
- package/.yalc/@node-dlc/core/dist/AsyncProcessingQueue.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/Base32.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/Base32.js +7 -0
- package/.yalc/@node-dlc/core/dist/Base32.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/BigIntUtils.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/BigIntUtils.js +8 -0
- package/.yalc/@node-dlc/core/dist/BigIntUtils.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/BitField.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/BitField.js +7 -0
- package/.yalc/@node-dlc/core/dist/BitField.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/ChannelId.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/ChannelId.js +7 -0
- package/.yalc/@node-dlc/core/dist/ChannelId.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/LinkedList.d.ts +30 -0
- package/.yalc/@node-dlc/core/dist/LinkedList.js +104 -0
- package/.yalc/@node-dlc/core/dist/LinkedList.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/LinkedListNode.d.ts +9 -0
- package/.yalc/@node-dlc/core/dist/LinkedListNode.js +15 -0
- package/.yalc/@node-dlc/core/dist/LinkedListNode.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/Queue.d.ts +22 -0
- package/.yalc/@node-dlc/core/dist/Queue.js +38 -0
- package/.yalc/@node-dlc/core/dist/Queue.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelId.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelId.js +7 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelId.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelIdUtils.d.ts +1 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelIdUtils.js +12 -0
- package/.yalc/@node-dlc/core/dist/ShortChannelIdUtils.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/CETCalculator.d.ts +50 -0
- package/.yalc/@node-dlc/core/dist/dlc/CETCalculator.js +332 -0
- package/.yalc/@node-dlc/core/dist/dlc/CETCalculator.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/CoinSelect.d.ts +23 -0
- package/.yalc/@node-dlc/core/dist/dlc/CoinSelect.js +77 -0
- package/.yalc/@node-dlc/core/dist/dlc/CoinSelect.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/HyperbolaPayoutCurve.d.ts +20 -0
- package/.yalc/@node-dlc/core/dist/dlc/HyperbolaPayoutCurve.js +117 -0
- package/.yalc/@node-dlc/core/dist/dlc/HyperbolaPayoutCurve.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/PayoutCurve.d.ts +5 -0
- package/.yalc/@node-dlc/core/dist/dlc/PayoutCurve.js +3 -0
- package/.yalc/@node-dlc/core/dist/dlc/PayoutCurve.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/PolynomialPayoutCurve.d.ts +52 -0
- package/.yalc/@node-dlc/core/dist/dlc/PolynomialPayoutCurve.js +173 -0
- package/.yalc/@node-dlc/core/dist/dlc/PolynomialPayoutCurve.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxBuilder.d.ts +55 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxBuilder.js +217 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxBuilder.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxFinalizer.d.ts +40 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxFinalizer.js +146 -0
- package/.yalc/@node-dlc/core/dist/dlc/TxFinalizer.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/Builder.d.ts +193 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/Builder.js +422 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/Builder.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CoveredCall.d.ts +13 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CoveredCall.js +67 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CoveredCall.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CsoInfo.d.ts +114 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CsoInfo.js +290 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/CsoInfo.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LinearPayout.d.ts +6 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LinearPayout.js +79 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LinearPayout.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongCall.d.ts +13 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongCall.js +47 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongCall.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongPut.d.ts +13 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongPut.js +47 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/LongPut.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/OptionInfo.d.ts +20 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/OptionInfo.js +101 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/OptionInfo.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/ShortPut.d.ts +12 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/ShortPut.js +46 -0
- package/.yalc/@node-dlc/core/dist/dlc/finance/ShortPut.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/index.d.ts +39 -0
- package/.yalc/@node-dlc/core/dist/index.js +78 -0
- package/.yalc/@node-dlc/core/dist/index.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelId.d.ts +31 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelId.js +52 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelId.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelKeys.d.ts +55 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelKeys.js +105 -0
- package/.yalc/@node-dlc/core/dist/lightning/ChannelKeys.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentNumber.d.ts +55 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentNumber.js +76 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentNumber.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecret.d.ts +26 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecret.js +44 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecret.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecretStore.d.ts +41 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecretStore.js +79 -0
- package/.yalc/@node-dlc/core/dist/lightning/CommitmentSecretStore.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/Htlc.d.ts +46 -0
- package/.yalc/@node-dlc/core/dist/lightning/Htlc.js +46 -0
- package/.yalc/@node-dlc/core/dist/lightning/Htlc.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/HtlcDirection.d.ts +16 -0
- package/.yalc/@node-dlc/core/dist/lightning/HtlcDirection.js +21 -0
- package/.yalc/@node-dlc/core/dist/lightning/HtlcDirection.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/ScriptFactory.d.ts +76 -0
- package/.yalc/@node-dlc/core/dist/lightning/ScriptFactory.js +102 -0
- package/.yalc/@node-dlc/core/dist/lightning/ScriptFactory.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/lightning/TxFactory.d.ts +83 -0
- package/.yalc/@node-dlc/core/dist/lightning/TxFactory.js +222 -0
- package/.yalc/@node-dlc/core/dist/lightning/TxFactory.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/utils/BigIntUtils.d.ts +9 -0
- package/.yalc/@node-dlc/core/dist/utils/BigIntUtils.js +59 -0
- package/.yalc/@node-dlc/core/dist/utils/BigIntUtils.js.map +1 -0
- package/.yalc/@node-dlc/core/dist/utils/Precision.d.ts +13 -0
- package/.yalc/@node-dlc/core/dist/utils/Precision.js +28 -0
- package/.yalc/@node-dlc/core/dist/utils/Precision.js.map +1 -0
- package/.yalc/@node-dlc/core/lib/AsyncProcessingQueue.ts +63 -0
- package/.yalc/@node-dlc/core/lib/Base32.ts +2 -0
- package/.yalc/@node-dlc/core/lib/BigIntUtils.ts +2 -0
- package/.yalc/@node-dlc/core/lib/BitField.ts +2 -0
- package/.yalc/@node-dlc/core/lib/ChannelId.ts +2 -0
- package/.yalc/@node-dlc/core/lib/LinkedList.ts +111 -0
- package/.yalc/@node-dlc/core/lib/LinkedListNode.ts +14 -0
- package/.yalc/@node-dlc/core/lib/Queue.ts +36 -0
- package/.yalc/@node-dlc/core/lib/ShortChannelId.ts +2 -0
- package/.yalc/@node-dlc/core/lib/ShortChannelIdUtils.ts +9 -0
- package/.yalc/@node-dlc/core/lib/dlc/CETCalculator.ts +450 -0
- package/.yalc/@node-dlc/core/lib/dlc/CoinSelect.ts +117 -0
- package/.yalc/@node-dlc/core/lib/dlc/HyperbolaPayoutCurve.ts +188 -0
- package/.yalc/@node-dlc/core/lib/dlc/PayoutCurve.ts +6 -0
- package/.yalc/@node-dlc/core/lib/dlc/PolynomialPayoutCurve.ts +266 -0
- package/.yalc/@node-dlc/core/lib/dlc/TxBuilder.ts +336 -0
- package/.yalc/@node-dlc/core/lib/dlc/TxFinalizer.ts +217 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/Builder.ts +730 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/CoveredCall.ts +110 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/CsoInfo.ts +498 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/LinearPayout.ts +94 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/LongCall.ts +74 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/LongPut.ts +74 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/OptionInfo.ts +182 -0
- package/.yalc/@node-dlc/core/lib/dlc/finance/ShortPut.ts +75 -0
- package/.yalc/@node-dlc/core/lib/index.ts +66 -0
- package/.yalc/@node-dlc/core/lib/lightning/ChannelId.ts +54 -0
- package/.yalc/@node-dlc/core/lib/lightning/ChannelKeys.ts +109 -0
- package/.yalc/@node-dlc/core/lib/lightning/CommitmentNumber.ts +94 -0
- package/.yalc/@node-dlc/core/lib/lightning/CommitmentSecret.ts +41 -0
- package/.yalc/@node-dlc/core/lib/lightning/CommitmentSecretStore.ts +84 -0
- package/.yalc/@node-dlc/core/lib/lightning/Htlc.ts +52 -0
- package/.yalc/@node-dlc/core/lib/lightning/HtlcDirection.ts +17 -0
- package/.yalc/@node-dlc/core/lib/lightning/ScriptFactory.ts +150 -0
- package/.yalc/@node-dlc/core/lib/lightning/TxFactory.ts +338 -0
- package/.yalc/@node-dlc/core/lib/utils/BigIntUtils.ts +64 -0
- package/.yalc/@node-dlc/core/lib/utils/Precision.ts +23 -0
- package/.yalc/@node-dlc/core/package.json +38 -0
- package/.yalc/@node-dlc/core/tsconfig.json +8 -0
- package/.yalc/@node-dlc/core/yalc.sig +1 -0
- package/CHANGELOG.md +56 -5
- package/dist/BitcoinWalletProvider.d.ts +4 -2
- package/dist/BitcoinWalletProvider.js +1 -0
- package/dist/BitcoinWalletProvider.js.map +1 -1
- package/lib/BitcoinWalletProvider.ts +11 -3
- package/package.json +5 -5
- package/yalc.lock +10 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DLC Transaction Builder with support for "exact amount" DLC scenarios.
|
|
3
|
+
*
|
|
4
|
+
* Key improvements:
|
|
5
|
+
* - Dust filtering: Only creates change outputs above DUST_LIMIT (1000 sats)
|
|
6
|
+
* - No-change support: Enables splicing with exact UTXO amounts
|
|
7
|
+
* - Max collateral calculation: Helper for determining exact amounts
|
|
8
|
+
*
|
|
9
|
+
* This matches the C++ layer behavior and fixes issues with DLC splicing
|
|
10
|
+
* where users want to use exact UTXO amounts without change outputs.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
LockTime,
|
|
15
|
+
OutPoint,
|
|
16
|
+
Script,
|
|
17
|
+
Tx,
|
|
18
|
+
TxBuilder,
|
|
19
|
+
Value,
|
|
20
|
+
} from '@node-dlc/bitcoin';
|
|
21
|
+
import {
|
|
22
|
+
DlcAcceptWithoutSigs,
|
|
23
|
+
DlcOffer,
|
|
24
|
+
FundingInput,
|
|
25
|
+
MessageType,
|
|
26
|
+
} from '@node-dlc/messaging';
|
|
27
|
+
import Decimal from 'decimal.js';
|
|
28
|
+
|
|
29
|
+
import { DualFundingTxFinalizer } from './TxFinalizer';
|
|
30
|
+
|
|
31
|
+
// Dust limit matching C++ implementation (1000 satoshis)
|
|
32
|
+
export const DUST_LIMIT = BigInt(1000);
|
|
33
|
+
|
|
34
|
+
export class DlcTxBuilder {
|
|
35
|
+
constructor(
|
|
36
|
+
readonly dlcOffer: DlcOffer,
|
|
37
|
+
readonly dlcAccept: DlcAcceptWithoutSigs,
|
|
38
|
+
) {}
|
|
39
|
+
|
|
40
|
+
public buildFundingTransaction(): Tx {
|
|
41
|
+
const txBuilder = new BatchDlcTxBuilder([this.dlcOffer], [this.dlcAccept]);
|
|
42
|
+
return txBuilder.buildFundingTransaction();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export class BatchDlcTxBuilder {
|
|
47
|
+
constructor(
|
|
48
|
+
readonly dlcOffers: DlcOffer[],
|
|
49
|
+
readonly dlcAccepts: DlcAcceptWithoutSigs[],
|
|
50
|
+
) {}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Calculates the maximum collateral that can be used given a set of funding inputs
|
|
54
|
+
* for exact-amount DLC scenarios (no change outputs).
|
|
55
|
+
*
|
|
56
|
+
* @param fundingInputs The inputs to be used for funding
|
|
57
|
+
* @param feeRatePerVb Fee rate in satoshis per virtual byte
|
|
58
|
+
* @param numContracts Number of DLC contracts being created (default: 1)
|
|
59
|
+
* @returns Maximum collateral amount in satoshis
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```typescript
|
|
63
|
+
* // Calculate max collateral for DLC splicing scenario
|
|
64
|
+
* const dlcFundingInput = getDlcFundingInput(); // 970,332 sats
|
|
65
|
+
* const additionalInput = getAdditionalInput(); // 100,000 sats
|
|
66
|
+
* const inputs = [dlcFundingInput, additionalInput];
|
|
67
|
+
*
|
|
68
|
+
* const maxCollateral = BatchDlcTxBuilder.calculateMaxCollateral(
|
|
69
|
+
* inputs,
|
|
70
|
+
* BigInt(1), // 1 sat/vB fee rate
|
|
71
|
+
* 1 // Single DLC contract
|
|
72
|
+
* );
|
|
73
|
+
*
|
|
74
|
+
* // Use maxCollateral in DLC offer to ensure exact amount with no change
|
|
75
|
+
* const dlcOffer = createDlcOffer(contractInfo, maxCollateral, ...);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
public static calculateMaxCollateral(
|
|
79
|
+
fundingInputs: FundingInput[],
|
|
80
|
+
feeRatePerVb: bigint,
|
|
81
|
+
numContracts = 1,
|
|
82
|
+
): bigint {
|
|
83
|
+
// Calculate total input value
|
|
84
|
+
const totalInputValue = fundingInputs.reduce((total, input) => {
|
|
85
|
+
return total + input.prevTx.outputs[input.prevTxVout].value.sats;
|
|
86
|
+
}, BigInt(0));
|
|
87
|
+
|
|
88
|
+
// Create a temporary finalizer to calculate fees
|
|
89
|
+
const fakeSPK = Buffer.from(
|
|
90
|
+
'0014663117d27e78eb432505180654e603acb30e8a4a',
|
|
91
|
+
'hex',
|
|
92
|
+
);
|
|
93
|
+
const finalizer = new DualFundingTxFinalizer(
|
|
94
|
+
fundingInputs,
|
|
95
|
+
fakeSPK,
|
|
96
|
+
fakeSPK,
|
|
97
|
+
[], // No accepter inputs for single-funded scenario
|
|
98
|
+
fakeSPK,
|
|
99
|
+
fakeSPK,
|
|
100
|
+
feeRatePerVb,
|
|
101
|
+
numContracts,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// For exact-amount scenarios, we need to account for:
|
|
105
|
+
// 1. Future fees (for CET/refund transactions)
|
|
106
|
+
// 2. Funding transaction fees
|
|
107
|
+
const futureFee = finalizer.offerFutureFee;
|
|
108
|
+
const fundingFee = finalizer.offerFundingFee;
|
|
109
|
+
|
|
110
|
+
// Maximum collateral is input value minus all fees
|
|
111
|
+
const maxCollateral = totalInputValue - futureFee - fundingFee;
|
|
112
|
+
|
|
113
|
+
// Ensure we don't return negative values
|
|
114
|
+
return maxCollateral > BigInt(0) ? maxCollateral : BigInt(0);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public buildFundingTransaction(): Tx {
|
|
118
|
+
const tx = new TxBuilder();
|
|
119
|
+
tx.version = 2;
|
|
120
|
+
tx.locktime = LockTime.zero();
|
|
121
|
+
|
|
122
|
+
if (this.dlcOffers.length !== this.dlcAccepts.length)
|
|
123
|
+
throw Error('DlcOffers and DlcAccepts must be the same length');
|
|
124
|
+
if (this.dlcOffers.length === 0) throw Error('DlcOffers must not be empty');
|
|
125
|
+
if (this.dlcAccepts.length === 0)
|
|
126
|
+
throw Error('DlcAccepts must not be empty');
|
|
127
|
+
|
|
128
|
+
// Ensure all DLC offers and accepts have the same funding inputs
|
|
129
|
+
this.ensureSameFundingInputs();
|
|
130
|
+
|
|
131
|
+
const multisigScripts: Script[] = [];
|
|
132
|
+
for (let i = 0; i < this.dlcOffers.length; i++) {
|
|
133
|
+
const offer = this.dlcOffers[i];
|
|
134
|
+
const accept = this.dlcAccepts[i];
|
|
135
|
+
|
|
136
|
+
multisigScripts.push(
|
|
137
|
+
Buffer.compare(offer.fundingPubkey, accept.fundingPubkey) === -1
|
|
138
|
+
? Script.p2msLock(2, offer.fundingPubkey, accept.fundingPubkey)
|
|
139
|
+
: Script.p2msLock(2, accept.fundingPubkey, offer.fundingPubkey),
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const witScripts = multisigScripts.map((multisigScript) =>
|
|
144
|
+
Script.p2wshLock(multisigScript),
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const finalizer = new DualFundingTxFinalizer(
|
|
148
|
+
this.dlcOffers[0].fundingInputs,
|
|
149
|
+
this.dlcOffers[0].payoutSpk,
|
|
150
|
+
this.dlcOffers[0].changeSpk,
|
|
151
|
+
this.dlcAccepts[0].fundingInputs,
|
|
152
|
+
this.dlcAccepts[0].payoutSpk,
|
|
153
|
+
this.dlcAccepts[0].changeSpk,
|
|
154
|
+
this.dlcOffers[0].feeRatePerVb,
|
|
155
|
+
this.dlcOffers.length,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
this.dlcOffers[0].fundingInputs.forEach((input) => {
|
|
159
|
+
if (input.type !== MessageType.FundingInput)
|
|
160
|
+
throw new Error('Input is not a funding input');
|
|
161
|
+
});
|
|
162
|
+
const offerFundingInputs: FundingInput[] = this.dlcOffers[0].fundingInputs.map(
|
|
163
|
+
(input) => input as FundingInput,
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const offerTotalFunding = offerFundingInputs.reduce((total, input) => {
|
|
167
|
+
return total + input.prevTx.outputs[input.prevTxVout].value.sats;
|
|
168
|
+
}, BigInt(0));
|
|
169
|
+
|
|
170
|
+
const acceptTotalFunding = this.dlcAccepts[0].fundingInputs.reduce(
|
|
171
|
+
(total, input) => {
|
|
172
|
+
return total + input.prevTx.outputs[input.prevTxVout].value.sats;
|
|
173
|
+
},
|
|
174
|
+
BigInt(0),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const fundingInputs: FundingInput[] = [
|
|
178
|
+
...offerFundingInputs,
|
|
179
|
+
...this.dlcAccepts[0].fundingInputs,
|
|
180
|
+
];
|
|
181
|
+
|
|
182
|
+
fundingInputs.sort(
|
|
183
|
+
(a, b) => Number(a.inputSerialId) - Number(b.inputSerialId),
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
fundingInputs.forEach((input) => {
|
|
187
|
+
tx.addInput(
|
|
188
|
+
OutPoint.fromString(
|
|
189
|
+
`${input.prevTx.txId.toString()}:${input.prevTxVout}`,
|
|
190
|
+
),
|
|
191
|
+
);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const offerInput = this.dlcOffers.reduce(
|
|
195
|
+
(total, offer) => total + offer.offerCollateral,
|
|
196
|
+
BigInt(0),
|
|
197
|
+
);
|
|
198
|
+
const acceptInput = this.dlcAccepts.reduce(
|
|
199
|
+
(total, accept) => total + accept.acceptCollateral,
|
|
200
|
+
BigInt(0),
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const totalInputs = this.dlcOffers.map((offer, i) => {
|
|
204
|
+
const offerInput = offer.offerCollateral;
|
|
205
|
+
const acceptInput = this.dlcAccepts[i].acceptCollateral;
|
|
206
|
+
return offerInput + acceptInput;
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const fundingValues = totalInputs.map((totalInput) => {
|
|
210
|
+
const offerFutureFeePerOffer = new Decimal(
|
|
211
|
+
finalizer.offerFutureFee.toString(),
|
|
212
|
+
)
|
|
213
|
+
.div(this.dlcOffers.length)
|
|
214
|
+
.ceil()
|
|
215
|
+
.toNumber();
|
|
216
|
+
const acceptFutureFeePerAccept = new Decimal(
|
|
217
|
+
finalizer.acceptFutureFee.toString(),
|
|
218
|
+
)
|
|
219
|
+
.div(this.dlcAccepts.length)
|
|
220
|
+
.ceil()
|
|
221
|
+
.toNumber();
|
|
222
|
+
|
|
223
|
+
return (
|
|
224
|
+
totalInput +
|
|
225
|
+
Value.fromSats(offerFutureFeePerOffer).sats +
|
|
226
|
+
Value.fromSats(acceptFutureFeePerAccept).sats
|
|
227
|
+
);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const offerChangeValue =
|
|
231
|
+
offerTotalFunding - offerInput - finalizer.offerFees;
|
|
232
|
+
const acceptChangeValue =
|
|
233
|
+
acceptTotalFunding - acceptInput - finalizer.acceptFees;
|
|
234
|
+
|
|
235
|
+
// Validate that we have sufficient funds
|
|
236
|
+
if (offerChangeValue < BigInt(0)) {
|
|
237
|
+
throw new Error(
|
|
238
|
+
`Insufficient funds for offerer: need ${
|
|
239
|
+
offerInput + finalizer.offerFees
|
|
240
|
+
} sats, have ${offerTotalFunding} sats`,
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// In single-funded DLCs, if accepter has no inputs, they don't pay fees
|
|
245
|
+
// This matches the C++ layer behavior where parties with no inputs have zero fees
|
|
246
|
+
if (acceptChangeValue < BigInt(0) && acceptTotalFunding > BigInt(0)) {
|
|
247
|
+
throw new Error(
|
|
248
|
+
`Insufficient funds for accepter: need ${
|
|
249
|
+
acceptInput + finalizer.acceptFees
|
|
250
|
+
} sats, have ${acceptTotalFunding} sats`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const outputs: Output[] = [];
|
|
255
|
+
witScripts.forEach((witScript, i) => {
|
|
256
|
+
outputs.push({
|
|
257
|
+
value: Value.fromSats(Number(fundingValues[i])),
|
|
258
|
+
script: witScript,
|
|
259
|
+
serialId: this.dlcOffers[i].fundOutputSerialId,
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
// Dust filtering: Only create change outputs if they're above dust threshold
|
|
264
|
+
// This matches the C++ implementation and enables "exact amount" DLC scenarios
|
|
265
|
+
// where all input value goes into the DLC funding output with no change
|
|
266
|
+
if (offerChangeValue >= DUST_LIMIT) {
|
|
267
|
+
outputs.push({
|
|
268
|
+
value: Value.fromSats(Number(offerChangeValue)),
|
|
269
|
+
script: Script.p2wpkhLock(this.dlcOffers[0].changeSpk.slice(2)),
|
|
270
|
+
serialId: this.dlcOffers[0].changeSerialId,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if (acceptChangeValue >= DUST_LIMIT) {
|
|
275
|
+
outputs.push({
|
|
276
|
+
value: Value.fromSats(Number(acceptChangeValue)),
|
|
277
|
+
script: Script.p2wpkhLock(this.dlcAccepts[0].changeSpk.slice(2)),
|
|
278
|
+
serialId: this.dlcAccepts[0].changeSerialId,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
outputs.sort((a, b) => Number(a.serialId) - Number(b.serialId));
|
|
283
|
+
|
|
284
|
+
outputs.forEach((output) => {
|
|
285
|
+
tx.addOutput(output.value, output.script);
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return tx.toTx();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
private ensureSameFundingInputs(): void {
|
|
292
|
+
// Check for offers
|
|
293
|
+
const referenceOfferInputs = this.dlcOffers[0].fundingInputs.map((input) =>
|
|
294
|
+
input.serialize().toString('hex'),
|
|
295
|
+
);
|
|
296
|
+
for (let i = 1; i < this.dlcOffers.length; i++) {
|
|
297
|
+
const currentInputs = this.dlcOffers[i].fundingInputs.map((input) =>
|
|
298
|
+
input.serialize().toString('hex'),
|
|
299
|
+
);
|
|
300
|
+
if (!this.arraysEqual(referenceOfferInputs, currentInputs)) {
|
|
301
|
+
throw new Error(
|
|
302
|
+
`Funding inputs for offer ${i} do not match the first offer's funding inputs.`,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Check for accepts
|
|
308
|
+
const referenceAcceptInputs = this.dlcAccepts[0].fundingInputs.map(
|
|
309
|
+
(input) => input.serialize().toString('hex'),
|
|
310
|
+
);
|
|
311
|
+
for (let i = 1; i < this.dlcAccepts.length; i++) {
|
|
312
|
+
const currentInputs = this.dlcAccepts[i].fundingInputs.map((input) =>
|
|
313
|
+
input.serialize().toString('hex'),
|
|
314
|
+
);
|
|
315
|
+
if (!this.arraysEqual(referenceAcceptInputs, currentInputs)) {
|
|
316
|
+
throw new Error(
|
|
317
|
+
`Funding inputs for accept ${i} do not match the first accept's funding inputs.`,
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
private arraysEqual(arr1: string[], arr2: string[]): boolean {
|
|
324
|
+
if (arr1.length !== arr2.length) return false;
|
|
325
|
+
for (let i = 0; i < arr1.length; i++) {
|
|
326
|
+
if (arr1[i] !== arr2[i]) return false;
|
|
327
|
+
}
|
|
328
|
+
return true;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
interface Output {
|
|
333
|
+
value: Value;
|
|
334
|
+
script: Script;
|
|
335
|
+
serialId: bigint;
|
|
336
|
+
}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { FundingInput, MessageType } from '@node-dlc/messaging';
|
|
2
|
+
import { Decimal } from 'decimal.js';
|
|
3
|
+
|
|
4
|
+
const BATCH_FUND_TX_BASE_WEIGHT = 42;
|
|
5
|
+
const FUNDING_OUTPUT_SIZE = 43;
|
|
6
|
+
|
|
7
|
+
export class DualFundingTxFinalizer {
|
|
8
|
+
constructor(
|
|
9
|
+
readonly offerInputs: FundingInput[],
|
|
10
|
+
readonly offerPayoutSPK: Buffer,
|
|
11
|
+
readonly offerChangeSPK: Buffer,
|
|
12
|
+
readonly acceptInputs: FundingInput[],
|
|
13
|
+
readonly acceptPayoutSPK: Buffer,
|
|
14
|
+
readonly acceptChangeSPK: Buffer,
|
|
15
|
+
readonly feeRate: bigint,
|
|
16
|
+
readonly numContracts = 1,
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
private computeFees(
|
|
20
|
+
_inputs: FundingInput[],
|
|
21
|
+
payoutSPK: Buffer,
|
|
22
|
+
changeSPK: Buffer,
|
|
23
|
+
numContracts: number,
|
|
24
|
+
): IFees {
|
|
25
|
+
// If no inputs, return zero fees (matches C++ layer behavior for single-funded DLCs)
|
|
26
|
+
if (_inputs.length === 0) {
|
|
27
|
+
return { futureFee: BigInt(0), fundingFee: BigInt(0) };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
_inputs.forEach((input) => {
|
|
31
|
+
if (input.type !== MessageType.FundingInput) {
|
|
32
|
+
console.error('input', input);
|
|
33
|
+
throw new Error('Input is not a funding input');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
const inputs: FundingInput[] = _inputs.map(
|
|
37
|
+
(input) => input as FundingInput,
|
|
38
|
+
);
|
|
39
|
+
// https://github.com/discreetlogcontracts/dlcspecs/blob/8ee4bbe816c9881c832b1ce320b9f14c72e3506f/Transactions.md#expected-weight-of-the-contract-execution-or-refund-transaction
|
|
40
|
+
const futureFeeWeight = 249 + 4 * payoutSPK.length;
|
|
41
|
+
const futureFeeVBytes = new Decimal(futureFeeWeight)
|
|
42
|
+
.times(numContracts)
|
|
43
|
+
.div(4)
|
|
44
|
+
.ceil()
|
|
45
|
+
.toNumber();
|
|
46
|
+
const futureFee = this.feeRate * BigInt(futureFeeVBytes);
|
|
47
|
+
|
|
48
|
+
// https://github.com/discreetlogcontracts/dlcspecs/blob/8ee4bbe816c9881c832b1ce320b9f14c72e3506f/Transactions.md#expected-weight-of-the-funding-transaction
|
|
49
|
+
const inputWeight = inputs.reduce((total, input) => {
|
|
50
|
+
return total + 164 + input.maxWitnessLen + input.scriptSigLength();
|
|
51
|
+
}, 0);
|
|
52
|
+
const contractWeight =
|
|
53
|
+
(BATCH_FUND_TX_BASE_WEIGHT + FUNDING_OUTPUT_SIZE * numContracts * 4) / 2;
|
|
54
|
+
const outputWeight = 36 + 4 * changeSPK.length + contractWeight;
|
|
55
|
+
const weight = outputWeight + inputWeight;
|
|
56
|
+
const vbytes = new Decimal(weight).div(4).ceil().toNumber();
|
|
57
|
+
const fundingFee = this.feeRate * BigInt(vbytes);
|
|
58
|
+
|
|
59
|
+
return { futureFee, fundingFee };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private getOfferFees(): IFees {
|
|
63
|
+
return this.computeFees(
|
|
64
|
+
this.offerInputs,
|
|
65
|
+
this.offerPayoutSPK,
|
|
66
|
+
this.offerChangeSPK,
|
|
67
|
+
this.numContracts,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private getAcceptFees(): IFees {
|
|
72
|
+
return this.computeFees(
|
|
73
|
+
this.acceptInputs,
|
|
74
|
+
this.acceptPayoutSPK,
|
|
75
|
+
this.acceptChangeSPK,
|
|
76
|
+
this.numContracts,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public get offerFees(): bigint {
|
|
81
|
+
const { futureFee, fundingFee } = this.getOfferFees();
|
|
82
|
+
return futureFee + fundingFee;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public get offerFutureFee(): bigint {
|
|
86
|
+
return this.getOfferFees().futureFee;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
public get offerFundingFee(): bigint {
|
|
90
|
+
return this.getOfferFees().fundingFee;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public get acceptFees(): bigint {
|
|
94
|
+
const { futureFee, fundingFee } = this.getAcceptFees();
|
|
95
|
+
return futureFee + fundingFee;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public get acceptFutureFee(): bigint {
|
|
99
|
+
return this.getAcceptFees().futureFee;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
public get acceptFundingFee(): bigint {
|
|
103
|
+
return this.getAcceptFees().fundingFee;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export class DualClosingTxFinalizer {
|
|
108
|
+
constructor(
|
|
109
|
+
readonly initiatorInputs: FundingInput[],
|
|
110
|
+
readonly offerPayoutSPK: Buffer,
|
|
111
|
+
readonly acceptPayoutSPK: Buffer,
|
|
112
|
+
readonly feeRate: bigint,
|
|
113
|
+
) {}
|
|
114
|
+
|
|
115
|
+
private computeFees(payoutSPK: Buffer, _inputs: FundingInput[] = []): bigint {
|
|
116
|
+
_inputs.forEach((input) => {
|
|
117
|
+
if (input.type !== MessageType.FundingInput)
|
|
118
|
+
throw new Error('Input is not a funding input');
|
|
119
|
+
});
|
|
120
|
+
const inputs: FundingInput[] = _inputs.map(
|
|
121
|
+
(input) => input as FundingInput,
|
|
122
|
+
);
|
|
123
|
+
// https://gist.github.com/matthewjablack/08c36baa513af9377508111405b22e03
|
|
124
|
+
const inputWeight = inputs.reduce((total, input) => {
|
|
125
|
+
return total + 164 + input.maxWitnessLen + input.scriptSigLength();
|
|
126
|
+
}, 0);
|
|
127
|
+
const outputWeight = 36 + 4 * payoutSPK.length;
|
|
128
|
+
const weight = 213 + outputWeight + inputWeight;
|
|
129
|
+
const vbytes = new Decimal(weight).div(4).ceil().toNumber();
|
|
130
|
+
const fee = this.feeRate * BigInt(vbytes);
|
|
131
|
+
|
|
132
|
+
return fee;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private getOfferInitiatorFees(): bigint {
|
|
136
|
+
return this.computeFees(this.offerPayoutSPK, this.initiatorInputs);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private getOfferReciprocatorFees(): bigint {
|
|
140
|
+
return this.computeFees(this.offerPayoutSPK);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
private getAcceptInitiatorFees(): bigint {
|
|
144
|
+
return this.computeFees(this.acceptPayoutSPK, this.initiatorInputs);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
private getAcceptReciprocatorFees(): bigint {
|
|
148
|
+
return this.computeFees(this.acceptPayoutSPK);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
public get offerInitiatorFees(): bigint {
|
|
152
|
+
return this.getOfferInitiatorFees();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
public get offerReciprocatorFees(): bigint {
|
|
156
|
+
return this.getOfferReciprocatorFees();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
public get acceptInitiatorFees(): bigint {
|
|
160
|
+
return this.getAcceptInitiatorFees();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
public get acceptReciprocatorFees(): bigint {
|
|
164
|
+
return this.getAcceptReciprocatorFees();
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface IFees {
|
|
169
|
+
futureFee: bigint;
|
|
170
|
+
fundingFee: bigint;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const getFinalizer = (
|
|
174
|
+
feeRate: bigint,
|
|
175
|
+
offerInputs?: FundingInput[],
|
|
176
|
+
acceptInputs?: FundingInput[],
|
|
177
|
+
numContracts?: number,
|
|
178
|
+
): DualFundingTxFinalizer => {
|
|
179
|
+
const input = new FundingInput();
|
|
180
|
+
input.maxWitnessLen = 108;
|
|
181
|
+
input.redeemScript = Buffer.from('', 'hex');
|
|
182
|
+
|
|
183
|
+
const fakeSPK = Buffer.from(
|
|
184
|
+
'0014663117d27e78eb432505180654e603acb30e8a4a',
|
|
185
|
+
'hex',
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
offerInputs = offerInputs || Array.from({ length: 1 }, () => input);
|
|
189
|
+
|
|
190
|
+
acceptInputs = acceptInputs || Array.from({ length: 1 }, () => input);
|
|
191
|
+
|
|
192
|
+
return new DualFundingTxFinalizer(
|
|
193
|
+
offerInputs,
|
|
194
|
+
fakeSPK,
|
|
195
|
+
fakeSPK,
|
|
196
|
+
acceptInputs,
|
|
197
|
+
fakeSPK,
|
|
198
|
+
fakeSPK,
|
|
199
|
+
feeRate,
|
|
200
|
+
numContracts,
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
export const getFinalizerByCount = (
|
|
205
|
+
feeRate: bigint,
|
|
206
|
+
numOfferInputs: number,
|
|
207
|
+
numAcceptInputs: number,
|
|
208
|
+
numContracts: number,
|
|
209
|
+
): DualFundingTxFinalizer => {
|
|
210
|
+
const input = new FundingInput();
|
|
211
|
+
input.maxWitnessLen = 108;
|
|
212
|
+
input.redeemScript = Buffer.from('', 'hex');
|
|
213
|
+
|
|
214
|
+
const offerInputs = Array.from({ length: numOfferInputs }, () => input);
|
|
215
|
+
const acceptInputs = Array.from({ length: numAcceptInputs }, () => input);
|
|
216
|
+
return getFinalizer(feeRate, offerInputs, acceptInputs, numContracts);
|
|
217
|
+
};
|