@defisaver/positions-sdk 2.1.102-aave-v4-merkl-1-dev → 2.1.103
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/index.d.ts +0 -1
- package/cjs/aaveV4/index.js +2 -8
- package/cjs/savings/morphoVaults/index.js +15 -18
- package/cjs/types/aaveV4.d.ts +0 -10
- package/cjs/types/merkl.d.ts +1 -14
- package/esm/aaveV4/index.d.ts +0 -1
- package/esm/aaveV4/index.js +1 -6
- package/esm/savings/morphoVaults/index.js +15 -18
- package/esm/types/aaveV4.d.ts +0 -10
- package/esm/types/merkl.d.ts +1 -14
- package/package.json +1 -1
- package/src/aaveV4/index.ts +1 -7
- package/src/savings/morphoVaults/index.ts +15 -18
- package/src/types/aaveV4.ts +0 -10
- package/src/types/merkl.ts +2 -14
- package/cjs/aaveV4/merkl.d.ts +0 -8
- package/cjs/aaveV4/merkl.js +0 -90
- package/esm/aaveV4/merkl.d.ts +0 -8
- package/esm/aaveV4/merkl.js +0 -85
- package/src/aaveV4/merkl.ts +0 -92
package/cjs/aaveV4/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Client } from 'viem';
|
|
2
2
|
import { AaveV4AccountData, AaveV4SpokeData, AaveV4SpokeInfo, EthAddress, EthereumProvider, NetworkNumber } from '../types';
|
|
3
3
|
export * as lend from './lend';
|
|
4
|
-
export { getAaveV4MerkleCampaigns } from './merkl';
|
|
5
4
|
export declare function _getAaveV4SpokeData(provider: Client, network: NetworkNumber, market: AaveV4SpokeInfo, blockNumber?: 'latest' | number): Promise<AaveV4SpokeData>;
|
|
6
5
|
export declare function getAaveV4SpokeData(provider: EthereumProvider, network: NetworkNumber, spoke: AaveV4SpokeInfo, blockNumber?: 'latest' | number): Promise<AaveV4SpokeData>;
|
|
7
6
|
export declare function _getAaveV4AccountData(provider: Client, network: NetworkNumber, spokeData: AaveV4SpokeData, address: EthAddress, blockNumber?: 'latest' | number): Promise<AaveV4AccountData>;
|
package/cjs/aaveV4/index.js
CHANGED
|
@@ -45,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
45
45
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
46
|
};
|
|
47
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
-
exports.
|
|
48
|
+
exports.lend = void 0;
|
|
49
49
|
exports._getAaveV4SpokeData = _getAaveV4SpokeData;
|
|
50
50
|
exports.getAaveV4SpokeData = getAaveV4SpokeData;
|
|
51
51
|
exports._getAaveV4AccountData = _getAaveV4AccountData;
|
|
@@ -61,10 +61,7 @@ const utils_1 = require("../services/utils");
|
|
|
61
61
|
const aaveV4Helpers_1 = require("../helpers/aaveV4Helpers");
|
|
62
62
|
const aaveV4_1 = require("../markets/aaveV4");
|
|
63
63
|
const moneymarket_1 = require("../moneymarket");
|
|
64
|
-
const merkl_1 = require("./merkl");
|
|
65
64
|
exports.lend = __importStar(require("./lend"));
|
|
66
|
-
var merkl_2 = require("./merkl");
|
|
67
|
-
Object.defineProperty(exports, "getAaveV4MerkleCampaigns", { enumerable: true, get: function () { return merkl_2.getAaveV4MerkleCampaigns; } });
|
|
68
65
|
const fetchHubData = (viewContract, hubAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
66
|
const hubData = yield viewContract.read.getHubAllAssetsData([hubAddress]);
|
|
70
67
|
return {
|
|
@@ -176,7 +173,6 @@ function _getAaveV4SpokeData(provider_1, network_1, market_1) {
|
|
|
176
173
|
return __awaiter(this, arguments, void 0, function* (provider, network, market, blockNumber = 'latest') {
|
|
177
174
|
const viewContract = (0, contracts_1.AaveV4ViewContractViem)(provider, network, blockNumber);
|
|
178
175
|
const hubsData = {};
|
|
179
|
-
const merklCampaignsPromise = (0, merkl_1.getAaveV4MerkleCampaigns)(network);
|
|
180
176
|
const [spokeData] = yield Promise.all([
|
|
181
177
|
viewContract.read.getSpokeDataFull([market.address]),
|
|
182
178
|
...market.hubs.map((hubAddress) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -184,10 +180,8 @@ function _getAaveV4SpokeData(provider_1, network_1, market_1) {
|
|
|
184
180
|
})),
|
|
185
181
|
]);
|
|
186
182
|
const reserveAssetsArray = yield Promise.all(spokeData[1].map((reserveAssetOnChain, index) => __awaiter(this, void 0, void 0, function* () { return formatReserveAsset(reserveAssetOnChain, hubsData[reserveAssetOnChain.hub].assets[reserveAssetOnChain.assetId], index, +spokeData[0].oracleDecimals.toString(), network); })));
|
|
187
|
-
const merklCampaigns = yield merklCampaignsPromise;
|
|
188
|
-
const enrichedAssets = reserveAssetsArray.map((asset) => (0, merkl_1.attachAaveV4MerklIncentives)(asset, market.address, merklCampaigns));
|
|
189
183
|
return {
|
|
190
|
-
assetsData:
|
|
184
|
+
assetsData: reserveAssetsArray.reduce((acc, reserveAsset) => {
|
|
191
185
|
acc[`${reserveAsset.symbol}-${reserveAsset.reserveId}`] = reserveAsset;
|
|
192
186
|
return acc;
|
|
193
187
|
}, {}),
|
|
@@ -54,25 +54,22 @@ const morphoVaultsOptions = __importStar(require("./options"));
|
|
|
54
54
|
exports.morphoVaultsOptions = morphoVaultsOptions;
|
|
55
55
|
const viem_1 = require("../../services/viem");
|
|
56
56
|
const contracts_1 = require("../../contracts");
|
|
57
|
-
const vaultDataQuery =
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
asset {
|
|
71
|
-
priceUsd
|
|
57
|
+
const vaultDataQuery = `
|
|
58
|
+
query VaultByAddress($address: String!, $chainId: Int!) {
|
|
59
|
+
vaultByAddress(address: $address, chainId: $chainId) {
|
|
60
|
+
address
|
|
61
|
+
state {
|
|
62
|
+
totalAssets
|
|
63
|
+
totalAssetsUsd
|
|
64
|
+
totalSupply
|
|
65
|
+
}
|
|
66
|
+
liquidity {
|
|
67
|
+
underlying
|
|
68
|
+
usd
|
|
69
|
+
}
|
|
72
70
|
}
|
|
73
|
-
}
|
|
74
71
|
}`;
|
|
75
|
-
const MORPHO_BLUE_API = 'https://
|
|
72
|
+
const MORPHO_BLUE_API = 'https://api.morpho.org/graphql';
|
|
76
73
|
const _getMorphoVaultData = (provider, network, morphoVault, accounts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
74
|
const morphoVaultContract = (0, contracts_1.getMorphoVaultContractViem)(provider, morphoVault.address);
|
|
78
75
|
const shares = {};
|
|
@@ -81,7 +78,7 @@ const _getMorphoVaultData = (provider, network, morphoVault, accounts) => __awai
|
|
|
81
78
|
morphoVaultContract.read.totalSupply(),
|
|
82
79
|
morphoVaultContract.read.decimals(),
|
|
83
80
|
morphoVaultContract.read.DECIMALS_OFFSET(),
|
|
84
|
-
(0, graphql_request_1.request)(MORPHO_BLUE_API, vaultDataQuery
|
|
81
|
+
(0, graphql_request_1.request)(MORPHO_BLUE_API, vaultDataQuery, { address: morphoVault.address, chainId: network }),
|
|
85
82
|
...accounts.map((account) => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
83
|
const share = yield morphoVaultContract.read.balanceOf([account]);
|
|
87
84
|
shares[account] = share;
|
package/cjs/types/aaveV4.d.ts
CHANGED
|
@@ -100,16 +100,6 @@ export interface AaveV4ReserveAssetData {
|
|
|
100
100
|
borrowRate: string;
|
|
101
101
|
supplyIncentives: IncentiveData[];
|
|
102
102
|
borrowIncentives: IncentiveData[];
|
|
103
|
-
/**
|
|
104
|
-
* Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
|
|
105
|
-
* - spoke* → spoke supply/borrow (Create page + dashboard market table)
|
|
106
|
-
* - hub* → hub supply/borrow (Lend page)
|
|
107
|
-
* `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
|
|
108
|
-
*/
|
|
109
|
-
spokeSupplyIncentives?: IncentiveData[];
|
|
110
|
-
spokeBorrowIncentives?: IncentiveData[];
|
|
111
|
-
hubSupplyIncentives?: IncentiveData[];
|
|
112
|
-
hubBorrowIncentives?: IncentiveData[];
|
|
113
103
|
canBeBorrowed: boolean;
|
|
114
104
|
canBeSupplied: boolean;
|
|
115
105
|
canBeWithdrawn: boolean;
|
package/cjs/types/merkl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EthAddress
|
|
1
|
+
import { EthAddress } from './common';
|
|
2
2
|
export declare enum OpportunityAction {
|
|
3
3
|
LEND = "LEND",
|
|
4
4
|
BORROW = "BORROW"
|
|
@@ -73,16 +73,3 @@ export type MerkleRewardMap = Record<EthAddress, {
|
|
|
73
73
|
supply?: MerkleRewardInfo;
|
|
74
74
|
borrow?: MerkleRewardInfo;
|
|
75
75
|
}>;
|
|
76
|
-
export type AaveV4MerklScopedReward = {
|
|
77
|
-
supply?: IncentiveData;
|
|
78
|
-
borrow?: IncentiveData;
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Aave V4 Merkl reward campaigns split by scope:
|
|
82
|
-
* - `hub`: keyed by underlying token address (lowercase) — rewards for supplying to a hub
|
|
83
|
-
* - `spoke`: keyed by `${spokeAddress}_${underlyingAddress}` (both lowercase) — rewards for supplying/borrowing on a spoke
|
|
84
|
-
*/
|
|
85
|
-
export type AaveV4MerklRewardMap = {
|
|
86
|
-
hub: Record<string, AaveV4MerklScopedReward>;
|
|
87
|
-
spoke: Record<string, AaveV4MerklScopedReward>;
|
|
88
|
-
};
|
package/esm/aaveV4/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { Client } from 'viem';
|
|
2
2
|
import { AaveV4AccountData, AaveV4SpokeData, AaveV4SpokeInfo, EthAddress, EthereumProvider, NetworkNumber } from '../types';
|
|
3
3
|
export * as lend from './lend';
|
|
4
|
-
export { getAaveV4MerkleCampaigns } from './merkl';
|
|
5
4
|
export declare function _getAaveV4SpokeData(provider: Client, network: NetworkNumber, market: AaveV4SpokeInfo, blockNumber?: 'latest' | number): Promise<AaveV4SpokeData>;
|
|
6
5
|
export declare function getAaveV4SpokeData(provider: EthereumProvider, network: NetworkNumber, spoke: AaveV4SpokeInfo, blockNumber?: 'latest' | number): Promise<AaveV4SpokeData>;
|
|
7
6
|
export declare function _getAaveV4AccountData(provider: Client, network: NetworkNumber, spokeData: AaveV4SpokeData, address: EthAddress, blockNumber?: 'latest' | number): Promise<AaveV4AccountData>;
|
package/esm/aaveV4/index.js
CHANGED
|
@@ -17,9 +17,7 @@ import { isMaxUint, wethToEth } from '../services/utils';
|
|
|
17
17
|
import { aaveV4GetAggregatedPositionData, calcUserRiskPremiumBps } from '../helpers/aaveV4Helpers';
|
|
18
18
|
import { getAaveV4HubByAddress } from '../markets/aaveV4';
|
|
19
19
|
import { aprToApy } from '../moneymarket';
|
|
20
|
-
import { attachAaveV4MerklIncentives, getAaveV4MerkleCampaigns } from './merkl';
|
|
21
20
|
export * as lend from './lend';
|
|
22
|
-
export { getAaveV4MerkleCampaigns } from './merkl';
|
|
23
21
|
const fetchHubData = (viewContract, hubAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
24
22
|
const hubData = yield viewContract.read.getHubAllAssetsData([hubAddress]);
|
|
25
23
|
return {
|
|
@@ -131,7 +129,6 @@ export function _getAaveV4SpokeData(provider_1, network_1, market_1) {
|
|
|
131
129
|
return __awaiter(this, arguments, void 0, function* (provider, network, market, blockNumber = 'latest') {
|
|
132
130
|
const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
|
|
133
131
|
const hubsData = {};
|
|
134
|
-
const merklCampaignsPromise = getAaveV4MerkleCampaigns(network);
|
|
135
132
|
const [spokeData] = yield Promise.all([
|
|
136
133
|
viewContract.read.getSpokeDataFull([market.address]),
|
|
137
134
|
...market.hubs.map((hubAddress) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -139,10 +136,8 @@ export function _getAaveV4SpokeData(provider_1, network_1, market_1) {
|
|
|
139
136
|
})),
|
|
140
137
|
]);
|
|
141
138
|
const reserveAssetsArray = yield Promise.all(spokeData[1].map((reserveAssetOnChain, index) => __awaiter(this, void 0, void 0, function* () { return formatReserveAsset(reserveAssetOnChain, hubsData[reserveAssetOnChain.hub].assets[reserveAssetOnChain.assetId], index, +spokeData[0].oracleDecimals.toString(), network); })));
|
|
142
|
-
const merklCampaigns = yield merklCampaignsPromise;
|
|
143
|
-
const enrichedAssets = reserveAssetsArray.map((asset) => attachAaveV4MerklIncentives(asset, market.address, merklCampaigns));
|
|
144
139
|
return {
|
|
145
|
-
assetsData:
|
|
140
|
+
assetsData: reserveAssetsArray.reduce((acc, reserveAsset) => {
|
|
146
141
|
acc[`${reserveAsset.symbol}-${reserveAsset.reserveId}`] = reserveAsset;
|
|
147
142
|
return acc;
|
|
148
143
|
}, {}),
|
|
@@ -14,25 +14,22 @@ import * as morphoVaultsOptions from './options';
|
|
|
14
14
|
import { getViemProvider } from '../../services/viem';
|
|
15
15
|
import { getMorphoVaultContractViem } from '../../contracts';
|
|
16
16
|
export { morphoVaultsOptions, };
|
|
17
|
-
const vaultDataQuery =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
asset {
|
|
31
|
-
priceUsd
|
|
17
|
+
const vaultDataQuery = `
|
|
18
|
+
query VaultByAddress($address: String!, $chainId: Int!) {
|
|
19
|
+
vaultByAddress(address: $address, chainId: $chainId) {
|
|
20
|
+
address
|
|
21
|
+
state {
|
|
22
|
+
totalAssets
|
|
23
|
+
totalAssetsUsd
|
|
24
|
+
totalSupply
|
|
25
|
+
}
|
|
26
|
+
liquidity {
|
|
27
|
+
underlying
|
|
28
|
+
usd
|
|
29
|
+
}
|
|
32
30
|
}
|
|
33
|
-
}
|
|
34
31
|
}`;
|
|
35
|
-
const MORPHO_BLUE_API = 'https://
|
|
32
|
+
const MORPHO_BLUE_API = 'https://api.morpho.org/graphql';
|
|
36
33
|
export const _getMorphoVaultData = (provider, network, morphoVault, accounts) => __awaiter(void 0, void 0, void 0, function* () {
|
|
37
34
|
const morphoVaultContract = getMorphoVaultContractViem(provider, morphoVault.address);
|
|
38
35
|
const shares = {};
|
|
@@ -41,7 +38,7 @@ export const _getMorphoVaultData = (provider, network, morphoVault, accounts) =>
|
|
|
41
38
|
morphoVaultContract.read.totalSupply(),
|
|
42
39
|
morphoVaultContract.read.decimals(),
|
|
43
40
|
morphoVaultContract.read.DECIMALS_OFFSET(),
|
|
44
|
-
graphqlRequest(MORPHO_BLUE_API, vaultDataQuery
|
|
41
|
+
graphqlRequest(MORPHO_BLUE_API, vaultDataQuery, { address: morphoVault.address, chainId: network }),
|
|
45
42
|
...accounts.map((account) => __awaiter(void 0, void 0, void 0, function* () {
|
|
46
43
|
const share = yield morphoVaultContract.read.balanceOf([account]);
|
|
47
44
|
shares[account] = share;
|
package/esm/types/aaveV4.d.ts
CHANGED
|
@@ -100,16 +100,6 @@ export interface AaveV4ReserveAssetData {
|
|
|
100
100
|
borrowRate: string;
|
|
101
101
|
supplyIncentives: IncentiveData[];
|
|
102
102
|
borrowIncentives: IncentiveData[];
|
|
103
|
-
/**
|
|
104
|
-
* Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
|
|
105
|
-
* - spoke* → spoke supply/borrow (Create page + dashboard market table)
|
|
106
|
-
* - hub* → hub supply/borrow (Lend page)
|
|
107
|
-
* `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
|
|
108
|
-
*/
|
|
109
|
-
spokeSupplyIncentives?: IncentiveData[];
|
|
110
|
-
spokeBorrowIncentives?: IncentiveData[];
|
|
111
|
-
hubSupplyIncentives?: IncentiveData[];
|
|
112
|
-
hubBorrowIncentives?: IncentiveData[];
|
|
113
103
|
canBeBorrowed: boolean;
|
|
114
104
|
canBeSupplied: boolean;
|
|
115
105
|
canBeWithdrawn: boolean;
|
package/esm/types/merkl.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EthAddress
|
|
1
|
+
import { EthAddress } from './common';
|
|
2
2
|
export declare enum OpportunityAction {
|
|
3
3
|
LEND = "LEND",
|
|
4
4
|
BORROW = "BORROW"
|
|
@@ -73,16 +73,3 @@ export type MerkleRewardMap = Record<EthAddress, {
|
|
|
73
73
|
supply?: MerkleRewardInfo;
|
|
74
74
|
borrow?: MerkleRewardInfo;
|
|
75
75
|
}>;
|
|
76
|
-
export type AaveV4MerklScopedReward = {
|
|
77
|
-
supply?: IncentiveData;
|
|
78
|
-
borrow?: IncentiveData;
|
|
79
|
-
};
|
|
80
|
-
/**
|
|
81
|
-
* Aave V4 Merkl reward campaigns split by scope:
|
|
82
|
-
* - `hub`: keyed by underlying token address (lowercase) — rewards for supplying to a hub
|
|
83
|
-
* - `spoke`: keyed by `${spokeAddress}_${underlyingAddress}` (both lowercase) — rewards for supplying/borrowing on a spoke
|
|
84
|
-
*/
|
|
85
|
-
export type AaveV4MerklRewardMap = {
|
|
86
|
-
hub: Record<string, AaveV4MerklScopedReward>;
|
|
87
|
-
spoke: Record<string, AaveV4MerklScopedReward>;
|
|
88
|
-
};
|
package/package.json
CHANGED
package/src/aaveV4/index.ts
CHANGED
|
@@ -23,10 +23,8 @@ import { isMaxUint, wethToEth } from '../services/utils';
|
|
|
23
23
|
import { aaveV4GetAggregatedPositionData, calcUserRiskPremiumBps } from '../helpers/aaveV4Helpers';
|
|
24
24
|
import { getAaveV4HubByAddress } from '../markets/aaveV4';
|
|
25
25
|
import { aprToApy } from '../moneymarket';
|
|
26
|
-
import { attachAaveV4MerklIncentives, getAaveV4MerkleCampaigns } from './merkl';
|
|
27
26
|
|
|
28
27
|
export * as lend from './lend';
|
|
29
|
-
export { getAaveV4MerkleCampaigns } from './merkl';
|
|
30
28
|
|
|
31
29
|
const fetchHubData = async (viewContract: ReturnType<typeof AaveV4ViewContractViem>, hubAddress: EthAddress): Promise<AaveV4HubOnChainData> => {
|
|
32
30
|
const hubData = await viewContract.read.getHubAllAssetsData([hubAddress]);
|
|
@@ -147,7 +145,6 @@ export async function _getAaveV4SpokeData(provider: Client, network: NetworkNumb
|
|
|
147
145
|
const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
|
|
148
146
|
|
|
149
147
|
const hubsData: Record<EthAddress, AaveV4HubOnChainData> = {};
|
|
150
|
-
const merklCampaignsPromise = getAaveV4MerkleCampaigns(network);
|
|
151
148
|
const [spokeData] = await Promise.all([
|
|
152
149
|
viewContract.read.getSpokeDataFull([market.address]),
|
|
153
150
|
...market.hubs.map(async (hubAddress) => {
|
|
@@ -157,11 +154,8 @@ export async function _getAaveV4SpokeData(provider: Client, network: NetworkNumb
|
|
|
157
154
|
|
|
158
155
|
const reserveAssetsArray = await Promise.all(spokeData[1].map(async (reserveAssetOnChain: AaveV4ReserveAssetOnChain, index: number) => formatReserveAsset(reserveAssetOnChain, hubsData[reserveAssetOnChain.hub].assets[reserveAssetOnChain.assetId], index, +spokeData[0].oracleDecimals.toString(), network)));
|
|
159
156
|
|
|
160
|
-
const merklCampaigns = await merklCampaignsPromise;
|
|
161
|
-
const enrichedAssets = reserveAssetsArray.map((asset) => attachAaveV4MerklIncentives(asset, market.address, merklCampaigns));
|
|
162
|
-
|
|
163
157
|
return {
|
|
164
|
-
assetsData:
|
|
158
|
+
assetsData: reserveAssetsArray.reduce((acc: Record<string, AaveV4ReserveAssetData>, reserveAsset: AaveV4ReserveAssetData) => {
|
|
165
159
|
acc[`${reserveAsset.symbol}-${reserveAsset.reserveId}`] = reserveAsset;
|
|
166
160
|
return acc;
|
|
167
161
|
}, {}),
|
|
@@ -12,26 +12,23 @@ export {
|
|
|
12
12
|
morphoVaultsOptions,
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
const vaultDataQuery =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
asset {
|
|
29
|
-
priceUsd
|
|
15
|
+
const vaultDataQuery = `
|
|
16
|
+
query VaultByAddress($address: String!, $chainId: Int!) {
|
|
17
|
+
vaultByAddress(address: $address, chainId: $chainId) {
|
|
18
|
+
address
|
|
19
|
+
state {
|
|
20
|
+
totalAssets
|
|
21
|
+
totalAssetsUsd
|
|
22
|
+
totalSupply
|
|
23
|
+
}
|
|
24
|
+
liquidity {
|
|
25
|
+
underlying
|
|
26
|
+
usd
|
|
27
|
+
}
|
|
30
28
|
}
|
|
31
|
-
}
|
|
32
29
|
}`;
|
|
33
30
|
|
|
34
|
-
const MORPHO_BLUE_API = 'https://
|
|
31
|
+
const MORPHO_BLUE_API = 'https://api.morpho.org/graphql';
|
|
35
32
|
|
|
36
33
|
export const _getMorphoVaultData = async (provider: Client, network: NetworkNumber, morphoVault: MorphoVault, accounts: EthAddress[]): Promise<SavingsVaultData> => {
|
|
37
34
|
const morphoVaultContract = getMorphoVaultContractViem(provider, morphoVault.address);
|
|
@@ -43,7 +40,7 @@ export const _getMorphoVaultData = async (provider: Client, network: NetworkNumb
|
|
|
43
40
|
morphoVaultContract.read.totalSupply(),
|
|
44
41
|
morphoVaultContract.read.decimals(),
|
|
45
42
|
morphoVaultContract.read.DECIMALS_OFFSET(),
|
|
46
|
-
graphqlRequest(MORPHO_BLUE_API, vaultDataQuery
|
|
43
|
+
graphqlRequest(MORPHO_BLUE_API, vaultDataQuery, { address: morphoVault.address, chainId: network }),
|
|
47
44
|
...accounts.map(async (account) => {
|
|
48
45
|
const share = await morphoVaultContract.read.balanceOf([account]);
|
|
49
46
|
shares[account] = share;
|
package/src/types/aaveV4.ts
CHANGED
|
@@ -111,16 +111,6 @@ export interface AaveV4ReserveAssetData {
|
|
|
111
111
|
borrowRate: string,
|
|
112
112
|
supplyIncentives: IncentiveData[];
|
|
113
113
|
borrowIncentives: IncentiveData[];
|
|
114
|
-
/**
|
|
115
|
-
* Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
|
|
116
|
-
* - spoke* → spoke supply/borrow (Create page + dashboard market table)
|
|
117
|
-
* - hub* → hub supply/borrow (Lend page)
|
|
118
|
-
* `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
|
|
119
|
-
*/
|
|
120
|
-
spokeSupplyIncentives?: IncentiveData[];
|
|
121
|
-
spokeBorrowIncentives?: IncentiveData[];
|
|
122
|
-
hubSupplyIncentives?: IncentiveData[];
|
|
123
|
-
hubBorrowIncentives?: IncentiveData[];
|
|
124
114
|
canBeBorrowed: boolean;
|
|
125
115
|
canBeSupplied: boolean;
|
|
126
116
|
canBeWithdrawn: boolean;
|
package/src/types/merkl.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EthAddress
|
|
1
|
+
import { EthAddress } from './common';
|
|
2
2
|
|
|
3
3
|
export enum OpportunityAction {
|
|
4
4
|
LEND = 'LEND',
|
|
@@ -68,16 +68,4 @@ export type MerklOpportunity = {
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
export type MerkleRewardInfo = { apy: string; rewardTokenSymbol: string, description: string, identifier: string };
|
|
71
|
-
export type MerkleRewardMap = Record<EthAddress, { supply?: MerkleRewardInfo; borrow?: MerkleRewardInfo }>;
|
|
72
|
-
|
|
73
|
-
export type AaveV4MerklScopedReward = { supply?: IncentiveData; borrow?: IncentiveData };
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Aave V4 Merkl reward campaigns split by scope:
|
|
77
|
-
* - `hub`: keyed by underlying token address (lowercase) — rewards for supplying to a hub
|
|
78
|
-
* - `spoke`: keyed by `${spokeAddress}_${underlyingAddress}` (both lowercase) — rewards for supplying/borrowing on a spoke
|
|
79
|
-
*/
|
|
80
|
-
export type AaveV4MerklRewardMap = {
|
|
81
|
-
hub: Record<string, AaveV4MerklScopedReward>;
|
|
82
|
-
spoke: Record<string, AaveV4MerklScopedReward>;
|
|
83
|
-
};
|
|
71
|
+
export type MerkleRewardMap = Record<EthAddress, { supply?: MerkleRewardInfo; borrow?: MerkleRewardInfo }>;
|
package/cjs/aaveV4/merkl.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { AaveV4MerklRewardMap, AaveV4ReserveAssetData } from '../types';
|
|
2
|
-
import { NetworkNumber } from '../types/common';
|
|
3
|
-
export declare const getAaveV4MerkleCampaigns: (chainId: NetworkNumber) => Promise<AaveV4MerklRewardMap>;
|
|
4
|
-
/**
|
|
5
|
-
* Returns a copy of the asset with scope-specific incentive arrays pre-combined with the asset's
|
|
6
|
-
* intrinsic (staking) incentives, so each surface can render base yield + the rewards that apply to it.
|
|
7
|
-
*/
|
|
8
|
-
export declare const attachAaveV4MerklIncentives: (asset: AaveV4ReserveAssetData, spokeAddress: string, campaigns: AaveV4MerklRewardMap) => AaveV4ReserveAssetData;
|
package/cjs/aaveV4/merkl.js
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.attachAaveV4MerklIncentives = exports.getAaveV4MerkleCampaigns = void 0;
|
|
13
|
-
const moneymarket_1 = require("../moneymarket");
|
|
14
|
-
const utils_1 = require("../services/utils");
|
|
15
|
-
const types_1 = require("../types");
|
|
16
|
-
/**
|
|
17
|
-
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
18
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW → reward tied to a hub (matched per underlying token)
|
|
19
|
-
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke (matched per spoke contract + underlying)
|
|
20
|
-
* Hub campaigns identify the underlying via `tokens[0]`; spoke campaigns identify the spoke via `explorerAddress`.
|
|
21
|
-
*/
|
|
22
|
-
const spokeKey = (spokeAddress, underlying) => `${spokeAddress.toLowerCase()}_${underlying.toLowerCase()}`;
|
|
23
|
-
const buildIncentive = (opportunity) => {
|
|
24
|
-
var _a, _b, _c, _d, _e;
|
|
25
|
-
const rewardToken = (_c = (_b = (_a = opportunity.rewardsRecord) === null || _a === void 0 ? void 0 : _a.breakdowns) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.token;
|
|
26
|
-
const token = (rewardToken === null || rewardToken === void 0 ? void 0 : rewardToken.symbol) || ((_e = (_d = opportunity.tokens) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.symbol) || '';
|
|
27
|
-
return {
|
|
28
|
-
apy: (0, moneymarket_1.aprToApy)(opportunity.apr),
|
|
29
|
-
token,
|
|
30
|
-
incentiveKind: types_1.IncentiveKind.Reward,
|
|
31
|
-
description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
35
|
-
const result = { hub: {}, spoke: {} };
|
|
36
|
-
try {
|
|
37
|
-
const res = yield fetch('https://api-merkl.angle.money/v4/opportunities?mainProtocolId=aave', {
|
|
38
|
-
signal: AbortSignal.timeout(utils_1.DEFAULT_TIMEOUT),
|
|
39
|
-
});
|
|
40
|
-
if (!res.ok)
|
|
41
|
-
throw new Error('Failed to fetch Aave V4 Merkle campaigns');
|
|
42
|
-
const opportunities = yield res.json();
|
|
43
|
-
opportunities
|
|
44
|
-
.filter((o) => o.chainId === chainId)
|
|
45
|
-
.filter((o) => o.status === types_1.OpportunityStatus.LIVE)
|
|
46
|
-
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
47
|
-
.forEach((o) => {
|
|
48
|
-
var _a, _b, _c, _d;
|
|
49
|
-
const underlying = (_c = (_b = (_a = o.tokens) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.address) === null || _c === void 0 ? void 0 : _c.toLowerCase();
|
|
50
|
-
if (!underlying)
|
|
51
|
-
return;
|
|
52
|
-
const side = o.action === types_1.OpportunityAction.BORROW ? 'borrow' : 'supply';
|
|
53
|
-
const incentive = buildIncentive(o);
|
|
54
|
-
if (o.type.includes('HUB')) {
|
|
55
|
-
if (!result.hub[underlying])
|
|
56
|
-
result.hub[underlying] = {};
|
|
57
|
-
result.hub[underlying][side] = incentive;
|
|
58
|
-
}
|
|
59
|
-
else if (o.type.includes('SPOKE')) {
|
|
60
|
-
const spokeAddress = (_d = o.explorerAddress) === null || _d === void 0 ? void 0 : _d.toLowerCase();
|
|
61
|
-
if (!spokeAddress)
|
|
62
|
-
return;
|
|
63
|
-
const key = spokeKey(spokeAddress, underlying);
|
|
64
|
-
if (!result.spoke[key])
|
|
65
|
-
result.spoke[key] = {};
|
|
66
|
-
result.spoke[key][side] = incentive;
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
catch (e) {
|
|
72
|
-
console.error('Failed to fetch Aave V4 Merkle campaigns', e);
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
exports.getAaveV4MerkleCampaigns = getAaveV4MerkleCampaigns;
|
|
77
|
-
/**
|
|
78
|
-
* Returns a copy of the asset with scope-specific incentive arrays pre-combined with the asset's
|
|
79
|
-
* intrinsic (staking) incentives, so each surface can render base yield + the rewards that apply to it.
|
|
80
|
-
*/
|
|
81
|
-
const attachAaveV4MerklIncentives = (asset, spokeAddress, campaigns) => {
|
|
82
|
-
var _a;
|
|
83
|
-
const underlying = (_a = asset.underlying) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
84
|
-
const baseSupply = asset.supplyIncentives || [];
|
|
85
|
-
const baseBorrow = asset.borrowIncentives || [];
|
|
86
|
-
const spokeScoped = (spokeAddress && underlying) ? campaigns.spoke[spokeKey(spokeAddress, underlying)] : undefined;
|
|
87
|
-
const hubScoped = underlying ? campaigns.hub[underlying] : undefined;
|
|
88
|
-
return Object.assign(Object.assign({}, asset), { spokeSupplyIncentives: (spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.supply) ? [...baseSupply, spokeScoped.supply] : baseSupply, spokeBorrowIncentives: (spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.borrow) ? [...baseBorrow, spokeScoped.borrow] : baseBorrow, hubSupplyIncentives: (hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.supply) ? [...baseSupply, hubScoped.supply] : baseSupply, hubBorrowIncentives: (hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.borrow) ? [...baseBorrow, hubScoped.borrow] : baseBorrow });
|
|
89
|
-
};
|
|
90
|
-
exports.attachAaveV4MerklIncentives = attachAaveV4MerklIncentives;
|
package/esm/aaveV4/merkl.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { AaveV4MerklRewardMap, AaveV4ReserveAssetData } from '../types';
|
|
2
|
-
import { NetworkNumber } from '../types/common';
|
|
3
|
-
export declare const getAaveV4MerkleCampaigns: (chainId: NetworkNumber) => Promise<AaveV4MerklRewardMap>;
|
|
4
|
-
/**
|
|
5
|
-
* Returns a copy of the asset with scope-specific incentive arrays pre-combined with the asset's
|
|
6
|
-
* intrinsic (staking) incentives, so each surface can render base yield + the rewards that apply to it.
|
|
7
|
-
*/
|
|
8
|
-
export declare const attachAaveV4MerklIncentives: (asset: AaveV4ReserveAssetData, spokeAddress: string, campaigns: AaveV4MerklRewardMap) => AaveV4ReserveAssetData;
|
package/esm/aaveV4/merkl.js
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { aprToApy } from '../moneymarket';
|
|
11
|
-
import { DEFAULT_TIMEOUT } from '../services/utils';
|
|
12
|
-
import { IncentiveKind, OpportunityAction, OpportunityStatus, } from '../types';
|
|
13
|
-
/**
|
|
14
|
-
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
15
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW → reward tied to a hub (matched per underlying token)
|
|
16
|
-
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke (matched per spoke contract + underlying)
|
|
17
|
-
* Hub campaigns identify the underlying via `tokens[0]`; spoke campaigns identify the spoke via `explorerAddress`.
|
|
18
|
-
*/
|
|
19
|
-
const spokeKey = (spokeAddress, underlying) => `${spokeAddress.toLowerCase()}_${underlying.toLowerCase()}`;
|
|
20
|
-
const buildIncentive = (opportunity) => {
|
|
21
|
-
var _a, _b, _c, _d, _e;
|
|
22
|
-
const rewardToken = (_c = (_b = (_a = opportunity.rewardsRecord) === null || _a === void 0 ? void 0 : _a.breakdowns) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.token;
|
|
23
|
-
const token = (rewardToken === null || rewardToken === void 0 ? void 0 : rewardToken.symbol) || ((_e = (_d = opportunity.tokens) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.symbol) || '';
|
|
24
|
-
return {
|
|
25
|
-
apy: aprToApy(opportunity.apr),
|
|
26
|
-
token,
|
|
27
|
-
incentiveKind: IncentiveKind.Reward,
|
|
28
|
-
description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
export const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
-
const result = { hub: {}, spoke: {} };
|
|
33
|
-
try {
|
|
34
|
-
const res = yield fetch('https://api-merkl.angle.money/v4/opportunities?mainProtocolId=aave', {
|
|
35
|
-
signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
|
|
36
|
-
});
|
|
37
|
-
if (!res.ok)
|
|
38
|
-
throw new Error('Failed to fetch Aave V4 Merkle campaigns');
|
|
39
|
-
const opportunities = yield res.json();
|
|
40
|
-
opportunities
|
|
41
|
-
.filter((o) => o.chainId === chainId)
|
|
42
|
-
.filter((o) => o.status === OpportunityStatus.LIVE)
|
|
43
|
-
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
44
|
-
.forEach((o) => {
|
|
45
|
-
var _a, _b, _c, _d;
|
|
46
|
-
const underlying = (_c = (_b = (_a = o.tokens) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.address) === null || _c === void 0 ? void 0 : _c.toLowerCase();
|
|
47
|
-
if (!underlying)
|
|
48
|
-
return;
|
|
49
|
-
const side = o.action === OpportunityAction.BORROW ? 'borrow' : 'supply';
|
|
50
|
-
const incentive = buildIncentive(o);
|
|
51
|
-
if (o.type.includes('HUB')) {
|
|
52
|
-
if (!result.hub[underlying])
|
|
53
|
-
result.hub[underlying] = {};
|
|
54
|
-
result.hub[underlying][side] = incentive;
|
|
55
|
-
}
|
|
56
|
-
else if (o.type.includes('SPOKE')) {
|
|
57
|
-
const spokeAddress = (_d = o.explorerAddress) === null || _d === void 0 ? void 0 : _d.toLowerCase();
|
|
58
|
-
if (!spokeAddress)
|
|
59
|
-
return;
|
|
60
|
-
const key = spokeKey(spokeAddress, underlying);
|
|
61
|
-
if (!result.spoke[key])
|
|
62
|
-
result.spoke[key] = {};
|
|
63
|
-
result.spoke[key][side] = incentive;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
return result;
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
console.error('Failed to fetch Aave V4 Merkle campaigns', e);
|
|
70
|
-
return result;
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
/**
|
|
74
|
-
* Returns a copy of the asset with scope-specific incentive arrays pre-combined with the asset's
|
|
75
|
-
* intrinsic (staking) incentives, so each surface can render base yield + the rewards that apply to it.
|
|
76
|
-
*/
|
|
77
|
-
export const attachAaveV4MerklIncentives = (asset, spokeAddress, campaigns) => {
|
|
78
|
-
var _a;
|
|
79
|
-
const underlying = (_a = asset.underlying) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
80
|
-
const baseSupply = asset.supplyIncentives || [];
|
|
81
|
-
const baseBorrow = asset.borrowIncentives || [];
|
|
82
|
-
const spokeScoped = (spokeAddress && underlying) ? campaigns.spoke[spokeKey(spokeAddress, underlying)] : undefined;
|
|
83
|
-
const hubScoped = underlying ? campaigns.hub[underlying] : undefined;
|
|
84
|
-
return Object.assign(Object.assign({}, asset), { spokeSupplyIncentives: (spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.supply) ? [...baseSupply, spokeScoped.supply] : baseSupply, spokeBorrowIncentives: (spokeScoped === null || spokeScoped === void 0 ? void 0 : spokeScoped.borrow) ? [...baseBorrow, spokeScoped.borrow] : baseBorrow, hubSupplyIncentives: (hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.supply) ? [...baseSupply, hubScoped.supply] : baseSupply, hubBorrowIncentives: (hubScoped === null || hubScoped === void 0 ? void 0 : hubScoped.borrow) ? [...baseBorrow, hubScoped.borrow] : baseBorrow });
|
|
85
|
-
};
|
package/src/aaveV4/merkl.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import { aprToApy } from '../moneymarket';
|
|
2
|
-
import { DEFAULT_TIMEOUT } from '../services/utils';
|
|
3
|
-
import {
|
|
4
|
-
AaveV4MerklRewardMap,
|
|
5
|
-
AaveV4ReserveAssetData,
|
|
6
|
-
IncentiveData,
|
|
7
|
-
IncentiveKind,
|
|
8
|
-
MerklOpportunity,
|
|
9
|
-
OpportunityAction,
|
|
10
|
-
OpportunityStatus,
|
|
11
|
-
} from '../types';
|
|
12
|
-
import { NetworkNumber } from '../types/common';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
16
|
-
* - AAVE_V4_HUB_SUPPLY / AAVE_V4_HUB_BORROW → reward tied to a hub (matched per underlying token)
|
|
17
|
-
* - AAVE_V4_SPOKE_SUPPLY / AAVE_V4_SPOKE_BORROW → reward tied to a spoke (matched per spoke contract + underlying)
|
|
18
|
-
* Hub campaigns identify the underlying via `tokens[0]`; spoke campaigns identify the spoke via `explorerAddress`.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
const spokeKey = (spokeAddress: string, underlying: string) => `${spokeAddress.toLowerCase()}_${underlying.toLowerCase()}`;
|
|
22
|
-
|
|
23
|
-
const buildIncentive = (opportunity: MerklOpportunity): IncentiveData => {
|
|
24
|
-
const rewardToken = opportunity.rewardsRecord?.breakdowns?.[0]?.token;
|
|
25
|
-
const token = rewardToken?.symbol || opportunity.tokens?.[0]?.symbol || '';
|
|
26
|
-
return {
|
|
27
|
-
apy: aprToApy(opportunity.apr),
|
|
28
|
-
token,
|
|
29
|
-
incentiveKind: IncentiveKind.Reward,
|
|
30
|
-
description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export const getAaveV4MerkleCampaigns = async (chainId: NetworkNumber): Promise<AaveV4MerklRewardMap> => {
|
|
35
|
-
const result: AaveV4MerklRewardMap = { hub: {}, spoke: {} };
|
|
36
|
-
try {
|
|
37
|
-
const res = await fetch('https://api-merkl.angle.money/v4/opportunities?mainProtocolId=aave', {
|
|
38
|
-
signal: AbortSignal.timeout(DEFAULT_TIMEOUT),
|
|
39
|
-
});
|
|
40
|
-
if (!res.ok) throw new Error('Failed to fetch Aave V4 Merkle campaigns');
|
|
41
|
-
const opportunities = await res.json() as MerklOpportunity[];
|
|
42
|
-
|
|
43
|
-
opportunities
|
|
44
|
-
.filter((o) => o.chainId === chainId)
|
|
45
|
-
.filter((o) => o.status === OpportunityStatus.LIVE)
|
|
46
|
-
.filter((o) => typeof o.type === 'string' && o.type.startsWith('AAVE_V4_'))
|
|
47
|
-
.forEach((o) => {
|
|
48
|
-
const underlying = o.tokens?.[0]?.address?.toLowerCase();
|
|
49
|
-
if (!underlying) return;
|
|
50
|
-
|
|
51
|
-
const side: 'supply' | 'borrow' = o.action === OpportunityAction.BORROW ? 'borrow' : 'supply';
|
|
52
|
-
const incentive = buildIncentive(o);
|
|
53
|
-
|
|
54
|
-
if (o.type.includes('HUB')) {
|
|
55
|
-
if (!result.hub[underlying]) result.hub[underlying] = {};
|
|
56
|
-
result.hub[underlying][side] = incentive;
|
|
57
|
-
} else if (o.type.includes('SPOKE')) {
|
|
58
|
-
const spokeAddress = o.explorerAddress?.toLowerCase();
|
|
59
|
-
if (!spokeAddress) return;
|
|
60
|
-
const key = spokeKey(spokeAddress, underlying);
|
|
61
|
-
if (!result.spoke[key]) result.spoke[key] = {};
|
|
62
|
-
result.spoke[key][side] = incentive;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return result;
|
|
67
|
-
} catch (e) {
|
|
68
|
-
console.error('Failed to fetch Aave V4 Merkle campaigns', e);
|
|
69
|
-
return result;
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Returns a copy of the asset with scope-specific incentive arrays pre-combined with the asset's
|
|
75
|
-
* intrinsic (staking) incentives, so each surface can render base yield + the rewards that apply to it.
|
|
76
|
-
*/
|
|
77
|
-
export const attachAaveV4MerklIncentives = (asset: AaveV4ReserveAssetData, spokeAddress: string, campaigns: AaveV4MerklRewardMap): AaveV4ReserveAssetData => {
|
|
78
|
-
const underlying = asset.underlying?.toLowerCase();
|
|
79
|
-
const baseSupply = asset.supplyIncentives || [];
|
|
80
|
-
const baseBorrow = asset.borrowIncentives || [];
|
|
81
|
-
|
|
82
|
-
const spokeScoped = (spokeAddress && underlying) ? campaigns.spoke[spokeKey(spokeAddress, underlying)] : undefined;
|
|
83
|
-
const hubScoped = underlying ? campaigns.hub[underlying] : undefined;
|
|
84
|
-
|
|
85
|
-
return {
|
|
86
|
-
...asset,
|
|
87
|
-
spokeSupplyIncentives: spokeScoped?.supply ? [...baseSupply, spokeScoped.supply] : baseSupply,
|
|
88
|
-
spokeBorrowIncentives: spokeScoped?.borrow ? [...baseBorrow, spokeScoped.borrow] : baseBorrow,
|
|
89
|
-
hubSupplyIncentives: hubScoped?.supply ? [...baseSupply, hubScoped.supply] : baseSupply,
|
|
90
|
-
hubBorrowIncentives: hubScoped?.borrow ? [...baseBorrow, hubScoped.borrow] : baseBorrow,
|
|
91
|
-
};
|
|
92
|
-
};
|