@defisaver/automation-sdk 2.0.5 → 2.0.8

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.
Files changed (50) hide show
  1. package/.env.dev +5 -0
  2. package/.tests.sh +3 -0
  3. package/README.md +3 -1
  4. package/esm/automation/private/LegacyProtocol.test.d.ts +1 -0
  5. package/esm/automation/private/LegacyProtocol.test.js +25 -0
  6. package/esm/automation/private/Protocol.test.d.ts +1 -0
  7. package/esm/automation/private/Protocol.test.js +25 -0
  8. package/esm/automation/private/StrategiesAutomation.js +1 -1
  9. package/esm/constants/index.js +15 -0
  10. package/esm/services/contractService.d.ts +3 -2
  11. package/esm/services/contractService.js +7 -1
  12. package/esm/services/ethereumService.test.d.ts +1 -0
  13. package/esm/services/ethereumService.test.js +241 -0
  14. package/esm/services/strategiesService.js +40 -0
  15. package/esm/services/strategiesService.test.d.ts +1 -0
  16. package/esm/services/strategiesService.test.js +108 -0
  17. package/esm/services/strategySubService.d.ts +17 -3
  18. package/esm/services/strategySubService.js +17 -6
  19. package/esm/services/strategySubService.test.d.ts +1 -0
  20. package/esm/services/strategySubService.test.js +692 -0
  21. package/esm/services/subDataService.d.ts +8 -1
  22. package/esm/services/subDataService.js +23 -14
  23. package/esm/services/subDataService.test.d.ts +1 -0
  24. package/esm/services/subDataService.test.js +993 -0
  25. package/esm/services/triggerService.d.ts +17 -0
  26. package/esm/services/triggerService.js +42 -1
  27. package/esm/services/triggerService.test.js +119 -17
  28. package/esm/types/enums.d.ts +10 -2
  29. package/esm/types/enums.js +8 -0
  30. package/esm/types/index.d.ts +19 -2
  31. package/package.json +3 -3
  32. package/src/automation/private/LegacyProtocol.test.ts +24 -0
  33. package/src/automation/private/Protocol.test.ts +24 -0
  34. package/src/automation/private/StrategiesAutomation.ts +1 -1
  35. package/src/constants/index.ts +15 -0
  36. package/src/services/contractService.ts +17 -4
  37. package/src/services/ethereumService.test.ts +256 -0
  38. package/src/services/ethereumService.ts +2 -1
  39. package/src/services/strategiesService.test.ts +103 -0
  40. package/src/services/strategiesService.ts +66 -3
  41. package/src/services/strategySubService.test.ts +835 -0
  42. package/src/services/strategySubService.ts +50 -15
  43. package/src/services/subDataService.test.ts +1063 -0
  44. package/src/services/subDataService.ts +29 -14
  45. package/src/services/triggerService.test.ts +133 -20
  46. package/src/services/triggerService.ts +55 -0
  47. package/src/services/utils.test.ts +1 -1
  48. package/src/types/enums.ts +8 -0
  49. package/src/types/index.ts +27 -3
  50. package/umd/index.js +282 -115
@@ -4,6 +4,7 @@ import { assetAmountInEth, getAssetInfo, getAssetInfoByAddress } from '@defisave
4
4
  import { otherAddresses } from '@defisaver/sdk';
5
5
 
6
6
  import type { EthereumAddress, SubData } from '../types';
7
+ import type { OrderType } from '../types/enums';
7
8
  import { ChainId, RatioState } from '../types/enums';
8
9
 
9
10
  import { ZERO_ADDRESS } from '../constants';
@@ -82,7 +83,7 @@ export const makerCloseSubData = {
82
83
  const vaultId = +AbiCoder.decodeParameter('uint256', subData[0])!;
83
84
  // if closing to collateral, asset addr will be 2nd param out of 4
84
85
  // if closing to DAI, will return 2nd param out of 3, which will be DAI addr
85
- const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[1])!.toString().toLowerCase();
86
+ const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[1])!.toString();
86
87
 
