@defisaver/automation-sdk 3.3.22-instant-twap-close-dev → 3.3.23

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 +40 -40
  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 +8 -21
  10. package/cjs/services/strategiesService.test.js +0 -63
  11. package/cjs/services/strategySubService.d.ts +1 -1
  12. package/cjs/services/strategySubService.js +6 -7
  13. package/cjs/services/strategySubService.test.js +71 -111
  14. package/cjs/services/subDataService.d.ts +10 -12
  15. package/cjs/services/subDataService.js +30 -36
  16. package/cjs/services/subDataService.test.js +104 -70
  17. package/cjs/types/enums.d.ts +18 -18
  18. package/cjs/types/enums.js +10 -11
  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 +40 -40
  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 +8 -21
  29. package/esm/services/strategiesService.test.js +1 -64
  30. package/esm/services/strategySubService.d.ts +1 -1
  31. package/esm/services/strategySubService.js +6 -7
  32. package/esm/services/strategySubService.test.js +71 -111
  33. package/esm/services/subDataService.d.ts +10 -12
  34. package/esm/services/subDataService.js +29 -35
  35. package/esm/services/subDataService.test.js +104 -70
  36. package/esm/types/enums.d.ts +18 -18
  37. package/esm/types/enums.js +10 -11
  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 +40 -40
  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 -79
  46. package/src/services/strategiesService.ts +8 -27
  47. package/src/services/strategySubService.test.ts +84 -125
  48. package/src/services/strategySubService.ts +16 -20
  49. package/src/services/subDataService.test.ts +108 -98
  50. package/src/services/subDataService.ts +40 -51
  51. package/src/types/enums.ts +10 -11
  52. package/src/types/index.ts +26 -2
@@ -105,24 +105,32 @@ 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";
108
110
  })(MainnetIds = Strategies.MainnetIds || (Strategies.MainnetIds = {}));
109
111
  let OptimismIds;
