@defisaver/automation-sdk 3.3.21-debt-switch-dev-dev → 3.3.22-coll-switch-generic-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.
@@ -170,6 +170,12 @@ export const aaveV3Encode = {
170
170
  const triggerDataEncoded = triggerService.aaveV3QuotePriceTrigger.encode(baseTokenAddress, quoteTokenAddress, price, state);
171
171
  return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
172
172
  },
173
+ collateralSwitchGeneric(strategyOrBundleId, fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user, baseTokenAddress, quoteTokenAddress, price, state) {
174
+ const isBundle = false;
175
+ const subDataEncoded = subDataService.aaveV3GenericFLCollateralSwitchSubData.encode(fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user);
176
+ const triggerDataEncoded = triggerService.aaveV3QuotePriceTrigger.encode(baseTokenAddress, quoteTokenAddress, price, state);
177
+ return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
178
+ },
173
179
  debtSwitch(strategyOrBundleId, fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user, baseTokenAddress, quoteTokenAddress, price, state) {
174
180
  const isBundle = false;
175
181
  const subDataEncoded = subDataService.aaveV3DebtSwitchSubData.encode(fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user);
@@ -831,6 +831,42 @@ describe('Feature: strategySubService.ts', () => {
831
831
  });
832
832
  });
833
833
  });
834
+ describe('collateralSwitchGeneric()', () => {
835
+ const strategyId = 12345;
836
+ const fromAsset = web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address);
837
+ const toAsset = web3Utils.toChecksumAddress(getAssetInfo('USDC', ChainId.Ethereum).address);
838
+ const marketAddr = web3Utils.toChecksumAddress('0x87870Bca3F3fD6335C3F4ce8392D69d0B4161d39');
839
+ const user = web3Utils.toChecksumAddress('0x1234567890abcdef1234567890abcdef12345678');
840
+ const examples = [
841
+ [
842
+ RatioState.UNDER,
843
+ '10000000000000000000',
844
+ '0x0000000000000000000000000000000000000000000000008ac7230489e80000',
845
+ '0000000000000000000000000000000000000000000000000000000000000001',
846
+ ],
847
+ [
848
+ RatioState.OVER,
849
+ MAXUINT,
850
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
851
+ '0000000000000000000000000000000000000000000000000000000000000000',
852
+ ],
853
+ ];
854
+ examples.forEach(([state, amountToSwitch, encodedAmount, encodedState]) => {
855
+ it(`encodes a generic collateral switch with the supplied quote pair and state ${state}`, () => {
856
+ const expectedTrigger = `0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000003e8${encodedState}`;
857
+ const expectedSubData = [
858
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
859
+ '0x0000000000000000000000000000000000000000000000000000000000000100',
860
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
861
+ '0x000000000000000000000000000000000000000000000000000000000000ffff',
862
+ '0x00000000000000000000000087870bca3f3fd6335c3f4ce8392d69d0b4161d39',
863
+ encodedAmount,
864
+ '0x0000000000000000000000001234567890abcdef1234567890abcdef12345678',
865
+ ];
866
+ expect(aaveV3Encode.collateralSwitchGeneric(strategyId, fromAsset, 256, toAsset, 65535, marketAddr, amountToSwitch, user, toAsset, fromAsset, 0.00001, state)).to.eql([strategyId, false, [expectedTrigger], expectedSubData]);
867
+ });
868
+ });
869
+ });
834
870
  describe('debtSwitch()', () => {
835
871
  const examples = [
836
872
  // USDC -> DAI, price 100000, state UNDER
@@ -259,6 +259,18 @@ export declare const aaveV3CollateralSwitchSubData: {
259
259
  amountToSwitch: string;
260
260
  };
261
261
  };
262
+ export declare const aaveV3GenericFLCollateralSwitchSubData: {
263
+ encode(fromAsset: EthereumAddress, fromAssetId: number, toAsset: EthereumAddress, toAssetId: number, marketAddr: EthereumAddress, amountToSwitch: string, user: EthereumAddress): string[];
264
+ decode(subData: string[]): {
265
+ fromAsset: EthereumAddress;
266
+ fromAssetId: number;
267
+ toAsset: EthereumAddress;
268
+ toAssetId: number;
269
+ marketAddr: EthereumAddress;
270
+ amountToSwitch: string;
271
+ user: EthereumAddress;
272
+ };
273
+ };
262
274
  export declare const aaveV3DebtSwitchSubData: {
263
275
  encode(fromAsset: EthereumAddress, fromAssetId: number, toAsset: EthereumAddress, toAssetId: number, marketAddr: EthereumAddress, amountToSwitch: string, user: EthereumAddress): string[];
264
276
  decode(subData: string[]): {
@@ -542,6 +542,38 @@ export const aaveV3CollateralSwitchSubData = {
542
542
  };
543
543
  },
544
544
  };
545
+ export const aaveV3GenericFLCollateralSwitchSubData = {
546
+ encode(fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user) {
547
+ const encodedFromAsset = AbiCoder.encodeParameter('address', fromAsset);
548
+ const encodedFromAssetId = AbiCoder.encodeParameter('uint16', fromAssetId);
549
+ const encodedToAsset = AbiCoder.encodeParameter('address', toAsset);
550
+ const encodedToAssetId = AbiCoder.encodeParameter('uint16', toAssetId);
551
+ const encodedMarketAddr = AbiCoder.encodeParameter('address', marketAddr);
552
+ const encodedAmountToSwitch = AbiCoder.encodeParameter('uint256', amountToSwitch);
553
+ const encodedUser = AbiCoder.encodeParameter('address', user);
554
+ return [
555
+ encodedFromAsset,
556
+ encodedFromAssetId,
557
+ encodedToAsset,
558
+ encodedToAssetId,
559
+ encodedMarketAddr,
560
+ encodedAmountToSwitch,
561
+ encodedUser,
562
+ ];
563
+ },
564
+ decode(subData) {
565
+ const fromAsset = AbiCoder.decodeParameter('address', subData[0]);
566
+ const fromAssetId = Number(AbiCoder.decodeParameter('uint16', subData[1]));
567
+ const toAsset = AbiCoder.decodeParameter('address', subData[2]);
568
+ const toAssetId = Number(AbiCoder.decodeParameter('uint16', subData[3]));
569
+ const marketAddr = AbiCoder.decodeParameter('address', subData[4]);
570
+ const amountToSwitch = AbiCoder.decodeParameter('uint256', subData[5]);
571
+ const user = AbiCoder.decodeParameter('address', subData[6]);
572
+ return {
573
+ fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user,
574
+ };
575
+ },
576
+ };
545
577
  export const aaveV3DebtSwitchSubData = {
546
578
  encode(fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user) {
547
579
  const encodedFromAsset = AbiCoder.encodeParameter('address', fromAsset);
@@ -614,6 +614,41 @@ describe('Feature: subDataService.ts', () => {
614
614
  });
615
615
  });
616
616
  });
