@defisaver/automation-sdk 3.0.1 → 3.0.2

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 (48) 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.js +10 -0
  6. package/esm/services/ethereumService.test.d.ts +1 -1
  7. package/esm/services/ethereumService.test.js +1 -0
  8. package/esm/services/strategiesService.js +38 -1
  9. package/esm/services/strategiesService.test.d.ts +1 -1
  10. package/esm/services/strategiesService.test.js +1 -0
  11. package/esm/services/strategySubService.d.ts +3 -0
  12. package/esm/services/strategySubService.js +11 -1
  13. package/esm/services/strategySubService.test.d.ts +1 -1
  14. package/esm/services/strategySubService.test.js +74 -0
  15. package/esm/services/subDataService.d.ts +12 -0
  16. package/esm/services/subDataService.js +33 -1
  17. package/esm/services/subDataService.test.d.ts +1 -1
  18. package/esm/services/subDataService.test.js +89 -0
  19. package/esm/services/triggerService.d.ts +9 -0
  20. package/esm/services/triggerService.js +17 -1
  21. package/esm/services/triggerService.test.d.ts +1 -1
  22. package/esm/services/triggerService.test.js +37 -0
  23. package/esm/services/utils.test.d.ts +1 -1
  24. package/esm/services/utils.test.js +1 -0
  25. package/esm/types/enums.d.ts +5 -2
  26. package/esm/types/enums.js +3 -0
  27. package/package.json +2 -2
  28. package/scripts/generateContractTypes.js +1 -1
  29. package/src/automation/private/LegacyAutomation.ts +2 -2
  30. package/src/automation/private/StrategiesAutomation.test.ts +503 -501
  31. package/src/automation/private/StrategiesAutomation.ts +9 -0
  32. package/src/constants/index.ts +10 -0
  33. package/src/services/ethereumService.test.ts +1 -0
  34. package/src/services/ethereumService.ts +1 -1
  35. package/src/services/strategiesService.test.ts +1 -0
  36. package/src/services/strategiesService.ts +47 -1
  37. package/src/services/strategySubService.test.ts +90 -1
  38. package/src/services/strategySubService.ts +25 -0
  39. package/src/services/subDataService.test.ts +97 -1
  40. package/src/services/subDataService.ts +43 -0
  41. package/src/services/triggerService.test.ts +40 -0
  42. package/src/services/triggerService.ts +23 -0
  43. package/src/services/utils.test.ts +1 -0
  44. package/src/types/enums.ts +3 -0
  45. package/umd/index.js +129 -4
  46. package/.env +0 -4
  47. package/.yarn/releases/yarn-1.22.1.cjs +0 -147386
  48. 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
 
@@ -293,6 +293,16 @@ export const MAINNET_BUNDLES_INFO: MainnetBundleInfo = {
293
293
  strategyId: Strategies.Identifiers.Boost,
294
294
  protocol: PROTOCOLS.CrvUSD,
295
295
  },
296
+ [Bundles.MainnetIds.MORPHO_BLUE_REPAY]: {
297
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_REPAY,
298
+ strategyId: Strategies.Identifiers.Repay,
299
+ protocol: PROTOCOLS.MorphoBlue,
300
+ },
301
+ [Bundles.MainnetIds.MORPHO_BLUE_BOOST]: {
302
+ strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_BOOST,
303
+ strategyId: Strategies.Identifiers.Boost,
304
+ protocol: PROTOCOLS.MorphoBlue,
305
+ },
296
306
  };
297
307
 
298
308
  export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
@@ -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', () => {
@@ -692,7 +692,50 @@ function parseCrvUSDLeverageManagement(position: Position.Automated, parseData:
692
692
  _position.strategyData.decoded.triggerData = triggerData;
693
693
  _position.strategyData.decoded.subData = subData;
694
694
 
695
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.controller);
696
+
695
697
  const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