110
112
  (function (OptimismIds) {
111
113
  OptimismIds[OptimismIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
112
114
  OptimismIds[OptimismIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
113
115
  OptimismIds[OptimismIds["AAVE_V3_COLLATERAL_SWITCH"] = 24] = "AAVE_V3_COLLATERAL_SWITCH";
116
+ OptimismIds[OptimismIds["AAVE_V3_DEBT_SWITCH"] = 25] = "AAVE_V3_DEBT_SWITCH";
117
+ OptimismIds[OptimismIds["AAVE_V3_DEBT_SWITCH_EOA"] = 26] = "AAVE_V3_DEBT_SWITCH_EOA";
114
118
  })(OptimismIds = Strategies.OptimismIds || (Strategies.OptimismIds = {}));
115
119
  let BaseIds;
116
120
  (function (BaseIds) {
117
121
  BaseIds[BaseIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
118
122
  BaseIds[BaseIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
119
123
  BaseIds[BaseIds["AAVE_V3_COLLATERAL_SWITCH"] = 56] = "AAVE_V3_COLLATERAL_SWITCH";
124
+ BaseIds[BaseIds["AAVE_V3_DEBT_SWITCH"] = 61] = "AAVE_V3_DEBT_SWITCH";
125
+ BaseIds[BaseIds["AAVE_V3_DEBT_SWITCH_EOA"] = 62] = "AAVE_V3_DEBT_SWITCH_EOA";
120
126
  })(BaseIds = Strategies.BaseIds || (Strategies.BaseIds = {}));
121
127
  let ArbitrumIds;
122
128
  (function (ArbitrumIds) {
123
129
  ArbitrumIds[ArbitrumIds["EXCHANGE_DCA"] = 8] = "EXCHANGE_DCA";
124
130
  ArbitrumIds[ArbitrumIds["EXCHANGE_LIMIT_ORDER"] = 9] = "EXCHANGE_LIMIT_ORDER";
125
131
  ArbitrumIds[ArbitrumIds["AAVE_V3_COLLATERAL_SWITCH"] = 50] = "AAVE_V3_COLLATERAL_SWITCH";
132
+ ArbitrumIds[ArbitrumIds["AAVE_V3_DEBT_SWITCH"] = 55] = "AAVE_V3_DEBT_SWITCH";
133
+ ArbitrumIds[ArbitrumIds["AAVE_V3_DEBT_SWITCH_EOA"] = 56] = "AAVE_V3_DEBT_SWITCH_EOA";
126
134
  })(ArbitrumIds = Strategies.ArbitrumIds || (Strategies.ArbitrumIds = {}));
127
135
  let Identifiers;
128
136
  (function (Identifiers) {
@@ -141,8 +149,6 @@ export var Strategies;
141
149
  Identifiers["CloseOnPriceToColl"] = "close-on-price-to-collateral";
142
150
  Identifiers["CloseOnPrice"] = "close-on-price";
143
151
  Identifiers["EoaCloseOnPrice"] = "eoa-close-on-price";
144
- Identifiers["InstantCloseOnPrice"] = "instant-close-on-price";
145
- Identifiers["EoaInstantCloseOnPrice"] = "eoa-instant-close-on-price";
146
152
  Identifiers["TrailingStopToColl"] = "trailing-stop-to-collateral";
147
153
  Identifiers["TrailingStopToDebt"] = "trailing-stop-to-debt";
148
154
  Identifiers["Rebond"] = "rebond";
@@ -159,6 +165,8 @@ export var Strategies;
159
165
  Identifiers["EoaRepayOnPrice"] = "eoa-repay-on-price";
160
166
  Identifiers["CollateralSwitch"] = "collateral-switch";
161
167
  Identifiers["EoaCollateralSwitch"] = "eoa-collateral-switch";
168
+ Identifiers["DebtSwitch"] = "debt-switch";
169
+ Identifiers["EoaDebtSwitch"] = "eoa-debt-switch";
162
170
  Identifiers["LiquidationProtection"] = "liquidation-protection";
163
171
  Identifiers["EoaLiquidationProtection"] = "liquidation-protection-eoa";
164
172
  })(Identifiers = Strategies.Identifiers || (Strategies.Identifiers = {}));
@@ -273,8 +281,6 @@ export var Bundles;
273
281
  MainnetIds[MainnetIds["SPARK_EOA_BOOST_ON_PRICE"] = 91] = "SPARK_EOA_BOOST_ON_PRICE";
274
282
  MainnetIds[MainnetIds["SPARK_EOA_CLOSE"] = 92] = "SPARK_EOA_CLOSE";
275
283
  MainnetIds[MainnetIds["SPARK_EOA_LIQUIDATION_PROTECTION"] = 93] = "SPARK_EOA_LIQUIDATION_PROTECTION";
276
- MainnetIds[MainnetIds["AAVE_V3_SW_INSTANT_CLOSE"] = 94] = "AAVE_V3_SW_INSTANT_CLOSE";
277
- MainnetIds[MainnetIds["AAVE_V3_EOA_INSTANT_CLOSE"] = 95] = "AAVE_V3_EOA_INSTANT_CLOSE";
278
284
  })(MainnetIds = Bundles.MainnetIds || (Bundles.MainnetIds = {}));
279
285
  let OptimismIds;
280
286
  (function (OptimismIds) {
@@ -291,9 +297,6 @@ export var Bundles;
291
297
  OptimismIds[OptimismIds["AAVE_V3_EOA_CLOSE"] = 10] = "AAVE_V3_EOA_CLOSE";
292
298
  OptimismIds[OptimismIds["AAVE_V3_SW_LIQUIDATION_PROTECTION"] = 11] = "AAVE_V3_SW_LIQUIDATION_PROTECTION";
293
299
  OptimismIds[OptimismIds["AAVE_V3_EOA_LIQUIDATION_PROTECTION"] = 12] = "AAVE_V3_EOA_LIQUIDATION_PROTECTION";
294
- // TODO -> Fix ids
295
- OptimismIds[OptimismIds["AAVE_V3_SW_INSTANT_CLOSE"] = 13] = "AAVE_V3_SW_INSTANT_CLOSE";
296
- OptimismIds[OptimismIds["AAVE_V3_EOA_INSTANT_CLOSE"] = 14] = "AAVE_V3_EOA_INSTANT_CLOSE";
297
300
  })(OptimismIds = Bundles.OptimismIds || (Bundles.OptimismIds = {}));
298
301
  let BaseIds;
299
302
  (function (BaseIds) {
@@ -337,8 +340,6 @@ export var Bundles;
337
340
  BaseIds[BaseIds["MORPHO_BLUE_EOA_REPAY_ON_PRICE"] = 40] = "MORPHO_BLUE_EOA_REPAY_ON_PRICE";
338
341
  BaseIds[BaseIds["MORPHO_BLUE_EOA_CLOSE"] = 41] = "MORPHO_BLUE_EOA_CLOSE";
339
342
  BaseIds[BaseIds["MORPHO_BLUE_EOA_LIQUIDATION_PROTECTION"] = 42] = "MORPHO_BLUE_EOA_LIQUIDATION_PROTECTION";
340
- BaseIds[BaseIds["AAVE_V3_SW_INSTANT_CLOSE"] = 43] = "AAVE_V3_SW_INSTANT_CLOSE";
341
- BaseIds[BaseIds["AAVE_V3_EOA_INSTANT_CLOSE"] = 44] = "AAVE_V3_EOA_INSTANT_CLOSE";
342
343
  })(BaseIds = Bundles.BaseIds || (Bundles.BaseIds = {}));
343
344
  let ArbitrumIds;
344
345
  (function (ArbitrumIds) {
@@ -382,7 +383,5 @@ export var Bundles;
382
383
  ArbitrumIds[ArbitrumIds["MORPHO_BLUE_EOA_BOOST_ON_PRICE"] = 37] = "MORPHO_BLUE_EOA_BOOST_ON_PRICE";
383
384
  ArbitrumIds[ArbitrumIds["MORPHO_BLUE_EOA_REPAY_ON_PRICE"] = 38] = "MORPHO_BLUE_EOA_REPAY_ON_PRICE";
384
385
  ArbitrumIds[ArbitrumIds["MORPHO_BLUE_EOA_CLOSE"] = 39] = "MORPHO_BLUE_EOA_CLOSE";
385
- ArbitrumIds[ArbitrumIds["AAVE_V3_SW_INSTANT_CLOSE"] = 40] = "AAVE_V3_SW_INSTANT_CLOSE";
386
- ArbitrumIds[ArbitrumIds["AAVE_V3_EOA_INSTANT_CLOSE"] = 41] = "AAVE_V3_EOA_INSTANT_CLOSE";
387
386
  })(ArbitrumIds = Bundles.ArbitrumIds || (Bundles.ArbitrumIds = {}));
388
387
  })(Bundles || (Bundles = {}));