617
+ describe('When testing subDataService.aaveV3GenericFLCollateralSwitchSubData', () => {
618
+ const fromAsset = web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address);
619
+ const toAsset = web3Utils.toChecksumAddress(getAssetInfo('USDC', ChainId.Ethereum).address);
620
+ const marketAddr = web3Utils.toChecksumAddress('0x87870Bca3F3fD6335C3F4ce8392D69d0B4161d39');
621
+ const user = web3Utils.toChecksumAddress('0x1234567890abcdef1234567890abcdef12345678');
622
+ const examples = [
623
+ ['10000000000000000000', '0x0000000000000000000000000000000000000000000000008ac7230489e80000'],
624
+ [MAXUINT, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'],
625
+ ];
626
+ examples.forEach(([amountToSwitch, encodedAmount]) => {
627
+ const subData = [
628
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
629
+ '0x0000000000000000000000000000000000000000000000000000000000000100',
630
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
631
+ '0x000000000000000000000000000000000000000000000000000000000000ffff',
632
+ '0x00000000000000000000000087870bca3f3fd6335c3f4ce8392d69d0b4161d39',
633
+ encodedAmount,
634
+ '0x0000000000000000000000001234567890abcdef1234567890abcdef12345678',
635
+ ];
636
+ it(`encode() preserves uint16 asset IDs and user when switching ${amountToSwitch}`, () => {
637
+ expect(subDataService.aaveV3GenericFLCollateralSwitchSubData.encode(fromAsset, 256, toAsset, 65535, marketAddr, amountToSwitch, user)).to.eql(subData);
638
+ });
639
+ it(`decode() preserves uint16 asset IDs and user when switching ${amountToSwitch}`, () => {
640
+ expect(subDataService.aaveV3GenericFLCollateralSwitchSubData.decode(subData)).to.eql({
641
+ fromAsset,
642
+ fromAssetId: 256,
643
+ toAsset,
644
+ toAssetId: 65535,
645
+ marketAddr,
646
+ amountToSwitch,
647
+ user,
648
+ });
649
+ });
650
+ });
651
+ });
617
652
  describe('When testing subDataService.sparkCollateralSwitchSubData', () => {
618
653
  describe('encode()', () => {
619
654
  const examples = [
@@ -93,28 +93,32 @@ export declare namespace Strategies {
93
93
  SPARK_COLLATERAL_SWITCH = 156,
94
94
  SPARK_GENERIC_FL_COLLATERAL_SWITCH = 167,
95
95
  AAVE_V3_DEBT_SWITCH = 168,
96
- AAVE_V3_DEBT_SWITCH_EOA = 169
96
+ AAVE_V3_DEBT_SWITCH_EOA = 169,
97
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 170
97
98
  }
98
99
  enum OptimismIds {
99
100
  EXCHANGE_DCA = 8,
100
101
  EXCHANGE_LIMIT_ORDER = 9,
101
102
  AAVE_V3_COLLATERAL_SWITCH = 24,
102
103
  AAVE_V3_DEBT_SWITCH = 25,
103
- AAVE_V3_DEBT_SWITCH_EOA = 26
104
+ AAVE_V3_DEBT_SWITCH_EOA = 26,
105
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 27
104
106
  }
105
107
  enum BaseIds {
106
108
  EXCHANGE_DCA = 8,
107
109
  EXCHANGE_LIMIT_ORDER = 9,
108
110
  AAVE_V3_COLLATERAL_SWITCH = 56,
109
111
  AAVE_V3_DEBT_SWITCH = 61,
110
- AAVE_V3_DEBT_SWITCH_EOA = 62
112
+ AAVE_V3_DEBT_SWITCH_EOA = 62,
113
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 63
111
114
  }
112
115
  enum ArbitrumIds {
113
116
  EXCHANGE_DCA = 8,
114
117
  EXCHANGE_LIMIT_ORDER = 9,
115
118
  AAVE_V3_COLLATERAL_SWITCH = 50,
116
119
  AAVE_V3_DEBT_SWITCH = 55,
117
- AAVE_V3_DEBT_SWITCH_EOA = 56
120
+ AAVE_V3_DEBT_SWITCH_EOA = 56,
121
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 57
118
122
  }
119
123
  enum Identifiers {
120
124
  SavingsLiqProtection = "smart-savings-liquidation-protection",
@@ -107,6 +107,7 @@ export var Strategies;
107
107
  MainnetIds[MainnetIds["SPARK_GENERIC_FL_COLLATERAL_SWITCH"] = 167] = "SPARK_GENERIC_FL_COLLATERAL_SWITCH";
108
108
  MainnetIds[MainnetIds["AAVE_V3_DEBT_SWITCH"] = 168] = "AAVE_V3_DEBT_SWITCH";
109
109
  MainnetIds[MainnetIds["AAVE_V3_DEBT_SWITCH_EOA"] = 169] = "AAVE_V3_DEBT_SWITCH_EOA";
110
+ MainnetIds[MainnetIds["AAVE_V3_COLLATERAL_SWITCH_EOA"] = 170] = "AAVE_V3_COLLATERAL_SWITCH_EOA";
110
111
  })(MainnetIds = Strategies.MainnetIds || (Strategies.MainnetIds = {}));
111
112
  let OptimismIds;
112
113
  (function (OptimismIds) {
@@ -115,6 +116,7 @@ export var Strategies;
115
116
  OptimismIds[OptimismIds["AAVE_V3_COLLATERAL_SWITCH"] = 24] = "AAVE_V3_COLLATERAL_SWITCH";
116
117
  OptimismIds[OptimismIds["AAVE_V3_DEBT_SWITCH"] = 25] = "AAVE_V3_DEBT_SWITCH";
117
118
  OptimismIds[OptimismIds["AAVE_V3_DEBT_SWITCH_EOA"] = 26] = "AAVE_V3_DEBT_SWITCH_EOA";
119
+ OptimismIds[OptimismIds["AAVE_V3_COLLATERAL_SWITCH_EOA"] = 27] = "AAVE_V3_COLLATERAL_SWITCH_EOA";
118
120
  })(OptimismIds = Strategies.OptimismIds || (Strategies.OptimismIds = {}));
119
121
  let BaseIds;
120
122
  (function (BaseIds) {
@@ -123,6 +125,7 @@ export var Strategies;
123
125
  BaseIds[BaseIds["AAVE_V3_COLLATERAL_SWITCH"] = 56] = "AAVE_V3_COLLATERAL_SWITCH";
124
126
  BaseIds[BaseIds["AAVE_V3_DEBT_SWITCH"] = 61] = "AAVE_V3_DEBT_SWITCH";
125
127
  BaseIds[BaseIds["AAVE_V3_DEBT_SWITCH_EOA"] = 62] = "AAVE_V3_DEBT_SWITCH_EOA";
128
+ BaseIds[BaseIds["AAVE_V3_COLLATERAL_SWITCH_EOA"] = 63] = "AAVE_V3_COLLATERAL_SWITCH_EOA";
126
129
  })(BaseIds = Strategies.BaseIds || (Strategies.BaseIds = {}));
127
130
  let ArbitrumIds;
128
131
  (function (ArbitrumIds) {
@@ -131,6 +134,7 @@ export var Strategies;
131
134
  ArbitrumIds[ArbitrumIds["AAVE_V3_COLLATERAL_SWITCH"] = 50] = "AAVE_V3_COLLATERAL_SWITCH";
132
135
  ArbitrumIds[ArbitrumIds["AAVE_V3_DEBT_SWITCH"] = 55] = "AAVE_V3_DEBT_SWITCH";
133
136
  ArbitrumIds[ArbitrumIds["AAVE_V3_DEBT_SWITCH_EOA"] = 56] = "AAVE_V3_DEBT_SWITCH_EOA";
137
+ ArbitrumIds[ArbitrumIds["AAVE_V3_COLLATERAL_SWITCH_EOA"] = 57] = "AAVE_V3_COLLATERAL_SWITCH_EOA";
134
138
  })(ArbitrumIds = Strategies.ArbitrumIds || (Strategies.ArbitrumIds = {}));
135
139
  let Identifiers;
136
140
  (function (Identifiers) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/automation-sdk",
3
- "version": "3.3.21-debt-switch-dev-dev",
3
+ "version": "3.3.22-coll-switch-generic-dev",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -125,6 +125,11 @@ export const MAINNET_STRATEGIES_INFO: MainnetStrategiesInfo = {
125
125
  strategyId: Strategies.Identifiers.CollateralSwitch,
126
126
  protocol: PROTOCOLS.AaveV3,
127
127
  },
128
+ [Strategies.MainnetIds.AAVE_V3_COLLATERAL_SWITCH_EOA]: {
129
+ strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_COLLATERAL_SWITCH_EOA,
130
+ strategyId: Strategies.Identifiers.EoaCollateralSwitch,
131
+ protocol: PROTOCOLS.AaveV3,
132
+ },
128
133
  [Strategies.MainnetIds.AAVE_V4_COLLATERAL_SWITCH]: {
129
134
  strategyOrBundleId: Strategies.MainnetIds.AAVE_V4_COLLATERAL_SWITCH,
130
135
  strategyId: Strategies.Identifiers.CollateralSwitch,
@@ -173,6 +178,11 @@ export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
173
178
  strategyId: Strategies.Identifiers.CollateralSwitch,
174
179
  protocol: PROTOCOLS.AaveV3,
175
180
  },
181
+ [Strategies.OptimismIds.AAVE_V3_COLLATERAL_SWITCH_EOA]: {
182
+ strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_COLLATERAL_SWITCH_EOA,
183
+ strategyId: Strategies.Identifiers.EoaCollateralSwitch,
184
+ protocol: PROTOCOLS.AaveV3,
185
+ },
176
186
  [Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH]: {
177
187
  strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH,
178
188
  strategyId: Strategies.Identifiers.DebtSwitch,
@@ -201,6 +211,11 @@ export const BASE_STRATEGIES_INFO: BaseStrategiesInfo = {
201
211
  strategyId: Strategies.Identifiers.CollateralSwitch,
202
212
  protocol: PROTOCOLS.AaveV3,
203
213
  },
214
+ [Strategies.BaseIds.AAVE_V3_COLLATERAL_SWITCH_EOA]: {
215
+ strategyOrBundleId: Strategies.BaseIds.AAVE_V3_COLLATERAL_SWITCH_EOA,
216
+ strategyId: Strategies.Identifiers.EoaCollateralSwitch,
217
+ protocol: PROTOCOLS.AaveV3,
218
+ },
204
219
  [Strategies.BaseIds.AAVE_V3_DEBT_SWITCH]: {
205
220
  strategyOrBundleId: Strategies.BaseIds.AAVE_V3_DEBT_SWITCH,
206
221
  strategyId: Strategies.Identifiers.DebtSwitch,
@@ -229,6 +244,11 @@ export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
229
244
  strategyId: Strategies.Identifiers.CollateralSwitch,
230
245
  protocol: PROTOCOLS.AaveV3,
231
246
  },
247
+ [Strategies.ArbitrumIds.AAVE_V3_COLLATERAL_SWITCH_EOA]: {
248
+ strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_COLLATERAL_SWITCH_EOA,
249
+ strategyId: Strategies.Identifiers.EoaCollateralSwitch,
250
+ protocol: PROTOCOLS.AaveV3,
251
+ },
232
252
  [Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH]: {
233
253
  strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH,
234
254
  strategyId: Strategies.Identifiers.DebtSwitch,
@@ -1,12 +1,113 @@
1
1
  import { expect } from 'chai';
2
2
 
3
- import { ProtocolIdentifiers, Strategies } from '../types/enums';
3
+ import { ChainId, ProtocolIdentifiers, RatioState, Strategies } from '../types/enums';
4
4
  import type { ParseData, Position } from '../types';
5
5
 
6
6
  import '../configuration';
7
7
  import { parseStrategiesAutomatedPosition } from './strategiesService';
8
8
 
9
9
  describe('Feature: strategiesService.ts', () => {
10
+ describe('When parsing Aave V3 collateral switch subscriptions', () => {
11
+ const proxy = '0x9cB7E19861665366011899d74E75d4F2A419aEeD';
12
+ const user = '0x1234567890123456789012345678901234567890';
13
+ const fromAsset = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
14
+ const toAsset = '0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf';
15
+ const marketAddr = '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e';
16
+ const amountToSwitch = '115792089237316195423570985008687907853269984665640564039457584007913129639935';
17
+ const subHash = `0x${'ab'.repeat(32)}`;
18
+ const triggerData = [
19
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2'
20
+ + '000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf'
21
+ + '0000000000000000000000000000000000000000000000000000000000989680'
22
+ + '0000000000000000000000000000000000000000000000000000000000000001',
23
+ ];
24
+
25
+ function getParseData(strategyId: number, isGeneric: boolean, chainId = ChainId.Ethereum): ParseData {
26
+ const subData = [
27
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
28
+ isGeneric
29
+ ? '0x0000000000000000000000000000000000000000000000000000000000000100'
30
+ : '0x0000000000000000000000000000000000000000000000000000000000000000',
31
+ '0x000000000000000000000000cbb7c0000ab88b473b1f5afd9ef808440eed33bf',
32
+ isGeneric
33
+ ? '0x000000000000000000000000000000000000000000000000000000000000ffff'
34
+ : '0x0000000000000000000000000000000000000000000000000000000000000007',
35
+ '0x0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e',
36
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
37
+ isGeneric
38
+ ? '0x0000000000000000000000001234567890123456789012345678901234567890'
39
+ : '0x0000000000000000000000000000000000000000000000000000000000000000',
40
+ ];
41
+ const subStruct = Object.assign(
42
+ [String(strategyId), false, triggerData, subData] as [string, boolean, string[], string[]],
43
+ { strategyOrBundleId: String(strategyId), isBundle: false, triggerData, subData },
44
+ );
45
+ return {
46
+ chainId,
47
+ blockNumber: 18015756,
48
+ subscriptionEventData: {
49
+ subId: '379', proxy, subHash, subStruct,
50
+ 0: '379', 1: proxy, 2: subHash, 3: subStruct,
51
+ },
52
+ strategiesSubsData: {
53
+ userProxy: proxy, isEnabled: true, strategySubHash: subHash,
54
+ },
55
+ };
56
+ }
57
+
58
+ const genericStrategies: Array<[ChainId, number]> = [
59
+ [ChainId.Ethereum, Strategies.MainnetIds.AAVE_V3_COLLATERAL_SWITCH_EOA],
60
+ [ChainId.Optimism, Strategies.OptimismIds.AAVE_V3_COLLATERAL_SWITCH_EOA],
61
+ [ChainId.Arbitrum, Strategies.ArbitrumIds.AAVE_V3_COLLATERAL_SWITCH_EOA],
62
+ [ChainId.Base, Strategies.BaseIds.AAVE_V3_COLLATERAL_SWITCH_EOA],
63
+ ];
64
+ genericStrategies.forEach(([chainId, strategyId]) => {
65
+ it(`decodes generic collateral switches with the user and uint16 reserve IDs on chain ${chainId}`, () => {
66
+ const parseData = getParseData(strategyId, true, chainId);
67
+ const position = parseStrategiesAutomatedPosition(parseData)!;
68
+
69
+ expect(position).not.to.equal(null);
70
+ expect(position.protocol.id).to.equal(ProtocolIdentifiers.StrategiesAutomation.AaveV3);
71
+ expect(position.strategy.strategyId).to.equal(Strategies.Identifiers.EoaCollateralSwitch);
72
+ expect(position.strategy.isBundle).to.equal(false);
73
+ expect(position.strategyData.encoded).to.eql({
74
+ triggerData,
75
+ subData: parseData.subscriptionEventData.subStruct.subData,
76
+ });
77
+ expect(position.strategyData.decoded.triggerData).to.eql({
78
+ baseTokenAddress: fromAsset,
79
+ quoteTokenAddress: toAsset,
80
+ price: '0.1',
81
+ ratioState: RatioState.UNDER,
82
+ });
83
+ expect(position.strategyData.decoded.subData).to.eql({
84
+ fromAsset, fromAssetId: 256, toAsset, toAssetId: 65535, marketAddr, amountToSwitch, user,
85
+ });
86
+ expect(position.owner).to.equal(proxy.toLowerCase());
87
+ expect(position.positionId).to.equal(`${chainId}-aave__v3-${proxy.toLowerCase()}-${marketAddr.toLowerCase()}`);
88
+ });
89
+ });
90
+
91
+ const legacyStrategies: Array<[ChainId, number]> = [
92
+ [ChainId.Ethereum, Strategies.MainnetIds.AAVE_V3_COLLATERAL_SWITCH],
93
+ [ChainId.Optimism, Strategies.OptimismIds.AAVE_V3_COLLATERAL_SWITCH],
94
+ [ChainId.Arbitrum, Strategies.ArbitrumIds.AAVE_V3_COLLATERAL_SWITCH],
95
+ [ChainId.Base, Strategies.BaseIds.AAVE_V3_COLLATERAL_SWITCH],
96
+ ];
97
+ legacyStrategies.forEach(([chainId, strategyId]) => {
98
+ it(`continues to decode legacy collateral switches on chain ${chainId}`, () => {
99
+ const position = parseStrategiesAutomatedPosition(getParseData(strategyId, false, chainId))!;
100
+
101
+ expect(position).not.to.equal(null);
102
+ expect(position.strategy.strategyId).to.equal(Strategies.Identifiers.CollateralSwitch);
103
+ expect(position.strategyData.decoded.subData).to.eql({
104
+ fromAsset, fromAssetId: 0, toAsset, toAssetId: 7, marketAddr, amountToSwitch,
105
+ });
106
+ expect(position.positionId).to.equal(`${chainId}-aave__v3-${proxy.toLowerCase()}-${marketAddr.toLowerCase()}`);
107
+ });
108
+ });
109
+ });
110
+
10
111
  describe('When testing strategiesService.parseStrategiesAutomatedPosition', async () => {
11
112
  // TODO: we should probably write this for every strategy?
12
113
  const examples: Array<[Position.Automated | null, ParseData]> = [
@@ -436,11 +436,17 @@ function parseAaveV3CloseOnPrice(position: Position.Automated, parseData: ParseD
436
436
  function parseAaveV3CollateralSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
437
437
  const _position = cloneDeep(position);
438
438
  const { subStruct } = parseData.subscriptionEventData;
439
+ const isEOA = _position.strategy.strategyId.includes('eoa');
439
440
  const triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
440
- const subData = subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
441
+ const subData = isEOA
442
+ ? subDataService.aaveV3GenericFLCollateralSwitchSubData.decode(subStruct.subData)
443
+ : subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
441
444
  _position.strategyData.decoded.triggerData = triggerData;
442
445
  _position.strategyData.decoded.subData = subData;
443
446
  _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, subData.marketAddr);
447
+ _position.strategy.strategyId = isEOA
448
+ ? Strategies.Identifiers.EoaCollateralSwitch
449
+ : Strategies.Identifiers.CollateralSwitch;
444
450
 
445
451
  return _position;
446
452
  }
@@ -1610,6 +1616,7 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
1610
1616
  [Strategies.Identifiers.EoaBoostOnPrice]: parseAaveV3LeverageManagementOnPrice,
1611
1617
  [Strategies.Identifiers.EoaCloseOnPrice]: parseAaveV3CloseOnPrice,
1612
1618
  [Strategies.Identifiers.CollateralSwitch]: parseAaveV3CollateralSwitch,
1619
+ [Strategies.Identifiers.EoaCollateralSwitch]: parseAaveV3CollateralSwitch,
1613
1620
  [Strategies.Identifiers.DebtSwitch]: parseAaveV3DebtSwitch,
1614
1621
  [Strategies.Identifiers.EoaDebtSwitch]: parseAaveV3DebtSwitch,
1615
1622
  [Strategies.Identifiers.LiquidationProtection]: parseAaveV3LiquidationProtection,
@@ -1003,6 +1003,48 @@ describe('Feature: strategySubService.ts', () => {
1003
1003
  });
1004
1004
  });
1005
1005
 
1006
+ describe('collateralSwitchGeneric()', () => {
1007
+ const strategyId = 12345;
1008
+ const fromAsset = web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address);
1009
+ const toAsset = web3Utils.toChecksumAddress(getAssetInfo('USDC', ChainId.Ethereum).address);
1010
+ const marketAddr = web3Utils.toChecksumAddress('0x87870Bca3F3fD6335C3F4ce8392D69d0B4161d39');
1011
+ const user = web3Utils.toChecksumAddress('0x1234567890abcdef1234567890abcdef12345678');
1012
+ const examples: Array<[RatioState, string, string, string]> = [
1013
+ [
1014
+ RatioState.UNDER,
1015
+ '10000000000000000000',
1016
+ '0x0000000000000000000000000000000000000000000000008ac7230489e80000',
1017
+ '0000000000000000000000000000000000000000000000000000000000000001',
1018
+ ],
1019
+ [
1020
+ RatioState.OVER,
1021
+ MAXUINT,
1022
+ '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff',
1023
+ '0000000000000000000000000000000000000000000000000000000000000000',
1024
+ ],
1025
+ ];
1026
+
1027
+ examples.forEach(([state, amountToSwitch, encodedAmount, encodedState]) => {
1028
+ it(`encodes a generic collateral switch with the supplied quote pair and state ${state}`, () => {
1029
+ const expectedTrigger = `0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000003e8${encodedState}`;
1030
+ const expectedSubData: SubData = [
1031
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
1032
+ '0x0000000000000000000000000000000000000000000000000000000000000100',
1033
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
1034
+ '0x000000000000000000000000000000000000000000000000000000000000ffff',
1035
+ '0x00000000000000000000000087870bca3f3fd6335c3f4ce8392d69d0b4161d39',
1036
+ encodedAmount,
1037
+ '0x0000000000000000000000001234567890abcdef1234567890abcdef12345678',
1038
+ ];
1039
+
1040
+ expect(aaveV3Encode.collateralSwitchGeneric(
1041
+ strategyId, fromAsset, 256, toAsset, 65535, marketAddr, amountToSwitch, user,
1042
+ toAsset, fromAsset, 0.00001, state,
1043
+ )).to.eql([strategyId, false, [expectedTrigger], expectedSubData]);
1044
+ });
1045
+ });
1046
+ });
1047
+
1006
1048
  describe('debtSwitch()', () => {
1007
1049
  const examples: Array<[
1008
1050
  [StrategyOrBundleIds, boolean, TriggerData, SubData],
@@ -445,6 +445,30 @@ export const aaveV3Encode = {
445
445
  return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
446
446
  },
447
447
 
448
+ collateralSwitchGeneric(
449
+ strategyOrBundleId: number,
450
+ fromAsset: EthereumAddress,
451
+ fromAssetId: number,
452
+ toAsset: EthereumAddress,
453
+ toAssetId: number,
454
+ marketAddr: EthereumAddress,
455
+ amountToSwitch: string,
456
+ user: EthereumAddress,
457
+ baseTokenAddress: EthereumAddress,
458
+ quoteTokenAddress: EthereumAddress,
459
+ price: number,
460
+ state: RatioState,
461
+ ) {
462
+ const isBundle = false;
463
+
464
+ const subDataEncoded = subDataService.aaveV3GenericFLCollateralSwitchSubData.encode(
465
+ fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user,
466
+ );
467
+ const triggerDataEncoded = triggerService.aaveV3QuotePriceTrigger.encode(baseTokenAddress, quoteTokenAddress, price, state);
468
+
469
+ return [strategyOrBundleId, isBundle, triggerDataEncoded, subDataEncoded];
470
+ },
471
+
448
472
  debtSwitch(
449
473
  strategyOrBundleId: number,
450
474
  fromAsset: EthereumAddress,
@@ -657,6 +657,47 @@ describe('Feature: subDataService.ts', () => {
657
657
  });
658
658
  });
659
659
 
660
+ describe('When testing subDataService.aaveV3GenericFLCollateralSwitchSubData', () => {
661
+ const fromAsset = web3Utils.toChecksumAddress(getAssetInfo('WETH', ChainId.Ethereum).address);
662
+ const toAsset = web3Utils.toChecksumAddress(getAssetInfo('USDC', ChainId.Ethereum).address);
663
+ const marketAddr = web3Utils.toChecksumAddress('0x87870Bca3F3fD6335C3F4ce8392D69d0B4161d39');
664
+ const user = web3Utils.toChecksumAddress('0x1234567890abcdef1234567890abcdef12345678');
665
+ const examples = [
666
+ ['10000000000000000000', '0x0000000000000000000000000000000000000000000000008ac7230489e80000'],
667
+ [MAXUINT, '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'],
668
+ ];
669
+
670
+ examples.forEach(([amountToSwitch, encodedAmount]) => {
671
+ const subData: SubData = [
672
+ '0x000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
673
+ '0x0000000000000000000000000000000000000000000000000000000000000100',
674
+ '0x000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
675
+ '0x000000000000000000000000000000000000000000000000000000000000ffff',
676
+ '0x00000000000000000000000087870bca3f3fd6335c3f4ce8392d69d0b4161d39',
677
+ encodedAmount,
678
+ '0x0000000000000000000000001234567890abcdef1234567890abcdef12345678',
679
+ ];
680
+
681
+ it(`encode() preserves uint16 asset IDs and user when switching ${amountToSwitch}`, () => {
682
+ expect(subDataService.aaveV3GenericFLCollateralSwitchSubData.encode(
683
+ fromAsset, 256, toAsset, 65535, marketAddr, amountToSwitch, user,
684
+ )).to.eql(subData);
685
+ });
686
+
687
+ it(`decode() preserves uint16 asset IDs and user when switching ${amountToSwitch}`, () => {
688
+ expect(subDataService.aaveV3GenericFLCollateralSwitchSubData.decode(subData)).to.eql({
689
+ fromAsset,
690
+ fromAssetId: 256,
691
+ toAsset,
692
+ toAssetId: 65535,
693
+ marketAddr,
694
+ amountToSwitch,
695
+ user,
696
+ });
697
+ });
698
+ });
699
+ });
700
+
660
701
  describe('When testing subDataService.sparkCollateralSwitchSubData', () => {
661
702
  describe('encode()', () => {
662
703
  const examples: Array<[SubData, [fromAsset: EthereumAddress, fromAssetId: number, toAsset: EthereumAddress, toAssetId: number, marketAddr: EthereumAddress, amountToSwitch: string, useOnBehalf?: boolean]]> = [
@@ -735,6 +735,57 @@ export const aaveV3CollateralSwitchSubData = {
735
735
  };
736
736
  },
737
737
  };
738
+ export const aaveV3GenericFLCollateralSwitchSubData = {
739
+ encode(
740
+ fromAsset: EthereumAddress,
741
+ fromAssetId: number,
742
+ toAsset: EthereumAddress,
743
+ toAssetId: number,
744
+ marketAddr: EthereumAddress,
745
+ amountToSwitch: string,
746
+ user: EthereumAddress,
747
+ ): SubData {
748
+ const encodedFromAsset = AbiCoder.encodeParameter('address', fromAsset);
749
+ const encodedFromAssetId = AbiCoder.encodeParameter('uint16', fromAssetId);
750
+ const encodedToAsset = AbiCoder.encodeParameter('address', toAsset);
751
+ const encodedToAssetId = AbiCoder.encodeParameter('uint16', toAssetId);
752
+ const encodedMarketAddr = AbiCoder.encodeParameter('address', marketAddr);
753
+ const encodedAmountToSwitch = AbiCoder.encodeParameter('uint256', amountToSwitch);
754
+ const encodedUser = AbiCoder.encodeParameter('address', user);
755
+
756
+ return [
757
+ encodedFromAsset,
758
+ encodedFromAssetId,
759
+ encodedToAsset,
760
+ encodedToAssetId,
761
+ encodedMarketAddr,
762
+ encodedAmountToSwitch,
763
+ encodedUser,
764
+ ];
765
+ },
766
+ decode(subData: SubData): {
767
+ fromAsset: EthereumAddress,
768
+ fromAssetId: number,
769
+ toAsset: EthereumAddress,
770
+ toAssetId: number,
771
+ marketAddr: EthereumAddress,
772
+ amountToSwitch: string,
773
+ user: EthereumAddress,
774
+ } {
775
+ const fromAsset = AbiCoder.decodeParameter('address', subData[0]) as unknown as EthereumAddress;
776
+ const fromAssetId = Number(AbiCoder.decodeParameter('uint16', subData[1]));
777
+ const toAsset = AbiCoder.decodeParameter('address', subData[2]) as unknown as EthereumAddress;
778
+ const toAssetId = Number(AbiCoder.decodeParameter('uint16', subData[3]));
779
+ const marketAddr = AbiCoder.decodeParameter('address', subData[4]) as unknown as EthereumAddress;
780
+ const amountToSwitch = AbiCoder.decodeParameter('uint256', subData[5]) as unknown as string;
781
+ const user = AbiCoder.decodeParameter('address', subData[6]) as unknown as EthereumAddress;
782
+
783
+ return {
784
+ fromAsset, fromAssetId, toAsset, toAssetId, marketAddr, amountToSwitch, user,
785
+ };
786
+ },
787
+ };
788
+
738
789
  export const aaveV3DebtSwitchSubData = {
739
790
  encode(
740
791
  fromAsset: EthereumAddress,
@@ -104,6 +104,7 @@ export namespace Strategies {
104
104
  SPARK_GENERIC_FL_COLLATERAL_SWITCH = 167,
105
105
  AAVE_V3_DEBT_SWITCH = 168,
106
106
  AAVE_V3_DEBT_SWITCH_EOA = 169,
107
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 170,
107
108
  }
108
109
 
109
110
  export enum OptimismIds {
@@ -112,6 +113,7 @@ export namespace Strategies {
112
113
  AAVE_V3_COLLATERAL_SWITCH = 24,
113
114
  AAVE_V3_DEBT_SWITCH = 25,
114
115
  AAVE_V3_DEBT_SWITCH_EOA = 26,
116
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 27,
115
117
  }
116
118
 
117
119
  export enum BaseIds {
@@ -120,6 +122,7 @@ export namespace Strategies {
120
122
  AAVE_V3_COLLATERAL_SWITCH = 56,
121
123
  AAVE_V3_DEBT_SWITCH = 61,
122
124
  AAVE_V3_DEBT_SWITCH_EOA = 62,
125
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 63,
123
126
  }
124
127
 
125
128
  export enum ArbitrumIds {
@@ -128,6 +131,7 @@ export namespace Strategies {
128
131
  AAVE_V3_COLLATERAL_SWITCH = 50,
129
132
  AAVE_V3_DEBT_SWITCH = 55,
130
133
  AAVE_V3_DEBT_SWITCH_EOA = 56,
134
+ AAVE_V3_COLLATERAL_SWITCH_EOA = 57,
131
135
  }
132
136
 
133
137
  export enum Identifiers {