@defisaver/automation-sdk 3.2.0 → 3.2.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 (41) hide show
  1. package/.env +4 -5
  2. package/cjs/automation/private/StrategiesAutomation.js +5 -6
  3. package/cjs/constants/index.js +70 -0
  4. package/cjs/services/strategiesService.js +174 -0
  5. package/cjs/services/strategySubService.d.ts +11 -1
  6. package/cjs/services/strategySubService.js +42 -1
  7. package/cjs/services/subDataService.d.ts +63 -1
  8. package/cjs/services/subDataService.js +195 -1
  9. package/cjs/services/triggerService.d.ts +43 -0
  10. package/cjs/services/triggerService.js +81 -1
  11. package/cjs/services/utils.d.ts +6 -1
  12. package/cjs/services/utils.js +52 -1
  13. package/cjs/types/contracts/generated/SubStorage.d.ts +4 -0
  14. package/cjs/types/enums.d.ts +45 -5
  15. package/cjs/types/enums.js +45 -1
  16. package/cjs/types/index.d.ts +26 -2
  17. package/esm/automation/private/StrategiesAutomation.js +5 -6
  18. package/esm/constants/index.js +70 -0
  19. package/esm/services/strategiesService.js +172 -1
  20. package/esm/services/strategySubService.d.ts +11 -1
  21. package/esm/services/strategySubService.js +43 -2
  22. package/esm/services/subDataService.d.ts +63 -1
  23. package/esm/services/subDataService.js +195 -1
  24. package/esm/services/triggerService.d.ts +43 -0
  25. package/esm/services/triggerService.js +80 -0
  26. package/esm/services/utils.d.ts +6 -1
  27. package/esm/services/utils.js +50 -1
  28. package/esm/types/contracts/generated/SubStorage.d.ts +4 -0
  29. package/esm/types/enums.d.ts +45 -5
  30. package/esm/types/enums.js +44 -0
  31. package/esm/types/index.d.ts +26 -2
  32. package/package.json +3 -5
  33. package/src/automation/private/StrategiesAutomation.ts +5 -5
  34. package/src/constants/index.ts +70 -0
  35. package/src/services/strategiesService.ts +224 -1
  36. package/src/services/strategySubService.ts +111 -1
  37. package/src/services/subDataService.ts +271 -2
  38. package/src/services/triggerService.ts +125 -0
  39. package/src/services/utils.ts +60 -1
  40. package/src/types/enums.ts +44 -0
  41. package/src/types/index.ts +34 -1
@@ -3,6 +3,7 @@ import { getAssetInfo } from '@defisaver/tokens';
3
3
 
4
4
  import type { OrderType } from '../types/enums';
5
5
  import {
6
+ CloseStrategyType, CloseToAssetType,
6
7
  Bundles, ChainId, RatioState, Strategies,
7
8
  } from '../types/enums';
8
9
  import type { EthereumAddress, StrategyOrBundleIds } from '../types';
@@ -11,7 +12,9 @@ import { STRATEGY_IDS } from '../constants';
11
12
 
12
13
  import * as subDataService from './subDataService';
13
14
  import * as triggerService from './triggerService';
14
- import { compareAddresses, requireAddress, requireAddresses } from './utils';
15
+ import {
16
+ compareAddresses, getCloseStrategyType, requireAddress, requireAddresses,
17
+ } from './utils';
15
18
 