@@ -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-instant-twap-close-dev",
3
+ "version": "3.3.23",
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
  }
@@ -145,6 +145,16 @@ export const MAINNET_STRATEGIES_INFO: MainnetStrategiesInfo = {
145
145
  strategyId: Strategies.Identifiers.EoaCollateralSwitch,
146
146
  protocol: PROTOCOLS.Spark,
147
147
  },
148
+ [Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH]: {
149
+ strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH,
150
+ strategyId: Strategies.Identifiers.DebtSwitch,
151
+ protocol: PROTOCOLS.AaveV3,
152
+ },
153
+ [Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH_EOA]: {
154
+ strategyOrBundleId: Strategies.MainnetIds.AAVE_V3_DEBT_SWITCH_EOA,
155
+ strategyId: Strategies.Identifiers.EoaDebtSwitch,
156
+ protocol: PROTOCOLS.AaveV3,
157
+ },
148
158
  };
149
159
 
150
160
  export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
@@ -163,6 +173,16 @@ export const OPTIMISM_STRATEGIES_INFO: OptimismStrategiesInfo = {
163
173
  strategyId: Strategies.Identifiers.CollateralSwitch,
164
174
  protocol: PROTOCOLS.AaveV3,
165
175
  },
176
+ [Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH]: {
177
+ strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH,
178
+ strategyId: Strategies.Identifiers.DebtSwitch,
179
+ protocol: PROTOCOLS.AaveV3,
180
+ },
181
+ [Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH_EOA]: {
182
+ strategyOrBundleId: Strategies.OptimismIds.AAVE_V3_DEBT_SWITCH_EOA,
183
+ strategyId: Strategies.Identifiers.EoaDebtSwitch,
184
+ protocol: PROTOCOLS.AaveV3,
185
+ },
166
186
  };
