@defisaver/positions-sdk 2.1.127-midnight-13-dev → 2.1.127-midnight-15-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/aaveV3/merkl.js +10 -9
- package/cjs/aaveV4/merkl.js +5 -6
- package/cjs/claiming/aaveV3.d.ts +2 -1
- package/cjs/claiming/aaveV3.js +13 -4
- package/cjs/compoundV3/index.d.ts +1 -0
- package/cjs/compoundV3/index.js +8 -2
- package/cjs/compoundV3/merkl.d.ts +16 -0
- package/cjs/compoundV3/merkl.js +77 -0
- package/cjs/fluid/index.d.ts +9 -0
- package/cjs/fluid/index.js +36 -10
- package/cjs/fluid/merkl.d.ts +32 -0
- package/cjs/fluid/merkl.js +103 -0
- package/cjs/helpers/fluidHelpers/index.d.ts +3 -1
- package/cjs/helpers/fluidHelpers/index.js +37 -4
- package/cjs/helpers/liquityV2Helpers/index.d.ts +2 -1
- package/cjs/helpers/liquityV2Helpers/index.js +3 -2
- package/cjs/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
- package/cjs/helpers/morphoMidnightHelpers/headroom.js +52 -0
- package/cjs/helpers/morphoMidnightHelpers/index.d.ts +2 -1
- package/cjs/helpers/morphoMidnightHelpers/index.js +10 -6
- package/cjs/liquityV2/index.js +3 -4
- package/cjs/moneymarket/moneymarketCommonService.js +2 -0
- package/cjs/morphoBlue/index.d.ts +1 -0
- package/cjs/morphoBlue/index.js +16 -10
- package/cjs/morphoBlue/merkl.d.ts +35 -0
- package/cjs/morphoBlue/merkl.js +102 -0
- package/cjs/morphoMidnight/index.js +22 -25
- package/cjs/portfolio/index.js +5 -5
- package/cjs/services/merkl.d.ts +6 -0
- package/cjs/services/merkl.js +39 -0
- package/cjs/staking/eligibility.d.ts +4 -0
- package/cjs/staking/eligibility.js +11 -1
- package/cjs/types/claiming.d.ts +12 -1
- package/cjs/types/claiming.js +2 -0
- package/cjs/types/common.d.ts +6 -1
- package/cjs/types/common.js +6 -1
- package/cjs/types/fluid.d.ts +2 -0
- package/cjs/types/liquityV2.d.ts +3 -0
- package/cjs/types/merkl.d.ts +8 -0
- package/cjs/types/morphoMidnight.d.ts +1 -4
- package/cjs/types/morphoMidnight.js +0 -3
- package/esm/aaveV3/merkl.js +11 -10
- package/esm/aaveV4/merkl.js +5 -6
- package/esm/claiming/aaveV3.d.ts +2 -1
- package/esm/claiming/aaveV3.js +12 -4
- package/esm/compoundV3/index.d.ts +1 -0
- package/esm/compoundV3/index.js +5 -1
- package/esm/compoundV3/merkl.d.ts +16 -0
- package/esm/compoundV3/merkl.js +72 -0
- package/esm/fluid/index.d.ts +9 -0
- package/esm/fluid/index.js +31 -9
- package/esm/fluid/merkl.d.ts +32 -0
- package/esm/fluid/merkl.js +95 -0
- package/esm/helpers/fluidHelpers/index.d.ts +3 -1
- package/esm/helpers/fluidHelpers/index.js +38 -6
- package/esm/helpers/liquityV2Helpers/index.d.ts +2 -1
- package/esm/helpers/liquityV2Helpers/index.js +3 -2
- package/esm/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
- package/esm/helpers/morphoMidnightHelpers/headroom.js +45 -0
- package/esm/helpers/morphoMidnightHelpers/index.d.ts +2 -1
- package/esm/helpers/morphoMidnightHelpers/index.js +7 -4
- package/esm/liquityV2/index.js +3 -4
- package/esm/moneymarket/moneymarketCommonService.js +2 -0
- package/esm/morphoBlue/index.d.ts +1 -0
- package/esm/morphoBlue/index.js +11 -9
- package/esm/morphoBlue/merkl.d.ts +35 -0
- package/esm/morphoBlue/merkl.js +96 -0
- package/esm/morphoMidnight/index.js +23 -26
- package/esm/portfolio/index.js +6 -6
- package/esm/services/merkl.d.ts +6 -0
- package/esm/services/merkl.js +35 -0
- package/esm/staking/eligibility.d.ts +4 -0
- package/esm/staking/eligibility.js +9 -0
- package/esm/types/claiming.d.ts +12 -1
- package/esm/types/claiming.js +2 -0
- package/esm/types/common.d.ts +6 -1
- package/esm/types/common.js +5 -0
- package/esm/types/fluid.d.ts +2 -0
- package/esm/types/liquityV2.d.ts +3 -0
- package/esm/types/merkl.d.ts +8 -0
- package/esm/types/morphoMidnight.d.ts +1 -4
- package/esm/types/morphoMidnight.js +0 -3
- package/package.json +1 -1
- package/src/aaveV3/merkl.ts +7 -7
- package/src/aaveV4/merkl.ts +5 -5
- package/src/claiming/aaveV3.ts +19 -7
- package/src/compoundV3/index.ts +6 -1
- package/src/compoundV3/merkl.ts +76 -0
- package/src/fluid/index.ts +37 -9
- package/src/fluid/merkl.ts +102 -0
- package/src/helpers/fluidHelpers/index.ts +68 -6
- package/src/helpers/liquityV2Helpers/index.ts +4 -1
- package/src/helpers/morphoMidnightHelpers/headroom.ts +82 -0
- package/src/helpers/morphoMidnightHelpers/index.ts +11 -7
- package/src/liquityV2/index.ts +4 -3
- package/src/moneymarket/moneymarketCommonService.ts +2 -0
- package/src/morphoBlue/index.ts +24 -9
- package/src/morphoBlue/merkl.ts +121 -0
- package/src/morphoMidnight/index.ts +25 -27
- package/src/portfolio/index.ts +6 -6
- package/src/services/merkl.ts +31 -0
- package/src/staking/eligibility.ts +10 -0
- package/src/types/claiming.ts +13 -0
- package/src/types/common.ts +6 -0
- package/src/types/fluid.ts +3 -1
- package/src/types/liquityV2.ts +3 -0
- package/src/types/merkl.ts +6 -0
- package/src/types/morphoMidnight.ts +0 -3
package/cjs/aaveV3/merkl.js
CHANGED
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.getMerkleCampaigns = exports.formatAaveAsset = exports.getAaveUnderlyingSymbol = void 0;
|
|
13
13
|
const moneymarket_1 = require("../moneymarket");
|
|
14
|
+
const merkl_1 = require("../services/merkl");
|
|
14
15
|
const utils_1 = require("../services/utils");
|
|
15
16
|
const types_1 = require("../types");
|
|
16
17
|
const getAaveUnderlyingSymbol = (_symbol = '') => {
|
|
@@ -40,21 +41,21 @@ const formatAaveAsset = (_symbol) => {
|
|
|
40
41
|
exports.formatAaveAsset = formatAaveAsset;
|
|
41
42
|
const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
42
43
|
try {
|
|
43
|
-
const
|
|
44
|
-
|
|
44
|
+
const opportunities = yield (0, merkl_1.fetchAllMerklOpportunities)({
|
|
45
|
+
mainProtocolId: 'aave',
|
|
46
|
+
status: types_1.OpportunityStatus.LIVE,
|
|
45
47
|
});
|
|
46
|
-
if (!res.ok)
|
|
47
|
-
throw new Error('Failed to fetch Merkle campaigns');
|
|
48
|
-
const opportunities = yield res.json();
|
|
49
48
|
const relevantOpportunities = opportunities
|
|
50
49
|
.filter((o) => o.chainId === chainId)
|
|
51
50
|
.filter((o) => o.status === types_1.OpportunityStatus.LIVE);
|
|
52
51
|
return relevantOpportunities.reduce((acc, opportunity) => {
|
|
53
|
-
var _a, _b;
|
|
54
|
-
const rewardToken = opportunity.rewardsRecord.breakdowns[0].token;
|
|
52
|
+
var _a, _b, _c, _d, _e;
|
|
53
|
+
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;
|
|
54
|
+
if (!rewardToken)
|
|
55
|
+
return acc;
|
|
55
56
|
const description = `Eligible for ${(0, exports.formatAaveAsset)(rewardToken.symbol)} rewards through Merkl. ${opportunity.description ? `\n${opportunity.description}` : ''}`;
|
|
56
57
|
if (opportunity.action === types_1.OpportunityAction.LEND && opportunity.explorerAddress) {
|
|
57
|
-
const supplyAToken = (
|
|
58
|
+
const supplyAToken = (_d = opportunity.explorerAddress) === null || _d === void 0 ? void 0 : _d.toLowerCase();
|
|
58
59
|
if (!acc[supplyAToken])
|
|
59
60
|
acc[supplyAToken] = {};
|
|
60
61
|
acc[supplyAToken].supply = {
|
|
@@ -66,7 +67,7 @@ const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, functi
|
|
|
66
67
|
};
|
|
67
68
|
}
|
|
68
69
|
if (opportunity.action === types_1.OpportunityAction.BORROW && opportunity.explorerAddress) {
|
|
69
|
-
const borrowAToken = (
|
|
70
|
+
const borrowAToken = (_e = opportunity.explorerAddress) === null || _e === void 0 ? void 0 : _e.toLowerCase();
|
|
70
71
|
if (!acc[borrowAToken])
|
|
71
72
|
acc[borrowAToken] = {};
|
|
72
73
|
acc[borrowAToken].borrow = {
|
package/cjs/aaveV4/merkl.js
CHANGED
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.attachAaveV4MerklIncentives = exports.getAaveV4MerkleCampaigns = exports.buildAaveV4MerklRewardMap = void 0;
|
|
13
13
|
const moneymarket_1 = require("../moneymarket");
|
|
14
|
-
const
|
|
14
|
+
const merkl_1 = require("../services/merkl");
|
|
15
15
|
const types_1 = require("../types");
|
|
16
16
|
/**
|
|
17
17
|
* Merkl tags Aave V4 reward campaigns by scope via the `type` field:
|
|
@@ -67,12 +67,11 @@ const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
|
|
|
67
67
|
exports.buildAaveV4MerklRewardMap = buildAaveV4MerklRewardMap;
|
|
68
68
|
const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
69
|
try {
|
|
70
|
-
const
|
|
71
|
-
|
|
70
|
+
const opportunities = yield (0, merkl_1.fetchAllMerklOpportunities)({
|
|
71
|
+
mainProtocolId: 'aave',
|
|
72
|
+
type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
|
|
73
|
+
status: types_1.OpportunityStatus.LIVE,
|
|
72
74
|
});
|
|
73
|
-
if (!res.ok)
|
|
74
|
-
throw new Error('Failed to fetch Aave V4 Merkle campaigns');
|
|
75
|
-
const opportunities = yield res.json();
|
|
76
75
|
return (0, exports.buildAaveV4MerklRewardMap)(opportunities, chainId);
|
|
77
76
|
}
|
|
78
77
|
catch (e) {
|
package/cjs/claiming/aaveV3.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Client } from 'viem';
|
|
2
2
|
import { EthAddress, NetworkNumber } from '../types';
|
|
3
|
-
import { ClaimableToken } from '../types/claiming';
|
|
3
|
+
import { ClaimableToken, MerklRewardsClaimableToken } from '../types/claiming';
|
|
4
4
|
export declare function getUnclaimedRewardsForAllMarkets(provider: Client, network: NetworkNumber, walletAddress: EthAddress, marketAddress: EthAddress): Promise<ClaimableToken[]>;
|
|
5
|
+
export declare function getMerklUnclaimedRewards(account: EthAddress, network: NetworkNumber): Promise<MerklRewardsClaimableToken[]>;
|
|
5
6
|
export declare function getMeritUnclaimedRewards(account: EthAddress, network: NetworkNumber): Promise<ClaimableToken[]>;
|
package/cjs/claiming/aaveV3.js
CHANGED
|
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.getUnclaimedRewardsForAllMarkets = getUnclaimedRewardsForAllMarkets;
|
|
16
|
+
exports.getMerklUnclaimedRewards = getMerklUnclaimedRewards;
|
|
16
17
|
exports.getMeritUnclaimedRewards = getMeritUnclaimedRewards;
|
|
17
18
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
18
19
|
const claiming_1 = require("../types/claiming");
|
|
@@ -95,7 +96,7 @@ function getUnclaimedRewardsForAllMarkets(provider, network, walletAddress, mark
|
|
|
95
96
|
return mapAaveRewardsToClaimableTokens(Object.values(totalUnclaimedPerRewardToken), marketAddress, walletAddress);
|
|
96
97
|
});
|
|
97
98
|
}
|
|
98
|
-
function
|
|
99
|
+
function getMerklUnclaimedRewards(account, network) {
|
|
99
100
|
return __awaiter(this, void 0, void 0, function* () {
|
|
100
101
|
let data;
|
|
101
102
|
try {
|
|
@@ -103,7 +104,7 @@ function getMeritUnclaimedRewards(account, network) {
|
|
|
103
104
|
data = yield res.json();
|
|
104
105
|
}
|
|
105
106
|
catch (error) {
|
|
106
|
-
console.error('External API Failure:
|
|
107
|
+
console.error('External API Failure: Merkl rewards', error);
|
|
107
108
|
data = [];
|
|
108
109
|
}
|
|
109
110
|
const claimableTokens = [];
|
|
@@ -121,12 +122,12 @@ function getMeritUnclaimedRewards(account, network) {
|
|
|
121
122
|
return;
|
|
122
123
|
const unclaimed = (0, utils_1.getEthAmountForDecimals)(unclaimedAmount, token.decimals);
|
|
123
124
|
claimableTokens.push({
|
|
124
|
-
claimType: claiming_1.ClaimType.
|
|
125
|
+
claimType: claiming_1.ClaimType.MERKL_REWARDS,
|
|
125
126
|
amount: unclaimed,
|
|
126
127
|
symbol: token.symbol,
|
|
127
128
|
tokenAddress: token.address,
|
|
128
129
|
walletAddress: account,
|
|
129
|
-
label: '
|
|
130
|
+
label: 'Merkl Rewards',
|
|
130
131
|
underlyingSymbol: (0, aaveHelpers_1.getAaveUnderlyingSymbol)(token.symbol),
|
|
131
132
|
additionalClaimFields: {
|
|
132
133
|
accumulated: amount,
|
|
@@ -140,3 +141,11 @@ function getMeritUnclaimedRewards(account, network) {
|
|
|
140
141
|
return claimableTokens;
|
|
141
142
|
});
|
|
142
143
|
}
|
|
144
|
+
function getMeritUnclaimedRewards(account, network) {
|
|
145
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
146
|
+
const rewards = yield getMerklUnclaimedRewards(account, network);
|
|
147
|
+
return rewards
|
|
148
|
+
.filter(reward => reward.symbol.startsWith('a'))
|
|
149
|
+
.map(reward => (Object.assign(Object.assign({}, reward), { claimType: claiming_1.ClaimType.AAVE_MERIT_REWARDS, label: 'AAVE Merit Rewards' })));
|
|
150
|
+
});
|
|
151
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client } from 'viem';
|
|
2
2
|
import { CompoundMarketData, CompoundV3AssetsData, CompoundV3MarketsData, CompoundV3PositionData } from '../types';
|
|
3
3
|
import { Blockish, EthAddress, EthereumProvider, NetworkNumber, PositionBalances } from '../types/common';
|
|
4
|
+
export { getCompoundV3MerklOpportunities, attachCompoundV3MerklIncentives } from './merkl';
|
|
4
5
|
export declare const _getCompoundV3MarketsData: (provider: Client, network: NetworkNumber, selectedMarket: CompoundMarketData, defaultProvider: Client) => Promise<CompoundV3MarketsData>;
|
|
5
6
|
export declare const getCompoundV3MarketsData: (provider: EthereumProvider, network: NetworkNumber, selectedMarket: CompoundMarketData, defaultProvider: EthereumProvider) => Promise<CompoundV3MarketsData>;
|
|
6
7
|
export declare const EMPTY_COMPOUND_V3_DATA: {
|
package/cjs/compoundV3/index.js
CHANGED
|
@@ -12,7 +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
|
-
exports.getCompoundV3FullPositionData = exports.getCompoundV3AccountData = exports._getCompoundV3AccountData = exports.getCompoundV3AccountBalances = exports._getCompoundV3AccountBalances = exports.EMPTY_USED_ASSET = exports.EMPTY_COMPOUND_V3_DATA = exports.getCompoundV3MarketsData = exports._getCompoundV3MarketsData = void 0;
|
|
15
|
+
exports.getCompoundV3FullPositionData = exports.getCompoundV3AccountData = exports._getCompoundV3AccountData = exports.getCompoundV3AccountBalances = exports._getCompoundV3AccountBalances = exports.EMPTY_USED_ASSET = exports.EMPTY_COMPOUND_V3_DATA = exports.getCompoundV3MarketsData = exports._getCompoundV3MarketsData = exports.attachCompoundV3MerklIncentives = exports.getCompoundV3MerklOpportunities = void 0;
|
|
16
16
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
17
17
|
const tokens_1 = require("@defisaver/tokens");
|
|
18
18
|
const contracts_1 = require("../contracts");
|
|
@@ -25,6 +25,10 @@ const compoundHelpers_1 = require("../helpers/compoundHelpers");
|
|
|
25
25
|
const compound_1 = require("../markets/compound");
|
|
26
26
|
const priceService_1 = require("../services/priceService");
|
|
27
27
|
const viem_1 = require("../services/viem");
|
|
28
|
+
const merkl_1 = require("./merkl");
|
|
29
|
+
var merkl_2 = require("./merkl");
|
|
30
|
+
Object.defineProperty(exports, "getCompoundV3MerklOpportunities", { enumerable: true, get: function () { return merkl_2.getCompoundV3MerklOpportunities; } });
|
|
31
|
+
Object.defineProperty(exports, "attachCompoundV3MerklIncentives", { enumerable: true, get: function () { return merkl_2.attachCompoundV3MerklIncentives; } });
|
|
28
32
|
const getSupportedAssetsAddressesForMarket = (selectedMarket, network) => selectedMarket.collAssets.map(asset => (0, tokens_1.getAssetInfo)((0, utils_1.ethToWeth)(asset), network)).map(addr => addr.address.toLowerCase());
|
|
29
33
|
const getBaseAssetPriceFunction = (asset) => {
|
|
30
34
|
switch (asset) {
|
|
@@ -38,12 +42,13 @@ const getBaseAssetPriceFunction = (asset) => {
|
|
|
38
42
|
};
|
|
39
43
|
const _getCompoundV3MarketsData = (provider, network, selectedMarket, defaultProvider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
40
44
|
const contract = (0, contracts_1.CompV3ViewContractViem)(provider, network);
|
|
41
|
-
const [baseAssetPrice, compPrice, baseTokenInfo, collInfos, govInfo] = yield Promise.all([
|
|
45
|
+
const [baseAssetPrice, compPrice, baseTokenInfo, collInfos, govInfo, merklOpportunities] = yield Promise.all([
|
|
42
46
|
getBaseAssetPriceFunction(selectedMarket.baseAsset)(defaultProvider),
|
|
43
47
|
(0, priceService_1.getCompPrice)(defaultProvider),
|
|
44
48
|
contract.read.getFullBaseTokenInfo([selectedMarket.baseMarketAddress]),
|
|
45
49
|
contract.read.getFullCollInfos([selectedMarket.baseMarketAddress]),
|
|
46
50
|
contract.read.getGovernanceInfoFull([selectedMarket.baseMarketAddress]),
|
|
51
|
+
(0, merkl_1.getCompoundV3MerklOpportunities)(),
|
|
47
52
|
]);
|
|
48
53
|
const { isSupplyPaused, isWithdrawPaused } = govInfo;
|
|
49
54
|
const supportedAssetsAddresses = getSupportedAssetsAddressesForMarket(selectedMarket, network);
|
|
@@ -63,6 +68,7 @@ const _getCompoundV3MarketsData = (provider, network, selectedMarket, defaultPro
|
|
|
63
68
|
const base = (0, compoundHelpers_1.formatBaseData)(baseTokenInfo, network, baseAssetPrice, isSupplyPaused, isWithdrawPaused);
|
|
64
69
|
const payload = {};
|
|
65
70
|
const baseObj = Object.assign(Object.assign({}, base), (yield (0, compoundHelpers_1.getIncentiveApys)(base, compPrice)));
|
|
71
|
+
(0, merkl_1.attachCompoundV3MerklIncentives)(baseObj, colls, selectedMarket.baseMarketAddress, network, merklOpportunities);
|
|
66
72
|
const allAssets = [baseObj, ...colls];
|
|
67
73
|
allAssets
|
|
68
74
|
.sort((a, b) => {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { CompoundV3AssetData, MerklOpportunity, NetworkNumber } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Merkl tags Compound V3 reward campaigns with COMPOUND_V3_* opportunity types (e.g.
|
|
4
|
+
* COMPOUND_V3_BORROW_FROM_COLLATERAL) and identifies the comet via `explorerAddress`. Campaign
|
|
5
|
+
* identifiers are opaque hashes, passed through as `eligibilityId` so conditional campaigns —
|
|
6
|
+
* like borrow-from-collateral ones, whose reward is min(collateral * LTV, borrow amount) — can
|
|
7
|
+
* be gated and sized by a curated check in EligibilityMapping; unknown ids apply
|
|
8
|
+
* unconditionally, mirroring Aave V3.
|
|
9
|
+
*/
|
|
10
|
+
export declare const getCompoundV3MerklOpportunities: () => Promise<MerklOpportunity[]>;
|
|
11
|
+
/**
|
|
12
|
+
* Appends the comet's Merkl campaigns to its assets' incentive arrays (mutating them, like the
|
|
13
|
+
* staking incentives are attached). BORROW campaigns land on the base asset — the only borrowable
|
|
14
|
+
* one — while LEND campaigns land on the asset the campaign's first token resolves to.
|
|
15
|
+
*/
|
|
16
|
+
export declare const attachCompoundV3MerklIncentives: (baseAsset: CompoundV3AssetData, collAssets: CompoundV3AssetData[], baseMarketAddress: string, chainId: NetworkNumber, opportunities: MerklOpportunity[]) => void;
|
|
@@ -0,0 +1,77 @@
|
|
|
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.attachCompoundV3MerklIncentives = exports.getCompoundV3MerklOpportunities = void 0;
|
|
13
|
+
const tokens_1 = require("@defisaver/tokens");
|
|
14
|
+
const moneymarket_1 = require("../moneymarket");
|
|
15
|
+
const merkl_1 = require("../services/merkl");
|
|
16
|
+
const utils_1 = require("../services/utils");
|
|
17
|
+
const types_1 = require("../types");
|
|
18
|
+
/**
|
|
19
|
+
* Merkl tags Compound V3 reward campaigns with COMPOUND_V3_* opportunity types (e.g.
|
|
20
|
+
* COMPOUND_V3_BORROW_FROM_COLLATERAL) and identifies the comet via `explorerAddress`. Campaign
|
|
21
|
+
* identifiers are opaque hashes, passed through as `eligibilityId` so conditional campaigns —
|
|
22
|
+
* like borrow-from-collateral ones, whose reward is min(collateral * LTV, borrow amount) — can
|
|
23
|
+
* be gated and sized by a curated check in EligibilityMapping; unknown ids apply
|
|
24
|
+
* unconditionally, mirroring Aave V3.
|
|
25
|
+
*/
|
|
26
|
+
const getCompoundV3MerklOpportunities = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
try {
|
|
28
|
+
return yield (0, merkl_1.fetchAllMerklOpportunities)({
|
|
29
|
+
mainProtocolId: 'compound-v3',
|
|
30
|
+
status: types_1.OpportunityStatus.LIVE,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
console.error('Failed to fetch Compound V3 Merkl campaigns', e);
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
exports.getCompoundV3MerklOpportunities = getCompoundV3MerklOpportunities;
|
|
39
|
+
const buildMerklIncentive = (opportunity) => {
|
|
40
|
+
var _a, _b, _c, _d, _e, _f;
|
|
41
|
+
const token = ((_d = (_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) === null || _d === void 0 ? void 0 : _d.symbol) || ((_f = (_e = opportunity.tokens) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.symbol) || '';
|
|
42
|
+
return {
|
|
43
|
+
apy: (0, moneymarket_1.aprToApy)(opportunity.apr),
|
|
44
|
+
token,
|
|
45
|
+
incentiveKind: types_1.IncentiveKind.Reward,
|
|
46
|
+
description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
|
|
47
|
+
eligibilityId: opportunity.identifier,
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Appends the comet's Merkl campaigns to its assets' incentive arrays (mutating them, like the
|
|
52
|
+
* staking incentives are attached). BORROW campaigns land on the base asset — the only borrowable
|
|
53
|
+
* one — while LEND campaigns land on the asset the campaign's first token resolves to.
|
|
54
|
+
*/
|
|
55
|
+
const attachCompoundV3MerklIncentives = (baseAsset, collAssets, baseMarketAddress, chainId, opportunities) => {
|
|
56
|
+
opportunities
|
|
57
|
+
.filter((o) => o.chainId === chainId
|
|
58
|
+
&& o.status === types_1.OpportunityStatus.LIVE
|
|
59
|
+
&& typeof o.type === 'string' && o.type.startsWith('COMPOUND_V3')
|
|
60
|
+
&& o.explorerAddress && (0, utils_1.compareAddresses)(o.explorerAddress, baseMarketAddress))
|
|
61
|
+
.forEach((o) => {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const incentive = buildMerklIncentive(o);
|
|
64
|
+
if (o.action === types_1.OpportunityAction.BORROW) {
|
|
65
|
+
baseAsset.borrowIncentives.push(incentive);
|
|
66
|
+
}
|
|
67
|
+
else if (o.action === types_1.OpportunityAction.LEND) {
|
|
68
|
+
const campaignTokenAddress = (_b = (_a = o.tokens) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.address;
|
|
69
|
+
if (!campaignTokenAddress)
|
|
70
|
+
return;
|
|
71
|
+
const campaignSymbol = (0, utils_1.wethToEth)((0, tokens_1.getAssetInfoByAddress)(campaignTokenAddress, chainId).symbol);
|
|
72
|
+
const target = [baseAsset, ...collAssets].find((asset) => asset.symbol === campaignSymbol);
|
|
73
|
+
target === null || target === void 0 ? void 0 : target.supplyIncentives.push(incentive);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
};
|
|
77
|
+
exports.attachCompoundV3MerklIncentives = attachCompoundV3MerklIncentives;
|
package/cjs/fluid/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client, PublicClient } from 'viem';
|
|
2
2
|
import { EthAddress, EthereumProvider, NetworkNumber } from '../types/common';
|
|
3
3
|
import { FluidAssetsData, FluidMarketData, FluidMarketInfo, FluidUsedAssets, FluidVaultData, InnerFluidMarketData } from '../types';
|
|
4
|
+
export { FluidMerklOpportunityType, buildFluidMerklRewardMap, getFluidMerklCampaigns, attachFluidMerklIncentives, } from './merkl';
|
|
4
5
|
export declare const EMPTY_USED_ASSET: {
|
|
5
6
|
isSupplied: boolean;
|
|
6
7
|
isBorrowed: boolean;
|
|
@@ -21,6 +22,8 @@ export declare const EMPTY_FLUID_DATA: {
|
|
|
21
22
|
minRatio: string;
|
|
22
23
|
netApy: string;
|
|
23
24
|
incentiveUsd: string;
|
|
25
|
+
merklSupplyIncentives: never[];
|
|
26
|
+
merklBorrowIncentives: never[];
|
|
24
27
|
totalInterestUsd: string;
|
|
25
28
|
isSubscribedToAutomation: boolean;
|
|
26
29
|
automationResubscribeRequired: boolean;
|
|
@@ -126,6 +129,8 @@ export declare const _getUserPositions: (provider: PublicClient, network: Networ
|
|
|
126
129
|
leftToBorrowUsd: string;
|
|
127
130
|
netApy: string;
|
|
128
131
|
incentiveUsd: string;
|
|
132
|
+
merklSupplyIncentives: import("../types").IncentiveData[];
|
|
133
|
+
merklBorrowIncentives: import("../types").IncentiveData[];
|
|
129
134
|
ratio: string;
|
|
130
135
|
collRatio: string;
|
|
131
136
|
minRatio: string;
|
|
@@ -158,6 +163,8 @@ export declare const getUserPositions: (provider: EthereumProvider, network: Net
|
|
|
158
163
|
leftToBorrowUsd: string;
|
|
159
164
|
netApy: string;
|
|
160
165
|
incentiveUsd: string;
|
|
166
|
+
merklSupplyIncentives: import("../types").IncentiveData[];
|
|
167
|
+
merklBorrowIncentives: import("../types").IncentiveData[];
|
|
161
168
|
ratio: string;
|
|
162
169
|
collRatio: string;
|
|
163
170
|
minRatio: string;
|
|
@@ -190,6 +197,8 @@ export declare const _getUserPositionsPortfolio: (provider: PublicClient, networ
|
|
|
190
197
|
leftToBorrowUsd: string;
|
|
191
198
|
netApy: string;
|
|
192
199
|
incentiveUsd: string;
|
|
200
|
+
merklSupplyIncentives: import("../types").IncentiveData[];
|
|
201
|
+
merklBorrowIncentives: import("../types").IncentiveData[];
|
|
193
202
|
ratio: string;
|
|
194
203
|
collRatio: string;
|
|
195
204
|
minRatio: string;
|
package/cjs/fluid/index.js
CHANGED
|
@@ -12,7 +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
|
-
exports._getUserPositionsPortfolio = exports.getUserPositions = exports._getUserPositions = exports.getAllUserEarnPositionsWithFTokens = exports._getAllUserEarnPositionsWithFTokens = exports.getFluidDepositData = exports._getFluidDepositData = exports.getFluidTokenData = exports._getFluidTokenData = exports.getAllFluidMarketDataChunked = exports._getAllFluidMarketDataChunked = exports.getFluidPositionWithMarket = exports._getFluidPositionWithMarket = exports.getFluidPosition = exports._getFluidPosition = exports.getFluidVaultIdsForUser = exports._getFluidVaultIdsForUser = exports.getFluidMarketData = exports._getFluidMarketData = exports.EMPTY_FLUID_DATA = exports.EMPTY_USED_ASSET = void 0;
|
|
15
|
+
exports._getUserPositionsPortfolio = exports.getUserPositions = exports._getUserPositions = exports.getAllUserEarnPositionsWithFTokens = exports._getAllUserEarnPositionsWithFTokens = exports.getFluidDepositData = exports._getFluidDepositData = exports.getFluidTokenData = exports._getFluidTokenData = exports.getAllFluidMarketDataChunked = exports._getAllFluidMarketDataChunked = exports.getFluidPositionWithMarket = exports._getFluidPositionWithMarket = exports.getFluidPosition = exports._getFluidPosition = exports.getFluidVaultIdsForUser = exports._getFluidVaultIdsForUser = exports.getFluidMarketData = exports._getFluidMarketData = exports.EMPTY_FLUID_DATA = exports.EMPTY_USED_ASSET = exports.attachFluidMerklIncentives = exports.getFluidMerklCampaigns = exports.buildFluidMerklRewardMap = exports.FluidMerklOpportunityType = void 0;
|
|
16
16
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
17
17
|
const tokens_1 = require("@defisaver/tokens");
|
|
18
18
|
const common_1 = require("../types/common");
|
|
@@ -25,6 +25,12 @@ const constants_1 = require("../constants");
|
|
|
25
25
|
const priceService_1 = require("../services/priceService");
|
|
26
26
|
const staking_1 = require("../staking");
|
|
27
27
|
const viem_1 = require("../services/viem");
|
|
28
|
+
const merkl_1 = require("./merkl");
|
|
29
|
+
var merkl_2 = require("./merkl");
|
|
30
|
+
Object.defineProperty(exports, "FluidMerklOpportunityType", { enumerable: true, get: function () { return merkl_2.FluidMerklOpportunityType; } });
|
|
31
|
+
Object.defineProperty(exports, "buildFluidMerklRewardMap", { enumerable: true, get: function () { return merkl_2.buildFluidMerklRewardMap; } });
|
|
32
|
+
Object.defineProperty(exports, "getFluidMerklCampaigns", { enumerable: true, get: function () { return merkl_2.getFluidMerklCampaigns; } });
|
|
33
|
+
Object.defineProperty(exports, "attachFluidMerklIncentives", { enumerable: true, get: function () { return merkl_2.attachFluidMerklIncentives; } });
|
|
28
34
|
exports.EMPTY_USED_ASSET = {
|
|
29
35
|
isSupplied: false,
|
|
30
36
|
isBorrowed: false,
|
|
@@ -916,6 +922,8 @@ exports.EMPTY_FLUID_DATA = {
|
|
|
916
922
|
minRatio: '0',
|
|
917
923
|
netApy: '0',
|
|
918
924
|
incentiveUsd: '0',
|
|
925
|
+
merklSupplyIncentives: [],
|
|
926
|
+
merklBorrowIncentives: [],
|
|
919
927
|
totalInterestUsd: '0',
|
|
920
928
|
isSubscribedToAutomation: false,
|
|
921
929
|
automationResubscribeRequired: false,
|
|
@@ -1106,8 +1114,12 @@ const parseUserData = (userPositionData, vaultData) => {
|
|
|
1106
1114
|
};
|
|
1107
1115
|
const _getFluidMarketData = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1108
1116
|
const view = (0, contracts_1.FluidViewContractViem)(provider, network);
|
|
1109
|
-
const data = yield
|
|
1110
|
-
|
|
1117
|
+
const [data, merklCampaigns] = yield Promise.all([
|
|
1118
|
+
view.read.getVaultData([market.marketAddress]),
|
|
1119
|
+
(0, merkl_1.getFluidMerklCampaigns)(network),
|
|
1120
|
+
]);
|
|
1121
|
+
const marketData = yield parseMarketData(provider, data, network);
|
|
1122
|
+
return marketData ? (0, merkl_1.attachFluidMerklIncentives)(marketData, merklCampaigns) : marketData;
|
|
1111
1123
|
});
|
|
1112
1124
|
exports._getFluidMarketData = _getFluidMarketData;
|
|
1113
1125
|
const getFluidMarketData = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getFluidMarketData)((0, viem_1.getViemProvider)(provider, network), network, market); });
|
|
@@ -1130,11 +1142,15 @@ const getFluidPosition = (provider, network, vaultId, extractedState) => __await
|
|
|
1130
1142
|
exports.getFluidPosition = getFluidPosition;
|
|
1131
1143
|
const _getFluidPositionWithMarket = (provider, network, vaultId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1132
1144
|
const view = (0, contracts_1.FluidViewContractViem)(provider, network);
|
|
1133
|
-
const data = yield
|
|
1134
|
-
|
|
1135
|
-
|
|
1145
|
+
const [data, merklCampaigns] = yield Promise.all([
|
|
1146
|
+
view.read.getPositionByNftId([BigInt(vaultId)]),
|
|
1147
|
+
(0, merkl_1.getFluidMerklCampaigns)(network),
|
|
1148
|
+
]);
|
|
1149
|
+
const parsedMarketData = yield parseMarketData(provider, data[1], network);
|
|
1150
|
+
if (!parsedMarketData) {
|
|
1136
1151
|
return;
|
|
1137
1152
|
}
|
|
1153
|
+
const marketData = (0, merkl_1.attachFluidMerklIncentives)(parsedMarketData, merklCampaigns);
|
|
1138
1154
|
const userData = parseUserData(data[0], marketData);
|
|
1139
1155
|
return {
|
|
1140
1156
|
userData,
|
|
@@ -1147,8 +1163,14 @@ exports.getFluidPositionWithMarket = getFluidPositionWithMarket;
|
|
|
1147
1163
|
const _getAllFluidMarketDataChunked = (network, provider) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1148
1164
|
const versions = (0, markets_1.getFluidVersionsDataForNetwork)(network);
|
|
1149
1165
|
const view = (0, contracts_1.FluidViewContractViem)(provider, network);
|
|
1150
|
-
const data = yield Promise.all(
|
|
1151
|
-
|
|
1166
|
+
const [data, merklCampaigns] = yield Promise.all([
|
|
1167
|
+
Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress]))),
|
|
1168
|
+
(0, merkl_1.getFluidMerklCampaigns)(network),
|
|
1169
|
+
]);
|
|
1170
|
+
return Promise.all(data.map((item) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1171
|
+
const marketData = yield parseMarketData(provider, item, network);
|
|
1172
|
+
return marketData ? (0, merkl_1.attachFluidMerklIncentives)(marketData, merklCampaigns) : marketData;
|
|
1173
|
+
})));
|
|
1152
1174
|
});
|
|
1153
1175
|
exports._getAllFluidMarketDataChunked = _getAllFluidMarketDataChunked;
|
|
1154
1176
|
const getAllFluidMarketDataChunked = (network, provider) => __awaiter(void 0, void 0, void 0, function* () { return (0, exports._getAllFluidMarketDataChunked)(network, (0, viem_1.getViemProvider)(provider, network, { batch: { multicall: true } })); });
|
|
@@ -1371,8 +1393,12 @@ const _getUserPositionsPortfolio = (provider, network, user) => __awaiter(void 0
|
|
|
1371
1393
|
tokens.push('ETH');
|
|
1372
1394
|
if (!tokens.includes('WBTC'))
|
|
1373
1395
|
tokens.push('WBTC');
|
|
1374
|
-
const tokenPrices = yield
|
|
1375
|
-
|
|
1396
|
+
const [tokenPrices, merklCampaigns] = yield Promise.all([
|
|
1397
|
+
getTokensPricesForPortfolio(tokens, provider, network),
|
|
1398
|
+
(0, merkl_1.getFluidMerklCampaigns)(network),
|
|
1399
|
+
]);
|
|
1400
|
+
const parsedMarketData = (yield Promise.all(data[1].map((vaultData) => __awaiter(void 0, void 0, void 0, function* () { return parseMarketData(provider, vaultData, network, tokenPrices); }))))
|
|
1401
|
+
.map(marketData => (marketData ? (0, merkl_1.attachFluidMerklIncentives)(marketData, merklCampaigns) : marketData));
|
|
1376
1402
|
const userData = data[0].map((position, i) => (parsedMarketData[i] && Object.assign({}, parseUserData(position, parsedMarketData[i]))));
|
|
1377
1403
|
return parsedMarketData.map((market, i) => ({
|
|
1378
1404
|
marketData: market,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import memoize from 'memoizee';
|
|
2
|
+
import { FluidMarketData, FluidMerklRewardMap, MerklOpportunity, NetworkNumber } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Merkl tags Fluid vault-scoped reward campaigns via the opportunity `type` field:
|
|
5
|
+
* - FLUIDVAULT_COLLATERAL → reward for supplying collateral to the vault
|
|
6
|
+
* - FLUIDVAULT_BORROW → reward for borrowing from the vault
|
|
7
|
+
* (ERC20LOGPROCESSOR campaigns target fToken earn positions rather than vaults, so they don't
|
|
8
|
+
* belong on vault market data.)
|
|
9
|
+
*
|
|
10
|
+
* A campaign identifies its vault via `identifier` — the vault address. Conditional campaigns
|
|
11
|
+
* append a marker to it (e.g. `0x5668…eeaBORROW_BL`, excluding holders who borrow the reward
|
|
12
|
+
* asset elsewhere); those are still attached, with the full identifier passed through as
|
|
13
|
+
* `eligibilityId` so a curated check in EligibilityMapping can gate them in net APY — unknown
|
|
14
|
+
* ids apply unconditionally, mirroring Aave V3. Whitelist-gated campaigns only accrue to
|
|
15
|
+
* whitelisted addresses, so they are skipped rather than advertised to every user.
|
|
16
|
+
*/
|
|
17
|
+
export declare enum FluidMerklOpportunityType {
|
|
18
|
+
Collateral = "FLUIDVAULT_COLLATERAL",
|
|
19
|
+
Borrow = "FLUIDVAULT_BORROW"
|
|
20
|
+
}
|
|
21
|
+
export declare const buildFluidMerklRewardMap: (opportunities: MerklOpportunity[], chainId: NetworkNumber) => FluidMerklRewardMap;
|
|
22
|
+
/**
|
|
23
|
+
* Fetches live vault-scoped Fluid campaigns for the chain, keyed by vault address. Never throws —
|
|
24
|
+
* on any failure it returns an empty map, so Merkl being down can't break market data.
|
|
25
|
+
*/
|
|
26
|
+
export declare const getFluidMerklCampaigns: ((chainId: NetworkNumber) => Promise<FluidMerklRewardMap>) & memoize.Memoized<(chainId: NetworkNumber) => Promise<FluidMerklRewardMap>>;
|
|
27
|
+
/**
|
|
28
|
+
* Appends the vault's Merkl campaigns to its assets' incentive arrays — supply rewards on every
|
|
29
|
+
* suppliable asset and borrow rewards on every borrowable one. Smart collateral/debt vaults hold
|
|
30
|
+
* the position across both pair tokens, so the pro-rata reward APY applies to each side's value.
|
|
31
|
+
*/
|
|
32
|
+
export declare const attachFluidMerklIncentives: (marketData: FluidMarketData, campaigns: FluidMerklRewardMap) => FluidMarketData;
|
|
@@ -0,0 +1,103 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.attachFluidMerklIncentives = exports.getFluidMerklCampaigns = exports.buildFluidMerklRewardMap = exports.FluidMerklOpportunityType = void 0;
|
|
16
|
+
const memoizee_1 = __importDefault(require("memoizee"));
|
|
17
|
+
const moneymarket_1 = require("../moneymarket");
|
|
18
|
+
const merkl_1 = require("../services/merkl");
|
|
19
|
+
const types_1 = require("../types");
|
|
20
|
+
/**
|
|
21
|
+
* Merkl tags Fluid vault-scoped reward campaigns via the opportunity `type` field:
|
|
22
|
+
* - FLUIDVAULT_COLLATERAL → reward for supplying collateral to the vault
|
|
23
|
+
* - FLUIDVAULT_BORROW → reward for borrowing from the vault
|
|
24
|
+
* (ERC20LOGPROCESSOR campaigns target fToken earn positions rather than vaults, so they don't
|
|
25
|
+
* belong on vault market data.)
|
|
26
|
+
*
|
|
27
|
+
* A campaign identifies its vault via `identifier` — the vault address. Conditional campaigns
|
|
28
|
+
* append a marker to it (e.g. `0x5668…eeaBORROW_BL`, excluding holders who borrow the reward
|
|
29
|
+
* asset elsewhere); those are still attached, with the full identifier passed through as
|
|
30
|
+
* `eligibilityId` so a curated check in EligibilityMapping can gate them in net APY — unknown
|
|
31
|
+
* ids apply unconditionally, mirroring Aave V3. Whitelist-gated campaigns only accrue to
|
|
32
|
+
* whitelisted addresses, so they are skipped rather than advertised to every user.
|
|
33
|
+
*/
|
|
34
|
+
var FluidMerklOpportunityType;
|
|
35
|
+
(function (FluidMerklOpportunityType) {
|
|
36
|
+
FluidMerklOpportunityType["Collateral"] = "FLUIDVAULT_COLLATERAL";
|
|
37
|
+
FluidMerklOpportunityType["Borrow"] = "FLUIDVAULT_BORROW";
|
|
38
|
+
})(FluidMerklOpportunityType || (exports.FluidMerklOpportunityType = FluidMerklOpportunityType = {}));
|
|
39
|
+
// '0x' + 20-byte vault address; conditional campaigns append a marker after it
|
|
40
|
+
const VAULT_ADDRESS_LENGTH = 42;
|
|
41
|
+
const buildMerklIncentive = (opportunity) => {
|
|
42
|
+
var _a, _b, _c, _d, _e, _f;
|
|
43
|
+
const token = ((_d = (_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) === null || _d === void 0 ? void 0 : _d.symbol) || ((_f = (_e = opportunity.tokens) === null || _e === void 0 ? void 0 : _e[0]) === null || _f === void 0 ? void 0 : _f.symbol) || '';
|
|
44
|
+
return {
|
|
45
|
+
apy: (0, moneymarket_1.aprToApy)(opportunity.apr),
|
|
46
|
+
token,
|
|
47
|
+
incentiveKind: types_1.IncentiveKind.Reward,
|
|
48
|
+
source: types_1.IncentiveSource.Merkl,
|
|
49
|
+
description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
|
|
50
|
+
eligibilityId: opportunity.identifier,
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
const buildFluidMerklRewardMap = (opportunities, chainId) => {
|
|
54
|
+
const result = {};
|
|
55
|
+
opportunities
|
|
56
|
+
.filter((o) => o.chainId === chainId)
|
|
57
|
+
.filter((o) => o.status === types_1.OpportunityStatus.LIVE)
|
|
58
|
+
.filter((o) => Object.values(FluidMerklOpportunityType).includes(o.type))
|
|
59
|
+
.filter((o) => { var _a; return !((_a = o.identifier) === null || _a === void 0 ? void 0 : _a.includes('WHITELIST')); })
|
|
60
|
+
.forEach((o) => {
|
|
61
|
+
var _a;
|
|
62
|
+
const vaultAddress = (_a = o.identifier) === null || _a === void 0 ? void 0 : _a.slice(0, VAULT_ADDRESS_LENGTH).toLowerCase();
|
|
63
|
+
if (!vaultAddress || vaultAddress.length !== VAULT_ADDRESS_LENGTH)
|
|
64
|
+
return;
|
|
65
|
+
if (!result[vaultAddress])
|
|
66
|
+
result[vaultAddress] = { supply: [], borrow: [] };
|
|
67
|
+
result[vaultAddress][o.type === FluidMerklOpportunityType.Borrow ? 'borrow' : 'supply'].push(buildMerklIncentive(o));
|
|
68
|
+
});
|
|
69
|
+
return result;
|
|
70
|
+
};
|
|
71
|
+
exports.buildFluidMerklRewardMap = buildFluidMerklRewardMap;
|
|
72
|
+
/**
|
|
73
|
+
* Fetches live vault-scoped Fluid campaigns for the chain, keyed by vault address. Never throws —
|
|
74
|
+
* on any failure it returns an empty map, so Merkl being down can't break market data.
|
|
75
|
+
*/
|
|
76
|
+
exports.getFluidMerklCampaigns = (0, memoizee_1.default)((chainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
77
|
+
try {
|
|
78
|
+
const opportunities = yield (0, merkl_1.fetchAllMerklOpportunities)({
|
|
79
|
+
mainProtocolId: 'fluid',
|
|
80
|
+
type: Object.values(FluidMerklOpportunityType).join(','),
|
|
81
|
+
status: types_1.OpportunityStatus.LIVE,
|
|
82
|
+
});
|
|
83
|
+
return (0, exports.buildFluidMerklRewardMap)(opportunities, chainId);
|
|
84
|
+
}
|
|
85
|
+
catch (e) {
|
|
86
|
+
console.error('Failed to fetch Fluid Merkl campaigns', e);
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
}), { promise: true, maxAge: 60 * 1000 });
|
|
90
|
+
/**
|
|
91
|
+
* Appends the vault's Merkl campaigns to its assets' incentive arrays — supply rewards on every
|
|
92
|
+
* suppliable asset and borrow rewards on every borrowable one. Smart collateral/debt vaults hold
|
|
93
|
+
* the position across both pair tokens, so the pro-rata reward APY applies to each side's value.
|
|
94
|
+
*/
|
|
95
|
+
const attachFluidMerklIncentives = (marketData, campaigns) => {
|
|
96
|
+
var _a;
|
|
97
|
+
const vaultCampaigns = campaigns[(_a = marketData.marketData.marketAddress) === null || _a === void 0 ? void 0 : _a.toLowerCase()];
|
|
98
|
+
if (!vaultCampaigns || (!vaultCampaigns.supply.length && !vaultCampaigns.borrow.length))
|
|
99
|
+
return marketData;
|
|
100
|
+
const assetsData = Object.fromEntries(Object.entries(marketData.assetsData).map(([symbol, asset]) => [symbol, Object.assign(Object.assign({}, asset), { supplyIncentives: asset.canBeSupplied ? [...asset.supplyIncentives, ...vaultCampaigns.supply] : asset.supplyIncentives, borrowIncentives: asset.canBeBorrowed ? [...asset.borrowIncentives, ...vaultCampaigns.borrow] : asset.borrowIncentives })]));
|
|
101
|
+
return Object.assign(Object.assign({}, marketData), { assetsData });
|
|
102
|
+
};
|
|
103
|
+
exports.attachFluidMerklIncentives = attachFluidMerklIncentives;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { FluidAggregatedVaultData, FluidAssetData, FluidAssetsData, FluidDexBorrowDataStructOutput, FluidDexSupplyDataStructOutput, FluidUsedAsset, FluidUsedAssets, InnerFluidMarketData } from '../../types';
|
|
1
|
+
import { FluidAggregatedVaultData, FluidAssetData, FluidAssetsData, FluidDexBorrowDataStructOutput, FluidDexSupplyDataStructOutput, FluidUsedAsset, FluidUsedAssets, IncentiveData, InnerFluidMarketData } from '../../types';
|
|
2
|
+
import { IncentiveSide } from '../../types/common';
|
|
3
|
+
export declare const getUniqueFluidMerklIncentives: (assetsData: FluidAssetsData, side: IncentiveSide) => IncentiveData[];
|
|
2
4
|
export declare const getFluidAggregatedData: ({ usedAssets, assetsData, marketData, }: {
|
|
3
5
|
usedAssets: FluidUsedAssets;
|
|
4
6
|
marketData: InnerFluidMarketData;
|