@defisaver/automation-sdk 3.1.5 → 3.1.6-fluid-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 (44) hide show
  1. package/cjs/automation/private/StrategiesAutomation.d.ts +2 -2
  2. package/cjs/automation/public/Strategies.test.d.ts +1 -0
  3. package/cjs/automation/public/Strategies.test.js +61 -0
  4. package/cjs/constants/index.js +35 -0
  5. package/cjs/services/strategiesService.js +123 -0
  6. package/cjs/services/strategySubService.d.ts +9 -1
  7. package/cjs/services/strategySubService.js +30 -1
  8. package/cjs/services/subDataService.d.ts +43 -1
  9. package/cjs/services/subDataService.js +143 -1
  10. package/cjs/services/triggerService.d.ts +33 -0
  11. package/cjs/services/triggerService.js +63 -1
  12. package/cjs/services/utils.d.ts +6 -1
  13. package/cjs/services/utils.js +52 -1
  14. package/cjs/types/enums.d.ts +34 -2
  15. package/cjs/types/enums.js +37 -1
  16. package/cjs/types/index.d.ts +12 -3
  17. package/esm/automation/private/StrategiesAutomation.d.ts +2 -2
  18. package/esm/automation/public/Strategies.test.d.ts +1 -0
  19. package/esm/automation/public/Strategies.test.js +56 -0
  20. package/esm/constants/index.js +35 -0
  21. package/esm/services/strategiesService.js +124 -1
  22. package/esm/services/strategySubService.d.ts +9 -1
  23. package/esm/services/strategySubService.js +31 -2
  24. package/esm/services/subDataService.d.ts +43 -1
  25. package/esm/services/subDataService.js +143 -1
  26. package/esm/services/triggerService.d.ts +33 -0
  27. package/esm/services/triggerService.js +62 -0
  28. package/esm/services/utils.d.ts +6 -1
  29. package/esm/services/utils.js +50 -1
  30. package/esm/types/enums.d.ts +34 -2
  31. package/esm/types/enums.js +36 -0
  32. package/esm/types/index.d.ts +12 -3
  33. package/package.json +3 -3
  34. package/src/automation/private/StrategiesAutomation.ts +2 -2
  35. package/src/automation/public/Strategies.test.ts +49 -0
  36. package/src/constants/index.ts +35 -0
  37. package/src/services/strategiesService.ts +159 -1
  38. package/src/services/strategySubService.ts +80 -1
  39. package/src/services/subDataService.ts +202 -2
  40. package/src/services/triggerService.ts +96 -0
  41. package/src/services/utils.ts +60 -1
  42. package/src/types/enums.ts +36 -0
  43. package/src/types/index.ts +13 -1
  44. package/umd/index.js +34219 -0
@@ -19,7 +19,7 @@ import Automation from './Automation';
19
19
 
20
20
  interface IStrategiesAutomation extends Interfaces.Automation {
21
21
  chainId: ChainId,
22
- providerFork: Web3,
22
+ providerFork?: Web3,
23
23
  }
24
24
 