167
187
 
168
188
  export const BASE_STRATEGIES_INFO: BaseStrategiesInfo = {
@@ -181,6 +201,16 @@ export const BASE_STRATEGIES_INFO: BaseStrategiesInfo = {
181
201
  strategyId: Strategies.Identifiers.CollateralSwitch,
182
202
  protocol: PROTOCOLS.AaveV3,
183
203
  },
204
+ [Strategies.BaseIds.AAVE_V3_DEBT_SWITCH]: {
205
+ strategyOrBundleId: Strategies.BaseIds.AAVE_V3_DEBT_SWITCH,
206
+ strategyId: Strategies.Identifiers.DebtSwitch,
207
+ protocol: PROTOCOLS.AaveV3,
208
+ },
209
+ [Strategies.BaseIds.AAVE_V3_DEBT_SWITCH_EOA]: {
210
+ strategyOrBundleId: Strategies.BaseIds.AAVE_V3_DEBT_SWITCH_EOA,
211
+ strategyId: Strategies.Identifiers.EoaDebtSwitch,
212
+ protocol: PROTOCOLS.AaveV3,
213
+ },
184
214
  };
185
215
 
186
216
  export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
@@ -199,6 +229,16 @@ export const ARBITRUM_STRATEGIES_INFO: ArbitrumStrategiesInfo = {
199
229
  strategyId: Strategies.Identifiers.CollateralSwitch,
200
230
  protocol: PROTOCOLS.AaveV3,
201
231
  },
232
+ [Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH]: {
233
+ strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH,
234
+ strategyId: Strategies.Identifiers.DebtSwitch,
235
+ protocol: PROTOCOLS.AaveV3,
236
+ },
237
+ [Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH_EOA]: {
238
+ strategyOrBundleId: Strategies.ArbitrumIds.AAVE_V3_DEBT_SWITCH_EOA,
239
+ strategyId: Strategies.Identifiers.EoaDebtSwitch,
240
+ protocol: PROTOCOLS.AaveV3,
241
+ },
202
242
  };
203
243
 
204
244
  export const STRATEGIES_INFO: StrategiesInfo = {
@@ -684,16 +724,6 @@ export const MAINNET_BUNDLES_INFO: MainnetBundleInfo = {
684
724
  strategyId: Strategies.Identifiers.EoaLiquidationProtection,
685
725
  protocol: PROTOCOLS.Spark,
686
726
  },
687
- [Bundles.MainnetIds.AAVE_V3_SW_INSTANT_CLOSE]: {
688
- strategyOrBundleId: Bundles.MainnetIds.AAVE_V3_SW_INSTANT_CLOSE,
689
- strategyId: Strategies.Identifiers.InstantCloseOnPrice,
690
- protocol: PROTOCOLS.AaveV3,
691
- },
692
- [Bundles.MainnetIds.AAVE_V3_EOA_INSTANT_CLOSE]: {
693
- strategyOrBundleId: Bundles.MainnetIds.AAVE_V3_EOA_INSTANT_CLOSE,
694
- strategyId: Strategies.Identifiers.EoaInstantCloseOnPrice,
695
- protocol: PROTOCOLS.AaveV3,
696
- },
697
727
  };
698
728
 
699
729
  export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
@@ -762,16 +792,6 @@ export const OPTIMISM_BUNDLES_INFO: OptimismBundleInfo = {
762
792
  strategyId: Strategies.Identifiers.EoaLiquidationProtection,
763
793
  protocol: PROTOCOLS.AaveV3,
764
794
  },
