@defisaver/automation-sdk 3.3.22-coll-switch-generic-dev → 3.3.22

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 (52) hide show
  1. package/cjs/automation/private/StrategiesAutomation.d.ts +5 -1
  2. package/cjs/automation/private/StrategiesAutomation.js +12 -0
  3. package/cjs/automation/private/StrategiesAutomation.test.js +51 -0
  4. package/cjs/constants/index.js +0 -60
  5. package/cjs/services/apiSubscriptionsService.d.ts +7 -0
  6. package/cjs/services/apiSubscriptionsService.js +33 -0
  7. package/cjs/services/apiSubscriptionsService.test.d.ts +1 -0
  8. package/cjs/services/apiSubscriptionsService.test.js +67 -0
  9. package/cjs/services/strategiesService.js +1 -21
  10. package/cjs/services/strategiesService.test.js +0 -93
  11. package/cjs/services/strategySubService.d.ts +0 -2
  12. package/cjs/services/strategySubService.js +0 -12
  13. package/cjs/services/strategySubService.test.js +0 -107
  14. package/cjs/services/subDataService.d.ts +0 -24
  15. package/cjs/services/subDataService.js +2 -66
  16. package/cjs/services/subDataService.test.js +0 -139
  17. package/cjs/types/enums.d.ts +4 -18
  18. package/cjs/types/enums.js +0 -14
  19. package/cjs/types/index.d.ts +24 -2
  20. package/esm/automation/private/StrategiesAutomation.d.ts +5 -1
  21. package/esm/automation/private/StrategiesAutomation.js +12 -0
  22. package/esm/automation/private/StrategiesAutomation.test.js +51 -0
  23. package/esm/constants/index.js +0 -60
  24. package/esm/services/apiSubscriptionsService.d.ts +7 -0
  25. package/esm/services/apiSubscriptionsService.js +29 -0
  26. package/esm/services/apiSubscriptionsService.test.d.ts +1 -0
  27. package/esm/services/apiSubscriptionsService.test.js +65 -0
  28. package/esm/services/strategiesService.js +1 -21
  29. package/esm/services/strategiesService.test.js +1 -94
  30. package/esm/services/strategySubService.d.ts +0 -2
  31. package/esm/services/strategySubService.js +0 -12
  32. package/esm/services/strategySubService.test.js +0 -107
  33. package/esm/services/subDataService.d.ts +0 -24
  34. package/esm/services/subDataService.js +0 -64
  35. package/esm/services/subDataService.test.js +0 -139
  36. package/esm/types/enums.d.ts +4 -18
  37. package/esm/types/enums.js +0 -14
  38. package/esm/types/index.d.ts +24 -2
  39. package/package.json +1 -1
  40. package/src/automation/private/StrategiesAutomation.test.ts +65 -1
  41. package/src/automation/private/StrategiesAutomation.ts +17 -0
  42. package/src/constants/index.ts +0 -60
  43. package/src/services/apiSubscriptionsService.test.ts +73 -0
  44. package/src/services/apiSubscriptionsService.ts +33 -0
  45. package/src/services/strategiesService.test.ts +1 -103
  46. package/src/services/strategiesService.ts +1 -23
  47. package/src/services/strategySubService.test.ts +0 -131
  48. package/src/services/strategySubService.ts +0 -46
  49. package/src/services/subDataService.test.ts +0 -149
  50. package/src/services/subDataService.ts +0 -101
  51. package/src/types/enums.ts +0 -14
  52. package/src/types/index.ts +26 -2
@@ -91,34 +91,22 @@ export declare namespace Strategies {
91
91
  AAVE_V4_COLLATERAL_SWITCH = 154,
92
92
  AAVE_V4_COLLATERAL_SWITCH_EOA = 155,
93
93
  SPARK_COLLATERAL_SWITCH = 156,
94
- SPARK_GENERIC_FL_COLLATERAL_SWITCH = 167,
95
- AAVE_V3_DEBT_SWITCH = 168,
96
- AAVE_V3_DEBT_SWITCH_EOA = 169,
97
- AAVE_V3_COLLATERAL_SWITCH_EOA = 170
94
+ SPARK_GENERIC_FL_COLLATERAL_SWITCH = 167
98
95
  }
