@atomicfinance/bitcoin-dlc-provider 3.5.3 → 3.6.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.
@@ -1,2181 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const provider_1 = __importDefault(require("@atomicfinance/provider"));
7
- const types_1 = require("@atomicfinance/types");
8
- const utils_1 = require("@atomicfinance/utils");
9
- const core_1 = require("@node-dlc/core");
10
- const messaging_1 = require("@node-dlc/messaging");
11
- const bitcoin_1 = require("@node-lightning/bitcoin");
12
- const bufio_1 = require("@node-lightning/bufio");
13
- const crypto_1 = require("@node-lightning/crypto");
14
- const assert_1 = __importDefault(require("assert"));
15
- const bignumber_js_1 = __importDefault(require("bignumber.js"));
16
- const bitcoin_networks_1 = require("bitcoin-networks");
17
- const bitcoinjs_lib_1 = require("bitcoinjs-lib");
18
- const Utils_1 = require("./utils/Utils");
19
- class BitcoinDlcProvider extends provider_1.default {
20
- constructor(network, cfdDlcJs) {
21
- super();
22
- this._network = network;
23
- this._cfdDlcJs = cfdDlcJs;
24
- }
25
- async CfdLoaded() {
26
- while (!this._cfdDlcJs) {
27
- await (0, utils_1.sleep)(10);
28
- }
29
- }
30
- async GetPrivKeysForInputs(inputs) {
31
- const privKeys = [];
32
- for (let i = 0; i < inputs.length; i++) {
33
- const input = inputs[i];
34
- let derivationPath = input.derivationPath;
35
- if (!derivationPath) {
36
- derivationPath = (await this.getMethod('getWalletAddress')(input.address)).derivationPath;
37
- }
38
- const keyPair = await this.getMethod('keyPair')(derivationPath);
39
- const privKey = Buffer.from(keyPair.__D).toString('hex');
40
- privKeys.push(privKey);
41
- }
42
- return privKeys;
43
- }
44
- async GetCfdNetwork() {
45
- const network = await this.getConnectedNetwork();
46
- switch (network.name) {
47
- case 'bitcoin_testnet':
48
- return 'testnet';
49
- case 'bitcoin_regtest':
50
- return 'regtest';
51
- default:
52
- return 'bitcoin';
53
- }
54
- }
55
- async GetInputsForAmount(amounts, feeRatePerVb, fixedInputs = []) {
56
- if (amounts.length === 0)
57
- return [];
58
- const fixedUtxos = fixedInputs.map((input) => input.toUtxo());
59
- let inputs;
60
- try {
61
- const inputsForAmount = await this.getMethod('getInputsForDualFunding')(amounts, feeRatePerVb, fixedUtxos);
62
- inputs = inputsForAmount.inputs;
63
- }
64
- catch (e) {
65
- const errorMessage = e instanceof Error ? e.message : 'Unknown error';
66
- if (fixedInputs.length === 0) {
67
- throw Error(`Not enough balance getInputsForAmount. Error: ${errorMessage}`);
68
- }
69
- else {
70
- inputs = fixedInputs;
71
- }
72
- }
73
- return inputs;
74
- }
75
- async Initialize(collateral, feeRatePerVb, fixedInputs) {
76
- const network = await this.getConnectedNetwork();
77
- const payoutAddress = await this.client.wallet.getUnusedAddress(false);
78
- const payoutSPK = bitcoinjs_lib_1.address.toOutputScript(payoutAddress.address, network);
79
- const changeAddress = await this.client.wallet.getUnusedAddress(true);
80
- const changeSPK = bitcoinjs_lib_1.address.toOutputScript(changeAddress.address, network);
81
- const fundingAddress = await this.client.wallet.getUnusedAddress(false);
82
- const fundingPubKey = Buffer.from(fundingAddress.publicKey, 'hex');
83
- if (fundingAddress.address === payoutAddress.address)
84
- throw Error('Address reuse');
85
- const inputs = await this.GetInputsForAmount([collateral], feeRatePerVb, fixedInputs);
86
- const fundingInputs = await Promise.all(inputs.map(async (input) => {
87
- return this.inputToFundingInput(input);
88
- }));
89
- const payoutSerialId = (0, Utils_1.generateSerialId)();
90
- const changeSerialId = (0, Utils_1.generateSerialId)();
91
- return {
92
- fundingPubKey,
93
- payoutSPK,
94
- payoutSerialId,
95
- fundingInputs,
96
- changeSPK,
97
- changeSerialId,
98
- };
99
- }
100
- async BatchInitialize(collaterals, feeRatePerVb, fixedInputs) {
101
- const network = await this.getConnectedNetwork();
102
- const inputs = await this.GetInputsForAmount(collaterals, feeRatePerVb, fixedInputs);
103
- const fundingInputs = await Promise.all(inputs.map(async (input) => {
104
- return this.inputToFundingInput(input);
105
- }));
106
- const initializeResponses = [];
107
- const changeSerialId = (0, Utils_1.generateSerialId)();
108
- const changeAddress = await this.client.wallet.getUnusedAddress(true);
109
- const changeSPK = bitcoinjs_lib_1.address.toOutputScript(changeAddress.address, network);
110
- for (let i = 0; i < collaterals.length; i++) {
111
- const payoutAddress = await this.client.wallet.getUnusedAddress(false);
112
- const payoutSPK = bitcoinjs_lib_1.address.toOutputScript(payoutAddress.address, network);
113
- const fundingAddress = await this.client.wallet.getUnusedAddress(false);
114
- const fundingPubKey = Buffer.from(fundingAddress.publicKey, 'hex');
115
- if (fundingAddress.address === payoutAddress.address)
116
- throw Error('Address reuse');
117
- const payoutSerialId = (0, Utils_1.generateSerialId)();
118
- initializeResponses.push({
119
- fundingPubKey,
120
- payoutSPK,
121
- payoutSerialId,
122
- });
123
- }
124
- return { fundingInputs, initializeResponses, changeSerialId, changeSPK };
125
- }
126
- /**
127
- * TODO: Add GetPayoutFromOutcomes
128
- *
129
- * private GetPayoutsFromOutcomes(
130
- * contractDescriptor: ContractDescriptorV0,
131
- * totalCollateral: bigint,
132
- * ): PayoutRequest[] {}
133
- */
134
- GetPayoutsFromPayoutFunction(_dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
135
- if (_dlcOffer.type !== messaging_1.MessageType.DlcOfferV0)
136
- throw Error('DlcOffer must be V0');
137
- const dlcOffer = _dlcOffer;
138
- if (contractDescriptor.payoutFunction.type !== messaging_1.MessageType.PayoutFunctionV0)
139
- throw Error('PayoutFunction must be V0');
140
- const payoutFunction = contractDescriptor.payoutFunction;
141
- if (payoutFunction.pieces.length === 0)
142
- throw Error('PayoutFunction must have at least once PayoutCurvePiece');
143
- if (payoutFunction.pieces.length > 1)
144
- throw Error('More than one PayoutCurvePiece not supported');
145
- const payoutCurvePiece = payoutFunction.pieces[0]
146
- .payoutCurvePiece;
147
- if (payoutCurvePiece.type !== messaging_1.MessageType.HyperbolaPayoutCurvePiece &&
148
- payoutCurvePiece.type !== messaging_1.MessageType.OldHyperbolaPayoutCurvePiece)
149
- throw Error('Must be HyperbolaPayoutCurvePiece');
150
- if (payoutCurvePiece.b !== BigInt(0) || payoutCurvePiece.c !== BigInt(0))
151
- throw Error('b and c HyperbolaPayoutCurvePiece values must be 0');
152
- const eventDescriptor = oracleInfo.announcement.oracleEvent
153
- .eventDescriptor;
154
- if (eventDescriptor.type !== messaging_1.MessageType.DigitDecompositionEventDescriptorV0)
155
- throw Error('Only DigitDecomposition Oracle Events supported');
156
- const roundingIntervals = contractDescriptor.roundingIntervals;
157
- const cetPayouts = core_1.HyperbolaPayoutCurve.computePayouts(payoutFunction, totalCollateral, roundingIntervals);
158
- const payoutGroups = [];
159
- cetPayouts.forEach((p) => {
160
- payoutGroups.push({
161
- payout: p.payout,
162
- groups: (0, core_1.groupByIgnoringDigits)(p.indexFrom, p.indexTo, eventDescriptor.base, contractDescriptor.numDigits),
163
- });
164
- });
165
- const rValuesMessagesList = this.GenerateMessages(oracleInfo);
166
- const { payouts, messagesList } = (0, Utils_1.outputsToPayouts)(payoutGroups, rValuesMessagesList, dlcOffer.offerCollateralSatoshis, dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, true);
167
- return { payouts, payoutGroups, messagesList };
168
- }
169
- GetPayoutsFromPolynomialPayoutFunction(_dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
170
- if (_dlcOffer.type !== messaging_1.MessageType.DlcOfferV0)
171
- throw Error('DlcOffer must be V0');
172
- const dlcOffer = _dlcOffer;
173
- if (contractDescriptor.payoutFunction.type !== messaging_1.MessageType.PayoutFunctionV0)
174
- throw Error('PayoutFunction must be V0');
175
- const payoutFunction = contractDescriptor.payoutFunction;
176
- if (payoutFunction.pieces.length === 0)
177
- throw Error('PayoutFunction must have at least once PayoutCurvePiece');
178
- for (const piece of payoutFunction.pieces) {
179
- if (piece.payoutCurvePiece.type !== messaging_1.MessageType.PolynomialPayoutCurvePiece)
180
- throw Error('Must be PolynomialPayoutCurvePiece');
181
- }
182
- const eventDescriptor = oracleInfo.announcement.oracleEvent
183
- .eventDescriptor;
184
- if (eventDescriptor.type !== messaging_1.MessageType.DigitDecompositionEventDescriptorV0)
185
- throw Error('Only DigitDecomposition Oracle Events supported');
186
- const roundingIntervals = contractDescriptor.roundingIntervals;
187
- const cetPayouts = core_1.PolynomialPayoutCurve.computePayouts(payoutFunction, totalCollateral, roundingIntervals);
188
- const payoutGroups = [];
189
- cetPayouts.forEach((p) => {
190
- payoutGroups.push({
191
- payout: p.payout,
192
- groups: (0, core_1.groupByIgnoringDigits)(p.indexFrom, p.indexTo, eventDescriptor.base, contractDescriptor.numDigits),
193
- });
194
- });
195
- const rValuesMessagesList = this.GenerateMessages(oracleInfo);
196
- const { payouts, messagesList } = (0, Utils_1.outputsToPayouts)(payoutGroups, rValuesMessagesList, dlcOffer.offerCollateralSatoshis, dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis, true);
197
- return { payouts, payoutGroups, messagesList };
198
- }
199
- GetPayouts(_dlcOffer) {
200
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
201
- const contractInfo = dlcOffer.contractInfo;
202
- const totalCollateral = contractInfo.totalCollateral;
203
- const contractOraclePairs = this.GetContractOraclePairs(contractInfo);
204
- const payoutResponses = contractOraclePairs.map(({ contractDescriptor, oracleInfo }) => this.GetPayoutsFromContractDescriptor(dlcOffer, contractDescriptor, oracleInfo, totalCollateral));
205
- return payoutResponses;
206
- }
207
- FlattenPayouts(payoutResponses) {
208
- return payoutResponses.reduce((acc, { payouts, payoutGroups, messagesList }) => {
209
- return {
210
- payouts: acc.payouts.concat(payouts),
211
- payoutGroups: acc.payoutGroups.concat(payoutGroups),
212
- messagesList: acc.messagesList.concat(messagesList),
213
- };
214
- });
215
- }
216
- GetIndicesFromPayouts(payoutResponses) {
217
- return payoutResponses.reduce((prev, acc) => {
218
- return prev.concat({
219
- startingMessagesIndex: prev[prev.length - 1].startingMessagesIndex +
220
- acc.messagesList.length,
221
- startingPayoutGroupsIndex: prev[prev.length - 1].startingPayoutGroupsIndex +
222
- acc.payoutGroups.length,
223
- });
224
- }, [{ startingMessagesIndex: 0, startingPayoutGroupsIndex: 0 }]);
225
- }
226
- GetPayoutsFromContractDescriptor(dlcOffer, contractDescriptor, oracleInfo, totalCollateral) {
227
- switch (contractDescriptor.type) {
228
- case messaging_1.MessageType.ContractDescriptorV0: {
229
- throw Error('ContractDescriptorV0 not yet supported');
230
- }
231
- case messaging_1.MessageType.ContractDescriptorV1:
232
- {
233
- const contractDescriptorV1 = contractDescriptor;
234
- const payoutFunction = contractDescriptorV1.payoutFunction;
235
- // TODO: add a better check for this
236
- const payoutCurvePiece = payoutFunction.pieces[0].payoutCurvePiece;
237
- switch (payoutCurvePiece.type) {
238
- case messaging_1.MessageType.HyperbolaPayoutCurvePiece:
239
- return this.GetPayoutsFromPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
240
- case messaging_1.MessageType.OldHyperbolaPayoutCurvePiece:
241
- return this.GetPayoutsFromPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
242
- case messaging_1.MessageType.PolynomialPayoutCurvePiece:
243
- return this.GetPayoutsFromPolynomialPayoutFunction(dlcOffer, contractDescriptor, oracleInfo, totalCollateral);
244
- }
245
- }
246
- break;
247
- default: {
248
- throw Error('ContractDescriptor must be V0 or V1');
249
- }
250
- }
251
- }
252
- async createDlcTxs(_dlcOffer, _dlcAccept) {
253
- const { dlcOffer, dlcAccept } = (0, Utils_1.checkTypes)({
254
- _dlcOffer,
255
- _dlcAccept,
256
- });
257
- const localFundPubkey = dlcOffer.fundingPubKey.toString('hex');
258
- const remoteFundPubkey = dlcAccept.fundingPubKey.toString('hex');
259
- const localFinalScriptPubkey = dlcOffer.payoutSPK.toString('hex');
260
- const remoteFinalScriptPubkey = dlcAccept.payoutSPK.toString('hex');
261
- const localChangeScriptPubkey = dlcOffer.changeSPK.toString('hex');
262
- const remoteChangeScriptPubkey = dlcAccept.changeSPK.toString('hex');
263
- const localInputs = await Promise.all(dlcOffer.fundingInputs.map(async (fundingInput) => {
264
- const input = await this.fundingInputToInput(fundingInput, false);
265
- return input.toUtxo();
266
- }));
267
- const remoteInputs = await Promise.all(dlcAccept.fundingInputs.map(async (fundingInput) => {
268
- const input = await this.fundingInputToInput(fundingInput, false);
269
- return input.toUtxo();
270
- }));
271
- const localInputAmount = localInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
272
- const remoteInputAmount = remoteInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
273
- let payouts = [];
274
- let messagesList = [];
275
- if (dlcOffer.contractInfo.type === messaging_1.MessageType.ContractInfoV0 &&
276
- dlcOffer.contractInfo.contractDescriptor.type ===
277
- messaging_1.MessageType.ContractDescriptorV0) {
278
- for (const outcome of dlcOffer.contractInfo
279
- .contractDescriptor.outcomes) {
280
- payouts.push({
281
- local: outcome.localPayout,
282
- remote: dlcOffer.offerCollateralSatoshis +
283
- dlcAccept.acceptCollateralSatoshis -
284
- outcome.localPayout,
285
- });
286
- messagesList.push({ messages: [outcome.outcome.toString('hex')] });
287
- }
288
- }
289
- else {
290
- const payoutResponses = this.GetPayouts(dlcOffer);
291
- const { payouts: tempPayouts, messagesList: tempMessagesList, } = this.FlattenPayouts(payoutResponses);
292
- payouts = tempPayouts;
293
- messagesList = tempMessagesList;
294
- }
295
- const dlcTxRequest = {
296
- payouts,
297
- localFundPubkey,
298
- localFinalScriptPubkey,
299
- remoteFundPubkey,
300
- remoteFinalScriptPubkey,
301
- localInputAmount,
302
- localCollateralAmount: dlcOffer.offerCollateralSatoshis,
303
- localPayoutSerialId: dlcOffer.payoutSerialId,
304
- localChangeSerialId: dlcOffer.changeSerialId,
305
- remoteInputAmount,
306
- remoteCollateralAmount: dlcAccept.acceptCollateralSatoshis,
307
- remotePayoutSerialId: dlcAccept.payoutSerialId,
308
- remoteChangeSerialId: dlcAccept.changeSerialId,
309
- refundLocktime: dlcOffer.refundLocktime,
310
- localInputs,
311
- remoteInputs,
312
- localChangeScriptPubkey,
313
- remoteChangeScriptPubkey,
314
- feeRate: Number(dlcOffer.feeRatePerVb),
315
- cetLockTime: dlcOffer.cetLocktime,
316
- fundOutputSerialId: dlcOffer.fundOutputSerialId,
317
- };
318
- const dlcTxs = await this.CreateDlcTransactions(dlcTxRequest);
319
- const dlcTransactions = new messaging_1.DlcTransactionsV0();
320
- dlcTransactions.fundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.fundTxHex));
321
- dlcTransactions.fundTxVout = [
322
- BigInt(dlcOffer.changeSerialId),
323
- BigInt(dlcAccept.changeSerialId),
324
- BigInt(dlcTxRequest.fundOutputSerialId),
325
- ]
326
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
327
- .findIndex((i) => BigInt(i) === BigInt(dlcTxRequest.fundOutputSerialId));
328
- dlcTransactions.refundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.refundTxHex));
329
- dlcTransactions.cets = dlcTxs.cetsHex.map((cetHex) => {
330
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(cetHex));
331
- });
332
- return { dlcTransactions, messagesList };
333
- }
334
- async createBatchDlcTxs(_dlcOffers, _dlcAccepts) {
335
- const dlcOffers = _dlcOffers.map((dlcOffer) => {
336
- return (0, Utils_1.checkTypes)({ _dlcOffer: dlcOffer }).dlcOffer;
337
- });
338
- const dlcAccepts = _dlcAccepts.map((dlcAccept) => {
339
- return (0, Utils_1.checkTypes)({ _dlcAccept: dlcAccept }).dlcAccept;
340
- });
341
- const localFundPubkeys = dlcOffers.map((dlcOffer) => dlcOffer.fundingPubKey.toString('hex'));
342
- const remoteFundPubkeys = dlcAccepts.map((dlcAccept) => dlcAccept.fundingPubKey.toString('hex'));
343
- const localFinalScriptPubkeys = dlcOffers.map((dlcOffer) => dlcOffer.payoutSPK.toString('hex'));
344
- const remoteFinalScriptPubkeys = dlcAccepts.map((dlcAccept) => dlcAccept.payoutSPK.toString('hex'));
345
- const localChangeScriptPubkey = dlcOffers[0].changeSPK.toString('hex');
346
- const remoteChangeScriptPubkey = dlcAccepts[0].changeSPK.toString('hex');
347
- const localInputs = await Promise.all(dlcOffers[0].fundingInputs.map(async (fundingInput) => {
348
- const input = await this.fundingInputToInput(fundingInput, false);
349
- return input.toUtxo();
350
- }));
351
- const remoteInputs = await Promise.all(dlcAccepts[0].fundingInputs.map(async (fundingInput) => {
352
- const input = await this.fundingInputToInput(fundingInput, false);
353
- return input.toUtxo();
354
- }));
355
- const localInputAmount = localInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
356
- const remoteInputAmount = remoteInputs.reduce((prev, cur) => prev + cur.amount.GetSatoshiAmount(), 0);
357
- const localPayouts = [];
358
- const remotePayouts = [];
359
- const numPayouts = [];
360
- const nestedMessagesList = [];
361
- // loop through all dlc offers, get payouts, and add to localPayouts and remotePayouts
362
- for (const dlcOffer of dlcOffers) {
363
- const payoutResponses = this.GetPayouts(dlcOffer);
364
- const { payouts, messagesList } = this.FlattenPayouts(payoutResponses);
365
- const tempLocalPayouts = payouts.map((payout) => payout.local);
366
- const tempRemotePayouts = payouts.map((payout) => payout.remote);
367
- localPayouts.push(...tempLocalPayouts);
368
- remotePayouts.push(...tempRemotePayouts);
369
- numPayouts.push(tempLocalPayouts.length);
370
- nestedMessagesList.push(messagesList);
371
- }
372
- const batchDlcTxRequest = {
373
- localPayouts,
374
- remotePayouts,
375
- numPayouts,
376
- localFundPubkeys,
377
- localFinalScriptPubkeys,
378
- remoteFundPubkeys,
379
- remoteFinalScriptPubkeys,
380
- localInputAmount,
381
- localCollateralAmounts: dlcOffers.map((dlcOffer) => dlcOffer.offerCollateralSatoshis),
382
- localPayoutSerialIds: dlcOffers.map((dlcOffer) => dlcOffer.payoutSerialId),
383
- localChangeSerialId: dlcOffers[0].changeSerialId,
384
- remoteInputAmount,
385
- remoteCollateralAmounts: dlcAccepts.map((dlcAccept) => dlcAccept.acceptCollateralSatoshis),
386
- remotePayoutSerialIds: dlcAccepts.map((dlcAccept) => dlcAccept.payoutSerialId),
387
- remoteChangeSerialId: dlcAccepts[0].changeSerialId,
388
- refundLocktimes: dlcOffers.map((dlcOffer) => dlcOffer.refundLocktime),
389
- localInputs,
390
- remoteInputs,
391
- localChangeScriptPubkey,
392
- remoteChangeScriptPubkey,
393
- feeRate: Number(dlcOffers[0].feeRatePerVb),
394
- cetLockTime: dlcOffers[0].cetLocktime,
395
- fundOutputSerialIds: dlcOffers.map((dlcOffer) => dlcOffer.fundOutputSerialId),
396
- };
397
- const dlcTxs = await this.CreateBatchDlcTransactions(batchDlcTxRequest);
398
- const dlcTransactionsList = [];
399
- let start = 0;
400
- for (let i = 0; i < dlcTxs.refundTxHexList.length; i++) {
401
- const dlcTransactions = new messaging_1.DlcTransactionsV0();
402
- dlcTransactions.fundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.fundTxHex));
403
- dlcTransactions.fundTxVout = [
404
- BigInt(dlcOffers[i].changeSerialId),
405
- BigInt(dlcAccepts[i].changeSerialId),
406
- ...dlcOffers.map((dlcOffer) => dlcOffer.fundOutputSerialId),
407
- ]
408
- .sort((a, b) => (a < b ? -1 : a > b ? 1 : 0))
409
- .findIndex((j) => BigInt(j) === BigInt(dlcOffers[i].fundOutputSerialId));
410
- dlcTransactions.refundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(dlcTxs.refundTxHexList[i]));
411
- // slice cetsHexList based on numPayouts
412
- const end = start + Number(numPayouts[i]);
413
- const cetsHexList = dlcTxs.cetsHexList.slice(start, end);
414
- start = end;
415
- dlcTransactions.cets = cetsHexList.map((cetHex) => {
416
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(cetHex));
417
- });
418
- dlcTransactionsList.push(dlcTransactions);
419
- }
420
- return { dlcTransactionsList, nestedMessagesList };
421
- }
422
- GenerateEnumMessages(oracleEvent) {
423
- throw Error('Only DigitDecomposition Oracle Events supported');
424
- }
425
- GenerateDigitDecompositionMessages(oracleEvent) {
426
- const oracleNonces = oracleEvent.oracleNonces;
427
- const eventDescriptor = oracleEvent.eventDescriptor;
428
- const messagesList = [];
429
- oracleNonces.forEach(() => {
430
- const messages = [];
431
- for (let i = 0; i < eventDescriptor.base; i++) {
432
- const m = i.toString();
433
- messages.push(m);
434
- }
435
- messagesList.push({ messages });
436
- });
437
- return messagesList;
438
- }
439
- GenerateMessages(oracleInfo) {
440
- const oracleEvent = oracleInfo.announcement.oracleEvent;
441
- switch (oracleEvent.eventDescriptor.type) {
442
- case messaging_1.MessageType.EnumEventDescriptorV0:
443
- return this.GenerateEnumMessages(oracleEvent);
444
- case messaging_1.MessageType.DigitDecompositionEventDescriptorV0:
445
- return this.GenerateDigitDecompositionMessages(oracleEvent);
446
- default:
447
- throw Error('EventDescriptor must be Enum or DigitDecomposition');
448
- }
449
- }
450
- GetContractOraclePairs(_contractInfo) {
451
- switch (_contractInfo.type) {
452
- case messaging_1.MessageType.ContractInfoV0: {
453
- const contractInfo = _contractInfo;
454
- return [
455
- {
456
- contractDescriptor: contractInfo.contractDescriptor,
457
- oracleInfo: contractInfo.oracleInfo,
458
- },
459
- ];
460
- }
461
- case messaging_1.MessageType.ContractInfoV1: {
462
- return _contractInfo.contractOraclePairs;
463
- }
464
- default:
465
- throw Error('ContractInfo must be V0 or V1');
466
- }
467
- }
468
- async CreateCetAdaptorAndRefundSigs(_dlcOffer, _dlcAccept, _dlcTxs, messagesList, isOfferer) {
469
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
470
- _dlcOffer,
471
- _dlcAccept,
472
- _dlcTxs,
473
- });
474
- const network = await this.getConnectedNetwork();
475
- const cetsHex = dlcTxs.cets.map((cet) => cet.serialize().toString('hex'));
476
- const fundingSPK = bitcoin_1.Script.p2wpkhLock((0, crypto_1.hash160)(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey))
477
- .serialize()
478
- .slice(1);
479
- const fundingAddress = bitcoinjs_lib_1.address.fromOutputScript(fundingSPK, network);
480
- const { derivationPath } = await this.client.wallet.findAddress([
481
- fundingAddress,
482
- ]);
483
- const fundPrivateKeyPair = await this.getMethod('keyPair')(derivationPath);
484
- const fundPrivateKey = Buffer.from(fundPrivateKeyPair.__D).toString('hex');
485
- const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
486
- const sigs = [];
487
- if (dlcOffer.contractInfo.type === messaging_1.MessageType.ContractInfoV0 &&
488
- dlcOffer.contractInfo.contractDescriptor.type ===
489
- messaging_1.MessageType.ContractDescriptorV0) {
490
- for (const [_, { oracleInfo }] of contractOraclePairs.entries()) {
491
- const oracleAnnouncement = oracleInfo.announcement;
492
- const adaptorSigRequestPromises = [];
493
- const tempMessagesList = messagesList;
494
- const tempCetsHex = cetsHex;
495
- const cetSignRequest = {
496
- messagesList: tempMessagesList,
497
- cetsHex: tempCetsHex,
498
- privkey: fundPrivateKey,
499
- fundTxId: dlcTxs.fundTx.txId.toString(),
500
- fundVout: dlcTxs.fundTxVout,
501
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
502
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
503
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
504
- oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
505
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
506
- };
507
- adaptorSigRequestPromises.push((async () => {
508
- const response = await this.CreateCetAdaptorSignatures(cetSignRequest);
509
- return response.adaptorPairs;
510
- })());
511
- const adaptorPairs = (await Promise.all(adaptorSigRequestPromises)).flat();
512
- sigs.push(adaptorPairs.map((adaptorPair) => {
513
- return {
514
- encryptedSig: Buffer.from(adaptorPair.signature, 'hex'),
515
- dleqProof: Buffer.from(adaptorPair.proof, 'hex'),
516
- };
517
- }));
518
- }
519
- }
520
- else {
521
- const indices = this.GetIndicesFromPayouts(this.GetPayouts(_dlcOffer));
522
- for (const [index, { oracleInfo }] of contractOraclePairs.entries()) {
523
- const oracleAnnouncement = oracleInfo.announcement;
524
- const startingIndex = indices[index].startingMessagesIndex, endingIndex = indices[index + 1].startingMessagesIndex;
525
- const oracleEventMessagesList = messagesList.slice(startingIndex, endingIndex);
526
- const oracleEventCetsHex = cetsHex.slice(startingIndex, endingIndex);
527
- const chunk = 100;
528
- const adaptorSigRequestPromises = [];
529
- for (let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk) {
530
- const tempMessagesList = oracleEventMessagesList.slice(i, i + chunk);
531
- const tempCetsHex = oracleEventCetsHex.slice(i, i + chunk);
532
- const cetSignRequest = {
533
- messagesList: tempMessagesList,
534
- cetsHex: tempCetsHex,
535
- privkey: fundPrivateKey,
536
- fundTxId: dlcTxs.fundTx.txId.toString(),
537
- fundVout: dlcTxs.fundTxVout,
538
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
539
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
540
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
541
- oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
542
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
543
- };
544
- adaptorSigRequestPromises.push((async () => {
545
- const response = await this.CreateCetAdaptorSignatures(cetSignRequest);
546
- return response.adaptorPairs;
547
- })());
548
- }
549
- const adaptorPairs = (await Promise.all(adaptorSigRequestPromises)).flat();
550
- sigs.push(adaptorPairs.map((adaptorPair) => {
551
- return {
552
- encryptedSig: Buffer.from(adaptorPair.signature, 'hex'),
553
- dleqProof: Buffer.from(adaptorPair.proof, 'hex'),
554
- };
555
- }));
556
- }
557
- }
558
- const refundSignRequest = {
559
- refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
560
- privkey: fundPrivateKey,
561
- fundTxId: dlcTxs.fundTx.txId.toString(),
562
- fundVout: dlcTxs.fundTxVout,
563
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
564
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
565
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
566
- };
567
- const refundSignature = Buffer.from((await this.GetRawRefundTxSignature(refundSignRequest)).hex, 'hex');
568
- const cetSignatures = new messaging_1.CetAdaptorSignaturesV0();
569
- cetSignatures.sigs = sigs.flat();
570
- return { cetSignatures, refundSignature };
571
- }
572
- async VerifyCetAdaptorAndRefundSigs(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, messagesList, isOfferer) {
573
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
574
- _dlcOffer,
575
- _dlcAccept,
576
- _dlcSign,
577
- _dlcTxs,
578
- });
579
- const cetsHex = dlcTxs.cets.map((cet) => cet.serialize().toString('hex'));
580
- const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
581
- if (dlcOffer.contractInfo.type === messaging_1.MessageType.ContractInfoV0 &&
582
- dlcOffer.contractInfo.contractDescriptor.type ===
583
- messaging_1.MessageType.ContractDescriptorV0) {
584
- for (const [_, { oracleInfo }] of contractOraclePairs.entries()) {
585
- const oracleAnnouncement = oracleInfo.announcement;
586
- const oracleEventCetsHex = cetsHex;
587
- const oracleEventSigs = isOfferer
588
- ? dlcAccept.cetSignatures.sigs
589
- : dlcSign.cetSignatures.sigs;
590
- const sigsValidity = [];
591
- const tempMessagesList = messagesList;
592
- const tempCetsHex = oracleEventCetsHex;
593
- const tempSigs = oracleEventSigs;
594
- const tempAdaptorPairs = tempSigs.map((sig) => {
595
- return {
596
- signature: sig.encryptedSig.toString('hex'),
597
- proof: sig.dleqProof.toString('hex'),
598
- };
599
- });
600
- const verifyCetAdaptorSignaturesRequest = {
601
- cetsHex: tempCetsHex,
602
- messagesList: tempMessagesList,
603
- oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
604
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
605
- adaptorPairs: tempAdaptorPairs,
606
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
607
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
608
- fundTxId: dlcTxs.fundTx.txId.toString(),
609
- fundVout: dlcTxs.fundTxVout,
610
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
611
- verifyRemote: isOfferer,
612
- };
613
- sigsValidity.push((async () => {
614
- const response = await this.VerifyCetAdaptorSignatures(verifyCetAdaptorSignaturesRequest);
615
- return response.valid;
616
- })());
617
- let areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
618
- const verifyRefundSigRequest = {
619
- refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
620
- signature: isOfferer
621
- ? dlcAccept.refundSignature.toString('hex')
622
- : dlcSign.refundSignature.toString('hex'),
623
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
624
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
625
- fundTxId: dlcTxs.fundTx.txId.toString(),
626
- fundVout: dlcTxs.fundTxVout,
627
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
628
- verifyRemote: isOfferer,
629
- };
630
- areSigsValid =
631
- areSigsValid &&
632
- (await this.VerifyRefundTxSignature(verifyRefundSigRequest)).valid;
633
- if (!areSigsValid) {
634
- throw new Error('Invalid signatures received');
635
- }
636
- }
637
- }
638
- else {
639
- const chunk = 100;
640
- const indices = this.GetIndicesFromPayouts(this.GetPayouts(_dlcOffer));
641
- for (const [index, { oracleInfo }] of contractOraclePairs.entries()) {
642
- const oracleAnnouncement = oracleInfo.announcement;
643
- const startingIndex = indices[index].startingMessagesIndex, endingIndex = indices[index + 1].startingMessagesIndex;
644
- const oracleEventMessagesList = messagesList.slice(startingIndex, endingIndex);
645
- const oracleEventCetsHex = cetsHex.slice(startingIndex, endingIndex);
646
- const oracleEventSigs = (isOfferer
647
- ? dlcAccept.cetSignatures.sigs
648
- : dlcSign.cetSignatures.sigs).slice(startingIndex, endingIndex);
649
- const sigsValidity = [];
650
- for (let i = 0, j = oracleEventMessagesList.length; i < j; i += chunk) {
651
- const tempMessagesList = oracleEventMessagesList.slice(i, i + chunk);
652
- const tempCetsHex = oracleEventCetsHex.slice(i, i + chunk);
653
- const tempSigs = oracleEventSigs.slice(i, i + chunk);
654
- const tempAdaptorPairs = tempSigs.map((sig) => {
655
- return {
656
- signature: sig.encryptedSig.toString('hex'),
657
- proof: sig.dleqProof.toString('hex'),
658
- };
659
- });
660
- const verifyCetAdaptorSignaturesRequest = {
661
- cetsHex: tempCetsHex,
662
- messagesList: tempMessagesList,
663
- oraclePubkey: oracleAnnouncement.oraclePubkey.toString('hex'),
664
- oracleRValues: oracleAnnouncement.oracleEvent.oracleNonces.map((nonce) => nonce.toString('hex')),
665
- adaptorPairs: tempAdaptorPairs,
666
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
667
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
668
- fundTxId: dlcTxs.fundTx.txId.toString(),
669
- fundVout: dlcTxs.fundTxVout,
670
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
671
- verifyRemote: isOfferer,
672
- };
673
- sigsValidity.push((async () => {
674
- const response = await this.VerifyCetAdaptorSignatures(verifyCetAdaptorSignaturesRequest);
675
- return response.valid;
676
- })());
677
- }
678
- let areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
679
- const verifyRefundSigRequest = {
680
- refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
681
- signature: isOfferer
682
- ? dlcAccept.refundSignature.toString('hex')
683
- : dlcSign.refundSignature.toString('hex'),
684
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
685
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
686
- fundTxId: dlcTxs.fundTx.txId.toString(),
687
- fundVout: dlcTxs.fundTxVout,
688
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
689
- verifyRemote: isOfferer,
690
- };
691
- areSigsValid =
692
- areSigsValid &&
693
- (await this.VerifyRefundTxSignature(verifyRefundSigRequest)).valid;
694
- if (!areSigsValid) {
695
- throw new Error('Invalid signatures received');
696
- }
697
- }
698
- }
699
- }
700
- async CreateFundingSigs(_dlcOffer, _dlcAccept, _dlcTxs, isOfferer) {
701
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
702
- _dlcOffer,
703
- _dlcAccept,
704
- _dlcTxs,
705
- });
706
- const fundingInputs = isOfferer
707
- ? dlcOffer.fundingInputs
708
- : dlcAccept.fundingInputs;
709
- const inputs = await Promise.all(fundingInputs.map(async (fundingInput) => {
710
- return this.fundingInputToInput(fundingInput);
711
- }));
712
- const inputPrivKeys = await this.GetPrivKeysForInputs(inputs);
713
- const fundTxSigs = await Promise.all(inputs.map(async (input, index) => {
714
- const fundTxSignRequest = {
715
- fundTxHex: dlcTxs.fundTx.serialize().toString('hex'),
716
- privkey: inputPrivKeys[index],
717
- prevTxId: input.txid,
718
- prevVout: input.vout,
719
- amount: input.value,
720
- };
721
- return (await this.GetRawFundTxSignature(fundTxSignRequest)).hex;
722
- }));
723
- const inputPubKeys = await Promise.all(inputPrivKeys.map(async (privkey) => {
724
- const reqPrivKey = {
725
- privkey,
726
- isCompressed: true,
727
- };
728
- return (await this.getMethod('GetPubkeyFromPrivkey')(reqPrivKey))
729
- .pubkey;
730
- }));
731
- const witnessElements = [];
732
- for (let i = 0; i < fundTxSigs.length; i++) {
733
- const sigWitness = new messaging_1.ScriptWitnessV0();
734
- sigWitness.witness = Buffer.from(fundTxSigs[i], 'hex');
735
- const pubKeyWitness = new messaging_1.ScriptWitnessV0();
736
- pubKeyWitness.witness = Buffer.from(inputPubKeys[i], 'hex');
737
- witnessElements.push([sigWitness, pubKeyWitness]);
738
- }
739
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
740
- fundingSignatures.witnessElements = witnessElements;
741
- return fundingSignatures;
742
- }
743
- async VerifyFundingSigs(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, isOfferer) {
744
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
745
- _dlcOffer,
746
- _dlcAccept,
747
- _dlcSign,
748
- _dlcTxs,
749
- });
750
- const sigsValidity = [];
751
- for (let i = 0; i < dlcSign.fundingSignatures.witnessElements.length; i++) {
752
- const witnessElement = dlcSign.fundingSignatures.witnessElements[i];
753
- const signature = witnessElement[0].witness.toString('hex');
754
- const pubkey = witnessElement[1].witness.toString('hex');
755
- const fundingInput = isOfferer
756
- ? dlcAccept.fundingInputs[i]
757
- : dlcOffer.fundingInputs[i];
758
- const verifyFundSigRequest = {
759
- fundTxHex: dlcTxs.fundTx.serialize().toString('hex'),
760
- signature,
761
- pubkey,
762
- prevTxId: fundingInput.prevTx.txId.toString(),
763
- prevVout: fundingInput.prevTxVout,
764
- fundInputAmount: fundingInput.prevTx.outputs[fundingInput.prevTxVout].value.sats,
765
- };
766
- sigsValidity.push((async () => {
767
- const response = await this.VerifyFundTxSignature(verifyFundSigRequest);
768
- return response.valid;
769
- })());
770
- }
771
- const areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
772
- if (!areSigsValid) {
773
- throw new Error('Invalid signatures received');
774
- }
775
- }
776
- async CreateFundingTx(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, fundingSignatures) {
777
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
778
- _dlcOffer,
779
- _dlcAccept,
780
- _dlcSign,
781
- _dlcTxs,
782
- });
783
- const witnessElements = [
784
- ...dlcSign.fundingSignatures.witnessElements,
785
- ...fundingSignatures.witnessElements,
786
- ];
787
- const fundingInputs = [
788
- ...dlcOffer.fundingInputs,
789
- ...dlcAccept.fundingInputs,
790
- ];
791
- let fundTxHex = dlcTxs.fundTx.serialize().toString('hex');
792
- await (0, Utils_1.asyncForEach)(witnessElements, async (witnessElement, i) => {
793
- const signature = witnessElement[0].witness.toString('hex');
794
- const pubkey = witnessElement[1].witness.toString('hex');
795
- const fundingInput = fundingInputs[i];
796
- const addSignRequest = {
797
- fundTxHex,
798
- signature,
799
- prevTxId: fundingInput.prevTx.txId.toString(),
800
- prevVout: fundingInput.prevTxVout,
801
- pubkey,
802
- };
803
- fundTxHex = (await this.AddSignatureToFundTransaction(addSignRequest))
804
- .hex;
805
- });
806
- const fundTx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(fundTxHex));
807
- return fundTx;
808
- }
809
- async FindOutcomeIndexFromPolynomialPayoutCurvePiece(_dlcOffer, contractDescriptor, contractOraclePairIndex, polynomialPayoutCurvePiece, oracleAttestation, outcome) {
810
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
811
- const polynomialCurve = core_1.PolynomialPayoutCurve.fromPayoutCurvePiece(polynomialPayoutCurvePiece);
812
- const payouts = polynomialPayoutCurvePiece.points.map((point) => Number(point.outcomePayout));
813
- const minPayout = Math.min(...payouts);
814
- const maxPayout = Math.max(...payouts);
815
- const clampBN = (val) => bignumber_js_1.default.max(minPayout, bignumber_js_1.default.min(val, maxPayout));
816
- const payout = clampBN(polynomialCurve.getPayout(outcome));
817
- const payoutResponses = this.GetPayouts(dlcOffer);
818
- const payoutIndexOffset = this.GetIndicesFromPayouts(payoutResponses)[contractOraclePairIndex].startingMessagesIndex;
819
- const { payoutGroups } = payoutResponses[contractOraclePairIndex];
820
- const intervalsSorted = [
821
- ...contractDescriptor.roundingIntervals.intervals,
822
- ].sort((a, b) => Number(b.beginInterval) - Number(a.beginInterval));
823
- const interval = intervalsSorted.find((interval) => Number(outcome) >= Number(interval.beginInterval));
824
- const roundedPayout = BigInt(clampBN(new bignumber_js_1.default((0, core_1.roundPayout)(payout, interval.roundingMod).toString())).toString());
825
- const outcomesFormatted = oracleAttestation.outcomes.map((outcome) => parseInt(outcome));
826
- let index = 0;
827
- let groupIndex = -1;
828
- let groupLength = 0;
829
- for (const payoutGroup of payoutGroups) {
830
- if (payoutGroup.payout === roundedPayout) {
831
- groupIndex = payoutGroup.groups.findIndex((group) => {
832
- return group.every((msg, i) => msg === outcomesFormatted[i]);
833
- });
834
- if (groupIndex === -1)
835
- throw Error('Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
836
- Payout Group found but incorrect group index');
837
- index += groupIndex;
838
- groupLength = payoutGroup.groups[groupIndex].length;
839
- break;
840
- }
841
- else {
842
- index += payoutGroup.groups.length;
843
- }
844
- }
845
- if (groupIndex === -1)
846
- throw Error('Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
847
- Payout Group not found');
848
- return { index: payoutIndexOffset + index, groupLength };
849
- }
850
- async FindOutcomeIndexFromHyperbolaPayoutCurvePiece(_dlcOffer, contractDescriptor, contractOraclePairIndex, hyperbolaPayoutCurvePiece, oracleAttestation, outcome) {
851
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
852
- const hyperbolaCurve = core_1.HyperbolaPayoutCurve.fromPayoutCurvePiece(hyperbolaPayoutCurvePiece);
853
- const clampBN = (val) => bignumber_js_1.default.max(0, bignumber_js_1.default.min(val, dlcOffer.contractInfo.totalCollateral.toString()));
854
- const payout = clampBN(hyperbolaCurve.getPayout(outcome));
855
- const payoutResponses = this.GetPayouts(dlcOffer);
856
- const payoutIndexOffset = this.GetIndicesFromPayouts(payoutResponses)[contractOraclePairIndex].startingMessagesIndex;
857
- const { payoutGroups } = payoutResponses[contractOraclePairIndex];
858
- const intervalsSorted = [
859
- ...contractDescriptor.roundingIntervals.intervals,
860
- ].sort((a, b) => Number(b.beginInterval) - Number(a.beginInterval));
861
- const interval = intervalsSorted.find((interval) => Number(outcome) >= Number(interval.beginInterval));
862
- const roundedPayout = BigInt(clampBN(new bignumber_js_1.default((0, core_1.roundPayout)(payout, interval.roundingMod).toString())).toString());
863
- const outcomesFormatted = oracleAttestation.outcomes.map((outcome) => parseInt(outcome));
864
- let index = 0;
865
- let groupIndex = -1;
866
- let groupLength = 0;
867
- for (const [i, payoutGroup] of payoutGroups.entries()) {
868
- if (payoutGroup.payout === roundedPayout) {
869
- groupIndex = payoutGroup.groups.findIndex((group) => {
870
- return group.every((msg, i) => msg === outcomesFormatted[i]);
871
- });
872
- if (groupIndex !== -1) {
873
- index += groupIndex;
874
- groupLength = payoutGroup.groups[groupIndex].length;
875
- break;
876
- }
877
- }
878
- else if (payoutGroup.payout === BigInt(Math.round(Number(payout.toString()))) &&
879
- i !== 0) {
880
- // Edge case to account for case where payout is maximum payout for DLC
881
- // But rounded payout does not round down
882
- if (payoutGroups[i - 1].payout === roundedPayout) {
883
- // Ensure that the previous payout group causes index to be incremented
884
- index += payoutGroups[i - 1].groups.length;
885
- }
886
- groupIndex = payoutGroup.groups.findIndex((group) => {
887
- return group.every((msg, i) => msg === outcomesFormatted[i]);
888
- });
889
- if (groupIndex !== -1) {
890
- index += groupIndex;
891
- groupLength = payoutGroup.groups[groupIndex].length;
892
- break;
893
- }
894
- }
895
- else {
896
- index += payoutGroup.groups.length;
897
- }
898
- }
899
- if (groupIndex === -1) {
900
- throw Error('Failed to Find OutcomeIndex From HyperbolaPayoutCurvePiece. \
901
- Payout Group not found');
902
- }
903
- return { index: payoutIndexOffset + index, groupLength };
904
- }
905
- async FindOutcomeIndex(_dlcOffer, oracleAttestation) {
906
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
907
- const contractOraclePairs = this.GetContractOraclePairs(dlcOffer.contractInfo);
908
- const contractOraclePairIndex = contractOraclePairs.findIndex(({ oracleInfo }) => oracleInfo.announcement.oracleEvent.eventId ===
909
- oracleAttestation.eventId);
910
- (0, assert_1.default)(contractOraclePairIndex !== -1, 'OracleAttestation must be for an existing OracleEvent');
911
- const contractOraclePair = contractOraclePairs[contractOraclePairIndex];
912
- const { contractDescriptor: _contractDescriptor, oracleInfo, } = contractOraclePair;
913
- (0, assert_1.default)(_contractDescriptor.type === messaging_1.MessageType.ContractDescriptorV1, 'ContractDescriptor must be V1');
914
- const contractDescriptor = _contractDescriptor;
915
- const _payoutFunction = contractDescriptor.payoutFunction;
916
- (0, assert_1.default)(_payoutFunction.type === messaging_1.MessageType.PayoutFunctionV0, 'PayoutFunction must be V0');
917
- const eventDescriptor = oracleInfo.announcement.oracleEvent
918
- .eventDescriptor;
919
- const payoutFunction = _payoutFunction;
920
- const base = eventDescriptor.base;
921
- const outcome = [...oracleAttestation.outcomes]
922
- .reverse()
923
- .reduce((acc, val, i) => acc + Number(val) * base ** i, 0);
924
- const piecesSorted = payoutFunction.pieces.sort((a, b) => Number(a.endpoint) - Number(b.endpoint));
925
- const piece = piecesSorted.find((piece) => outcome < piece.endpoint);
926
- switch (piece.payoutCurvePiece.type) {
927
- case messaging_1.MessageType.PolynomialPayoutCurvePiece:
928
- return this.FindOutcomeIndexFromPolynomialPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece.payoutCurvePiece, oracleAttestation, BigInt(outcome));
929
- case messaging_1.MessageType.HyperbolaPayoutCurvePiece:
930
- return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece.payoutCurvePiece, oracleAttestation, BigInt(outcome));
931
- case messaging_1.MessageType.OldHyperbolaPayoutCurvePiece:
932
- return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(dlcOffer, contractDescriptor, contractOraclePairIndex, piece.payoutCurvePiece, oracleAttestation, BigInt(outcome));
933
- default:
934
- throw Error('Must be Hyperbola or Polynomial curve piece');
935
- }
936
- }
937
- ValidateEvent(_dlcOffer, oracleAttestation) {
938
- const { dlcOffer } = (0, Utils_1.checkTypes)({
939
- _dlcOffer,
940
- });
941
- switch (dlcOffer.contractInfo.type) {
942
- case messaging_1.MessageType.ContractInfoV0: {
943
- const contractInfo = dlcOffer.contractInfo;
944
- switch (contractInfo.contractDescriptor.type) {
945
- case messaging_1.MessageType.ContractDescriptorV0: {
946
- const oracleInfo = contractInfo.oracleInfo;
947
- if (oracleInfo.announcement.oracleEvent.eventId !==
948
- oracleAttestation.eventId)
949
- throw Error('Incorrect Oracle Attestation. Event Id must match.');
950
- break;
951
- }
952
- case messaging_1.MessageType.ContractDescriptorV1: {
953
- const oracleInfo = contractInfo.oracleInfo;
954
- if (oracleInfo.announcement.oracleEvent.eventId !==
955
- oracleAttestation.eventId)
956
- throw Error('Incorrect Oracle Attestation. Event Id must match.');
957
- break;
958
- }
959
- default:
960
- throw Error('ConractDescriptor must be V0 or V1');
961
- }
962
- break;
963
- }
964
- case messaging_1.MessageType.ContractInfoV1: {
965
- const contractInfo = dlcOffer.contractInfo;
966
- const attestedOracleEvent = contractInfo.contractOraclePairs.find(({ oracleInfo }) => oracleInfo.announcement.oracleEvent.eventId ===
967
- oracleAttestation.eventId);
968
- if (!attestedOracleEvent)
969
- throw Error('Oracle event of attestation not found.');
970
- break;
971
- }
972
- default:
973
- throw Error('ContractInfo must be V0 or V1');
974
- }
975
- }
976
- async FindAndSignCet(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, oracleAttestation, isOfferer) {
977
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
978
- _dlcOffer,
979
- _dlcAccept,
980
- _dlcSign,
981
- _dlcTxs,
982
- });
983
- if (isOfferer === undefined)
984
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
985
- const fundPrivateKey = await this.GetFundPrivateKey(dlcOffer, dlcAccept, isOfferer);
986
- let signCetRequest;
987
- if (dlcOffer.contractInfo.type === messaging_1.MessageType.ContractInfoV0 &&
988
- dlcOffer.contractInfo.contractDescriptor.type ===
989
- messaging_1.MessageType.ContractDescriptorV0) {
990
- const outcomeIndex = dlcOffer.contractInfo
991
- .contractDescriptor.outcomes.findIndex((outcome) => outcome.outcome.toString('hex') ===
992
- (0, crypto_1.sha256)(Buffer.from(oracleAttestation.outcomes[0])).toString('hex'));
993
- signCetRequest = {
994
- cetHex: dlcTxs.cets[outcomeIndex].serialize().toString('hex'),
995
- fundPrivkey: fundPrivateKey,
996
- fundTxId: dlcTxs.fundTx.txId.toString(),
997
- fundVout: dlcTxs.fundTxVout,
998
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
999
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
1000
- oracleSignatures: oracleAttestation.signatures.map((sig) => sig.toString('hex')),
1001
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
1002
- adaptorSignature: isOfferer
1003
- ? dlcAccept.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex')
1004
- : dlcSign.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex'),
1005
- };
1006
- }
1007
- else {
1008
- const { index: outcomeIndex, groupLength } = await this.FindOutcomeIndex(dlcOffer, oracleAttestation);
1009
- const sliceIndex = -(oracleAttestation.signatures.length - groupLength);
1010
- const oracleSignatures = sliceIndex === 0
1011
- ? oracleAttestation.signatures
1012
- : oracleAttestation.signatures.slice(0, sliceIndex);
1013
- signCetRequest = {
1014
- cetHex: dlcTxs.cets[outcomeIndex].serialize().toString('hex'),
1015
- fundPrivkey: fundPrivateKey,
1016
- fundTxId: dlcTxs.fundTx.txId.toString(),
1017
- fundVout: dlcTxs.fundTxVout,
1018
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
1019
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
1020
- oracleSignatures: oracleSignatures.map((sig) => sig.toString('hex')),
1021
- fundInputAmount: dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats,
1022
- adaptorSignature: isOfferer
1023
- ? dlcAccept.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex')
1024
- : dlcSign.cetSignatures.sigs[outcomeIndex].encryptedSig.toString('hex'),
1025
- };
1026
- }
1027
- const finalCet = (await this.SignCet(signCetRequest)).hex;
1028
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(finalCet));
1029
- }
1030
- async GetFundAddress(dlcOffer, dlcAccept, isOfferer) {
1031
- const network = await this.getConnectedNetwork();
1032
- const fundingSPK = bitcoin_1.Script.p2wpkhLock((0, crypto_1.hash160)(isOfferer ? dlcOffer.fundingPubKey : dlcAccept.fundingPubKey))
1033
- .serialize()
1034
- .slice(1);
1035
- const fundingAddress = bitcoinjs_lib_1.address.fromOutputScript(fundingSPK, network);
1036
- return fundingAddress;
1037
- }
1038
- async GetFundKeyPair(dlcOffer, dlcAccept, isOfferer) {
1039
- const fundingAddress = await this.GetFundAddress(dlcOffer, dlcAccept, isOfferer);
1040
- const { derivationPath } = await this.getMethod('getWalletAddress')(fundingAddress);
1041
- const keyPair = await this.getMethod('keyPair')(derivationPath);
1042
- return keyPair;
1043
- }
1044
- async GetFundPrivateKey(dlcOffer, dlcAccept, isOfferer) {
1045
- const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, isOfferer);
1046
- return Buffer.from(fundPrivateKeyPair.privateKey).toString('hex');
1047
- }
1048
- async CreateCloseRawTxs(_dlcOffer, _dlcAccept, _dlcTxs, closeInputAmount, isOfferer, _dlcCloses = [], fundingInputs, initiatorPayouts) {
1049
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1050
- _dlcOffer,
1051
- _dlcAccept,
1052
- _dlcTxs,
1053
- });
1054
- const network = await this.getConnectedNetwork();
1055
- let finalizer;
1056
- if (_dlcCloses.length === 0) {
1057
- finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1058
- }
1059
- const rawTransactionRequestPromises = [];
1060
- const rawCloseTxs = [];
1061
- const numPayouts = _dlcCloses.length === 0 ? initiatorPayouts.length : _dlcCloses.length;
1062
- for (let i = 0; i < numPayouts; i++) {
1063
- let offerPayoutValue = BigInt(0);
1064
- let acceptPayoutValue = BigInt(0);
1065
- if (_dlcCloses.length === 0) {
1066
- const payout = initiatorPayouts[i];
1067
- const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout
1068
- ? BigInt(0)
1069
- : payout - finalizer.offerInitiatorFees;
1070
- const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral
1071
- ? BigInt(0)
1072
- : dlcOffer.contractInfo.totalCollateral - payout;
1073
- offerPayoutValue = isOfferer
1074
- ? closeInputAmount + payoutMinusOfferFees
1075
- : collateralMinusPayout;
1076
- acceptPayoutValue = isOfferer
1077
- ? collateralMinusPayout
1078
- : closeInputAmount + payoutMinusOfferFees;
1079
- }
1080
- else {
1081
- const dlcClose = (0, Utils_1.checkTypes)({ _dlcClose: _dlcCloses[i] }).dlcClose;
1082
- offerPayoutValue = dlcClose.offerPayoutSatoshis;
1083
- acceptPayoutValue = dlcClose.acceptPayoutSatoshis;
1084
- }
1085
- const txOuts = [];
1086
- if (Number(offerPayoutValue) > 0) {
1087
- txOuts.push({
1088
- address: bitcoinjs_lib_1.address.fromOutputScript(dlcOffer.payoutSPK, network),
1089
- amount: Number(offerPayoutValue),
1090
- });
1091
- }
1092
- if (Number(acceptPayoutValue) > 0) {
1093
- txOuts.push({
1094
- address: bitcoinjs_lib_1.address.fromOutputScript(dlcAccept.payoutSPK, network),
1095
- amount: Number(acceptPayoutValue),
1096
- });
1097
- }
1098
- if (dlcOffer.payoutSerialId > dlcAccept.payoutSerialId)
1099
- txOuts.reverse();
1100
- const rawTransactionRequest = {
1101
- version: 2,
1102
- locktime: 0,
1103
- txins: [
1104
- {
1105
- txid: dlcTxs.fundTx.txId.serialize().reverse().toString('hex'),
1106
- vout: dlcTxs.fundTxVout,
1107
- sequence: 0,
1108
- },
1109
- ],
1110
- txouts: txOuts,
1111
- };
1112
- rawTransactionRequestPromises.push((async () => {
1113
- const response = await this.getMethod('CreateRawTransaction')(rawTransactionRequest);
1114
- return response.hex;
1115
- })());
1116
- }
1117
- const hexs = await Promise.all(rawTransactionRequestPromises);
1118
- rawCloseTxs.push(hexs);
1119
- return rawCloseTxs.flat();
1120
- }
1121
- async CreateSignatureHashes(_dlcOffer, _dlcAccept, _dlcTxs, rawCloseTxs) {
1122
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1123
- _dlcOffer,
1124
- _dlcAccept,
1125
- _dlcTxs,
1126
- });
1127
- const network = await this.getConnectedNetwork();
1128
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1129
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1130
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1131
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1132
- m: 2,
1133
- pubkeys: fundingPubKeys,
1134
- network,
1135
- });
1136
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1137
- redeem: p2ms,
1138
- network,
1139
- });
1140
- const sigHashRequestPromises = [];
1141
- const sigHashes = [];
1142
- for (let i = 0; i < rawCloseTxs.length; i++) {
1143
- const rawTx = rawCloseTxs[i];
1144
- const sigHashRequest = {
1145
- tx: rawTx,
1146
- txin: {
1147
- txid: dlcTxs.fundTx.txId.serialize().reverse().toString('hex'),
1148
- vout: dlcTxs.fundTxVout,
1149
- keyData: {
1150
- hex: paymentVariant.redeem.output.toString('hex'),
1151
- type: 'redeem_script',
1152
- },
1153
- amount: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1154
- hashType: 'p2wsh',
1155
- sighashType: 'all',
1156
- sighashAnyoneCanPay: false,
1157
- },
1158
- };
1159
- sigHashRequestPromises.push((async () => {
1160
- const response = await this.getMethod('CreateSignatureHash')(sigHashRequest);
1161
- return response.sighash;
1162
- })());
1163
- }
1164
- const sighashes = await Promise.all(sigHashRequestPromises);
1165
- sigHashes.push(sighashes);
1166
- return sigHashes.flat();
1167
- }
1168
- async CalculateEcSignatureHashes(sigHashes, privKey) {
1169
- const cfdNetwork = await this.GetCfdNetwork();
1170
- const sigsRequestPromises = [];
1171
- for (let i = 0; i < sigHashes.length; i++) {
1172
- const sigHash = sigHashes[i];
1173
- const calculateEcSignatureRequest = {
1174
- sighash: sigHash,
1175
- privkeyData: {
1176
- privkey: privKey,
1177
- wif: false,
1178
- network: cfdNetwork,
1179
- },
1180
- isGrindR: true,
1181
- };
1182
- sigsRequestPromises.push((async () => {
1183
- const response = await this.getMethod('CalculateEcSignature')(calculateEcSignatureRequest);
1184
- return response.signature;
1185
- })());
1186
- }
1187
- const sigs = await Promise.all(sigsRequestPromises);
1188
- return sigs.flat();
1189
- }
1190
- async VerifySignatures(_dlcOffer, _dlcAccept, _dlcTxs, _dlcCloses, rawCloseTxs, isOfferer) {
1191
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1192
- _dlcOffer,
1193
- _dlcAccept,
1194
- _dlcTxs,
1195
- });
1196
- const dlcCloses = _dlcCloses.map((_dlcClose) => (0, Utils_1.checkTypes)({ _dlcClose }).dlcClose);
1197
- const network = await this.getConnectedNetwork();
1198
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1199
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1200
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1201
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1202
- m: 2,
1203
- pubkeys: fundingPubKeys,
1204
- network,
1205
- });
1206
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1207
- redeem: p2ms,
1208
- network,
1209
- });
1210
- const pubkey = isOfferer ? dlcAccept.fundingPubKey : dlcOffer.fundingPubKey;
1211
- const sigsValidity = [];
1212
- for (let i = 0; i < rawCloseTxs.length; i++) {
1213
- const rawTx = rawCloseTxs[i];
1214
- const dlcClose = dlcCloses[i];
1215
- const verifySignatureRequest = {
1216
- tx: rawTx,
1217
- txin: {
1218
- txid: dlcTxs.fundTx.txId.serialize().reverse().toString('hex'),
1219
- vout: dlcTxs.fundTxVout,
1220
- signature: dlcClose.closeSignature.toString('hex'),
1221
- pubkey: pubkey.toString('hex'),
1222
- redeemScript: paymentVariant.redeem.output.toString('hex'),
1223
- hashType: 'p2wsh',
1224
- sighashType: 'all',
1225
- sighashAnyoneCanPay: false,
1226
- amount: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1227
- },
1228
- };
1229
- sigsValidity.push((async () => {
1230
- const response = await this.getMethod('VerifySignature')(verifySignatureRequest);
1231
- return response.success;
1232
- })());
1233
- }
1234
- const areSigsValid = (await Promise.all(sigsValidity)).every((b) => b);
1235
- return areSigsValid;
1236
- }
1237
- /**
1238
- * Check whether wallet is offerer of DlcOffer or DlcAccept
1239
- * @param dlcOffer Dlc Offer Message
1240
- * @param dlcAccept Dlc Accept Message
1241
- * @returns {Promise<boolean>}
1242
- */
1243
- async isOfferer(_dlcOffer, _dlcAccept) {
1244
- const { dlcOffer, dlcAccept } = (0, Utils_1.checkTypes)({
1245
- _dlcOffer,
1246
- _dlcAccept,
1247
- });
1248
- const network = await this.getConnectedNetwork();
1249
- const offerFundingSPK = bitcoin_1.Script.p2wpkhLock((0, crypto_1.hash160)(dlcOffer.fundingPubKey))
1250
- .serialize()
1251
- .slice(1);
1252
- const acceptFundingSPK = bitcoin_1.Script.p2wpkhLock((0, crypto_1.hash160)(dlcAccept.fundingPubKey))
1253
- .serialize()
1254
- .slice(1);
1255
- const offerFundingAddress = bitcoinjs_lib_1.address.fromOutputScript(offerFundingSPK, network);
1256
- const acceptFundingAddress = bitcoinjs_lib_1.address.fromOutputScript(acceptFundingSPK, network);
1257
- let walletAddress = await this.client.wallet.findAddress([
1258
- offerFundingAddress,
1259
- ]);
1260
- if (walletAddress)
1261
- return true;
1262
- walletAddress = await this.client.wallet.findAddress([
1263
- acceptFundingAddress,
1264
- ]);
1265
- if (walletAddress)
1266
- return false;
1267
- throw Error('Wallet Address not found for DlcOffer or DlcAccept');
1268
- }
1269
- /**
1270
- * Create DLC Offer Message
1271
- * @param contractInfo ContractInfo TLV (V0 or V1)
1272
- * @param offerCollateralSatoshis Amount DLC Initiator is putting into the contract
1273
- * @param feeRatePerVb Fee rate in satoshi per virtual byte that both sides use to compute fees in funding tx
1274
- * @param cetLocktime The nLockTime to be put on CETs
1275
- * @param refundLocktime The nLockTime to be put on the refund transaction
1276
- * @returns {Promise<DlcOffer>}
1277
- */
1278
- async createDlcOffer(contractInfo, offerCollateralSatoshis, feeRatePerVb, cetLocktime, refundLocktime, fixedInputs) {
1279
- contractInfo.validate();
1280
- const network = await this.getConnectedNetwork();
1281
- const dlcOffer = new messaging_1.DlcOfferV0();
1282
- const { fundingPubKey, payoutSPK, payoutSerialId, fundingInputs: _fundingInputs, changeSPK, changeSerialId, } = await this.Initialize(offerCollateralSatoshis, feeRatePerVb, fixedInputs);
1283
- _fundingInputs.forEach((input) => (0, assert_1.default)(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
1284
- const fundingInputs = _fundingInputs.map((input) => input);
1285
- fundingInputs.sort((a, b) => Number(a.inputSerialId) - Number(b.inputSerialId));
1286
- const fundOutputSerialId = (0, Utils_1.generateSerialId)();
1287
- (0, assert_1.default)(changeSerialId !== fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
1288
- dlcOffer.contractFlags = Buffer.from('00', 'hex');
1289
- dlcOffer.chainHash = (0, bitcoin_networks_1.chainHashFromNetwork)(network);
1290
- dlcOffer.contractInfo = contractInfo;
1291
- dlcOffer.fundingPubKey = fundingPubKey;
1292
- dlcOffer.payoutSPK = payoutSPK;
1293
- dlcOffer.payoutSerialId = payoutSerialId;
1294
- dlcOffer.offerCollateralSatoshis = offerCollateralSatoshis;
1295
- dlcOffer.fundingInputs = fundingInputs;
1296
- dlcOffer.changeSPK = changeSPK;
1297
- dlcOffer.changeSerialId = changeSerialId;
1298
- dlcOffer.fundOutputSerialId = dlcOffer.fundOutputSerialId = fundOutputSerialId;
1299
- dlcOffer.feeRatePerVb = feeRatePerVb;
1300
- dlcOffer.cetLocktime = cetLocktime;
1301
- dlcOffer.refundLocktime = refundLocktime;
1302
- (0, assert_1.default)((() => {
1303
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, null, null, null, dlcOffer.feeRatePerVb);
1304
- const funding = fundingInputs.reduce((total, input) => {
1305
- return total + input.prevTx.outputs[input.prevTxVout].value.sats;
1306
- }, BigInt(0));
1307
- return funding >= offerCollateralSatoshis + finalizer.offerFees;
1308
- })(), 'fundingInputs for dlcOffer must be greater than offerCollateralSatoshis plus offerFees');
1309
- dlcOffer.validate();
1310
- return dlcOffer;
1311
- }
1312
- async batchCreateDlcOffer(contractInfos, offerCollaterals, feeRatePerVb, cetLocktime, refundLocktimes, fixedInputs) {
1313
- if (contractInfos.length !== offerCollaterals.length ||
1314
- contractInfos.length !== refundLocktimes.length) {
1315
- throw new Error('The number of contractInfos, offerCollateralSatoshis, and refundLocktimes must be the same');
1316
- }
1317
- const dlcOffers = [];
1318
- for (let i = 0; i < contractInfos.length; i++) {
1319
- contractInfos[i].validate();
1320
- }
1321
- const network = await this.getConnectedNetwork();
1322
- const { fundingInputs: _fundingInputs, changeSPK, changeSerialId, initializeResponses, } = await this.BatchInitialize(offerCollaterals, feeRatePerVb, fixedInputs);
1323
- _fundingInputs.forEach((input) => (0, assert_1.default)(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
1324
- const fundingInputs = _fundingInputs.map((input) => input);
1325
- fundingInputs.sort((a, b) => Number(a.inputSerialId) - Number(b.inputSerialId));
1326
- const fundOutputsSerialIds = (0, Utils_1.generateSerialIds)(contractInfos.length);
1327
- for (let i = 0; i < contractInfos.length; i++) {
1328
- const contractInfo = contractInfos[i];
1329
- const offerCollateralSatoshis = offerCollaterals[i];
1330
- const fundOutputSerialId = fundOutputsSerialIds[i];
1331
- const { fundingPubKey, payoutSPK, payoutSerialId } = initializeResponses[i];
1332
- const refundLocktime = refundLocktimes[i];
1333
- const dlcOffer = new messaging_1.DlcOfferV0();
1334
- dlcOffer.contractFlags = Buffer.from('00', 'hex');
1335
- dlcOffer.chainHash = (0, bitcoin_networks_1.chainHashFromNetwork)(network);
1336
- dlcOffer.contractInfo = contractInfo;
1337
- dlcOffer.fundingPubKey = fundingPubKey;
1338
- dlcOffer.payoutSPK = payoutSPK;
1339
- dlcOffer.payoutSerialId = payoutSerialId;
1340
- dlcOffer.offerCollateralSatoshis = offerCollateralSatoshis;
1341
- dlcOffer.fundingInputs = fundingInputs;
1342
- dlcOffer.changeSPK = changeSPK;
1343
- dlcOffer.changeSerialId = changeSerialId;
1344
- dlcOffer.fundOutputSerialId = fundOutputSerialId;
1345
- dlcOffer.feeRatePerVb = feeRatePerVb;
1346
- dlcOffer.cetLocktime = cetLocktime;
1347
- dlcOffer.refundLocktime = refundLocktime;
1348
- (0, assert_1.default)((() => {
1349
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, null, null, null, dlcOffer.feeRatePerVb);
1350
- const funding = fundingInputs.reduce((total, input) => {
1351
- return total + input.prevTx.outputs[input.prevTxVout].value.sats;
1352
- }, BigInt(0));
1353
- return funding >= offerCollateralSatoshis + finalizer.offerFees;
1354
- })(), 'fundingInputs for dlcOffer must be greater than offerCollateralSatoshis plus offerFees');
1355
- dlcOffer.validate();
1356
- dlcOffers.push(dlcOffer);
1357
- }
1358
- return dlcOffers;
1359
- }
1360
- /**
1361
- * Accept DLC Offer
1362
- * @param _dlcOffer Dlc Offer Message
1363
- * @param fixedInputs Optional inputs to use for Funding Inputs
1364
- * @returns {Promise<AcceptDlcOfferResponse}
1365
- */
1366
- async acceptDlcOffer(_dlcOffer, fixedInputs) {
1367
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
1368
- dlcOffer.validate();
1369
- const acceptCollateralSatoshis = dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis;
1370
- (0, assert_1.default)(acceptCollateralSatoshis ===
1371
- dlcOffer.contractInfo.totalCollateral -
1372
- dlcOffer.offerCollateralSatoshis, 'acceptCollaterialSatoshis should equal totalCollateral - offerCollateralSatoshis');
1373
- const { fundingPubKey, payoutSPK, payoutSerialId, fundingInputs: _fundingInputs, changeSPK, changeSerialId, } = await this.Initialize(acceptCollateralSatoshis, dlcOffer.feeRatePerVb, fixedInputs);
1374
- (0, assert_1.default)(Buffer.compare(dlcOffer.fundingPubKey, fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1375
- _fundingInputs.forEach((input) => (0, assert_1.default)(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
1376
- const fundingInputs = _fundingInputs.map((input) => input);
1377
- fundingInputs.sort((a, b) => Number(a.inputSerialId) - Number(b.inputSerialId));
1378
- const dlcAccept = new messaging_1.DlcAcceptV0();
1379
- dlcAccept.tempContractId = (0, crypto_1.sha256)(dlcOffer.serialize());
1380
- dlcAccept.acceptCollateralSatoshis = acceptCollateralSatoshis;
1381
- dlcAccept.fundingPubKey = fundingPubKey;
1382
- dlcAccept.payoutSPK = payoutSPK;
1383
- dlcAccept.payoutSerialId = dlcAccept.payoutSerialId = payoutSerialId;
1384
- dlcAccept.fundingInputs = fundingInputs;
1385
- dlcAccept.changeSPK = changeSPK;
1386
- dlcAccept.changeSerialId = dlcAccept.changeSerialId = changeSerialId;
1387
- (0, assert_1.default)(dlcAccept.changeSerialId !== dlcOffer.fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
1388
- (0, assert_1.default)(dlcOffer.payoutSerialId !== dlcAccept.payoutSerialId, 'offer.payoutSerialId cannot equal accept.payoutSerialId');
1389
- (0, assert_1.default)((() => {
1390
- const ids = [
1391
- dlcOffer.changeSerialId,
1392
- dlcAccept.changeSerialId,
1393
- dlcOffer.fundOutputSerialId,
1394
- ];
1395
- return new Set(ids).size === ids.length;
1396
- })(), 'offer.changeSerialID, accept.changeSerialId and fundOutputSerialId must be unique');
1397
- dlcAccept.validate();
1398
- (0, assert_1.default)((() => {
1399
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, dlcAccept.fundingInputs, dlcAccept.payoutSPK, dlcAccept.changeSPK, dlcOffer.feeRatePerVb);
1400
- const funding = fundingInputs.reduce((total, input) => {
1401
- return total + input.prevTx.outputs[input.prevTxVout].value.sats;
1402
- }, BigInt(0));
1403
- return funding >= acceptCollateralSatoshis + finalizer.acceptFees;
1404
- })(), 'fundingInputs for dlcAccept must be greater than acceptCollateralSatoshis plus acceptFees');
1405
- const { dlcTransactions, messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
1406
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, false);
1407
- (0, assert_1.default)(dlcTransactions.type === messaging_1.MessageType.DlcTransactionsV0, 'DlcTransactions must be V0');
1408
- const _dlcTransactions = dlcTransactions;
1409
- const contractId = (0, crypto_1.xor)(_dlcTransactions.fundTx.txId.serialize(), dlcAccept.tempContractId);
1410
- _dlcTransactions.contractId = contractId;
1411
- dlcAccept.cetSignatures = cetSignatures;
1412
- dlcAccept.refundSignature = refundSignature;
1413
- dlcAccept.negotiationFields = new messaging_1.NegotiationFieldsV0();
1414
- return { dlcAccept, dlcTransactions: _dlcTransactions };
1415
- }
1416
- async batchAcceptDlcOffer(_dlcOffers, fixedInputs) {
1417
- const dlcOffers = _dlcOffers.map((_dlcOffer) => {
1418
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
1419
- dlcOffer.validate();
1420
- return dlcOffer;
1421
- });
1422
- const acceptCollaterals = dlcOffers.map((dlcOffer) => dlcOffer.contractInfo.totalCollateral -
1423
- dlcOffer.offerCollateralSatoshis);
1424
- const { fundingInputs: _fundingInputs, changeSPK, changeSerialId, initializeResponses, } = await this.BatchInitialize(acceptCollaterals, dlcOffers[0].feeRatePerVb, fixedInputs);
1425
- // Check that none of the funding pubkeys are the same between the
1426
- // dlcOffers and the dlcAccepts (from initializeResponses)
1427
- dlcOffers.forEach((dlcOffer) => {
1428
- initializeResponses.forEach((initializeResponse) => {
1429
- (0, assert_1.default)(Buffer.compare(dlcOffer.fundingPubKey, initializeResponse.fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1430
- });
1431
- });
1432
- _fundingInputs.forEach((input) => (0, assert_1.default)(input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0'));
1433
- const fundingInputs = _fundingInputs.map((input) => input);
1434
- fundingInputs.sort((a, b) => Number(a.inputSerialId) - Number(b.inputSerialId));
1435
- const dlcAccepts = [];
1436
- initializeResponses.forEach((initializeResponse, i) => {
1437
- const dlcOffer = dlcOffers[i];
1438
- const dlcAccept = new messaging_1.DlcAcceptV0();
1439
- const { fundingPubKey, payoutSPK, payoutSerialId } = initializeResponse;
1440
- dlcAccept.tempContractId = (0, crypto_1.sha256)(dlcOffers[i].serialize());
1441
- dlcAccept.acceptCollateralSatoshis = acceptCollaterals[i];
1442
- dlcAccept.fundingPubKey = fundingPubKey;
1443
- dlcAccept.payoutSPK = payoutSPK;
1444
- dlcAccept.payoutSerialId = payoutSerialId;
1445
- dlcAccept.fundingInputs = fundingInputs;
1446
- dlcAccept.changeSPK = changeSPK;
1447
- dlcAccept.changeSerialId = changeSerialId;
1448
- (0, assert_1.default)(dlcAccept.changeSerialId !== dlcOffer.fundOutputSerialId, 'changeSerialId cannot equal the fundOutputSerialId');
1449
- (0, assert_1.default)(dlcOffer.payoutSerialId !== dlcAccept.payoutSerialId, 'offer.payoutSerialId cannot equal accept.payoutSerialId');
1450
- (0, assert_1.default)((() => {
1451
- const ids = [
1452
- dlcOffer.changeSerialId,
1453
- dlcAccept.changeSerialId,
1454
- dlcOffer.fundOutputSerialId,
1455
- ];
1456
- return new Set(ids).size === ids.length;
1457
- })(), 'offer.changeSerialID, accept.changeSerialId and fundOutputSerialId must be unique');
1458
- dlcAccept.validate();
1459
- (0, assert_1.default)((() => {
1460
- const finalizer = new core_1.DualFundingTxFinalizer(dlcOffer.fundingInputs, dlcOffer.payoutSPK, dlcOffer.changeSPK, dlcAccept.fundingInputs, dlcAccept.payoutSPK, dlcAccept.changeSPK, dlcOffer.feeRatePerVb);
1461
- const funding = fundingInputs.reduce((total, input) => {
1462
- return total + input.prevTx.outputs[input.prevTxVout].value.sats;
1463
- }, BigInt(0));
1464
- return funding >= acceptCollaterals[i] + finalizer.acceptFees;
1465
- })(), 'fundingInputs for dlcAccept must be greater than acceptCollateralSatoshis plus acceptFees');
1466
- dlcAccepts.push(dlcAccept);
1467
- });
1468
- const { dlcTransactionsList, nestedMessagesList, } = await this.createBatchDlcTxs(dlcOffers, dlcAccepts);
1469
- for (let i = 0; i < dlcAccepts.length; i++) {
1470
- const dlcOffer = dlcOffers[i];
1471
- const dlcAccept = dlcAccepts[i];
1472
- const dlcTransactions = dlcTransactionsList[i];
1473
- const messagesList = nestedMessagesList[i];
1474
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, false);
1475
- (0, assert_1.default)(dlcTransactions.type === messaging_1.MessageType.DlcTransactionsV0, 'DlcTransactions must be V0');
1476
- const _dlcTransactions = dlcTransactions;
1477
- const contractId = (0, crypto_1.xor)(_dlcTransactions.fundTx.txId.serialize(), dlcAccept.tempContractId);
1478
- _dlcTransactions.contractId = contractId;
1479
- dlcAccepts[i].cetSignatures = cetSignatures;
1480
- dlcAccepts[i].refundSignature = refundSignature;
1481
- dlcAccepts[i].negotiationFields = new messaging_1.NegotiationFieldsV0();
1482
- }
1483
- return { dlcAccepts, dlcTransactionsList };
1484
- }
1485
- /**
1486
- * Sign Dlc Accept Message
1487
- * @param _dlcOffer Dlc Offer Message
1488
- * @param _dlcAccept Dlc Accept Message
1489
- * @returns {Promise<SignDlcAcceptResponse}
1490
- */
1491
- async signDlcAccept(_dlcOffer, _dlcAccept) {
1492
- const { dlcOffer, dlcAccept } = (0, Utils_1.checkTypes)({
1493
- _dlcOffer,
1494
- _dlcAccept,
1495
- });
1496
- dlcOffer.validate();
1497
- dlcAccept.validate();
1498
- (0, assert_1.default)(Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) !== 0, 'DlcOffer and DlcAccept FundingPubKey cannot be the same');
1499
- const dlcSign = new messaging_1.DlcSignV0();
1500
- const { dlcTransactions, messagesList } = await this.createDlcTxs(dlcOffer, dlcAccept);
1501
- await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTransactions, messagesList, true);
1502
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, true);
1503
- const fundingSignatures = await this.CreateFundingSigs(dlcOffer, dlcAccept, dlcTransactions, true);
1504
- const dlcTxs = dlcTransactions;
1505
- const contractId = (0, crypto_1.xor)(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId);
1506
- (0, assert_1.default)(Buffer.compare(contractId, (0, crypto_1.xor)(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId)) === 0, 'contractId must be the xor of funding txid, fundingOutputIndex and the tempContractId');
1507
- dlcTxs.contractId = contractId;
1508
- dlcSign.contractId = contractId;
1509
- dlcSign.cetSignatures = cetSignatures;
1510
- dlcSign.refundSignature = refundSignature;
1511
- dlcSign.fundingSignatures = fundingSignatures;
1512
- return { dlcSign, dlcTransactions: dlcTxs };
1513
- }
1514
- async batchSignDlcAccept(_dlcOffers, _dlcAccepts) {
1515
- const dlcOffers = _dlcOffers.map((_dlcOffer) => {
1516
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
1517
- dlcOffer.validate();
1518
- return dlcOffer;
1519
- });
1520
- const dlcAccepts = _dlcAccepts.map((_dlcAccept) => {
1521
- const { dlcAccept } = (0, Utils_1.checkTypes)({ _dlcAccept });
1522
- dlcAccept.validate();
1523
- return dlcAccept;
1524
- });
1525
- const { dlcTransactionsList, nestedMessagesList, } = await this.createBatchDlcTxs(dlcOffers, dlcAccepts);
1526
- const dlcSigns = [];
1527
- const fundingSignatures = await this.CreateFundingSigs(dlcOffers[0], dlcAccepts[0], dlcTransactionsList[0], true);
1528
- for (let i = 0; i < dlcAccepts.length; i++) {
1529
- const dlcOffer = dlcOffers[i];
1530
- const dlcAccept = dlcAccepts[i];
1531
- const dlcTransactions = dlcTransactionsList[i];
1532
- const messagesList = nestedMessagesList[i];
1533
- const dlcSign = new messaging_1.DlcSignV0();
1534
- await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTransactions, messagesList, true);
1535
- const { cetSignatures, refundSignature, } = await this.CreateCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcTransactions, messagesList, true);
1536
- const dlcTxs = dlcTransactions;
1537
- const contractId = (0, crypto_1.xor)(dlcTxs.fundTx.txId.serialize(), dlcAccept.tempContractId);
1538
- dlcTxs.contractId = contractId;
1539
- dlcSign.contractId = contractId;
1540
- dlcSign.cetSignatures = cetSignatures;
1541
- dlcSign.refundSignature = refundSignature;
1542
- dlcSign.fundingSignatures = fundingSignatures;
1543
- dlcSigns.push(dlcSign);
1544
- }
1545
- return { dlcSigns, dlcTransactionsList };
1546
- }
1547
- /**
1548
- * Finalize Dlc Sign
1549
- * @param _dlcOffer Dlc Offer Message
1550
- * @param _dlcAccept Dlc Accept Message
1551
- * @param _dlcSign Dlc Sign Message
1552
- * @param _dlcTxs Dlc Transactions Message
1553
- * @returns {Promise<Tx>}
1554
- */
1555
- async finalizeDlcSign(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1556
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
1557
- _dlcOffer,
1558
- _dlcAccept,
1559
- _dlcSign,
1560
- _dlcTxs,
1561
- });
1562
- let messagesList = [];
1563
- if (dlcOffer.contractInfo.type === messaging_1.MessageType.ContractInfoV0 &&
1564
- dlcOffer.contractInfo.contractDescriptor.type ===
1565
- messaging_1.MessageType.ContractDescriptorV0) {
1566
- for (const outcome of dlcOffer.contractInfo
1567
- .contractDescriptor.outcomes) {
1568
- messagesList.push({ messages: [outcome.outcome.toString('hex')] });
1569
- }
1570
- }
1571
- else {
1572
- const payoutResponses = this.GetPayouts(dlcOffer);
1573
- const { messagesList: oracleEventMessagesList } = this.FlattenPayouts(payoutResponses);
1574
- messagesList = oracleEventMessagesList;
1575
- }
1576
- await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTxs, messagesList, false);
1577
- await this.VerifyFundingSigs(dlcOffer, dlcAccept, dlcSign, dlcTxs, false);
1578
- const fundingSignatures = await this.CreateFundingSigs(dlcOffer, dlcAccept, dlcTxs, false);
1579
- const fundTx = await this.CreateFundingTx(dlcOffer, dlcAccept, dlcSign, dlcTxs, fundingSignatures);
1580
- return fundTx;
1581
- }
1582
- async batchFinalizeDlcSign(_dlcOffers, _dlcAccepts, _dlcSigns, _dlcTxsList) {
1583
- const dlcOffers = _dlcOffers.map((_dlcOffer) => {
1584
- const { dlcOffer } = (0, Utils_1.checkTypes)({ _dlcOffer });
1585
- dlcOffer.validate();
1586
- return dlcOffer;
1587
- });
1588
- const dlcAccepts = _dlcAccepts.map((_dlcAccept) => {
1589
- const { dlcAccept } = (0, Utils_1.checkTypes)({ _dlcAccept });
1590
- dlcAccept.validate();
1591
- return dlcAccept;
1592
- });
1593
- const dlcSigns = _dlcSigns.map((_dlcSign) => {
1594
- const { dlcSign } = (0, Utils_1.checkTypes)({ _dlcSign });
1595
- return dlcSign;
1596
- });
1597
- const dlcTxsList = _dlcTxsList.map((_dlcTxs) => {
1598
- const { dlcTxs } = (0, Utils_1.checkTypes)({ _dlcTxs });
1599
- return dlcTxs;
1600
- });
1601
- await this.VerifyFundingSigs(dlcOffers[0], dlcAccepts[0], dlcSigns[0], dlcTxsList[0], false);
1602
- for (let i = 0; i < dlcOffers.length; i++) {
1603
- const dlcOffer = dlcOffers[i];
1604
- const dlcAccept = dlcAccepts[i];
1605
- const dlcSign = dlcSigns[i];
1606
- const dlcTxs = dlcTxsList[i];
1607
- const payoutResponses = this.GetPayouts(dlcOffer);
1608
- const { messagesList } = this.FlattenPayouts(payoutResponses);
1609
- await this.VerifyCetAdaptorAndRefundSigs(dlcOffer, dlcAccept, dlcSign, dlcTxs, messagesList, false);
1610
- }
1611
- const fundingSignatures = await this.CreateFundingSigs(dlcOffers[0], dlcAccepts[0], dlcTxsList[0], false);
1612
- const fundTx = await this.CreateFundingTx(dlcOffers[0], dlcAccepts[0], dlcSigns[0], dlcTxsList[0], fundingSignatures);
1613
- return fundTx;
1614
- }
1615
- /**
1616
- * Execute DLC
1617
- * @param _dlcOffer Dlc Offer Message
1618
- * @param _dlcAccept Dlc Accept Message
1619
- * @param _dlcSign Dlc Sign Message
1620
- * @param _dlcTxs Dlc Transactions Message
1621
- * @param oracleAttestation Oracle Attestations TLV (V0)
1622
- * @param isOfferer Whether party is Dlc Offerer
1623
- * @returns {Promise<Tx>}
1624
- */
1625
- async execute(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs, oracleAttestation, isOfferer) {
1626
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
1627
- _dlcOffer,
1628
- _dlcAccept,
1629
- _dlcSign,
1630
- _dlcTxs,
1631
- });
1632
- if (isOfferer === undefined)
1633
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1634
- this.ValidateEvent(dlcOffer, oracleAttestation);
1635
- return this.FindAndSignCet(dlcOffer, dlcAccept, dlcSign, dlcTxs, oracleAttestation, isOfferer);
1636
- }
1637
- /**
1638
- * Refund DLC
1639
- * @param _dlcOffer Dlc Offer Message
1640
- * @param _dlcAccept Dlc Accept Message
1641
- * @param _dlcSign Dlc Sign Message
1642
- * @param _dlcTxs Dlc Transactions message
1643
- * @returns {Promise<Tx>}
1644
- */
1645
- async refund(_dlcOffer, _dlcAccept, _dlcSign, _dlcTxs) {
1646
- const { dlcOffer, dlcAccept, dlcSign, dlcTxs } = (0, Utils_1.checkTypes)({
1647
- _dlcOffer,
1648
- _dlcAccept,
1649
- _dlcSign,
1650
- _dlcTxs,
1651
- });
1652
- const signatures = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1653
- ? [
1654
- dlcSign.refundSignature.toString('hex'),
1655
- dlcAccept.refundSignature.toString('hex'),
1656
- ]
1657
- : [
1658
- dlcAccept.refundSignature.toString('hex'),
1659
- dlcSign.refundSignature.toString('hex'),
1660
- ];
1661
- const addSigsToRefundTxRequest = {
1662
- refundTxHex: dlcTxs.refundTx.serialize().toString('hex'),
1663
- signatures,
1664
- fundTxId: dlcTxs.fundTx.txId.toString(),
1665
- fundVout: dlcTxs.fundTxVout,
1666
- localFundPubkey: dlcOffer.fundingPubKey.toString('hex'),
1667
- remoteFundPubkey: dlcAccept.fundingPubKey.toString('hex'),
1668
- };
1669
- const refundHex = (await this.AddSignaturesToRefundTx(addSigsToRefundTxRequest)).hex;
1670
- return bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(refundHex));
1671
- }
1672
- /**
1673
- * Goal of createDlcClose is for alice (the initiator) to
1674
- * 1. take dlcoffer, accept, and sign messages. Create a dlcClose message.
1675
- * 2. Build a close tx, sign.
1676
- * 3. return dlcClose message (no psbt)
1677
- */
1678
- /**
1679
- * Generate DlcClose messagetype for closing DLC with Mutual Consent
1680
- * @param _dlcOffer DlcOffer TLV (V0)
1681
- * @param _dlcAccept DlcAccept TLV (V0)
1682
- * @param _dlcTxs DlcTransactions TLV (V0)
1683
- * @param initiatorPayoutSatoshis Amount initiator expects as a payout
1684
- * @param isOfferer Whether offerer or not
1685
- * @param _inputs Optionally specified closing inputs
1686
- * @returns {Promise<DlcClose>}
1687
- */
1688
- async createDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayoutSatoshis, isOfferer, _inputs) {
1689
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1690
- _dlcOffer,
1691
- _dlcAccept,
1692
- _dlcTxs,
1693
- });
1694
- if (isOfferer === undefined)
1695
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1696
- const network = await this.getConnectedNetwork();
1697
- const psbt = new bitcoinjs_lib_1.Psbt({ network });
1698
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1699
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1700
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1701
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1702
- m: 2,
1703
- pubkeys: fundingPubKeys,
1704
- network,
1705
- });
1706
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1707
- redeem: p2ms,
1708
- network,
1709
- });
1710
- // Initiate and build PSBT
1711
- let inputs = _inputs;
1712
- if (!_inputs) {
1713
- const tempInputs = await this.GetInputsForAmount([BigInt(20000)], dlcOffer.feeRatePerVb, _inputs);
1714
- _inputs = tempInputs;
1715
- }
1716
- inputs = _inputs.map((input) => {
1717
- return {
1718
- ...input,
1719
- inputSerialId: input.inputSerialId || (0, Utils_1.generateSerialId)(),
1720
- toUtxo: input.toUtxo,
1721
- };
1722
- });
1723
- const pubkeys = await Promise.all(inputs.map(async (input) => {
1724
- const address = await this.getMethod('getWalletAddress')(input.address);
1725
- return Buffer.from(address.publicKey, 'hex');
1726
- }));
1727
- const fundingInputSerialId = (0, Utils_1.generateSerialId)();
1728
- // Make temporary array to hold all inputs and then sort them
1729
- // this method can be improved later
1730
- const psbtInputs = [];
1731
- psbtInputs.push({
1732
- hash: dlcTxs.fundTx.txId.serialize(),
1733
- index: dlcTxs.fundTxVout,
1734
- sequence: 0,
1735
- witnessUtxo: {
1736
- script: paymentVariant.output,
1737
- value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1738
- },
1739
- witnessScript: paymentVariant.redeem.output,
1740
- inputSerialId: fundingInputSerialId,
1741
- derivationPath: null,
1742
- });
1743
- // add all dlc close inputs
1744
- inputs.forEach((input, i) => {
1745
- const paymentVariant = bitcoinjs_lib_1.payments.p2wpkh({ pubkey: pubkeys[i], network });
1746
- psbtInputs.push({
1747
- hash: input.txid,
1748
- index: input.vout,
1749
- sequence: 0,
1750
- witnessUtxo: {
1751
- script: paymentVariant.output,
1752
- value: input.value,
1753
- },
1754
- inputSerialId: input.inputSerialId,
1755
- derivationPath: input.derivationPath,
1756
- });
1757
- });
1758
- // sort all inputs in ascending order by serial ID
1759
- // The only reason we are doing this is for privacy. If the fundingInput is
1760
- // always first, it is very obvious. Hence, a serialId is randomly generated
1761
- // and the inputs are sorted by that instead.
1762
- const sortedPsbtInputs = psbtInputs.sort((a, b) => Number(a.inputSerialId - b.inputSerialId));
1763
- // Get index of fundingInput
1764
- const fundingInputIndex = sortedPsbtInputs.findIndex((input) => input.inputSerialId === fundingInputSerialId);
1765
- // add to psbt
1766
- sortedPsbtInputs.forEach((input, i) => psbt.addInput(input));
1767
- const fundingInputs = await Promise.all(inputs.map(async (input) => {
1768
- return this.inputToFundingInput(input);
1769
- }));
1770
- const finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1771
- const closeInputAmount = BigInt(inputs.reduce((acc, val) => acc + val.value, 0));
1772
- const offerPayoutValue = isOfferer
1773
- ? closeInputAmount +
1774
- initiatorPayoutSatoshis -
1775
- finalizer.offerInitiatorFees
1776
- : dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis;
1777
- const acceptPayoutValue = isOfferer
1778
- ? dlcOffer.contractInfo.totalCollateral - initiatorPayoutSatoshis
1779
- : closeInputAmount +
1780
- initiatorPayoutSatoshis -
1781
- finalizer.offerInitiatorFees;
1782
- const offerFirst = dlcOffer.payoutSerialId < dlcAccept.payoutSerialId;
1783
- psbt.addOutput({
1784
- value: Number(offerFirst ? offerPayoutValue : acceptPayoutValue),
1785
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network),
1786
- });
1787
- psbt.addOutput({
1788
- value: Number(offerFirst ? acceptPayoutValue : offerPayoutValue),
1789
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network),
1790
- });
1791
- // Generate keypair to sign inputs
1792
- const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, isOfferer);
1793
- // Sign dlc fundinginput
1794
- psbt.signInput(fundingInputIndex, fundPrivateKeyPair);
1795
- // Sign dlcclose inputs
1796
- await Promise.all(sortedPsbtInputs.map(async (input, i) => {
1797
- if (i === fundingInputIndex)
1798
- return;
1799
- // derive keypair
1800
- const keyPair = await this.getMethod('keyPair')(input.derivationPath);
1801
- psbt.signInput(i, keyPair);
1802
- }));
1803
- // Validate signatures
1804
- psbt.validateSignaturesOfAllInputs();
1805
- // Extract close signature from psbt and decode it to only extract r and s values
1806
- const closeSignature = await bitcoinjs_lib_1.script.signature.decode(psbt.data.inputs[fundingInputIndex].partialSig[0].signature).signature;
1807
- // Extract funding signatures from psbt
1808
- const inputSigs = psbt.data.inputs
1809
- .filter((input) => input !== fundingInputIndex)
1810
- .map((input) => input.partialSig[0]);
1811
- // create fundingSignatures
1812
- const witnessElements = [];
1813
- for (let i = 0; i < inputSigs.length; i++) {
1814
- const sigWitness = new messaging_1.ScriptWitnessV0();
1815
- sigWitness.witness = inputSigs[i].signature;
1816
- const pubKeyWitness = new messaging_1.ScriptWitnessV0();
1817
- pubKeyWitness.witness = inputSigs[i].pubkey;
1818
- witnessElements.push([sigWitness, pubKeyWitness]);
1819
- }
1820
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
1821
- fundingSignatures.witnessElements = witnessElements;
1822
- // Create DlcClose
1823
- const dlcClose = new messaging_1.DlcCloseV0();
1824
- dlcClose.contractId = dlcTxs.contractId;
1825
- dlcClose.offerPayoutSatoshis = BigInt(psbt.txOutputs[offerFirst ? 0 : 1].value); // You give collateral back to users
1826
- dlcClose.acceptPayoutSatoshis = BigInt(psbt.txOutputs[offerFirst ? 1 : 0].value); // give collateral back to users
1827
- dlcClose.fundInputSerialId = fundingInputSerialId; // randomly generated serial id
1828
- dlcClose.closeSignature = closeSignature;
1829
- dlcClose.fundingSignatures = fundingSignatures;
1830
- dlcClose.fundingInputs = fundingInputs;
1831
- dlcClose.validate();
1832
- return dlcClose;
1833
- }
1834
- /**
1835
- * Generate multiple DlcClose messagetypes for closing DLC with Mutual Consent
1836
- * @param _dlcOffer DlcOffer TLV (V0)
1837
- * @param _dlcAccept DlcAccept TLV (V0)
1838
- * @param _dlcTxs DlcTransactions TLV (V0)
1839
- * @param initiatorPayouts Array of amounts initiator expects as payouts
1840
- * @param isOfferer Whether offerer or not
1841
- * @param _inputs Optionally specified closing inputs
1842
- * @returns {Promise<DlcClose[]>}
1843
- */
1844
- async createBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, initiatorPayouts, isOfferer, _inputs) {
1845
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1846
- _dlcOffer,
1847
- _dlcAccept,
1848
- _dlcTxs,
1849
- });
1850
- if (isOfferer === undefined)
1851
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1852
- if (_inputs && _inputs.length > 0)
1853
- throw Error('funding inputs not supported on BatchDlcClose'); // TODO support multiple funding inputs
1854
- const fundingInputSerialId = (0, Utils_1.generateSerialId)();
1855
- const fundingInputs = []; // TODO: support multiple funding inputs
1856
- const finalizer = new core_1.DualClosingTxFinalizer(fundingInputs, dlcOffer.payoutSPK, dlcAccept.payoutSPK, dlcOffer.feeRatePerVb);
1857
- // Generate keypair to sign inputs
1858
- const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, isOfferer);
1859
- const closeInputAmount = BigInt(0); // TODO support multiple funding inputs
1860
- const privKey = Buffer.from(fundPrivateKeyPair.privateKey).toString('hex');
1861
- const rawCloseTxs = await this.CreateCloseRawTxs(dlcOffer, dlcAccept, dlcTxs, closeInputAmount, isOfferer, [], fundingInputs, initiatorPayouts);
1862
- const sigHashes = await this.CreateSignatureHashes(dlcOffer, dlcAccept, dlcTxs, rawCloseTxs);
1863
- const signatures = await this.CalculateEcSignatureHashes(sigHashes, privKey);
1864
- const dlcCloses = [];
1865
- signatures.forEach((sig, i) => {
1866
- const payout = initiatorPayouts[i];
1867
- const payoutMinusOfferFees = finalizer.offerInitiatorFees > payout
1868
- ? BigInt(0)
1869
- : payout - finalizer.offerInitiatorFees;
1870
- const collateralMinusPayout = payout > dlcOffer.contractInfo.totalCollateral
1871
- ? BigInt(0)
1872
- : dlcOffer.contractInfo.totalCollateral - payout;
1873
- const offerPayoutValue = isOfferer
1874
- ? closeInputAmount + payoutMinusOfferFees
1875
- : collateralMinusPayout;
1876
- const acceptPayoutValue = isOfferer
1877
- ? collateralMinusPayout
1878
- : closeInputAmount + payoutMinusOfferFees;
1879
- const fundingSignatures = new messaging_1.FundingSignaturesV0();
1880
- const dlcClose = new messaging_1.DlcCloseV0();
1881
- dlcClose.contractId = dlcTxs.contractId;
1882
- dlcClose.offerPayoutSatoshis = offerPayoutValue;
1883
- dlcClose.acceptPayoutSatoshis = acceptPayoutValue;
1884
- dlcClose.fundInputSerialId = fundingInputSerialId;
1885
- dlcClose.closeSignature = Buffer.from(sig, 'hex');
1886
- dlcClose.fundingSignatures = fundingSignatures;
1887
- dlcClose.validate();
1888
- dlcCloses.push(dlcClose);
1889
- });
1890
- return dlcCloses;
1891
- }
1892
- async verifyBatchDlcCloseUsingMetadata(dlcCloseMetadata, _dlcCloses, isOfferer) {
1893
- const { dlcOffer, dlcAccept, dlcTxs } = dlcCloseMetadata.toDlcMessages();
1894
- await this.verifyBatchDlcClose(dlcOffer, dlcAccept, dlcTxs, _dlcCloses, isOfferer);
1895
- }
1896
- /**
1897
- * Verify multiple DlcClose messagetypes for closing DLC with Mutual Consent
1898
- * @param _dlcOffer DlcOffer TLV (V0)
1899
- * @param _dlcAccept DlcAccept TLV (V0)
1900
- * @param _dlcTxs DlcTransactions TLV (V0)
1901
- * @param _dlcCloses DlcClose[] TLV (V0)
1902
- * @param isOfferer Whether offerer or not
1903
- * @returns {Promise<void>}
1904
- */
1905
- async verifyBatchDlcClose(_dlcOffer, _dlcAccept, _dlcTxs, _dlcCloses, isOfferer) {
1906
- const { dlcOffer, dlcAccept, dlcTxs } = (0, Utils_1.checkTypes)({
1907
- _dlcOffer,
1908
- _dlcAccept,
1909
- _dlcTxs,
1910
- });
1911
- const dlcCloses = _dlcCloses.map((_dlcClose) => (0, Utils_1.checkTypes)({ _dlcClose }).dlcClose);
1912
- if (isOfferer === undefined)
1913
- isOfferer = await this.isOfferer(dlcOffer, dlcAccept);
1914
- (0, assert_1.default)(dlcCloses.every((dlcClose) => dlcClose.fundingInputs.length === 0), 'funding inputs not supported on verify BatchDlcClose'); // TODO support multiple funding inputs
1915
- const closeInputAmount = BigInt(0); // TODO support multiple funding inputs
1916
- const rawCloseTxs = await this.CreateCloseRawTxs(dlcOffer, dlcAccept, dlcTxs, closeInputAmount, isOfferer, dlcCloses);
1917
- const areSigsValid = await this.VerifySignatures(dlcOffer, dlcAccept, dlcTxs, dlcCloses, rawCloseTxs, isOfferer);
1918
- (0, assert_1.default)(areSigsValid, 'Signatures invalid in Verify Batch DlcClose');
1919
- }
1920
- /**
1921
- * Goal of finalize Dlc Close is for bob to
1922
- * 1. take the dlcClose created by alice using createDlcClose,
1923
- * 2. Build a psbt using Alice's dlcClose message
1924
- * 3. Sign psbt with bob's privkey
1925
- * 4. return a tx ready to be broadcast
1926
- */
1927
- /**
1928
- * Finalize Dlc Close
1929
- * @param _dlcOffer Dlc Offer Message
1930
- * @param _dlcAccept Dlc Accept Message
1931
- * @param _dlcClose Dlc Close Message
1932
- * @param _dlcTxs Dlc Transactions Message
1933
- * @returns {Promise<Tx>}
1934
- */
1935
- async finalizeDlcClose(_dlcOffer, _dlcAccept, _dlcClose, _dlcTxs) {
1936
- const { dlcOffer, dlcAccept, dlcClose, dlcTxs } = (0, Utils_1.checkTypes)({
1937
- _dlcOffer,
1938
- _dlcAccept,
1939
- _dlcClose,
1940
- _dlcTxs,
1941
- });
1942
- dlcOffer.validate();
1943
- dlcAccept.validate();
1944
- dlcClose.validate();
1945
- const network = await this.getConnectedNetwork();
1946
- const psbt = new bitcoinjs_lib_1.Psbt({ network });
1947
- const fundingPubKeys = Buffer.compare(dlcOffer.fundingPubKey, dlcAccept.fundingPubKey) === -1
1948
- ? [dlcOffer.fundingPubKey, dlcAccept.fundingPubKey]
1949
- : [dlcAccept.fundingPubKey, dlcOffer.fundingPubKey];
1950
- const p2ms = bitcoinjs_lib_1.payments.p2ms({
1951
- m: 2,
1952
- pubkeys: fundingPubKeys,
1953
- network,
1954
- });
1955
- const paymentVariant = bitcoinjs_lib_1.payments.p2wsh({
1956
- redeem: p2ms,
1957
- network,
1958
- });
1959
- // Make temporary array to hold all inputs and then sort them
1960
- // this method can be improved later
1961
- const psbtInputs = [];
1962
- psbtInputs.push({
1963
- hash: dlcTxs.fundTx.txId.serialize(),
1964
- index: dlcTxs.fundTxVout,
1965
- sequence: 0,
1966
- witnessUtxo: {
1967
- script: paymentVariant.output,
1968
- value: Number(dlcTxs.fundTx.outputs[dlcTxs.fundTxVout].value.sats),
1969
- },
1970
- witnessScript: paymentVariant.redeem.output,
1971
- inputSerialId: dlcClose.fundInputSerialId,
1972
- });
1973
- // add all dlc close inputs
1974
- dlcClose.fundingInputs.forEach((input, i) => {
1975
- psbtInputs.push({
1976
- hash: input.prevTx.txId.serialize(),
1977
- index: input.prevTxVout,
1978
- sequence: 0,
1979
- witnessUtxo: {
1980
- script: input.prevTx.outputs[input.prevTxVout].scriptPubKey
1981
- .serialize()
1982
- .slice(1),
1983
- value: Number(input.prevTx.outputs[input.prevTxVout].value.sats),
1984
- },
1985
- inputSerialId: input.inputSerialId,
1986
- });
1987
- });
1988
- // sort all inputs in ascending order by serial ID
1989
- // The only reason we are doing this is for privacy. If the fundingInput is
1990
- // always first, it is very obvious. Hence, a serialId is randomly generated
1991
- // and the inputs are sorted by that instead.
1992
- const sortedPsbtInputs = psbtInputs.sort((a, b) => Number(a.inputSerialId - b.inputSerialId));
1993
- // Get index of fundingInput
1994
- const fundingInputIndex = sortedPsbtInputs.findIndex((input) => input.inputSerialId === dlcClose.fundInputSerialId);
1995
- const offerFirst = dlcOffer.payoutSerialId < dlcAccept.payoutSerialId;
1996
- psbt.addOutput({
1997
- value: Number(offerFirst
1998
- ? dlcClose.offerPayoutSatoshis
1999
- : dlcClose.acceptPayoutSatoshis),
2000
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcOffer.payoutSPK : dlcAccept.payoutSPK, network),
2001
- });
2002
- psbt.addOutput({
2003
- value: Number(offerFirst
2004
- ? dlcClose.acceptPayoutSatoshis
2005
- : dlcClose.offerPayoutSatoshis),
2006
- address: bitcoinjs_lib_1.address.fromOutputScript(offerFirst ? dlcAccept.payoutSPK : dlcOffer.payoutSPK, network),
2007
- });
2008
- // add to psbt
2009
- sortedPsbtInputs.forEach((input, i) => psbt.addInput(input));
2010
- const offerer = await this.isOfferer(dlcOffer, dlcAccept);
2011
- // Generate keypair to sign inputs
2012
- const fundPrivateKeyPair = await this.GetFundKeyPair(dlcOffer, dlcAccept, offerer);
2013
- // Sign dlc fundinginput
2014
- psbt.signInput(fundingInputIndex, fundPrivateKeyPair);
2015
- const partialSig = [
2016
- {
2017
- pubkey: offerer ? dlcAccept.fundingPubKey : dlcOffer.fundingPubKey,
2018
- signature: await bitcoinjs_lib_1.script.signature.encode(dlcClose.closeSignature, 1), // encode using SIGHASH_ALL
2019
- },
2020
- ];
2021
- psbt.updateInput(fundingInputIndex, { partialSig });
2022
- for (let i = 0; i < psbt.data.inputs.length; ++i) {
2023
- if (i === fundingInputIndex)
2024
- continue;
2025
- if (!psbt.data.inputs[i].partialSig)
2026
- psbt.data.inputs[i].partialSig = [];
2027
- const witnessI = dlcClose.fundingSignatures.witnessElements.findIndex((el) => Buffer.compare(bitcoin_1.Script.p2wpkhLock((0, crypto_1.hash160)(el[1].witness)).serialize().slice(1), psbt.data.inputs[i].witnessUtxo.script) === 0);
2028
- const partialSig = [
2029
- {
2030
- pubkey: dlcClose.fundingSignatures.witnessElements[witnessI][1].witness,
2031
- signature: dlcClose.fundingSignatures.witnessElements[witnessI][0].witness,
2032
- },
2033
- ];
2034
- psbt.updateInput(i, { partialSig });
2035
- }
2036
- psbt.validateSignaturesOfAllInputs();
2037
- psbt.finalizeAllInputs();
2038
- return psbt.extractTransaction().toHex();
2039
- }
2040
- async AddSignatureToFundTransaction(jsonObject) {
2041
- await this.CfdLoaded();
2042
- return this._cfdDlcJs.AddSignatureToFundTransaction(jsonObject);
2043
- }
2044
- async CreateCetAdaptorSignature(jsonObject) {
2045
- await this.CfdLoaded();
2046
- return this._cfdDlcJs.CreateCetAdaptorSignature(jsonObject);
2047
- }
2048
- async CreateCetAdaptorSignatures(jsonObject) {
2049
- await this.CfdLoaded();
2050
- return this._cfdDlcJs.CreateCetAdaptorSignatures(jsonObject);
2051
- }
2052
- async AddSignaturesToRefundTx(jsonObject) {
2053
- await this.CfdLoaded();
2054
- return this._cfdDlcJs.AddSignaturesToRefundTx(jsonObject);
2055
- }
2056
- async CreateCet(jsonObject) {
2057
- await this.CfdLoaded();
2058
- return this._cfdDlcJs.CreateCet(jsonObject);
2059
- }
2060
- async CreateDlcTransactions(jsonObject) {
2061
- await this.CfdLoaded();
2062
- return this._cfdDlcJs.CreateDlcTransactions(jsonObject);
2063
- }
2064
- async CreateBatchDlcTransactions(jsonObject) {
2065
- await this.CfdLoaded();
2066
- return this._cfdDlcJs.CreateBatchDlcTransactions(jsonObject);
2067
- }
2068
- async CreateFundTransaction(jsonObject) {
2069
- await this.CfdLoaded();
2070
- return this._cfdDlcJs.CreateFundTransaction(jsonObject);
2071
- }
2072
- async CreateBatchFundTransaction(jsonObject) {
2073
- await this.CfdLoaded();
2074
- return this._cfdDlcJs.CreateBatchFundTransaction(jsonObject);
2075
- }
2076
- async CreateRefundTransaction(jsonObject) {
2077
- await this.CfdLoaded();
2078
- return this._cfdDlcJs.CreateRefundTransaction(jsonObject);
2079
- }
2080
- async GetRawFundTxSignature(jsonObject) {
2081
- await this.CfdLoaded();
2082
- return this._cfdDlcJs.GetRawFundTxSignature(jsonObject);
2083
- }
2084
- async GetRawRefundTxSignature(jsonObject) {
2085
- await this.CfdLoaded();
2086
- return this._cfdDlcJs.GetRawRefundTxSignature(jsonObject);
2087
- }
2088
- async SignCet(jsonObject) {
2089
- await this.CfdLoaded();
2090
- return this._cfdDlcJs.SignCet(jsonObject);
2091
- }
2092
- async VerifyCetAdaptorSignature(jsonObject) {
2093
- await this.CfdLoaded();
2094
- return this._cfdDlcJs.VerifyCetAdaptorSignature(jsonObject);
2095
- }
2096
- async VerifyCetAdaptorSignatures(jsonObject) {
2097
- await this.CfdLoaded();
2098
- return this._cfdDlcJs.VerifyCetAdaptorSignatures(jsonObject);
2099
- }
2100
- async SignFundTransaction(jsonObject) {
2101
- await this.CfdLoaded();
2102
- return this._cfdDlcJs.SignFundTransaction(jsonObject);
2103
- }
2104
- async VerifyFundTxSignature(jsonObject) {
2105
- await this.CfdLoaded();
2106
- return this._cfdDlcJs.VerifyFundTxSignature(jsonObject);
2107
- }
2108
- async VerifyRefundTxSignature(jsonObject) {
2109
- await this.CfdLoaded();
2110
- return this._cfdDlcJs.VerifyRefundTxSignature(jsonObject);
2111
- }
2112
- async fundingInputToInput(_input, findDerivationPath = true) {
2113
- (0, assert_1.default)(_input.type === messaging_1.MessageType.FundingInputV0, 'FundingInput must be V0');
2114
- const network = await this.getConnectedNetwork();
2115
- const input = _input;
2116
- const prevTx = input.prevTx;
2117
- const prevTxOut = prevTx.outputs[input.prevTxVout];
2118
- const scriptPubKey = prevTxOut.scriptPubKey.serialize().slice(1);
2119
- const _address = bitcoinjs_lib_1.address.fromOutputScript(scriptPubKey, network);
2120
- let derivationPath;
2121
- if (findDerivationPath) {
2122
- const inputAddress = await this.client.wallet.findAddress([
2123
- _address,
2124
- ]);
2125
- if (inputAddress) {
2126
- derivationPath = inputAddress.derivationPath;
2127
- }
2128
- }
2129
- return {
2130
- txid: prevTx.txId.toString(),
2131
- vout: input.prevTxVout,
2132
- address: _address,
2133
- amount: prevTxOut.value.bitcoin,
2134
- value: Number(prevTxOut.value.sats),
2135
- derivationPath,
2136
- maxWitnessLength: input.maxWitnessLen,
2137
- redeemScript: input.redeemScript
2138
- ? input.redeemScript.toString('hex')
2139
- : '',
2140
- scriptPubKey: scriptPubKey.toString('hex'),
2141
- inputSerialId: input.inputSerialId,
2142
- toUtxo: types_1.Input.prototype.toUtxo,
2143
- };
2144
- }
2145
- async inputToFundingInput(input) {
2146
- const fundingInput = new messaging_1.FundingInputV0();
2147
- fundingInput.prevTxVout = input.vout;
2148
- let txRaw = '';
2149
- try {
2150
- txRaw = await this.getMethod('getRawTransactionByHash')(input.txid);
2151
- }
2152
- catch (e) {
2153
- try {
2154
- txRaw = (await this.getMethod('jsonrpc')('gettransaction', input.txid))
2155
- .hex;
2156
- }
2157
- catch (e) {
2158
- throw Error(`Cannot find tx ${input.txid} in inputToFundingInput using getrawtransactionbyhash or gettransaction`);
2159
- }
2160
- }
2161
- const tx = bitcoin_1.Tx.decode(bufio_1.StreamReader.fromHex(txRaw));
2162
- fundingInput.prevTx = tx;
2163
- fundingInput.sequence = bitcoin_1.Sequence.default();
2164
- fundingInput.maxWitnessLen = input.maxWitnessLength
2165
- ? input.maxWitnessLength
2166
- : 108;
2167
- fundingInput.redeemScript = input.redeemScript
2168
- ? Buffer.from(input.redeemScript, 'hex')
2169
- : Buffer.from('', 'hex');
2170
- fundingInput.inputSerialId = input.inputSerialId
2171
- ? input.inputSerialId
2172
- : (0, Utils_1.generateSerialId)();
2173
- return fundingInput;
2174
- }
2175
- async getConnectedNetwork() {
2176
- return this._network;
2177
- }
2178
- }
2179
- exports.default = BitcoinDlcProvider;
2180
- const BurnAddress = 'bcrt1qxcjufgh2jarkp2qkx68azh08w9v5gah8u6es8s';
2181
- //# sourceMappingURL=BitcoinDlcProvider.js.map