@atomicfinance/bitcoin-dlc-provider 2.4.1 → 2.5.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.
@@ -52,6 +52,7 @@ import {
52
52
  DualFundingTxFinalizer,
53
53
  groupByIgnoringDigits,
54
54
  HyperbolaPayoutCurve,
55
+ PolynomialPayoutCurve,
55
56
  roundPayout,
56
57
  } from '@node-dlc/core';
57
58
  import {
@@ -83,6 +84,7 @@ import {
83
84
  OracleEventV0,
84
85
  OracleInfoV0,
85
86
  PayoutFunctionV0,
87
+ PolynomialPayoutCurvePiece,
86
88
  ScriptWitnessV0,
87
89
  } from '@node-dlc/messaging';
88
90
  import { Script, Sequence, Tx } from '@node-lightning/bitcoin';
@@ -131,7 +133,15 @@ export default class BitcoinDlcProvider
131
133
 
132
134
  for (let i = 0; i < inputs.length; i++) {
133
135
  const input = inputs[i];
134
- const keyPair = await this.getMethod('keyPair')(input.derivationPath);
136
+ let derivationPath = input.derivationPath;
137
+
138
+ if (!derivationPath) {
139
+ derivationPath = (
140
+ await this.getMethod('getWalletAddress')(input.address)
141
+ ).derivationPath;
142
+ }
143
+
144
+ const keyPair = await this.getMethod('keyPair')(derivationPath);
135
145
  const privKey = Buffer.from(keyPair.__D).toString('hex');
136
146
  privKeys.push(privKey);
137
147
  }
@@ -308,6 +318,66 @@ export default class BitcoinDlcProvider
308
318
  return { payouts, payoutGroups, messagesList };
309
319
  }
310
320
 
