@atomicfinance/bitcoin-dlc-provider 2.4.2 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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';
@@ -316,6 +318,66 @@ export default class BitcoinDlcProvider
316
318
  return { payouts, payoutGroups, messagesList };
317
319
  }
318
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
+
319
381
  private GetPayouts(_dlcOffer: DlcOffer): GetPayoutsResponse[] {
320
382
  const { dlcOffer } = checkTypes({ _dlcOffer });
321
383
 
@@ -371,18 +433,45 @@ export default class BitcoinDlcProvider
371
433
  totalCollateral: bigint,
372
434
  ) {
373
435
  switch (contractDescriptor.type) {
374
- case MessageType.ContractDescriptorV0:
436
+ case MessageType.ContractDescriptorV0: {
375
437
  throw Error('ContractDescriptorV0 not yet supported');
438
+ }
376
439
  case MessageType.ContractDescriptorV1:
377
- // eslint-disable-next-line no-case-declarations
378
- return this.GetPayoutsFromPayoutFunction(
379
- dlcOffer,
380
- contractDescriptor as ContractDescriptorV1,
381
- oracleInfo,
382
- totalCollateral,
383
- );
384
- 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: {
385
473
  throw Error('ContractDescriptor must be V0 or V1');
474
+ }
386
475
  }
387
476
  }
388
477
 
@@ -558,9 +647,9 @@ export default class BitcoinDlcProvider
558
647
  network,
559
648
  );
560
649
 
561
- const { derivationPath } = await this.getMethod('findAddress')([
562
- fundingAddress,
563
- ]);
650
+ const {
651
+ derivationPath,
652
+ } = await this.client.financewallet.quickFindAddress([fundingAddress]);
564
653
 
565
654
  const fundPrivateKeyPair = await this.getMethod('keyPair')(derivationPath);
566
655
  const fundPrivateKey = Buffer.from(fundPrivateKeyPair.__D).toString('hex');
@@ -922,6 +1011,84 @@ export default class BitcoinDlcProvider
922
1011
  return fundTx;
923
1012
  }
924
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
+
925
1092
  async FindOutcomeIndexFromHyperbolaPayoutCurvePiece(
926
1093
  _dlcOffer: DlcOffer,
927
1094
  contractDescriptor: ContractDescriptorV1,
@@ -1052,14 +1219,21 @@ Payout Group not found',
1052
1219
  .reduce((acc, val, i) => acc + Number(val) * base ** i, 0);
1053
1220
 
1054
1221
  const piecesSorted = payoutFunction.pieces.sort(
1055
- (a, b) => Number(b.endpoint) - Number(a.endpoint),
1222
+ (a, b) => Number(a.endpoint) - Number(b.endpoint),
1056
1223
  );
1057
1224
 
1058
1225
  const piece = piecesSorted.find((piece) => outcome < piece.endpoint);
1059
1226
 
1060
1227
  switch (piece.payoutCurvePiece.type) {
1061
1228
  case MessageType.PolynomialPayoutCurvePiece:
1062
- 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
+ );
1063
1237
  case MessageType.HyperbolaPayoutCurvePiece:
1064
1238
  return this.FindOutcomeIndexFromHyperbolaPayoutCurvePiece(
1065
1239
  dlcOffer,
@@ -1563,11 +1737,13 @@ Payout Group not found',
1563
1737
  network,
1564
1738
  );
1565
1739
 
1566
- let walletAddress: Address = await this.getMethod('findAddress')([
1567
- offerFundingAddress,
1568
- ]);
1740
+ let walletAddress: Address = await this.client.financewallet.quickFindAddress(
1741
+ [offerFundingAddress],
1742
+ );
1569
1743
  if (walletAddress) return true;
1570
- walletAddress = await this.getMethod('findAddress')([acceptFundingAddress]);
1744
+ walletAddress = await this.client.financewallet.quickFindAddress([
1745
+ acceptFundingAddress,
1746
+ ]);
1571
1747
  if (walletAddress) return false;
1572
1748
 
1573
1749
  throw Error('Wallet Address not found for DlcOffer or DlcAccept');
package/package.json CHANGED
@@ -1,33 +1,33 @@
1
1
  {
2
2
  "name": "@atomicfinance/bitcoin-dlc-provider",
3
3
  "umdName": "BitcoinDlcProvider",
4
- "version": "2.4.2",
4
+ "version": "2.5.0",
5
5
  "description": "CAL Finance Bitcoin Dlc Provider",
6
6
  "author": "Atomic Finance <info@atomic.finance>",
7
7
  "homepage": "",
8
8
  "license": "ISC",
9
9
  "main": "dist/index.js",
10
10
  "scripts": {
11
- "build": "../../node_modules/.bin/tsc --project tsconfig.json",
11
+ "build": "../../node_modules/.bin/swc lib --out-dir=dist --config-file=../../.swcrc",
12
12
  "prepublishOnly": "yarn run build",
13
13
  "test": "yarn run build",
14
14
  "lint": "../../node_modules/.bin/eslint --ignore-path ../../.eslintignore -c ../../.eslintrc.js .",
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.2",
19
- "@atomicfinance/provider": "^2.4.2",
20
- "@atomicfinance/types": "^2.4.2",
18
+ "@atomicfinance/bitcoin-networks": "^2.5.0",
19
+ "@atomicfinance/provider": "^2.5.0",
20
+ "@atomicfinance/types": "^2.5.0",
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,10 @@
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
43
  },
44
- "gitHead": "ae5d1bf9db5c664032f0be604116a83dbf6b5db3"
44
+ "gitHead": "021537d74a46eb5bd578a7c4b122555e6b0a310f"
45
45
  }