@defisaver/automation-sdk 3.3.14 → 3.3.15-liq-prot-1-dev

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 (41) hide show
  1. package/cjs/constants/index.js +130 -0
  2. package/cjs/index.d.ts +4 -3
  3. package/cjs/index.js +6 -2
  4. package/cjs/services/strategiesService.js +178 -17
  5. package/cjs/services/strategySubService.d.ts +14 -13
  6. package/cjs/services/strategySubService.js +79 -63
  7. package/cjs/services/strategySubService.test.js +0 -234
  8. package/cjs/services/subDataService.d.ts +92 -4
  9. package/cjs/services/subDataService.js +245 -35
  10. package/cjs/services/subDataService.test.js +0 -110
  11. package/cjs/services/utils.d.ts +3 -1
  12. package/cjs/services/utils.js +34 -1
  13. package/cjs/services/utils.test.js +25 -0
  14. package/cjs/types/enums.d.ts +36 -6
  15. package/cjs/types/enums.js +30 -0
  16. package/esm/constants/index.js +130 -0
  17. package/esm/index.d.ts +4 -3
  18. package/esm/index.js +7 -3
  19. package/esm/services/strategiesService.js +178 -17
  20. package/esm/services/strategySubService.d.ts +14 -13
  21. package/esm/services/strategySubService.js +79 -60
  22. package/esm/services/strategySubService.test.js +2 -236
  23. package/esm/services/subDataService.d.ts +92 -4
  24. package/esm/services/subDataService.js +243 -34
  25. package/esm/services/subDataService.test.js +0 -110
  26. package/esm/services/utils.d.ts +3 -1
  27. package/esm/services/utils.js +32 -1
  28. package/esm/services/utils.test.js +27 -2
  29. package/esm/types/enums.d.ts +36 -6
  30. package/esm/types/enums.js +30 -0
  31. package/package.json +1 -1
  32. package/src/constants/index.ts +132 -1
  33. package/src/index.ts +24 -6
  34. package/src/services/strategiesService.ts +242 -17
  35. package/src/services/strategySubService.test.ts +0 -279
  36. package/src/services/strategySubService.ts +209 -116
  37. package/src/services/subDataService.test.ts +0 -120
  38. package/src/services/subDataService.ts +335 -49
  39. package/src/services/utils.test.ts +32 -1
  40. package/src/services/utils.ts +32 -1
  41. package/src/types/enums.ts +30 -2
@@ -164,6 +164,9 @@ export const makerLeverageManagementSubData = {
164
164
  return { vaultId, targetRatio };
165
165
  },
166
166
  };