765
- [Bundles.OptimismIds.AAVE_V3_SW_INSTANT_CLOSE]: {
766
- strategyOrBundleId: Bundles.OptimismIds.AAVE_V3_SW_INSTANT_CLOSE,
767
- strategyId: Strategies.Identifiers.InstantCloseOnPrice,
768
- protocol: PROTOCOLS.AaveV3,
769
- },
770
- [Bundles.OptimismIds.AAVE_V3_EOA_INSTANT_CLOSE]: {
771
- strategyOrBundleId: Bundles.OptimismIds.AAVE_V3_EOA_INSTANT_CLOSE,
772
- strategyId: Strategies.Identifiers.EoaInstantCloseOnPrice,
773
- protocol: PROTOCOLS.AaveV3,
774
- },
775
795
  };
776
796
 
777
797
  export const BASE_BUNDLES_INFO: BaseBundleInfo = {
@@ -975,16 +995,6 @@ export const BASE_BUNDLES_INFO: BaseBundleInfo = {
975
995
  strategyId: Strategies.Identifiers.EoaCloseOnPrice,
976
996
  protocol: PROTOCOLS.MorphoBlue,
977
997
  },
978
- [Bundles.BaseIds.AAVE_V3_SW_INSTANT_CLOSE]: {
979
- strategyOrBundleId: Bundles.BaseIds.AAVE_V3_SW_INSTANT_CLOSE,
980
- strategyId: Strategies.Identifiers.InstantCloseOnPrice,
981
- protocol: PROTOCOLS.AaveV3,
982
- },
983
- [Bundles.BaseIds.AAVE_V3_EOA_INSTANT_CLOSE]: {
984
- strategyOrBundleId: Bundles.BaseIds.AAVE_V3_EOA_INSTANT_CLOSE,
985
- strategyId: Strategies.Identifiers.EoaInstantCloseOnPrice,
986
- protocol: PROTOCOLS.AaveV3,
987
- },
988
998
  };
989
999
 
990
1000
  export const ARBITRUM_BUNDLES_INFO: ArbitrumBundleInfo = {
@@ -1189,16 +1199,6 @@ export const ARBITRUM_BUNDLES_INFO: ArbitrumBundleInfo = {
1189
1199
  strategyId: Strategies.Identifiers.EoaCloseOnPrice,
1190
1200
  protocol: PROTOCOLS.MorphoBlue,
1191
1201
  },
1192
- [Bundles.ArbitrumIds.AAVE_V3_SW_INSTANT_CLOSE]: {
1193
- strategyOrBundleId: Bundles.ArbitrumIds.AAVE_V3_SW_INSTANT_CLOSE,
1194
- strategyId: Strategies.Identifiers.InstantCloseOnPrice,
1195
- protocol: PROTOCOLS.AaveV3,
1196
- },
1197
- [Bundles.ArbitrumIds.AAVE_V3_EOA_INSTANT_CLOSE]: {
1198
- strategyOrBundleId: Bundles.ArbitrumIds.AAVE_V3_EOA_INSTANT_CLOSE,
1199
- strategyId: Strategies.Identifiers.EoaInstantCloseOnPrice,
1200
- protocol: PROTOCOLS.AaveV3,
1201
- },
1202
1202
  };
1203
1203
 
