@defisaver/positions-sdk 2.1.123 → 2.1.124

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.
@@ -74,6 +74,16 @@ const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
74
74
  return riskPremiumBps.toNumber();
75
75
  };
76
76
  exports.calcUserRiskPremiumBps = calcUserRiskPremiumBps;
77
+ /**
78
+ * `spokeXIncentives`/`hubXIncentives` are each the intrinsic `base` list with at most one Merkl
79
+ * reward appended (see attachAaveV4MerklIncentives). Both scopes can apply to the same position at
80
+ * once (spoke-specific + hub-wide), so the full applicable set is base + whatever each scope appended.
81
+ */
82
+ const mergeScopedIncentives = (base = [], spokeScoped, hubScoped) => [
83
+ ...base,
84
+ ...(spokeScoped ? spokeScoped.slice(base.length) : []),
85
+ ...(hubScoped ? hubScoped.slice(base.length) : []),
86
+ ];
77
87
  const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
78
88
  const riskPremiumBps = (0, exports.calcUserRiskPremiumBps)(usedAssets, assetsData);
79
89
  const riskPremiumFraction = new decimal_js_1.default(riskPremiumBps).div(10000);
@@ -87,11 +97,10 @@ const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
87
97
  acc.suppliedUsd = new decimal_js_1.default(acc.suppliedUsd).add(amount).toString();
88
98
  const supplyInterest = (0, staking_1.calculateInterestEarned)(amount, assetData.supplyRate, 'year', true);
89
99
  acc.supplyInterest = new decimal_js_1.default(acc.supplyInterest).add(supplyInterest.toString()).toString();
90
- if (assetData.supplyIncentives) {
91
- for (const supplyIncentive of assetData.supplyIncentives) {
92
- const incentiveInterest = (0, staking_1.calculateInterestEarned)(amount, supplyIncentive.apy, 'year', true);
93
- acc.incentiveUsd = new decimal_js_1.default(acc.incentiveUsd).add(incentiveInterest).toString();
94
- }
100
+ const supplyIncentives = mergeScopedIncentives(assetData.supplyIncentives, assetData.spokeSupplyIncentives, assetData.hubSupplyIncentives);
101
+ for (const supplyIncentive of supplyIncentives) {
102
+ const incentiveInterest = (0, staking_1.calculateInterestEarned)(amount, supplyIncentive.apy, 'year', true);
103
+ acc.incentiveUsd = new decimal_js_1.default(acc.incentiveUsd).add(incentiveInterest).toString();
95
104
  }
96
105
  }
97
106
  if (usedAsset.isBorrowed) {
@@ -104,11 +113,10 @@ const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
104
113
  const userBorrowRate = (0, moneymarket_1.aprToApy)(userBorrowApr.toString());
105
114
  const borrowInterest = (0, staking_1.calculateInterestEarned)(amount, userBorrowRate, 'year', true);
106
115
  acc.borrowInterest = new decimal_js_1.default(acc.borrowInterest).sub(borrowInterest.toString()).toString();
107
- if (assetData.borrowIncentives) {
108
- for (const borrowIncentive of assetData.borrowIncentives) {
109
- const incentiveInterest = (0, staking_1.calculateInterestEarned)(amount, borrowIncentive.apy, 'year', true);
110
- acc.incentiveUsd = new decimal_js_1.default(acc.incentiveUsd).add(incentiveInterest).toString();
111
- }
116
+ const borrowIncentives = mergeScopedIncentives(assetData.borrowIncentives, assetData.spokeBorrowIncentives, assetData.hubBorrowIncentives);
117
+ for (const borrowIncentive of borrowIncentives) {
118
+ const incentiveInterest = (0, staking_1.calculateInterestEarned)(amount, borrowIncentive.apy, 'year', true);
119
+ acc.incentiveUsd = new decimal_js_1.default(acc.incentiveUsd).add(incentiveInterest).toString();
112
120
  }
113
121
  }
114
122
  return acc;
@@ -108,7 +108,8 @@ export interface AaveV4ReserveAssetData {
108
108
  * Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
109
109
  * - spoke* → spoke supply/borrow (Create page + dashboard market table)
110
110
  * - hub* → hub supply/borrow (Lend page)
111
- * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
111
+ * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only; calculateNetApyAaveV4 merges
112
+ * these scope-specific arrays back in so net APY reflects applicable Merkl rewards too.
112
113
  */
113
114
  spokeSupplyIncentives?: IncentiveData[];
114
115
  spokeBorrowIncentives?: IncentiveData[];
@@ -67,6 +67,16 @@ export const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
67
67
  const riskPremiumBps = numerator.div(coveredDebt);
68
68
  return riskPremiumBps.toNumber();
69
69
  };
70
+ /**
71
+ * `spokeXIncentives`/`hubXIncentives` are each the intrinsic `base` list with at most one Merkl
72
+ * reward appended (see attachAaveV4MerklIncentives). Both scopes can apply to the same position at
73
+ * once (spoke-specific + hub-wide), so the full applicable set is base + whatever each scope appended.
74
+ */
75
+ const mergeScopedIncentives = (base = [], spokeScoped, hubScoped) => [
76
+ ...base,
77
+ ...(spokeScoped ? spokeScoped.slice(base.length) : []),
78
+ ...(hubScoped ? hubScoped.slice(base.length) : []),
79
+ ];
70
80
  export const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
71
81
  const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, assetsData);