167
+
168
+ // ! Any change here will PROBABLY require a change in makerLiquidationProtectionSubData as well, since it is copy paste
169
+ // ! Double check before changing
167
170
  export const makerLeverageManagementWithoutSubProxy = {
168
171
  encode(
169
172
  vaultId: number,
@@ -184,6 +187,28 @@ export const makerLeverageManagementWithoutSubProxy = {
184
187
  },
185
188
  };
186
189
 
190
+ export const makerLiquidationProtectionSubData = {
191
+ encode(
192
+ vaultId: number,
193
+ targetRatio: number,
194
+ daiAddr?: EthereumAddress,
195
+ ): SubData {
196
+ const encodedVaultId = AbiCoder.encodeParameter('uint256', vaultId);
197
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
198
+ const encodedDaiAddr = AbiCoder.encodeParameter('address', daiAddr || getAssetInfo('DAI', 1).address);
199
+
200
+ return [encodedVaultId, encodedTargetRatio, encodedDaiAddr];
201
+ },
202
+ decode(subData: SubData): { vaultId: number, targetRatio: number, daiAddr: string } {
203
+ const vaultId = +AbiCoder.decodeParameter('uint256', subData[0])!.toString();
204
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[1]) as any as string);
205
+ const daiAddr = AbiCoder.decodeParameter('address', subData[2])!.toString();
206
+
207
+ return { vaultId, targetRatio, daiAddr };
208
+ },
209
+ };
210
+
211
+
187
212
  /**
188
213
  __ __ ______ __ __ __ .___________.____ ____ ____ ____ __
189
214
  | | | | / __ \ | | | | | | | |\ \ / / \ \ / / /_ |
@@ -207,6 +232,30 @@ export const liquityLeverageManagementSubData = {
207
232
  return { targetRatio };
208
233
  },
209
234
  };
235
+ export const liquityLeverageManagementSubDataWithoutSubProxy = {
236
+ encode(
237
+ targetRatio: number,
238
+ ratioState: RatioState,
239
+ ): SubData {
240
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
241
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
242
+
243
+ const isRepay = ratioState === RatioState.UNDER;
244
+ const collActionType = isRepay ? CollActionType.WITHDRAW : CollActionType.SUPPLY;
245
+ const debtActionType = isRepay ? DebtActionType.PAYBACK : DebtActionType.BORROW;
246
+
247
+ const collActionTypeEncoded = AbiCoder.encodeParameter('uint8', collActionType);
248
+ const debtActionTypeEncoded = AbiCoder.encodeParameter('uint8', debtActionType);
249
+
250
+ return [encodedRatioState, encodedTargetRatio, collActionTypeEncoded, debtActionTypeEncoded];
251
+ },
252
+ decode(subData: SubData): { targetRatio: number, ratioState: RatioState } {
253
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[0]) as any as RatioState;
254
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[1]) as any as string);
255
+
256
+ return { targetRatio, ratioState };
257
+ },
258
+ };
210
259
  export const liquityCloseSubData = {
211
260
  encode(
212
261
  closeToAssetAddr: EthereumAddress,
@@ -510,6 +559,33 @@ export const aaveV2LeverageManagementSubData = {
510
559
  return { targetRatio };
511
560
  },
512
561
  };
562
+ export const aaveV2LeverageManagementSubDataWithoutSubProxy = {
563
+ encode(
564
+ market: EthereumAddress,
565
+ targetRatio: number,
566
+ ratioState: RatioState,
567
+ ): SubData {
568
+ const encodedMarket = AbiCoder.encodeParameter('address', market);
569
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
570
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
571
+
572
+ const isBoost = ratioState === RatioState.OVER;
573
+
574
+ if (isBoost) {
575
+ const enableAsCollEncoded = AbiCoder.encodeParameter('uint256', 1);
576
+ return [encodedMarket, encodedTargetRatio, encodedRatioState, enableAsCollEncoded];
577
+ }
578
+
579
+ return [encodedMarket, encodedTargetRatio, encodedRatioState];
580
+ },
581
+ decode(subData: SubData): { market: EthereumAddress, targetRatio: number, ratioState: RatioState } {
582
+ const market = AbiCoder.decodeParameter('address', subData[0]) as any as EthereumAddress;
583
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[1]) as any as string);
584
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[2]) as any as RatioState;
585
+
586
+ return { market, targetRatio, ratioState };
587
+ },
588
+ };
513
589
 
514
590
  /**
515
591
  ___ ___ ____ ____ _______ ____ ____ ____
@@ -527,6 +603,9 @@ export const aaveV3LeverageManagementSubData = {
527
603
  return { targetRatio };
528
604
  },
529
605
  };
606
+
607
+ // ! Any change here will PROBABLY require a change in aaveV3LiquidationProtectionSubData as well
608
+ // ! Double check before changing. Liquidation protection is using Generic encoding for both - EOA and SW
530
609
  export const aaveV3LeverageManagementSubDataWithoutSubProxy = {
531
610
  encode(
532
611
  targetRatio: number,
@@ -554,6 +633,30 @@ export const aaveV3LeverageManagementSubDataWithoutSubProxy = {
554
633
  return { targetRatio, ratioState };
555
634
  },
556
635
  };
636
+
637
+ export const aaveV3LiquidationProtectionSubData = {
638
+ encode(
639
+ targetRatio: number,
640
+ ratioState: RatioState,
641
+ market: EthereumAddress,
642
+ user: EthereumAddress,
643
+ ): SubData {
644
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
645
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
646
+ const encodedMarket = AbiCoder.encodeParameter('address', market);
647
+ const encodedUser = AbiCoder.encodeParameter('address', user);
648
+
649
+ return [encodedTargetRatio, encodedRatioState, encodedMarket, encodedUser];
650
+ },
651
+ decode(subData: SubData): { targetRatio: number, ratioState: RatioState } {
652
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[0]) as any as string);
653
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[1]) as any as RatioState;
654
+
655
+ return { targetRatio, ratioState };
656
+ },
657
+ };
658
+
659
+
557
660
  export const aaveV3LeverageManagementOnPriceGeneric = {
558
661
  encode(
559
662
  collAsset: EthereumAddress,
@@ -800,6 +903,9 @@ export const aaveV3LeverageManagementOnPriceSubData = {
800
903
  / _____ \ / _____ \ \ / | |____ \ / | |
801
904
  /__/ \__\ /__/ \__\ \__/ |_______| \__/ |_|
802
905
  */
906
+
907
+ // ! Any change here will PROBABLY require a change in aaveV4LiquidationProtectionSubData as well, since it is copy paste
908
+ // ! Double check before changing
803
909
  export const aaveV4LeverageManagementSubData = {
804
910
  encode: (
805
911
  spoke: EthereumAddress,
@@ -831,6 +937,39 @@ export const aaveV4LeverageManagementSubData = {
831
937
  };
832
938
  },
833
939
  };