87
88
  return {
88
89
  vaultId, closeToAssetAddr,
@@ -91,14 +92,6 @@ export const makerCloseSubData = {
91
92
  };
92
93
 
93
94
  export const makerLeverageManagementSubData = {
94
- // encode: (vaultId:number, repayFrom, boostFrom, boostTo, repayTo, boostEnabled) => [
95
- // vaultId,
96
- // new Dec(repayFrom).mul(1e16).toString(),
97
- // new Dec(boostFrom).mul(1e16).toString(),
98
- // new Dec(boostTo).mul(1e16).toString(),
99
- // new Dec(repayTo).mul(1e16).toString(),
100
- // boostEnabled,
101
- // ],
102
95
  decode: (subData:SubData) => {
103
96
  const vaultId = +AbiCoder.decodeParameter('uint256', subData[0])!.toString();
104
97
  const weiRatio = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
@@ -106,6 +99,7 @@ export const makerLeverageManagementSubData = {
106
99
  return { vaultId, targetRatio };
107
100
  },
108
101
  };
102
+
109
103
  export const liquityLeverageManagementSubData = {
110
104
  decode: (subData:SubData) => {
111
105
  const weiRatio = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
@@ -113,6 +107,7 @@ export const liquityLeverageManagementSubData = {
113
107
  return { targetRatio };
114
108
  },
115
109
  };
110
+
116
111
  export const liquityCloseSubData = {
117
112
  encode(
118
113
  closeToAssetAddr: EthereumAddress,
@@ -125,16 +120,16 @@ export const liquityCloseSubData = {
125
120
 
126
121
  const collAddrEncoded = AbiCoder.encodeParameter('address', _collAddr);
127
122
  const debtAddrEncoded = AbiCoder.encodeParameter('address', _debtAddr);
128
- // if (compareAddresses(closeToAssetAddr, daiAddr)) { // TODO - Uhm, wth?
123
+ // if (compareAddresses(closeToAssetAddr, _debtAddr)) { // Closing to debt strategy was not implemented, but it should be in the future
129
124
  // // close to LUSD strategy
130
- // return [daiAddrEncoded, mcdManagerAddrEncoded];
125
+ // return [debtAddrEncoded, collAddrEncoded];
131
126
  // }
132
127
  // close to collateral strategy
133
128
  return [collAddrEncoded, debtAddrEncoded];
134
129
  },
135
130
  decode(subData: SubData): { closeToAssetAddr: EthereumAddress, debtAddr: string } {
136
- const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[0])!.toString().toLowerCase();
137
- const debtAddr = AbiCoder.decodeParameter('address', subData[1])!.toString().toLowerCase();
131
+ const closeToAssetAddr = AbiCoder.decodeParameter('address', subData[0])!.toString();
132
+ const debtAddr = AbiCoder.decodeParameter('address', subData[1])!.toString();
138
133
 
139
134
  return { closeToAssetAddr, debtAddr };
140
135
  },
@@ -342,7 +337,7 @@ export const exchangeDcaSubData = {
342
337
  };
343
338
 
344
339
  export const exchangeLimitOrderSubData = {
345
- encode(fromToken: EthereumAddress, toToken: EthereumAddress, amount: string, targetPrice: string, goodUntil: string | number, orderType: number) : SubData {
340
+ encode(fromToken: EthereumAddress, toToken: EthereumAddress, amount: string, targetPrice: string, goodUntil: string | number, orderType: OrderType) : SubData {
346
341
  return [
347
342
  fromToken,
348
343
  toToken,
@@ -437,3 +432,23 @@ export const liquityDsrSupplySubData = {
437
432
  return { targetRatio };
438
433
  },
439
434
  };
435
+
436
+ export const liquityDebtInFrontRepaySubData = {
437
+ encode: (targetRatioIncrease: number) => {
438
+ const wethAddress = getAssetInfo('WETH').address;
439
+ const lusdAddress = getAssetInfo('LUSD').address;
440
+
441
+ const wethAddressEncoded = AbiCoder.encodeParameter('address', wethAddress);
442
+ const lusdAddressEncoded = AbiCoder.encodeParameter('address', lusdAddress);
443
+ const targetRatioIncreaseEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatioIncrease));
444
+ const withdrawIdEncoded = AbiCoder.encodeParameter('uint8', 1); // withdraw - 1
445
+ const paybackIdEncoded = AbiCoder.encodeParameter('uint8', 0); // payback - 0
446
+
447
+ return [wethAddressEncoded, lusdAddressEncoded, targetRatioIncreaseEncoded, withdrawIdEncoded, paybackIdEncoded];
448
+ },
449
+ decode: (subData: SubData) => {
450
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[2]) as any as string;
451
+ const targetRatioIncrease = weiToRatioPercentage(weiRatio);
452
+ return { targetRatioIncrease };
453
+ },
454
+ };
@@ -1,19 +1,21 @@
1
1
  import { expect } from 'chai';
2
- import { getAssetInfo } from '@defisaver/tokens';
2
+ import { getAssetInfo, MAXUINT } from '@defisaver/tokens';
3
3
  import * as web3Utils from 'web3-utils';
4
4
 
5
5
  import { ChainId, OrderType, RatioState } from '../types/enums';
6
- import { EthereumAddress, TriggerData } from '../types';
6
+ import type { EthereumAddress, TriggerData } from '../types';
7
7
 
8
8
  import {
9
9
  aaveV2RatioTrigger,
10
10
  aaveV3QuotePriceTrigger,
11
+ aaveV3QuotePriceWithMaximumGasPriceTrigger,
11
12
  aaveV3RatioTrigger,
12
13
  cBondsRebondTrigger,
13
14
  chainlinkPriceTrigger,
14
15
  compoundV2RatioTrigger,
15
16
  compoundV3RatioTrigger,
16
- curveUsdBorrowRateTrigger, curveUsdSoftLiquidationTrigger,
17
+ curveUsdBorrowRateTrigger,
18
+ curveUsdSoftLiquidationTrigger,
17
19
  exchangeOffchainPriceTrigger,
18
20
  exchangeTimestampTrigger,
19
21
  liquityDebtInFrontTrigger,
@@ -22,6 +24,7 @@ import {
22
24
  sparkQuotePriceTrigger,
23
25
  sparkRatioTrigger,
24
26
  trailingStopTrigger,
27
+ liquityDebtInFrontWithLimitTrigger,
25
28
  } from './triggerService';
26
29
 
27
30
  describe('Feature: triggerService.ts', () => {
@@ -59,7 +62,7 @@ describe('Feature: triggerService.ts', () => {
59
62
  ];
60
63
 
61
64
  examples.forEach(([expected, actual]) => {
62
- it(`Given ${actual} should return expected value: ${expected}`, () => {
65
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
63
66
  expect(chainlinkPriceTrigger.decode(actual)).to.eql(expected);
64
67
  });
65
68
  });
@@ -99,7 +102,7 @@ describe('Feature: triggerService.ts', () => {
99
102
  ];
100
103
 
101
104
  examples.forEach(([expected, actual]) => {
102
- it(`Given ${actual} should return expected value: ${expected}`, () => {
105
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
103
106
  expect(trailingStopTrigger.decode(actual)).to.eql(expected);
104
107
  });
105
108
  });
@@ -139,7 +142,7 @@ describe('Feature: triggerService.ts', () => {
139
142
  ];
140
143
 
141
144
  examples.forEach(([expected, actual]) => {
142
- it(`Given ${actual} should return expected value: ${expected}`, () => {
145
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
143
146
  expect(makerRatioTrigger.decode(actual)).to.eql(expected);
144
147
  });
145
148
  });
@@ -179,7 +182,7 @@ describe('Feature: triggerService.ts', () => {
179
182
  ];
180
183
 
181
184
  examples.forEach(([expected, actual]) => {
182
- it(`Given ${actual} should return expected value: ${expected}`, () => {
185
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
183
186
  expect(aaveV3RatioTrigger.decode(actual)).to.eql(expected);
184
187
  });
185
188
  });
@@ -219,7 +222,7 @@ describe('Feature: triggerService.ts', () => {
219
222
  ];
220
223
 
221
224
  examples.forEach(([expected, actual]) => {
222
- it(`Given ${actual} should return expected value: ${expected}`, () => {
225
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
223
226
  expect(morphoAaveV2RatioTrigger.decode(actual)).to.eql(expected);
224
227
  });
225
228
  });
@@ -269,13 +272,77 @@ describe('Feature: triggerService.ts', () => {
269
272
  ];
270
273
 
271
274
  examples.forEach(([expected, actual]) => {
272
- it(`Given ${actual} should return expected value: ${expected}`, () => {
275
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
273
276
  expect(aaveV3QuotePriceTrigger.decode(actual)).to.eql(expected);
274
277
  });
275
278
  });
276
279
  });
277
280
  });
278
281
 
282
+ describe('When testing triggerService.aaveV3QuotePriceWithMaximumGasPriceTrigger', () => {
283
+ describe('encode()', () => {
284
+ const examples: Array<[TriggerData, [baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: number, ratioState: RatioState, maximumGasPriceInGwei?: number]]> = [
285
+ [
286
+ [
287
+ '0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000000001',
288
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
289
+ ],
290
+ [getAssetInfo('DAI', ChainId.Ethereum).address, getAssetInfo('WETH', ChainId.Ethereum).address, 0.0004, RatioState.UNDER]
291
+ ],
292
+ [
293
+ [
294
+ '0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000000',
295
+ '0x00000000000000000000000000000000000000000000000000000002cb417800',
296
+ ],
297
+ [getAssetInfo('WBTC', ChainId.Ethereum).address, getAssetInfo('USDT', ChainId.Ethereum).address, 0.00000023, RatioState.OVER, 12]
298
+ ],
299
+ ];
300
+
301
+ examples.forEach(([expected, actual]) => {
302
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
303
+ expect(aaveV3QuotePriceWithMaximumGasPriceTrigger.encode(...actual)).to.eql(expected);
304
+ });
305
+ });
306
+ });
307
+
308
+ describe('decode()', () => {
309
+ const examples: Array<[{ baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: string, ratioState: RatioState, maximumGasPrice: string }, TriggerData]> = [
310
+ [
311
+ {
312
+ baseTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('DAI', ChainId.Ethereum).address),
313
+ quoteTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address),
314
+ price: '0.0004',
315
+ ratioState: RatioState.UNDER,
316
+ maximumGasPrice: web3Utils.fromWei(MAXUINT, 'gwei')
317
+ },
318
+ [
319
+ '0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000009c400000000000000000000000000000000000000000000000000000000000000001',
320
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
321
+ ],
322
+ ],
323
+ [
324
+ {
325
+ baseTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('WBTC', ChainId.Ethereum).address),
326
+ quoteTokenAddress: web3Utils.toChecksumAddress(getAssetInfo('USDT', ChainId.Ethereum).address),
327
+ price: '0.00000023',
328
+ ratioState: RatioState.OVER,
329
+ maximumGasPrice: '12',
330
+ },
331
+ [
332
+ '0x0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec700000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000000',
333
+ '0x00000000000000000000000000000000000000000000000000000002cb417800',
334
+ ],
335
+ ]
336
+ ];
337
+
338
+ examples.forEach(([expected, actual]) => {
339
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
340
+ expect(aaveV3QuotePriceWithMaximumGasPriceTrigger.decode(actual)).to.eql(expected);
341
+ });
342
+ });
343
+ });
344
+ });
345
+
279
346
  describe('When testing triggerService.liquityRatioTrigger', () => {
280
347
  describe('encode()', () => {
281
348
  const examples: Array<[[string], [owner: EthereumAddress, ratioPercentage: number, ratioState: RatioState]]> = [
@@ -317,7 +384,7 @@ describe('Feature: triggerService.ts', () => {
317
384
  ];
318
385
 
319
386
  examples.forEach(([expected, actual]) => {
320
- it(`Given ${actual} should return expected value: ${expected}`, () => {
387
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
321
388
  expect(compoundV2RatioTrigger.decode(actual)).to.eql(expected);
322
389
  });
323
390
  });
@@ -363,7 +430,7 @@ describe('Feature: triggerService.ts', () => {
363
430
  ];
364
431
 
365
432
  examples.forEach(([expected, actual]) => {
366
- it(`Given ${actual} should return expected value: ${expected}`, () => {
433
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
367
434
  expect(liquityDebtInFrontTrigger.decode(actual)).to.eql(expected);
368
435
  });
369
436
  });
@@ -400,7 +467,7 @@ describe('Feature: triggerService.ts', () => {
400
467
  ];
401
468
 
402
469
  examples.forEach(([expected, actual]) => {
403
- it(`Given ${actual} should return expected value: ${expected}`, () => {
470
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
404
471
  expect(aaveV2RatioTrigger.decode(actual)).to.eql(expected);
405
472
  });
406
473
  });
@@ -440,7 +507,7 @@ describe('Feature: triggerService.ts', () => {
440
507
  ];
441
508
 
442
509
  examples.forEach(([expected, actual]) => {
443
- it(`Given ${actual} should return expected value: ${expected}`, () => {
510
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
444
511
  expect(cBondsRebondTrigger.decode(actual)).to.eql(expected);
445
512
  });
446
513
  });
@@ -490,7 +557,7 @@ describe('Feature: triggerService.ts', () => {
490
557
  ];
491
558
 
492
559
  examples.forEach(([expected, actual]) => {
493
- it(`Given ${actual} should return expected value: ${expected}`, () => {
560
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
494
561
  expect(compoundV3RatioTrigger.decode(actual)).to.eql(expected);
495
562
  });
496
563
  });
@@ -534,7 +601,7 @@ describe('Feature: triggerService.ts', () => {
534
601
  ];
535
602
 
536
603
  examples.forEach(([expected, actual]) => {
537
- it(`Given ${actual} should return expected value: ${expected}`, () => {
604
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
538
605
  expect(exchangeTimestampTrigger.decode(actual)).to.eql(expected);
539
606
  });
540
607
  });
@@ -586,7 +653,7 @@ describe('Feature: triggerService.ts', () => {
586
653
  ];
587
654
 
588
655
  examples.forEach(([expected, actual]) => {
589
- it(`Given ${actual} should return expected value: ${expected}`, () => {
656
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
590
657
  expect(exchangeOffchainPriceTrigger.decode(...actual)).to.eql(expected);
591
658
  });
592
659
  });
@@ -626,7 +693,7 @@ describe('Feature: triggerService.ts', () => {
626
693
  ];
627
694
 
628
695
  examples.forEach(([expected, actual]) => {
629
- it(`Given ${actual} should return expected value: ${expected}`, () => {
696
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
630
697
  expect(sparkRatioTrigger.decode(actual)).to.eql(expected);
631
698
  });
632
699
  });
@@ -676,7 +743,7 @@ describe('Feature: triggerService.ts', () => {
676
743
  ];
677
744
 
678
745
  examples.forEach(([expected, actual]) => {
679
- it(`Given ${actual} should return expected value: ${expected}`, () => {
746
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
680
747
  expect(sparkQuotePriceTrigger.decode(actual)).to.eql(expected);
681
748
  });
682
749
  });
@@ -726,7 +793,7 @@ describe('Feature: triggerService.ts', () => {
726
793
  ];
727
794
 
728
795
  examples.forEach(([expected, actual]) => {
729
- it(`Given ${actual} should return expected value: ${expected}`, () => {
796
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
730
797
  expect(curveUsdBorrowRateTrigger.decode(actual)).to.eql(expected);
731
798
  });
732
799
  });
@@ -774,11 +841,57 @@ describe('Feature: triggerService.ts', () => {
774
841
  ];
775
842
 
776
843
  examples.forEach(([expected, actual]) => {
777
- it(`Given ${actual} should return expected value: ${expected}`, () => {
844
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
778
845
  expect(curveUsdSoftLiquidationTrigger.decode(actual)).to.eql(expected);
779
846
  });
780
847
  });
781
848
  });
782
849
  });
783
850
 
851
+ describe('When testing triggerService.liquityDebtInFrontWithLimitTrigger', () => {
852
+ describe('encode()', () => {
853
+ const examples: Array<[[string], [owner: EthereumAddress, debtInFrontMin: string]]> = [
854
+ [
855
+ ['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a0000000000000000000000000000000000000000019d971e4fe8401e74000000'],
856
+ [web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'), '500000000']
857
+ ],
858
+ [
859
+ ['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a00000000000000000000000000000000000000000001a784379d99db42000000'],
860
+ [web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'), '2000000']
861
+ ],
862
+ ];
863
+
864
+ examples.forEach(([expected, actual]) => {
865
+ it(`Given ${actual} should return expected value: ${expected}`, () => {
866
+ expect(liquityDebtInFrontWithLimitTrigger.encode(...actual)).to.eql(expected);
867
+ });
868
+ });
869
+ });
870
+
871
+ describe('decode()', () => {
872
+ const examples: Array<[{ owner: EthereumAddress, debtInFrontMin: string }, TriggerData]> = [
873
+ [
874
+ {
875
+ owner: web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'),
876
+ debtInFrontMin: '500000000',
877
+ },
878
+ ['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a0000000000000000000000000000000000000000019d971e4fe8401e74000000'],
879
+ ],
880
+ [
881
+ {
882
+ owner: web3Utils.toChecksumAddress('0x235d6A8DB3C57c3f7b4ebA749E1738Db6093732a'),
883
+ debtInFrontMin: '2000000',
884
+ },
885
+ ['0x000000000000000000000000235d6a8db3c57c3f7b4eba749e1738db6093732a00000000000000000000000000000000000000000001a784379d99db42000000'],
886
+ ],
887
+ ];
888
+
889
+ examples.forEach(([expected, actual]) => {
890
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
891
+ expect(liquityDebtInFrontWithLimitTrigger.decode(actual)).to.eql(expected);
892
+ });
893
+ });
894
+ });
895
+ });
896
+
784
897
  });
@@ -1,4 +1,5 @@
1
1
  import Dec from 'decimal.js';
2
+ import { MAXUINT } from '@defisaver/tokens';
2
3
  import AbiCoder from 'web3-eth-abi';
3
4
  import * as web3Utils from 'web3-utils';
4
5
 
@@ -100,6 +101,46 @@ export const aaveV3QuotePriceTrigger = {
100
101
  },
101
102
  };
102
103
 
104
+ export const aaveV3QuotePriceWithMaximumGasPriceTrigger = {
105
+ encode(
106
+ baseTokenAddress: EthereumAddress,
107
+ quoteTokenAddress: EthereumAddress,
108
+ price: number,
109
+ ratioState: RatioState,
110
+ maximumGasPriceInGwei?: number,
111
+ ) {
112
+ // Price is always in 8 decimals
113
+ const _price = new Dec(price.toString()).mul(10 ** 8).floor().toString();
114
+
115
+ const _maximumGasPrice = maximumGasPriceInGwei
116
+ ? new Dec(maximumGasPriceInGwei.toString()).mul(10 ** 9).floor().toString() // We convert it to WEI
117
+ : MAXUINT; // If undefined than set to MAXUINT
118
+
119
+ return [
120
+ AbiCoder.encodeParameters(['address', 'address', 'uint256', 'uint8'], [baseTokenAddress, quoteTokenAddress, _price, ratioState]),
121
+ AbiCoder.encodeParameters(['uint256'], [_maximumGasPrice]),
122
+ ];
123
+ },
124
+ decode(
125
+ triggerData: TriggerData,
126
+ ): { baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: string, ratioState: RatioState, maximumGasPrice: string } {
127
+ const decodedPriceTrigger = AbiCoder.decodeParameters(['address', 'address', 'uint256', 'uint8'], triggerData[0]) as Array<string>;
128
+ const decodedMaximumGasPriceTrigger = AbiCoder.decodeParameters(['uint256'], triggerData[1]) as Array<string>;
129
+ // Price is always in 8 decimals
130
+ const price = new Dec(decodedPriceTrigger[2]).div(10 ** 8).toDP(8).toString();
131
+
132
+ const maximumGasPrice = new Dec(decodedMaximumGasPriceTrigger[0]).div(10 ** 9).toDP(9).toString();
133
+
134
+ return {
135
+ baseTokenAddress: decodedPriceTrigger[0],
136
+ quoteTokenAddress: decodedPriceTrigger[1],
137
+ price,
138
+ ratioState: +decodedPriceTrigger[3],
139
+ maximumGasPrice,
140
+ };
141
+ },
142
+ };
143
+
103
144
  export const compoundV2RatioTrigger = {
104
145
  encode(owner: EthereumAddress, ratioPercentage: number, ratioState: RatioState) {
105
146
  const ratioWei = ratioPercentageToWei(ratioPercentage);
@@ -143,6 +184,20 @@ export const liquityDebtInFrontTrigger = {
143
184
  },
144
185
  };
145
186
 
187
+ export const liquityDebtInFrontWithLimitTrigger = {
188
+ encode(owner: EthereumAddress, debtInFrontMin: string) {
189
+ const debtInFrontMinWei = web3Utils.toWei(new Dec(debtInFrontMin).toString(), 'ether');
190
+ return [AbiCoder.encodeParameters(['address', 'uint256'], [owner, debtInFrontMinWei])];
191
+ },
192
+ decode(triggerData: TriggerData): { owner: EthereumAddress, debtInFrontMin: string } {
193
+ const decodedData = AbiCoder.decodeParameters(['address', 'uint256'], triggerData[0]);
194
+ return {
195
+ owner: decodedData[0] as EthereumAddress,
196
+ debtInFrontMin: new Dec(decodedData[1] as string).div(10 ** 18).toString(),
197
+ };
198
+ },
199
+ };
200
+
146
201
  export const aaveV2RatioTrigger = {
147
202
  encode(owner: EthereumAddress, market: EthereumAddress, ratioPercentage: number, ratioState: RatioState) {
148
203
  const ratioWei = ratioPercentageToWei(ratioPercentage);
@@ -3,7 +3,7 @@ import * as web3Utils from 'web3-utils';
3
3
  import AbiCoder from 'web3-eth-abi';
4
4
  import { getAssetInfo } from '@defisaver/tokens';
5
5
 
6
- import { EthereumAddress } from '../types';
6
+ import type { EthereumAddress } from '../types';
7
7
  import { ChainId, RatioState } from '../types/enums';
8
8
 
9
9
  import { sparkEncode } from './strategySubService';
@@ -62,6 +62,7 @@ export namespace Strategies {
62
62
  EXCHANGE_LIMIT_ORDER = 51,
63
63
  LIQUITY_DSR_PAYBACK = 69,
64
64
  LIQUITY_DSR_SUPPLY = 70,
65
+ LIQUITY_DEBT_IN_FRONT_REPAY = 75,
65
66
  }
66
67
 
67
68
  export enum OptimismIds {
@@ -83,7 +84,9 @@ export namespace Strategies {
83
84
  Boost = 'boost',
84
85
  EoaBoost = 'eoa-boost',
85
86
  CloseToDebt = 'close-to-debt',
87
+ CloseToDebtWithGasPrice = 'close-to-debt-with-gas-price',
86
88
  CloseToCollateral = 'close-to-collateral',
89
+ CloseToCollateralWithGasPrice = 'close-to-collateral-with-gas-price',
87
90
  CloseOnPriceToDebt = 'close-on-price-to-debt',
88
91
  CloseOnPriceToColl = 'close-on-price-to-collateral',
89
92
  TrailingStopToColl = 'trailing-stop-to-collateral',
@@ -92,10 +95,13 @@ export namespace Strategies {
92
95
  BondProtection = 'bond-protection',
93
96
  Dca = 'dca',
94
97
  LimitOrder = 'limit-order',
98
+ DebtInFrontRepay = 'debt-in-front-repay',
95
99
  }
96
100
  export enum IdOverrides {
97
101
  TakeProfit = 'take-profit',
98
102
  StopLoss = 'stop-loss',
103
+ TakeProfitWithGasPrice = 'take-profit-with-gas-price',
104
+ StopLossWithGasPrice = 'stop-loss-with-gas-price',
99
105
  TrailingStop = 'trailing-stop',
100
106
  LeverageManagement = 'leverage-management',
101
107
  EoaLeverageManagement = 'leverage-management-eoa',
@@ -117,7 +123,9 @@ export namespace Bundles {
117
123
  MAKER_REPAY = 10,
118
124
  MAKER_BOOST = 11,
119
125
  AAVE_V3_CLOSE_TO_DEBT = 12,
126
+ AAVE_V3_CLOSE_TO_DEBT_WITH_GAS_PRICE = 24,
120
127
  AAVE_V3_CLOSE_TO_COLLATERAL = 13,
128
+ AAVE_V3_CLOSE_TO_COLLATERAL_WITH_GAS_PRICE = 25,
121
129
  MORPHO_AAVE_V2_REPAY = 14,
122
130
  MORPHO_AAVE_V2_BOOST = 15,
123
131
  LIQUITY_REPAY = 16,
@@ -140,14 +140,32 @@ export declare namespace Position {
140
140
  price: string,
141
141
  ratioState: RatioState,
142
142
  }
143
+
144
+ interface CloseOnPriceWithMaximumGasPriceAave extends Base {
145
+ collAsset: EthereumAddress,
146
+ collAssetId: number,
147
+ debtAsset: EthereumAddress,
148
+ debtAssetId: number,
149
+ baseToken: EthereumAddress,
150
+ quoteToken: EthereumAddress,
151
+ price: string,
152
+ maximumGasPrice: string,
153
+ ratioState: RatioState,
154
+ }
155
+
143
156
  interface TrailingStop extends Base {
144
157
  roundId: number,
145
158
  triggerPercentage: number,
146
159
  closeToAssetAddr: EthereumAddress,
147
160
  }
161
+
162
+ interface DebtInFrontRepay extends Base {
163
+ debtInFrontMin: string,
164
+ targetRepayRatioIncrease: number,
165
+ }
148
166
  }
149
167
 
150
- type SpecificAny = Specific.CloseOnPrice | Specific.TrailingStop | Specific.RatioProtection | Specific.CloseOnPriceAave;
168
+ type SpecificAny = Specific.CloseOnPrice | Specific.TrailingStop | Specific.RatioProtection | Specific.CloseOnPriceAave | Specific.CloseOnPriceWithMaximumGasPriceAave | Specific.DebtInFrontRepay;
151
169
 
152
170
  export interface Automated {
153
171
  chainId: ChainId,
@@ -189,11 +207,13 @@ type StrategyInfo<T extends number> = Record<T, Strategy<T>>;
189
207
  export type MainnetStrategiesInfo = StrategyInfo<Strategies.MainnetIds>;
190
208
  export type OptimismStrategiesInfo = StrategyInfo<Strategies.OptimismIds>;
191
209
  export type ArbitrumStrategiesInfo = StrategyInfo<Strategies.ArbitrumIds>;
210
+ export type StrategyInfoUnion = MainnetStrategiesInfo | OptimismStrategiesInfo | ArbitrumStrategiesInfo;
192
211
 
193
212
  type BundleInfo<T extends number> = Record<T, BundleOrStrategy<T>>;
194
213
  export type MainnetBundleInfo = BundleInfo<Bundles.MainnetIds>;
195
214
  export type OptimismBundleInfo = BundleInfo<Bundles.OptimismIds>;
196
215
  export type ArbitrumBundleInfo = BundleInfo<Bundles.ArbitrumIds>;
216
+ export type BundleInfoUnion = MainnetBundleInfo | OptimismBundleInfo | ArbitrumBundleInfo;
197
217
 
198
218
  export interface StrategiesInfo {
199
219
  [ChainId.Ethereum]: MainnetStrategiesInfo,
@@ -208,8 +228,12 @@ export interface BundlesInfo {
208
228
  }
209
229
 
210
230
  export type StrategyOrBundleIds =
211
- Strategies.MainnetIds & Strategies.OptimismIds & Strategies.ArbitrumIds
212
- & Bundles.MainnetIds & Bundles.OptimismIds & Bundles.ArbitrumIds;
231
+ typeof Strategies.MainnetIds[keyof typeof Strategies.MainnetIds]
232
+ | typeof Strategies.OptimismIds[keyof typeof Strategies.OptimismIds]
233
+ | typeof Strategies.ArbitrumIds[keyof typeof Strategies.ArbitrumIds]
234
+ | typeof Bundles.MainnetIds[keyof typeof Bundles.MainnetIds]
235
+ | typeof Bundles.OptimismIds[keyof typeof Bundles.OptimismIds]
236
+ | typeof Bundles.ArbitrumIds[keyof typeof Bundles.ArbitrumIds];
213
237
 
214
238
  export interface ParseData {
215
239
  chainId: ChainId,