698
+
699
+ if (isRepay) {
700
+ _position.specific = {
701
+ triggerRepayRatio: triggerData.ratio,
702
+ targetRepayRatio: subData.targetRatio,
703
+ repayEnabled: isEnabled,
704
+ subId1: Number(subId),
705
+ subHashRepay: subHash,
706
+ mergeWithId: Strategies.Identifiers.Boost,
707
+ };
708
+ } else {
709
+ _position.specific = {
710
+ triggerBoostRatio: triggerData.ratio,
711
+ targetBoostRatio: subData.targetRatio,
712
+ boostEnabled: isEnabled,
713
+ subId2: Number(subId),
714
+ subHashBoost: subHash,
715
+ mergeId: Strategies.Identifiers.Boost,
716
+ };
717
+ }
718
+
719
+ _position.strategy.strategyId = Strategies.IdOverrides.LeverageManagement;
720
+
721
+ return _position;
722
+ }
723
+
724
+ function parseMorphoBlueLeverageManagement(position: Position.Automated, parseData: ParseData): Position.Automated {
725
+ const _position = cloneDeep(position);
726
+
727
+ const { subStruct, subId, subHash } = parseData.subscriptionEventData;
728
+ const { isEnabled } = parseData.strategiesSubsData;
729
+ const triggerData = triggerService.morphoBlueRatioTrigger.decode(subStruct.triggerData);
730
+ const subData = subDataService.morphoBlueLeverageManagementSubData.decode(subStruct.subData);
731
+
732
+ _position.strategyData.decoded.triggerData = triggerData;
733
+ _position.strategyData.decoded.subData = subData;
734
+
735
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.marketId);
736
+
737
+ const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
738
+
696
739
  if (isRepay) {
697
740
  _position.specific = {
698
741
  triggerRepayRatio: triggerData.ratio,
@@ -713,7 +756,6 @@ function parseCrvUSDLeverageManagement(position: Position.Automated, parseData:
713
756
  };
714
757
  }
715
758
 
716
- _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, triggerData.controller);
717
759
  _position.strategy.strategyId = Strategies.IdOverrides.LeverageManagement;
718
760
 
719
761
  return _position;
@@ -782,6 +824,10 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
782
824
  [Strategies.Identifiers.Repay]: parseCrvUSDLeverageManagement,
783
825
  [Strategies.Identifiers.Boost]: parseCrvUSDLeverageManagement,
784
826
  },
827
+ [ProtocolIdentifiers.StrategiesAutomation.MorphoBlue]: {
828
+ [Strategies.Identifiers.Repay]: parseMorphoBlueLeverageManagement,
829
+ [Strategies.Identifiers.Boost]: parseMorphoBlueLeverageManagement,
830
+ },
785
831
  };
786
832
 
787
833
  function getParsingMethod(id: ProtocolIdentifiers.StrategiesAutomation, strategy: BundleOrStrategy) {
@@ -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', () => {
@@ -899,6 +900,94 @@ describe('Feature: strategySubService.ts', () => {
899
900
  });
900
901
  });
901
902
  });
903
+ describe('When testing strategySubService.morphoBlueEncode', () => {
904
+ describe('leverageManagement()', () => {
905
+ const examples: Array<[
906
+ [StrategyOrBundleIds, boolean, TriggerData, SubData],
907
+ [
908
+ marketId: string,
909
+ loanToken: EthereumAddress,
910
+ collToken: EthereumAddress,
911
+ oracle: EthereumAddress,
912
+ irm: EthereumAddress,
913
+ lltv: string,
914
+ ratioState: RatioState,
915
+ targetRatio: number,
916
+ triggerRatio: number,
917
+ user: EthereumAddress,
918
+ ],
919
+ ]> = [
920
+ [
921
+ [
922
+ Bundles.MainnetIds.MORPHO_BLUE_REPAY,
923
+ true,
924
+ [
925
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c00000000000000000000000000000000000000000000000010a741a4627800000000000000000000000000000000000000000000000000000000000000000001',
926
+ ],
927
+ [
928
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
929
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
930
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
931
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
932
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
933
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
934
+ '0x000000000000000000000000000000000000000000000000136dcc951d8c0000',
935
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
936
+ ],
937
+ ],
938
+ [
939
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41',
940
+ web3Utils.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
941
+ web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'),
942
+ web3Utils.toChecksumAddress('0x2a01eb9496094da03c4e364def50f5ad1280ad72'),
943
+ web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'),
944
+ '945000000000000000',
945
+ RatioState.UNDER,
946
+ 140,
947
+ 120,
948
+ web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c')
949
+ ]
950
+ ],
951
+ [
952
+ [
953
+ Bundles.MainnetIds.MORPHO_BLUE_BOOST,
954
+ true,
955
+ [
956
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c0000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000'
957
+ ],
958
+ [
959
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
960
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
961
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
962
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
963
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
964
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
965
+ '0x00000000000000000000000000000000000000000000000016345785d8a00000',
966
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
967
+ ],
968
+ ],
969
+ [
970
+ '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41',
971
+ web3Utils.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'),
972
+ web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'),
973
+ web3Utils.toChecksumAddress('0x2a01eb9496094da03c4e364def50f5ad1280ad72'),
974
+ web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'),
975
+ '945000000000000000',
976
+ RatioState.OVER,
977
+ 160,
978
+ 200,
979
+ web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c')
980
+ ]
981
+ ],
982
+ ];
983
+
984
+ examples.forEach(([expected, actual]) => {
985
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
986
+ expect(morphoBlueEncode.leverageManagement(...actual)).to.eql(expected);
987
+ });
988
+ });
989
+ });
990
+ });
902
991
 