940
+
941
+ export const aaveV4LiquidationProtectionSubData = {
942
+ encode: (
943
+ spoke: EthereumAddress,
944
+ owner: EthereumAddress,
945
+ ratioState: RatioState,
946
+ targetRatio: number,
947
+ ) => {
948
+ const spokeEncoded = AbiCoder.encodeParameter('address', spoke);
949
+ const ownerEncoded = AbiCoder.encodeParameter('address', owner);
950
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
951
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
952
+ // Add two empty slots for future addons (e.g tsi or slippage settings)
953
+ return [
954
+ spokeEncoded,
955
+ ownerEncoded,
956
+ ratioStateEncoded,
957
+ targetRatioEncoded,
958
+ EMPTY_SLOT,
959
+ EMPTY_SLOT,
960
+ ];
961
+ },
962
+ decode: (subData: SubData) => {
963
+ const spoke = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
964
+ const owner = AbiCoder.decodeParameter('address', subData[1]) as unknown as EthereumAddress;
965
+ const ratioState = Number(AbiCoder.decodeParameter('uint8', subData[2])) as RatioState;
966
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[3]) as any as string);
967
+ return {
968
+ spoke, owner, ratioState, targetRatio,
969
+ };
970
+ },
971
+ };
972
+
834
973
  export const aaveV4LeverageManagementOnPriceSubData = {
835
974
  encode: (
836
975
  spoke: EthereumAddress,
@@ -997,6 +1136,30 @@ export const compoundV2LeverageManagementSubData = {
997
1136
  return { targetRatio };
998
1137
  },
999
1138
  };
1139
+ export const compoundV2LeverageManagementSubDataWithoutSubProxy = {
1140
+ encode(
1141
+ targetRatio: number,
1142
+ ratioState: RatioState,
1143
+ ): SubData {
1144
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1145
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
1146
+
1147
+ const isBoost = ratioState === RatioState.OVER;
1148
+
1149
+ if (isBoost) {
1150
+ const enableAsCollEncoded = AbiCoder.encodeParameter('uint256', 1);
1151
+ return [encodedTargetRatio, encodedRatioState, enableAsCollEncoded];
1152
+ }
1153
+
1154
+ return [encodedTargetRatio, encodedRatioState];
1155
+ },
1156
+ decode(subData: SubData): { targetRatio: number, ratioState: RatioState } {
1157
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[0]) as any as string);
1158
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[1]) as any as RatioState;
1159
+
1160
+ return { targetRatio, ratioState };
1161
+ },
1162
+ };
1000
1163
 
1001
1164
  /**
1002
1165
  ______ ______ .___ ___. .______ ____ ____ ____
@@ -1006,70 +1169,59 @@ export const compoundV2LeverageManagementSubData = {
1006
1169
  | `----.| `--' | | | | | | | \ / ___) |
1007
1170
  \______| \______/ |__| |__| | _| \__/ |____/
1008
1171
  */
1009
- export const compoundV3LeverageManagementSubData = {
1172
+
1173
+ // ! Any change here will PROBABLY require a change in compoundV3LiquidationProtectionSubDataWithoutSubProxy as well, since it is copy paste
1174
+ // ! Double check before changing
1175
+ export const compoundV3LeverageManagementSubDataWithoutSubProxy = {
1010
1176
  encode(
1011
1177
  market: EthereumAddress,
1012
1178
  baseToken: EthereumAddress,
1013
- triggerRepayRatio: number,
1014
- triggerBoostRatio: number,
1015
- targetBoostRatio: number,
1016
- targetRepayRatio: number,
1017
- boostEnabled: boolean,
1018
- isEOA: boolean,
1179
+ targetRatio: number,
1180
+ ratioState: RatioState,
1019
1181
  ): SubData {
1020
- return [
1021
- market,
1022
- baseToken,
1023
- new Dec(triggerRepayRatio).mul(1e16).toString(),
1024
- new Dec(triggerBoostRatio).mul(1e16).toString(),
1025
- new Dec(targetBoostRatio).mul(1e16).toString(),
1026
- new Dec(targetRepayRatio).mul(1e16).toString(),
1027
- // @ts-ignore // TODO
1028
- boostEnabled, isEOA,
1029
- ];
1182
+ const encodedMarket = AbiCoder.encodeParameter('address', market);
1183
+ const encodedBaseToken = AbiCoder.encodeParameter('address', baseToken);
1184
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
1185
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1186
+ return [encodedMarket, encodedBaseToken, encodedRatioState, encodedTargetRatio];
1030
1187
  },
1031
- decode(subData: SubData): { targetRatio: number } {
1032
- const weiRatio = AbiCoder.decodeParameter('uint256', subData[3]) as any as string;
1033
- const targetRatio = weiToRatioPercentage(weiRatio);
1188
+ decode(subData: SubData): { market: EthereumAddress, baseToken: EthereumAddress, targetRatio: number, ratioState: RatioState } {
1189
+ const market = AbiCoder.decodeParameter('address', subData[0]) as any as EthereumAddress;
1190
+ const baseToken = AbiCoder.decodeParameter('address', subData[1]) as any as EthereumAddress;
1191
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[2]) as any as RatioState;
1192
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[3]) as any as string);
1034
1193
 
1035
- return { targetRatio };
1194
+ return {
1195
+ market, baseToken, targetRatio, ratioState,
1196
+ };
1036
1197
  },
