@defisaver/automation-sdk 2.0.8 → 2.1.0
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.
- package/.env +4 -0
- package/esm/automation/private/LegacyAutomation.js +9 -3
- package/esm/automation/private/StrategiesAutomation.d.ts +4 -0
- package/esm/automation/private/StrategiesAutomation.js +29 -4
- package/esm/services/strategiesService.js +37 -6
- package/esm/services/strategiesService.test.js +3 -2
- package/esm/services/utils.d.ts +1 -0
- package/esm/services/utils.js +5 -1
- package/esm/services/utils.test.js +13 -0
- package/esm/types/index.d.ts +6 -2
- package/package.json +4 -4
- package/src/automation/private/LegacyAutomation.ts +14 -4
- package/src/automation/private/StrategiesAutomation.ts +40 -6
- package/src/services/strategiesService.test.ts +3 -2
- package/src/services/strategiesService.ts +67 -9
- package/src/services/utils.test.ts +17 -1
- package/src/services/utils.ts +4 -0
- package/src/types/index.ts +7 -2
- package/umd/index.js +824 -462
package/.env
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
RPC_1=https://mainnet.infura.io/v3/a3503e4501d040cd9ea2c913c68983a1
|
|
2
|
+
RPC_10=https://opt-mainnet.g.alchemy.com/v2/Pwh-hdbsP7Bf0CP_UMw4_Pw-NfHhSpIA
|
|
3
|
+
RPC_8453=https://base-mainnet.g.alchemy.com/v2/TERsAaPNcA7sgCVHHAMBvd95UtT4wCEf
|
|
4
|
+
RPC_42161=https://arb-mainnet.g.alchemy.com/v2/Pwh-hdbsP7Bf0CP_UMw4_Pw-NfHhSpIA
|
|
@@ -12,6 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
15
16
|
const contractService_1 = require("../../services/contractService");
|
|
16
17
|
const ethereumService_1 = require("../../services/ethereumService");
|
|
17
18
|
const utils_1 = require("../../services/utils");
|
|
@@ -82,13 +83,18 @@ class LegacyAutomation extends Automation_1.default {
|
|
|
82
83
|
}
|
|
83
84
|
getParsedSubscriptions(addresses, options) {
|
|
84
85
|
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
+
// Legacy automation was disabled on block 18213086
|
|
87
|
+
if (!(options === null || options === void 0 ? void 0 : options.fromBlock)
|
|
88
|
+
|| (options === null || options === void 0 ? void 0 : options.fromBlock) === 'latest'
|
|
89
|
+
|| (options === null || options === void 0 ? void 0 : options.fromBlock) === 'pending'
|
|
90
|
+
|| ((options === null || options === void 0 ? void 0 : options.fromBlock) && new decimal_js_1.default(options === null || options === void 0 ? void 0 : options.fromBlock.toString()).lt(18213086))) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
85
93
|
const subscriptions = yield this._getSubscriptions(addresses, options);
|
|
86
|
-
// @ts-ignore
|
|
87
94
|
return subscriptions.map((sub) => ({
|
|
88
95
|
chainId: this.chainId,
|
|
89
96
|
owner: sub[this.getOwnerPropName()],
|
|
90
|
-
isEnabled:
|
|
91
|
-
? (options === null || options === void 0 ? void 0 : options.fromBlock) > 18213086 : false,
|
|
97
|
+
isEnabled: true,
|
|
92
98
|
protocol: this.protocol,
|
|
93
99
|
specific: Object.assign({}, sub),
|
|
94
100
|
strategy: {
|
|
@@ -20,6 +20,10 @@ export default class StrategiesAutomation extends Automation {
|
|
|
20
20
|
protected getSubscriptionEventsFromSubStorage(options?: PastEventOptions): Promise<any[]>;
|
|
21
21
|
protected getUpdateDataEventsFromSubStorage(options?: PastEventOptions): Promise<any[]>;
|
|
22
22
|
protected getParsedSubscriptions(parseData: ParseData): Position.Automated | null;
|
|
23
|
+
/**
|
|
24
|
+
* @description Removes expired Limit Order subscriptions
|
|
25
|
+
*/
|
|
26
|
+
protected removeExpiredSubscriptions(subscriptions: (Position.Automated | null)[]): (Position.Automated | null)[];
|
|
23
27
|
protected _getSubscriptions(addresses?: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
24
28
|
getSubscriptions(options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
25
29
|
getSubscriptionsFor(addresses: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
16
|
+
const enums_1 = require("../../types/enums");
|
|
16
17
|
const utils_1 = require("../../services/utils");
|
|
17
18
|
const contractService_1 = require("../../services/contractService");
|
|
18
19
|
const ethereumService_1 = require("../../services/ethereumService");
|
|
@@ -70,14 +71,38 @@ class StrategiesAutomation extends Automation_1.default {
|
|
|
70
71
|
getParsedSubscriptions(parseData) {
|
|
71
72
|
return (0, strategiesService_1.parseStrategiesAutomatedPosition)(parseData);
|
|
72
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* @description Removes expired Limit Order subscriptions
|
|
76
|
+
*/
|
|
77
|
+
removeExpiredSubscriptions(subscriptions) {
|
|
78
|
+
return subscriptions.filter((subscription) => {
|
|
79
|
+
if (!subscription) {
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
const { protocol, strategy, strategyData } = subscription;
|
|
83
|
+
if (protocol.id === enums_1.ProtocolIdentifiers.StrategiesAutomation.Exchange
|
|
84
|
+
&& strategy.strategyId === enums_1.Strategies.Identifiers.LimitOrder) {
|
|
85
|
+
return new decimal_js_1.default(strategyData.decoded.triggerData.goodUntil).gt(new decimal_js_1.default(Date.now()).div(1000));
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
73
90
|
_getSubscriptions(addresses, options) {
|
|
74
91
|
return __awaiter(this, void 0, void 0, function* () {
|
|
75
92
|
const _options = Object.assign(Object.assign({}, (0, utils_1.addToObjectIf)((0, utils_1.isDefined)(options), options)), (0, utils_1.addToObjectIf)((0, utils_1.isDefined)(addresses), { filter: { proxy: addresses } }));
|
|
76
|
-
|
|
93
|
+
let subscriptionEvents = (yield this.getSubscriptionEventsFromSubStorage(_options)); // TODO PlaceholderType
|
|
77
94
|
let subscriptions = [];
|
|
78
95
|
if (subscriptionEvents) {
|
|
79
|
-
|
|
80
|
-
|
|
96
|
+
let strategiesSubs = yield this.getStrategiesSubs(subscriptionEvents.map((e) => e.returnValues.subId), _options.toBlock);
|
|
97
|
+
if (_options.enabledOnly) {
|
|
98
|
+
const filteredSubscriptionEvents = [];
|
|
99
|
+
strategiesSubs = strategiesSubs.filter((sub, index) => {
|
|
100
|
+
if (sub === null || sub === void 0 ? void 0 : sub.isEnabled)
|
|
101
|
+
filteredSubscriptionEvents.push(subscriptionEvents[index]);
|
|
102
|
+
return sub === null || sub === void 0 ? void 0 : sub.isEnabled;
|
|
103
|
+
});
|
|
104
|
+
subscriptionEvents = filteredSubscriptionEvents;
|
|
105
|
+
}
|
|
81
106
|
subscriptions = yield Promise.all(strategiesSubs.map((sub, index) => __awaiter(this, void 0, void 0, function* () {
|
|
82
107
|
var _a;
|
|
83
108
|
let latestUpdate = subscriptionEvents[index].returnValues;
|
|
@@ -120,7 +145,7 @@ class StrategiesAutomation extends Automation_1.default {
|
|
|
120
145
|
}, []);
|
|
121
146
|
}
|
|
122
147
|
}
|
|
123
|
-
return subscriptions;
|
|
148
|
+
return _options.unexpiredOnly ? this.removeExpiredSubscriptions(subscriptions) : subscriptions;
|
|
124
149
|
});
|
|
125
150
|
}
|
|
126
151
|
getSubscriptions(options) {
|
|
@@ -31,6 +31,14 @@ const enums_1 = require("../types/enums");
|
|
|
31
31
|
const utils_1 = require("./utils");
|
|
32
32
|
const subDataService = __importStar(require("./subDataService"));
|
|
33
33
|
const triggerService = __importStar(require("./triggerService"));
|
|
34
|
+
const SPARK_MARKET_ADDRESSES = {
|
|
35
|
+
[enums_1.ChainId.Ethereum]: '0x02C3eA4e34C0cBd694D2adFa2c690EECbC1793eE',
|
|
36
|
+
};
|
|
37
|
+
const AAVE_V3_MARKET_ADDRESSES = {
|
|
38
|
+
[enums_1.ChainId.Ethereum]: '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e',
|
|
39
|
+
[enums_1.ChainId.Optimism]: '0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb',
|
|
40
|
+
[enums_1.ChainId.Arbitrum]: '0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb',
|
|
41
|
+
};
|
|
34
42
|
function parseMakerSavingsLiqProtection(position, parseData) {
|
|
35
43
|
const _position = (0, lodash_1.cloneDeep)(position);
|
|
36
44
|
const { subStruct } = parseData.subscriptionEventData;
|
|
@@ -38,6 +46,7 @@ function parseMakerSavingsLiqProtection(position, parseData) {
|
|
|
38
46
|
const subData = subDataService.makerRepayFromSavingsSubData.decode(subStruct.subData);
|
|
39
47
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
40
48
|
_position.strategyData.decoded.subData = subData;
|
|
49
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, subData.vaultId);
|
|
41
50
|
_position.specific = {
|
|
42
51
|
triggerRepayRatio: Number(triggerData.ratio),
|
|
43
52
|
targetRepayRatio: Number(subData.targetRatio),
|
|
@@ -53,6 +62,7 @@ function parseMakerCloseOnPrice(position, parseData) {
|
|
|
53
62
|
const subData = subDataService.makerCloseSubData.decode(subStruct.subData);
|
|
54
63
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
55
64
|
_position.strategyData.decoded.subData = subData;
|
|
65
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, subData.vaultId);
|
|
56
66
|
const isTakeProfit = (0, utils_1.isRatioStateOver)(Number(triggerData.state));
|
|
57
67
|
_position.strategy.strategyId = isTakeProfit ? enums_1.Strategies.IdOverrides.TakeProfit : enums_1.Strategies.IdOverrides.StopLoss;
|
|
58
68
|
_position.specific = {
|
|
@@ -68,6 +78,7 @@ function parseMakerTrailingStop(position, parseData) {
|
|
|
68
78
|
const subData = subDataService.makerCloseSubData.decode(subStruct.subData);
|
|
69
79
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
70
80
|
_position.strategyData.decoded.subData = subData;
|
|
81
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, subData.vaultId);
|
|
71
82
|
_position.strategy.strategyId = enums_1.Strategies.IdOverrides.TrailingStop;
|
|
72
83
|
_position.specific = {
|
|
73
84
|
triggerPercentage: Number(triggerData.triggerPercentage),
|
|
@@ -84,6 +95,7 @@ function parseMakerLeverageManagement(position, parseData) {
|
|
|
84
95
|
const subData = subDataService.makerLeverageManagementSubData.decode(subStruct.subData);
|
|
85
96
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
86
97
|
_position.strategyData.decoded.subData = subData;
|
|
98
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, subData.vaultId);
|
|
87
99
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
88
100
|
if (isRepay) {
|
|
89
101
|
_position.specific = {
|
|
@@ -112,6 +124,7 @@ function parseLiquityCloseOnPrice(position, parseData) {
|
|
|
112
124
|
const subData = subDataService.liquityCloseSubData.decode(subStruct.subData);
|
|
113
125
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
114
126
|
_position.strategyData.decoded.subData = subData;
|
|
127
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
115
128
|
const isTakeProfit = (0, utils_1.isRatioStateOver)(Number(triggerData.state));
|
|
116
129
|
_position.strategy.strategyId = isTakeProfit ? enums_1.Strategies.IdOverrides.TakeProfit : enums_1.Strategies.IdOverrides.StopLoss;
|
|
117
130
|
_position.specific = {
|
|
@@ -127,6 +140,7 @@ function parseLiquityTrailingStop(position, parseData) {
|
|
|
127
140
|
const subData = subDataService.liquityCloseSubData.decode(subStruct.subData);
|
|
128
141
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
129
142
|
_position.strategyData.decoded.subData = subData;
|
|
143
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
130
144
|
_position.strategy.strategyId = enums_1.Strategies.IdOverrides.TrailingStop;
|
|
131
145
|
_position.specific = {
|
|
132
146
|
triggerPercentage: Number(triggerData.triggerPercentage),
|
|
@@ -143,6 +157,7 @@ function parseAaveV2LeverageManagement(position, parseData) {
|
|
|
143
157
|
const subData = subDataService.aaveV2LeverageManagementSubData.decode(subStruct.subData);
|
|
144
158
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
145
159
|
_position.strategyData.decoded.subData = subData;
|
|
160
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
|
|
146
161
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
147
162
|
if (isRepay) {
|
|
148
163
|
_position.specific = {
|
|
@@ -172,6 +187,7 @@ function parseAaveV3LeverageManagement(position, parseData) {
|
|
|
172
187
|
const subData = subDataService.aaveV3LeverageManagementSubData.decode(subStruct.subData);
|
|
173
188
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
174
189
|
_position.strategyData.decoded.subData = subData;
|
|
190
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
|
|
175
191
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
176
192
|
if (isRepay) {
|
|
177
193
|
_position.specific = {
|
|
@@ -201,6 +217,7 @@ function parseMorphoAaveV2LeverageManagement(position, parseData) {
|
|
|
201
217
|
const subData = subDataService.morphoAaveV2LeverageManagementSubData.decode(subStruct.subData);
|
|
202
218
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
203
219
|
_position.strategyData.decoded.subData = subData;
|
|
220
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
204
221
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
205
222
|
if (isRepay) {
|
|
206
223
|
_position.specific = {
|
|
@@ -229,6 +246,7 @@ function parseAaveV3CloseOnPrice(position, parseData) {
|
|
|
229
246
|
const subData = subDataService.aaveV3QuotePriceSubData.decode(subStruct.subData);
|
|
230
247
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
231
248
|
_position.strategyData.decoded.subData = subData;
|
|
249
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, AAVE_V3_MARKET_ADDRESSES[_position.chainId]);
|
|
232
250
|
_position.specific = {
|
|
233
251
|
collAsset: subData.collAsset,
|
|
234
252
|
collAssetId: subData.collAssetId,
|
|
@@ -250,6 +268,7 @@ function parseAaveV3CloseOnPriceWithMaximumGasPrice(position, parseData) {
|
|
|
250
268
|
const subData = subDataService.aaveV3QuotePriceSubData.decode(subStruct.subData);
|
|
251
269
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
252
270
|
_position.strategyData.decoded.subData = subData;
|
|
271
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, AAVE_V3_MARKET_ADDRESSES[_position.chainId]);
|
|
253
272
|
_position.specific = {
|
|
254
273
|
collAsset: subData.collAsset,
|
|
255
274
|
collAssetId: subData.collAssetId,
|
|
@@ -275,7 +294,8 @@ function parseCompoundV2LeverageManagement(position, parseData) {
|
|
|
275
294
|
const subData = subDataService.compoundV2LeverageManagementSubData.decode(subStruct.subData);
|
|
276
295
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
277
296
|
_position.strategyData.decoded.subData = subData;
|
|
278
|
-
_position.owner = triggerData.owner;
|
|
297
|
+
_position.owner = triggerData.owner.toLowerCase();
|
|
298
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
279
299
|
const isRepay = [enums_1.Strategies.Identifiers.Repay, enums_1.Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId);
|
|
280
300
|
if (isRepay) {
|
|
281
301
|
_position.specific = {
|
|
@@ -305,7 +325,8 @@ function parseCompoundV3LeverageManagement(position, parseData) {
|
|
|
305
325
|
const subData = subDataService.compoundV3LeverageManagementSubData.decode(subStruct.subData);
|
|
306
326
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
307
327
|
_position.strategyData.decoded.subData = subData;
|
|
308
|
-
_position.owner = triggerData.owner;
|
|
328
|
+
_position.owner = triggerData.owner.toLowerCase();
|
|
329
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
|
|
309
330
|
const isRepay = [enums_1.Strategies.Identifiers.Repay, enums_1.Strategies.Identifiers.EoaRepay].includes(_position.strategy.strategyId);
|
|
310
331
|
if (isRepay) {
|
|
311
332
|
_position.specific = {
|
|
@@ -333,14 +354,16 @@ function parseChickenBondsRebond(position, parseData) {
|
|
|
333
354
|
const { subStruct } = parseData.subscriptionEventData;
|
|
334
355
|
_position.strategyData.decoded.triggerData = triggerService.cBondsRebondTrigger.decode(subStruct.triggerData);
|
|
335
356
|
_position.strategyData.decoded.subData = subDataService.cBondsRebondSubData.decode(subStruct.subData);
|
|
357
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.strategyData.decoded.triggerData.bondId);
|
|
336
358
|
return _position;
|
|
337
359
|
}
|
|
338
360
|
function parseLiquityBondProtection(position, parseData) {
|
|
339
361
|
const _position = (0, lodash_1.cloneDeep)(position);
|
|
340
362
|
const { subStruct } = parseData.subscriptionEventData;
|
|
341
363
|
const triggerData = triggerService.liquityRatioTrigger.decode(subStruct.triggerData);
|
|
342
|
-
_position.strategyData.decoded.subData = subDataService.liquityPaybackUsingChickenBondSubData.decode(subStruct.subData);
|
|
343
364
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
365
|
+
_position.strategyData.decoded.subData = subDataService.liquityPaybackUsingChickenBondSubData.decode(subStruct.subData);
|
|
366
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
344
367
|
_position.specific = {
|
|
345
368
|
triggerRepayRatio: Number(triggerData.ratio),
|
|
346
369
|
targetRepayRatio: Infinity,
|
|
@@ -353,6 +376,7 @@ function parseExchangeDca(position, parseData, chainId) {
|
|
|
353
376
|
const { subStruct } = parseData.subscriptionEventData;
|
|
354
377
|
_position.strategyData.decoded.triggerData = triggerService.exchangeTimestampTrigger.decode(subStruct.triggerData);
|
|
355
378
|
_position.strategyData.decoded.subData = subDataService.exchangeDcaSubData.decode(subStruct.subData, chainId);
|
|
379
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, Math.random());
|
|
356
380
|
return _position;
|
|
357
381
|
}
|
|
358
382
|
function parseExchangeLimitOrder(position, parseData, chainId) {
|
|
@@ -362,6 +386,7 @@ function parseExchangeLimitOrder(position, parseData, chainId) {
|
|
|
362
386
|
const fromTokenDecimals = (0, tokens_1.getAssetInfoByAddress)(_position.strategyData.decoded.subData.fromToken, chainId).decimals;
|
|
363
387
|
const toTokenDecimals = (0, tokens_1.getAssetInfoByAddress)(_position.strategyData.decoded.subData.toToken, chainId).decimals;
|
|
364
388
|
_position.strategyData.decoded.triggerData = triggerService.exchangeOffchainPriceTrigger.decode(subStruct.triggerData, fromTokenDecimals, toTokenDecimals);
|
|
389
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, Math.random());
|
|
365
390
|
return _position;
|
|
366
391
|
}
|
|
367
392
|
function parseLiquityLeverageManagement(position, parseData) {
|
|
@@ -372,6 +397,7 @@ function parseLiquityLeverageManagement(position, parseData) {
|
|
|
372
397
|
const subData = subDataService.liquityLeverageManagementSubData.decode(subStruct.subData);
|
|
373
398
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
374
399
|
_position.strategyData.decoded.subData = subData;
|
|
400
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
375
401
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
376
402
|
if (isRepay) {
|
|
377
403
|
_position.specific = {
|
|
@@ -401,6 +427,7 @@ function parseSparkLeverageManagement(position, parseData) {
|
|
|
401
427
|
const subData = subDataService.sparkLeverageManagementSubData.decode(subStruct.subData);
|
|
402
428
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
403
429
|
_position.strategyData.decoded.subData = subData;
|
|
430
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, triggerData.market);
|
|
404
431
|
const isRepay = _position.strategy.strategyId === enums_1.Strategies.Identifiers.Repay;
|
|
405
432
|
if (isRepay) {
|
|
406
433
|
_position.specific = {
|
|
@@ -429,6 +456,7 @@ function parseSparkCloseOnPrice(position, parseData) {
|
|
|
429
456
|
const subData = subDataService.sparkQuotePriceSubData.decode(subStruct.subData);
|
|
430
457
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
431
458
|
_position.strategyData.decoded.subData = subData;
|
|
459
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner, SPARK_MARKET_ADDRESSES[_position.chainId]);
|
|
432
460
|
_position.specific = {
|
|
433
461
|
collAsset: subData.collAsset,
|
|
434
462
|
collAssetId: subData.collAssetId,
|
|
@@ -450,6 +478,7 @@ function parseLiquitySavingsLiqProtection(position, parseData) {
|
|
|
450
478
|
const subData = subDataService.liquityRepayFromSavingsSubData.decode(subStruct.subData);
|
|
451
479
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
452
480
|
_position.strategyData.decoded.subData = subData;
|
|
481
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
453
482
|
_position.specific = {
|
|
454
483
|
triggerRepayRatio: triggerData.ratio,
|
|
455
484
|
targetRepayRatio: subData.targetRatio,
|
|
@@ -458,13 +487,14 @@ function parseLiquitySavingsLiqProtection(position, parseData) {
|
|
|
458
487
|
};
|
|
459
488
|
return _position;
|
|
460
489
|
}
|
|
461
|
-
function
|
|
490
|
+
function parseLiquityDebtInFrontRepay(position, parseData) {
|
|
462
491
|
const _position = (0, lodash_1.cloneDeep)(position);
|
|
463
492
|
const { subStruct } = parseData.subscriptionEventData;
|
|
464
493
|
const triggerData = triggerService.liquityDebtInFrontWithLimitTrigger.decode(subStruct.triggerData);
|
|
465
494
|
const subData = subDataService.liquityDebtInFrontRepaySubData.decode(subStruct.subData);
|
|
466
495
|
_position.strategyData.decoded.triggerData = triggerData;
|
|
467
496
|
_position.strategyData.decoded.subData = subData;
|
|
497
|
+
_position.positionId = (0, utils_1.getPositionId)(_position.chainId, _position.protocol.id, _position.owner);
|
|
468
498
|
_position.specific = {
|
|
469
499
|
debtInFrontMin: triggerData.debtInFrontMin,
|
|
470
500
|
targetRepayRatioIncrease: subData.targetRatioIncrease,
|
|
@@ -489,7 +519,7 @@ const parsingMethodsMapping = {
|
|
|
489
519
|
[enums_1.Strategies.Identifiers.Boost]: parseLiquityLeverageManagement,
|
|
490
520
|
[enums_1.Strategies.Identifiers.SavingsDsrPayback]: parseLiquitySavingsLiqProtection,
|
|
491
521
|
[enums_1.Strategies.Identifiers.SavingsDsrSupply]: parseLiquitySavingsLiqProtection,
|
|
492
|
-
[enums_1.Strategies.Identifiers.DebtInFrontRepay]:
|
|
522
|
+
[enums_1.Strategies.Identifiers.DebtInFrontRepay]: parseLiquityDebtInFrontRepay,
|
|
493
523
|
},
|
|
494
524
|
[enums_1.ProtocolIdentifiers.StrategiesAutomation.AaveV2]: {
|
|
495
525
|
[enums_1.Strategies.Identifiers.Repay]: parseAaveV2LeverageManagement,
|
|
@@ -549,8 +579,9 @@ function parseStrategiesAutomatedPosition(parseData) {
|
|
|
549
579
|
chainId,
|
|
550
580
|
subHash,
|
|
551
581
|
blockNumber,
|
|
582
|
+
positionId: 'positionId parsing not implemented.',
|
|
552
583
|
subId: Number(subId),
|
|
553
|
-
owner: proxy,
|
|
584
|
+
owner: proxy.toLowerCase(),
|
|
554
585
|
protocol: Object.assign({}, strategyOrBundleInfo.protocol),
|
|
555
586
|
strategy: Object.assign({ isBundle: subStruct.isBundle }, strategyOrBundleInfo),
|
|
556
587
|
strategyData: {
|
|
@@ -20,10 +20,11 @@ describe('Feature: strategiesService.ts', () => {
|
|
|
20
20
|
{
|
|
21
21
|
isEnabled: true,
|
|
22
22
|
chainId: 1,
|
|
23
|
+
positionId: '1-aave__v3-0x9cb7e19861665366011899d74e75d4f2a419aeed-0x2f39d218133afab8f2b819b1066c7e434ad94e9e',
|
|
23
24
|
subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
|
|
24
25
|
blockNumber: 18015756,
|
|
25
26
|
subId: 379,
|
|
26
|
-
owner: '
|
|
27
|
+
owner: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
|
|
27
28
|
protocol: {
|
|
28
29
|
id: enums_1.ProtocolIdentifiers.StrategiesAutomation.AaveV3,
|
|
29
30
|
name: 'Aave',
|
|
@@ -78,7 +79,7 @@ describe('Feature: strategiesService.ts', () => {
|
|
|
78
79
|
blockNumber: 18015756,
|
|
79
80
|
subscriptionEventData: {
|
|
80
81
|
subId: '379',
|
|
81
|
-
proxy: '
|
|
82
|
+
proxy: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
|
|
82
83
|
subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
|
|
83
84
|
// @ts-ignore
|
|
84
85
|
subStruct: {
|
package/esm/services/utils.d.ts
CHANGED
package/esm/services/utils.js
CHANGED
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.getRatioStateInfoForAaveCloseStrategy = exports.requireAddresses = exports.requireAddress = exports.isEmptyBytes = exports.isRatioStateUnder = exports.isRatioStateOver = exports.weiToRatioPercentage = exports.ratioPercentageToWei = exports.encodeSubId = exports.compareSubHashes = exports.wethToEthByAddress = exports.wethToEth = exports.ethToWeth = exports.addToObjectIf = exports.addToArrayIf = exports.isAddress = exports.compareAddresses = exports.isUndefined = exports.isDefined = void 0;
|
|
29
|
+
exports.getPositionId = exports.getRatioStateInfoForAaveCloseStrategy = exports.requireAddresses = exports.requireAddress = exports.isEmptyBytes = exports.isRatioStateUnder = exports.isRatioStateOver = exports.weiToRatioPercentage = exports.ratioPercentageToWei = exports.encodeSubId = exports.compareSubHashes = exports.wethToEthByAddress = exports.wethToEth = exports.ethToWeth = exports.addToObjectIf = exports.addToArrayIf = exports.isAddress = exports.compareAddresses = exports.isUndefined = exports.isDefined = void 0;
|
|
30
30
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
31
31
|
const web3Utils = __importStar(require("web3-utils"));
|
|
32
32
|
const web3_eth_abi_1 = __importDefault(require("web3-eth-abi"));
|
|
@@ -125,3 +125,7 @@ function getRatioStateInfoForAaveCloseStrategy(currentRatioState, collAsset, deb
|
|
|
125
125
|
return { shouldFlip, ratioState };
|
|
126
126
|
}
|
|
127
127
|
exports.getRatioStateInfoForAaveCloseStrategy = getRatioStateInfoForAaveCloseStrategy;
|
|
128
|
+
function getPositionId(...args) {
|
|
129
|
+
return args.map(arg => arg.toString().toLowerCase().split(' ').join('_')).join('-');
|
|
130
|
+
}
|
|
131
|
+
exports.getPositionId = getPositionId;
|
|
@@ -359,4 +359,17 @@ describe('Feature: utils.ts', () => {
|
|
|
359
359
|
});
|
|
360
360
|
});
|
|
361
361
|
});
|
|
362
|
+
describe('When testing utils.getPositionId()', () => {
|
|
363
|
+
const examples = [
|
|
364
|
+
[
|
|
365
|
+
'1-aave__v3-0x9cb7e19861665366011899d74e75d4f2a419aeed-0x2f39d218133afab8f2b819b1066c7e434ad94e9e',
|
|
366
|
+
[1, enums_1.ProtocolIdentifiers.StrategiesAutomation.AaveV3, '0x9cB7E19861665366011899d74E75d4F2A419aEeD', '0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e']
|
|
367
|
+
],
|
|
368
|
+
];
|
|
369
|
+
examples.forEach(([expected, actual]) => {
|
|
370
|
+
it(`Given ${actual} should return expected value: ${JSON.stringify(expected)}`, () => {
|
|
371
|
+
(0, chai_1.expect)((0, utils_1.getPositionId)(...actual)).to.eql(expected);
|
|
372
|
+
});
|
|
373
|
+
});
|
|
374
|
+
});
|
|
362
375
|
});
|
package/esm/types/index.d.ts
CHANGED
|
@@ -45,11 +45,14 @@ export declare namespace Multicall {
|
|
|
45
45
|
}
|
|
46
46
|
type Payload = any[];
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
interface _SubscriptionOptions {
|
|
49
49
|
toBlock: BlockNumber;
|
|
50
50
|
fromBlock: BlockNumber;
|
|
51
|
-
mergeWithSameId
|
|
51
|
+
mergeWithSameId: boolean;
|
|
52
|
+
enabledOnly: boolean;
|
|
53
|
+
unexpiredOnly: boolean;
|
|
52
54
|
}
|
|
55
|
+
export type SubscriptionOptions = Partial<_SubscriptionOptions>;
|
|
53
56
|
export declare namespace Interfaces {
|
|
54
57
|
interface ProtocolBase {
|
|
55
58
|
id: ProtocolIdentifiers.StrategiesAutomation | ProtocolIdentifiers.LegacyAutomation;
|
|
@@ -140,6 +143,7 @@ export declare namespace Position {
|
|
|
140
143
|
type SpecificAny = Specific.CloseOnPrice | Specific.TrailingStop | Specific.RatioProtection | Specific.CloseOnPriceAave | Specific.CloseOnPriceWithMaximumGasPriceAave | Specific.DebtInFrontRepay;
|
|
141
144
|
interface Automated {
|
|
142
145
|
chainId: ChainId;
|
|
146
|
+
positionId: string;
|
|
143
147
|
owner: EthereumAddress;
|
|
144
148
|
subId: number;
|
|
145
149
|
subIds?: number[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defisaver/automation-sdk",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./umd/index.js",
|
|
6
6
|
"module": "./esm/index.js",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"repository": "https://github.com/defisaver/automation-sdk",
|
|
22
22
|
"license": "ISC",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@defisaver/eslint-config": "^1.0.
|
|
25
|
-
"@defisaver/sdk": "^1.0.
|
|
26
|
-
"@defisaver/tokens": "^1.
|
|
24
|
+
"@defisaver/eslint-config": "^1.0.1",
|
|
25
|
+
"@defisaver/sdk": "^1.0.55",
|
|
26
|
+
"@defisaver/tokens": "^1.5.3",
|
|
27
27
|
"@ethersproject/address": "^5.0.10",
|
|
28
28
|
"@ethersproject/solidity": "^5.0.9",
|
|
29
29
|
"decimal.js": "^10.4.3",
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
2
|
+
|
|
1
3
|
import type Web3 from 'web3';
|
|
2
4
|
import type {
|
|
3
5
|
EthereumAddress, Position, Interfaces, Contract, PlaceholderType, SubscriptionOptions,
|
|
@@ -99,14 +101,22 @@ export default class LegacyAutomation extends Automation {
|
|
|
99
101
|
}
|
|
100
102
|
|
|
101
103
|
protected async getParsedSubscriptions(addresses?: EthereumAddress[], options?: SubscriptionOptions): Promise<Position.LegacyAutomated[]> {
|
|
104
|
+
// Legacy automation was disabled on block 18213086
|
|
105
|
+
if (
|
|
106
|
+
!options?.fromBlock
|
|
107
|
+
|| options?.fromBlock === 'latest'
|
|
108
|
+
|| options?.fromBlock === 'pending'
|
|
109
|
+
|| (options?.fromBlock && new Dec(options?.fromBlock.toString()).lt(18213086))
|
|
110
|
+
) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
|
|
102
114
|
const subscriptions = await this._getSubscriptions(addresses, options);
|
|
103
115
|
|
|
104
|
-
|
|
105
|
-
return subscriptions.map((sub) => ({
|
|
116
|
+
return subscriptions.map((sub: any) => ({
|
|
106
117
|
chainId: this.chainId,
|
|
107
118
|
owner: sub[this.getOwnerPropName()],
|
|
108
|
-
isEnabled:
|
|
109
|
-
? options?.fromBlock > 18213086 : false, // Legacy automation was disabled on block 18213086
|
|
119
|
+
isEnabled: true,
|
|
110
120
|
protocol: this.protocol,
|
|
111
121
|
specific: { ...sub },
|
|
112
122
|
strategy: {
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
StrategyModel, SubStorage,
|
|
9
9
|
} from '../../types/contracts/generated/SubStorage';
|
|
10
10
|
import type { ChainId } from '../../types/enums';
|
|
11
|
+
import { Strategies, ProtocolIdentifiers } from '../../types/enums';
|
|
11
12
|
|
|
12
13
|
import { addToObjectIf, isDefined } from '../../services/utils';
|
|
13
14
|
import { getAbiItem, makeSubStorageContract } from '../../services/contractService';
|
|
@@ -84,20 +85,53 @@ export default class StrategiesAutomation extends Automation {
|
|
|
84
85
|
return parseStrategiesAutomatedPosition(parseData);
|
|
85
86
|
}
|
|
86
87
|
|
|
88
|
+
/**
|
|
89
|
+
* @description Removes expired Limit Order subscriptions
|
|
90
|
+
*/
|
|
91
|
+
protected removeExpiredSubscriptions(subscriptions: (Position.Automated | null)[]) {
|
|
92
|
+
return subscriptions.filter((subscription: Position.Automated | null) => {
|
|
93
|
+
if (!subscription) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const { protocol, strategy, strategyData } = subscription;
|
|
98
|
+
|
|
99
|
+
if (
|
|
100
|
+
protocol.id === ProtocolIdentifiers.StrategiesAutomation.Exchange
|
|
101
|
+
&& strategy.strategyId === Strategies.Identifiers.LimitOrder
|
|
102
|
+
) {
|
|
103
|
+
return new Dec(strategyData.decoded.triggerData.goodUntil).gt(new Dec(Date.now()).div(1000));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
protected async _getSubscriptions(addresses?: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]> {
|
|
88
111
|
const _options = {
|
|
89
112
|
...addToObjectIf(isDefined(options), options),
|
|
90
113
|
...addToObjectIf(isDefined(addresses), { filter: { proxy: addresses } }),
|
|
91
|
-
};
|
|
114
|
+
} as SubscriptionOptions & PastEventOptions;
|
|
92
115
|
|
|
93
|
-
|
|
94
|
-
const subscriptionEvents = (await this.getSubscriptionEventsFromSubStorage(_options)) as PlaceholderType; // TODO PlaceholderType
|
|
116
|
+
let subscriptionEvents = (await this.getSubscriptionEventsFromSubStorage(_options)) as PlaceholderType; // TODO PlaceholderType
|
|
95
117
|
|
|
96
118
|
let subscriptions: (Position.Automated | null)[] = [];
|
|
97
119
|
|
|
98
120
|
if (subscriptionEvents) {
|
|
99
|
-
|
|
100
|
-
|
|
121
|
+
let strategiesSubs = await this.getStrategiesSubs(
|
|
122
|
+
subscriptionEvents.map((e: { returnValues: { subId: number } }) => e.returnValues.subId), _options.toBlock,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (_options.enabledOnly) {
|
|
126
|
+
const filteredSubscriptionEvents = [] as PlaceholderType;
|
|
127
|
+
|
|
128
|
+
strategiesSubs = strategiesSubs.filter((sub, index) => {
|
|
129
|
+
if (sub?.isEnabled) filteredSubscriptionEvents.push(subscriptionEvents[index]);
|
|
130
|
+
return sub?.isEnabled;
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
subscriptionEvents = filteredSubscriptionEvents;
|
|
134
|
+
}
|
|
101
135
|
|
|
102
136
|
subscriptions = await Promise.all(strategiesSubs.map(async (sub, index: number) => {
|
|
103
137
|
let latestUpdate = subscriptionEvents[index].returnValues;
|
|
@@ -168,7 +202,7 @@ export default class StrategiesAutomation extends Automation {
|
|
|
168
202
|
}
|
|
169
203
|
}
|
|
170
204
|
|
|
171
|
-
return subscriptions;
|
|
205
|
+
return _options.unexpiredOnly ? this.removeExpiredSubscriptions(subscriptions) : subscriptions;
|
|
172
206
|
}
|
|
173
207
|
|
|
174
208
|
public async getSubscriptions(options?: SubscriptionOptions): Promise<(Position.Automated | null)[]> {
|
|
@@ -13,10 +13,11 @@ describe('Feature: strategiesService.ts', () => {
|
|
|
13
13
|
{
|
|
14
14
|
isEnabled: true,
|
|
15
15
|
chainId: 1,
|
|
16
|
+
positionId: '1-aave__v3-0x9cb7e19861665366011899d74e75d4f2a419aeed-0x2f39d218133afab8f2b819b1066c7e434ad94e9e',
|
|
16
17
|
subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
|
|
17
18
|
blockNumber: 18015756,
|
|
18
19
|
subId: 379,
|
|
19
|
-
owner: '
|
|
20
|
+
owner: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
|
|
20
21
|
protocol: {
|
|
21
22
|
id: ProtocolIdentifiers.StrategiesAutomation.AaveV3,
|
|
22
23
|
name: 'Aave',
|
|
@@ -71,7 +72,7 @@ describe('Feature: strategiesService.ts', () => {
|
|
|
71
72
|
blockNumber: 18015756,
|
|
72
73
|
subscriptionEventData: {
|
|
73
74
|
subId: '379',
|
|
74
|
-
proxy: '
|
|
75
|
+
proxy: '0x9cb7e19861665366011899d74e75d4f2a419aeed',
|
|
75
76
|
subHash: '0xafa4d200be62f171b57b1ae0f4e8348d1ac3f6d0812ad6da74a2adae8037dde1',
|
|
76
77
|
// @ts-ignore
|
|
77
78
|
subStruct:
|