@defisaver/automation-sdk 3.0.1 → 3.0.2-dev2

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 (49) hide show
  1. package/esm/automation/private/LegacyAutomation.js +2 -2
  2. package/esm/automation/private/StrategiesAutomation.js +9 -1
  3. package/esm/automation/private/StrategiesAutomation.test.d.ts +1 -1
  4. package/esm/automation/private/StrategiesAutomation.test.js +500 -499
  5. package/esm/constants/index.d.ts +4 -25
  6. package/esm/constants/index.js +77 -1
  7. package/esm/services/ethereumService.test.d.ts +1 -1
  8. package/esm/services/ethereumService.test.js +1 -0
  9. package/esm/services/strategiesService.js +63 -3
  10. package/esm/services/strategiesService.test.d.ts +1 -1
  11. package/esm/services/strategiesService.test.js +1 -0
  12. package/esm/services/strategySubService.d.ts +17 -0
  13. package/esm/services/strategySubService.js +30 -1
  14. package/esm/services/strategySubService.test.d.ts +1 -1
  15. package/esm/services/strategySubService.test.js +152 -0
  16. package/esm/services/subDataService.d.ts +32 -0
  17. package/esm/services/subDataService.js +96 -1
  18. package/esm/services/subDataService.test.d.ts +1 -1
  19. package/esm/services/subDataService.test.js +193 -0
  20. package/esm/services/triggerService.d.ts +17 -0
  21. package/esm/services/triggerService.js +31 -1
  22. package/esm/services/triggerService.test.d.ts +1 -1
  23. package/esm/services/triggerService.test.js +65 -0
  24. package/esm/services/utils.test.d.ts +1 -1
  25. package/esm/services/utils.test.js +1 -0
  26. package/esm/types/enums.d.ts +27 -8
  27. package/esm/types/enums.js +19 -0
  28. package/package.json +3 -3
  29. package/scripts/generateContractTypes.js +1 -1
  30. package/src/automation/private/LegacyAutomation.ts +2 -2
  31. package/src/automation/private/StrategiesAutomation.test.ts +503 -501
  32. package/src/automation/private/StrategiesAutomation.ts +9 -0
  33. package/src/constants/index.ts +80 -3
  34. package/src/services/ethereumService.test.ts +1 -0
  35. package/src/services/ethereumService.ts +1 -1
  36. package/src/services/strategiesService.test.ts +1 -0
  37. package/src/services/strategiesService.ts +81 -3
  38. package/src/services/strategySubService.test.ts +187 -1
  39. package/src/services/strategySubService.ts +68 -0
  40. package/src/services/subDataService.test.ts +212 -1
  41. package/src/services/subDataService.ts +134 -1
  42. package/src/services/triggerService.test.ts +70 -0
  43. package/src/services/triggerService.ts +44 -1
  44. package/src/services/utils.test.ts +1 -0
  45. package/src/types/enums.ts +19 -0
  46. package/umd/index.js +397 -58
  47. package/.env +0 -4
  48. package/.yarn/releases/yarn-1.22.1.cjs +0 -147386
  49. package/.yarnrc.yml +0 -3
@@ -46,6 +46,11 @@ export default class StrategiesAutomation extends Automation {
46
46
  }
47
47
 
48
48
  protected async getEventFromSubStorage(event: string, options?: PastEventOptions) {
49
+ // only used for backfilling, so in case options?.fromBlock in undefined
50
+ // (just like we omit fromBlock when we call from app when not on fork), we still want to fetch events
51
+ if (new Dec(this.subStorageContract.createdBlock.toString()).gt(options?.fromBlock?.toString() || this.subStorageContract.createdBlock.toString())) {
52
+ return [];
53
+ }
49
54
  return getEventsFromContract<SubStorage>(this.subStorageContract, this.subStorageContractFork, event, options);
50
55
  }
51
56
 
@@ -119,6 +124,10 @@ export default class StrategiesAutomation extends Automation {
119
124
  && (
120
125
  s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.CrvUSD // merge only crvUSD leverage management for the same market
121
126
  || s.strategyData.decoded.subData.controller.toLowerCase() === current.strategyData.decoded.triggerData.controller.toLowerCase()
127
+ )
128
+ && (
129
+ s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.MorphoBlue // merge morpho blue with the same marketId
130
+ || s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase()
122
131
  );
123
132
  }