1037
1198
  };
1038
- export const compoundV3L2LeverageManagementSubData = {
1199
+
1200
+ export const compoundV3LiquidationProtectionSubDataWithoutSubProxy = {
1039
1201
  encode(
1040
1202
  market: EthereumAddress,
1041
1203
  baseToken: EthereumAddress,
1042
- triggerRepayRatio: number,
1043
- triggerBoostRatio: number,
1044
- targetBoostRatio: number,
1045
- targetRepayRatio: number,
1046
- boostEnabled: boolean,
1047
- isEOA: boolean,
1048
- ): string {
1049
- let subInput = '0x';
1050
-
1051
- subInput = subInput.concat(market.slice(2));
1052
- subInput = subInput.concat(baseToken.slice(2));
1053
- subInput = subInput.concat(new Dec(triggerRepayRatio).mul(1e16).toHex().slice(2)
1054
- .padStart(32, '0'));
1055
- subInput = subInput.concat(new Dec(triggerBoostRatio).mul(1e16).toHex().slice(2)
1056
- .padStart(32, '0'));
1057
- subInput = subInput.concat(new Dec(targetBoostRatio).mul(1e16).toHex().slice(2)
1058
- .padStart(32, '0'));
1059
- subInput = subInput.concat(new Dec(targetRepayRatio).mul(1e16).toHex().slice(2)
1060
- .padStart(32, '0'));
1061
- subInput = subInput.concat(boostEnabled ? '01' : '00');
1062
- subInput = subInput.concat(isEOA ? '01' : '00');
1063
-
1064
- return subInput;
1204
+ targetRatio: number,
1205
+ ratioState: RatioState,
1206
+ ): SubData {
1207
+ const encodedMarket = AbiCoder.encodeParameter('address', market);
1208
+ const encodedBaseToken = AbiCoder.encodeParameter('address', baseToken);
1209
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
1210
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1211
+ return [encodedMarket, encodedBaseToken, encodedRatioState, encodedTargetRatio];
1065
1212
  },
1066
- decode(subData: SubData): { targetRatio: number } {
1067
- const ratioWei = AbiCoder.decodeParameter('uint256', subData[3]) as any as string;
1068
- const targetRatio = weiToRatioPercentage(ratioWei);
1213
+ decode(subData: SubData): { market: EthereumAddress, baseToken: EthereumAddress, targetRatio: number, ratioState: RatioState } {
1214
+ const market = AbiCoder.decodeParameter('address', subData[0]) as any as EthereumAddress;
1215
+ const baseToken = AbiCoder.decodeParameter('address', subData[1]) as any as EthereumAddress;
1216
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[2]) as any as RatioState;
1217
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[3]) as any as string);
1069
1218
 
1070
- return { targetRatio };
1219
+ return {
1220
+ market, baseToken, targetRatio, ratioState,
1221
+ };
1071
1222
  },
1072
1223
  };