321
+ private GetPayoutsFromPolynomialPayoutFunction(
322
+ _dlcOffer: DlcOffer,
323
+ contractDescriptor: ContractDescriptorV1,
324
+ oracleInfo: OracleInfoV0,
325
+ totalCollateral: bigint,
326
+ ): GetPayoutsResponse {
327
+ if (_dlcOffer.type !== MessageType.DlcOfferV0)
328
+ throw Error('DlcOffer must be V0');
329
+ const dlcOffer = _dlcOffer as DlcOfferV0;
330
+ if (contractDescriptor.payoutFunction.type !== MessageType.PayoutFunctionV0)
331
+ throw Error('PayoutFunction must be V0');
332
+ const payoutFunction = contractDescriptor.payoutFunction as PayoutFunctionV0;
333
+ if (payoutFunction.pieces.length === 0)
334
+ throw Error('PayoutFunction must have at least once PayoutCurvePiece');
335
+ for (const piece of payoutFunction.pieces) {
336
+ if (
337
+ piece.payoutCurvePiece.type !== MessageType.PolynomialPayoutCurvePiece
338
+ )
339
+ throw Error('Must be PolynomialPayoutCurvePiece');
340
+ }
341
+ const eventDescriptor = oracleInfo.announcement.oracleEvent
342
+ .eventDescriptor as DigitDecompositionEventDescriptorV0;
343
+ if (
344
+ eventDescriptor.type !== MessageType.DigitDecompositionEventDescriptorV0
345
+ )
346
+ throw Error('Only DigitDecomposition Oracle Events supported');
347
+
348
+ const roundingIntervals = contractDescriptor.roundingIntervals;
349
+ const cetPayouts = PolynomialPayoutCurve.computePayouts(
350
+ payoutFunction,
351
+ totalCollateral,
352
+ roundingIntervals,
353
+ );
354
+
355
+ const payoutGroups: PayoutGroup[] = [];
356
+ cetPayouts.forEach((p) => {
357
+ payoutGroups.push({
358
+ payout: p.payout,
359
+ groups: groupByIgnoringDigits(
360
+ p.indexFrom,
361
+ p.indexTo,
362
+ eventDescriptor.base,
363
+ contractDescriptor.numDigits,
364
+ ),
365
+ });
366
+ });
367
+
368
+ const rValuesMessagesList = this.GenerateMessages(oracleInfo);
369
+
370
+ const { payouts, messagesList } = outputsToPayouts(
371
+ payoutGroups,
372
+ rValuesMessagesList,
373
+ dlcOffer.offerCollateralSatoshis,
374
+ dlcOffer.contractInfo.totalCollateral - dlcOffer.offerCollateralSatoshis,
375
+ true,
376
+ );
377
+
378
+ return { payouts, payoutGroups, messagesList };
379
+ }
380
+
311
381
  private GetPayouts(_dlcOffer: DlcOffer): GetPayoutsResponse[] {
312
382
  const { dlcOffer } = checkTypes({ _dlcOffer });
313
383
 
@@ -363,18 +433,45 @@ export default class BitcoinDlcProvider
363
433
  totalCollateral: bigint,
364
434
  ) {
365
435
  switch (contractDescriptor.type) {
366
- case MessageType.ContractDescriptorV0:
436
+ case MessageType.ContractDescriptorV0: {
367
437
  throw Error('ContractDescriptorV0 not yet supported');
438
+ }
368
439
  case MessageType.ContractDescriptorV1:
369
- // eslint-disable-next-line no-case-declarations
370
- return this.GetPayoutsFromPayoutFunction(
371
- dlcOffer,
372
- contractDescriptor as ContractDescriptorV1,
373
- oracleInfo,
374
- totalCollateral,
375
- );
376
- default:
440
+ {
441
+ const contractDescriptorV1 = contractDescriptor as ContractDescriptorV1;
442
+ const payoutFunction = contractDescriptorV1.payoutFunction as PayoutFunctionV0;
443
+
444
+ // TODO: add a better check for this
445
+ const payoutCurvePiece = payoutFunction.pieces[0].payoutCurvePiece;
446
+
447
+ switch (payoutCurvePiece.type) {
448
+ case MessageType.HyperbolaPayoutCurvePiece:
449
+ return this.GetPayoutsFromPayoutFunction(
450
+ dlcOffer,
451
+ contractDescriptor as ContractDescriptorV1,
452
+ oracleInfo,
453
+ totalCollateral,
454
+ );
455
+ case MessageType.OldHyperbolaPayoutCurvePiece:
456
+ return this.GetPayoutsFromPayoutFunction(
457
+ dlcOffer,
458
+ contractDescriptor as ContractDescriptorV1,
459
+ oracleInfo,
460
+ totalCollateral,
461
+ );
462
+ case MessageType.PolynomialPayoutCurvePiece:
463
+ return this.GetPayoutsFromPolynomialPayoutFunction(
464
+ dlcOffer,
465
+ contractDescriptor as ContractDescriptorV1,
466
+ oracleInfo,
467
+ totalCollateral,
468
+ );
469
+ }
470
+ }
471
+ break;
472
+ default: {
377
473
  throw Error('ContractDescriptor must be V0 or V1');
474
+ }
378
475
  }
379
476
  }
380
477
 
@@ -550,9 +647,9 @@ export default class BitcoinDlcProvider
550
647
  network,
551
648
  );
552
649
 
553
- const { derivationPath } = await this.getMethod('findAddress')([
554
- fundingAddress,
555
- ]);
650
+ const {
651
+ derivationPath,
652
+ } = await this.client.financewallet.quickFindAddress([fundingAddress]);
556
653
 
557
654
  const fundPrivateKeyPair = await this.getMethod('keyPair')(derivationPath);
558
655
  const fundPrivateKey = Buffer.from(fundPrivateKeyPair.__D).toString('hex');
@@ -914,6 +1011,84 @@ export default class BitcoinDlcProvider
914
1011
  return fundTx;
915
1012
  }
916
1013
 
