@defisaver/automation-sdk 2.0.8 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,13 +6,24 @@ import type {
6
6
  Position, ParseData, StrategiesToProtocolVersionMapping, BundleOrStrategy, StrategyOrBundleIds,
7
7
  BundleInfoUnion, StrategyInfoUnion,
8
8
  } from '../types';
9
- import type { ChainId } from '../types/enums';
10
- import { ProtocolIdentifiers, Strategies } from '../types/enums';
9
+ import { ChainId, ProtocolIdentifiers, Strategies } from '../types/enums';
11
10
 
12
- import { getRatioStateInfoForAaveCloseStrategy, isRatioStateOver, wethToEthByAddress } from './utils';
11
+ import {
12
+ getPositionId, getRatioStateInfoForAaveCloseStrategy, isRatioStateOver, wethToEthByAddress,
13
+ } from './utils';
13
14
  import * as subDataService from './subDataService';
14
15
  import * as triggerService from './triggerService';
15
16
 
17
+ const SPARK_MARKET_ADDRESSES = {
18
+ [ChainId.Ethereum]: '0x02C3eA4e34C0cBd694D2adFa2c690EECbC1793eE',
19
+ };
20
+
21
+ const AAVE_V3_MARKET_ADDRESSES = {
22
+ [ChainId.Ethereum]: '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e',
23
+ [ChainId.Optimism]: '0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb',
24
+ [ChainId.Arbitrum]: '0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb',
25
+ };
26
+
16
27
  function parseMakerSavingsLiqProtection(position: Position.Automated, parseData: ParseData): Position.Automated {
17
28
  const _position = cloneDeep(position);
18
29
 
@@ -24,6 +35,8 @@ function parseMakerSavingsLiqProtection(position: Position.Automated, parseData:
24
35
  _position.strategyData.decoded.triggerData = triggerData;
25
36
  _position.strategyData.decoded.subData = subData;
26
37
 
38
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, subData.vaultId);
39
+
27
40
  _position.specific = {
28
41
  triggerRepayRatio: Number(triggerData.ratio),
29
42
  targetRepayRatio: Number(subData.targetRatio),
@@ -45,6 +58,8 @@ function parseMakerCloseOnPrice(position: Position.Automated, parseData: ParseDa
45
58
  _position.strategyData.decoded.triggerData = triggerData;
46
59
  _position.strategyData.decoded.subData = subData;
47
60
 
61
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, subData.vaultId);
62
+
48
63
  const isTakeProfit = isRatioStateOver(Number(triggerData.state));
49
64
 
50
65
  _position.strategy.strategyId = isTakeProfit ? Strategies.IdOverrides.TakeProfit : Strategies.IdOverrides.StopLoss;
@@ -68,6 +83,8 @@ function parseMakerTrailingStop(position: Position.Automated, parseData: ParseDa
68
83
  _position.strategyData.decoded.triggerData = triggerData;
69
84
  _position.strategyData.decoded.subData = subData;
70
85
 
86
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, subData.vaultId);
87
+
71
88
  _position.strategy.strategyId = Strategies.IdOverrides.TrailingStop;
72
89
 
73
90
  _position.specific = {
@@ -91,6 +108,8 @@ function parseMakerLeverageManagement(position: Position.Automated, parseData: P
91
108
  _position.strategyData.decoded.triggerData = triggerData;
92
109
  _position.strategyData.decoded.subData = subData;
93
110
 
111
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, subData.vaultId);
112
+
94
113
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
95
114
 
96
115
  if (isRepay) {
@@ -126,6 +145,8 @@ function parseLiquityCloseOnPrice(position: Position.Automated, parseData: Parse
126
145
  _position.strategyData.decoded.triggerData = triggerData;
127
146
  _position.strategyData.decoded.subData = subData;
128
147
 
148
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
149
+
129
150
  const isTakeProfit = isRatioStateOver(Number(triggerData.state));
130
151
 
131
152
  _position.strategy.strategyId = isTakeProfit ? Strategies.IdOverrides.TakeProfit : Strategies.IdOverrides.StopLoss;
@@ -149,6 +170,8 @@ function parseLiquityTrailingStop(position: Position.Automated, parseData: Parse
149
170
  _position.strategyData.decoded.triggerData = triggerData;
150
171
  _position.strategyData.decoded.subData = subData;
151
172
 
173
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
174
+
152
175
  _position.strategy.strategyId = Strategies.IdOverrides.TrailingStop;
153
176
 
154
177
  _position.specific = {
@@ -172,6 +195,8 @@ function parseAaveV2LeverageManagement(position: Position.Automated, parseData:
172
195
  _position.strategyData.decoded.triggerData = triggerData;
173
196
  _position.strategyData.decoded.subData = subData;
174
197
 
198
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
199
+
175
200
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
176
201
 
177
202
  if (isRepay) {
@@ -208,6 +233,8 @@ function parseAaveV3LeverageManagement(position: Position.Automated, parseData:
208
233
  _position.strategyData.decoded.triggerData = triggerData;
209
234
  _position.strategyData.decoded.subData = subData;
210
235
 
236
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
237
+
211
238
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
212
239
 
213
240
  if (isRepay) {
@@ -244,6 +271,8 @@ function parseMorphoAaveV2LeverageManagement(position: Position.Automated, parse
244
271
  _position.strategyData.decoded.triggerData = triggerData;
245
272
  _position.strategyData.decoded.subData = subData;
246
273
 
274
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
275
+
247
276
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
248
277
 
249
278
  if (isRepay) {
@@ -279,6 +308,8 @@ function parseAaveV3CloseOnPrice(position: Position.Automated, parseData: ParseD
279
308
  _position.strategyData.decoded.triggerData = triggerData;
280
309
  _position.strategyData.decoded.subData = subData;
281
310
 
311
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, AAVE_V3_MARKET_ADDRESSES[_position.chainId]);
312
+
282
313
  _position.specific = {
283
314
  collAsset: subData.collAsset,
284
315
  collAssetId: subData.collAssetId,
@@ -313,6 +344,8 @@ function parseAaveV3CloseOnPriceWithMaximumGasPrice(position: Position.Automated
313
344
  _position.strategyData.decoded.triggerData = triggerData;
314
345
  _position.strategyData.decoded.subData = subData;
315
346
 
347
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, AAVE_V3_MARKET_ADDRESSES[_position.chainId]);
348
+
316
349
  _position.specific = {
317
350
  collAsset: subData.collAsset,
318
351
  collAssetId: subData.collAssetId,
@@ -350,7 +383,10 @@ function parseCompoundV2LeverageManagement(position: Position.Automated, parseDa
350
383
 
351
384
  _position.strategyData.decoded.triggerData = triggerData;
352
385
  _position.strategyData.decoded.subData = subData;
353
- _position.owner = triggerData.owner;
386
+ _position.owner = triggerData.owner.toLowerCase();
387
+
388
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
389
+
354
390
  const isRepay = [Strategies.Identifiers.Repay, Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId as Strategies.Identifiers);
355
391
 
356
392
  if (isRepay) {
@@ -386,7 +422,10 @@ function parseCompoundV3LeverageManagement(position: Position.Automated, parseDa
386
422
 
387
423
  _position.strategyData.decoded.triggerData = triggerData;
388
424
  _position.strategyData.decoded.subData = subData;
389
- _position.owner = triggerData.owner;
425
+ _position.owner = triggerData.owner.toLowerCase();
426
+
427
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
428
+
390
429
  const isRepay = [Strategies.Identifiers.Repay, Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId as Strategies.Identifiers);
391
430
 
392
431
  if (isRepay) {
@@ -421,6 +460,8 @@ function parseChickenBondsRebond(position: Position.Automated, parseData: ParseD
421
460
  _position.strategyData.decoded.triggerData = triggerService.cBondsRebondTrigger.decode(subStruct.triggerData);
422
461
  _position.strategyData.decoded.subData = subDataService.cBondsRebondSubData.decode(subStruct.subData);
423
462
 
463
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.strategyData.decoded.triggerData.bondId);
464
+
424
465
  return _position;
425
466
  }
426
467
 
@@ -430,9 +471,11 @@ function parseLiquityBondProtection(position: Position.Automated, parseData: Par
430
471
  const { subStruct } = parseData.subscriptionEventData;
431
472
 
432
473
  const triggerData = triggerService.liquityRatioTrigger.decode(subStruct.triggerData);
433
- _position.strategyData.decoded.subData = subDataService.liquityPaybackUsingChickenBondSubData.decode(subStruct.subData);
434
474
 
435
475
  _position.strategyData.decoded.triggerData = triggerData;
476
+ _position.strategyData.decoded.subData = subDataService.liquityPaybackUsingChickenBondSubData.decode(subStruct.subData);
477
+
478
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
436
479
 
437
480
  _position.specific = {
438
481
  triggerRepayRatio: Number(triggerData.ratio),
@@ -450,6 +493,8 @@ function parseExchangeDca(position: Position.Automated, parseData: ParseData, ch
450
493
  _position.strategyData.decoded.triggerData = triggerService.exchangeTimestampTrigger.decode(subStruct.triggerData);
451
494
  _position.strategyData.decoded.subData = subDataService.exchangeDcaSubData.decode(subStruct.subData, chainId);
452
495
 
496
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, Math.random());
497
+
453
498
  return _position;
454
499
  }
455
500
 
@@ -463,6 +508,8 @@ function parseExchangeLimitOrder(position: Position.Automated, parseData: ParseD
463
508
  const toTokenDecimals = getAssetInfoByAddress(_position.strategyData.decoded.subData.toToken, chainId).decimals;
464
509
  _position.strategyData.decoded.triggerData = triggerService.exchangeOffchainPriceTrigger.decode(subStruct.triggerData, fromTokenDecimals, toTokenDecimals);
465
510
 
511
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, Math.random());
512
+
466
513
  return _position;
467
514
  }
468
515
 
@@ -478,6 +525,8 @@ function parseLiquityLeverageManagement(position: Position.Automated, parseData:
478
525
  _position.strategyData.decoded.triggerData = triggerData;
479
526
  _position.strategyData.decoded.subData = subData;
480
527
 
528
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
529
+
481
530
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
482
531
 
483
532
  if (isRepay) {
@@ -514,6 +563,8 @@ function parseSparkLeverageManagement(position: Position.Automated, parseData: P
514
563
  _position.strategyData.decoded.triggerData = triggerData;
515
564
  _position.strategyData.decoded.subData = subData;
516
565
 
566
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
567
+
517
568
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
518
569
 
519
570
  if (isRepay) {
@@ -549,6 +600,8 @@ function parseSparkCloseOnPrice(position: Position.Automated, parseData: ParseDa
549
600
  _position.strategyData.decoded.triggerData = triggerData;
550
601
  _position.strategyData.decoded.subData = subData;
551
602
 
603
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, SPARK_MARKET_ADDRESSES[_position.chainId as ChainId.Ethereum]);
604
+
552
605
  _position.specific = {
553
606
  collAsset: subData.collAsset,
554
607
  collAssetId: subData.collAssetId,
@@ -583,6 +636,8 @@ function parseLiquitySavingsLiqProtection(position: Position.Automated, parseDat
583
636
  _position.strategyData.decoded.triggerData = triggerData;
584
637
  _position.strategyData.decoded.subData = subData;
585
638
 
639
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
640
+
586
641
  _position.specific = {
587
642
  triggerRepayRatio: triggerData.ratio,
588
643
  targetRepayRatio: subData.targetRatio,
@@ -593,7 +648,7 @@ function parseLiquitySavingsLiqProtection(position: Position.Automated, parseDat
593
648
  return _position;
594
649
  }
595
650
 
596
- function parseDebtInFrontRepay(position: Position.Automated, parseData: ParseData): Position.Automated {
651
+ function parseLiquityDebtInFrontRepay(position: Position.Automated, parseData: ParseData): Position.Automated {
597
652
  const _position = cloneDeep(position);
598
653
 
599
654
  const { subStruct } = parseData.subscriptionEventData;
@@ -604,6 +659,8 @@ function parseDebtInFrontRepay(position: Position.Automated, parseData: ParseDat
604
659
  _position.strategyData.decoded.triggerData = triggerData;
605
660
  _position.strategyData.decoded.subData = subData;
606
661
 
662
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner);
663
+
607
664
  _position.specific = {
608
665
  debtInFrontMin: triggerData.debtInFrontMin,
609
666
  targetRepayRatioIncrease: subData.targetRatioIncrease,
@@ -630,7 +687,7 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
630
687
  [Strategies.Identifiers.Boost]: parseLiquityLeverageManagement,
631
688
  [Strategies.Identifiers.SavingsDsrPayback]: parseLiquitySavingsLiqProtection,
632
689
  [Strategies.Identifiers.SavingsDsrSupply]: parseLiquitySavingsLiqProtection,
633
- [Strategies.Identifiers.DebtInFrontRepay]: parseDebtInFrontRepay,
690
+ [Strategies.Identifiers.DebtInFrontRepay]: parseLiquityDebtInFrontRepay,
634
691
  },
635
692
  [ProtocolIdentifiers.StrategiesAutomation.AaveV2]: {
636
693
  [Strategies.Identifiers.Repay]: parseAaveV2LeverageManagement,
@@ -701,8 +758,9 @@ export function parseStrategiesAutomatedPosition(parseData: ParseData): Position
701
758
  chainId,
702
759
  subHash,
703
760
  blockNumber,
761
+ positionId: 'positionId parsing not implemented.',
704
762
  subId: Number(subId),
705
- owner: proxy,
763
+ owner: proxy.toLowerCase(),
706
764
  protocol: {
707
765
  ...strategyOrBundleInfo.protocol,
708
766
  },
@@ -4,7 +4,7 @@ import AbiCoder from 'web3-eth-abi';
4
4
  import { getAssetInfo } from '@defisaver/tokens';
5
5
 
6
6
  import type { EthereumAddress } from '../types';
7
- import { ChainId, RatioState } from '../types/enums';
7
+ import { ChainId, ProtocolIdentifiers, RatioState } from '../types/enums';
8
8
 
9
9
  import { sparkEncode } from './strategySubService';
10
10
 
@@ -28,6 +28,7 @@ import {
28
28
  weiToRatioPercentage,
29
29
  wethToEth,
30
30
  wethToEthByAddress,
31
+ getPositionId,
31
32
  } from './utils';
32
33
 
33
34
  describe('Feature: utils.ts', () => {
@@ -411,4 +412,19 @@ describe('Feature: utils.ts', () => {
411
412
  });
412
413
  });
413
414
  });
415
+
416
+ describe('When testing utils.getPositionId()', () => {
417
+ const examples: Array<[string, (number | string)[]]> = [
418
+ [
419
+ '1-aave__v3-0x9cb7e19861665366011899d74e75d4f2a419aeed-0x2f39d218133afab8f2b819b1066c7e434ad94e9e',
420
+ [1, ProtocolIdentifiers.StrategiesAutomation.AaveV3, '0x9cB7E19861665366011899d74E75d4F2A419aEeD', '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e']
421
+ ],
422
+ ];
423
+
424
+ examples.forEach(([expected, actual]) => {
425
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
426
+ expect(getPositionId(...actual)).to.eql(expected);
427
+ });
428
+ });
429
+ });
414
430
  });
@@ -97,4 +97,8 @@ export function getRatioStateInfoForAaveCloseStrategy(
97
97
  : ratioState = RatioState.OVER;
98
98
  }
99
99
  return { shouldFlip, ratioState };
100
+ }
101
+
102
+ export function getPositionId(...args: (number | string)[]) {
103
+ return args.map(arg => arg.toString().toLowerCase().split(' ').join('_')).join('-');
100
104
  }
@@ -61,12 +61,16 @@ export declare namespace Multicall {
61
61
  type Payload = any[];
62
62
  }
63
63
 
64
- export interface SubscriptionOptions {
64
+ interface _SubscriptionOptions {
65
65
  toBlock: BlockNumber,
66
66
  fromBlock: BlockNumber,
67
- mergeWithSameId?: boolean,
67
+ mergeWithSameId: boolean,
68
+ enabledOnly: boolean,
69
+ unexpiredOnly: boolean,
68
70
  }
69
71
 
72
+ export type SubscriptionOptions = Partial<_SubscriptionOptions>;
73
+
70
74
  export declare namespace Interfaces {
71
75
  interface ProtocolBase {
72
76
  id: ProtocolIdentifiers.StrategiesAutomation | ProtocolIdentifiers.LegacyAutomation,
@@ -169,6 +173,7 @@ export declare namespace Position {
169
173
 
170
174
  export interface Automated {
171
175
  chainId: ChainId,
176
+ positionId: string, // Helps to unify all strategies connected to a specific position
172
177
  owner: EthereumAddress,
173
178
  subId: number,
174
179
  subIds?: number[],