1224
+
1073
1225
  export const compoundV3LeverageManagementOnPriceSubData = {
1074
1226
  encode(
1075
1227
  market: EthereumAddress,
@@ -1205,6 +1357,21 @@ export const exchangeLimitOrderSubData = {
1205
1357
  return { fromToken, toToken, amount };
1206
1358
  },
1207
1359
  };
1360
+ export const exchangeLimitOrderSubDataWithoutSubProxy = {
1361
+ encode(fromToken: EthereumAddress, toToken: EthereumAddress, amount: string): SubData {
1362
+ return [
1363
+ AbiCoder.encodeParameter('address', fromToken),
1364
+ AbiCoder.encodeParameter('address', toToken),
1365
+ AbiCoder.encodeParameter('uint256', amount),
1366
+ ];
1367
+ },
1368
+ decode: (subData: SubData, chainId: ChainId) => {
1369
+ const fromToken = AbiCoder.decodeParameter('address', subData[0])!.toString();
1370
+ const toToken = AbiCoder.decodeParameter('address', subData[1])!.toString();
1371
+ const amount = assetAmountInEth(AbiCoder.decodeParameter('uint256', subData[2])!.toString(), getAssetInfoByAddress(fromToken, chainId).symbol);
1372
+ return { fromToken, toToken, amount };
1373
+ },
1374
+ };
1208
1375
 
1209
1376
  /**
1210
1377
  _______..______ ___ .______ __ ___
@@ -1222,6 +1389,9 @@ export const sparkLeverageManagementSubData = {
1222
1389
  return { targetRatio };
1223
1390
  },
1224
1391
  };
1392
+
1393
+ // ! Any change here will PROBABLY require a change in sparkLiquidationProtectionSubData as well, since it is copy paste
1394
+ // ! Double check before changing
1225
1395
  export const sparkLeverageManagementSubDataWithoutSubProxy = {
1226
1396
  encode(
1227
1397
  targetRatio: number,
@@ -1241,6 +1411,28 @@ export const sparkLeverageManagementSubDataWithoutSubProxy = {
1241
1411
  return { targetRatio, ratioState };
1242
1412
  },
1243
1413
  };
1414
+
1415
+ export const sparkLiquidationProtectionSubData = {
1416
+ encode(
1417
+ targetRatio: number,
1418
+ ratioState: RatioState,
1419
+ ): SubData {
1420
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1421
+ const encodedRatioState = AbiCoder.encodeParameter('uint8', ratioState);
1422
+ const encodedUseDefaultMarket = AbiCoder.encodeParameter('bool', true);
1423
+ const encodedUseOnBehalf = AbiCoder.encodeParameter('bool', false);
1424
+
1425
+ return [encodedTargetRatio, encodedRatioState, encodedUseDefaultMarket, encodedUseOnBehalf];
1426
+ },
1427
+ decode(subData: SubData): { targetRatio: number, ratioState: RatioState } {
1428
+ const targetRatio = weiToRatioPercentage(AbiCoder.decodeParameter('uint256', subData[0]) as any as string);
1429
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[1]) as any as RatioState;
1430
+
1431
+ return { targetRatio, ratioState };
1432
+ },
1433
+ };
1434
+
1435
+
1244
1436
  export const sparkCloseGenericSubData = {
1245
1437
  encode(
1246
1438
  collAsset: EthereumAddress,
@@ -1455,6 +1647,9 @@ export const crvUSDPaybackSubData = {
1455
1647
  | | | | | `--' | | |\ \----.| | | | | | | `--' |
1456
1648
  |__| |__| \______/ | _| `._____|| _| |__| |__| \______/
1457
1649
  */
1650
+
1651
+ // ! Any change here will PROBABLY require a change in morphoBlueLiquidationProtectionSubData as well, since it is copy paste
1652
+ // ! Double check before changing
1458
1653
  export const morphoBlueLeverageManagementSubData = {
1459
1654
  encode: (
1460
1655
  loanToken: EthereumAddress,
@@ -1499,6 +1694,53 @@ export const morphoBlueLeverageManagementSubData = {
1499
1694
  };
1500
1695
  },
1501
1696
  };
1697
+
1698
+ export const morphoBlueLiquidationProtectionSubData = {
1699
+ encode: (
1700
+ loanToken: EthereumAddress,
1701
+ collToken: EthereumAddress,
1702
+ oracle: EthereumAddress,
1703
+ irm: EthereumAddress,
1704
+ lltv: string,
1705
+ ratioState: RatioState,
1706
+ targetRatio: number,
1707
+ user: EthereumAddress,
1708
+ isEOA: boolean,
1709
+ ) => {
1710
+ const loanTokenEncoded = AbiCoder.encodeParameter('address', loanToken);
1711
+ const collTokenEncoded = AbiCoder.encodeParameter('address', collToken);
1712
+ const oracleEncoded = AbiCoder.encodeParameter('address', oracle);
1713
+ const irmEncoded = AbiCoder.encodeParameter('address', irm);
1714
+ const lltvEncoded = AbiCoder.encodeParameter('uint256', lltv);
1715
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
1716
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1717
+ const userEncoded = AbiCoder.encodeParameter('address', user);
1718
+ const isEOAEncoded = AbiCoder.encodeParameter('bool', isEOA);
1719
+ return [loanTokenEncoded, collTokenEncoded, oracleEncoded, irmEncoded, lltvEncoded, ratioStateEncoded, targetRatioEncoded, userEncoded, isEOAEncoded];
1720
+ },
1721
+ decode: (subData: SubData) => {
1722
+ const loanToken = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
1723
+ const collToken = AbiCoder.decodeParameter('address', subData[1]) as any as EthereumAddress;
1724
+ const oracle = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
1725
+ const irm = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
1726
+ const lltv = AbiCoder.decodeParameter('uint256', subData[4]) as any as EthereumAddress;
1727
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[6]) as any as EthereumAddress;
1728
+ const user = AbiCoder.decodeParameter('address', subData[7]) as any as EthereumAddress;
1729
+ const targetRatio = weiToRatioPercentage(weiRatio);
1730
+
1731
+ return {
1732
+ loanToken,
1733
+ collToken,
1734
+ oracle,
1735
+ irm,
1736
+ lltv,
1737
+ user,
1738
+ targetRatio,
1739
+ };
1740
+ },
1741
+ };
1742
+
1743
+
1502
1744
  export const morphoBlueLeverageManagementOnPriceSubData = {
1503
1745
  encode(
1504
1746
  loanToken: EthereumAddress,
@@ -1587,6 +1829,8 @@ _______ __ __ __ __ _______
1587
1829
  | | | `----.| `--' | | | | '--' |
1588
1830
  |__| |_______| \______/ |__| |_______/
1589
1831
  */
1832
+ // ! Any change here will PROBABLY require a change in fluidLeverageManagementSubData as well, since it is copy paste
1833
+ // ! Double check before changing
1590
1834
  export const fluidLeverageManagementSubData = {
1591
1835
  encode: (
1592
1836
  nftId: string,
@@ -1629,3 +1873,45 @@ export const fluidLeverageManagementSubData = {
1629
1873
  };
1630
1874
  },
1631
1875
  };
1876
+
1877
+ export const fluidLiquidationProtectionSubData = {
1878
+ encode: (
1879
+ nftId: string,
1880
+ vault: EthereumAddress,
1881
+ ratioState: RatioState,
1882
+ targetRatio: number,
1883
+ ) => {
1884
+ const nftIdEncoded = AbiCoder.encodeParameter('uint256', nftId);
1885
+ const vaultEncoded = AbiCoder.encodeParameter('address', vault);
1886
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
1887
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
1888
+ const wrapEthEncoded = AbiCoder.encodeParameter('bool', true);
1889
+
1890
+ const collActionType = CollActionType.WITHDRAW;
1891
+ const debtActionType = DebtActionType.PAYBACK;
1892
+
1893
+ const collActionTypeEncoded = AbiCoder.encodeParameter('uint8', collActionType);
1894
+ const debtActionTypeEncoded = AbiCoder.encodeParameter('uint8', debtActionType);
1895
+
1896
+ return [
1897
+ nftIdEncoded,
1898
+ vaultEncoded,
1899
+ ratioStateEncoded,
1900
+ targetRatioEncoded,
1901
+ wrapEthEncoded,
1902
+ collActionTypeEncoded,
1903
+ debtActionTypeEncoded,
1904
+ ];
1905
+ },
1906
+ decode: (subData: SubData) => {
1907
+ const nftId = AbiCoder.decodeParameter('uint256', subData[0]) as any as string;
1908
+ const vault = AbiCoder.decodeParameter('address', subData[1]) as unknown as EthereumAddress;
1909
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[2]) as any as RatioState;
1910
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[3]) as any as string;
1911
+ const targetRatio = weiToRatioPercentage(weiRatio);
1912
+
1913
+ return {
1914
+ nftId, vault, ratioState, targetRatio,
1915
+ };
1916
+ },
1917
+ };
@@ -2,7 +2,7 @@ import { expect } from 'chai';
2
2
  import { getAssetInfo } from '@defisaver/tokens';