99
96
  enum OptimismIds {
100
97
  EXCHANGE_DCA = 8,
101
98
  EXCHANGE_LIMIT_ORDER = 9,
102
- AAVE_V3_COLLATERAL_SWITCH = 24,
103
- AAVE_V3_DEBT_SWITCH = 25,
104
- AAVE_V3_DEBT_SWITCH_EOA = 26,
105
- AAVE_V3_COLLATERAL_SWITCH_EOA = 27
99
+ AAVE_V3_COLLATERAL_SWITCH = 24
106
100
  }
107
101
  enum BaseIds {
108
102
  EXCHANGE_DCA = 8,
109
103
  EXCHANGE_LIMIT_ORDER = 9,
110
- AAVE_V3_COLLATERAL_SWITCH = 56,
111
- AAVE_V3_DEBT_SWITCH = 61,
112
- AAVE_V3_DEBT_SWITCH_EOA = 62,
113
- AAVE_V3_COLLATERAL_SWITCH_EOA = 63
104
+ AAVE_V3_COLLATERAL_SWITCH = 56
114
105
  }
115
106
  enum ArbitrumIds {
116
107
  EXCHANGE_DCA = 8,
117
108
  EXCHANGE_LIMIT_ORDER = 9,
118
- AAVE_V3_COLLATERAL_SWITCH = 50,
119
- AAVE_V3_DEBT_SWITCH = 55,
120
- AAVE_V3_DEBT_SWITCH_EOA = 56,
121
- AAVE_V3_COLLATERAL_SWITCH_EOA = 57
109
+ AAVE_V3_COLLATERAL_SWITCH = 50
122
110
  }
123
111
  enum Identifiers {
124
112
  SavingsLiqProtection = "smart-savings-liquidation-protection",
@@ -152,8 +140,6 @@ export declare namespace Strategies {
152
140
  EoaRepayOnPrice = "eoa-repay-on-price",
153
141
  CollateralSwitch = "collateral-switch",
154
142
  EoaCollateralSwitch = "eoa-collateral-switch",
155
- DebtSwitch = "debt-switch",
156
- EoaDebtSwitch = "eoa-debt-switch",
157
143
  LiquidationProtection = "liquidation-protection",
158
144
  EoaLiquidationProtection = "liquidation-protection-eoa"
159
145
  }
@@ -105,36 +105,24 @@ export var Strategies;
105
105
  MainnetIds[MainnetIds["AAVE_V4_COLLATERAL_SWITCH_EOA"] = 155] = "AAVE_V4_COLLATERAL_SWITCH_EOA";
106
106
  MainnetIds[MainnetIds["SPARK_COLLATERAL_SWITCH"] = 156] = "SPARK_COLLATERAL_SWITCH";
107
107
  MainnetIds[MainnetIds["SPARK_GENERIC_FL_COLLATERAL_SWITCH"] = 167] = "SPARK_GENERIC_FL_COLLATERAL_SWITCH";
108
- MainnetIds[MainnetIds["AAVE_V3_DEBT_SWITCH"] = 168] = "AAVE_V3_DEBT_SWITCH";
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";
111
108
  })(MainnetIds = Strategies.MainnetIds || (Strategies.MainnetIds = {}));
112
109
  let OptimismIds;
