@atomicfinance/bitcoin-ddk-provider 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,142 @@
1
+ # Bitcoin DDK Provider
2
+
3
+ A Bitcoin provider that implements DLC (Discreet Log Contract) functionality using the DDK (Discreet Log Contract Development Kit) interface.
4
+
5
+ ## Features
6
+
7
+ - **Interface-based design**: Uses a `DdkInterface` that allows different DDK implementations to be injected
8
+ - **Flexible**: Can work with `ddk-ts`, `ddk-rn`, or any custom DDK implementation
9
+ - **Type-safe**: Full TypeScript support with proper type definitions
10
+ - **Testable**: Easy to mock for unit testing
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @atomicfinance/bitcoin-ddk-provider
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### Basic Usage with ddk-ts
21
+
22
+ ```typescript
23
+ import BitcoinDdkProvider from '@atomicfinance/bitcoin-ddk-provider';
24
+ import * as ddkTs from '@bennyblader/ddk-ts';
25
+ import { BitcoinNetwork } from 'bitcoin-networks';
26
+
27
+ // Create provider with ddk-ts implementation
28
+ const network = BitcoinNetwork.MAINNET;
29
+ const provider = new BitcoinDdkProvider(network, ddkTs);
30
+
31
+ // Use the provider
32
+ const version = await provider.getVersion();
33
+ console.log(`DDK Version: ${version}`);
34
+ ```
35
+
36
+ ### Usage with ddk-rn
37
+
38
+ ```typescript
39
+ import BitcoinDdkProvider from '@atomicfinance/bitcoin-ddk-provider';
40
+ import * as ddkRn from '@bennyblader/ddk-rn';
41
+ import { BitcoinNetwork } from 'bitcoin-networks';
42
+
43
+ // Create provider with ddk-rn implementation
44
+ const network = BitcoinNetwork.MAINNET;
45
+ const provider = new BitcoinDdkProvider(network, ddkRn);
46
+ ```
47
+
48
+ ### Custom DDK Implementation
49
+
50
+ ```typescript
51
+ import BitcoinDdkProvider from '@atomicfinance/bitcoin-ddk-provider';
52
+ import { DdkInterface, DlcOutcome, PartyParams, DlcTransactions } from '@atomicfinance/types';
53
+
54
+ // Create your own DDK implementation
55
+ class MyCustomDdk implements DdkInterface {
56
+ createDlcTransactions(
57
+ outcomes: DlcOutcome[],
58
+ localParams: PartyParams,
59
+ remoteParams: PartyParams,
60
+ refundLocktime: number,
61
+ feeRate: bigint,
62
+ fundLockTime: number,
63
+ cetLockTime: number,
64
+ fundOutputSerialId: bigint,
65
+ ): DlcTransactions {
66
+ // Your custom implementation
67
+ return {
68
+ fund: { /* ... */ },
69
+ cets: [],
70
+ refund: { /* ... */ },
71
+ fundingScriptPubkey: Buffer.alloc(0),
72
+ };
73
+ }
74
+
75
+ // Implement all other required methods...
76
+ createCet(/* ... */) { /* ... */ }
77
+ createCets(/* ... */) { /* ... */ }
78
+ // ... etc
79
+ }
80
+
81
+ // Use your custom implementation
82
+ const network = BitcoinNetwork.MAINNET;
83
+ const customDdk = new MyCustomDdk();
84
+ const provider = new BitcoinDdkProvider(network, customDdk);
85
+ ```
86
+
87
+ ### Testing with Mock Implementation
88
+
89
+ ```typescript
90
+ import BitcoinDdkProvider from '@atomicfinance/bitcoin-ddk-provider';
91
+ import { DdkInterface } from '@atomicfinance/types';
92
+
93
+ // Create a mock for testing
94
+ const mockDdk: DdkInterface = {
95
+ createDlcTransactions: jest.fn().mockResolvedValue(/* mock data */),
96
+ createFundTxLockingScript: jest.fn().mockReturnValue(Buffer.alloc(0)),
97
+ // ... implement other methods as needed
98
+ };
99
+
100
+ const provider = new BitcoinDdkProvider(BitcoinNetwork.TESTNET, mockDdk);
101
+ ```
102
+
103
+ ## API Reference
104
+
105
+ ### Constructor
106
+
107
+ ```typescript
108
+ constructor(network: BitcoinNetwork, ddkLib: DdkInterface)
109
+ ```
110
+
111
+ - `network`: The Bitcoin network to use (mainnet, testnet, etc.)
112
+ - `ddkLib`: A DDK implementation that conforms to the `DdkInterface`
113
+
114
+ ### Methods
115
+
116
+ The provider implements all the standard DLC methods:
117
+
118
+ - `createDlcTransactions()` - Create DLC transactions
119
+ - `createFundTx()` - Create funding transaction
120
+ - `createCet()` - Create CET (Contract Execution Transaction)
121
+ - `createCets()` - Create multiple CETs
122
+ - `createRefundTransaction()` - Create refund transaction
123
+ - `createCetAdaptorSignature()` - Create CET adaptor signature
124
+ - `signFundTransactionInput()` - Sign funding transaction input
125
+ - `verifyFundTxSignature()` - Verify funding transaction signature
126
+ - `getVersion()` - Get DDK version
127
+ - `getChangeOutputAndFees()` - Calculate change output and fees
128
+ - `getTotalInputVsize()` - Get total input vsize
129
+ - `isDustOutput()` - Check if output is dust
130
+ - `createSplicedDlcTransactions()` - Create spliced DLC transactions
131
+
132
+ ## Benefits of Interface-Based Design
133
+
134
+ 1. **Dependency Injection**: Easy to swap implementations
135
+ 2. **Testing**: Simple to mock for unit tests
136
+ 3. **Flexibility**: Support multiple DDK libraries
137
+ 4. **Maintainability**: Clear contract for what any DDK implementation must provide
138
+ 5. **Future-Proof**: Easy to add new DDK implementations or remove dependencies
139
+
140
+ ## Type Safety
141
+
142
+ All methods are fully typed using TypeScript interfaces from `@atomicfinance/types`. The provider ensures type safety while maintaining flexibility through the interface-based design.
@@ -0,0 +1,297 @@
1
+ import Provider from '@atomicfinance/provider';
2
+ import { DdkInterface, DlcInputInfoRequest, Input, InputSupplementationMode, Messages, PayoutRequest } from '@atomicfinance/types';
3
+ import { Tx } from '@node-dlc/bitcoin';
4
+ import { CetAdaptorSignatures, ContractInfo, DlcAccept, DlcClose, DlcCloseMetadata, DlcOffer, DlcSign, DlcTransactions, FundingInput, HyperbolaPayoutCurvePiece, NumericalDescriptor, OracleAttestation, PolynomialPayoutCurvePiece } from '@node-dlc/messaging';
5
+ import { BitcoinNetwork } from 'bitcoin-networks';
6
+ export default class BitcoinDdkProvider extends Provider {
7
+ private _network;
8
+ private _ddk;
9
+ constructor(network: BitcoinNetwork, ddkLib: DdkInterface);
10
+ DdkLoaded(): Promise<void>;
11
+ /**
12
+ * Find private key for DLC funding pubkey by deriving wallet addresses
13
+ */
14
+ private findDlcFundingPrivateKey;
15
+ private GetPrivKeysForInputs;
16
+ GetCfdNetwork(): Promise<string>;
17
+ /**
18
+ * Get inputs for amount with explicit supplementation control
19
+ */
20
+ GetInputsForAmountWithMode(amounts: bigint[], feeRatePerVb: bigint, fixedInputs?: Input[], supplementation?: InputSupplementationMode): Promise<Input[]>;
21
+ GetInputsForAmount(amounts: bigint[], feeRatePerVb: bigint, fixedInputs?: Input[]): Promise<Input[]>;
22
+ private Initialize;
23
+ /**
24
+ * TODO: Add GetPayoutFromOutcomes
25
+ *
26
+ * private GetPayoutsFromOutcomes(
27
+ * contractDescriptor: ContractDescriptorV0,
28
+ * totalCollateral: bigint,
29
+ * ): PayoutRequest[] {}
30
+ */
31
+ private GetPayoutsFromPayoutFunction;
32
+ private GetPayoutsFromPolynomialPayoutFunction;
33
+ private GetPayouts;
34
+ private FlattenPayouts;
35
+ private GetIndicesFromPayouts;
36
+ private GetPayoutsFromEnumeratedDescriptor;
37
+ private GetPayoutsFromContractDescriptor;
38
+ /**
39
+ * Converts a @node-dlc/bitcoin Tx to a DDK Transaction
40
+ * @param tx The @node-dlc/bitcoin transaction
41
+ * @returns DDK Transaction object
42
+ */
43
+ private convertTxToDdkTransaction;
44
+ createDlcTxs(dlcOffer: DlcOffer, dlcAccept: DlcAccept): Promise<CreateDlcTxsResponse>;
45
+ /**
46
+ * Computes DLC-spec compliant tagged attestation message digest
47
+ * This matches what the oracle should sign according to the DLC specification
48
+ */
49
+ private computeTaggedAttestationMessage;
50
+ /**
51
+ * Convert message lists to the format expected by DDK FFI
52
+ * DDK expects 32-byte message digests (tagged attestation messages)
53
+ */
54
+ private convertMessagesForDdk;
55
+ private GenerateEnumMessages;
56
+ private convertToJsonSerializable;
57
+ private GenerateDigitDecompositionMessages;
58
+ private GenerateMessages;
59
+ private GetContractOraclePairs;
60
+ private getFundOutputValueSats;
61
+ private CreateCetAdaptorAndRefundSigs;
62
+ private VerifyCetAdaptorAndRefundSigs;
63
+ private CreateFundingSigsAlt;
64
+ private VerifyFundingSigsAlt;
65
+ private VerifyRefundSignatureAlt;
66
+ private CreateFundingScript;
67
+ private CreateFundingTx;
68
+ FindOutcomeIndexFromPolynomialPayoutCurvePiece(dlcOffer: DlcOffer, contractDescriptor: NumericalDescriptor, contractOraclePairIndex: number, polynomialPayoutCurvePiece: PolynomialPayoutCurvePiece, oracleAttestation: OracleAttestation, outcome: bigint): Promise<FindOutcomeResponse>;
69
+ FindOutcomeIndexFromHyperbolaPayoutCurvePiece(_dlcOffer: DlcOffer, contractDescriptor: NumericalDescriptor, contractOraclePairIndex: number, hyperbolaPayoutCurvePiece: HyperbolaPayoutCurvePiece, oracleAttestation: OracleAttestation, outcome: bigint): Promise<FindOutcomeResponse>;
70
+ FindOutcomeIndex(dlcOffer: DlcOffer, oracleAttestation: OracleAttestation): Promise<FindOutcomeResponse>;
71
+ ValidateEvent(dlcOffer: DlcOffer, oracleAttestation: OracleAttestation): void;
72
+ FindAndSignCet(dlcOffer: DlcOffer, dlcAccept: DlcAccept, dlcSign: DlcSign, dlcTxs: DlcTransactions, oracleAttestation: OracleAttestation, isOfferer?: boolean): Promise<Tx>;
73
+ private GetFundAddress;
74
+ private GetFundKeyPair;
75
+ private GetFundPrivateKey;
76
+ CreateCloseRawTxs(dlcOffer: DlcOffer, dlcAccept: DlcAccept, dlcTxs: DlcTransactions, closeInputAmount: bigint, isOfferer: boolean, _dlcCloses?: DlcClose[], fundingInputs?: FundingInput[], initiatorPayouts?: bigint[]): Promise<string[]>;
77
+ CreateSignatureHashes(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcTxs: DlcTransactions, rawCloseTxs: string[]): Promise<string[]>;
78
+ CalculateEcSignatureHashes(sigHashes: string[], privKey: string): Promise<string[]>;
79
+ VerifySignatures(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcTxs: DlcTransactions, _dlcCloses: DlcClose[], rawCloseTxs: string[], isOfferer: boolean): Promise<boolean>;
80
+ /**
81
+ * Check whether wallet is offerer of DlcOffer or DlcAccept
82
+ * @param dlcOffer Dlc Offer Message
83
+ * @param dlcAccept Dlc Accept Message
84
+ * @returns {Promise<boolean>}
85
+ */
86
+ isOfferer(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept): Promise<boolean>;
87
+ /**
88
+ * Create DLC Offer Message
89
+ * @param contractInfo ContractInfo TLV (V0 or V1)
90
+ * @param offerCollateralSatoshis Amount DLC Initiator is putting into the contract
91
+ * @param feeRatePerVb Fee rate in satoshi per virtual byte that both sides use to compute fees in funding tx
92
+ * @param cetLocktime The nLockTime to be put on CETs
93
+ * @param refundLocktime The nLockTime to be put on the refund transaction
94
+ * @param fixedInputs Optional fixed inputs - can be Input[] for regular inputs or FundingInput[] for DLC inputs
95
+ * @returns {Promise<DlcOffer>}
96
+ */
97
+ createDlcOffer(contractInfo: ContractInfo, offerCollateralSatoshis: bigint, feeRatePerVb: bigint, cetLocktime: number, refundLocktime: number, fixedInputs?: Input[] | FundingInput[], inputSupplementationMode?: InputSupplementationMode): Promise<DlcOffer>;
98
+ /**
99
+ * Accept DLC Offer (supports single-funded DLCs when accept collateral is 0)
100
+ * @param _dlcOffer Dlc Offer Message
101
+ * @param fixedInputs Optional inputs to use for Funding Inputs
102
+ * @returns {Promise<AcceptDlcOfferResponse}
103
+ */
104
+ acceptDlcOffer(_dlcOffer: DlcOffer, fixedInputs?: Input[] | FundingInput[]): Promise<AcceptDlcOfferResponse>;
105
+ /**
106
+ * Sign Dlc Accept Message
107
+ * @param _dlcOffer Dlc Offer Message
108
+ * @param _dlcAccept Dlc Accept Message
109
+ * @returns {Promise<SignDlcAcceptResponse}
110
+ */
111
+ signDlcAccept(dlcOffer: DlcOffer, dlcAccept: DlcAccept): Promise<SignDlcAcceptResponse>;
112
+ /**
113
+ * Finalize Dlc Sign
114
+ * @param dlcOffer Dlc Offer Message
115
+ * @param dlcAccept Dlc Accept Message
116
+ * @param dlcSign Dlc Sign Message
117
+ * @param dlcTxs Dlc Transactions Message
118
+ * @returns {Promise<Tx>}
119
+ */
120
+ finalizeDlcSign(dlcOffer: DlcOffer, dlcAccept: DlcAccept, dlcSign: DlcSign, dlcTxs: DlcTransactions): Promise<Tx>;
121
+ /**
122
+ * Execute DLC
123
+ * @param _dlcOffer Dlc Offer Message
124
+ * @param _dlcAccept Dlc Accept Message
125
+ * @param _dlcSign Dlc Sign Message
126
+ * @param _dlcTxs Dlc Transactions Message
127
+ * @param oracleAttestation Oracle Attestations TLV (V0)
128
+ * @param isOfferer Whether party is Dlc Offerer
129
+ * @returns {Promise<Tx>}
130
+ */
131
+ execute(dlcOffer: DlcOffer, dlcAccept: DlcAccept, dlcSign: DlcSign, dlcTxs: DlcTransactions, oracleAttestation: OracleAttestation, isOfferer?: boolean): Promise<Tx>;
132
+ /**
133
+ * Refund DLC
134
+ * @param dlcOffer Dlc Offer Message
135
+ * @param dlcAccept Dlc Accept Message
136
+ * @param dlcSign Dlc Sign Message
137
+ * @param dlcTxs Dlc Transactions message
138
+ * @returns {Promise<Tx>}
139
+ */
140
+ refund(dlcOffer: DlcOffer, dlcAccept: DlcAccept, dlcSign: DlcSign, dlcTxs: DlcTransactions): Promise<Tx>;
141
+ /**
142
+ * Goal of createDlcClose is for alice (the initiator) to
143
+ * 1. take dlcoffer, accept, and sign messages. Create a dlcClose message.
144
+ * 2. Build a close tx, sign.
145
+ * 3. return dlcClose message (no psbt)
146
+ */
147
+ /**
148
+ * Generate DlcClose messagetype for closing DLC with Mutual Consent
149
+ * @param _dlcOffer DlcOffer TLV (V0)
150
+ * @param _dlcAccept DlcAccept TLV (V0)
151
+ * @param _dlcTxs DlcTransactions TLV (V0)
152
+ * @param initiatorPayoutSatoshis Amount initiator expects as a payout
153
+ * @param isOfferer Whether offerer or not
154
+ * @param _inputs Optionally specified closing inputs
155
+ * @returns {Promise<DlcClose>}
156
+ */
157
+ createDlcClose(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcTxs: DlcTransactions, initiatorPayoutSatoshis: bigint, isOfferer?: boolean, _inputs?: Input[]): Promise<DlcClose>;
158
+ /**
159
+ * Generate multiple DlcClose messagetypes for closing DLC with Mutual Consent
160
+ * @param _dlcOffer DlcOffer TLV (V0)
161
+ * @param _dlcAccept DlcAccept TLV (V0)
162
+ * @param _dlcTxs DlcTransactions TLV (V0)
163
+ * @param initiatorPayouts Array of amounts initiator expects as payouts
164
+ * @param isOfferer Whether offerer or not
165
+ * @param _inputs Optionally specified closing inputs
166
+ * @returns {Promise<DlcClose[]>}
167
+ */
168
+ createBatchDlcClose(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcTxs: DlcTransactions, initiatorPayouts: bigint[], isOfferer?: boolean, _inputs?: Input[]): Promise<DlcClose[]>;
169
+ verifyBatchDlcCloseUsingMetadata(dlcCloseMetadata: DlcCloseMetadata, _dlcCloses: DlcClose[], isOfferer?: boolean): Promise<void>;
170
+ /**
171
+ * Verify multiple DlcClose messagetypes for closing DLC with Mutual Consent
172
+ * @param _dlcOffer DlcOffer TLV (V0)
173
+ * @param _dlcAccept DlcAccept TLV (V0)
174
+ * @param _dlcTxs DlcTransactions TLV (V0)
175
+ * @param _dlcCloses DlcClose[] TLV (V0)
176
+ * @param isOfferer Whether offerer or not
177
+ * @returns {Promise<void>}
178
+ */
179
+ verifyBatchDlcClose(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcTxs: DlcTransactions, _dlcCloses: DlcClose[], isOfferer?: boolean): Promise<void>;
180
+ /**
181
+ * Goal of finalize Dlc Close is for bob to
182
+ * 1. take the dlcClose created by alice using createDlcClose,
183
+ * 2. Build a psbt using Alice's dlcClose message
184
+ * 3. Sign psbt with bob's privkey
185
+ * 4. return a tx ready to be broadcast
186
+ */
187
+ /**
188
+ * Finalize Dlc Close
189
+ * @param _dlcOffer Dlc Offer Message
190
+ * @param _dlcAccept Dlc Accept Message
191
+ * @param _dlcClose Dlc Close Message
192
+ * @param _dlcTxs Dlc Transactions Message
193
+ * @returns {Promise<Tx>}
194
+ */
195
+ finalizeDlcClose(_dlcOffer: DlcOffer, _dlcAccept: DlcAccept, _dlcClose: DlcClose, _dlcTxs: DlcTransactions): Promise<string>;
196
+ fundingInputToInput(_input: FundingInput, findDerivationPath?: boolean): Promise<Input>;
197
+ inputToFundingInput(input: Input): Promise<FundingInput>;
198
+ getConnectedNetwork(): Promise<BitcoinNetwork>;
199
+ /**
200
+ * Convert BitcoinNetwork to bitcoinjs-lib network format
201
+ */
202
+ private getBitcoinJsNetwork;
203
+ /**
204
+ * Calculate the maximum collateral possible with given inputs
205
+ * @param inputs Array of Input objects to use for funding
206
+ * @param feeRatePerVb Fee rate in satoshis per virtual byte
207
+ * @param contractCount Number of DLC contracts (default: 1)
208
+ * @returns Maximum collateral amount in satoshis
209
+ */
210
+ calculateMaxCollateral(inputs: Input[], feeRatePerVb: bigint, contractCount?: number): Promise<bigint>;
211
+ /**
212
+ * Create a funding input with DLC input information for splicing
213
+ * @param dlcInputInfo DLC input information
214
+ * @param fundingTxHex Raw transaction hex of the funding transaction
215
+ */
216
+ createDlcFundingInput(dlcInputInfo: DlcInputInfoRequest, fundingTxHex: string): Promise<FundingInput>;
217
+ }
218
+ export interface BasicInitializeResponse {
219
+ fundingPubKey: Buffer;
220
+ payoutSPK: Buffer;
221
+ payoutSerialId: bigint;
222
+ changeSPK: Buffer;
223
+ changeSerialId: bigint;
224
+ }
225
+ export interface InitializeResponse extends BasicInitializeResponse {
226
+ fundingInputs: FundingInput[];
227
+ }
228
+ export interface BatchBaseInitializeResponse {
229
+ fundingPubKey: Buffer;
230
+ payoutSPK: Buffer;
231
+ payoutSerialId: bigint;
232
+ }
233
+ export interface BatchInitializeResponse {
234
+ initializeResponses: BatchBaseInitializeResponse[];
235
+ fundingInputs: FundingInput[];
236
+ changeSPK: Buffer;
237
+ changeSerialId: bigint;
238
+ }
239
+ export interface AcceptDlcOfferResponse {
240
+ dlcAccept: DlcAccept;
241
+ dlcTransactions: DlcTransactions;
242
+ }
243
+ export interface BatchAcceptDlcOfferResponse {
244
+ dlcAccepts: DlcAccept[];
245
+ dlcTransactionsList: DlcTransactions[];
246
+ }
247
+ export interface SignDlcAcceptResponse {
248
+ dlcSign: DlcSign;
249
+ dlcTransactions: DlcTransactions;
250
+ }
251
+ export interface BatchSignDlcAcceptResponse {
252
+ dlcSigns: DlcSign[];
253
+ dlcTransactionsList: DlcTransactions[];
254
+ }
255
+ export interface GetPayoutsResponse {
256
+ payouts: PayoutRequest[];
257
+ payoutGroups: PayoutGroup[];
258
+ messagesList: Messages[];
259
+ }
260
+ export interface CreateDlcTxsResponse {
261
+ dlcTransactions: DlcTransactions;
262
+ messagesList: Messages[];
263
+ }
264
+ export interface CreateBatchDlcTxsResponse {
265
+ dlcTransactionsList: DlcTransactions[];
266
+ nestedMessagesList: Messages[][];
267
+ }
268
+ export interface CreateCetAdaptorAndRefundSigsResponse {
269
+ cetSignatures: CetAdaptorSignatures;
270
+ refundSignature: Buffer;
271
+ }
272
+ interface PayoutGroup {
273
+ payout: bigint;
274
+ groups: number[][];
275
+ }
276
+ interface FindOutcomeResponse {
277
+ index: number;
278
+ groupLength: number;
279
+ }
280
+ export interface Change {
281
+ value: number;
282
+ }
283
+ export interface Output {
284
+ value: number;
285
+ id?: string;
286
+ }
287
+ export interface InputsForAmountResponse {
288
+ inputs: Input[];
289
+ change: Change;
290
+ outputs: Output[];
291
+ fee: number;
292
+ }
293
+ export interface InputsForDualAmountResponse {
294
+ inputs: Input[];
295
+ fee: number;
296
+ }
297
+ export {};