124
133
 
@@ -1,5 +1,5 @@
1
1
  import type {
2
- ArbitrumBundleInfo, BundlesInfo, EthereumAddress, Interfaces, MainnetBundleInfo, MainnetStrategiesInfo, OptimismBundleInfo, StrategiesInfo,
2
+ ArbitrumBundleInfo, ArbitrumStrategiesInfo, BundlesInfo, EthereumAddress, Interfaces, MainnetBundleInfo, MainnetStrategiesInfo, OptimismBundleInfo, OptimismStrategiesInfo, StrategiesInfo,
3
3
  } from '../types';
4
4
 
5
5
  import {
@@ -12,6 +12,8 @@ import LegacyProtocol from '../automation/private/LegacyProtocol';
12
12
  // General
13
13
  export const ZERO_ADDRESS: EthereumAddress = '0x0000000000000000000000000000000000000000';
14
14
 
15
+ export const AAVE_V3_VARIABLE_BORROW_RATE = 2;
16
+
15
17
  export const PROTOCOLS: Record<keyof typeof ProtocolIdentifiers.StrategiesAutomation, Interfaces.Protocol> = (() => {
16
18
  const protocolsMapping: any = {};
17
19
  Object.entries(ProtocolIdentifiers.StrategiesAutomation).forEach(([id, value]) => {
@@ -95,9 +97,19 @@ export const MAINNET_STRATEGIES_INFO: MainnetStrategiesInfo = {
95
97
  strategyId: Strategies.Identifiers.DebtInFrontRepay,
96
98
  protocol: PROTOCOLS.Liquity,
97
99
  },
100
+ [Strategies.MainnetIds.CURVEUSD_PAYBACK]: {
101
+ strategyOrBundleId: Strategies.MainnetIds.CURVEUSD_PAYBACK,
102
+ strategyId: Strategies.Identifiers.Payback,
103
+ protocol: PROTOCOLS.CrvUSD,
104
+ },
105
+ [Strategies.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_DEBT]: {
106
+ strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_DEBT,
107
+ strategyId: Strategies.Identifiers.OpenOrderFromDebt,
108
+ protocol: PROTOCOLS.AaveV3,
109
+ },
98
110
  };
99
111
 
100
- export const OPTIMISM_STRATEGIES_INFO = {
112
+ export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
101
113
  [Strategies.OptimismIds.EXCHANGE_DCA]: {
102
114
  strategyOrBundleId: Strategies.OptimismIds.EXCHANGE_DCA,
103
115
  strategyId: Strategies.Identifiers.Dca,
@@ -108,9 +120,14 @@ export const OPTIMISM_STRATEGIES_INFO = {
108
120
  strategyId: Strategies.Identifiers.LimitOrder,
109
121
  protocol: PROTOCOLS.Exchange,
110
122
  },
123
+ [Strategies.OptimismIds.AAVE_V3_OPEN_ORDER_FROM_DEBT]: {
124
+ strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_OPEN_ORDER_FROM_DEBT,
125
+ strategyId: Strategies.Identifiers.OpenOrderFromDebt,
126
+ protocol: PROTOCOLS.AaveV3,
127
+ },
111
128
  };
112
129
 
113
- export const ARBITRUM_STRATEGIES_INFO = {
130
+ export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
114
131
  [Strategies.ArbitrumIds.EXCHANGE_DCA]: {
115
132
  strategyOrBundleId: Strategies.ArbitrumIds.EXCHANGE_DCA,
116
133
  strategyId: Strategies.Identifiers.Dca,
@@ -121,6 +138,11 @@ export const ARBITRUM_STRATEGIES_INFO = {
121
138
  strategyId: Strategies.Identifiers.LimitOrder,
122
139
  protocol: PROTOCOLS.Exchange,
123
140
  },
141
+ [Strategies.ArbitrumIds.AAVE_V3_OPEN_ORDER_FROM_DEBT]: {
142
+ strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_OPEN_ORDER_FROM_DEBT,
143
+ strategyId: Strategies.Identifiers.OpenOrderFromDebt,
144
+ protocol: PROTOCOLS.AaveV3,
145
+ },
124
146
  };
125
147
 
126
148
  export const STRATEGIES_INFO: StrategiesInfo = {
@@ -178,6 +200,26 @@ export const MAINNET_BUNDLES_INFO: MainnetBundleInfo = {
178
200
  strategyId: Strategies.Identifiers.EoaBoost,
179
201
  protocol: PROTOCOLS.CompoundV3,
180
202
  },
203
+ [Bundles.MainnetIds.COMP_V3_SW_REPAY_V2_BUNDLE]: {
204
+ strategyOrBundleId: Bundles.MainnetIds.COMP_V3_SW_REPAY_V2_BUNDLE,
205
+ strategyId: Strategies.Identifiers.Repay,
206
+ protocol: PROTOCOLS.CompoundV3,
207
+ },
208
+ [Bundles.MainnetIds.COMP_V3_SW_BOOST_V2_BUNDLE]: {
209
+ strategyOrBundleId: Bundles.MainnetIds.COMP_V3_SW_BOOST_V2_BUNDLE,
210
+ strategyId: Strategies.Identifiers.Boost,
211
+ protocol: PROTOCOLS.CompoundV3,
212
+ },
213
+ [Bundles.MainnetIds.COMP_V3_EOA_REPAY_V2_BUNDLE]: {
214
+ strategyOrBundleId: Bundles.MainnetIds.COMP_V3_EOA_REPAY_V2_BUNDLE,
215
+ strategyId: Strategies.Identifiers.EoaRepay,
216
+ protocol: PROTOCOLS.CompoundV3,
217
+ },
218
+ [Bundles.MainnetIds.COMP_V3_EOA_BOOST_V2_BUNDLE]: {
219
+ strategyOrBundleId: Bundles.MainnetIds.COMP_V3_EOA_BOOST_V2_BUNDLE,
220
+ strategyId: Strategies.Identifiers.EoaBoost,
221
+ protocol: PROTOCOLS.CompoundV3,
222
+ },
181
223
  [Bundles.MainnetIds.LIQUITY_PAYBACK_USING_CHICKEN_BOND]: {
182
224
  strategyOrBundleId: Bundles.MainnetIds.LIQUITY_PAYBACK_USING_CHICKEN_BOND,
183
225
  strategyId: Strategies.Identifiers.BondProtection,
@@ -293,6 +335,31 @@ export const MAINNET_BUNDLES_INFO: MainnetBundleInfo = {
293
335
  strategyId: Strategies.Identifiers.Boost,
294
336
  protocol: PROTOCOLS.CrvUSD,
295
337
  },
338
+ [Bundles.MainnetIds.MORPHO_BLUE_REPAY]: {
339
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_REPAY,
340
+ strategyId: Strategies.Identifiers.Repay,
341
+ protocol: PROTOCOLS.MorphoBlue,
342
+ },
343
+ [Bundles.MainnetIds.MORPHO_BLUE_BOOST]: {
344
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_BOOST,
345
+ strategyId: Strategies.Identifiers.Boost,
346
+ protocol: PROTOCOLS.MorphoBlue,
347
+ },
348
+ [Bundles.MainnetIds.MORPHO_BLUE_EOA_REPAY]: {
349
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_EOA_REPAY,
350
+ strategyId: Strategies.Identifiers.EoaRepay,
351
+ protocol: PROTOCOLS.MorphoBlue,
352
+ },
353
+ [Bundles.MainnetIds.MORPHO_BLUE_EOA_BOOST]: {
354
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_EOA_BOOST,
355
+ strategyId: Strategies.Identifiers.EoaBoost,
356
+ protocol: PROTOCOLS.MorphoBlue,
357
+ },
358
+ [Bundles.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL]: {
359
+ strategyOrBundleId: Bundles.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL,
360
+ strategyId: Strategies.Identifiers.OpenOrderFromCollateral,
361
+ protocol: PROTOCOLS.AaveV3,
362
+ },
296
363
  };
297
364
 
298
365
  export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
@@ -316,6 +383,11 @@ export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
316
383
  strategyId: Strategies.Identifiers.CloseToCollateral,
317
384
  protocol: PROTOCOLS.AaveV3,
318
385
  },
386
+ [Bundles.OptimismIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL]: {
387
+ strategyOrBundleId: Bundles.OptimismIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL,
388
+ strategyId: Strategies.Identifiers.OpenOrderFromCollateral,
389
+ protocol: PROTOCOLS.AaveV3,
390
+ },
319
391
  };
320
392
 
321
393
  export const ARBITRUM_BUNDLES_INFO: ArbitrumBundleInfo = {
@@ -349,6 +421,11 @@ export const ARBITRUM_BUNDLES_INFO: ArbitrumBundleInfo = {
349
421
  strategyId: Strategies.Identifiers.Repay,
350
422
  protocol: PROTOCOLS.CompoundV3,
351
423
  },
424
+ [Bundles.ArbitrumIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL]: {
425
+ strategyOrBundleId: Bundles.ArbitrumIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL,
426
+ strategyId: Strategies.Identifiers.OpenOrderFromCollateral,
427
+ protocol: PROTOCOLS.AaveV3,
428
+ },
352
429
  };
353
430
 
354
431
  export const BUNDLES_INFO: BundlesInfo = {
@@ -8,6 +8,7 @@ import type { BlockNumber, Multicall } from '../types';
8
8
  import { Contract } from '../types';
9
9
  import type { Erc20 } from '../types/contracts/generated';
10
10
 
11
+ import '../configuration';
11
12
  import { getEventsFromContract, multicall, } from './ethereumService';
12
13
 
13
14
  import { makeErc20Contract } from './contractService';
@@ -66,4 +66,4 @@ export async function getEventsFromContract<T extends BaseContract>(
66
66
  }
67
67
 
68
68
  return [...events, ...eventsFork];
69
- }
69
+ }
@@ -3,6 +3,7 @@ import { expect } from 'chai';
3
3
  import { ProtocolIdentifiers, Strategies } from '../types/enums';
4
4
  import type { ParseData, Position } from '../types';
5
5
 
6
+ import '../configuration';
6
7
  import { parseStrategiesAutomatedPosition } from './strategiesService';
7
8
 
8
9
  describe('Feature: strategiesService.ts', () => {
@@ -431,9 +431,8 @@ function parseCompoundV3LeverageManagement(position: Position.Automated, parseDa
431
431
 
432
432
  _position.strategyData.decoded.triggerData = triggerData;
433
433
  _position.strategyData.decoded.subData = subData;
434
- _position.owner = triggerData.owner.toLowerCase();
435
434
 
436
- _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
435
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, triggerData.owner.toLowerCase(), triggerData.market);
437
436
 
438
437
  const isRepay = [Strategies.Identifiers.Repay, Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId as Strategies.Identifiers);
439
438
 
@@ -692,7 +691,10 @@ function parseCrvUSDLeverageManagement(position: Position.Automated, parseData:
692
691
  _position.strategyData.decoded.triggerData = triggerData;
693
692
  _position.strategyData.decoded.subData = subData;
694
693
 
694
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.controller);
695
+
695
696
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
697
+
696
698
  if (isRepay) {
697
699
  _position.specific = {
698
700
  triggerRepayRatio: triggerData.ratio,
@@ -713,12 +715,80 @@ function parseCrvUSDLeverageManagement(position: Position.Automated, parseData:
713
715
  };
714
716
  }
715
717
 
716
- _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.controller);
717
718
  _position.strategy.strategyId = Strategies.IdOverrides.LeverageManagement;
718
719
 
719
720
  return _position;
720
721
  }
721
722
 
723
+ function parseCrvUSDPayback(position: Position.Automated, parseData: ParseData): Position.Automated {
724
+ const _position = cloneDeep(position);
725
+
726
+ const { subStruct } = parseData.subscriptionEventData;
727
+ const triggerData = triggerService.crvUsdHealthRatioTrigger.decode(subStruct.triggerData);
728
+ const subData = subDataService.crvUSDPaybackSubData.decode(subStruct.subData);
729
+
730
+ _position.strategyData.decoded.triggerData = triggerData;
731
+ _position.strategyData.decoded.subData = subData;
732
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.controller, Math.random());
733
+ _position.strategy.strategyId = Strategies.Identifiers.Payback;
734
+
735
+ return _position;
736
+ }
737
+
738
+ function parseMorphoBlueLeverageManagement(position: Position.Automated, parseData: ParseData): Position.Automated {
739
+ const _position = cloneDeep(position);
740
+
741
+ const { subStruct, subId, subHash } = parseData.subscriptionEventData;
742
+ const { isEnabled } = parseData.strategiesSubsData;
743
+ const triggerData = triggerService.morphoBlueRatioTrigger.decode(subStruct.triggerData);
744
+ const subData = subDataService.morphoBlueLeverageManagementSubData.decode(subStruct.subData);
745
+
746
+ _position.strategyData.decoded.triggerData = triggerData;
747
+ _position.strategyData.decoded.subData = subData;
748
+
749
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, triggerData.owner.toLowerCase(), triggerData.marketId);
750
+
751
+ const isRepay = [Strategies.Identifiers.Repay, Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId as Strategies.Identifiers);
752
+
753
+ if (isRepay) {
754
+ _position.specific = {
755
+ triggerRepayRatio: triggerData.ratio,
756
+ targetRepayRatio: subData.targetRatio,
757
+ repayEnabled: isEnabled,
758
+ subId1: Number(subId),
759
+ subHashRepay: subHash,
760
+ mergeWithId: Strategies.Identifiers.Boost,
761
+ };
762
+ } else {
763
+ _position.specific = {
764
+ triggerBoostRatio: triggerData.ratio,
765
+ targetBoostRatio: subData.targetRatio,
766
+ boostEnabled: isEnabled,
767
+ subId2: Number(subId),
768
+ subHashBoost: subHash,
769
+ mergeId: Strategies.Identifiers.Boost,
770
+ };
771
+ }
772
+
773
+ const isEOA = _position.strategy.strategyId.includes('eoa');
774
+ _position.strategy.strategyId = isEOA ? Strategies.IdOverrides.EoaLeverageManagement : Strategies.IdOverrides.LeverageManagement;
775
+
776
+
777
+ return _position;
778
+ }
779
+
780
+ function parseAaveV3OpenOrderFromCollateral(position: Position.Automated, parseData: ParseData): Position.Automated {
781
+ const _position = cloneDeep(position);
782
+
783
+ const { subStruct } = parseData.subscriptionEventData;
784
+
785
+ _position.strategyData.decoded.triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
786
+ _position.strategyData.decoded.subData = subDataService.aaveV3OpenOrderSubData.decode(subStruct.subData);
787
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, Math.random());
788
+
789
+ return _position;
790
+ }
791
+
722
792
  const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
723
793
  [ProtocolIdentifiers.StrategiesAutomation.MakerDAO]: {
724
794
  [Strategies.Identifiers.SavingsLiqProtection]: parseMakerSavingsLiqProtection,
@@ -750,6 +820,7 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
750
820
  [Strategies.Identifiers.CloseToDebtWithGasPrice]: parseAaveV3CloseOnPriceWithMaximumGasPrice,
751
821
  [Strategies.Identifiers.CloseToCollateral]: parseAaveV3CloseOnPrice,
752
822
  [Strategies.Identifiers.CloseToCollateralWithGasPrice]: parseAaveV3CloseOnPriceWithMaximumGasPrice,
823
+ [Strategies.Identifiers.OpenOrderFromCollateral]: parseAaveV3OpenOrderFromCollateral,
753
824
  },
754
825
  [ProtocolIdentifiers.StrategiesAutomation.CompoundV2]: {
755
826
  [Strategies.Identifiers.Repay]: parseCompoundV2LeverageManagement,
@@ -781,6 +852,13 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
781
852
  [ProtocolIdentifiers.StrategiesAutomation.CrvUSD]: {
782
853
  [Strategies.Identifiers.Repay]: parseCrvUSDLeverageManagement,
783
854
  [Strategies.Identifiers.Boost]: parseCrvUSDLeverageManagement,
855
+ [Strategies.Identifiers.Payback]: parseCrvUSDPayback,
856
+ },
857
+ [ProtocolIdentifiers.StrategiesAutomation.MorphoBlue]: {
858
+ [Strategies.Identifiers.Repay]: parseMorphoBlueLeverageManagement,
859
+ [Strategies.Identifiers.Boost]: parseMorphoBlueLeverageManagement,
860
+ [Strategies.Identifiers.EoaRepay]: parseMorphoBlueLeverageManagement,
861
+ [Strategies.Identifiers.EoaBoost]: parseMorphoBlueLeverageManagement,
784
862
  },
785
863
  };
786
864
 
@@ -7,6 +7,7 @@ import * as web3Utils from 'web3-utils';
7
7
  import { Bundles, ChainId, OrderType, RatioState, Strategies } from '../types/enums';
8
8
  import type { EthereumAddress, StrategyOrBundleIds, SubData, TriggerData } from '../types';
9
9
 
10
+ import '../configuration';
10
11
  import {
11
12
  aaveV2Encode,
12
13
  chickenBondsEncode,
@@ -18,7 +19,7 @@ import {
18
19
  morphoAaveV2Encode,
19
20
  exchangeEncode,
20
21
  sparkEncode,
21
- crvUSDEncode, compoundV3L2Encode,
22
+ crvUSDEncode, compoundV3L2Encode, morphoBlueEncode,
22
23
  } from './strategySubService';
23
24
 
24
25
  describe('Feature: strategySubService.ts', () => {
@@ -563,6 +564,60 @@ describe('Feature: strategySubService.ts', () => {
563
564
  });
564
565
  });
565
566
  });
567
+
568
+ describe('openOrder()', () => {
569
+ const examples: Array<[
570
+ [StrategyOrBundleIds, boolean, TriggerData, SubData],
571
+ [
572
+ strategyOrBundleId: number,
573
+ isBundle: boolean,
574
+ triggerData: {
575
+ baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: number, state: RatioState.UNDER
576
+ },
577
+ subData: {
578
+ collAsset: EthereumAddress, collAssetId: number, debtAsset: EthereumAddress, debtAssetId: number, marketAddr: EthereumAddress, targetRatio: number,
579
+ },
580
+ ]
581
+ ]> = [
582
+ [
583
+ [
584
+ Bundles.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL,
585
+ true,
586
+ ['0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000006b175474e89094c44da98b954eedeac495271d0f0000000000000000000000000000000000000000000000000000007acead34980000000000000000000000000000000000000000000000000000000000000001'],
587
+ [
588
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
589
+ '0x000000000000000000000000000000000000000000000000000000000000000a',
590
+ '0x0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f',
591
+ '0x0000000000000000000000000000000000000000000000000000000000000004',
592
+ '0x0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e',
593
+ '0x0000000000000000000000000000000000000000000000001bc16d674ec80000',
594
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
595
+ ],
596
+ ],
597
+ [
598
+ Bundles.MainnetIds.AAVE_V3_OPEN_ORDER_FROM_COLLATERAL,
599
+ true,
600
+ {
601
+ baseTokenAddress: getAssetInfo('WETH').address, quoteTokenAddress: getAssetInfo('DAI').address, price: 5274.534678, state: RatioState.UNDER
602
+ },
603
+ {
604
+ collAsset: getAssetInfo('WETH').address,
605
+ collAssetId: 10,
606
+ debtAsset: getAssetInfo('DAI').address,
607
+ debtAssetId: 4,
608
+ marketAddr: '0x2f39d218133afab8f2b819b1066c7e434ad94e9e',
609
+ targetRatio: 200,
610
+ },
611
+ ]
612
+ ],
613
+ ];
614
+
615
+ examples.forEach(([expected, actual]) => {
616
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
617
+ expect(aaveV3Encode.openOrder(...actual)).to.eql(expected);
618
+ });
619
+ });
620
+ });
566
621
  });