903
992
  describe('When testing strategySubService.compoundV3L2Encode', () => {
904
993
  describe('leverageManagement()', () => {
@@ -448,3 +448,28 @@ export const crvUSDEncode = {
448
448
  return [strategyOrBundleId, isBundle, triggerData, subData];
449
449
  },
450
450
  };
451
+
452
+ export const morphoBlueEncode = {
453
+ leverageManagement(
454
+ marketId: string,
455
+ loanToken: EthereumAddress,
456
+ collToken: EthereumAddress,
457
+ oracle: EthereumAddress,
458
+ irm: EthereumAddress,
459
+ lltv: string,
460
+ ratioState: RatioState,
461
+ targetRatio: number,
462
+ triggerRatio: number,
463
+ user: EthereumAddress,
464
+ ) {
465
+ const subData = subDataService.morphoBlueLeverageManagementSubData.encode(loanToken, collToken, oracle, irm, lltv, ratioState, targetRatio, user);
466
+
467
+ const triggerData = triggerService.morphoBlueRatioTrigger.encode(marketId, user, triggerRatio, ratioState);
468
+
469
+ // over is boost, under is repay
470
+ const strategyOrBundleId = ratioState === RatioState.OVER ? Bundles.MainnetIds.MORPHO_BLUE_BOOST : Bundles.MainnetIds.MORPHO_BLUE_REPAY;
471
+ const isBundle = true;
472
+
473
+ return [strategyOrBundleId, isBundle, triggerData, subData];
474
+ },
475
+ };
@@ -6,6 +6,7 @@ import * as web3Utils from 'web3-utils';
6
6
  import { ChainId, OrderType, RatioState } from '../types/enums';
7
7
  import type { EthereumAddress, SubData } from '../types';
8
8
 
9
+ import '../configuration';
9
10
  import {
10
11
  aaveV2LeverageManagementSubData,
11
12
  aaveV3LeverageManagementSubData,
@@ -29,7 +30,7 @@ import {
29
30
  sparkLeverageManagementSubData,
30
31
  sparkQuotePriceSubData,
31
32
  crvUSDLeverageManagementSubData,
32
- compoundV3L2LeverageManagementSubData,
33
+ compoundV3L2LeverageManagementSubData, morphoBlueLeverageManagementSubData,
33
34
  } from './subDataService';
34
35
 
35
36
  describe('Feature: subDataService.ts', () => {
@@ -1172,5 +1173,100 @@ describe('Feature: subDataService.ts', () => {
1172
1173
  });
1173
1174
  });
1174
1175
 
1176
+ describe('When testing subDataService.morphoBlueLeverageManagementSubData', () => {
1177
+ describe('encode()', () => {
1178
+ const examples: Array<[
1179
+ SubData,
1180
+ [loanToken: EthereumAddress, collToken: EthereumAddress, oracle: EthereumAddress, irm: EthereumAddress, lltv: string, ratioState: RatioState, targetRatio: number, user: EthereumAddress],
1181
+ ]> = [
1182
+ [
1183
+ [
1184
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
1185
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1186
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
1187
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1188
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
1189
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
1190
+ '0x00000000000000000000000000000000000000000000000010a741a462780000',
1191
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
1192
+ ],
1193
+ [web3Utils.toChecksumAddress('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'), web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'), web3Utils.toChecksumAddress('0x2a01eb9496094da03c4e364def50f5ad1280ad72'), web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'), '945000000000000000', RatioState.UNDER, 120, web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c')]
1194
+ ],
1195
+ [
1196
+ [
1197
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
1198
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1199
+ '0x00000000000000000000000048f7e36eb6b826b2df4b2e630b62cd25e89e40e2',
1200
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1201
+ '0x0000000000000000000000000000000000000000000000000bef55718ad60000',
1202
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
1203
+ '0x0000000000000000000000000000000000000000000000001bc16d674ec80000',
1204
+ '0x0000000000000000000000000043d218133afab8f2b829b106633e434ad94e2c',
1205
+ ],
1206
+ [web3Utils.toChecksumAddress('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'), web3Utils.toChecksumAddress('0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0'), web3Utils.toChecksumAddress('0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2'), web3Utils.toChecksumAddress('0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC'), '860000000000000000', RatioState.OVER, 200, web3Utils.toChecksumAddress('0x0043d218133AFaB8F2B829B106633E434Ad94E2c')]
1207
+ ],
1208
+ ];
1209
+
1210
+ examples.forEach(([expected, actual]) => {
1211
+ it(`Given ${actual} should return expected value: ${expected}`, () => {
1212
+ expect(morphoBlueLeverageManagementSubData.encode(...actual)).to.eql(expected);
1213
+ });
1214
+ });
1215
+ });
1216
+
1217
+ describe('decode()', () => {
1218
+ const examples: Array<[{ collToken: EthereumAddress, loanToken: EthereumAddress, oracle: EthereumAddress, irm: EthereumAddress, lltv: string, targetRatio: number, user: EthereumAddress }, SubData]> = [
1219
+ [
1220
+ {
1221
+ 'collToken': '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
1222
+ 'irm': '0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC',
1223
+ 'lltv': '945000000000000000',
1224
+ 'loanToken': '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
1225
+ 'oracle': '0x2a01EB9496094dA03c4E364Def50f5aD1280AD72',
1226
+ 'targetRatio': 120,
1227
+ 'user': '0x1031d218133AFaB8C2B819B1366c7e434Ad91e9c',
1228
+ },
1229
+ [
1230
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
1231
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1232
+ '0x0000000000000000000000002a01eb9496094da03c4e364def50f5ad1280ad72',
1233
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1234
+ '0x0000000000000000000000000000000000000000000000000d1d507e40be8000',
1235
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
1236
+ '0x00000000000000000000000000000000000000000000000010a741a462780000',
1237
+ '0x0000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c',
1238
+ ],
1239
+ ],
1240
+ [
1241
+ {
1242
+ 'collToken': '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0',
1243
+ 'irm': '0x870aC11D48B15DB9a138Cf899d20F13F79Ba00BC',
1244
+ 'lltv': '860000000000000000',
1245
+ 'loanToken': '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1246
+ 'oracle': '0x48F7E36EB6B826B2dF4B2E630B62Cd25e89E40e2',
1247
+ 'targetRatio': 200,
1248
+ 'user': '0x0043d218133aFaB8F2b829B106633E434aD94e2C',
1249
+ },
1250
+ [
1251
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
1252
+ '0x0000000000000000000000007f39c581f595b53c5cb19bd0b3f8da6c935e2ca0',
1253
+ '0x00000000000000000000000048f7e36eb6b826b2df4b2e630b62cd25e89e40e2',
1254
+ '0x000000000000000000000000870ac11d48b15db9a138cf899d20f13f79ba00bc',
1255
+ '0x0000000000000000000000000000000000000000000000000bef55718ad60000',
1256
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
1257
+ '0x0000000000000000000000000000000000000000000000001bc16d674ec80000',
1258
+ '0x0000000000000000000000000043d218133afab8f2b829b106633e434ad94e2c',
1259
+ ],
1260
+ ],
1261
+ ];
1262
+
1263
+ examples.forEach(([expected, actual]) => {
1264
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
1265
+ expect(morphoBlueLeverageManagementSubData.decode(actual)).to.eql(expected);
1266
+ });
1267
+ });
1268
+ });
1269
+ });
1270
+
1175
1271
 
1176
1272
  });