25
25
  export default class StrategiesAutomation extends Automation {
@@ -27,7 +27,7 @@ export default class StrategiesAutomation extends Automation {
27
27
 
28
28
  protected web3: Web3;
29
29
 
30
- protected web3Fork: Web3;
30
+ protected web3Fork?: Web3;
31
31
 
32
32
  protected subStorageContract: Contract.WithMeta<SubStorage>;
33
33
 
@@ -0,0 +1,49 @@
1
+ import Web3 from 'web3';
2
+ import { expect } from 'chai';
3
+
4
+ import {ChainId} from '../../types/enums';
5
+
6
+ import '../../configuration';
7
+ import EthereumStrategies from './EthereumStrategies';
8
+ import ArbitrumStrategies from './ArbitrumStrategies';
9
+ import OptimismStrategies from './OptimismStrategies';
10
+ import BaseStrategies from './BaseStrategies';
11
+
12
+ require('dotenv').config({ path: '.env' });
13
+
14
+ const Web3_1 = new Web3(process.env.RPC_1!);
15
+ const Web3_42161 = new Web3(process.env.RPC_42161!);
16
+ const Web3_10 = new Web3(process.env.RPC_10!);
17
+ const Web3_8453 = new Web3(process.env.RPC_8453!);
18
+
19
+ describe('Feature: StrategiesAutomation.ts', () => {
20
+ describe('Fetching subscriptions', () => {
21
+ it('can fetch subscriptions on Mainnet', async function () {
22
+ this.timeout(120000);
23
+ const ethStrategies = new EthereumStrategies({provider: Web3_1});
24
+ const subs = await ethStrategies.getSubscriptions({mergeSubs: true})
25
+ console.log(subs.length);
26
+ });
27
+
28
+ it('can fetch subscriptions on Arbitrum', async function () {
29
+ this.timeout(120000);
30
+ const arbiStrategies = new ArbitrumStrategies({provider: Web3_42161});
31
+ const subs = await arbiStrategies.getSubscriptions({mergeSubs: true})
32
+ console.log(subs.length);
33
+ });
34
+
35
+ it('can fetch subscriptions on Optimism', async function () {
36
+ this.timeout(120000);
37
+ const optimismStrategies = new OptimismStrategies({provider: Web3_10});
38
+ const subs = await optimismStrategies.getSubscriptions({mergeSubs: true})
39
+ console.log(subs.length);
40
+ });
41
+
42
+ it('can fetch subscriptions on Base', async function () {
43
+ this.timeout(120000);
44
+ const baseStrategies = new BaseStrategies({provider: Web3_8453});
45
+ const subs = await baseStrategies.getSubscriptions({mergeSubs: true})
46
+ console.log(subs.length);
47
+ });
48
+ });
49
+ });
@@ -376,11 +376,46 @@ export const MAINNET_BUNDLES_INFO: MainnetBundleInfo = {
376
376
  strategyId: Strategies.Identifiers.RepayOnPrice,
377
377
  protocol: PROTOCOLS.AaveV3,
378
378
  },
379
+ [Bundles.MainnetIds.LIQUITY_V2_REPAY]: {
380
+ strategyOrBundleId: Bundles.MainnetIds.LIQUITY_V2_REPAY,
381
+ strategyId: Strategies.Identifiers.Repay,
382
+ protocol: PROTOCOLS.LiquityV2,
383
+ },
384
+ [Bundles.MainnetIds.LIQUITY_V2_BOOST]: {
385
+ strategyOrBundleId: Bundles.MainnetIds.LIQUITY_V2_BOOST,
386
+ strategyId: Strategies.Identifiers.Boost,
387
+ protocol: PROTOCOLS.LiquityV2,
388
+ },
389
+ [Bundles.MainnetIds.LIQUITY_V2_CLOSE]: {
390
+ strategyOrBundleId: Bundles.MainnetIds.LIQUITY_V2_CLOSE,
391
+ strategyId: Strategies.Identifiers.CloseOnPrice,
392
+ protocol: PROTOCOLS.LiquityV2,
393
+ },
394
+ [Bundles.MainnetIds.LIQUITY_V2_REPAY_ON_PRICE]: {
395
+ strategyOrBundleId: Bundles.MainnetIds.LIQUITY_V2_REPAY_ON_PRICE,
396
+ strategyId: Strategies.Identifiers.OpenOrderFromCollateral,
397
+ protocol: PROTOCOLS.LiquityV2,
398
+ },
399
+ [Bundles.MainnetIds.LIQUITY_V2_BOOST_ON_PRICE]: {
400
+ strategyOrBundleId: Bundles.MainnetIds.LIQUITY_V2_BOOST_ON_PRICE,
401
+ strategyId: Strategies.Identifiers.RepayOnPrice,
402
+ protocol: PROTOCOLS.LiquityV2,
403
+ },
379
404
  [Bundles.MainnetIds.MORPHO_BLUE_BOOST_ON_PRICE]: {
380
405
  strategyOrBundleId: Bundles.MainnetIds.MORPHO_BLUE_BOOST_ON_PRICE,
381
406
  strategyId: Strategies.Identifiers.BoostOnPrice,
382
407
  protocol: PROTOCOLS.MorphoBlue,
383
408
  },
409
+ [Bundles.MainnetIds.FLUID_T1_REPAY]: {
410
+ strategyOrBundleId: Bundles.MainnetIds.FLUID_T1_REPAY,
411
+ strategyId: Strategies.Identifiers.Repay,
412
+ protocol: PROTOCOLS.FluidT1,
413
+ },
414
+ [Bundles.MainnetIds.FLUID_T2_BOOST]: {
415
+ strategyOrBundleId: Bundles.MainnetIds.FLUID_T2_BOOST,
416
+ strategyId: Strategies.Identifiers.Boost,
417
+ protocol: PROTOCOLS.FluidT1,
418
+ },
384
419
  };
385
420
 
386
421
  export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
@@ -10,7 +10,7 @@ import type {
10
10
  import { ChainId, ProtocolIdentifiers, Strategies } from '../types/enums';
11
11
 
12
12
  import {
13
- getPositionId, getRatioStateInfoForAaveCloseStrategy, isRatioStateOver, wethToEthByAddress,
13
+ getPositionId, getRatioStateInfoForAaveCloseStrategy, getStopLossAndTakeProfitTypeByCloseStrategyType, isRatioStateOver, wethToEthByAddress,
14
14
  } from './utils';
15
15
  import * as subDataService from './subDataService';
16
16
  import * as triggerService from './triggerService';
@@ -566,6 +566,49 @@ function parseLiquityLeverageManagement(position: Position.Automated, parseData:
566
566
  return _position;
567
567
  }
568
568
 
569
+ function parseLiquityV2LeverageManagement(position: Position.Automated, parseData: ParseData): Position.Automated {
570
+ const _position = cloneDeep(position);
571
+
572
+ const { subStruct, subId, subHash } = parseData.subscriptionEventData;
573
+ const { isEnabled } = parseData.strategiesSubsData;
574
+
575
+ const triggerData = triggerService.liquityV2RatioTrigger.decode(subStruct.triggerData);
576
+ const subData = subDataService.liquityV2LeverageManagementSubData.decode(subStruct.subData);
577
+
578
+ _position.strategyData.decoded.triggerData = triggerData;
579
+ _position.strategyData.decoded.subData = subData;
580
+
581
+ _position.positionId = getPositionId(
582
+ _position.chainId, _position.protocol.id, _position.owner, triggerData.troveId, triggerData.market,
583
+ );
584
+
585
+ const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
586
+
587
+ if (isRepay) {
588
+ _position.specific = {
589
+ triggerRepayRatio: triggerData.ratio,
590
+ targetRepayRatio: subData.targetRatio,
591
+ repayEnabled: isEnabled,
592
+ subId1: Number(subId),
593
+ subHashRepay: subHash,
594
+ mergeWithId: Strategies.Identifiers.Boost,
595
+ };
596
+ } else {
597
+ _position.specific = {
598
+ triggerBoostRatio: triggerData.ratio,
599
+ targetBoostRatio: subData.targetRatio,
600
+ boostEnabled: isEnabled,
601
+ subId2: Number(subId),
602
+ subHashBoost: subHash,
603
+ mergeId: Strategies.Identifiers.Boost,
604
+ };
605
+ }
606
+
607
+ _position.strategy.strategyId = Strategies.IdOverrides.LeverageManagement;
608
+
609
+ return _position;
610
+ }
611
+
569
612
  function parseSparkLeverageManagement(position: Position.Automated, parseData: ParseData): Position.Automated {
570
613
  const _position = cloneDeep(position);
571
614
 
@@ -845,6 +888,110 @@ function parseAaveV3LeverageManagementOnPrice(position: Position.Automated, pars
845
888
  return _position;
846
889
  }
847
890
 
891
+ function parseLiquityV2CloseOnPrice(position: Position.Automated, parseData: ParseData): Position.Automated {
892
+ const _position = cloneDeep(position);
893
+
894
+ const { subStruct } = parseData.subscriptionEventData;
895
+
896
+ const triggerData = triggerService.closePriceTrigger.decode(subStruct.triggerData);
897
+ const subData = subDataService.liquityV2CloseSubData.decode(subStruct.subData);
898
+
899
+ _position.strategyData.decoded.triggerData = triggerData;
900
+ _position.strategyData.decoded.subData = subData;
901
+
902
+ _position.positionId = getPositionId(
903
+ _position.chainId, _position.protocol.id, _position.owner, subData.troveId, subData.market,
904
+ );
905
+
906
+ const { takeProfitType, stopLossType } = getStopLossAndTakeProfitTypeByCloseStrategyType(+subData.closeType);
907
+
908
+ // User can have:
909
+ // - Only TakeProfit
910
+ // - Only StopLoss
911
+ // - Both
912
+ // TODO: see on frontend what specific data we need here because stop-loss and take-profit is one bundle now
913
+ _position.strategy.strategyId = Strategies.Identifiers.CloseOnPrice;
914
+ _position.specific = {
915
+ market: subData.market,
916
+ troveId: subData.troveId,
917
+ stopLossPrice: triggerData.lowerPrice,
918
+ takeProfitPrice: triggerData.upperPrice,
919
+ closeToAssetAddr: triggerData.tokenAddr,
920
+ takeProfitType,
921
+ stopLossType,
922
+ };
923
+
924
+ return _position;
925
+ }
926
+
927
+ function parseLiquityV2LeverageManagementOnPrice(position: Position.Automated, parseData: ParseData): Position.Automated {
928
+ const _position = cloneDeep(position);
929
+
930
+ const { subStruct } = parseData.subscriptionEventData;
931
+
932
+ const triggerData = triggerService.liquityV2QuotePriceTrigger.decode(subStruct.triggerData);
933
+ const subData = subDataService.liquityV2LeverageManagementOnPriceSubData.decode(subStruct.subData);
934
+
935
+ _position.strategyData.decoded.triggerData = triggerData;
936
+ _position.strategyData.decoded.subData = subData;
937
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, Math.random());
938
+ /// @TODO: what does even go here
939
+ /*
940
+ _position.specific = {
941
+ market: subData.market,
942
+ troveId: subData.troveId,
943
+ ratio: subData.targetRatio,
944
+ price: triggerData.price,
945
+ ratioState: triggerData.ratioState,
946
+ };
947
+ */
948
+
949
+ return _position;
950
+ }
951
+
952
+ function parseFluidT1LeverageManagement(position: Position.Automated, parseData: ParseData): Position.Automated {
953
+ const _position = cloneDeep(position);
954
+
955
+ const { subStruct, subId, subHash } = parseData.subscriptionEventData;
956
+ const { isEnabled } = parseData.strategiesSubsData;
957
+
958
+ const triggerData = triggerService.fluidRatioTrigger.decode(subStruct.triggerData);
959
+ const subData = subDataService.fluidLeverageManagementSubData.decode(subStruct.subData);
960
+
961
+ _position.strategyData.decoded.triggerData = triggerData;
962
+ _position.strategyData.decoded.subData = subData;
963
+
964
+ _position.positionId = getPositionId(
965
+ _position.chainId, _position.protocol.id, _position.owner, triggerData.nftId, subData.vault,
966
+ );
967
+
968
+ const isRepay = _position.strategy.strategyId === Strategies.Identifiers.Repay;
969
+
970
+ if (isRepay) {
971
+ _position.specific = {
972
+ triggerRepayRatio: triggerData.ratio,
973
+ targetRepayRatio: subData.targetRatio,
974
+ repayEnabled: isEnabled,
975
+ subId1: Number(subId),
976
+ subHashRepay: subHash,
977
+ mergeWithId: Strategies.Identifiers.Boost,
978
+ };
979
+ } else {
980
+ _position.specific = {
981
+ triggerBoostRatio: triggerData.ratio,
982
+ targetBoostRatio: subData.targetRatio,
983
+ boostEnabled: isEnabled,
984
+ subId2: Number(subId),
985
+ subHashBoost: subHash,
986
+ mergeId: Strategies.Identifiers.Boost,
987
+ };
988
+ }
989
+
990
+ _position.strategy.strategyId = Strategies.IdOverrides.LeverageManagement;
991
+
992
+ return _position;
993
+ }
994
+
848
995
  const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
849
996
  [ProtocolIdentifiers.StrategiesAutomation.MakerDAO]: {
850
997
  [Strategies.Identifiers.SavingsLiqProtection]: parseMakerSavingsLiqProtection,
@@ -865,6 +1012,13 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
865
1012
  [Strategies.Identifiers.SavingsDsrSupply]: parseLiquitySavingsLiqProtection,
866
1013
  [Strategies.Identifiers.DebtInFrontRepay]: parseLiquityDebtInFrontRepay,
867
1014
  },
1015
+ [ProtocolIdentifiers.StrategiesAutomation.LiquityV2]: {
1016
+ [Strategies.Identifiers.Repay]: parseLiquityV2LeverageManagement,
1017
+ [Strategies.Identifiers.Boost]: parseLiquityV2LeverageManagement,
1018
+ [Strategies.Identifiers.CloseOnPrice]: parseLiquityV2CloseOnPrice,
1019
+ [Strategies.Identifiers.OpenOrderFromCollateral]: parseLiquityV2LeverageManagementOnPrice,
1020
+ [Strategies.Identifiers.RepayOnPrice]: parseLiquityV2LeverageManagementOnPrice,
1021
+ },
868
1022
  [ProtocolIdentifiers.StrategiesAutomation.AaveV2]: {
869
1023
  [Strategies.Identifiers.Repay]: parseAaveV2LeverageManagement,
870
1024
  [Strategies.Identifiers.Boost]: parseAaveV2LeverageManagement,
@@ -918,6 +1072,10 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
918
1072
  [Strategies.Identifiers.EoaBoost]: parseMorphoBlueLeverageManagement,
919
1073
  [Strategies.Identifiers.BoostOnPrice]: parseMorphoBlueLeverageManagementOnPrice,
920
1074
  },
1075
+ [ProtocolIdentifiers.StrategiesAutomation.FluidT1]: {
1076
+ [Strategies.Identifiers.Repay]: parseFluidT1LeverageManagement,
1077
+ [Strategies.Identifiers.Boost]: parseFluidT1LeverageManagement,
1078
+ },
921
1079
  };
922
1080
 
923
1081
  function getParsingMethod(id: ProtocolIdentifiers.StrategiesAutomation, strategy: BundleOrStrategy) {
@@ -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(
@@ -539,3 +542,79 @@ export const morphoBlueEncode = {
539
542
  return [strategyOrBundleId, isBundle, triggerData, subData];
540
543
  },
541
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
+ };
602
+
603
+ export const fluidEncode = {
604
+ leverageManagement(
605
+ nftId: string,
606
+ vault: EthereumAddress,
607
+ collToken: EthereumAddress,
608
+ debtToken: EthereumAddress,
609
+ ratioState: RatioState,
610
+ targetRatio: number,
611
+ triggerRatio: number,
612
+ strategyOrBundleId: number,
613
+ ) {
614
+ const isBundle = true;
615
+ const subData = subDataService.fluidLeverageManagementSubData.encode(nftId, vault, collToken, debtToken, ratioState, targetRatio);
616
+ const triggerData = triggerService.fluidRatioTrigger.encode(nftId, triggerRatio, ratioState);
617
+
618
+ return [strategyOrBundleId, isBundle, triggerData, subData];
619
+ },
620
+ };
@@ -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
 
@@ -644,6 +646,153 @@ export const aaveV3LeverageManagementOnPriceSubData = {
644
646
  },
645
647
  };
646
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
+ };
647
796
  export const morphoBlueLeverageManagementOnPriceSubData = {
648
797
  encode(
649
798
  loanToken: EthereumAddress,
@@ -684,3 +833,54 @@ export const morphoBlueLeverageManagementOnPriceSubData = {
684
833
  };
685
834
  },
686
835
  };