567
622
 
568
623
  describe('When testing strategySubService.compoundV2Encode', () => {
@@ -898,6 +953,137 @@ describe('Feature: strategySubService.ts', () => {
898
953
  });
899
954
  });
900
955
  });
956
+ describe('payback()', () => {
957
+ const examples: Array<[
958
+ [StrategyOrBundleIds, boolean, TriggerData, SubData],
959
+ [owner: EthereumAddress, addressToPullTokensFrom: EthereumAddress, positionOwner: EthereumAddress, paybackAmount: string, crvUSDAddr: EthereumAddress, controllerAddr: EthereumAddress, minHealthRatio: number],
960
+ ]> = [
961
+ [
962
+ [
963
+ Strategies.MainnetIds.CURVEUSD_PAYBACK,
964
+ false,
965
+ [
966
+ '0x0000000000000000000000007a2af22ba3276108cd331c8985ef9528e10a871a000000000000000000000000a920de414ea4ab66b97da1bfe9e6eca7d421963500000000000000000000000000000000000000000000000002c68af0bb140000',
967
+ ],
968
+ [
969
+ '0x000000000000000000000000a920de414ea4ab66b97da1bfe9e6eca7d4219635',
970
+ '0x000000000000000000000000dc0ad7a48088f1aa55d26f8b36f7c1e827ddd280',
971
+ '0x000000000000000000000000dc0ad7a48088f1aa55d26f8b36f7c1e827ddd280',
972
+ '0x00000000000000000000000000000000000000000000043c33c1937564800000',
973
+ '0x000000000000000000000000f939e0a03fb07f59a73314e73794be0e57ac1b4e'
974
+ ],
975
+ ],
976
+ [
977
+ web3Utils.toChecksumAddress('0x7a2af22ba3276108cd331c8985ef9528e10a871a'),
978
+ web3Utils.toChecksumAddress('0xDc0Ad7a48088f1AA55d26f8b36F7C1E827DdD280'),
979
+ web3Utils.toChecksumAddress('0xDc0Ad7a48088f1AA55d26f8b36F7C1E827DdD280'),
980
+ '20000',
981
+ '0xf939E0A03FB07F59A73314E73794Be0E57ac1b4E',
982
+ web3Utils.toChecksumAddress('0xA920De414eA4Ab66b97dA1bFE9e6EcA7d4219635'),
983
+ 20,
984
+ ]
985
+ ]
986
+ ];
987
+
988
+ examples.forEach(([expected, actual]) => {
989
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
990
+ expect(crvUSDEncode.payback(...actual)).to.eql(expected);
991
+ });
992
+ });
993
+ });
994
+ });
995
+ describe('When testing strategySubService.morphoBlueEncode', () => {
996
+ describe('leverageManagement()', () => {
997
+ const examples: Array<[
998
+ [StrategyOrBundleIds, boolean, TriggerData, SubData],
999
+ [
1000
+ marketId: string,
1001
+ loanToken: EthereumAddress,
1002
+ collToken: EthereumAddress,
1003
+ oracle: EthereumAddress,
1004
+ irm: EthereumAddress,
1005
+ lltv: string,
1006
+ ratioState: RatioState,
1007
+ targetRatio: number,
1008
+ triggerRatio: number,
1009
+ user: EthereumAddress,
1010
+ isEoa: boolean,
1011
+ ],
1012
+ ]> = [
1013
+ [
1014
+ [
1015
+ Bundles.MainnetIds.MORPHO_BLUE_REPAY,
1016
+ true,
1017
+ [
1018
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c00000000000000000000000000000000000000000000000010a741a4627800000000000000000000000000000000000000000000000000000000000000000001',
1019
+ ],
1020
+ [
1021
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
1022
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1023
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
1024
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1025
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
1026
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
1027
+ '0x000000000000000000000000000000000000000000000000136dcc951d8c0000',
1028
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
1029
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
1030
+ ],
1031
+ ],
1032
+ [
1033
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41',
1034
+ web3Utils.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
1035
+ web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'),
1036
+ web3Utils.toChecksumAddress('0x2a01eb9496094da03c4e364def50f5ad1280ad72'),
1037
+ web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'),
1038
+ '945000000000000000',
1039
+ RatioState.UNDER,
1040
+ 140,
1041
+ 120,
1042
+ web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c'),
1043
+ false,
1044
+ ]
1045
+ ],
1046
+ [
1047
+ [
1048
+ Bundles.MainnetIds.MORPHO_BLUE_BOOST,
1049
+ true,
1050
+ [
1051
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c0000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000'
1052
+ ],
1053
+ [
1054
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
1055
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1056
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
1057
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1058
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
1059
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
1060
+ '0x00000000000000000000000000000000000000000000000016345785d8a00000',
1061
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
1062
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
1063
+ ],
1064
+ ],
1065
+ [
1066
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41',
1067
+ web3Utils.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
1068
+ web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'),
1069
+ web3Utils.toChecksumAddress('0x2a01eb9496094da03c4e364def50f5ad1280ad72'),
1070
+ web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'),
1071
+ '945000000000000000',
1072
+ RatioState.OVER,
1073
+ 160,
1074
+ 200,
1075
+ web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c'),
1076
+ false,
1077
+ ]
1078
+ ],
1079
+ ];
1080
+
1081
+ examples.forEach(([expected, actual]) => {
1082
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
1083
+ expect(morphoBlueEncode.leverageManagement(...actual)).to.eql(expected);
1084
+ });
1085
+ });
1086
+ });
901
1087
  });