1014
+ async FindOutcomeIndexFromPolynomialPayoutCurvePiece(
1015
+ _dlcOffer: DlcOffer,
1016
+ contractDescriptor: ContractDescriptorV1,
1017
+ contractOraclePairIndex: number,
1018
+ polynomialPayoutCurvePiece: PolynomialPayoutCurvePiece,
1019
+ oracleAttestation: OracleAttestationV0,
1020
+ outcome: bigint,
1021
+ ): Promise<FindOutcomeResponse> {
1022
+ const { dlcOffer } = checkTypes({ _dlcOffer });
1023
+
1024
+ const polynomialCurve = PolynomialPayoutCurve.fromPayoutCurvePiece(
1025
+ polynomialPayoutCurvePiece,
1026
+ );
1027
+
1028
+ const clampBN = (val: BigNumber) =>
1029
+ BigNumber.max(
1030
+ 0,
1031
+ BigNumber.min(val, dlcOffer.contractInfo.totalCollateral.toString()),
1032
+ );
1033
+
1034
+ const payout = clampBN(polynomialCurve.getPayout(outcome));
1035
+
1036
+ const payoutResponses = this.GetPayouts(dlcOffer);
1037
+ const payoutIndexOffset = this.GetIndicesFromPayouts(payoutResponses)[
1038
+ contractOraclePairIndex
1039
+ ].startingMessagesIndex;
1040
+
1041
+ const { payoutGroups } = payoutResponses[contractOraclePairIndex];
1042
+
1043
+ const intervalsSorted = [
1044
+ ...contractDescriptor.roundingIntervals.intervals,
1045
+ ].sort((a, b) => Number(b.beginInterval) - Number(a.beginInterval));
1046
+
1047
+ const interval = intervalsSorted.find(
1048
+ (interval) => Number(outcome) >= Number(interval.beginInterval),
1049
+ );
1050
+
1051
+ const roundedPayout = BigInt(
1052
+ clampBN(
1053
+ new BigNumber(roundPayout(payout, interval.roundingMod).toString()),
1054
+ ).toString(),
1055
+ );
1056
+
1057
+ const outcomesFormatted = oracleAttestation.outcomes.map((outcome) =>
1058
+ parseInt(outcome),
1059
+ );
1060
+
1061
+ let index = 0;
1062
+ let groupIndex = -1;
1063
+ let groupLength = 0;
1064
+
1065
+ for (const payoutGroup of payoutGroups) {
1066
+ if (payoutGroup.payout === roundedPayout) {
1067
+ groupIndex = payoutGroup.groups.findIndex((group) => {
1068
+ return group.every((msg, i) => msg === outcomesFormatted[i]);
1069
+ });
1070
+ if (groupIndex === -1)
1071
+ throw Error(
1072
+ 'Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
1073
+ Payout Group found but incorrect group index',
1074
+ );
1075
+ index += groupIndex;
1076
+ groupLength = payoutGroup.groups[groupIndex].length;
1077
+ break;
1078
+ } else {
1079
+ index += payoutGroup.groups.length;
1080
+ }
1081
+ }
1082
+
1083
+ if (groupIndex === -1)
1084
+ throw Error(
1085
+ 'Failed to Find OutcomeIndex From PolynomialPayoutCurvePiece. \
1086
+ Payout Group not found',
1087
+ );
1088
+
1089
+ return { index: payoutIndexOffset + index, groupLength };
1090
+ }
1091
+
917
1092
  async FindOutcomeIndexFromHyperbolaPayoutCurvePiece(
918
1093
  _dlcOffer: DlcOffer,
919
1094
  contractDescriptor: ContractDescriptorV1,
@@ -1044,14 +1219,21 @@ Payout Group not found',
1044
1219
  .reduce((acc, val, i) => acc + Number(val) * base ** i, 0);
1045
1220
 
1046
1221
  const piecesSorted = payoutFunction.pieces.sort(
1047
- (a, b) => Number(b.endpoint) - Number(a.endpoint),
1222
+ (a, b) => Number(a.endpoint) - Number(b.endpoint),
1048
1223
  );
1049
1224
 
1050
1225
  const piece = piecesSorted.find((piece) => outcome < piece.endpoint);
1051
1226
 
1052
1227
  switch (piece.payoutCurvePiece.type) {
1053
1228
  case MessageType.PolynomialPayoutCurvePiece:
1054
- throw Error('Polynomial Curve Piece not yet supported');
1229
+ return this.FindOutcomeIndexFromPolynomialPayoutCurvePiece(
1230
+ dlcOffer,
1231
+ contractDescriptor,
1232
+ contractOraclePairIndex,
1233
+ piece.payoutCurvePiece as PolynomialPayoutCurvePiece,
1234
+ oracleAttestation,
1235
+ BigInt(outcome),
1236
+ );
1055
1237
  case MessageType.HyperbolaPayoutCurvePiece:
1056
1238
  return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(
1057
1239
  dlcOffer,
@@ -1555,11 +1737,13 @@ Payout Group not found',
1555
1737
  network,
1556
1738
  );
1557
1739
 
1558
- let walletAddress: Address = await this.getMethod('findAddress')([
1559
- offerFundingAddress,
1560
- ]);
1740
+ let walletAddress: Address = await this.client.financewallet.quickFindAddress(
1741
+ [offerFundingAddress],
1742
+ );
1561
1743
  if (walletAddress) return true;
1562
- walletAddress = await this.getMethod('findAddress')([acceptFundingAddress]);
1744
+ walletAddress = await this.client.financewallet.quickFindAddress([
1745
+ acceptFundingAddress,
1746
+ ]);
1563
1747
  if (walletAddress) return false;
1564
1748
 
1565
1749
  throw Error('Wallet Address not found for DlcOffer or DlcAccept');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atomicfinance/bitcoin-dlc-provider",
3
3
  "umdName": "BitcoinDlcProvider",
4
- "version": "2.4.1",
4
+ "version": "2.5.1",
5
5
  "description": "CAL Finance Bitcoin Dlc Provider",
6
6
  "author": "Atomic Finance <info@atomic.finance>",
7
7
  "homepage": "",
@@ -15,19 +15,19 @@
15
15
  "lint:fix": "../../node_modules/.bin/eslint --fix --ignore-path ../../.eslintignore -c ../../.eslintrc.js ."
16
16
  },
17
17
  "dependencies": {
18
- "@atomicfinance/bitcoin-networks": "^2.4.1",
19
- "@atomicfinance/provider": "^2.4.1",
20
- "@atomicfinance/types": "^2.4.1",
18
+ "@atomicfinance/bitcoin-networks": "^2.5.1",
19
+ "@atomicfinance/provider": "^2.5.1",
20
+ "@atomicfinance/types": "^2.5.1",
21
21
  "@liquality/bitcoin-utils": "1.1.5",
22
22
  "@liquality/provider": "1.1.5",
23
23
  "@liquality/types": "1.1.5",
24
24
  "@liquality/utils": "1.1.5",
25
- "@node-dlc/core": "0.12.1",
26
- "@node-dlc/messaging": "0.12.1",
25
+ "@node-dlc/core": "0.18.3",
26
+ "@node-dlc/messaging": "0.18.3",
27
27
  "@node-lightning/bitcoin": "0.26.1",
28
28
  "@node-lightning/bufio": "0.26.1",
29
29
  "@node-lightning/crypto": "0.26.1",
30
- "bignumber.js": "9.0.1",
30
+ "bignumber.js": "^9.0.1",
31
31
  "bip-schnorr": "0.6.2",
32
32
  "bitcoinjs-lib": "5.2.0",
33
33
  "lodash": "^4.17.20",
@@ -36,10 +36,9 @@
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/lodash": "^4.14.160",
39
- "@types/node": "^16.10.2"
39
+ "@types/node": "16.10.3"
40
40
  },
41
41
  "publishConfig": {
42
42
  "access": "public"
43
- },
44
- "gitHead": "480ad354fdda15c0500d5b9db190e6999e97d95c"
43
+ }
45
44
  }