1204
1204
  export const BUNDLES_INFO: BundlesInfo = {
@@ -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,13 +1,10 @@
1
1
  import { expect } from 'chai';
2
2
 
3
- import {
4
- Bundles, CloseStrategyType, CloseToAssetType, ProtocolIdentifiers, Strategies,
5
- } from '../types/enums';
3
+ import { ProtocolIdentifiers, Strategies } from '../types/enums';
6
4
  import type { ParseData, Position } from '../types';
7
5
 
8
6
  import '../configuration';
9
7
  import { parseStrategiesAutomatedPosition } from './strategiesService';
10
- import { aaveV3Encode } from './strategySubService';
11
8
 
12
9
  describe('Feature: strategiesService.ts', () => {
13
10
  describe('When testing strategiesService.parseStrategiesAutomatedPosition', async () => {
@@ -79,7 +76,6 @@ describe('Feature: strategiesService.ts', () => {
79
76
  subId: '379',
80
77
  proxy: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
81
78
  subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
82
- // @ts-ignore
83
79
  subStruct:
84
80
  {
85
81
  strategyOrBundleId: '8',
@@ -106,78 +102,4 @@ describe('Feature: strategiesService.ts', () => {
106
102
  });
107
103
  });
108
104
  });
109
-
110
- describe('When parsing Aave V3 instant close bundles', () => {
111
- const owner = '0x1234567890123456789012345678901234567890';
112
- const market = '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e';
113
- const weth = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
114
- const usdc = '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48';
115
-
116
- const bundles: Array<[string, Bundles.MainnetIds, Strategies.Identifiers]> = [
117
- ['SW', Bundles.MainnetIds.AAVE_V3_SW_INSTANT_CLOSE, Strategies.Identifiers.InstantCloseOnPrice],
118
- ['EOA', Bundles.MainnetIds.AAVE_V3_EOA_INSTANT_CLOSE, Strategies.Identifiers.EoaInstantCloseOnPrice],
119
- ];
120
-
121
- bundles.forEach(([walletType, expectedBundleId, expectedStrategyId]) => {
122
- describe(`${walletType} bundle`, () => {
123
- const [bundleId, isBundle, triggerData, subData] = aaveV3Encode.instantCloseOnPriceGeneric(
124
- expectedBundleId,
125
- weth, 0, usdc, 1, market, owner,
126
- '1000000000000000000', '10000000000000000',
127
- 1500, CloseToAssetType.DEBT, 5000, CloseToAssetType.COLLATERAL,
128
- );
129
-
130
- const parseData = {
131
- chainId: 1,
132
- blockNumber: 1,
133
- subscriptionEventData: {
134
- subId: '1',
135
- proxy: owner,
136
- subHash: '0xhash',
137
- subStruct: {
138
- strategyOrBundleId: String(bundleId), isBundle, triggerData, subData,
139
- },
140
- },
141
- strategiesSubsData: { userProxy: owner, isEnabled: true, strategySubHash: '0xhash' },
142
- } as unknown as ParseData;
143
-
144
- const result = parseStrategiesAutomatedPosition(parseData) as Position.Automated;
145
-
146
- it('should identify the strategy as instant close on price', () => {
147
- expect(result.strategy.strategyOrBundleId).to.equal(expectedBundleId);
148
- expect(result.strategy.strategyId).to.equal(expectedStrategyId);
149
- expect(result.protocol.id).to.equal(ProtocolIdentifiers.StrategiesAutomation.AaveV3);
150
- });
151
-
152
- it('should decode sub data including tsi and slippage', () => {
153
- expect(result.strategyData.decoded.subData).to.eql({
154
- collAsset: weth,
155
- collAssetId: 0,
156
- debtAsset: usdc,
157
- debtAssetId: 1,
158
- closeType: CloseStrategyType.TAKE_PROFIT_IN_COLLATERAL_AND_STOP_LOSS_IN_DEBT,
159
- marketAddr: market,
160
- owner,
161
- tsi: '1000000000000000000',
162
- slippage: '10000000000000000',
163
- });
164
- });
165
-
166
- it('should fill specific with prices and close types', () => {
167
- expect(result.specific).to.eql({
168
- collAsset: weth,
169
- collAssetId: 0,
170
- debtAsset: usdc,
171
- debtAssetId: 1,
172
- baseToken: weth,
173
- quoteToken: usdc,
174
- stopLossPrice: '1500',
175
- takeProfitPrice: '5000',
176
- stopLossType: CloseToAssetType.DEBT,
177
- takeProfitType: CloseToAssetType.COLLATERAL,
178
- });
179
- });
180
- });
181
- });
182
- });
183
105
  });
@@ -433,42 +433,23 @@ function parseAaveV3CloseOnPrice(position: Position.Automated, parseData: ParseD
433
433
  return _position;
434
434
  }
435
435
 
436
- function parseAaveV3InstantCloseOnPrice(position: Position.Automated, parseData: ParseData): Position.Automated {
436
+ function parseAaveV3CollateralSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
437
437
  const _position = cloneDeep(position);
438
-
439
438
  const { subStruct } = parseData.subscriptionEventData;
440
-
441
- const triggerData = triggerService.aaveV3QuotePriceRangeTrigger.decode(subStruct.triggerData);
442
- const subData = subDataService.aaveV3InstantCloseGenericSubData.decode(subStruct.subData);
443
-
444
- const { takeProfitType, stopLossType } = getStopLossAndTakeProfitTypeByCloseStrategyType(+subData.closeType);
445
-
446
- _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, AAVE_V3_MARKET_ADDRESSES[_position.chainId]);
447
-
439
+ const triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
440
+ const subData = subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
448
441
  _position.strategyData.decoded.triggerData = triggerData;
449
442
  _position.strategyData.decoded.subData = subData;
450
-
451
- _position.specific = {
452
- collAsset: subData.collAsset,
453
- collAssetId: subData.collAssetId,
454
- debtAsset: subData.debtAsset,
455
- debtAssetId: subData.debtAssetId,
456
- baseToken: triggerData.collToken,
457
- quoteToken: triggerData.debtToken,
458
- stopLossPrice: triggerData.lowerPrice,
459
- takeProfitPrice: triggerData.upperPrice,
460
- stopLossType,
461
- takeProfitType,
462
- };
443
+ _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, subData.marketAddr);
463
444
 
464
445
  return _position;
465
446
  }