@@ -510,3 +510,46 @@ export const crvUSDLeverageManagementSubData = {
510
510
  return { controller, targetRatio };
511
511
  },
512
512
  };
513
+
514
+ export const morphoBlueLeverageManagementSubData = {
515
+ encode: (
516
+ loanToken: EthereumAddress,
517
+ collToken: EthereumAddress,
518
+ oracle: EthereumAddress,
519
+ irm: EthereumAddress,
520
+ lltv: string,
521
+ ratioState: RatioState,
522
+ targetRatio: number,
523
+ user: EthereumAddress,
524
+ ) => {
525
+ const loanTokenEncoded = AbiCoder.encodeParameter('address', loanToken);
526
+ const collTokenEncoded = AbiCoder.encodeParameter('address', collToken);
527
+ const oracleEncoded = AbiCoder.encodeParameter('address', oracle);
528
+ const irmEncoded = AbiCoder.encodeParameter('address', irm);
529
+ const lltvEncoded = AbiCoder.encodeParameter('uint256', lltv);
530
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
531
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
532
+ const userEncoded = AbiCoder.encodeParameter('address', user);
533
+ return [loanTokenEncoded, collTokenEncoded, oracleEncoded, irmEncoded, lltvEncoded, ratioStateEncoded, targetRatioEncoded, userEncoded];
534
+ },
535
+ decode: (subData: SubData) => {
536
+ const loanToken = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
537
+ const collToken = AbiCoder.decodeParameter('address', subData[1]) as any as EthereumAddress;
538
+ const oracle = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
539
+ const irm = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
540
+ const lltv = AbiCoder.decodeParameter('uint256', subData[4]) as any as EthereumAddress;
541
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[6]) as any as EthereumAddress;
542
+ const user = AbiCoder.decodeParameter('address', subData[7]) as any as EthereumAddress;
543
+ const targetRatio = weiToRatioPercentage(weiRatio);
544
+
545
+ return {
546
+ loanToken,
547
+ collToken,
548
+ oracle,
549
+ irm,
550
+ lltv,
551
+ user,
552
+ targetRatio,
553
+ };
554
+ },
555
+ };
@@ -5,6 +5,7 @@ import * as web3Utils from 'web3-utils';
5
5
  import { ChainId, OrderType, RatioState } from '../types/enums';
