@defisaver/positions-sdk 2.1.79-aave-v4-4-dev → 2.1.79-aave-v4-6-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/aaveV4/index.js +3 -58
- package/cjs/aaveV4/lend.js +0 -1
- package/cjs/helpers/aaveV4Helpers/index.d.ts +5 -0
- package/cjs/helpers/aaveV4Helpers/index.js +72 -1
- package/esm/aaveV4/index.js +3 -58
- package/esm/aaveV4/lend.js +0 -1
- package/esm/helpers/aaveV4Helpers/index.d.ts +5 -0
- package/esm/helpers/aaveV4Helpers/index.js +70 -1
- package/package.json +1 -1
- package/src/aaveV4/index.ts +3 -73
- package/src/aaveV4/lend.ts +0 -1
- package/src/helpers/aaveV4Helpers/index.ts +98 -1
package/cjs/aaveV4/index.js
CHANGED
|
@@ -79,59 +79,6 @@ const fetchHubData = (viewContract, hubAddress) => __awaiter(void 0, void 0, voi
|
|
|
79
79
|
}, {}),
|
|
80
80
|
};
|
|
81
81
|
});
|
|
82
|
-
// TODO AaveV4: Will be used for after values, onchain data is available when fetching position data
|
|
83
|
-
const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
|
|
84
|
-
const collaterals = [];
|
|
85
|
-
const debts = [];
|
|
86
|
-
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
87
|
-
const reserveData = assetsData[identifier];
|
|
88
|
-
if (!reserveData)
|
|
89
|
-
return;
|
|
90
|
-
const borrowedUsdDec = new decimal_js_1.default(asset.borrowedUsd || '0');
|
|
91
|
-
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
92
|
-
debts.push({ valueUsd: borrowedUsdDec });
|
|
93
|
-
}
|
|
94
|
-
const suppliedUsdDec = new decimal_js_1.default(asset.suppliedUsd || '0');
|
|
95
|
-
const isActiveCollateral = asset.collateral
|
|
96
|
-
&& asset.isSupplied
|
|
97
|
-
&& asset.collateralFactor > 0
|
|
98
|
-
&& suppliedUsdDec.gt(0);
|
|
99
|
-
if (isActiveCollateral) {
|
|
100
|
-
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
101
|
-
const riskBps = new decimal_js_1.default(reserveData.collateralRisk).mul(10000).toNumber();
|
|
102
|
-
collaterals.push({
|
|
103
|
-
riskBps,
|
|
104
|
-
valueUsd: suppliedUsdDec,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new decimal_js_1.default(0));
|
|
109
|
-
if (totalDebtUsd.lte(0)) {
|
|
110
|
-
return 0;
|
|
111
|
-
}
|
|
112
|
-
// sort by risk ASC, value DESC
|
|
113
|
-
collaterals.sort((a, b) => {
|
|
114
|
-
if (a.riskBps !== b.riskBps)
|
|
115
|
-
return a.riskBps - b.riskBps;
|
|
116
|
-
return b.valueUsd.comparedTo(a.valueUsd);
|
|
117
|
-
});
|
|
118
|
-
let debtLeftToCover = totalDebtUsd;
|
|
119
|
-
let numerator = new decimal_js_1.default(0); // sum(coveredUsd * riskBps)
|
|
120
|
-
let coveredDebt = new decimal_js_1.default(0); // sum(coveredUsd)
|
|
121
|
-
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
122
|
-
if (debtLeftToCover.lte(0))
|
|
123
|
-
return;
|
|
124
|
-
const coveredUsd = decimal_js_1.default.min(valueUsd, debtLeftToCover);
|
|
125
|
-
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
126
|
-
coveredDebt = coveredDebt.add(coveredUsd);
|
|
127
|
-
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
128
|
-
});
|
|
129
|
-
if (coveredDebt.lte(0)) {
|
|
130
|
-
return 0;
|
|
131
|
-
}
|
|
132
|
-
const riskPremiumBps = numerator.div(coveredDebt);
|
|
133
|
-
return riskPremiumBps.toNumber();
|
|
134
|
-
};
|
|
135
82
|
const formatReserveAsset = (reserveAsset, hubAsset, reserveId, oracleDecimals, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
136
83
|
var _a, _b, _c, _d, _e, _f;
|
|
137
84
|
const assetInfo = (0, tokens_1.getAssetInfoByAddress)(reserveAsset.underlying, network);
|
|
@@ -181,10 +128,8 @@ const formatReserveAsset = (reserveAsset, hubAsset, reserveId, oracleDecimals, n
|
|
|
181
128
|
const liquidityFee = new decimal_js_1.default(hubAsset.liquidityFee.toString()).div(new decimal_js_1.default(10).pow(4));
|
|
182
129
|
const totalDrawnShares = new decimal_js_1.default(hubAsset.totalDrawnShares.toString());
|
|
183
130
|
const totalPremiumShares = new decimal_js_1.default(hubAsset.totalPremiumShares.toString());
|
|
184
|
-
// TODO JK@JK premiumMultiplier should be added to supplyApr calculation (.mul(premiumMultiplier)
|
|
185
|
-
// TODO JKJ@JK when we confirm that this is the right way to calculate it
|
|
186
131
|
const premiumMultiplier = totalDrawnShares.isZero() ? new decimal_js_1.default(1) : totalDrawnShares.add(totalPremiumShares).div(totalDrawnShares);
|
|
187
|
-
const supplyApr = borrowApr.mul(hubUtilization).mul(new decimal_js_1.default(1).minus(liquidityFee));
|
|
132
|
+
const supplyApr = borrowApr.mul(hubUtilization).mul(premiumMultiplier).mul(new decimal_js_1.default(1).minus(liquidityFee));
|
|
188
133
|
return ({
|
|
189
134
|
symbol,
|
|
190
135
|
underlying: reserveAsset.underlying,
|
|
@@ -251,7 +196,7 @@ function _getAaveV4AccountData(provider_1, network_1, spokeData_1, address_1) {
|
|
|
251
196
|
const viewContract = (0, contracts_1.AaveV4ViewContractViem)(provider, network, blockNumber);
|
|
252
197
|
const loanData = yield viewContract.read.getLoanData([spokeData.address, address]);
|
|
253
198
|
const healthFactorFromContract = new decimal_js_1.default(loanData.healthFactor.toString());
|
|
254
|
-
const healthFactor = (0, utils_1.isMaxUint)(healthFactorFromContract.toString()) ? '
|
|
199
|
+
const healthFactor = (0, utils_1.isMaxUint)(healthFactorFromContract.toString()) ? 'Infinity' : healthFactorFromContract.div(1e18).toString();
|
|
255
200
|
const usedAssets = loanData.reserves.reduce((acc, usedReserveAsset) => {
|
|
256
201
|
const identifier = `${(0, utils_1.wethToEth)((0, tokens_1.getAssetInfoByAddress)(usedReserveAsset.underlying, network).symbol)}-${+usedReserveAsset.reserveId.toString()}`;
|
|
257
202
|
const reserveData = spokeData.assetsData[identifier];
|
|
@@ -286,7 +231,7 @@ function _getAaveV4AccountData(provider_1, network_1, spokeData_1, address_1) {
|
|
|
286
231
|
network,
|
|
287
232
|
useUserCollateralFactor: true,
|
|
288
233
|
});
|
|
289
|
-
const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, spokeData.assetsData);
|
|
234
|
+
const riskPremiumBps = (0, aaveV4Helpers_1.calcUserRiskPremiumBps)(usedAssets, spokeData.assetsData);
|
|
290
235
|
return Object.assign(Object.assign({}, aggregated), { usedAssets,
|
|
291
236
|
healthFactor,
|
|
292
237
|
riskPremiumBps });
|
package/cjs/aaveV4/lend.js
CHANGED
|
@@ -57,7 +57,6 @@ const aaveV4GetTokenizedHubKey = (hubNameOrKey) => {
|
|
|
57
57
|
if (!hubNameOrKey)
|
|
58
58
|
return null;
|
|
59
59
|
const normalized = hubNameOrKey.trim().toUpperCase();
|
|
60
|
-
// TODO AaveV4 Maybe turn into constants
|
|
61
60
|
if (normalized === 'CORE' || normalized === 'CORE HUB')
|
|
62
61
|
return 'CORE';
|
|
63
62
|
if (normalized === 'PLUS' || normalized === 'PLUS HUB')
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { AaveV4AggregatedPositionData, AaveV4AssetsData, AaveV4ReserveAssetData, AaveV4UsedReserveAsset, AaveV4UsedReserveAssets, LeverageType, NetworkNumber } from '../../types';
|
|
2
|
+
export declare const calcUserRiskPremiumBps: (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData) => number;
|
|
3
|
+
export declare const getApyAfterValuesEstimation: (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData) => Record<string, {
|
|
4
|
+
borrowRate: string;
|
|
5
|
+
supplyRate: string;
|
|
6
|
+
}>;
|
|
2
7
|
export declare const aaveV4GetCollateralFactor: (assetData: AaveV4ReserveAssetData, usedAssetData: AaveV4UsedReserveAsset, useUserCollateralFactor?: boolean) => number;
|
|
3
8
|
export declare const isLeveragedPosAaveV4: (usedAssets: AaveV4UsedReserveAssets, dustLimit?: number) => {
|
|
4
9
|
leveragedType: LeverageType;
|
|
@@ -3,10 +3,81 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.aaveV4GetAggregatedPositionData = exports.isLeveragedPosAaveV4 = exports.aaveV4GetCollateralFactor = void 0;
|
|
6
|
+
exports.aaveV4GetAggregatedPositionData = exports.isLeveragedPosAaveV4 = exports.aaveV4GetCollateralFactor = exports.getApyAfterValuesEstimation = exports.calcUserRiskPremiumBps = void 0;
|
|
7
7
|
const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
8
8
|
const moneymarket_1 = require("../../moneymarket");
|
|
9
9
|
const types_1 = require("../../types");
|
|
10
|
+
const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
|
|
11
|
+
const collaterals = [];
|
|
12
|
+
const debts = [];
|
|
13
|
+
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
14
|
+
const reserveData = assetsData[identifier];
|
|
15
|
+
if (!reserveData)
|
|
16
|
+
return;
|
|
17
|
+
const borrowedUsdDec = new decimal_js_1.default(asset.borrowedUsd || '0');
|
|
18
|
+
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
19
|
+
debts.push({ valueUsd: borrowedUsdDec });
|
|
20
|
+
}
|
|
21
|
+
const suppliedUsdDec = new decimal_js_1.default(asset.suppliedUsd || '0');
|
|
22
|
+
const isActiveCollateral = asset.collateral
|
|
23
|
+
&& asset.isSupplied
|
|
24
|
+
&& asset.collateralFactor > 0
|
|
25
|
+
&& suppliedUsdDec.gt(0);
|
|
26
|
+
if (isActiveCollateral) {
|
|
27
|
+
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
28
|
+
const riskBps = new decimal_js_1.default(reserveData.collateralRisk).mul(10000).toNumber();
|
|
29
|
+
collaterals.push({
|
|
30
|
+
riskBps,
|
|
31
|
+
valueUsd: suppliedUsdDec,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new decimal_js_1.default(0));
|
|
36
|
+
if (totalDebtUsd.lte(0)) {
|
|
37
|
+
return 0;
|
|
38
|
+
}
|
|
39
|
+
// sort by risk ASC, value DESC
|
|
40
|
+
collaterals.sort((a, b) => {
|
|
41
|
+
if (a.riskBps !== b.riskBps)
|
|
42
|
+
return a.riskBps - b.riskBps;
|
|
43
|
+
return b.valueUsd.comparedTo(a.valueUsd);
|
|
44
|
+
});
|
|
45
|
+
let debtLeftToCover = totalDebtUsd;
|
|
46
|
+
let numerator = new decimal_js_1.default(0); // sum(coveredUsd * riskBps)
|
|
47
|
+
let coveredDebt = new decimal_js_1.default(0); // sum(coveredUsd)
|
|
48
|
+
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
49
|
+
if (debtLeftToCover.lte(0))
|
|
50
|
+
return;
|
|
51
|
+
const coveredUsd = decimal_js_1.default.min(valueUsd, debtLeftToCover);
|
|
52
|
+
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
53
|
+
coveredDebt = coveredDebt.add(coveredUsd);
|
|
54
|
+
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
55
|
+
});
|
|
56
|
+
if (coveredDebt.lte(0)) {
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
59
|
+
const riskPremiumBps = numerator.div(coveredDebt);
|
|
60
|
+
return riskPremiumBps.toNumber();
|
|
61
|
+
};
|
|
62
|
+
exports.calcUserRiskPremiumBps = calcUserRiskPremiumBps;
|
|
63
|
+
const getApyAfterValuesEstimation = (usedAssets, assetsData) => {
|
|
64
|
+
const riskPremiumBps = (0, exports.calcUserRiskPremiumBps)(usedAssets, assetsData);
|
|
65
|
+
const riskPremiumFraction = new decimal_js_1.default(riskPremiumBps).div(10000); // bps to fraction
|
|
66
|
+
const result = {};
|
|
67
|
+
Object.entries(assetsData).forEach(([identifier, assetData]) => {
|
|
68
|
+
const drawnRate = new decimal_js_1.default(assetData.drawnRate);
|
|
69
|
+
const baseBorrowApr = drawnRate.mul(100);
|
|
70
|
+
// finalBorrowRate = baseBorrowRate * (1 + riskPremiumFraction)
|
|
71
|
+
const userBorrowApr = baseBorrowApr.mul(new decimal_js_1.default(1).add(riskPremiumFraction));
|
|
72
|
+
result[identifier] = {
|
|
73
|
+
borrowRate: (0, moneymarket_1.aprToApy)(userBorrowApr.toString()),
|
|
74
|
+
// Supply rate is market-level (not user-specific), use existing value
|
|
75
|
+
supplyRate: assetData.supplyRate,
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return result;
|
|
79
|
+
};
|
|
80
|
+
exports.getApyAfterValuesEstimation = getApyAfterValuesEstimation;
|
|
10
81
|
const aaveV4GetCollateralFactor = (assetData, usedAssetData, useUserCollateralFactor = false) => (useUserCollateralFactor ? usedAssetData.collateralFactor : assetData.collateralFactor);
|
|
11
82
|
exports.aaveV4GetCollateralFactor = aaveV4GetCollateralFactor;
|
|
12
83
|
const isLeveragedPosAaveV4 = (usedAssets, dustLimit = 5) => {
|
package/esm/aaveV4/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { IncentiveKind, } from '../types';
|
|
|
14
14
|
import { AaveV4ViewContractViem } from '../contracts';
|
|
15
15
|
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
16
16
|
import { isMaxUint, wethToEth } from '../services/utils';
|
|
17
|
-
import { aaveV4GetAggregatedPositionData } from '../helpers/aaveV4Helpers';
|
|
17
|
+
import { aaveV4GetAggregatedPositionData, calcUserRiskPremiumBps } from '../helpers/aaveV4Helpers';
|
|
18
18
|
import { getAaveV4HubByAddress } from '../markets/aaveV4';
|
|
19
19
|
import { aprToApy } from '../moneymarket';
|
|
20
20
|
export * as lend from './lend';
|
|
@@ -36,59 +36,6 @@ const fetchHubData = (viewContract, hubAddress) => __awaiter(void 0, void 0, voi
|
|
|
36
36
|
}, {}),
|
|
37
37
|
};
|
|
38
38
|
});
|
|
39
|
-
// TODO AaveV4: Will be used for after values, onchain data is available when fetching position data
|
|
40
|
-
const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
|
|
41
|
-
const collaterals = [];
|
|
42
|
-
const debts = [];
|
|
43
|
-
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
44
|
-
const reserveData = assetsData[identifier];
|
|
45
|
-
if (!reserveData)
|
|
46
|
-
return;
|
|
47
|
-
const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
|
|
48
|
-
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
49
|
-
debts.push({ valueUsd: borrowedUsdDec });
|
|
50
|
-
}
|
|
51
|
-
const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
|
|
52
|
-
const isActiveCollateral = asset.collateral
|
|
53
|
-
&& asset.isSupplied
|
|
54
|
-
&& asset.collateralFactor > 0
|
|
55
|
-
&& suppliedUsdDec.gt(0);
|
|
56
|
-
if (isActiveCollateral) {
|
|
57
|
-
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
58
|
-
const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
|
|
59
|
-
collaterals.push({
|
|
60
|
-
riskBps,
|
|
61
|
-
valueUsd: suppliedUsdDec,
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
|
|
66
|
-
if (totalDebtUsd.lte(0)) {
|
|
67
|
-
return 0;
|
|
68
|
-
}
|
|
69
|
-
// sort by risk ASC, value DESC
|
|
70
|
-
collaterals.sort((a, b) => {
|
|
71
|
-
if (a.riskBps !== b.riskBps)
|
|
72
|
-
return a.riskBps - b.riskBps;
|
|
73
|
-
return b.valueUsd.comparedTo(a.valueUsd);
|
|
74
|
-
});
|
|
75
|
-
let debtLeftToCover = totalDebtUsd;
|
|
76
|
-
let numerator = new Dec(0); // sum(coveredUsd * riskBps)
|
|
77
|
-
let coveredDebt = new Dec(0); // sum(coveredUsd)
|
|
78
|
-
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
79
|
-
if (debtLeftToCover.lte(0))
|
|
80
|
-
return;
|
|
81
|
-
const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
|
|
82
|
-
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
83
|
-
coveredDebt = coveredDebt.add(coveredUsd);
|
|
84
|
-
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
85
|
-
});
|
|
86
|
-
if (coveredDebt.lte(0)) {
|
|
87
|
-
return 0;
|
|
88
|
-
}
|
|
89
|
-
const riskPremiumBps = numerator.div(coveredDebt);
|
|
90
|
-
return riskPremiumBps.toNumber();
|
|
91
|
-
};
|
|
92
39
|
const formatReserveAsset = (reserveAsset, hubAsset, reserveId, oracleDecimals, network) => __awaiter(void 0, void 0, void 0, function* () {
|
|
93
40
|
var _a, _b, _c, _d, _e, _f;
|
|
94
41
|
const assetInfo = getAssetInfoByAddress(reserveAsset.underlying, network);
|
|
@@ -138,10 +85,8 @@ const formatReserveAsset = (reserveAsset, hubAsset, reserveId, oracleDecimals, n
|
|
|
138
85
|
const liquidityFee = new Dec(hubAsset.liquidityFee.toString()).div(new Dec(10).pow(4));
|
|
139
86
|
const totalDrawnShares = new Dec(hubAsset.totalDrawnShares.toString());
|
|
140
87
|
const totalPremiumShares = new Dec(hubAsset.totalPremiumShares.toString());
|
|
141
|
-
// TODO JK@JK premiumMultiplier should be added to supplyApr calculation (.mul(premiumMultiplier)
|
|
142
|
-
// TODO JKJ@JK when we confirm that this is the right way to calculate it
|
|
143
88
|
const premiumMultiplier = totalDrawnShares.isZero() ? new Dec(1) : totalDrawnShares.add(totalPremiumShares).div(totalDrawnShares);
|
|
144
|
-
const supplyApr = borrowApr.mul(hubUtilization).mul(new Dec(1).minus(liquidityFee));
|
|
89
|
+
const supplyApr = borrowApr.mul(hubUtilization).mul(premiumMultiplier).mul(new Dec(1).minus(liquidityFee));
|
|
145
90
|
return ({
|
|
146
91
|
symbol,
|
|
147
92
|
underlying: reserveAsset.underlying,
|
|
@@ -208,7 +153,7 @@ export function _getAaveV4AccountData(provider_1, network_1, spokeData_1, addres
|
|
|
208
153
|
const viewContract = AaveV4ViewContractViem(provider, network, blockNumber);
|
|
209
154
|
const loanData = yield viewContract.read.getLoanData([spokeData.address, address]);
|
|
210
155
|
const healthFactorFromContract = new Dec(loanData.healthFactor.toString());
|
|
211
|
-
const healthFactor = isMaxUint(healthFactorFromContract.toString()) ? '
|
|
156
|
+
const healthFactor = isMaxUint(healthFactorFromContract.toString()) ? 'Infinity' : healthFactorFromContract.div(1e18).toString();
|
|
212
157
|
const usedAssets = loanData.reserves.reduce((acc, usedReserveAsset) => {
|
|
213
158
|
const identifier = `${wethToEth(getAssetInfoByAddress(usedReserveAsset.underlying, network).symbol)}-${+usedReserveAsset.reserveId.toString()}`;
|
|
214
159
|
const reserveData = spokeData.assetsData[identifier];
|
package/esm/aaveV4/lend.js
CHANGED
|
@@ -53,7 +53,6 @@ export const aaveV4GetTokenizedHubKey = (hubNameOrKey) => {
|
|
|
53
53
|
if (!hubNameOrKey)
|
|
54
54
|
return null;
|
|
55
55
|
const normalized = hubNameOrKey.trim().toUpperCase();
|
|
56
|
-
// TODO AaveV4 Maybe turn into constants
|
|
57
56
|
if (normalized === 'CORE' || normalized === 'CORE HUB')
|
|
58
57
|
return 'CORE';
|
|
59
58
|
if (normalized === 'PLUS' || normalized === 'PLUS HUB')
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { AaveV4AggregatedPositionData, AaveV4AssetsData, AaveV4ReserveAssetData, AaveV4UsedReserveAsset, AaveV4UsedReserveAssets, LeverageType, NetworkNumber } from '../../types';
|
|
2
|
+
export declare const calcUserRiskPremiumBps: (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData) => number;
|
|
3
|
+
export declare const getApyAfterValuesEstimation: (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData) => Record<string, {
|
|
4
|
+
borrowRate: string;
|
|
5
|
+
supplyRate: string;
|
|
6
|
+
}>;
|
|
2
7
|
export declare const aaveV4GetCollateralFactor: (assetData: AaveV4ReserveAssetData, usedAssetData: AaveV4UsedReserveAsset, useUserCollateralFactor?: boolean) => number;
|
|
3
8
|
export declare const isLeveragedPosAaveV4: (usedAssets: AaveV4UsedReserveAssets, dustLimit?: number) => {
|
|
4
9
|
leveragedType: LeverageType;
|
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
import Dec from 'decimal.js';
|
|
2
|
-
import { calcLeverageLiqPrice, getAssetsTotal, STABLE_ASSETS } from '../../moneymarket';
|
|
2
|
+
import { aprToApy, calcLeverageLiqPrice, getAssetsTotal, STABLE_ASSETS, } from '../../moneymarket';
|
|
3
3
|
import { LeverageType, } from '../../types';
|
|
4
|
+
export const calcUserRiskPremiumBps = (usedAssets, assetsData) => {
|
|
5
|
+
const collaterals = [];
|
|
6
|
+
const debts = [];
|
|
7
|
+
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
8
|
+
const reserveData = assetsData[identifier];
|
|
9
|
+
if (!reserveData)
|
|
10
|
+
return;
|
|
11
|
+
const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
|
|
12
|
+
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
13
|
+
debts.push({ valueUsd: borrowedUsdDec });
|
|
14
|
+
}
|
|
15
|
+
const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
|
|
16
|
+
const isActiveCollateral = asset.collateral
|
|
17
|
+
&& asset.isSupplied
|
|
18
|
+
&& asset.collateralFactor > 0
|
|
19
|
+
&& suppliedUsdDec.gt(0);
|
|
20
|
+
if (isActiveCollateral) {
|
|
21
|
+
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
22
|
+
const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
|
|
23
|
+
collaterals.push({
|
|
24
|
+
riskBps,
|
|
25
|
+
valueUsd: suppliedUsdDec,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
|
|
30
|
+
if (totalDebtUsd.lte(0)) {
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
// sort by risk ASC, value DESC
|
|
34
|
+
collaterals.sort((a, b) => {
|
|
35
|
+
if (a.riskBps !== b.riskBps)
|
|
36
|
+
return a.riskBps - b.riskBps;
|
|
37
|
+
return b.valueUsd.comparedTo(a.valueUsd);
|
|
38
|
+
});
|
|
39
|
+
let debtLeftToCover = totalDebtUsd;
|
|
40
|
+
let numerator = new Dec(0); // sum(coveredUsd * riskBps)
|
|
41
|
+
let coveredDebt = new Dec(0); // sum(coveredUsd)
|
|
42
|
+
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
43
|
+
if (debtLeftToCover.lte(0))
|
|
44
|
+
return;
|
|
45
|
+
const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
|
|
46
|
+
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
47
|
+
coveredDebt = coveredDebt.add(coveredUsd);
|
|
48
|
+
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
49
|
+
});
|
|
50
|
+
if (coveredDebt.lte(0)) {
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
const riskPremiumBps = numerator.div(coveredDebt);
|
|
54
|
+
return riskPremiumBps.toNumber();
|
|
55
|
+
};
|
|
56
|
+
export const getApyAfterValuesEstimation = (usedAssets, assetsData) => {
|
|
57
|
+
const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, assetsData);
|
|
58
|
+
const riskPremiumFraction = new Dec(riskPremiumBps).div(10000); // bps to fraction
|
|
59
|
+
const result = {};
|
|
60
|
+
Object.entries(assetsData).forEach(([identifier, assetData]) => {
|
|
61
|
+
const drawnRate = new Dec(assetData.drawnRate);
|
|
62
|
+
const baseBorrowApr = drawnRate.mul(100);
|
|
63
|
+
// finalBorrowRate = baseBorrowRate * (1 + riskPremiumFraction)
|
|
64
|
+
const userBorrowApr = baseBorrowApr.mul(new Dec(1).add(riskPremiumFraction));
|
|
65
|
+
result[identifier] = {
|
|
66
|
+
borrowRate: aprToApy(userBorrowApr.toString()),
|
|
67
|
+
// Supply rate is market-level (not user-specific), use existing value
|
|
68
|
+
supplyRate: assetData.supplyRate,
|
|
69
|
+
};
|
|
70
|
+
});
|
|
71
|
+
return result;
|
|
72
|
+
};
|
|
4
73
|
export const aaveV4GetCollateralFactor = (assetData, usedAssetData, useUserCollateralFactor = false) => (useUserCollateralFactor ? usedAssetData.collateralFactor : assetData.collateralFactor);
|
|
5
74
|
export const isLeveragedPosAaveV4 = (usedAssets, dustLimit = 5) => {
|
|
6
75
|
let borrowUnstable = 0;
|
package/package.json
CHANGED
package/src/aaveV4/index.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
AaveV4SpokeData,
|
|
12
12
|
AaveV4SpokeInfo,
|
|
13
13
|
AaveV4UsedReserveAssets,
|
|
14
|
-
AaveV4AssetsData,
|
|
15
14
|
EthAddress,
|
|
16
15
|
EthereumProvider,
|
|
17
16
|
IncentiveData,
|
|
@@ -21,7 +20,7 @@ import {
|
|
|
21
20
|
import { AaveV4ViewContractViem } from '../contracts';
|
|
22
21
|
import { getStakingApy, STAKING_ASSETS } from '../staking';
|
|
23
22
|
import { isMaxUint, wethToEth } from '../services/utils';
|
|
24
|
-
import { aaveV4GetAggregatedPositionData } from '../helpers/aaveV4Helpers';
|
|
23
|
+
import { aaveV4GetAggregatedPositionData, calcUserRiskPremiumBps } from '../helpers/aaveV4Helpers';
|
|
25
24
|
import { getAaveV4HubByAddress } from '../markets/aaveV4';
|
|
26
25
|
import { aprToApy } from '../moneymarket';
|
|
27
26
|
|
|
@@ -46,73 +45,6 @@ const fetchHubData = async (viewContract: ReturnType<typeof AaveV4ViewContractVi
|
|
|
46
45
|
};
|
|
47
46
|
};
|
|
48
47
|
|
|
49
|
-
// TODO AaveV4: Will be used for after values, onchain data is available when fetching position data
|
|
50
|
-
const calcUserRiskPremiumBps = (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData): number => {
|
|
51
|
-
type CollateralInfo = { riskBps: number; valueUsd: Dec };
|
|
52
|
-
type DebtInfo = { valueUsd: Dec };
|
|
53
|
-
|
|
54
|
-
const collaterals: CollateralInfo[] = [];
|
|
55
|
-
const debts: DebtInfo[] = [];
|
|
56
|
-
|
|
57
|
-
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
58
|
-
const reserveData = assetsData[identifier];
|
|
59
|
-
if (!reserveData) return;
|
|
60
|
-
|
|
61
|
-
const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
|
|
62
|
-
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
63
|
-
debts.push({ valueUsd: borrowedUsdDec });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
|
|
67
|
-
const isActiveCollateral = asset.collateral
|
|
68
|
-
&& asset.isSupplied
|
|
69
|
-
&& asset.collateralFactor > 0
|
|
70
|
-
&& suppliedUsdDec.gt(0);
|
|
71
|
-
|
|
72
|
-
if (isActiveCollateral) {
|
|
73
|
-
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
74
|
-
const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
|
|
75
|
-
collaterals.push({
|
|
76
|
-
riskBps,
|
|
77
|
-
valueUsd: suppliedUsdDec,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
|
|
83
|
-
|
|
84
|
-
if (totalDebtUsd.lte(0)) {
|
|
85
|
-
return 0;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// sort by risk ASC, value DESC
|
|
89
|
-
collaterals.sort((a, b) => {
|
|
90
|
-
if (a.riskBps !== b.riskBps) return a.riskBps - b.riskBps;
|
|
91
|
-
return b.valueUsd.comparedTo(a.valueUsd);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
let debtLeftToCover = totalDebtUsd;
|
|
95
|
-
let numerator = new Dec(0); // sum(coveredUsd * riskBps)
|
|
96
|
-
let coveredDebt = new Dec(0); // sum(coveredUsd)
|
|
97
|
-
|
|
98
|
-
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
99
|
-
if (debtLeftToCover.lte(0)) return;
|
|
100
|
-
|
|
101
|
-
const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
|
|
102
|
-
|
|
103
|
-
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
104
|
-
coveredDebt = coveredDebt.add(coveredUsd);
|
|
105
|
-
|
|
106
|
-
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
if (coveredDebt.lte(0)) {
|
|
110
|
-
return 0;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const riskPremiumBps = numerator.div(coveredDebt);
|
|
114
|
-
return riskPremiumBps.toNumber();
|
|
115
|
-
};
|
|
116
48
|
|
|
117
49
|
const formatReserveAsset = async (reserveAsset: AaveV4ReserveAssetOnChain, hubAsset: AaveV4HubAssetOnChainData, reserveId: number, oracleDecimals: number, network: NetworkNumber): Promise<AaveV4ReserveAssetData> => {
|
|
118
50
|
const assetInfo = getAssetInfoByAddress(reserveAsset.underlying, network);
|
|
@@ -166,10 +98,8 @@ const formatReserveAsset = async (reserveAsset: AaveV4ReserveAssetOnChain, hubAs
|
|
|
166
98
|
const liquidityFee = new Dec(hubAsset.liquidityFee.toString()).div(new Dec(10).pow(4));
|
|
167
99
|
const totalDrawnShares = new Dec(hubAsset.totalDrawnShares.toString());
|
|
168
100
|
const totalPremiumShares = new Dec(hubAsset.totalPremiumShares.toString());
|
|
169
|
-
// TODO JK@JK premiumMultiplier should be added to supplyApr calculation (.mul(premiumMultiplier)
|
|
170
|
-
// TODO JKJ@JK when we confirm that this is the right way to calculate it
|
|
171
101
|
const premiumMultiplier = totalDrawnShares.isZero() ? new Dec(1) : totalDrawnShares.add(totalPremiumShares).div(totalDrawnShares);
|
|
172
|
-
const supplyApr = borrowApr.mul(hubUtilization).mul(new Dec(1).minus(liquidityFee));
|
|
102
|
+
const supplyApr = borrowApr.mul(hubUtilization).mul(premiumMultiplier).mul(new Dec(1).minus(liquidityFee));
|
|
173
103
|
|
|
174
104
|
return ({
|
|
175
105
|
symbol,
|
|
@@ -240,7 +170,7 @@ export async function _getAaveV4AccountData(provider: Client, network: NetworkNu
|
|
|
240
170
|
const loanData = await viewContract.read.getLoanData([spokeData.address, address]);
|
|
241
171
|
|
|
242
172
|
const healthFactorFromContract = new Dec(loanData.healthFactor.toString());
|
|
243
|
-
const healthFactor = isMaxUint(healthFactorFromContract.toString()) ? '
|
|
173
|
+
const healthFactor = isMaxUint(healthFactorFromContract.toString()) ? 'Infinity' : healthFactorFromContract.div(1e18).toString();
|
|
244
174
|
const usedAssets = loanData.reserves.reduce((acc: AaveV4UsedReserveAssets, usedReserveAsset) => {
|
|
245
175
|
const identifier = `${wethToEth(getAssetInfoByAddress(usedReserveAsset.underlying, network).symbol)}-${+usedReserveAsset.reserveId.toString()}`;
|
|
246
176
|
const reserveData = spokeData.assetsData[identifier];
|
package/src/aaveV4/lend.ts
CHANGED
|
@@ -73,7 +73,6 @@ export const aaveV4GetTokenizedHubKey = (hubNameOrKey?: string | null): AaveV4To
|
|
|
73
73
|
if (!hubNameOrKey) return null;
|
|
74
74
|
const normalized = hubNameOrKey.trim().toUpperCase();
|
|
75
75
|
|
|
76
|
-
// TODO AaveV4 Maybe turn into constants
|
|
77
76
|
if (normalized === 'CORE' || normalized === 'CORE HUB') return 'CORE';
|
|
78
77
|
if (normalized === 'PLUS' || normalized === 'PLUS HUB') return 'PLUS';
|
|
79
78
|
if (normalized === 'PRIME' || normalized === 'PRIME HUB') return 'PRIME';
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import Dec from 'decimal.js';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
aprToApy,
|
|
4
|
+
calcLeverageLiqPrice,
|
|
5
|
+
getAssetsTotal,
|
|
6
|
+
STABLE_ASSETS,
|
|
7
|
+
} from '../../moneymarket';
|
|
3
8
|
import {
|
|
4
9
|
AaveV4AggregatedPositionData,
|
|
5
10
|
AaveV4AssetsData,
|
|
@@ -10,6 +15,98 @@ import {
|
|
|
10
15
|
NetworkNumber,
|
|
11
16
|
} from '../../types';
|
|
12
17
|
|
|
18
|
+
export const calcUserRiskPremiumBps = (usedAssets: AaveV4UsedReserveAssets, assetsData: AaveV4AssetsData): number => {
|
|
19
|
+
type CollateralInfo = { riskBps: number; valueUsd: Dec };
|
|
20
|
+
type DebtInfo = { valueUsd: Dec };
|
|
21
|
+
|
|
22
|
+
const collaterals: CollateralInfo[] = [];
|
|
23
|
+
const debts: DebtInfo[] = [];
|
|
24
|
+
|
|
25
|
+
Object.entries(usedAssets).forEach(([identifier, asset]) => {
|
|
26
|
+
const reserveData = assetsData[identifier];
|
|
27
|
+
if (!reserveData) return;
|
|
28
|
+
|
|
29
|
+
const borrowedUsdDec = new Dec(asset.borrowedUsd || '0');
|
|
30
|
+
if (asset.isBorrowed && borrowedUsdDec.gt(0)) {
|
|
31
|
+
debts.push({ valueUsd: borrowedUsdDec });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const suppliedUsdDec = new Dec(asset.suppliedUsd || '0');
|
|
35
|
+
const isActiveCollateral = asset.collateral
|
|
36
|
+
&& asset.isSupplied
|
|
37
|
+
&& asset.collateralFactor > 0
|
|
38
|
+
&& suppliedUsdDec.gt(0);
|
|
39
|
+
|
|
40
|
+
if (isActiveCollateral) {
|
|
41
|
+
// collateralRisk is stored as a fraction (e.g. 0.25), convert back to bps
|
|
42
|
+
const riskBps = new Dec(reserveData.collateralRisk).mul(10000).toNumber();
|
|
43
|
+
collaterals.push({
|
|
44
|
+
riskBps,
|
|
45
|
+
valueUsd: suppliedUsdDec,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const totalDebtUsd = debts.reduce((sum, d) => sum.add(d.valueUsd), new Dec(0));
|
|
51
|
+
|
|
52
|
+
if (totalDebtUsd.lte(0)) {
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// sort by risk ASC, value DESC
|
|
57
|
+
collaterals.sort((a, b) => {
|
|
58
|
+
if (a.riskBps !== b.riskBps) return a.riskBps - b.riskBps;
|
|
59
|
+
return b.valueUsd.comparedTo(a.valueUsd);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
let debtLeftToCover = totalDebtUsd;
|
|
63
|
+
let numerator = new Dec(0); // sum(coveredUsd * riskBps)
|
|
64
|
+
let coveredDebt = new Dec(0); // sum(coveredUsd)
|
|
65
|
+
|
|
66
|
+
collaterals.forEach(({ riskBps, valueUsd }) => {
|
|
67
|
+
if (debtLeftToCover.lte(0)) return;
|
|
68
|
+
|
|
69
|
+
const coveredUsd = Dec.min(valueUsd, debtLeftToCover);
|
|
70
|
+
|
|
71
|
+
numerator = numerator.add(coveredUsd.mul(riskBps));
|
|
72
|
+
coveredDebt = coveredDebt.add(coveredUsd);
|
|
73
|
+
|
|
74
|
+
debtLeftToCover = debtLeftToCover.sub(coveredUsd);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
if (coveredDebt.lte(0)) {
|
|
78
|
+
return 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const riskPremiumBps = numerator.div(coveredDebt);
|
|
82
|
+
return riskPremiumBps.toNumber();
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const getApyAfterValuesEstimation = (
|
|
86
|
+
usedAssets: AaveV4UsedReserveAssets,
|
|
87
|
+
assetsData: AaveV4AssetsData,
|
|
88
|
+
): Record<string, { borrowRate: string; supplyRate: string }> => {
|
|
89
|
+
const riskPremiumBps = calcUserRiskPremiumBps(usedAssets, assetsData);
|
|
90
|
+
const riskPremiumFraction = new Dec(riskPremiumBps).div(10000); // bps to fraction
|
|
91
|
+
|
|
92
|
+
const result: Record<string, { borrowRate: string; supplyRate: string }> = {};
|
|
93
|
+
|
|
94
|
+
Object.entries(assetsData).forEach(([identifier, assetData]) => {
|
|
95
|
+
const drawnRate = new Dec(assetData.drawnRate);
|
|
96
|
+
const baseBorrowApr = drawnRate.mul(100);
|
|
97
|
+
// finalBorrowRate = baseBorrowRate * (1 + riskPremiumFraction)
|
|
98
|
+
const userBorrowApr = baseBorrowApr.mul(new Dec(1).add(riskPremiumFraction));
|
|
99
|
+
|
|
100
|
+
result[identifier] = {
|
|
101
|
+
borrowRate: aprToApy(userBorrowApr.toString()),
|
|
102
|
+
// Supply rate is market-level (not user-specific), use existing value
|
|
103
|
+
supplyRate: assetData.supplyRate,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
return result;
|
|
108
|
+
};
|
|
109
|
+
|
|
13
110
|
export const aaveV4GetCollateralFactor = (assetData: AaveV4ReserveAssetData, usedAssetData: AaveV4UsedReserveAsset, useUserCollateralFactor: boolean = false): number => (useUserCollateralFactor ? usedAssetData.collateralFactor : assetData.collateralFactor);
|
|
14
111
|
|
|
15
112
|
export const isLeveragedPosAaveV4 = (usedAssets: AaveV4UsedReserveAssets, dustLimit = 5) => {
|