836
+
837
+ export const fluidLeverageManagementSubData = {
838
+ encode: (
839
+ nftId: string,
840
+ vault: EthereumAddress,
841
+ collToken: EthereumAddress,
842
+ debtToken: EthereumAddress,
843
+ ratioState: RatioState,
844
+ targetRatio: number,
845
+ ) => {
846
+ const nftIdEncoded = AbiCoder.encodeParameter('uint256', nftId);
847
+ const vaultEncoded = AbiCoder.encodeParameter('address', vault);
848
+ const collTokenEncoded = AbiCoder.encodeParameter('address', collToken);
849
+ const debtTokenEncoded = AbiCoder.encodeParameter('address', debtToken);
850
+ const ratioStateEncoded = AbiCoder.encodeParameter('uint8', ratioState);
851
+ const targetRatioEncoded = AbiCoder.encodeParameter('uint256', ratioPercentageToWei(targetRatio));
852
+ const wrapEthEncoded = AbiCoder.encodeParameter('bool', true);
853
+
854
+ const isRepay = ratioState === RatioState.UNDER;
855
+ const collActionType = isRepay ? CollActionType.WITHDRAW : CollActionType.SUPPLY;
856
+ const debtActionType = isRepay ? DebtActionType.PAYBACK : DebtActionType.BORROW;
857
+
858
+ const collActionTypeEncoded = AbiCoder.encodeParameter('uint8', collActionType);
859
+ const debtActionTypeEncoded = AbiCoder.encodeParameter('uint8', debtActionType);
860
+
861
+ return [
862
+ nftIdEncoded,
863
+ vaultEncoded,
864
+ collTokenEncoded,
865
+ debtTokenEncoded,
866
+ ratioStateEncoded,
867
+ targetRatioEncoded,
868
+ wrapEthEncoded,
869
+ collActionTypeEncoded,
870
+ debtActionTypeEncoded,
871
+ ];
872
+ },
873
+ decode: (subData: SubData) => {
874
+ const nftId = AbiCoder.decodeParameter('uint256', subData[0]) as any as string;
875
+ const vault = AbiCoder.decodeParameter('address', subData[1]) as unknown as EthereumAddress;
876
+ const collToken = AbiCoder.decodeParameter('address', subData[2]) as any as EthereumAddress;
877
+ const debtToken = AbiCoder.decodeParameter('address', subData[3]) as any as EthereumAddress;
878
+ const ratioState = AbiCoder.decodeParameter('uint8', subData[4]) as any as RatioState;
879
+ const weiRatio = AbiCoder.decodeParameter('uint256', subData[5]) as any as string;
880
+ const targetRatio = weiToRatioPercentage(weiRatio);
881
+
882
+ return {
883
+ nftId, vault, collToken, debtToken, ratioState, targetRatio,
884
+ };
885
+ },
886
+ };