16
19
  export const makerEncode = {
17
20
  repayFromSavings(
@@ -519,6 +522,113 @@ export const morphoBlueEncode = {
519
522
  else strategyOrBundleId = isEOA ? Bundles.MainnetIds.MORPHO_BLUE_EOA_REPAY : Bundles.MainnetIds.MORPHO_BLUE_REPAY;
520
523
  const isBundle = true;
521
524
 
525
+ return [strategyOrBundleId, isBundle, triggerData, subData];
526
+ },
527
+ leverageManagementOnPrice(
528
+ strategyOrBundleId: number,
529
+ isBundle: boolean = true,
530
+ loanToken: EthereumAddress,
531
+ collToken: EthereumAddress,
532
+ oracle: EthereumAddress,
533
+ irm: EthereumAddress,
534
+ lltv: string,
535
+ user: EthereumAddress,
536
+ targetRatio: number,
537
+ price: number,
538
+ priceState: RatioState,
539
+ ) {
540
+ const subData = subDataService.morphoBlueLeverageManagementOnPriceSubData.encode(loanToken, collToken, oracle, irm, lltv, targetRatio, user);
541
+ const triggerData = triggerService.morphoBluePriceTrigger.encode(oracle, collToken, loanToken, price, priceState);
542
+ return [strategyOrBundleId, isBundle, triggerData, subData];
543
+ },
544
+ };
545
+
546
+ export const liquityV2Encode = {
547
+ leverageManagement(
548
+ market: EthereumAddress,
549
+ troveId: string,
550
+ collToken: EthereumAddress,
551
+ boldToken: EthereumAddress,
552
+ ratioState: RatioState,
553
+ targetRatio: number,
554
+ triggerRatio: number,
555
+ strategyOrBundleId: number,
556
+ ) {
557
+ const isBundle = true;
558
+ const subData = subDataService.liquityV2LeverageManagementSubData.encode(market, troveId, collToken, boldToken, ratioState, targetRatio);
559
+ const triggerData = triggerService.liquityV2RatioTrigger.encode(market, troveId, triggerRatio, ratioState);
560
+
561
+ return [strategyOrBundleId, isBundle, triggerData, subData];
562
+ },
563
+ closeOnPrice(
564
+ strategyOrBundleId: number,
565
+ market: EthereumAddress,
566
+ troveId: string,
567
+ collToken: EthereumAddress,
568
+ boldToken: EthereumAddress,
569
+ stopLossPrice: number = 0,
570
+ stopLossType: CloseToAssetType = CloseToAssetType.DEBT,
571
+ takeProfitPrice: number = 0,
572
+ takeProfitType: CloseToAssetType = CloseToAssetType.COLLATERAL,
573
+ ) {
574
+ const isBundle = true;
575
+ const closeType = getCloseStrategyType(stopLossPrice, stopLossType, takeProfitPrice, takeProfitType);
576
+
577
+ const subData = subDataService.liquityV2CloseSubData.encode(market, troveId, collToken, boldToken, closeType);
578
+ const triggerData = triggerService.closePriceTrigger.encode(collToken, stopLossPrice, takeProfitPrice);
579
+
580
+ return [strategyOrBundleId, isBundle, triggerData, subData];
581
+ },
582
+ leverageManagementOnPrice(
583
+ strategyOrBundleId: number,
584
+ market: EthereumAddress,
585
+ price: number,
586
+ state: RatioState,
587
+ troveId: string,
588
+ collToken: EthereumAddress,
589
+ boldToken: EthereumAddress,
590
+ targetRatio: number,
591
+ isRepayOnPrice: boolean,
592
+ ) {
593
+ const subDataEncoded = subDataService.liquityV2LeverageManagementOnPriceSubData.encode(
594
+ market, troveId, collToken, boldToken, targetRatio, isRepayOnPrice,
595
+ );
596
+
597
+ const triggerDataEncoded = triggerService.liquityV2QuotePriceTrigger.encode(market, price, state);
598
+ const isBundle = true;
599
+ return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
600
+ },
601
+ payback(
602
+ market: EthereumAddress,
603
+ troveId: string,
604
+ boldToken: EthereumAddress,
605
+ targetRatio: number,
606
+ ratioState: RatioState,
607
+ triggerRatio: number,
608
+ ) {
609
+ const strategyId = Strategies.MainnetIds.LIQUITY_V2_PAYBACK;
610
+ const isBundle = false;
611
+
612
+ const subData = subDataService.liquityV2PaybackSubData.encode(market, troveId, boldToken, targetRatio, ratioState);
613
+ const triggerData = triggerService.liquityV2RatioTrigger.encode(market, troveId, triggerRatio, ratioState);
614
+
615
+ return [strategyId, isBundle, triggerData, subData];
616
+ },
617
+ };
618
+
619
+ export const fluidEncode = {
620
+ leverageManagement(
621
+ nftId: string,
622
+ vault: EthereumAddress,
623
+ ratioState: RatioState,
624
+ targetRatio: number,
625
+ triggerRatio: number,
626
+ strategyOrBundleId: number,
627
+ ) {
628
+ const isBundle = true;
629
+ const subData = subDataService.fluidLeverageManagementSubData.encode(nftId, vault, ratioState, targetRatio);
630
+ const triggerData = triggerService.fluidRatioTrigger.encode(nftId, triggerRatio, ratioState);
631
+
522
632
  return [strategyOrBundleId, isBundle, triggerData, subData];
523
633
  },
524
634
  };
@@ -6,8 +6,10 @@ import { assetAmountInEth, getAssetInfo, getAssetInfoByAddress } from '@defisave
6
6
  import { otherAddresses } from '@defisaver/sdk';
7
7
 
8
8
  import type { SubData, EthereumAddress } from '../types';
9
- import type { OrderType } from '../types/enums';
10
- import { ChainId, RatioState } from '../types/enums';
9
+ import type { CloseStrategyType, OrderType } from '../types/enums';
10
+ import {
11
+ ChainId, CollActionType, DebtActionType, RatioState,
12
+ } from '../types/enums';
11
13
 
12
14
  import { AAVE_V3_VARIABLE_BORROW_RATE, ZERO_ADDRESS } from '../constants';
13
15
 
@@ -643,3 +645,270 @@ export const aaveV3LeverageManagementOnPriceSubData = {
643
645
  };
644
646
  },