3
3
 
4
4
  import type { EthereumAddress } from '../types';
5
- import { ChainId, ProtocolIdentifiers, RatioState } from '../types/enums';
5
+ import { Bundles, ChainId, ProtocolIdentifiers, RatioState } from '../types/enums';
6
6
 
7
7
  import '../configuration';
8
8
  import {
@@ -11,6 +11,7 @@ import {
11
11
  compareAddresses,
12
12
  encodeSubId,
13
13
  ethToWeth,
14
+ getCompoundV3LeverageManagementBundleId,
14
15
  getRatioStateInfoForAaveCloseStrategy,
15
16
  isAddress,
16
17
  isDefined,
@@ -369,4 +370,34 @@ describe('Feature: utils.ts', () => {
369
370
  });
370
371
  });
371
372
  });
373
+
374
+ describe('When testing utils.getCompoundV3LeverageManagementBundleId()', () => {
375
+ // Mainnet uses the V2 bundle ids; L2s use the original bundle ids.
376
+ const examples: Array<[number, [network: ChainId, isEOA: boolean, isBoost: boolean]]> = [
377
+ [Bundles.MainnetIds.COMP_V3_SW_REPAY_V2_BUNDLE, [ChainId.Ethereum, false, false]],
378
+ [Bundles.MainnetIds.COMP_V3_SW_BOOST_V2_BUNDLE, [ChainId.Ethereum, false, true]],
379
+ [Bundles.MainnetIds.COMP_V3_EOA_REPAY_V2_BUNDLE, [ChainId.Ethereum, true, false]],
380
+ [Bundles.MainnetIds.COMP_V3_EOA_BOOST_V2_BUNDLE, [ChainId.Ethereum, true, true]],
381
+
382
+ [Bundles.BaseIds.COMP_V3_SW_REPAY_BUNDLE, [ChainId.Base, false, false]],
383
+ [Bundles.BaseIds.COMP_V3_SW_BOOST_BUNDLE, [ChainId.Base, false, true]],
384
+ [Bundles.BaseIds.COMP_V3_EOA_REPAY, [ChainId.Base, true, false]],
385
+ [Bundles.BaseIds.COMP_V3_EOA_BOOST, [ChainId.Base, true, true]],
386
+
387
+ [Bundles.ArbitrumIds.COMP_V3_SW_REPAY_BUNDLE, [ChainId.Arbitrum, false, false]],
388
+ [Bundles.ArbitrumIds.COMP_V3_SW_BOOST_BUNDLE, [ChainId.Arbitrum, false, true]],
389
+ [Bundles.ArbitrumIds.COMP_V3_EOA_REPAY, [ChainId.Arbitrum, true, false]],
390
+ [Bundles.ArbitrumIds.COMP_V3_EOA_BOOST, [ChainId.Arbitrum, true, true]],
391
+ ];
392
+
393
+ examples.forEach(([expected, actual]) => {
394
+ it(`Given ${actual} should return expected value: ${expected}`, () => {
395
+ expect(getCompoundV3LeverageManagementBundleId(...actual)).to.equal(expected);
396
+ });
397
+ });
398
+
399
+ it(`Given ${ChainId.Optimism} (unsupported) should throw an error`, () => {
400
+ expect(() => getCompoundV3LeverageManagementBundleId(ChainId.Optimism, false, false)).to.throw(Error);
401
+ });
402
+ });
372
403
  });