72
82
  const riskPremiumFraction = new Dec(riskPremiumBps).div(10000);
@@ -80,11 +90,10 @@ export const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
80
90
  acc.suppliedUsd = new Dec(acc.suppliedUsd).add(amount).toString();
81
91
  const supplyInterest = calculateInterestEarned(amount, assetData.supplyRate, 'year', true);
82
92
  acc.supplyInterest = new Dec(acc.supplyInterest).add(supplyInterest.toString()).toString();
83
- if (assetData.supplyIncentives) {
84
- for (const supplyIncentive of assetData.supplyIncentives) {
85
- const incentiveInterest = calculateInterestEarned(amount, supplyIncentive.apy, 'year', true);
86
- acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
87
- }
93
+ const supplyIncentives = mergeScopedIncentives(assetData.supplyIncentives, assetData.spokeSupplyIncentives, assetData.hubSupplyIncentives);
94
+ for (const supplyIncentive of supplyIncentives) {
95
+ const incentiveInterest = calculateInterestEarned(amount, supplyIncentive.apy, 'year', true);
96
+ acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
88
97
  }
89
98
  }
90
99
  if (usedAsset.isBorrowed) {
@@ -97,11 +106,10 @@ export const calculateNetApyAaveV4 = ({ usedAssets, assetsData, }) => {
97
106
  const userBorrowRate = aprToApy(userBorrowApr.toString());
98
107
  const borrowInterest = calculateInterestEarned(amount, userBorrowRate, 'year', true);
99
108
  acc.borrowInterest = new Dec(acc.borrowInterest).sub(borrowInterest.toString()).toString();
100
- if (assetData.borrowIncentives) {
101
- for (const borrowIncentive of assetData.borrowIncentives) {
102
- const incentiveInterest = calculateInterestEarned(amount, borrowIncentive.apy, 'year', true);
103
- acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
104
- }
109
+ const borrowIncentives = mergeScopedIncentives(assetData.borrowIncentives, assetData.spokeBorrowIncentives, assetData.hubBorrowIncentives);
110
+ for (const borrowIncentive of borrowIncentives) {
111
+ const incentiveInterest = calculateInterestEarned(amount, borrowIncentive.apy, 'year', true);
112
+ acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
105
113
  }
106
114
  }
107
115
  return acc;
@@ -108,7 +108,8 @@ export interface AaveV4ReserveAssetData {
108
108
  * Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
109
109
  * - spoke* → spoke supply/borrow (Create page + dashboard market table)
110
110
  * - hub* → hub supply/borrow (Lend page)
111
- * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
111
+ * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only; calculateNetApyAaveV4 merges
112
+ * these scope-specific arrays back in so net APY reflects applicable Merkl rewards too.
112
113
  */
113
114
  spokeSupplyIncentives?: IncentiveData[];
114
115
  spokeBorrowIncentives?: IncentiveData[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defisaver/positions-sdk",
3
- "version": "2.1.123",
3
+ "version": "2.1.124",
4
4
  "description": "",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
@@ -16,6 +16,7 @@ import {
16
16
  AaveV4UsedReserveAsset,
17
17
  AaveV4UsedReserveAssets,
18
18
  EthereumProvider,
19
+ IncentiveData,
19
20
  LeverageType,
20
21
  NetworkNumber,
21
22
  } from '../../types';
@@ -90,6 +91,17 @@ export const calcUserRiskPremiumBps = (usedAssets: AaveV4UsedReserveAssets, asse
90
91
  return riskPremiumBps.toNumber();
91
92
  };
92
93
 
94
+ /**
95
+ * `spokeXIncentives`/`hubXIncentives` are each the intrinsic `base` list with at most one Merkl
96
+ * reward appended (see attachAaveV4MerklIncentives). Both scopes can apply to the same position at
97
+ * once (spoke-specific + hub-wide), so the full applicable set is base + whatever each scope appended.
98
+ */
99
+ const mergeScopedIncentives = (base: IncentiveData[] = [], spokeScoped?: IncentiveData[], hubScoped?: IncentiveData[]): IncentiveData[] => [
100
+ ...base,
101
+ ...(spokeScoped ? spokeScoped.slice(base.length) : []),
102
+ ...(hubScoped ? hubScoped.slice(base.length) : []),
103
+ ];
104
+
93
105
  export const calculateNetApyAaveV4 = ({
94
106
  usedAssets,
95
107
  assetsData,
@@ -111,11 +123,10 @@ export const calculateNetApyAaveV4 = ({
111
123
  const supplyInterest = calculateInterestEarned(amount, assetData.supplyRate, 'year', true);
112
124
  acc.supplyInterest = new Dec(acc.supplyInterest).add(supplyInterest.toString()).toString();
113
125
 
114
- if (assetData.supplyIncentives) {
115
- for (const supplyIncentive of assetData.supplyIncentives) {
116
- const incentiveInterest = calculateInterestEarned(amount, supplyIncentive.apy, 'year', true);
117
- acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
118
- }
126
+ const supplyIncentives = mergeScopedIncentives(assetData.supplyIncentives, assetData.spokeSupplyIncentives, assetData.hubSupplyIncentives);
127
+ for (const supplyIncentive of supplyIncentives) {
128
+ const incentiveInterest = calculateInterestEarned(amount, supplyIncentive.apy, 'year', true);
129
+ acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
119
130
  }
120
131
  }
121
132
 
@@ -130,11 +141,10 @@ export const calculateNetApyAaveV4 = ({
130
141
  const borrowInterest = calculateInterestEarned(amount, userBorrowRate, 'year', true);
131
142
  acc.borrowInterest = new Dec(acc.borrowInterest).sub(borrowInterest.toString()).toString();
132
143
 
133
- if (assetData.borrowIncentives) {
134
- for (const borrowIncentive of assetData.borrowIncentives) {
135
- const incentiveInterest = calculateInterestEarned(amount, borrowIncentive.apy, 'year', true);
136
- acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
137
- }
144
+ const borrowIncentives = mergeScopedIncentives(assetData.borrowIncentives, assetData.spokeBorrowIncentives, assetData.hubBorrowIncentives);
145
+ for (const borrowIncentive of borrowIncentives) {
146
+ const incentiveInterest = calculateInterestEarned(amount, borrowIncentive.apy, 'year', true);
147
+ acc.incentiveUsd = new Dec(acc.incentiveUsd).add(incentiveInterest).toString();
138
148
  }
139
149
  }
140
150
 
@@ -119,7 +119,8 @@ export interface AaveV4ReserveAssetData {
119
119
  * Intrinsic incentives pre-combined with scope-specific Merkl rewards, ready to render per surface:
120
120
  * - spoke* → spoke supply/borrow (Create page + dashboard market table)
121
121
  * - hub* → hub supply/borrow (Lend page)
122
- * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only so the net-APY calc is unaffected.
122
+ * `supplyIncentives`/`borrowIncentives` above remain intrinsic-only; calculateNetApyAaveV4 merges
123
+ * these scope-specific arrays back in so net APY reflects applicable Merkl rewards too.
123
124
  */
124
125
  spokeSupplyIncentives?: IncentiveData[];
125
126
  spokeBorrowIncentives?: IncentiveData[];