902
1088
 
903
1089
  describe('When testing strategySubService.compoundV3L2Encode', () => {
@@ -296,6 +296,28 @@ export const aaveV3Encode = {
296
296
  } = triggerData;
297
297
  const triggerDataEncoded = triggerService.aaveV3QuotePriceWithMaximumGasPriceTrigger.encode(baseTokenAddress, quoteTokenAddress, price, ratioState, maximumGasPrice);
298
298
 
299
+ return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
300
+ },
301
+ openOrder(
302
+ strategyOrBundleId: number,
303
+ isBundle: boolean = true,
304
+ triggerData: {
305
+ baseTokenAddress: EthereumAddress, quoteTokenAddress: EthereumAddress, price: number, state: RatioState.UNDER
306
+ },
307
+ subData: {
308
+ collAsset: EthereumAddress, collAssetId: number, debtAsset: EthereumAddress, debtAssetId: number, marketAddr: EthereumAddress, targetRatio: number,
309
+ },
310
+ ) {
311
+ const {
312
+ collAsset, collAssetId, debtAsset, debtAssetId, marketAddr, targetRatio,
313
+ } = subData;
314
+ const subDataEncoded = subDataService.aaveV3OpenOrderSubData.encode(collAsset, collAssetId, debtAsset, debtAssetId, marketAddr, targetRatio);
315
+
316
+ const {
317
+ baseTokenAddress, quoteTokenAddress, price, state,
318
+ } = triggerData;
319
+ const triggerDataEncoded = triggerService.aaveV3QuotePriceTrigger.encode(baseTokenAddress, quoteTokenAddress, price, state);
320
+
299
321
  return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
300
322
  },
301
323
  };