6
6
  import type { EthereumAddress, TriggerData } from '../types';
7
7
 
8
+ import '../configuration';
8
9
  import {
9
10
  aaveV2RatioTrigger,
10
11
  aaveV3QuotePriceTrigger,
@@ -26,6 +27,7 @@ import {
26
27
  trailingStopTrigger,
27
28
  liquityDebtInFrontWithLimitTrigger,
28
29
  crvUSDRatioTrigger,
30
+ morphoBlueRatioTrigger,
29
31
  } from './triggerService';
30
32
 
31
33
  describe('Feature: triggerService.ts', () => {
@@ -931,4 +933,42 @@ describe('Feature: triggerService.ts', () => {
931
933
  });
932
934
  });
933
935
  });
936
+
937
+ describe('When testing triggerService.morphoBlueRatioTrigger', () => {
938
+ describe('encode()', () => {
939
+ const examples: Array<[[string], [marketId: string, owner: EthereumAddress, ratioPercentage: number, ratioState: RatioState]]> = [
940
+ [
941
+ ['0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c00000000000000000000000000000000000000000000000010a741a4627800000000000000000000000000000000000000000000000000000000000000000001'],
942
+ ['0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41', web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c'), 120, RatioState.UNDER]
943
+ ],
944
+ [
945
+ ['0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc0000000000000000000000000043d218133afab8f2b829b106633e434ad94e2c0000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000'],
946
+ ['0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc', web3Utils.toChecksumAddress('0x0043d218133AFaB8F2B829B106633E434Ad94E2c'), 200, RatioState.OVER]
947
+ ],
948
+ ];
949
+ examples.forEach(([expected, actual]) => {
950
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
951
+ expect(morphoBlueRatioTrigger.encode(...actual)).to.eql(expected);
952
+ });
953
+ });
954
+ });
955
+ describe('decode()', () => {
956
+ const examples: Array<[{ marketId: string, owner: EthereumAddress, ratio: number, ratioState: RatioState }, TriggerData]> = [
957
+ [
958
+ { marketId: '0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec41', owner: web3Utils.toChecksumAddress('0x1031d218133AFaB8c2B819B1366c7E434Ad91E9c'), ratio: 120, ratioState: RatioState.UNDER },
959
+ ['0xc54d7acf14de29e0e5527cabd7a576506870346a78a11a6762e2cca66322ec410000000000000000000000001031d218133afab8c2b819b1366c7e434ad91e9c00000000000000000000000000000000000000000000000010a741a4627800000000000000000000000000000000000000000000000000000000000000000001'],
960
+ ],
961
+ [
962
+ { marketId: '0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc', owner: web3Utils.toChecksumAddress('0x0043d218133AFaB8F2B829B106633E434Ad94E2c'), ratio: 200, ratioState: RatioState.OVER },
963
+ ['0xb323495f7e4148be5643a4ea4a8221eef163e4bccfdedc2a6f4696baacbc86cc0000000000000000000000000043d218133afab8f2b829b106633e434ad94e2c0000000000000000000000000000000000000000000000001bc16d674ec800000000000000000000000000000000000000000000000000000000000000000000'],
964
+ ],
965
+ ];
966
+
967
+ examples.forEach(([expected, actual]) => {
968
+ it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
969
+ expect(morphoBlueRatioTrigger.decode(actual)).to.eql(expected);
970
+ });
971
+ });
972
+ });
973
+ });
934
974
  });