645
647
  };
648
+
649
+ export const liquityV2LeverageManagementSubData = {
650
+ encode: (
651
+ market: EthereumAddress,
652
+ troveId: string,
653
+ collToken: EthereumAddress,
654
+ boldToken: EthereumAddress,
655
+ ratioState: RatioState,
656
+ targetRatio: number,
657
+ ) => {
658
+ const marketEncoded = AbiCoder.encodeParameter('address', market);
659
+ const troveIdEncoded = AbiCoder.encodeParameter('uint256', troveId);
660
+ const collTokenEncoded = AbiCoder.encodeParameter('address', collToken);
661
+ const boldTokenEncoded = AbiCoder.encodeParameter('address', boldToken);
662
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
663
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
664
+
665
+ const isRepay = ratioState === RatioState.UNDER;
666
+ const collActionType = isRepay ? CollActionType.WITHDRAW : CollActionType.SUPPLY;
667
+ const debtActionType = isRepay ? DebtActionType.PAYBACK : DebtActionType.BORROW;
668
+
669
+ const collActionTypeEncoded = AbiCoder.encodeParameter('uint8', collActionType);
670
+ const debtActionTypeEncoded = AbiCoder.encodeParameter('uint8', debtActionType);
671
+
672
+ return [
673
+ marketEncoded,
674
+ troveIdEncoded,
675
+ collTokenEncoded,
676
+ boldTokenEncoded,
677
+ ratioStateEncoded,
678
+ targetRatioEncoded,
679
+ collActionTypeEncoded,
680
+ debtActionTypeEncoded,
681
+ ];
682
+ },
683
+ decode: (subData: SubData) => {
684
+ const market = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
685
+ const troveId = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
686
+ const collToken = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
687
+ const boldToken = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
688
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[4]) as any as RatioState;
689
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[5]) as any as string;
690
+ const targetRatio = weiToRatioPercentage(weiRatio);
691
+
692
+ return {
693
+ market, troveId, collToken, boldToken, ratioState, targetRatio,
694
+ };
695
+ },
696
+ };
697
+
698
+ export const liquityV2CloseSubData = {
699
+ encode(
700
+ market: EthereumAddress,
701
+ troveId: string,
702
+ collToken: EthereumAddress,
703
+ boldToken: EthereumAddress,
704
+ closeType: CloseStrategyType,
705
+ ): SubData {
706
+ const marketEncoded = AbiCoder.encodeParameter('address', market);
707
+ const troveIdEncoded = AbiCoder.encodeParameter('uint256', troveId);
708
+ const collAddrEncoded = AbiCoder.encodeParameter('address', collToken);
709
+ const boldTokenEncoded = AbiCoder.encodeParameter('address', boldToken);
710
+ const wethAddress = getAssetInfo('WETH').address;
711
+ const wethAddressEncoded = AbiCoder.encodeParameter('address', wethAddress);
712
+ const gasCompensation = new Dec('0.0375').mul(1e18).toString();
713
+ const gasCompensationEncoded = AbiCoder.encodeParameter('uint256', gasCompensation);
714
+ const closeTypeEncoded = AbiCoder.encodeParameter('uint8', closeType);
715
+
716
+ return [
717
+ marketEncoded,
718
+ troveIdEncoded,
719
+ collAddrEncoded,
720
+ boldTokenEncoded,
721
+ wethAddressEncoded,
722
+ gasCompensationEncoded,
723
+ closeTypeEncoded,
724
+ ];
725
+ },
726
+ decode(subData: SubData): {
727
+ market: EthereumAddress,
728
+ troveId: string,
729
+ collToken: EthereumAddress,
730
+ boldToken: EthereumAddress,
731
+ closeType: CloseStrategyType,
732
+ } {
733
+ const market = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
734
+ const troveId = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
735
+ const collToken = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
736
+ const boldToken = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
737
+ // skip wethAddress and gasCompensation
738
+ const closeType = AbiCoder.decodeParameter('uint8', subData[6]) as any as CloseStrategyType;
739
+
740
+ return {
741
+ market, troveId, collToken, boldToken, closeType,
742
+ };
743
+ },
744
+ };
745
+
746
+ export const liquityV2LeverageManagementOnPriceSubData = {
747
+ encode(
748
+ market: EthereumAddress,
749
+ troveId: string,
750
+ collToken: EthereumAddress,
751
+ boldToken: EthereumAddress,
752
+ targetRatio: number,
753
+ isRepayOnPrice: boolean,
754
+ ): SubData {
755
+ const encodedMarket = AbiCoder.encodeParameter('address', market);
756
+ const encodedTroveId = AbiCoder.encodeParameter('uint256', troveId);
757
+ const encodedCollToken = AbiCoder.encodeParameter('address', collToken);
758
+ const encodedBoldToken = AbiCoder.encodeParameter('address', boldToken);
759
+ const encodedTargetRatio = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
760
+
761
+ const collActionType = isRepayOnPrice ? CollActionType.WITHDRAW : CollActionType.SUPPLY;
762
+ const debtActionType = isRepayOnPrice ? DebtActionType.PAYBACK : DebtActionType.BORROW;
763
+
764
+ const encodedCollActionType = AbiCoder.encodeParameter('uint8', collActionType);
765
+ const encodedDebtActionType = AbiCoder.encodeParameter('uint8', debtActionType);
766
+
767
+ return [
768
+ encodedMarket,
769
+ encodedTroveId,
770
+ encodedCollToken,
771
+ encodedBoldToken,
772
+ encodedTargetRatio,
773
+ encodedCollActionType,
774
+ encodedDebtActionType,
775
+ ];
776
+ },
777
+ decode(subData: SubData): {
778
+ market: EthereumAddress,
779
+ troveId: string,
780
+ collToken: EthereumAddress,
781
+ boldToken: EthereumAddress,
782
+ targetRatio: number,
783
+ } {
784
+ const market = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
785
+ const troveId = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
786
+ const collToken = AbiCoder.decodeParameter('address', subData[2]) as unknown as EthereumAddress;
787
+ const boldToken = AbiCoder.decodeParameter('address', subData[3]) as unknown as EthereumAddress;
788
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[4]) as any as string;
789
+ const targetRatio = weiToRatioPercentage(weiRatio);
790
+
791
+ return {
792
+ market, troveId, collToken, boldToken, targetRatio,
793
+ };
794
+ },
795
+ };
796
+ export const morphoBlueLeverageManagementOnPriceSubData = {
797
+ encode(
798
+ loanToken: EthereumAddress,
799
+ collToken: EthereumAddress,
800
+ oracle: EthereumAddress,
801
+ irm: EthereumAddress,
802
+ lltv: string,
803
+ targetRatio: number,
804
+ user: EthereumAddress,
805
+ ): SubData {
806
+ const loanTokenEncoded = AbiCoder.encodeParameter('address', loanToken);
807
+ const collTokenEncoded = AbiCoder.encodeParameter('address', collToken);
808
+ const oracleEncoded = AbiCoder.encodeParameter('address', oracle);
809
+ const irmEncoded = AbiCoder.encodeParameter('address', irm);
810
+ const lltvEncoded = AbiCoder.encodeParameter('uint256', lltv);
811
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
812
+ const userEncoded = AbiCoder.encodeParameter('address', user);
813
+ return [loanTokenEncoded, collTokenEncoded, oracleEncoded, irmEncoded, lltvEncoded, targetRatioEncoded, userEncoded];
814
+ },
815
+ decode(subData: SubData) {
816
+ const loanToken = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
817
+ const collToken = AbiCoder.decodeParameter('address', subData[1]) as any as EthereumAddress;
818
+ const oracle = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
819
+ const irm = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
820
+ const lltv = AbiCoder.decodeParameter('uint256', subData[4]) as any as EthereumAddress;
821
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[5]) as any as EthereumAddress;
822
+ const targetRatio = weiToRatioPercentage(weiRatio);
823
+ const user = AbiCoder.decodeParameter('address', subData[6]) as any as EthereumAddress;
824
+
825
+ return {
826
+ loanToken,
827
+ collToken,
828
+ oracle,
829
+ irm,
830
+ lltv,
831
+ targetRatio,
832
+ user,
833
+ };
834
+ },
835
+ };
836
+
837
+ export const liquityV2PaybackSubData = {
838
+ encode: (
839
+ market: EthereumAddress,
840
+ troveId: string,
841
+ boldToken: EthereumAddress,
842
+ targetRatio: number,
843
+ ratioState: RatioState,
844
+ ) => {
845
+ const marketEncoded = AbiCoder.encodeParameter('address', market);
846
+ const troveIdEncoded = AbiCoder.encodeParameter('uint256', troveId);
847
+ const boldTokenEncoded = AbiCoder.encodeParameter('address', boldToken);
848
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
849
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
850
+
851
+ return [
852
+ marketEncoded,
853
+ troveIdEncoded,
854
+ boldTokenEncoded,
855
+ targetRatioEncoded,
856
+ ratioStateEncoded,
857
+ ];
858
+ },
859
+ decode: (subData: SubData) => {
860
+ const market = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
861
+ const troveId = AbiCoder.decodeParameter('uint256', subData[1]) as any as string;
862
+ const boldToken = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
863
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[3]) as any as string;
864
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[4]) as any as RatioState;
865
+ const targetRatio = weiToRatioPercentage(weiRatio);
866
+
867
+ return {
868
+ market, troveId, boldToken, ratioState, targetRatio,
869
+ };
870
+ },
871
+ };
872
+
873
+ export const fluidLeverageManagementSubData = {
874
+ encode: (
875
+ nftId: string,
876
+ vault: EthereumAddress,
877
+ ratioState: RatioState,
878
+ targetRatio: number,
879
+ ) => {
880
+ const nftIdEncoded = AbiCoder.encodeParameter('uint256', nftId);
881
+ const vaultEncoded = AbiCoder.encodeParameter('address', vault);
882
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
883
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
884
+ const wrapEthEncoded = AbiCoder.encodeParameter('bool', true);
885
+
886
+ const isRepay = ratioState === RatioState.UNDER;
887
+ const collActionType = isRepay ? CollActionType.WITHDRAW : CollActionType.SUPPLY;
888
+ const debtActionType = isRepay ? DebtActionType.PAYBACK : DebtActionType.BORROW;
889
+
890
+ const collActionTypeEncoded = AbiCoder.encodeParameter('uint8', collActionType);
891
+ const debtActionTypeEncoded = AbiCoder.encodeParameter('uint8', debtActionType);
892
+
893
+ return [
894
+ nftIdEncoded,
895
+ vaultEncoded,
896
+ ratioStateEncoded,
897
+ targetRatioEncoded,
898
+ wrapEthEncoded,
899
+ collActionTypeEncoded,
900
+ debtActionTypeEncoded,
901
+ ];
902
+ },
903
+ decode: (subData: SubData) => {
904
+ const nftId = AbiCoder.decodeParameter('uint256', subData[0]) as any as string;
905
+ const vault = AbiCoder.decodeParameter('address', subData[1]) as unknown as EthereumAddress;
906
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[2]) as any as RatioState;
907
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[3]) as any as string;
908
+ const targetRatio = weiToRatioPercentage(weiRatio);
909
+
910
+ return {
911
+ nftId, vault, ratioState, targetRatio,
912
+ };
913
+ },
914
+ };
@@ -447,3 +447,128 @@ export const morphoBlueRatioTrigger = {
447
447
  };
