@defisaver/positions-sdk 2.1.127-midnight-14-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.
Files changed (100) hide show
  1. package/cjs/aaveV3/merkl.js +10 -9
  2. package/cjs/aaveV4/merkl.js +5 -6
  3. package/cjs/claiming/aaveV3.d.ts +2 -1
  4. package/cjs/claiming/aaveV3.js +13 -4
  5. package/cjs/compoundV3/index.d.ts +1 -0
  6. package/cjs/compoundV3/index.js +8 -2
  7. package/cjs/compoundV3/merkl.d.ts +16 -0
  8. package/cjs/compoundV3/merkl.js +77 -0
  9. package/cjs/fluid/index.d.ts +9 -0
  10. package/cjs/fluid/index.js +36 -10
  11. package/cjs/fluid/merkl.d.ts +32 -0
  12. package/cjs/fluid/merkl.js +103 -0
  13. package/cjs/helpers/fluidHelpers/index.d.ts +3 -1
  14. package/cjs/helpers/fluidHelpers/index.js +37 -4
  15. package/cjs/helpers/liquityV2Helpers/index.d.ts +2 -1
  16. package/cjs/helpers/liquityV2Helpers/index.js +3 -2
  17. package/cjs/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
  18. package/cjs/helpers/morphoMidnightHelpers/headroom.js +52 -0
  19. package/cjs/helpers/morphoMidnightHelpers/index.d.ts +2 -0
  20. package/cjs/helpers/morphoMidnightHelpers/index.js +10 -4
  21. package/cjs/liquityV2/index.js +3 -4
  22. package/cjs/moneymarket/moneymarketCommonService.js +2 -0
  23. package/cjs/morphoBlue/index.d.ts +1 -0
  24. package/cjs/morphoBlue/index.js +16 -10
  25. package/cjs/morphoBlue/merkl.d.ts +35 -0
  26. package/cjs/morphoBlue/merkl.js +102 -0
  27. package/cjs/portfolio/index.js +5 -5
  28. package/cjs/services/merkl.d.ts +6 -0
  29. package/cjs/services/merkl.js +39 -0
  30. package/cjs/staking/eligibility.d.ts +4 -0
  31. package/cjs/staking/eligibility.js +11 -1
  32. package/cjs/types/claiming.d.ts +12 -1
  33. package/cjs/types/claiming.js +2 -0
  34. package/cjs/types/common.d.ts +6 -1
  35. package/cjs/types/common.js +6 -1
  36. package/cjs/types/fluid.d.ts +2 -0
  37. package/cjs/types/liquityV2.d.ts +3 -0
  38. package/cjs/types/merkl.d.ts +8 -0
  39. package/esm/aaveV3/merkl.js +11 -10
  40. package/esm/aaveV4/merkl.js +5 -6
  41. package/esm/claiming/aaveV3.d.ts +2 -1
  42. package/esm/claiming/aaveV3.js +12 -4
  43. package/esm/compoundV3/index.d.ts +1 -0
  44. package/esm/compoundV3/index.js +5 -1
  45. package/esm/compoundV3/merkl.d.ts +16 -0
  46. package/esm/compoundV3/merkl.js +72 -0
  47. package/esm/fluid/index.d.ts +9 -0
  48. package/esm/fluid/index.js +31 -9
  49. package/esm/fluid/merkl.d.ts +32 -0
  50. package/esm/fluid/merkl.js +95 -0
  51. package/esm/helpers/fluidHelpers/index.d.ts +3 -1
  52. package/esm/helpers/fluidHelpers/index.js +38 -6
  53. package/esm/helpers/liquityV2Helpers/index.d.ts +2 -1
  54. package/esm/helpers/liquityV2Helpers/index.js +3 -2
  55. package/esm/helpers/morphoMidnightHelpers/headroom.d.ts +48 -0
  56. package/esm/helpers/morphoMidnightHelpers/headroom.js +45 -0
  57. package/esm/helpers/morphoMidnightHelpers/index.d.ts +2 -0
  58. package/esm/helpers/morphoMidnightHelpers/index.js +7 -3
  59. package/esm/liquityV2/index.js +3 -4
  60. package/esm/moneymarket/moneymarketCommonService.js +2 -0
  61. package/esm/morphoBlue/index.d.ts +1 -0
  62. package/esm/morphoBlue/index.js +11 -9
  63. package/esm/morphoBlue/merkl.d.ts +35 -0
  64. package/esm/morphoBlue/merkl.js +96 -0
  65. package/esm/portfolio/index.js +6 -6
  66. package/esm/services/merkl.d.ts +6 -0
  67. package/esm/services/merkl.js +35 -0
  68. package/esm/staking/eligibility.d.ts +4 -0
  69. package/esm/staking/eligibility.js +9 -0
  70. package/esm/types/claiming.d.ts +12 -1
  71. package/esm/types/claiming.js +2 -0
  72. package/esm/types/common.d.ts +6 -1
  73. package/esm/types/common.js +5 -0
  74. package/esm/types/fluid.d.ts +2 -0
  75. package/esm/types/liquityV2.d.ts +3 -0
  76. package/esm/types/merkl.d.ts +8 -0
  77. package/package.json +1 -1
  78. package/src/aaveV3/merkl.ts +7 -7
  79. package/src/aaveV4/merkl.ts +5 -5
  80. package/src/claiming/aaveV3.ts +19 -7
  81. package/src/compoundV3/index.ts +6 -1
  82. package/src/compoundV3/merkl.ts +76 -0
  83. package/src/fluid/index.ts +37 -9
  84. package/src/fluid/merkl.ts +102 -0
  85. package/src/helpers/fluidHelpers/index.ts +68 -6
  86. package/src/helpers/liquityV2Helpers/index.ts +4 -1
  87. package/src/helpers/morphoMidnightHelpers/headroom.ts +82 -0
  88. package/src/helpers/morphoMidnightHelpers/index.ts +11 -3
  89. package/src/liquityV2/index.ts +4 -3
  90. package/src/moneymarket/moneymarketCommonService.ts +2 -0
  91. package/src/morphoBlue/index.ts +24 -9
  92. package/src/morphoBlue/merkl.ts +121 -0
  93. package/src/portfolio/index.ts +6 -6
  94. package/src/services/merkl.ts +31 -0
  95. package/src/staking/eligibility.ts +10 -0
  96. package/src/types/claiming.ts +13 -0
  97. package/src/types/common.ts +6 -0
  98. package/src/types/fluid.ts +3 -1
  99. package/src/types/liquityV2.ts +3 -0
  100. package/src/types/merkl.ts +6 -0