@@ -445,6 +467,52 @@ export const crvUSDEncode = {
445
467
  const strategyOrBundleId = ratioState === RatioState.OVER ? Bundles.MainnetIds.CRVUSD_BOOST : Bundles.MainnetIds.CRVUSD_REPAY;
446
468
  const isBundle = true;
447
469
 
470
+ return [strategyOrBundleId, isBundle, triggerData, subData];
471
+ },
472
+ payback(
473
+ proxyAddress: EthereumAddress,
474
+ addressToPullTokensFrom: EthereumAddress,
475
+ positionOwner: EthereumAddress,
476
+ paybackAmount: string,
477
+ crvUSDAddr: EthereumAddress,
478
+ controllerAddr: EthereumAddress,
479
+ minHealthRatio: number,
480
+ ) {
481
+ const subData = subDataService.crvUSDPaybackSubData.encode(controllerAddr, addressToPullTokensFrom, positionOwner, paybackAmount, crvUSDAddr);
482
+ const triggerData = triggerService.crvUsdHealthRatioTrigger.encode(proxyAddress, controllerAddr, minHealthRatio);
483
+
484
+ const strategyId = Strategies.MainnetIds.CURVEUSD_PAYBACK;
485
+ const isBundle = false;
486
+
487
+ return [strategyId, isBundle, triggerData, subData];
488
+ },
489
+ };
490
+
491
+ export const morphoBlueEncode = {
492
+ leverageManagement(
493
+ marketId: string,
494
+ loanToken: EthereumAddress,
495
+ collToken: EthereumAddress,
496
+ oracle: EthereumAddress,
497
+ irm: EthereumAddress,
498
+ lltv: string,
499
+ ratioState: RatioState,
500
+ targetRatio: number,
501
+ triggerRatio: number,
502
+ user: EthereumAddress,
503
+ isEOA: boolean,
504
+ ) {
505
+ const subData = subDataService.morphoBlueLeverageManagementSubData.encode(loanToken, collToken, oracle, irm, lltv, ratioState, targetRatio, user, isEOA);
506
+
507
+ const triggerData = triggerService.morphoBlueRatioTrigger.encode(marketId, user, triggerRatio, ratioState);
508
+
509
+ // over is boost, under is repay
510
+ const isBoost = ratioState === RatioState.OVER;
511
+ let strategyOrBundleId;
512
+ if (isBoost) strategyOrBundleId = isEOA ? Bundles.MainnetIds.MORPHO_BLUE_EOA_BOOST : Bundles.MainnetIds.MORPHO_BLUE_BOOST;
513
+ else strategyOrBundleId = isEOA ? Bundles.MainnetIds.MORPHO_BLUE_EOA_REPAY : Bundles.MainnetIds.MORPHO_BLUE_REPAY;
514
+ const isBundle = true;
515
+
448
516
  return [strategyOrBundleId, isBundle, triggerData, subData];
449
517
  },
450
518
  };