448
448
  },
449
449
  };
450
+
451
+ export const liquityV2RatioTrigger = {
452
+ encode(
453
+ market: EthereumAddress,
454
+ troveId: string,
455
+ ratioPercentage: number,
456
+ ratioState: RatioState,
457
+ ) {
458
+ const ratioWei = ratioPercentageToWei(ratioPercentage);
459
+ return [AbiCoder.encodeParameters(['address', 'uint256', 'uint256', 'uint8'], [market, troveId, ratioWei, ratioState])];
460
+ },
461
+ decode(
462
+ triggerData: TriggerData,
463
+ ) {
464
+ const decodedData = AbiCoder.decodeParameters(['address', 'uint256', 'uint256', 'uint8'], triggerData[0]);
465
+ return {
466
+ market: decodedData[0] as EthereumAddress,
467
+ troveId: decodedData[1] as string,
468
+ ratio: weiToRatioPercentage(decodedData[2] as string),
469
+ ratioState: Number(decodedData[3]),
470
+ };
471
+ },
472
+ };
473
+
474
+ export const liquityV2QuotePriceTrigger = {
475
+ encode(
476
+ market: EthereumAddress,
477
+ price: number,
478
+ ratioState: RatioState,
479
+ ) {
480
+ // Price is always in 18 decimals
481
+ const _price = new Dec(price.toString()).mul(10 ** 18).floor().toString();
482
+ return [AbiCoder.encodeParameters(['address', 'uint256', 'uint8'], [market, _price, ratioState])];
483
+ },
484
+ decode(
485
+ triggerData: TriggerData,
486
+ ) {
487
+ const decodedData = AbiCoder.decodeParameters(['address', 'uint256', 'uint8'], triggerData[0]);
488
+ const price = new Dec(decodedData[1] as string).div(10 ** 18).toDP(18).toString();
489
+ return {
490
+ market: decodedData[0] as EthereumAddress,
491
+ price,
492
+ ratioState: Number(decodedData[2]),
493
+ };
494
+ },
495
+ };
496
+
497
+ export const closePriceTrigger = {
498
+ encode(
499
+ tokenAddr: EthereumAddress,
500
+ lowerPrice: number,
501
+ upperPrice: number,
502
+ ) {
503
+ const lowerPriceFormatted = new Dec(lowerPrice).mul(1e8).floor().toString();
504
+ const upperPriceFormatted = new Dec(upperPrice).mul(1e8).floor().toString();
505
+
506
+ return [
507
+ AbiCoder.encodeParameters(
508
+ ['address', 'uint256', 'uint256'],
509
+ [tokenAddr, lowerPriceFormatted, upperPriceFormatted],
510
+ ),
511
+ ];
512
+ },
513
+ decode(triggerData: TriggerData): {
514
+ tokenAddr: EthereumAddress,
515
+ lowerPrice: string,
516
+ upperPrice: string,
517
+ } {
518
+ const decodedData = AbiCoder.decodeParameters(['address', 'uint256', 'uint256'], triggerData[0]);
519
+ return {
520
+ tokenAddr: decodedData[0] as EthereumAddress,
521
+ lowerPrice: new Dec(decodedData[1] as string).div(1e8).toString(),
522
+ upperPrice: new Dec(decodedData[2] as string).div(1e8).toString(),
523
+ };
524
+ },
525
+ };
526
+ export const morphoBluePriceTrigger = {
527
+ encode(
528
+ oracle: EthereumAddress,
529
+ collateralToken: EthereumAddress,
530
+ loanToken: EthereumAddress,
531
+ price: number,
532
+ priceState: RatioState,
533
+ ) {
534
+ const _price = new Dec(price.toString()).mul(1e8).floor().toString();
535
+ return [
536
+ AbiCoder.encodeParameters(
537
+ ['address', 'address', 'address', 'uint256', 'uint8'],
538
+ [oracle, collateralToken, loanToken, _price, priceState]),
539
+ ];
540
+ },
541
+ decode(
542
+ triggerData: TriggerData,
543
+ ) {
544
+ const decodedData = AbiCoder.decodeParameters(['address', 'address', 'address', 'uint256', 'uint8'], triggerData[0]);
545
+ return {
546
+ oracle: decodedData[0] as EthereumAddress,
547
+ collateralToken: decodedData[1] as EthereumAddress,
548
+ loanToken: decodedData[2] as EthereumAddress,
549
+ price: new Dec(decodedData[3] as string).div(1e8).toString(),
550
+ priceState: Number(decodedData[4]),
551
+ };
552
+ },
553
+ };
554
+
555
+ export const fluidRatioTrigger = {
556
+ encode(
557
+ nftId: string,
558
+ ratioPercentage: number,
559
+ ratioState: RatioState,
560
+ ) {
561
+ const ratioWei = ratioPercentageToWei(ratioPercentage);
562
+ return [AbiCoder.encodeParameters(['uint256', 'uint256', 'uint8'], [nftId, ratioWei, ratioState])];
563
+ },
564
+ decode(
565
+ triggerData: TriggerData,
566
+ ) {
567
+ const decodedData = AbiCoder.decodeParameters(['uint256', 'uint256', 'uint8'], triggerData[0]);
568
+ return {
569
+ nftId: decodedData[0] as string,
570
+ ratio: weiToRatioPercentage(decodedData[1] as string),
571
+ ratioState: Number(decodedData[2]),
572
+ };
573
+ },
574
+ };
@@ -4,7 +4,9 @@ import AbiCoder from 'web3-eth-abi';
4
4
  import { getAssetInfo, getAssetInfoByAddress } from '@defisaver/tokens';