113
110
  (function (OptimismIds) {
114
111
  OptimismIds[OptimismIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
115
112
  OptimismIds[OptimismIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
116
113
  OptimismIds[OptimismIds["AAVE_V3_COLLATERAL_SWITCH"] = 24] = "AAVE_V3_COLLATERAL_SWITCH";
117
- OptimismIds[OptimismIds["AAVE_V3_DEBT_SWITCH"] = 25] = "AAVE_V3_DEBT_SWITCH";
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";
120
114
  })(OptimismIds = Strategies.OptimismIds || (Strategies.OptimismIds = {}));
121
115
  let BaseIds;
122
116
  (function (BaseIds) {
123
117
  BaseIds[BaseIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
124
118
  BaseIds[BaseIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
125
119
  BaseIds[BaseIds["AAVE_V3_COLLATERAL_SWITCH"] = 56] = "AAVE_V3_COLLATERAL_SWITCH";
126
- BaseIds[BaseIds["AAVE_V3_DEBT_SWITCH"] = 61] = "AAVE_V3_DEBT_SWITCH";
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";
129
120
  })(BaseIds = Strategies.BaseIds || (Strategies.BaseIds = {}));
130
121
  let ArbitrumIds;
131
122
  (function (ArbitrumIds) {
132
123
  ArbitrumIds[ArbitrumIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
133
124
  ArbitrumIds[ArbitrumIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
134
125
  ArbitrumIds[ArbitrumIds["AAVE_V3_COLLATERAL_SWITCH"] = 50] = "AAVE_V3_COLLATERAL_SWITCH";
135
- ArbitrumIds[ArbitrumIds["AAVE_V3_DEBT_SWITCH"] = 55] = "AAVE_V3_DEBT_SWITCH";
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";
138
126
  })(ArbitrumIds = Strategies.ArbitrumIds || (Strategies.ArbitrumIds = {}));
139
127
  let Identifiers;
140
128
  (function (Identifiers) {
@@ -169,8 +157,6 @@ export var Strategies;
169
157
  Identifiers["EoaRepayOnPrice"] = "eoa-repay-on-price";
170
158
  Identifiers["CollateralSwitch"] = "collateral-switch";
171
159
  Identifiers["EoaCollateralSwitch"] = "eoa-collateral-switch";
172
- Identifiers["DebtSwitch"] = "debt-switch";
173
- Identifiers["EoaDebtSwitch"] = "eoa-debt-switch";
174
160
  Identifiers["LiquidationProtection"] = "liquidation-protection";
175
161
  Identifiers["EoaLiquidationProtection"] = "liquidation-protection-eoa";
176
162
  })(Identifiers = Strategies.Identifiers || (Strategies.Identifiers = {}));
@@ -1,7 +1,7 @@
1
1
  import type Web3 from 'web3';
2
2
  import type { AbiItem } from 'web3-utils';
3
3
  import type { BaseContract, BlockType } from './contracts/generated/types';
4
- import type { Subscribe, StrategyModel } from './contracts/generated/SubStorage';
4
+ import type { StrategyModel } from './contracts/generated/SubStorage';
5
5
  import type { ChainId, Strategies, Bundles, ProtocolIdentifiers, RatioState, CloseToAssetType } from './enums';
6
6
  export type PlaceholderType = any;
7
7
  export type EthereumAddress = string;
@@ -53,6 +53,21 @@ interface _SubscriptionOptions {
53
53
  unexpiredOnly: boolean;
54
54
  }
55
55
  export type SubscriptionOptions = Partial<_SubscriptionOptions>;
56
+ /** Subscription record as returned by the automation API (GET /v1/subscriptions) */
57
+ export interface ApiSubscriptionRecord {
58
+ id: number;
59
+ wallet: EthereumAddress;
60
+ wallet_type: string;
61
+ is_enabled: boolean;
62
+ is_bundle: boolean;
63
+ strategy_or_bundle_id: number;
64
+ strategy_ids: number[];
65
+ sub_data_hash: string;
66
+ trigger_data: string[];
67
+ sub_data: string[];
68
+ block_number: number;
69
+ additional_triggers: string[] | null;
70
+ }
56
71
  export declare namespace Interfaces {
57
72
  interface ProtocolBase {
58
73
  id: ProtocolIdentifiers.StrategiesAutomation | ProtocolIdentifiers.LegacyAutomation;
@@ -291,10 +306,17 @@ export interface BundlesInfo {
291
306
  [ChainId.Base]: BaseBundleInfo;
292
307
  }
293
308
  export type StrategyOrBundleIds = typeof Strategies.MainnetIds[keyof typeof Strategies.MainnetIds] | typeof Strategies.OptimismIds[keyof typeof Strategies.OptimismIds] | typeof Strategies.ArbitrumIds[keyof typeof Strategies.ArbitrumIds] | typeof Strategies.BaseIds[keyof typeof Strategies.BaseIds] | typeof Bundles.MainnetIds[keyof typeof Bundles.MainnetIds] | typeof Bundles.OptimismIds[keyof typeof Bundles.OptimismIds] | typeof Bundles.ArbitrumIds[keyof typeof Bundles.ArbitrumIds] | typeof Bundles.BaseIds[keyof typeof Bundles.BaseIds];
309
+ /** Fields of the Subscribe event that parsing relies on */
310
+ export interface SubscriptionEventData {
311
+ subId: string;
312
+ proxy: EthereumAddress;
313
+ subHash: string;
314
+ subStruct: StrategyModel.StrategySubStructOutputStruct;
315
+ }
294
316
  export interface ParseData {
295
317
  chainId: ChainId;
296
318
  blockNumber: BlockNumber;
297
- subscriptionEventData: Subscribe['returnValues'];
319
+ subscriptionEventData: SubscriptionEventData;
298
320
  strategiesSubsData: StrategyModel.StoredSubDataStructOutputStruct;
299
321
  }
300
322
  type MapToProtocolVersion<T> = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/automation-sdk",
3
- "version": "3.3.22-coll-switch-generic-dev",
3
+ "version": "3.3.22",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -1,7 +1,8 @@
1
1
  import Web3 from 'web3';
2
2
  import { expect } from 'chai';
3
3
 
4
- import {ChainId} from '../../types/enums';
4
+ import { ChainId } from '../../types/enums';
5
+ import type { ApiSubscriptionRecord } from '../../types';
5
6
 
6
7
  import '../../configuration';
7
8
  import StrategiesAutomation from './StrategiesAutomation';
@@ -700,4 +701,67 @@ describe('Feature: StrategiesAutomation.ts', () => {
700
701
  expect(loneBoost?.subId).to.equal(1);
701
702
  });
702
703
  });
704
+
705
+ describe('When testing StrategiesAutomation.parseSubscriptionsFromApi', () => {
706
+ const strategiesAutomation = new StrategiesAutomation({
707
+ chainId: ChainId.Ethereum,
708
+ provider: Web3_1,
709
+ providerFork: null!,
710
+ });
711
+
712
+ const owner = '0x9cB7E19861665366011899d74E75d4F2A419aEeD';
713
+ const subData = [
714
+ '0x0000000000000000000000000000000000000000000000001bc16d674ec80000',
715
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
716
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
717
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
718
+ ];
719
+ // Aave V3 leverage management: repay (bundle 8, ratio under) and boost (bundle 9, ratio over) for the same owner and market
720
+ const repay: ApiSubscriptionRecord = {
721
+ id: 379,
722
+ wallet: owner,
723
+ wallet_type: 'safe',
724
+ is_enabled: true,
725
+ is_bundle: true,
726
+ strategy_or_bundle_id: 8,
727
+ strategy_ids: [34, 35],
728
+ sub_data_hash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
729
+ trigger_data: ['0000000000000000000000009cb7e19861665366011899d74e75d4f2a419aeed0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e00000000000000000000000000000000000000000000000019ac8532c27900000000000000000000000000000000000000000000000000000000000000000001'],
730
+ sub_data: subData,
731
+ block_number: 18015756,
732
+ additional_triggers: null,
733
+ };
734
+ const boost: ApiSubscriptionRecord = {
735
+ ...repay,
736
+ id: 380,
737
+ is_enabled: false,
738
+ strategy_or_bundle_id: 9,
739
+ sub_data_hash: '0x1111111111111111111111111111111111111111111111111111111111111111',
740
+ trigger_data: ['0000000000000000000000009cb7e19861665366011899d74e75d4f2a419aeed0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e0000000000000000000000000000000000000000000000002386f26fc10000000000000000000000000000000000000000000000000000000000000000000000'],
741
+ };
742
+
743
+ it('Given API records should return parsed positions', () => {
744
+ const positions = strategiesAutomation.parseSubscriptionsFromApi([repay, boost]);
745
+ expect(positions).to.have.length(2);
746
+ expect(positions.map((p) => p?.subId)).to.eql([379, 380]);
747
+ expect(positions.map((p) => p?.isEnabled)).to.eql([true, false]);
748
+ });
749
+
750
+ it('Given mergeSubs option should merge the repay and boost pair', () => {
751
+ const positions = strategiesAutomation.parseSubscriptionsFromApi([repay, boost], { mergeSubs: true });
752
+ expect(positions).to.have.length(1);
753
+ expect(positions[0]?.subIds).to.eql([379, 380]);
754
+ expect(positions[0]?.isEnabled).to.equal(true);
755
+ });
756
+
757
+ it('Given enabledOnly option should drop disabled records before parsing', () => {
758
+ const positions = strategiesAutomation.parseSubscriptionsFromApi([repay, boost], { enabledOnly: true });
759
+ expect(positions.map((p) => p?.subId)).to.eql([379]);
760
+ });
761
+
762
+ it('Given a record of an unknown strategy should return null for it', () => {
763
+ const positions = strategiesAutomation.parseSubscriptionsFromApi([{ ...repay, strategy_or_bundle_id: 9999 }]);
764
+ expect(positions).to.eql([null]);
765
+ });
766
+ });
703
767
  });
@@ -4,6 +4,7 @@ import type { PastEventOptions } from 'web3-eth-contract';
4
4
  import PromisePool from 'es6-promise-pool';
5
5
  import type {
6
6
  Position, Interfaces, EthereumAddress, SubscriptionOptions, Contract, ParseData, PlaceholderType, BlockNumber,
7
+ ApiSubscriptionRecord,
7
8
  } from '../../types';
8
9
  import type {
9
10
  StrategyModel, Subscribe, SubStorage, UpdateData,
@@ -15,6 +16,7 @@ import { addToObjectIf, isDefined, isUndefined } from '../../services/utils';
15
16
  import { getAbiItem, makeSubStorageContract } from '../../services/contractService';
16
17
  import { getEventsFromContract, multicall } from '../../services/ethereumService';
17
18
  import { parseStrategiesAutomatedPosition } from '../../services/strategiesService';
19
+ import { parseDataFromApiSubscription } from '../../services/apiSubscriptionsService';
18
20
 
19
21
  import Automation from './Automation';
20
22
 
@@ -259,6 +261,21 @@ export default class StrategiesAutomation extends Automation {
259
261
  return this._getSubscriptions(undefined, options);
260
262
  }
261
263
 
264
+ /**
265
+ * @description Parses subscriptions returned by the automation API (GET /v1/subscriptions)
266
+ */
267
+ public parseSubscriptionsFromApi(records: ApiSubscriptionRecord[], options?: SubscriptionOptions): (Position.Automated | null)[] {
268
+ const filtered = options?.enabledOnly ? records.filter((record) => record.is_enabled) : records;
269
+
270
+ let subscriptions = filtered.map((record) => this.getParsedSubscriptions(parseDataFromApiSubscription(record, this.chainId)));
271
+
272
+ if (options?.mergeSubs) {
273
+ subscriptions = this.mergeSubs(subscriptions);
274
+ }
275
+
276
+ return options?.unexpiredOnly ? this.removeExpiredSubscriptions(subscriptions) : subscriptions;
277
+ }
278
+
262
279
  public async getSubscriptionsFor(addresses: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]> {
263
280
  return this._getSubscriptions(addresses, options);
264
281
  }
@@ -125,11 +125,6 @@ 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
- },
133
128
  [Strategies.MainnetIds.AAVE_V4_COLLATERAL_SWITCH]: {
134
129
  strategyOrBundleId: Strategies.MainnetIds.AAVE_V4_COLLATERAL_SWITCH,
135
130
  strategyId: Strategies.Identifiers.CollateralSwitch,
@@ -150,16 +145,6 @@ export const MAINNET_STRATEGIES_INFO: MainnetStrategiesInfo = {
150
145
  strategyId: Strategies.Identifiers.EoaCollateralSwitch,
151
146
  protocol: PROTOCOLS.Spark,
152
147
  },
153
- [Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH]: {
154
- strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH,
155
- strategyId: Strategies.Identifiers.DebtSwitch,
156
- protocol: PROTOCOLS.AaveV3,
157
- },
158
- [Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH_EOA]: {
159
- strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH_EOA,
160
- strategyId: Strategies.Identifiers.EoaDebtSwitch,
161
- protocol: PROTOCOLS.AaveV3,
162
- },
163
148
  };
164
149
 
165
150
  export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
@@ -178,21 +163,6 @@ export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
178
163
  strategyId: Strategies.Identifiers.CollateralSwitch,
179
164
  protocol: PROTOCOLS.AaveV3,
180
165
  },
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
- },
186
- [Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH]: {
187
- strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH,
188
- strategyId: Strategies.Identifiers.DebtSwitch,
189
- protocol: PROTOCOLS.AaveV3,
190
- },
191
- [Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH_EOA]: {
192
- strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH_EOA,
193
- strategyId: Strategies.Identifiers.EoaDebtSwitch,
194
- protocol: PROTOCOLS.AaveV3,
195
- },
196
166
  };
197
167
 
198
168
  export const BASE_STRATEGIES_INFO: BaseStrategiesInfo = {
@@ -211,21 +181,6 @@ export const BASE_STRATEGIES_INFO: BaseStrategiesInfo = {
211
181
  strategyId: Strategies.Identifiers.CollateralSwitch,
212
182
  protocol: PROTOCOLS.AaveV3,
213
183
  },
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
- },
219
- [Strategies.BaseIds.AAVE_V3_DEBT_SWITCH]: {
220
- strategyOrBundleId: Strategies.BaseIds.AAVE_V3_DEBT_SWITCH,
221
- strategyId: Strategies.Identifiers.DebtSwitch,
222
- protocol: PROTOCOLS.AaveV3,
223
- },
224
- [Strategies.BaseIds.AAVE_V3_DEBT_SWITCH_EOA]: {
225
- strategyOrBundleId: Strategies.BaseIds.AAVE_V3_DEBT_SWITCH_EOA,
226
- strategyId: Strategies.Identifiers.EoaDebtSwitch,
227
- protocol: PROTOCOLS.AaveV3,
228
- },
229
184
  };
