@defisaver/positions-sdk 2.1.156 → 2.1.157
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/aaveV4/merkl.js +28 -10
- package/cjs/types/merkl.d.ts +10 -0
- package/esm/aaveV4/merkl.js +25 -10
- package/esm/types/merkl.d.ts +10 -0
- package/package.json +1 -1
- package/src/aaveV4/merkl.ts +29 -7
- package/src/types/merkl.ts +10 -0
package/cjs/aaveV4/merkl.js
CHANGED
|
@@ -8,14 +8,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.attachAaveV4MerklIncentives = exports.getAaveV4MerkleCampaigns = exports.buildAaveV4MerklRewardMap = void 0;
|
|
16
|
+
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
13
17
|
const moneymarket_1 = require("../moneymarket");
|
|
14
18
|
const merkl_1 = require("../services/merkl");
|
|
15
19
|
const types_1 = require("../types");
|
|
16
20
|
/**
|
|
17
21
|
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
18
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW
|
|
22
|
+
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW / AAVE_V4_HUB_NET_LENDING → hub asset
|
|
19
23
|
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke reserve
|
|
20
24
|
* Embedded campaign params provide the exact on-chain identifiers. Token addresses cannot safely
|
|
21
25
|
* identify Aave V4 rewards because one spoke can expose the same underlying from multiple hubs.
|
|
@@ -42,9 +46,19 @@ const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
42
46
|
.filter((o) => o.status === types_1.OpportunityStatus.LIVE)
|
|
43
47
|
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
44
48
|
.forEach((o) => {
|
|
45
|
-
var _a, _b;
|
|
49
|
+
var _a, _b, _c;
|
|
46
50
|
const side = o.action === types_1.OpportunityAction.BORROW ? types_1.IncentiveSide.Borrow : types_1.IncentiveSide.Supply;
|
|
47
|
-
const
|
|
51
|
+
const now = Date.now() / 1000;
|
|
52
|
+
const methods = (_a = o.campaigns) === null || _a === void 0 ? void 0 : _a.filter((c) => (c.startTimestamp === undefined || c.startTimestamp <= now)
|
|
53
|
+
&& (c.endTimestamp === undefined || c.endTimestamp > now)).map((c) => { var _a, _b; return (_b = (_a = c.params) === null || _a === void 0 ? void 0 : _a.distributionMethodParameters) === null || _b === void 0 ? void 0 : _b.distributionMethod; });
|
|
54
|
+
// An opportunity-level APR cannot be split between simultaneous net and additive campaigns.
|
|
55
|
+
if (side === types_1.IncentiveSide.Supply && (methods === null || methods === void 0 ? void 0 : methods.includes('AAVE_V4_NET_APR'))
|
|
56
|
+
&& methods.some((method) => !!method && method !== 'AAVE_V4_NET_APR'))
|
|
57
|
+
return;
|
|
58
|
+
const incentive = Object.assign(Object.assign({}, buildIncentive(o)), {
|
|
59
|
+
// Missing methods keep the existing target-yield behavior.
|
|
60
|
+
isAdditiveReward: side === types_1.IncentiveSide.Supply && !!(methods === null || methods === void 0 ? void 0 : methods.length)
|
|
61
|
+
&& methods.every((method) => !!method && method !== 'AAVE_V4_NET_APR') });
|
|
48
62
|
// one opportunity can span several campaigns (e.g. renewed periods), so campaign identity is
|
|
49
63
|
// collected per scope key before the reward entries are written
|
|
50
64
|
const idsByKey = {};
|
|
@@ -57,11 +71,13 @@ const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
57
71
|
idsByKey[key].parentCampaignIds.add(campaign.parentCampaignId);
|
|
58
72
|
};
|
|
59
73
|
if (o.type.includes('HUB')) {
|
|
60
|
-
(
|
|
61
|
-
var _a;
|
|
62
|
-
|
|
74
|
+
(_b = o.campaigns) === null || _b === void 0 ? void 0 : _b.forEach((c) => {
|
|
75
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
76
|
+
const hubAddress = (_b = (_a = c.params) === null || _a === void 0 ? void 0 : _a.hubAddress) !== null && _b !== void 0 ? _b : (_e = (_d = (_c = c.params) === null || _c === void 0 ? void 0 : _c.distributionMethodParameters) === null || _d === void 0 ? void 0 : _d.distributionSettings) === null || _e === void 0 ? void 0 : _e.hubAddress;
|
|
77
|
+
const assetId = (_g = (_f = c.params) === null || _f === void 0 ? void 0 : _f.assetId) !== null && _g !== void 0 ? _g : (_k = (_j = (_h = c.params) === null || _h === void 0 ? void 0 : _h.distributionMethodParameters) === null || _j === void 0 ? void 0 : _j.distributionSettings) === null || _k === void 0 ? void 0 : _k.assetId;
|
|
78
|
+
if (!hubAddress || assetId === undefined || assetId === null)
|
|
63
79
|
return;
|
|
64
|
-
collect(scopeKey(
|
|
80
|
+
collect(scopeKey(hubAddress, assetId), c);
|
|
65
81
|
});
|
|
66
82
|
Object.entries(idsByKey).forEach(([key, ids]) => {
|
|
67
83
|
if (!result.hub[key])
|
|
@@ -70,7 +86,7 @@ const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
70
86
|
});
|
|
71
87
|
}
|
|
72
88
|
else if (o.type.includes('SPOKE')) {
|
|
73
|
-
(
|
|
89
|
+
(_c = o.campaigns) === null || _c === void 0 ? void 0 : _c.forEach((c) => {
|
|
74
90
|
var _a;
|
|
75
91
|
if (!((_a = c.params) === null || _a === void 0 ? void 0 : _a.spokeAddress) || c.params.reserveId === undefined || c.params.reserveId === null)
|
|
76
92
|
return;
|
|
@@ -90,7 +106,7 @@ const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0,
|
|
|
90
106
|
try {
|
|
91
107
|
const opportunities = yield (0, merkl_1.fetchAllMerklOpportunities)({
|
|
92
108
|
mainProtocolId: 'aave',
|
|
93
|
-
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
109
|
+
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_HUB_NET_LENDING,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
94
110
|
status: types_1.OpportunityStatus.LIVE,
|
|
95
111
|
campaigns: 'true',
|
|
96
112
|
});
|
|
@@ -112,6 +128,8 @@ const attachAaveV4MerklIncentives = (asset, spokeAddress, campaigns) => {
|
|
|
112
128
|
const baseBorrow = asset.borrowIncentives || [];
|
|
113
129
|
const spokeScoped = spokeAddress ? campaigns.spoke[scopeKey(spokeAddress, asset.reserveId)] : undefined;
|
|
114
130
|
const hubScoped = asset.hub ? campaigns.hub[scopeKey(asset.hub, asset.assetId)] : undefined;
|
|
115
|
-
|
|
131
|
+
// Net-APR campaigns top up native yield; additive campaigns pay their APR on top.
|
|
132
|
+
const supplyRewards = (rewards = []) => rewards.map((reward) => (Object.assign(Object.assign({}, reward), { apy: reward.isAdditiveReward ? reward.apy : decimal_js_1.default.max(0, new decimal_js_1.default(reward.apy).minus(asset.supplyRate || 0)).toString() })));
|
|
133
|
+
return Object.assign(Object.assign({}, asset), { spokeSupplyIncentives: ((_a = spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.supply) === null || _a === void 0 ? void 0 : _a.length) ? [...baseSupply, ...supplyRewards(spokeScoped.supply)] : baseSupply, spokeBorrowIncentives: ((_b = spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.borrow) === null || _b === void 0 ? void 0 : _b.length) ? [...baseBorrow, ...spokeScoped.borrow] : baseBorrow, hubSupplyIncentives: ((_c = hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.supply) === null || _c === void 0 ? void 0 : _c.length) ? [...baseSupply, ...supplyRewards(hubScoped.supply)] : baseSupply, hubBorrowIncentives: ((_d = hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.borrow) === null || _d === void 0 ? void 0 : _d.length) ? [...baseBorrow, ...hubScoped.borrow] : baseBorrow });
|
|
116
134
|
};
|
|
117
135
|
exports.attachAaveV4MerklIncentives = attachAaveV4MerklIncentives;
|
package/cjs/types/merkl.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare enum OpportunityStatus {
|
|
|
11
11
|
export type MerklCampaign = {
|
|
12
12
|
id: string;
|
|
13
13
|
campaignId: string;
|
|
14
|
+
startTimestamp?: number;
|
|
15
|
+
endTimestamp?: number;
|
|
14
16
|
/**
|
|
15
17
|
* Merkl-internal `id` of the parent campaign — set on child campaigns, which re-publish a hub
|
|
16
18
|
* (parent) campaign's reward scoped to a single spoke reserve. Absent on standalone campaigns,
|
|
@@ -24,6 +26,13 @@ export type MerklCampaign = {
|
|
|
24
26
|
hubAddress?: EthAddress;
|
|
25
27
|
hubAssetId?: string | number;
|
|
26
28
|
assetId?: string | number;
|
|
29
|
+
distributionMethodParameters?: {
|
|
30
|
+
distributionMethod?: string;
|
|
31
|
+
distributionSettings?: {
|
|
32
|
+
hubAddress?: EthAddress;
|
|
33
|
+
assetId?: string | number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
27
36
|
};
|
|
28
37
|
};
|
|
29
38
|
export type MerklOpportunity = {
|
|
@@ -102,6 +111,7 @@ export type MerkleRewardMap = Record<EthAddress, {
|
|
|
102
111
|
export type AaveV4MerklIncentive = IncentiveData & {
|
|
103
112
|
campaignIds?: string[];
|
|
104
113
|
parentCampaignIds?: string[];
|
|
114
|
+
isAdditiveReward?: boolean;
|
|
105
115
|
};
|
|
106
116
|
export type AaveV4MerklScopedReward = {
|
|
107
117
|
[side in IncentiveSide]?: AaveV4MerklIncentive[];
|
package/esm/aaveV4/merkl.js
CHANGED
|
@@ -7,12 +7,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
import Dec from 'decimal.js';
|
|
10
11
|
import { aprToApy } from '../moneymarket';
|
|
11
12
|
import { fetchAllMerklOpportunities } from '../services/merkl';
|
|
12
13
|
import { IncentiveKind, IncentiveSide, OpportunityAction, OpportunityStatus, } from '../types';
|
|
13
14
|
/**
|
|
14
15
|
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
15
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW
|
|
16
|
+
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW / AAVE_V4_HUB_NET_LENDING → hub asset
|
|
16
17
|
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke reserve
|
|
17
18
|
* Embedded campaign params provide the exact on-chain identifiers. Token addresses cannot safely
|
|
18
19
|
* identify Aave V4 rewards because one spoke can expose the same underlying from multiple hubs.
|
|
@@ -39,9 +40,19 @@ export const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
39
40
|
.filter((o) => o.status === OpportunityStatus.LIVE)
|
|
40
41
|
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
41
42
|
.forEach((o) => {
|
|
42
|
-
var _a, _b;
|
|
43
|
+
var _a, _b, _c;
|
|
43
44
|
const side = o.action === OpportunityAction.BORROW ? IncentiveSide.Borrow : IncentiveSide.Supply;
|
|
44
|
-
const
|
|
45
|
+
const now = Date.now() / 1000;
|
|
46
|
+
const methods = (_a = o.campaigns) === null || _a === void 0 ? void 0 : _a.filter((c) => (c.startTimestamp === undefined || c.startTimestamp <= now)
|
|
47
|
+
&& (c.endTimestamp === undefined || c.endTimestamp > now)).map((c) => { var _a, _b; return (_b = (_a = c.params) === null || _a === void 0 ? void 0 : _a.distributionMethodParameters) === null || _b === void 0 ? void 0 : _b.distributionMethod; });
|
|
48
|
+
// An opportunity-level APR cannot be split between simultaneous net and additive campaigns.
|
|
49
|
+
if (side === IncentiveSide.Supply && (methods === null || methods === void 0 ? void 0 : methods.includes('AAVE_V4_NET_APR'))
|
|
50
|
+
&& methods.some((method) => !!method && method !== 'AAVE_V4_NET_APR'))
|
|
51
|
+
return;
|
|
52
|
+
const incentive = Object.assign(Object.assign({}, buildIncentive(o)), {
|
|
53
|
+
// Missing methods keep the existing target-yield behavior.
|
|
54
|
+
isAdditiveReward: side === IncentiveSide.Supply && !!(methods === null || methods === void 0 ? void 0 : methods.length)
|
|
55
|
+
&& methods.every((method) => !!method && method !== 'AAVE_V4_NET_APR') });
|
|
45
56
|
// one opportunity can span several campaigns (e.g. renewed periods), so campaign identity is
|
|
46
57
|
// collected per scope key before the reward entries are written
|
|
47
58
|
const idsByKey = {};
|
|
@@ -54,11 +65,13 @@ export const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
54
65
|
idsByKey[key].parentCampaignIds.add(campaign.parentCampaignId);
|
|
55
66
|
};
|
|
56
67
|
if (o.type.includes('HUB')) {
|
|
57
|
-
(
|
|
58
|
-
var _a;
|
|
59
|
-
|
|
68
|
+
(_b = o.campaigns) === null || _b === void 0 ? void 0 : _b.forEach((c) => {
|
|
69
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
70
|
+
const hubAddress = (_b = (_a = c.params) === null || _a === void 0 ? void 0 : _a.hubAddress) !== null && _b !== void 0 ? _b : (_e = (_d = (_c = c.params) === null || _c === void 0 ? void 0 : _c.distributionMethodParameters) === null || _d === void 0 ? void 0 : _d.distributionSettings) === null || _e === void 0 ? void 0 : _e.hubAddress;
|
|
71
|
+
const assetId = (_g = (_f = c.params) === null || _f === void 0 ? void 0 : _f.assetId) !== null && _g !== void 0 ? _g : (_k = (_j = (_h = c.params) === null || _h === void 0 ? void 0 : _h.distributionMethodParameters) === null || _j === void 0 ? void 0 : _j.distributionSettings) === null || _k === void 0 ? void 0 : _k.assetId;
|
|
72
|
+
if (!hubAddress || assetId === undefined || assetId === null)
|
|
60
73
|
return;
|
|
61
|
-
collect(scopeKey(
|
|
74
|
+
collect(scopeKey(hubAddress, assetId), c);
|
|
62
75
|
});
|
|
63
76
|
Object.entries(idsByKey).forEach(([key, ids]) => {
|
|
64
77
|
if (!result.hub[key])
|
|
@@ -67,7 +80,7 @@ export const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
67
80
|
});
|
|
68
81
|
}
|
|
69
82
|
else if (o.type.includes('SPOKE')) {
|
|
70
|
-
(
|
|
83
|
+
(_c = o.campaigns) === null || _c === void 0 ? void 0 : _c.forEach((c) => {
|
|
71
84
|
var _a;
|
|
72
85
|
if (!((_a = c.params) === null || _a === void 0 ? void 0 : _a.spokeAddress) || c.params.reserveId === undefined || c.params.reserveId === null)
|
|
73
86
|
return;
|
|
@@ -86,7 +99,7 @@ export const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, v
|
|
|
86
99
|
try {
|
|
87
100
|
const opportunities = yield fetchAllMerklOpportunities({
|
|
88
101
|
mainProtocolId: 'aave',
|
|
89
|
-
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
102
|
+
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_HUB_NET_LENDING,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
90
103
|
status: OpportunityStatus.LIVE,
|
|
91
104
|
campaigns: 'true',
|
|
92
105
|
});
|
|
@@ -107,5 +120,7 @@ export const attachAaveV4MerklIncentives = (asset, spokeAddress, campaigns) => {
|
|
|
107
120
|
const baseBorrow = asset.borrowIncentives || [];
|
|
108
121
|
const spokeScoped = spokeAddress ? campaigns.spoke[scopeKey(spokeAddress, asset.reserveId)] : undefined;
|
|
109
122
|
const hubScoped = asset.hub ? campaigns.hub[scopeKey(asset.hub, asset.assetId)] : undefined;
|
|
110
|
-
|
|
123
|
+
// Net-APR campaigns top up native yield; additive campaigns pay their APR on top.
|
|
124
|
+
const supplyRewards = (rewards = []) => rewards.map((reward) => (Object.assign(Object.assign({}, reward), { apy: reward.isAdditiveReward ? reward.apy : Dec.max(0, new Dec(reward.apy).minus(asset.supplyRate || 0)).toString() })));
|
|
125
|
+
return Object.assign(Object.assign({}, asset), { spokeSupplyIncentives: ((_a = spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.supply) === null || _a === void 0 ? void 0 : _a.length) ? [...baseSupply, ...supplyRewards(spokeScoped.supply)] : baseSupply, spokeBorrowIncentives: ((_b = spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.borrow) === null || _b === void 0 ? void 0 : _b.length) ? [...baseBorrow, ...spokeScoped.borrow] : baseBorrow, hubSupplyIncentives: ((_c = hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.supply) === null || _c === void 0 ? void 0 : _c.length) ? [...baseSupply, ...supplyRewards(hubScoped.supply)] : baseSupply, hubBorrowIncentives: ((_d = hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.borrow) === null || _d === void 0 ? void 0 : _d.length) ? [...baseBorrow, ...hubScoped.borrow] : baseBorrow });
|
|
111
126
|
};
|
package/esm/types/merkl.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare enum OpportunityStatus {
|
|
|
11
11
|
export type MerklCampaign = {
|
|
12
12
|
id: string;
|
|
13
13
|
campaignId: string;
|
|
14
|
+
startTimestamp?: number;
|
|
15
|
+
endTimestamp?: number;
|
|
14
16
|
/**
|
|
15
17
|
* Merkl-internal `id` of the parent campaign — set on child campaigns, which re-publish a hub
|
|
16
18
|
* (parent) campaign's reward scoped to a single spoke reserve. Absent on standalone campaigns,
|
|
@@ -24,6 +26,13 @@ export type MerklCampaign = {
|
|
|
24
26
|
hubAddress?: EthAddress;
|
|
25
27
|
hubAssetId?: string | number;
|
|
26
28
|
assetId?: string | number;
|
|
29
|
+
distributionMethodParameters?: {
|
|
30
|
+
distributionMethod?: string;
|
|
31
|
+
distributionSettings?: {
|
|
32
|
+
hubAddress?: EthAddress;
|
|
33
|
+
assetId?: string | number;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
27
36
|
};
|
|
28
37
|
};
|
|
29
38
|
export type MerklOpportunity = {
|
|
@@ -102,6 +111,7 @@ export type MerkleRewardMap = Record<EthAddress, {
|
|
|
102
111
|
export type AaveV4MerklIncentive = IncentiveData & {
|
|
103
112
|
campaignIds?: string[];
|
|
104
113
|
parentCampaignIds?: string[];
|
|
114
|
+
isAdditiveReward?: boolean;
|
|
105
115
|
};
|
|
106
116
|
export type AaveV4MerklScopedReward = {
|
|
107
117
|
[side in IncentiveSide]?: AaveV4MerklIncentive[];
|
package/package.json
CHANGED
package/src/aaveV4/merkl.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import Dec from 'decimal.js';
|
|
1
2
|
import { aprToApy } from '../moneymarket';
|
|
2
3
|
import { fetchAllMerklOpportunities } from '../services/merkl';
|
|
3
4
|
import {
|
|
4
5
|
AaveV4MerklRewardMap,
|
|
6
|
+
AaveV4MerklIncentive,
|
|
5
7
|
AaveV4ReserveAssetData,
|
|
6
8
|
IncentiveData,
|
|
7
9
|
IncentiveKind,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
18
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW
|
|
20
|
+
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW / AAVE_V4_HUB_NET_LENDING → hub asset
|
|
19
21
|
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke reserve
|
|
20
22
|
* Embedded campaign params provide the exact on-chain identifiers. Token addresses cannot safely
|
|
21
23
|
* identify Aave V4 rewards because one spoke can expose the same underlying from multiple hubs.
|
|
@@ -46,7 +48,20 @@ export const buildAaveV4MerklRewardMap = (opportunities: MerklOpportunity[], cha
|
|
|
46
48
|
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
47
49
|
.forEach((o) => {
|
|
48
50
|
const side = o.action === OpportunityAction.BORROW ? IncentiveSide.Borrow : IncentiveSide.Supply;
|
|
49
|
-
const
|
|
51
|
+
const now = Date.now() / 1000;
|
|
52
|
+
const methods = o.campaigns
|
|
53
|
+
?.filter((c) => (c.startTimestamp === undefined || c.startTimestamp <= now)
|
|
54
|
+
&& (c.endTimestamp === undefined || c.endTimestamp > now))
|
|
55
|
+
.map((c) => c.params?.distributionMethodParameters?.distributionMethod);
|
|
56
|
+
// An opportunity-level APR cannot be split between simultaneous net and additive campaigns.
|
|
57
|
+
if (side === IncentiveSide.Supply && methods?.includes('AAVE_V4_NET_APR')
|
|
58
|
+
&& methods.some((method) => !!method && method !== 'AAVE_V4_NET_APR')) return;
|
|
59
|
+
const incentive = {
|
|
60
|
+
...buildIncentive(o),
|
|
61
|
+
// Missing methods keep the existing target-yield behavior.
|
|
62
|
+
isAdditiveReward: side === IncentiveSide.Supply && !!methods?.length
|
|
63
|
+
&& methods.every((method) => !!method && method !== 'AAVE_V4_NET_APR'),
|
|
64
|
+
};
|
|
50
65
|
// one opportunity can span several campaigns (e.g. renewed periods), so campaign identity is
|
|
51
66
|
// collected per scope key before the reward entries are written
|
|
52
67
|
const idsByKey: Record<string, { campaignIds: Set<string>, parentCampaignIds: Set<string> }> = {};
|
|
@@ -58,8 +73,10 @@ export const buildAaveV4MerklRewardMap = (opportunities: MerklOpportunity[], cha
|
|
|
58
73
|
|
|
59
74
|
if (o.type.includes('HUB')) {
|
|
60
75
|
o.campaigns?.forEach((c) => {
|
|
61
|
-
|
|
62
|
-
|
|
76
|
+
const hubAddress = c.params?.hubAddress ?? c.params?.distributionMethodParameters?.distributionSettings?.hubAddress;
|
|
77
|
+
const assetId = c.params?.assetId ?? c.params?.distributionMethodParameters?.distributionSettings?.assetId;
|
|
78
|
+
if (!hubAddress || assetId === undefined || assetId === null) return;
|
|
79
|
+
collect(scopeKey(hubAddress, assetId), c);
|
|
63
80
|
});
|
|
64
81
|
Object.entries(idsByKey).forEach(([key, ids]) => {
|
|
65
82
|
if (!result.hub[key]) result.hub[key] = {};
|
|
@@ -84,7 +101,7 @@ export const getAaveV4MerkleCampaigns = async (chainId: NetworkNumber): Promise<
|
|
|
84
101
|
try {
|
|
85
102
|
const opportunities = await fetchAllMerklOpportunities({
|
|
86
103
|
mainProtocolId: 'aave',
|
|
87
|
-
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
104
|
+
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_HUB_NET_LENDING,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
88
105
|
status: OpportunityStatus.LIVE,
|
|
89
106
|
campaigns: 'true',
|
|
90
107
|
});
|
|
@@ -105,12 +122,17 @@ export const attachAaveV4MerklIncentives = (asset: AaveV4ReserveAssetData, spoke
|
|
|
105
122
|
|
|
106
123
|
const spokeScoped = spokeAddress ? campaigns.spoke[scopeKey(spokeAddress, asset.reserveId)] : undefined;
|
|
107
124
|
const hubScoped = asset.hub ? campaigns.hub[scopeKey(asset.hub, asset.assetId)] : undefined;
|
|
125
|
+
// Net-APR campaigns top up native yield; additive campaigns pay their APR on top.
|
|
126
|
+
const supplyRewards = (rewards: AaveV4MerklIncentive[] = []) => rewards.map((reward) => ({
|
|
127
|
+
...reward,
|
|
128
|
+
apy: reward.isAdditiveReward ? reward.apy : Dec.max(0, new Dec(reward.apy).minus(asset.supplyRate || 0)).toString(),
|
|
129
|
+
}));
|
|
108
130
|
|
|
109
131
|
return {
|
|
110
132
|
...asset,
|
|
111
|
-
spokeSupplyIncentives: spokeScoped?.supply?.length ? [...baseSupply, ...spokeScoped.supply] : baseSupply,
|
|
133
|
+
spokeSupplyIncentives: spokeScoped?.supply?.length ? [...baseSupply, ...supplyRewards(spokeScoped.supply)] : baseSupply,
|
|
112
134
|
spokeBorrowIncentives: spokeScoped?.borrow?.length ? [...baseBorrow, ...spokeScoped.borrow] : baseBorrow,
|
|
113
|
-
hubSupplyIncentives: hubScoped?.supply?.length ? [...baseSupply, ...hubScoped.supply] : baseSupply,
|
|
135
|
+
hubSupplyIncentives: hubScoped?.supply?.length ? [...baseSupply, ...supplyRewards(hubScoped.supply)] : baseSupply,
|
|
114
136
|
hubBorrowIncentives: hubScoped?.borrow?.length ? [...baseBorrow, ...hubScoped.borrow] : baseBorrow,
|
|
115
137
|
};
|
|
116
138
|
};
|
package/src/types/merkl.ts
CHANGED
|
@@ -14,6 +14,8 @@ export enum OpportunityStatus {
|
|
|
14
14
|
export type MerklCampaign = {
|
|
15
15
|
id: string;
|
|
16
16
|
campaignId: string;
|
|
17
|
+
startTimestamp?: number;
|
|
18
|
+
endTimestamp?: number;
|
|
17
19
|
/**
|
|
18
20
|
* Merkl-internal `id` of the parent campaign — set on child campaigns, which re-publish a hub
|
|
19
21
|
* (parent) campaign's reward scoped to a single spoke reserve. Absent on standalone campaigns,
|
|
@@ -27,6 +29,13 @@ export type MerklCampaign = {
|
|
|
27
29
|
hubAddress?: EthAddress;
|
|
28
30
|
hubAssetId?: string | number;
|
|
29
31
|
assetId?: string | number;
|
|
32
|
+
distributionMethodParameters?: {
|
|
33
|
+
distributionMethod?: string;
|
|
34
|
+
distributionSettings?: {
|
|
35
|
+
hubAddress?: EthAddress;
|
|
36
|
+
assetId?: string | number;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
30
39
|
};
|
|
31
40
|
};
|
|
32
41
|
|
|
@@ -100,6 +109,7 @@ export type MerkleRewardMap = Record<EthAddress, { supply?: MerkleRewardInfo; bo
|
|
|
100
109
|
export type AaveV4MerklIncentive = IncentiveData & {
|
|
101
110
|
campaignIds?: string[];
|
|
102
111
|
parentCampaignIds?: string[];
|
|
112
|
+
isAdditiveReward?: boolean;
|
|
103
113
|
};
|
|
104
114
|
|
|
105
115
|
export type AaveV4MerklScopedReward = { [side in IncentiveSide]?: AaveV4MerklIncentive[] };
|