@@ -4,6 +4,8 @@ export declare enum ClaimType {
4
4
  AAVE_REWARDS = "AAVE_REWARDS",
5
5
  /** Merit rewards from AAVE (various tokens) */
6
6
  AAVE_MERIT_REWARDS = "AAVE_MERIT_REWARDS",
7
+ /** Rewards distributed through Merkl across supported protocols */
8
+ MERKL_REWARDS = "MERKL_REWARDS",
7
9
  /** Rewards from Compound V3 (only in COMP) */
8
10
  COMPOUND_V3_COMP = "COMPOUND_V3_COMP",
9
11
  /** Rewards from Spark (wstETH only for now) */
@@ -43,6 +45,15 @@ export type AaveMeritRewardsClaimableToken = _ClaimableTokenPartial & {
43
45
  unclaimed: string;
44
46
  };
45
47
  };
48
+ export type MerklRewardsClaimableToken = _ClaimableTokenPartial & {
49
+ claimType: ClaimType.MERKL_REWARDS;
50
+ additionalClaimFields: {
51
+ accumulated: string;
52
+ proof: string[];
53
+ decimals: string;
54
+ unclaimed: string;
55
+ };
56
+ };
46
57
  export type SparkRewardsClaimableToken = _ClaimableTokenPartial & {
47
58
  claimType: ClaimType.SPARK_REWARDS;
48
59
  additionalClaimFields: {
@@ -91,5 +102,5 @@ export type UniswapAirdropClaimableToken = _ClaimableTokenPartial & {
91
102
  proof: string[];
92
103
  };
93
104
  };
94
- export type ClaimableToken = AaveRewardsClaimableToken | AaveMeritRewardsClaimableToken | CompoundV3CompClaimableToken | SparkRewardsClaimableToken | KingRewardsClaimableToken | SparkAirdropClaimableToken | SparkWstEthRewardsClaimableToken | EthenaAirdropClaimableToken;
105
+ export type ClaimableToken = AaveRewardsClaimableToken | AaveMeritRewardsClaimableToken | MerklRewardsClaimableToken | CompoundV3CompClaimableToken | SparkRewardsClaimableToken | KingRewardsClaimableToken | SparkAirdropClaimableToken | SparkWstEthRewardsClaimableToken | EthenaAirdropClaimableToken;
95
106
  export {};
@@ -7,6 +7,8 @@ var ClaimType;
7
7
  ClaimType["AAVE_REWARDS"] = "AAVE_REWARDS";
8
8
  /** Merit rewards from AAVE (various tokens) */
9
9
  ClaimType["AAVE_MERIT_REWARDS"] = "AAVE_MERIT_REWARDS";
10
+ /** Rewards distributed through Merkl across supported protocols */
11
+ ClaimType["MERKL_REWARDS"] = "MERKL_REWARDS";
10
12
  /** Rewards from Compound V3 (only in COMP) */
11
13
  ClaimType["COMPOUND_V3_COMP"] = "COMPOUND_V3_COMP";
12
14
  /** Rewards from Spark (wstETH only for now) */
@@ -6,12 +6,16 @@ export declare enum IncentiveSide {
6
6
  Supply = "supply",
7
7
  Borrow = "borrow"
8
8
  }
9
+ export declare enum IncentiveSource {
10
+ Merkl = "merkl"
11
+ }
9
12
  export declare enum IncentiveEligibilityId {
10
13
  AaveV3EthenaLiquidLeverage = "0x0dC599DBB180E64E42b87332FDeC3a551445ea44BORROW_BL",
11
14
  AaveV3ArbitrumEthSupply = "0x5d16261c6715a653248269861bbacf68a9774cde",
12
15
  AaveV3ArbitrumETHLSBorrow = "0x0c84331e39d6658Cd6e6b9ba04736cC4c4734351",
13
16
  AaveV3EthenaLiquidLeveragePlasma = "0x2E8f1FA9c73F9d975B46BDFe40C92b6dDEFA3f31BORROW_BL",
14
- AaveV3EthenaLiquidLeveragePlasmaGHO = "2b2f6fefcd3df634"
17
+ AaveV3EthenaLiquidLeveragePlasmaGHO = "2b2f6fefcd3df634",
18
+ CompoundV3PufEthWethBorrow = "e6e49b79e83041f9"
15
19
  }
16
20
  export declare enum LeverageType {
17
21
  Long = "long",
@@ -24,6 +28,7 @@ export interface IncentiveData {
24
28
  token: string;
25
29
  apy: string;
26
30
  incentiveKind?: IncentiveKind;
31
+ source?: IncentiveSource;
27
32
  description?: string;
28
33
  eligibilityId?: IncentiveEligibilityId;
29
34
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.NetworkNumber = exports.LeverageType = exports.IncentiveEligibilityId = exports.IncentiveSide = exports.IncentiveKind = void 0;
3
+ exports.NetworkNumber = exports.LeverageType = exports.IncentiveEligibilityId = exports.IncentiveSource = exports.IncentiveSide = exports.IncentiveKind = void 0;
4
4
  var IncentiveKind;
5
5
  (function (IncentiveKind) {
6
6
  IncentiveKind["Staking"] = "staking";
@@ -11,6 +11,10 @@ var IncentiveSide;
11
11
  IncentiveSide["Supply"] = "supply";
12
12
  IncentiveSide["Borrow"] = "borrow";
13
13
  })(IncentiveSide || (exports.IncentiveSide = IncentiveSide = {}));
14
+ var IncentiveSource;
15
+ (function (IncentiveSource) {
16
+ IncentiveSource["Merkl"] = "merkl";
17
+ })(IncentiveSource || (exports.IncentiveSource = IncentiveSource = {}));
14
18
  var IncentiveEligibilityId;
15
19
  (function (IncentiveEligibilityId) {
16
20
  IncentiveEligibilityId["AaveV3EthenaLiquidLeverage"] = "0x0dC599DBB180E64E42b87332FDeC3a551445ea44BORROW_BL";
@@ -18,6 +22,7 @@ var IncentiveEligibilityId;
18
22
  IncentiveEligibilityId["AaveV3ArbitrumETHLSBorrow"] = "0x0c84331e39d6658Cd6e6b9ba04736cC4c4734351";
19
23
  IncentiveEligibilityId["AaveV3EthenaLiquidLeveragePlasma"] = "0x2E8f1FA9c73F9d975B46BDFe40C92b6dDEFA3f31BORROW_BL";
20
24
  IncentiveEligibilityId["AaveV3EthenaLiquidLeveragePlasmaGHO"] = "2b2f6fefcd3df634";
25
+ IncentiveEligibilityId["CompoundV3PufEthWethBorrow"] = "e6e49b79e83041f9";
21
26
  })(IncentiveEligibilityId || (exports.IncentiveEligibilityId = IncentiveEligibilityId = {}));
22
27
  var LeverageType;
23
28
  (function (LeverageType) {
@@ -319,6 +319,8 @@ export interface FluidAggregatedVaultData {
319
319
  leftToBorrowUsd: string;
320
320
  netApy: string;
321
321
  incentiveUsd: string;
322
+ merklSupplyIncentives: IncentiveData[];
323
+ merklBorrowIncentives: IncentiveData[];
322
324
  ratio: string;
323
325
  collRatio: string;
324
326
  minRatio: string;
@@ -84,6 +84,7 @@ export interface LiquityV2AggregatedTroveData {
84
84
  suppliedUsd: string;
85
85
  borrowedUsd: string;
86
86
  borrowLimitUsd: string;
87
+ liquidationLimitUsd: string;
87
88
  leftToBorrowUsd: string;
88
89
  netApy: string;
89
90
  incentiveUsd: string;
@@ -101,9 +102,11 @@ export interface LiquityV2TroveData {
101
102
  ratio: string;
102
103
  collRatio: string;
103
104
  liqRatio: string;
105
+ borrowLimitRatio: string;
104
106
  interestRate: string;
105
107
  leftToBorrowUsd: string;
106
108
  borrowLimitUsd: string;
109
+ liquidationLimitUsd: string;
107
110
  suppliedUsd: string;
108
111
  borrowedUsd: string;
109
112
  netApy: string;
@@ -76,6 +76,14 @@ export type MerkleRewardMap = Record<EthAddress, {
76
76
  export type AaveV4MerklScopedReward = {
77
77
  [side in IncentiveSide]?: IncentiveData;
78
78
  };
79
+ /**
80
+ * Fluid vault-scoped Merkl campaigns keyed by lowercase vault address — `supply` rewards apply to
81
+ * the vault's collateral side, `borrow` rewards to its debt side.
82
+ */
83
+ export type FluidMerklRewardMap = Record<string, {
84
+ supply: IncentiveData[];
85
+ borrow: IncentiveData[];
86
+ }>;
79
87
  /**
80
88
  * Aave V4 Merkl reward campaigns split by scope:
81
89
  * - `hub`: keyed by `${hubAddress}_${underlyingAddress}` (both lowercase) — rewards for supplying/borrowing via a hub
@@ -8,7 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { aprToApy } from '../moneymarket';
11
- import { LONGER_TIMEOUT, wethToEth } from '../services/utils';
11
+ import { fetchAllMerklOpportunities } from '../services/merkl';
12
+ import { wethToEth } from '../services/utils';
12
13
  import { OpportunityAction, OpportunityStatus, } from '../types';
13
14
  export const getAaveUnderlyingSymbol = (_symbol = '') => {
14
15
  let symbol = _symbol
@@ -35,21 +36,21 @@ export const formatAaveAsset = (_symbol) => {
35
36
  };
36
37
  export const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
37
38
  try {
38
- const res = yield fetch('https://fe.defisaver.com/api/merkl/opportunities?mainProtocolId=aave', {
39
- signal: AbortSignal.timeout(LONGER_TIMEOUT),
39
+ const opportunities = yield fetchAllMerklOpportunities({
40
+ mainProtocolId: 'aave',
41
+ status: OpportunityStatus.LIVE,
40
42
  });
41
- if (!res.ok)
42
- throw new Error('Failed to fetch Merkle campaigns');
43
- const opportunities = yield res.json();
44
43
  const relevantOpportunities = opportunities
45
44
  .filter((o) => o.chainId === chainId)
46
45
  .filter((o) => o.status === OpportunityStatus.LIVE);
47
46
  return relevantOpportunities.reduce((acc, opportunity) => {
48
- var _a, _b;
49
- const rewardToken = opportunity.rewardsRecord.breakdowns[0].token;
47
+ var _a, _b, _c, _d, _e;
48
+ 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;
49
+ if (!rewardToken)
50
+ return acc;
50
51
  const description = `Eligible for ${formatAaveAsset(rewardToken.symbol)} rewards through Merkl. ${opportunity.description ? `\n${opportunity.description}` : ''}`;
51
52
  if (opportunity.action === OpportunityAction.LEND && opportunity.explorerAddress) {
52
- const supplyAToken = (_a = opportunity.explorerAddress) === null || _a === void 0 ? void 0 : _a.toLowerCase();
53
+ const supplyAToken = (_d = opportunity.explorerAddress) === null || _d === void 0 ? void 0 : _d.toLowerCase();
53
54
  if (!acc[supplyAToken])
54
55
  acc[supplyAToken] = {};
55
56
  acc[supplyAToken].supply = {
@@ -61,7 +62,7 @@ export const getMerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0,
61
62
  };
62
63
  }
63
64
  if (opportunity.action === OpportunityAction.BORROW && opportunity.explorerAddress) {
64
- const borrowAToken = (_b = opportunity.explorerAddress) === null || _b === void 0 ? void 0 : _b.toLowerCase();
65
+ const borrowAToken = (_e = opportunity.explorerAddress) === null || _e === void 0 ? void 0 : _e.toLowerCase();
65
66
  if (!acc[borrowAToken])
66
67
  acc[borrowAToken] = {};
67
68
  acc[borrowAToken].borrow = {
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  import { aprToApy } from '../moneymarket';
11
- import { LONGER_TIMEOUT } from '../services/utils';
11
+ import { fetchAllMerklOpportunities } from '../services/merkl';
12
12
  import { IncentiveKind, IncentiveSide, OpportunityAction, OpportunityStatus, } from '../types';
13
13
  /**
14
14
  * Merkl tags Aave V4 reward campaigns by scope via the `type` field:
@@ -63,12 +63,11 @@ export const buildAaveV4MerklRewardMap = (opportunities, chainId) => {
63
63
  };
64
64
  export const getAaveV4MerkleCampaigns = (chainId) => __awaiter(void 0, void 0, void 0, function* () {
65
65
  try {
66
- const res = yield fetch('https://fe.defisaver.com/api/merkl/opportunities?mainProtocolId=aave&type=AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW', {
67
- signal: AbortSignal.timeout(LONGER_TIMEOUT),
66
+ const opportunities = yield fetchAllMerklOpportunities({
67
+ mainProtocolId: 'aave',
68
+ type: 'AAVE_V4_HUB_SUPPLY,AAVE_V4_HUB_BORROW,AAVE_V4_SPOKE_SUPPLY,AAVE_V4_SPOKE_BORROW',
69
+ status: OpportunityStatus.LIVE,
68
70
  });
69
- if (!res.ok)
70
- throw new Error('Failed to fetch Aave V4 Merkle campaigns');
71
- const opportunities = yield res.json();
72
71
  return buildAaveV4MerklRewardMap(opportunities, chainId);
73
72
  }
74
73
  catch (e) {
@@ -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[]>;
@@ -88,7 +88,7 @@ export function getUnclaimedRewardsForAllMarkets(provider, network, walletAddres
88
88
  return mapAaveRewardsToClaimableTokens(Object.values(totalUnclaimedPerRewardToken), marketAddress, walletAddress);
89
89
  });
90
90
  }
91
- export function getMeritUnclaimedRewards(account, network) {
91
+ export function getMerklUnclaimedRewards(account, network) {
92
92
  return __awaiter(this, void 0, void 0, function* () {
93
93
  let data;
94
94
  try {
@@ -96,7 +96,7 @@ export function getMeritUnclaimedRewards(account, network) {
96
96
  data = yield res.json();
97
97
  }
98
98
  catch (error) {
99
- console.error('External API Failure: Aave Merit', error);
99
+ console.error('External API Failure: Merkl rewards', error);
100
100
  data = [];
101
101
  }
102
102
  const claimableTokens = [];
@@ -114,12 +114,12 @@ export function getMeritUnclaimedRewards(account, network) {
114
114
  return;
115
115
  const unclaimed = getEthAmountForDecimals(unclaimedAmount, token.decimals);
116
116
  claimableTokens.push({
117
- claimType: ClaimType.AAVE_MERIT_REWARDS,
117
+ claimType: ClaimType.MERKL_REWARDS,
118
118
  amount: unclaimed,
119
119
  symbol: token.symbol,
120
120
  tokenAddress: token.address,
121
121
  walletAddress: account,
122
- label: 'AAVE Merit Rewards',
122
+ label: 'Merkl Rewards',
123
123
  underlyingSymbol: getAaveUnderlyingSymbol(token.symbol),
124
124
  additionalClaimFields: {
125
125
  accumulated: amount,
@@ -133,3 +133,11 @@ export function getMeritUnclaimedRewards(account, network) {
133
133
  return claimableTokens;
134
134
  });
135
135
  }
136
+ export function getMeritUnclaimedRewards(account, network) {
137
+ return __awaiter(this, void 0, void 0, function* () {
138
+ const rewards = yield getMerklUnclaimedRewards(account, network);
139
+ return rewards
140
+ .filter(reward => reward.symbol.startsWith('a'))
141
+ .map(reward => (Object.assign(Object.assign({}, reward), { claimType: ClaimType.AAVE_MERIT_REWARDS, label: 'AAVE Merit Rewards' })));
142
+ });
143
+ }
@@ -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: {
@@ -19,6 +19,8 @@ import { formatBaseData, formatMarketData, getCompoundV3AggregatedData, getIncen
19
19
  import { CompoundMarkets } from '../markets/compound';
20
20
  import { getEthPrice, getCompPrice, getUSDCPrice, getWstETHPrice, } from '../services/priceService';
21
21
  import { getViemProvider, setViemBlockNumber } from '../services/viem';
22
+ import { attachCompoundV3MerklIncentives, getCompoundV3MerklOpportunities } from './merkl';
23
+ export { getCompoundV3MerklOpportunities, attachCompoundV3MerklIncentives } from './merkl';
22
24
  const getSupportedAssetsAddressesForMarket = (selectedMarket, network) => selectedMarket.collAssets.map(asset => getAssetInfo(ethToWeth(asset), network)).map(addr => addr.address.toLowerCase());
23
25
  const getBaseAssetPriceFunction = (asset) => {
24
26
  switch (asset) {
@@ -32,12 +34,13 @@ const getBaseAssetPriceFunction = (asset) => {
32
34
  };
33
35
  export const _getCompoundV3MarketsData = (provider, network, selectedMarket, defaultProvider) => __awaiter(void 0, void 0, void 0, function* () {
34
36
  const contract = CompV3ViewContractViem(provider, network);
35
- const [baseAssetPrice, compPrice, baseTokenInfo, collInfos, govInfo] = yield Promise.all([
37
+ const [baseAssetPrice, compPrice, baseTokenInfo, collInfos, govInfo, merklOpportunities] = yield Promise.all([
36
38
  getBaseAssetPriceFunction(selectedMarket.baseAsset)(defaultProvider),
37
39
  getCompPrice(defaultProvider),
38
40
  contract.read.getFullBaseTokenInfo([selectedMarket.baseMarketAddress]),
39
41
  contract.read.getFullCollInfos([selectedMarket.baseMarketAddress]),
40
42
  contract.read.getGovernanceInfoFull([selectedMarket.baseMarketAddress]),
43
+ getCompoundV3MerklOpportunities(),
41
44
  ]);
42
45
  const { isSupplyPaused, isWithdrawPaused } = govInfo;
43
46
  const supportedAssetsAddresses = getSupportedAssetsAddressesForMarket(selectedMarket, network);
@@ -57,6 +60,7 @@ export const _getCompoundV3MarketsData = (provider, network, selectedMarket, def
57
60
  const base = formatBaseData(baseTokenInfo, network, baseAssetPrice, isSupplyPaused, isWithdrawPaused);
58
61
  const payload = {};
59
62
  const baseObj = Object.assign(Object.assign({}, base), (yield getIncentiveApys(base, compPrice)));
63
+ attachCompoundV3MerklIncentives(baseObj, colls, selectedMarket.baseMarketAddress, network, merklOpportunities);
60
64
  const allAssets = [baseObj, ...colls];
61
65
  allAssets
62
66
  .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,72 @@
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 { getAssetInfoByAddress } from '@defisaver/tokens';
11
+ import { aprToApy } from '../moneymarket';
12
+ import { fetchAllMerklOpportunities } from '../services/merkl';
13
+ import { compareAddresses, wethToEth } from '../services/utils';
14
+ import { IncentiveKind, OpportunityAction, OpportunityStatus, } from '../types';
15
+ /**
16
+ * Merkl tags Compound V3 reward campaigns with COMPOUND_V3_* opportunity types (e.g.
17
+ * COMPOUND_V3_BORROW_FROM_COLLATERAL) and identifies the comet via `explorerAddress`. Campaign
18
+ * identifiers are opaque hashes, passed through as `eligibilityId` so conditional campaigns —
19
+ * like borrow-from-collateral ones, whose reward is min(collateral * LTV, borrow amount) — can
20
+ * be gated and sized by a curated check in EligibilityMapping; unknown ids apply
21
+ * unconditionally, mirroring Aave V3.
22
+ */
23
+ export const getCompoundV3MerklOpportunities = () => __awaiter(void 0, void 0, void 0, function* () {
24
+ try {
25
+ return yield fetchAllMerklOpportunities({
26
+ mainProtocolId: 'compound-v3',
27
+ status: OpportunityStatus.LIVE,
28
+ });
29
+ }
30
+ catch (e) {
31
+ console.error('Failed to fetch Compound V3 Merkl campaigns', e);
32
+ return [];
33
+ }
34
+ });
35
+ const buildMerklIncentive = (opportunity) => {
36
+ var _a, _b, _c, _d, _e, _f;
37
+ 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) || '';
38
+ return {
39
+ apy: aprToApy(opportunity.apr),
40
+ token,
41
+ incentiveKind: IncentiveKind.Reward,
42
+ description: `Eligible for ${token} rewards through Merkl.${opportunity.description ? `\n${opportunity.description}` : ''}`,
43
+ eligibilityId: opportunity.identifier,
44
+ };
45
+ };
46
+ /**
47
+ * Appends the comet's Merkl campaigns to its assets' incentive arrays (mutating them, like the
48
+ * staking incentives are attached). BORROW campaigns land on the base asset — the only borrowable
49
+ * one — while LEND campaigns land on the asset the campaign's first token resolves to.
50
+ */
51
+ export const attachCompoundV3MerklIncentives = (baseAsset, collAssets, baseMarketAddress, chainId, opportunities) => {
52
+ opportunities
53
+ .filter((o) => o.chainId === chainId
54
+ && o.status === OpportunityStatus.LIVE
55
+ && typeof o.type === 'string' && o.type.startsWith('COMPOUND_V3')
56
+ && o.explorerAddress && compareAddresses(o.explorerAddress, baseMarketAddress))
57
+ .forEach((o) => {
58
+ var _a, _b;
59
+ const incentive = buildMerklIncentive(o);
60
+ if (o.action === OpportunityAction.BORROW) {
61
+ baseAsset.borrowIncentives.push(incentive);
62
+ }
63
+ else if (o.action === OpportunityAction.LEND) {
64
+ const campaignTokenAddress = (_b = (_a = o.tokens) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.address;
65
+ if (!campaignTokenAddress)
66
+ return;
67
+ const campaignSymbol = wethToEth(getAssetInfoByAddress(campaignTokenAddress, chainId).symbol);
68
+ const target = [baseAsset, ...collAssets].find((asset) => asset.symbol === campaignSymbol);
69
+ target === null || target === void 0 ? void 0 : target.supplyIncentives.push(incentive);
70
+ }
71
+ });
72
+ };
@@ -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;
@@ -19,6 +19,8 @@ import { USD_QUOTE, ZERO_ADDRESS } from '../constants';
19
19
  import { getChainlinkAssetAddress, getSyrupUSDTChainLinkPriceCalls, getSyrupUSDTPrice, getWeETHChainLinkPriceCalls, getWeETHPrice, getWsrETHChainLinkPriceCalls, getWsrETHPrice, getWstETHChainLinkPriceCalls, getWstETHPrice, getWstETHPriceFluid, getWstUSRChainLinkPriceCalls, getWstUSRPrice, parseSyrupUSDTPriceCalls, parseWeETHPriceCalls, parseWrsETHPriceCalls, parseWstETHPriceCalls, parseWstUSRPriceCalls, } from '../services/priceService';
20
20
  import { getStakingApy, STAKING_ASSETS } from '../staking';
21
21
  import { getViemProvider } from '../services/viem';
22
+ import { attachFluidMerklIncentives, getFluidMerklCampaigns } from './merkl';
23
+ export { FluidMerklOpportunityType, buildFluidMerklRewardMap, getFluidMerklCampaigns, attachFluidMerklIncentives, } from './merkl';
22
24
  export const EMPTY_USED_ASSET = {
23
25
  isSupplied: false,
24
26
  isBorrowed: false,
@@ -910,6 +912,8 @@ export const EMPTY_FLUID_DATA = {
910
912
  minRatio: '0',
911
913
  netApy: '0',
912
914
  incentiveUsd: '0',
915
+ merklSupplyIncentives: [],
916
+ merklBorrowIncentives: [],
913
917
  totalInterestUsd: '0',
914
918
  isSubscribedToAutomation: false,
915
919
  automationResubscribeRequired: false,
@@ -1100,8 +1104,12 @@ const parseUserData = (userPositionData, vaultData) => {
1100
1104
  };
1101
1105
  export const _getFluidMarketData = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () {
1102
1106
  const view = FluidViewContractViem(provider, network);
1103
- const data = yield view.read.getVaultData([market.marketAddress]);
1104
- return parseMarketData(provider, data, network);
1107
+ const [data, merklCampaigns] = yield Promise.all([
1108
+ view.read.getVaultData([market.marketAddress]),
1109
+ getFluidMerklCampaigns(network),
1110
+ ]);
1111
+ const marketData = yield parseMarketData(provider, data, network);
1112
+ return marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData;
1105
1113
  });
1106
1114
  export const getFluidMarketData = (provider, network, market) => __awaiter(void 0, void 0, void 0, function* () { return _getFluidMarketData(getViemProvider(provider, network), network, market); });
1107
1115
  export const _getFluidVaultIdsForUser = (provider, network, user) => __awaiter(void 0, void 0, void 0, function* () {
@@ -1118,11 +1126,15 @@ export const _getFluidPosition = (provider, network, vaultId, extractedState) =>
1118
1126
  export const getFluidPosition = (provider, network, vaultId, extractedState) => __awaiter(void 0, void 0, void 0, function* () { return _getFluidPosition(getViemProvider(provider, network), network, vaultId, extractedState); });
1119
1127
  export const _getFluidPositionWithMarket = (provider, network, vaultId) => __awaiter(void 0, void 0, void 0, function* () {
1120
1128
  const view = FluidViewContractViem(provider, network);
1121
- const data = yield view.read.getPositionByNftId([BigInt(vaultId)]);
1122
- const marketData = yield parseMarketData(provider, data[1], network);
1123
- if (!marketData) {
1129
+ const [data, merklCampaigns] = yield Promise.all([
1130
+ view.read.getPositionByNftId([BigInt(vaultId)]),
1131
+ getFluidMerklCampaigns(network),
1132
+ ]);
1133
+ const parsedMarketData = yield parseMarketData(provider, data[1], network);
1134
+ if (!parsedMarketData) {
1124
1135
  return;
1125
1136
  }
1137
+ const marketData = attachFluidMerklIncentives(parsedMarketData, merklCampaigns);
1126
1138
  const userData = parseUserData(data[0], marketData);
1127
1139
  return {
1128
1140
  userData,
@@ -1133,8 +1145,14 @@ export const getFluidPositionWithMarket = (provider, network, vaultId) => __awai
1133
1145
  export const _getAllFluidMarketDataChunked = (network, provider) => __awaiter(void 0, void 0, void 0, function* () {
1134
1146
  const versions = getFluidVersionsDataForNetwork(network);
1135
1147
  const view = FluidViewContractViem(provider, network);
1136
- const data = yield Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress])));
1137
- return Promise.all(data.map((item, i) => __awaiter(void 0, void 0, void 0, function* () { return parseMarketData(provider, item, network); })));
1148
+ const [data, merklCampaigns] = yield Promise.all([
1149
+ Promise.all(versions.map((version) => view.read.getVaultData([version.marketAddress]))),
1150
+ getFluidMerklCampaigns(network),
1151
+ ]);
1152
+ return Promise.all(data.map((item) => __awaiter(void 0, void 0, void 0, function* () {
1153
+ const marketData = yield parseMarketData(provider, item, network);
1154
+ return marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData;
1155
+ })));
1138
1156
  });
1139
1157
  export const getAllFluidMarketDataChunked = (network, provider) => __awaiter(void 0, void 0, void 0, function* () { return _getAllFluidMarketDataChunked(network, getViemProvider(provider, network, { batch: { multicall: true } })); });
1140
1158
  export const _getFluidTokenData = (provider, network, token) => __awaiter(void 0, void 0, void 0, function* () {
@@ -1347,8 +1365,12 @@ export const _getUserPositionsPortfolio = (provider, network, user) => __awaiter
1347
1365
  tokens.push('ETH');
1348
1366
  if (!tokens.includes('WBTC'))
1349
1367
  tokens.push('WBTC');
1350
- const tokenPrices = yield getTokensPricesForPortfolio(tokens, provider, network);
1351
- const parsedMarketData = (yield Promise.all(data[1].map((vaultData) => __awaiter(void 0, void 0, void 0, function* () { return parseMarketData(provider, vaultData, network, tokenPrices); }))));
1368
+ const [tokenPrices, merklCampaigns] = yield Promise.all([
1369
+ getTokensPricesForPortfolio(tokens, provider, network),
1370
+ getFluidMerklCampaigns(network),
1371
+ ]);
1372
+ const parsedMarketData = (yield Promise.all(data[1].map((vaultData) => __awaiter(void 0, void 0, void 0, function* () { return parseMarketData(provider, vaultData, network, tokenPrices); }))))
1373
+ .map(marketData => (marketData ? attachFluidMerklIncentives(marketData, merklCampaigns) : marketData));
1352
1374
  const userData = data[0].map((position, i) => (parsedMarketData[i] && Object.assign({}, parseUserData(position, parsedMarketData[i]))));
1353
1375
  return parsedMarketData.map((market, i) => ({
1354
1376
  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;