@defisaver/automation-sdk 3.3.11-aave-v4-dev → 3.3.11-aave-v4-1-dev
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/automation/private/StrategiesAutomation.d.ts +2 -0
- package/cjs/automation/private/StrategiesAutomation.js +10 -1
- package/cjs/automation/private/StrategiesAutomation.test.js +25 -0
- package/esm/automation/private/StrategiesAutomation.d.ts +2 -0
- package/esm/automation/private/StrategiesAutomation.js +10 -1
- package/esm/automation/private/StrategiesAutomation.test.js +25 -0
- package/package.json +1 -1
- package/src/automation/private/StrategiesAutomation.test.ts +40 -0
- package/src/automation/private/StrategiesAutomation.ts +11 -0
|
@@ -25,6 +25,8 @@ export default class StrategiesAutomation extends Automation {
|
|
|
25
25
|
*/
|
|
26
26
|
protected removeExpiredSubscriptions(subscriptions: (Position.Automated | null)[]): (Position.Automated | null)[];
|
|
27
27
|
private _mergeCheck;
|
|
28
|
+
/** Repay/boost leverage pairs must not merge across different Aave V4 spokes. */
|
|
29
|
+
private _aaveV4MergeSpokesMatch;
|
|
28
30
|
protected mergeSubs(_subscriptions: (Position.Automated | null)[]): Position.Automated[];
|
|
29
31
|
protected _getSubscriptions(addresses?: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
30
32
|
getSubscriptions(options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
@@ -104,7 +104,16 @@ class StrategiesAutomation extends Automation_1.default {
|
|
|
104
104
|
&& (s.protocol.id !== enums_1.ProtocolIdentifiers.StrategiesAutomation.CrvUSD // merge only crvUSD leverage management for the same market
|
|
105
105
|
|| s.strategyData.decoded.subData.controller.toLowerCase() === current.strategyData.decoded.triggerData.controller.toLowerCase())
|
|
106
106
|
&& (s.protocol.id !== enums_1.ProtocolIdentifiers.StrategiesAutomation.MorphoBlue // merge morpho blue with the same marketId
|
|
107
|
-
|| s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase())
|
|
107
|
+
|| s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase())
|
|
108
|
+
&& (s.protocol.id !== enums_1.ProtocolIdentifiers.StrategiesAutomation.AaveV4
|
|
109
|
+
|| this._aaveV4MergeSpokesMatch(s, current));
|
|
110
|
+
}
|
|
111
|
+
/** Repay/boost leverage pairs must not merge across different Aave V4 spokes. */
|
|
112
|
+
_aaveV4MergeSpokesMatch(s, current) {
|
|
113
|
+
var _a, _b, _c, _d, _e, _f;
|
|
114
|
+
const a = (_c = (_b = (_a = s.strategyData) === null || _a === void 0 ? void 0 : _a.decoded) === null || _b === void 0 ? void 0 : _b.triggerData) === null || _c === void 0 ? void 0 : _c.spoke;
|
|
115
|
+
const b = (_f = (_e = (_d = current.strategyData) === null || _d === void 0 ? void 0 : _d.decoded) === null || _e === void 0 ? void 0 : _e.triggerData) === null || _f === void 0 ? void 0 : _f.spoke;
|
|
116
|
+
return !!a && !!b && a.toLowerCase() === b.toLowerCase();
|
|
108
117
|
}
|
|
109
118
|
mergeSubs(_subscriptions) {
|
|
110
119
|
const mergeBase = _subscriptions.filter(s => (0, utils_1.isDefined)(s) && (0, utils_1.isDefined)(s.specific.mergeWithId));
|
|
@@ -667,5 +667,30 @@ describe('Feature: StrategiesAutomation.ts', () => {
|
|
|
667
667
|
(0, chai_1.expect)(JSON.stringify(actual)).to.equal(JSON.stringify(expected));
|
|
668
668
|
}));
|
|
669
669
|
});
|
|
670
|
+
it('Aave V4: pairs repay/boost merge only when trigger spoke matches (no cross-spoke merge)', () => {
|
|
671
|
+
var _a, _b, _c;
|
|
672
|
+
const spoke1 = '0x0000000000000000000000000000000000000a01';
|
|
673
|
+
const spoke2 = '0x0000000000000000000000000000000000000a02';
|
|
674
|
+
const base = {
|
|
675
|
+
isEnabled: true,
|
|
676
|
+
chainId: 1,
|
|
677
|
+
owner: '0x0000000000000000000000000000000000000b01',
|
|
678
|
+
protocol: { id: 'Aave__V4' },
|
|
679
|
+
strategy: { strategyId: 'leverage-management' },
|
|
680
|
+
blockNumber: 0,
|
|
681
|
+
subHash: '0x1',
|
|
682
|
+
positionId: 'test',
|
|
683
|
+
};
|
|
684
|
+
const boostSpoke1 = Object.assign(Object.assign({}, base), { subId: 1, strategyData: { decoded: { triggerData: { spoke: spoke1 }, subData: {} } }, specific: { mergeId: 'boost', subId2: 1 } });
|
|
685
|
+
const repaySpoke2 = Object.assign(Object.assign({}, base), { subId: 2, strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } }, specific: { mergeWithId: 'boost', subId1: 2 } });
|
|
686
|
+
const boostSpoke2 = Object.assign(Object.assign({}, base), { subId: 3, strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } }, specific: { mergeId: 'boost', subId2: 3 } });
|
|
687
|
+
// @ts-ignore — mergeSubs is protected; exercised here as in examples above
|
|
688
|
+
const merged = exampleStrategiesAutomation.mergeSubs([boostSpoke1, repaySpoke2, boostSpoke2]);
|
|
689
|
+
(0, chai_1.expect)(merged).to.have.length(2);
|
|
690
|
+
const mergedPair = merged.find((m) => { var _a; return ((_a = m.subIds) === null || _a === void 0 ? void 0 : _a.length) === 2; });
|
|
691
|
+
const loneBoost = merged.find((m) => { var _a; return ((_a = m.subIds) === null || _a === void 0 ? void 0 : _a.length) === 1; });
|
|
692
|
+
(0, chai_1.expect)((_c = (_b = (_a = mergedPair === null || mergedPair === void 0 ? void 0 : mergedPair.strategyData) === null || _a === void 0 ? void 0 : _a.decoded) === null || _b === void 0 ? void 0 : _b.triggerData) === null || _c === void 0 ? void 0 : _c.spoke).to.equal(spoke2);
|
|
693
|
+
(0, chai_1.expect)(loneBoost === null || loneBoost === void 0 ? void 0 : loneBoost.subId).to.equal(1);
|
|
694
|
+
});
|
|
670
695
|
}));
|
|
671
696
|
});
|
|
@@ -25,6 +25,8 @@ export default class StrategiesAutomation extends Automation {
|
|
|
25
25
|
*/
|
|
26
26
|
protected removeExpiredSubscriptions(subscriptions: (Position.Automated | null)[]): (Position.Automated | null)[];
|
|
27
27
|
private _mergeCheck;
|
|
28
|
+
/** Repay/boost leverage pairs must not merge across different Aave V4 spokes. */
|
|
29
|
+
private _aaveV4MergeSpokesMatch;
|
|
28
30
|
protected mergeSubs(_subscriptions: (Position.Automated | null)[]): Position.Automated[];
|
|
29
31
|
protected _getSubscriptions(addresses?: EthereumAddress[], options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
30
32
|
getSubscriptions(options?: SubscriptionOptions): Promise<(Position.Automated | null)[]>;
|
|
@@ -99,7 +99,16 @@ export default class StrategiesAutomation extends Automation {
|
|
|
99
99
|
&& (s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.CrvUSD // merge only crvUSD leverage management for the same market
|
|
100
100
|
|| s.strategyData.decoded.subData.controller.toLowerCase() === current.strategyData.decoded.triggerData.controller.toLowerCase())
|
|
101
101
|
&& (s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.MorphoBlue // merge morpho blue with the same marketId
|
|
102
|
-
|| s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase())
|
|
102
|
+
|| s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase())
|
|
103
|
+
&& (s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.AaveV4
|
|
104
|
+
|| this._aaveV4MergeSpokesMatch(s, current));
|
|
105
|
+
}
|
|
106
|
+
/** Repay/boost leverage pairs must not merge across different Aave V4 spokes. */
|
|
107
|
+
_aaveV4MergeSpokesMatch(s, current) {
|
|
108
|
+
var _a, _b, _c, _d, _e, _f;
|
|
109
|
+
const a = (_c = (_b = (_a = s.strategyData) === null || _a === void 0 ? void 0 : _a.decoded) === null || _b === void 0 ? void 0 : _b.triggerData) === null || _c === void 0 ? void 0 : _c.spoke;
|
|
110
|
+
const b = (_f = (_e = (_d = current.strategyData) === null || _d === void 0 ? void 0 : _d.decoded) === null || _e === void 0 ? void 0 : _e.triggerData) === null || _f === void 0 ? void 0 : _f.spoke;
|
|
111
|
+
return !!a && !!b && a.toLowerCase() === b.toLowerCase();
|
|
103
112
|
}
|
|
104
113
|
mergeSubs(_subscriptions) {
|
|
105
114
|
const mergeBase = _subscriptions.filter(s => isDefined(s) && isDefined(s.specific.mergeWithId));
|
|
@@ -662,5 +662,30 @@ describe('Feature: StrategiesAutomation.ts', () => {
|
|
|
662
662
|
expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected));
|
|
663
663
|
}));
|
|
664
664
|
});
|
|
665
|
+
it('Aave V4: pairs repay/boost merge only when trigger spoke matches (no cross-spoke merge)', () => {
|
|
666
|
+
var _a, _b, _c;
|
|
667
|
+
const spoke1 = '0x0000000000000000000000000000000000000a01';
|
|
668
|
+
const spoke2 = '0x0000000000000000000000000000000000000a02';
|
|
669
|
+
const base = {
|
|
670
|
+
isEnabled: true,
|
|
671
|
+
chainId: 1,
|
|
672
|
+
owner: '0x0000000000000000000000000000000000000b01',
|
|
673
|
+
protocol: { id: 'Aave__V4' },
|
|
674
|
+
strategy: { strategyId: 'leverage-management' },
|
|
675
|
+
blockNumber: 0,
|
|
676
|
+
subHash: '0x1',
|
|
677
|
+
positionId: 'test',
|
|
678
|
+
};
|
|
679
|
+
const boostSpoke1 = Object.assign(Object.assign({}, base), { subId: 1, strategyData: { decoded: { triggerData: { spoke: spoke1 }, subData: {} } }, specific: { mergeId: 'boost', subId2: 1 } });
|
|
680
|
+
const repaySpoke2 = Object.assign(Object.assign({}, base), { subId: 2, strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } }, specific: { mergeWithId: 'boost', subId1: 2 } });
|
|
681
|
+
const boostSpoke2 = Object.assign(Object.assign({}, base), { subId: 3, strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } }, specific: { mergeId: 'boost', subId2: 3 } });
|
|
682
|
+
// @ts-ignore — mergeSubs is protected; exercised here as in examples above
|
|
683
|
+
const merged = exampleStrategiesAutomation.mergeSubs([boostSpoke1, repaySpoke2, boostSpoke2]);
|
|
684
|
+
expect(merged).to.have.length(2);
|
|
685
|
+
const mergedPair = merged.find((m) => { var _a; return ((_a = m.subIds) === null || _a === void 0 ? void 0 : _a.length) === 2; });
|
|
686
|
+
const loneBoost = merged.find((m) => { var _a; return ((_a = m.subIds) === null || _a === void 0 ? void 0 : _a.length) === 1; });
|
|
687
|
+
expect((_c = (_b = (_a = mergedPair === null || mergedPair === void 0 ? void 0 : mergedPair.strategyData) === null || _a === void 0 ? void 0 : _a.decoded) === null || _b === void 0 ? void 0 : _b.triggerData) === null || _c === void 0 ? void 0 : _c.spoke).to.equal(spoke2);
|
|
688
|
+
expect(loneBoost === null || loneBoost === void 0 ? void 0 : loneBoost.subId).to.equal(1);
|
|
689
|
+
});
|
|
665
690
|
}));
|
|
666
691
|
});
|
package/package.json
CHANGED
|
@@ -659,5 +659,45 @@ describe('Feature: StrategiesAutomation.ts', () => {
|
|
|
659
659
|
expect(JSON.stringify(actual)).to.equal(JSON.stringify(expected));
|
|
660
660
|
});
|
|
661
661
|
});
|
|
662
|
+
|
|
663
|
+
it('Aave V4: pairs repay/boost merge only when trigger spoke matches (no cross-spoke merge)', () => {
|
|
664
|
+
const spoke1 = '0x0000000000000000000000000000000000000a01';
|
|
665
|
+
const spoke2 = '0x0000000000000000000000000000000000000a02';
|
|
666
|
+
const base = {
|
|
667
|
+
isEnabled: true,
|
|
668
|
+
chainId: 1,
|
|
669
|
+
owner: '0x0000000000000000000000000000000000000b01',
|
|
670
|
+
protocol: { id: 'Aave__V4' },
|
|
671
|
+
strategy: { strategyId: 'leverage-management' },
|
|
672
|
+
blockNumber: 0,
|
|
673
|
+
subHash: '0x1',
|
|
674
|
+
positionId: 'test',
|
|
675
|
+
};
|
|
676
|
+
const boostSpoke1 = {
|
|
677
|
+
...base,
|
|
678
|
+
subId: 1,
|
|
679
|
+
strategyData: { decoded: { triggerData: { spoke: spoke1 }, subData: {} } },
|
|
680
|
+
specific: { mergeId: 'boost', subId2: 1 },
|
|
681
|
+
};
|
|
682
|
+
const repaySpoke2 = {
|
|
683
|
+
...base,
|
|
684
|
+
subId: 2,
|
|
685
|
+
strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } },
|
|
686
|
+
specific: { mergeWithId: 'boost', subId1: 2 },
|
|
687
|
+
};
|
|
688
|
+
const boostSpoke2 = {
|
|
689
|
+
...base,
|
|
690
|
+
subId: 3,
|
|
691
|
+
strategyData: { decoded: { triggerData: { spoke: spoke2 }, subData: {} } },
|
|
692
|
+
specific: { mergeId: 'boost', subId2: 3 },
|
|
693
|
+
};
|
|
694
|
+
// @ts-ignore — mergeSubs is protected; exercised here as in examples above
|
|
695
|
+
const merged = exampleStrategiesAutomation.mergeSubs([boostSpoke1, repaySpoke2, boostSpoke2]);
|
|
696
|
+
expect(merged).to.have.length(2);
|
|
697
|
+
const mergedPair = merged.find((m: { subIds?: number[] }) => m.subIds?.length === 2);
|
|
698
|
+
const loneBoost = merged.find((m: { subIds?: number[] }) => m.subIds?.length === 1);
|
|
699
|
+
expect(mergedPair?.strategyData?.decoded?.triggerData?.spoke).to.equal(spoke2);
|
|
700
|
+
expect(loneBoost?.subId).to.equal(1);
|
|
701
|
+
});
|
|
662
702
|
});
|
|
663
703
|
});
|
|
@@ -129,9 +129,20 @@ export default class StrategiesAutomation extends Automation {
|
|
|
129
129
|
&& (
|
|
130
130
|
s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.MorphoBlue // merge morpho blue with the same marketId
|
|
131
131
|
|| s.strategyData.decoded.triggerData.marketId.toLowerCase() === current.strategyData.decoded.triggerData.marketId.toLowerCase()
|
|
132
|
+
)
|
|
133
|
+
&& (
|
|
134
|
+
s.protocol.id !== ProtocolIdentifiers.StrategiesAutomation.AaveV4
|
|
135
|
+
|| this._aaveV4MergeSpokesMatch(s, current)
|
|
132
136
|
);
|
|
133
137
|
}
|
|
134
138
|
|
|
139
|
+
/** Repay/boost leverage pairs must not merge across different Aave V4 spokes. */
|
|
140
|
+
private _aaveV4MergeSpokesMatch(s: Position.Automated, current: Position.Automated): boolean {
|
|
141
|
+
const a = s.strategyData?.decoded?.triggerData?.spoke as EthereumAddress | undefined;
|
|
142
|
+
const b = current.strategyData?.decoded?.triggerData?.spoke as EthereumAddress | undefined;
|
|
143
|
+
return !!a && !!b && a.toLowerCase() === b.toLowerCase();
|
|
144
|
+
}
|
|
145
|
+
|
|
135
146
|
protected mergeSubs(_subscriptions:(Position.Automated | null)[]) {
|
|
136
147
|
const mergeBase = _subscriptions.filter(s => isDefined(s) && isDefined(s.specific.mergeWithId)) as Position.Automated[];
|
|
137
148
|
const mergeExtension = _subscriptions.filter(s => isDefined(s) && isDefined(s.specific.mergeId)) as Position.Automated[];
|