@@ -5,6 +5,7 @@ import { getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
5
5
 
6
6
  import type { EthereumAddress } from '../types';
7
7
  import {
8
+ Bundles,
8
9
  ChainId, CloseStrategyType, CloseToAssetType, RatioState,
9
10
  } from '../types/enums';
10
11
 
@@ -171,4 +172,34 @@ export function getStopLossAndTakeProfitTypeByCloseStrategyType(
171
172
  default:
172
173
  throw new Error('CloseStrategyType not supported');
173
174
  }
174
- }
175
+ }
176
+
177
+ export function getBundleIdsByNetwork(network: ChainId) {
178
+ switch (Number(network)) {
179
+ case ChainId.Ethereum:
180
+ return Bundles.MainnetIds;
181
+ case ChainId.Arbitrum:
182
+ return Bundles.ArbitrumIds;
183
+ case ChainId.Base:
184
+ return Bundles.BaseIds;
185
+ default:
186
+ throw new Error(`Unsupported network ${network}`);
187
+ }
188
+ }
189
+
190
+ // Mainnet uses the V2 bundle ids; L2s use the original bundle ids.
191
+ export function getCompoundV3LeverageManagementBundleId(network: ChainId, isEOA: boolean, isBoost: boolean): number {
192
+ switch (Number(network)) {
193
+ case ChainId.Ethereum:
194
+ if (isEOA) return isBoost ? Bundles.MainnetIds.COMP_V3_EOA_BOOST_V2_BUNDLE : Bundles.MainnetIds.COMP_V3_EOA_REPAY_V2_BUNDLE;
195
+ return isBoost ? Bundles.MainnetIds.COMP_V3_SW_BOOST_V2_BUNDLE : Bundles.MainnetIds.COMP_V3_SW_REPAY_V2_BUNDLE;
196
+ case ChainId.Base:
197
+ if (isEOA) return isBoost ? Bundles.BaseIds.COMP_V3_EOA_BOOST : Bundles.BaseIds.COMP_V3_EOA_REPAY;
198
+ return isBoost ? Bundles.BaseIds.COMP_V3_SW_BOOST_BUNDLE : Bundles.BaseIds.COMP_V3_SW_REPAY_BUNDLE;
199
+ case ChainId.Arbitrum:
200
+ if (isEOA) return isBoost ? Bundles.ArbitrumIds.COMP_V3_EOA_BOOST : Bundles.ArbitrumIds.COMP_V3_EOA_REPAY;
201
+ return isBoost ? Bundles.ArbitrumIds.COMP_V3_SW_BOOST_BUNDLE : Bundles.ArbitrumIds.COMP_V3_SW_REPAY_BUNDLE;
202
+ default:
203
+ throw new Error(`Compound V3 leverage management is not supported on network ${network}`);
204
+ }
205
+ }
@@ -153,6 +153,8 @@ export namespace Strategies {
153
153
  EoaRepayOnPrice = 'eoa-repay-on-price',
154
154
  CollateralSwitch = 'collateral-switch',
155
155
  EoaCollateralSwitch = 'eoa-collateral-switch',
156
+ LiquidationProtection = 'liquidation-protection',
157
+ EoaLiquidationProtection = 'eoa-liquidation-protection',
156
158
  }