5
5
 
6
6
  import type { EthereumAddress } from '../types';
7
- import { ChainId, RatioState } from '../types/enums';
7
+ import {
8
+ ChainId, CloseStrategyType, CloseToAssetType, RatioState,
9
+ } from '../types/enums';
8
10
 
9
11
  export function isDefined<T>(value: T): value is NonNullable<T> {
10
12
  return value !== undefined && value !== null;
@@ -101,4 +103,61 @@ export function getRatioStateInfoForAaveCloseStrategy(
101
103
 
102
104
  export function getPositionId(...args: (number | string)[]) {
103
105
  return args.map(arg => arg.toString().toLowerCase().split(' ').join('_')).join('-');
106
+ }
107
+
108
+ export function getCloseStrategyType(
109
+ stopLossPrice: number,
110
+ stopLossType: CloseToAssetType,
111
+ takeProfitPrice: number,
112
+ takeProfitType: CloseToAssetType,
113
+ ): CloseStrategyType {
114
+ const isStopLoss = stopLossPrice > 0;
115
+ const isTakeProfit = takeProfitPrice > 0;
116
+
117
+ if (!isStopLoss && !isTakeProfit) {
118
+ throw new Error('CloseOnPrice: At least one price must be defined');
119
+ }
120
+
121
+ if (isStopLoss && isTakeProfit) {
122
+ if (stopLossType === CloseToAssetType.COLLATERAL && takeProfitType === CloseToAssetType.COLLATERAL) {
123
+ return CloseStrategyType.TAKE_PROFIT_AND_STOP_LOSS_IN_COLLATERAL;
124
+ } if (stopLossType === CloseToAssetType.COLLATERAL) {
125
+ return CloseStrategyType.TAKE_PROFIT_IN_DEBT_AND_STOP_LOSS_IN_COLLATERAL;
126
+ } if (takeProfitType === CloseToAssetType.COLLATERAL) {
127
+ return CloseStrategyType.TAKE_PROFIT_IN_COLLATERAL_AND_STOP_LOSS_IN_DEBT;
128
+ }
129
+ return CloseStrategyType.TAKE_PROFIT_AND_STOP_LOSS_IN_DEBT;
130
+ } if (isStopLoss) {
131
+ return stopLossType === CloseToAssetType.COLLATERAL
132
+ ? CloseStrategyType.STOP_LOSS_IN_COLLATERAL
133
+ : CloseStrategyType.STOP_LOSS_IN_DEBT;
134
+ }
135
+ return takeProfitType === CloseToAssetType.COLLATERAL
136
+ ? CloseStrategyType.TAKE_PROFIT_IN_COLLATERAL
137
+ : CloseStrategyType.TAKE_PROFIT_IN_DEBT;
138
+ }
139
+
140
+ export function getStopLossAndTakeProfitTypeByCloseStrategyType(
141
+ closeStrategyType: CloseStrategyType,
142
+ ): { stopLossType: CloseToAssetType | undefined, takeProfitType: CloseToAssetType | undefined } {
143
+ switch (closeStrategyType) {
144
+ case CloseStrategyType.STOP_LOSS_IN_COLLATERAL:
145
+ return { stopLossType: CloseToAssetType.COLLATERAL, takeProfitType: undefined };
146
+ case CloseStrategyType.STOP_LOSS_IN_DEBT:
147
+ return { stopLossType: CloseToAssetType.DEBT, takeProfitType: undefined };
148
+ case CloseStrategyType.TAKE_PROFIT_IN_COLLATERAL:
149
+ return { stopLossType: undefined, takeProfitType: CloseToAssetType.COLLATERAL };
150
+ case CloseStrategyType.TAKE_PROFIT_IN_DEBT:
151
+ return { stopLossType: undefined, takeProfitType: CloseToAssetType.DEBT };
152
+ case CloseStrategyType.TAKE_PROFIT_IN_COLLATERAL_AND_STOP_LOSS_IN_DEBT:
153
+ return { stopLossType: CloseToAssetType.DEBT, takeProfitType: CloseToAssetType.COLLATERAL };
154
+ case CloseStrategyType.TAKE_PROFIT_IN_DEBT_AND_STOP_LOSS_IN_COLLATERAL:
155
+ return { stopLossType: CloseToAssetType.COLLATERAL, takeProfitType: CloseToAssetType.DEBT };
156
+ case CloseStrategyType.TAKE_PROFIT_AND_STOP_LOSS_IN_DEBT:
157
+ return { stopLossType: CloseToAssetType.DEBT, takeProfitType: CloseToAssetType.DEBT };
158
+ case CloseStrategyType.TAKE_PROFIT_AND_STOP_LOSS_IN_COLLATERAL:
159
+ return { stopLossType: CloseToAssetType.COLLATERAL, takeProfitType: CloseToAssetType.COLLATERAL };
160
+ default:
161
+ throw new Error('CloseStrategyType not supported');
162
+ }
104
163
  }