230
185
 
231
186
  export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
@@ -244,21 +199,6 @@ export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
244
199
  strategyId: Strategies.Identifiers.CollateralSwitch,
245
200
  protocol: PROTOCOLS.AaveV3,
246
201
  },
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
- },
252
- [Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH]: {
253
- strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH,
254
- strategyId: Strategies.Identifiers.DebtSwitch,
255
- protocol: PROTOCOLS.AaveV3,
256
- },
257
- [Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH_EOA]: {
258
- strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH_EOA,
259
- strategyId: Strategies.Identifiers.EoaDebtSwitch,
260
- protocol: PROTOCOLS.AaveV3,
261
- },
262
202
  };
263
203
 
264
204
  export const STRATEGIES_INFO: StrategiesInfo = {
@@ -0,0 +1,73 @@
1
+ import { expect } from 'chai';
2
+
3
+ import type { ApiSubscriptionRecord, ParseData } from '../types';
4
+ import { ChainId } from '../types/enums';
5
+
6
+ import '../configuration';
7
+ import { parseDataFromApiSubscription } from './apiSubscriptionsService';
8
+ import { parseStrategiesAutomatedPosition } from './strategiesService';
9
+
10
+ describe('Feature: apiSubscriptionsService.ts', () => {
11
+ describe('When testing apiSubscriptionsService.parseDataFromApiSubscription', () => {
12
+ // same subscription as in strategiesService.test.ts, in the shape the automation API returns it
13
+ const record: ApiSubscriptionRecord = {
14
+ id: 379,
15
+ wallet: '0x9cB7E19861665366011899d74E75d4F2A419aEeD',
16
+ wallet_type: 'safe',
17
+ is_enabled: true,
18
+ is_bundle: true,
19
+ strategy_or_bundle_id: 8,
20
+ strategy_ids: [34, 35],
21
+ sub_data_hash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
22
+ trigger_data: [
23
+ '0000000000000000000000009cb7e19861665366011899d74e75d4f2a419aeed0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e00000000000000000000000000000000000000000000000019ac8532c27900000000000000000000000000000000000000000000000000000000000000000001',
24
+ ],
25
+ sub_data: [
26
+ '0x0000000000000000000000000000000000000000000000001bc16d674ec80000',
27
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
28
+ '0x0000000000000000000000000000000000000000000000000000000000000001',
29
+ '0x0000000000000000000000000000000000000000000000000000000000000000',
30
+ ],
31
+ block_number: 18015756,
32
+ additional_triggers: null,
33
+ };
34
+
35
+ const fromEvents: ParseData = {
36
+ chainId: ChainId.Ethereum,
37
+ blockNumber: 18015756,
38
+ subscriptionEventData: {
39
+ subId: '379',
40
+ proxy: '0x9cB7E19861665366011899d74E75d4F2A419aEeD',
41
+ subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
42
+ subStruct: {
43
+ strategyOrBundleId: '8',
44
+ isBundle: true,
45
+ triggerData: [
46
+ '0x0000000000000000000000009cb7e19861665366011899d74e75d4f2a419aeed0000000000000000000000002f39d218133afab8f2b819b1066c7e434ad94e9e00000000000000000000000000000000000000000000000019ac8532c27900000000000000000000000000000000000000000000000000000000000000000001',
47
+ ],
48
+ subData: record.sub_data,
49
+ },
50
+ },
51
+ strategiesSubsData: {
52
+ userProxy: '0x9cB7E19861665366011899d74E75d4F2A419aEeD',
53
+ isEnabled: true,
54
+ strategySubHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
55
+ },
56
+ };
57
+
58
+ it('Given an API record should return the same parse data as Subscribe event and SubStorage would', () => {
59
+ expect(parseDataFromApiSubscription(record, ChainId.Ethereum)).to.eql(fromEvents);
60
+ });
61
+
62
+ it('Given an API record the parsed position should match the one parsed from events', () => {
63
+ const fromApi = parseStrategiesAutomatedPosition(parseDataFromApiSubscription(record, ChainId.Ethereum));
64
+ expect(fromApi).to.not.equal(null);
65
+ expect(fromApi).to.eql(parseStrategiesAutomatedPosition(fromEvents));
66
+ });
67
+
68
+ it('Given a disabled record should keep it disabled', () => {
69
+ const parseData = parseDataFromApiSubscription({ ...record, is_enabled: false }, ChainId.Ethereum);
70
+ expect(parseData.strategiesSubsData.isEnabled).to.equal(false);
71
+ });
72
+ });
73
+ });
@@ -0,0 +1,33 @@
1
+ import type { ApiSubscriptionRecord, ParseData } from '../types';
2
+ import type { ChainId } from '../types/enums';
3
+
4
+ function addHexPrefix(value: string): string {
5
+ return value.startsWith('0x') ? value : `0x${value}`;
6
+ }
7
+
8
+ /**
9
+ * @description Maps a subscription record returned by the automation API to the data
10
+ * the parser expects from Subscribe events and SubStorage (trigger data is stored without 0x prefix)
11
+ */
12
+ export function parseDataFromApiSubscription(record: ApiSubscriptionRecord, chainId: ChainId): ParseData {
13
+ return {
14
+ chainId,
15
+ blockNumber: record.block_number,
16
+ subscriptionEventData: {
17
+ subId: record.id.toString(),
18
+ proxy: record.wallet,
19
+ subHash: record.sub_data_hash,
20
+ subStruct: {
21
+ strategyOrBundleId: record.strategy_or_bundle_id.toString(),
22
+ isBundle: record.is_bundle,
23
+ triggerData: record.trigger_data.map(addHexPrefix),
24
+ subData: record.sub_data.map(addHexPrefix),
25
+ },
26
+ },
27
+ strategiesSubsData: {
28
+ userProxy: record.wallet,
29
+ isEnabled: record.is_enabled,
30
+ strategySubHash: record.sub_data_hash,
31
+ },
32
+ };
33
+ }
@@ -1,113 +1,12 @@
1
1
  import { expect } from 'chai';
2
2
 
3
- import { ChainId, ProtocolIdentifiers, RatioState, Strategies } from '../types/enums';
3
+ import { ProtocolIdentifiers, 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
-
111
10
  describe('When testing strategiesService.parseStrategiesAutomatedPosition', async () => {
112
11
  // TODO: we should probably write this for every strategy?
113
12
  const examples: Array<[Position.Automated | null, ParseData]> = [
@@ -177,7 +76,6 @@ describe('Feature: strategiesService.ts', () => {
177
76
  subId: '379',
178
77
  proxy: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
179
78
  subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
180
- // @ts-ignore
181
79
  subStruct:
182
80
  {
183
81
  strategyOrBundleId: '8',
@@ -434,31 +434,12 @@ function parseAaveV3CloseOnPrice(position: Position.Automated, parseData: ParseD
434
434
  }
435
435
 
436
436
  function parseAaveV3CollateralSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
437
- const _position = cloneDeep(position);
438
- const { subStruct } = parseData.subscriptionEventData;
439
- const isEOA = _position.strategy.strategyId.includes('eoa');
440
- const triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
441
- const subData = isEOA
442
- ? subDataService.aaveV3GenericFLCollateralSwitchSubData.decode(subStruct.subData)
443
- : subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
444
- _position.strategyData.decoded.triggerData = triggerData;
445
- _position.strategyData.decoded.subData = subData;
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;
450
-
451
- return _position;
452
- }
453
-
454
- function parseAaveV3DebtSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
455
437
  const _position = cloneDeep(position);
456
438
  const { subStruct } = parseData.subscriptionEventData;
457
439
  const triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
458
- const subData = subDataService.aaveV3DebtSwitchSubData.decode(subStruct.subData);
440
+ const subData = subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
459
441
  _position.strategyData.decoded.triggerData = triggerData;
460
442
  _position.strategyData.decoded.subData = subData;
461
- // TODO -> This isn't enough for ID
462
443
  _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, subData.marketAddr);
463
444
 
464
445
  return _position;
@@ -1616,9 +1597,6 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
1616
1597
  [Strategies.Identifiers.EoaBoostOnPrice]: parseAaveV3LeverageManagementOnPrice,
1617
1598
  [Strategies.Identifiers.EoaCloseOnPrice]: parseAaveV3CloseOnPrice,
1618
1599
  [Strategies.Identifiers.CollateralSwitch]: parseAaveV3CollateralSwitch,
1619
- [Strategies.Identifiers.EoaCollateralSwitch]: parseAaveV3CollateralSwitch,
1620
- [Strategies.Identifiers.DebtSwitch]: parseAaveV3DebtSwitch,
1621
- [Strategies.Identifiers.EoaDebtSwitch]: parseAaveV3DebtSwitch,
1622
1600
  [Strategies.Identifiers.LiquidationProtection]: parseAaveV3LiquidationProtection,
1623
1601
  [Strategies.Identifiers.EoaLiquidationProtection]: parseAaveV3LiquidationProtection,
1624
1602
  },