157
159
  export enum IdOverrides {
158
160
  TakeProfit = 'take-profit',
@@ -164,6 +166,8 @@ export namespace Strategies {
164
166
  EoaLeverageManagement = 'leverage-management-eoa',
165
167
  LeverageManagementOnPrice = 'leverage-management-on-price',
166
168
  EoaLeverageManagementOnPrice = 'leverage-management-on-price-eoa',
169
+ LiquidationProtection = 'liquidation-protection',
170
+ EoaLiquidationProtection = 'liquidation-protection-eoa',
167
171
  }
168
172
  }
169
173
 
@@ -240,6 +244,17 @@ export namespace Bundles {
240
244
  AAVE_V4_EOA_REPAY_ON_PRICE = 68,
241
245
  AAVE_V4_EOA_BOOST_ON_PRICE = 69,
242
246
  AAVE_V4_EOA_CLOSE = 70,
247
+ AAVE_V3_SW_LIQUIDATION_PROTECTION = 71,
248
+ SPARK_SW_LIQUIDATION_PROTECTION = 72,
249
+ MAKER_SW_LIQUIDATION_PROTECTION = 75,
250
+ FLUID_T1_SW_LIQUIDATION_PROTECTION = 76,
251
+ AAVE_V4_SW_LIQUIDATION_PROTECTION = 77,
252
+ MORPHO_BLUE_SW_LIQUIDATION_PROTECTION = 78,
253
+ AAVE_V3_EOA_LIQUIDATION_PROTECTION = 79,
254
+ AAVE_V4_EOA_LIQUIDATION_PROTECTION = 80,
255
+ MORPHO_BLUE_EOA_LIQUIDATION_PROTECTION = 81,
256
+ COMP_V3_SW_LIQUIDATION_PROTECTION = 82,
257
+ COMP_V3_EOA_LIQUIDATION_PROTECTION = 83,
243
258
  }
244
259
 
245
260
  export enum OptimismIds {
@@ -254,6 +269,8 @@ export namespace Bundles {
254
269
  AAVE_V3_EOA_REPAY_ON_PRICE = 8,
255
270
  AAVE_V3_EOA_BOOST_ON_PRICE = 9,
256
271
  AAVE_V3_EOA_CLOSE = 10,
272
+ AAVE_V3_SW_LIQUIDATION_PROTECTION = 11,
273
+ AAVE_V3_EOA_LIQUIDATION_PROTECTION = 12,
257
274
  }
258
275
 
259
276
  export enum BaseIds {
@@ -284,6 +301,12 @@ export namespace Bundles {
284
301
  AAVE_V3_EOA_BOOST_ON_PRICE = 26,
285
302
  AAVE_V3_EOA_CLOSE = 27,
286
303
  MORPHO_BLUE_CLOSE = 28,
304
+ AAVE_V3_SW_LIQUIDATION_PROTECTION = 29,
305
+ FLUID_T1_SW_LIQUIDATION_PROTECTION = 30,
306
+ COMP_V3_SW_LIQUIDATION_PROTECTION = 32,
307
+ COMP_V3_EOA_LIQUIDATION_PROTECTION = 33,
308
+ AAVE_V3_EOA_LIQUIDATION_PROTECTION = 34,
309
+ MORPHO_BLUE_SW_LIQUIDATION_PROTECTION = 35,
287
310
  }
288
311
 
289
312
  export enum ArbitrumIds {
@@ -316,7 +339,12 @@ export namespace Bundles {
316
339
  MORPHO_BLUE_EOA_REPAY = 26,
317
340
  MORPHO_BLUE_EOA_BOOST = 27,
318
341
  MORPHO_BLUE_CLOSE = 28,
342
+ AAVE_V3_SW_LIQUIDATION_PROTECTION = 29,
343
+ FLUID_T1_SW_LIQUIDATION_PROTECTION = 30,
344
+ MORPHO_BLUE_SW_LIQUIDATION_PROTECTION = 31,
345
+ COMP_V3_SW_LIQUIDATION_PROTECTION = 32,
346
+ COMP_V3_EOA_LIQUIDATION_PROTECTION = 33,
347
+ AAVE_V3_EOA_LIQUIDATION_PROTECTION = 34,
348
+ MORPHO_BLUE_EOA_LIQUIDATION_PROTECTION = 35,
319
349
  }
320
350
  }
321
-
322
-