@@ -404,3 +404,26 @@ export const crvUSDRatioTrigger = {
404
404
  };
405
405
  },
406
406
  };
407
+
408
+ export const morphoBlueRatioTrigger = {
409
+ encode(
410
+ marketId: string, // bytes32
411
+ owner: EthereumAddress,
412
+ ratioPercentage: number,
413
+ ratioState: RatioState,
414
+ ) {
415
+ const ratioWei = ratioPercentageToWei(ratioPercentage);
416
+ return [AbiCoder.encodeParameters(['bytes32', 'address', 'uint256', 'uint8'], [marketId, owner, ratioWei, ratioState])];
417
+ },
418
+ decode(
419
+ triggerData: TriggerData,
420
+ ) {
421
+ const decodedData = AbiCoder.decodeParameters(['bytes32', 'address', 'uint256', 'uint8'], triggerData[0]);
422
+ return {
423
+ marketId: decodedData[0] as string,
424
+ owner: decodedData[1] as EthereumAddress,
425
+ ratio: weiToRatioPercentage(decodedData[2] as string),
426
+ ratioState: Number(decodedData[3]),
427
+ };
428
+ },
429
+ };
@@ -8,6 +8,7 @@ import { ChainId, ProtocolIdentifiers, RatioState } from '../types/enums';
8
8
 
9
9
  import { sparkEncode } from './strategySubService';
10
10
 
11
+ import '../configuration';
11
12
  import {
12
13
  addToArrayIf,
13
14
  addToObjectIf,
@@ -40,6 +40,7 @@ export namespace ProtocolIdentifiers {
40
40
  Exchange = 'Exchange',
41
41
  Spark = 'Spark',
42
42
  CrvUSD = 'CurveUSD',
43
+ MorphoBlue = 'MorphoBlue',
43
44
  }
44
45
 
45
46
  export enum LegacyAutomation {
@@ -141,6 +142,8 @@ export namespace Bundles {
141
142
  COMP_V2_BOOST = 21,
142
143
  CRVUSD_REPAY = 26,
143
144
  CRVUSD_BOOST = 27,
145
+ MORPHO_BLUE_REPAY = 32,
146
+ MORPHO_BLUE_BOOST = 33,
144
147
  }
145
148
 
146
149
  export enum OptimismIds {