466
447
 
467
- function parseAaveV3CollateralSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
448
+ function parseAaveV3DebtSwitch(position: Position.Automated, parseData: ParseData): Position.Automated {
468
449
  const _position = cloneDeep(position);
469
450
  const { subStruct } = parseData.subscriptionEventData;
470
451
  const triggerData = triggerService.aaveV3QuotePriceTrigger.decode(subStruct.triggerData);
471
- const subData = subDataService.aaveV3CollateralSwitchSubData.decode(subStruct.subData);
452
+ const subData = subDataService.aaveV3DebtSwitchSubData.decode(subStruct.subData);
472
453
  _position.strategyData.decoded.triggerData = triggerData;
473
454
  _position.strategyData.decoded.subData = subData;
474
455
  _position.positionId = getPositionId(_position.chainId, _position.protocol.id, _position.owner, subData.marketAddr);
@@ -1627,9 +1608,9 @@ const parsingMethodsMapping: StrategiesToProtocolVersionMapping = {
1627
1608
  [Strategies.Identifiers.EoaRepayOnPrice]: parseAaveV3LeverageManagementOnPrice,
1628
1609
  [Strategies.Identifiers.EoaBoostOnPrice]: parseAaveV3LeverageManagementOnPrice,
1629
1610
  [Strategies.Identifiers.EoaCloseOnPrice]: parseAaveV3CloseOnPrice,
1630
- [Strategies.Identifiers.InstantCloseOnPrice]: parseAaveV3InstantCloseOnPrice,
1631
- [Strategies.Identifiers.EoaInstantCloseOnPrice]: parseAaveV3InstantCloseOnPrice,
1632
1611
  [Strategies.Identifiers.CollateralSwitch]: parseAaveV3CollateralSwitch,
1612
+ [Strategies.Identifiers.DebtSwitch]: parseAaveV3DebtSwitch,
1613
+ [Strategies.Identifiers.EoaDebtSwitch]: parseAaveV3DebtSwitch,
1633
1614
  [Strategies.Identifiers.LiquidationProtection]: parseAaveV3LiquidationProtection,
1634
1615
  [Strategies.Identifiers.EoaLiquidationProtection]: parseAaveV3LiquidationProtection,
1635
1616
  },