@hobba-io/core 0.1.0
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/LICENSE +15 -0
- package/README.md +87 -0
- package/dist/amountUtils.d.ts +15 -0
- package/dist/amountUtils.d.ts.map +1 -0
- package/dist/amountUtils.js +59 -0
- package/dist/amountUtils.js.map +1 -0
- package/dist/constants.d.ts +148 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +231 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +29 -0
- package/dist/errors.js.map +1 -0
- package/dist/executeAction.d.ts +36 -0
- package/dist/executeAction.d.ts.map +1 -0
- package/dist/executeAction.js +606 -0
- package/dist/executeAction.js.map +1 -0
- package/dist/executeDepositBorrow.d.ts +49 -0
- package/dist/executeDepositBorrow.d.ts.map +1 -0
- package/dist/executeDepositBorrow.js +444 -0
- package/dist/executeDepositBorrow.js.map +1 -0
- package/dist/idl/hobba.json +5072 -0
- package/dist/idl.d.ts +783 -0
- package/dist/idl.d.ts.map +1 -0
- package/dist/idl.js +7 -0
- package/dist/idl.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/juplend/accountResolvers.d.ts +106 -0
- package/dist/juplend/accountResolvers.d.ts.map +1 -0
- package/dist/juplend/accountResolvers.js +148 -0
- package/dist/juplend/accountResolvers.js.map +1 -0
- package/dist/juplend/operateRemaining.d.ts +11 -0
- package/dist/juplend/operateRemaining.d.ts.map +1 -0
- package/dist/juplend/operateRemaining.js +46 -0
- package/dist/juplend/operateRemaining.js.map +1 -0
- package/dist/juplend/positionInit.d.ts +34 -0
- package/dist/juplend/positionInit.d.ts.map +1 -0
- package/dist/juplend/positionInit.js +56 -0
- package/dist/juplend/positionInit.js.map +1 -0
- package/dist/juplend/positionParser.d.ts +8 -0
- package/dist/juplend/positionParser.d.ts.map +1 -0
- package/dist/juplend/positionParser.js +30 -0
- package/dist/juplend/positionParser.js.map +1 -0
- package/dist/juplend/sdkApi.d.ts +39 -0
- package/dist/juplend/sdkApi.d.ts.map +1 -0
- package/dist/juplend/sdkApi.js +68 -0
- package/dist/juplend/sdkApi.js.map +1 -0
- package/dist/juplend/tickMath.d.ts +19 -0
- package/dist/juplend/tickMath.d.ts.map +1 -0
- package/dist/juplend/tickMath.js +91 -0
- package/dist/juplend/tickMath.js.map +1 -0
- package/dist/juplend/tickUtils.d.ts +20 -0
- package/dist/juplend/tickUtils.d.ts.map +1 -0
- package/dist/juplend/tickUtils.js +115 -0
- package/dist/juplend/tickUtils.js.map +1 -0
- package/dist/juplend/vaultConfigParser.d.ts +25 -0
- package/dist/juplend/vaultConfigParser.d.ts.map +1 -0
- package/dist/juplend/vaultConfigParser.js +38 -0
- package/dist/juplend/vaultConfigParser.js.map +1 -0
- package/dist/kamino/accountResolvers.d.ts +110 -0
- package/dist/kamino/accountResolvers.d.ts.map +1 -0
- package/dist/kamino/accountResolvers.js +220 -0
- package/dist/kamino/accountResolvers.js.map +1 -0
- package/dist/kamino/obligationParser.d.ts +13 -0
- package/dist/kamino/obligationParser.d.ts.map +1 -0
- package/dist/kamino/obligationParser.js +92 -0
- package/dist/kamino/obligationParser.js.map +1 -0
- package/dist/kamino/refreshInstructions.d.ts +4 -0
- package/dist/kamino/refreshInstructions.d.ts.map +1 -0
- package/dist/kamino/refreshInstructions.js +32 -0
- package/dist/kamino/refreshInstructions.js.map +1 -0
- package/dist/limits.d.ts +87 -0
- package/dist/limits.d.ts.map +1 -0
- package/dist/limits.js +174 -0
- package/dist/limits.js.map +1 -0
- package/dist/marketConfig.d.ts +35 -0
- package/dist/marketConfig.d.ts.map +1 -0
- package/dist/marketConfig.js +85 -0
- package/dist/marketConfig.js.map +1 -0
- package/dist/oracle/scopePrice.d.ts +7 -0
- package/dist/oracle/scopePrice.d.ts.map +1 -0
- package/dist/oracle/scopePrice.js +31 -0
- package/dist/oracle/scopePrice.js.map +1 -0
- package/dist/pdas.d.ts +33 -0
- package/dist/pdas.d.ts.map +1 -0
- package/dist/pdas.js +116 -0
- package/dist/pdas.js.map +1 -0
- package/dist/position.d.ts +45 -0
- package/dist/position.d.ts.map +1 -0
- package/dist/position.js +68 -0
- package/dist/position.js.map +1 -0
- package/dist/positionMetrics.d.ts +108 -0
- package/dist/positionMetrics.d.ts.map +1 -0
- package/dist/positionMetrics.js +238 -0
- package/dist/positionMetrics.js.map +1 -0
- package/dist/program.d.ts +12 -0
- package/dist/program.d.ts.map +1 -0
- package/dist/program.js +24 -0
- package/dist/program.js.map +1 -0
- package/dist/quote.d.ts +90 -0
- package/dist/quote.d.ts.map +1 -0
- package/dist/quote.js +198 -0
- package/dist/quote.js.map +1 -0
- package/dist/rates/borrowRates.d.ts +44 -0
- package/dist/rates/borrowRates.d.ts.map +1 -0
- package/dist/rates/borrowRates.js +229 -0
- package/dist/rates/borrowRates.js.map +1 -0
- package/dist/rates/collateralInfo.d.ts +21 -0
- package/dist/rates/collateralInfo.d.ts.map +1 -0
- package/dist/rates/collateralInfo.js +104 -0
- package/dist/rates/collateralInfo.js.map +1 -0
- package/dist/rates/constants.d.ts +22 -0
- package/dist/rates/constants.d.ts.map +1 -0
- package/dist/rates/constants.js +70 -0
- package/dist/rates/constants.js.map +1 -0
- package/dist/rates/index.d.ts +11 -0
- package/dist/rates/index.d.ts.map +1 -0
- package/dist/rates/index.js +11 -0
- package/dist/rates/index.js.map +1 -0
- package/dist/rates/kaminoApi.d.ts +24 -0
- package/dist/rates/kaminoApi.d.ts.map +1 -0
- package/dist/rates/kaminoApi.js +98 -0
- package/dist/rates/kaminoApi.js.map +1 -0
- package/dist/rates/supplyRates.d.ts +23 -0
- package/dist/rates/supplyRates.d.ts.map +1 -0
- package/dist/rates/supplyRates.js +67 -0
- package/dist/rates/supplyRates.js.map +1 -0
- package/dist/transactionBuilder.d.ts +5 -0
- package/dist/transactionBuilder.d.ts.map +1 -0
- package/dist/transactionBuilder.js +287 -0
- package/dist/transactionBuilder.js.map +1 -0
- package/dist/txHelpers.d.ts +16 -0
- package/dist/txHelpers.d.ts.map +1 -0
- package/dist/txHelpers.js +82 -0
- package/dist/txHelpers.js.map +1 -0
- package/dist/userState.d.ts +21 -0
- package/dist/userState.d.ts.map +1 -0
- package/dist/userState.js +60 -0
- package/dist/userState.js.map +1 -0
- package/dist/vault/vaultAccounts.d.ts +82 -0
- package/dist/vault/vaultAccounts.d.ts.map +1 -0
- package/dist/vault/vaultAccounts.js +275 -0
- package/dist/vault/vaultAccounts.js.map +1 -0
- package/dist/wallet.d.ts +12 -0
- package/dist/wallet.d.ts.map +1 -0
- package/dist/wallet.js +2 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +63 -0
- package/src/amountUtils.ts +69 -0
- package/src/constants.ts +263 -0
- package/src/errors.ts +33 -0
- package/src/executeAction.ts +884 -0
- package/src/executeDepositBorrow.ts +677 -0
- package/src/idl/hobba.json +5072 -0
- package/src/idl.ts +7 -0
- package/src/index.ts +21 -0
- package/src/juplend/accountResolvers.ts +207 -0
- package/src/juplend/operateRemaining.ts +81 -0
- package/src/juplend/positionInit.ts +86 -0
- package/src/juplend/positionParser.ts +41 -0
- package/src/juplend/sdkApi.ts +112 -0
- package/src/juplend/tickMath.ts +82 -0
- package/src/juplend/tickUtils.ts +163 -0
- package/src/juplend/vaultConfigParser.ts +45 -0
- package/src/kamino/accountResolvers.ts +299 -0
- package/src/kamino/obligationParser.ts +123 -0
- package/src/kamino/refreshInstructions.ts +45 -0
- package/src/limits.ts +222 -0
- package/src/marketConfig.ts +139 -0
- package/src/oracle/scopePrice.ts +31 -0
- package/src/pdas.ts +226 -0
- package/src/position.ts +131 -0
- package/src/positionMetrics.ts +387 -0
- package/src/program.ts +30 -0
- package/src/quote.ts +310 -0
- package/src/rates/borrowRates.ts +270 -0
- package/src/rates/collateralInfo.ts +136 -0
- package/src/rates/constants.ts +87 -0
- package/src/rates/index.ts +38 -0
- package/src/rates/kaminoApi.ts +134 -0
- package/src/rates/supplyRates.ts +102 -0
- package/src/transactionBuilder.ts +324 -0
- package/src/txHelpers.ts +107 -0
- package/src/userState.ts +91 -0
- package/src/vault/vaultAccounts.ts +365 -0
- package/src/wallet.ts +12 -0
package/dist/quote.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { collateralDecimals, collateralLabel } from "./amountUtils";
|
|
2
|
+
import { getPosition } from "./position";
|
|
3
|
+
import { bestMarketName, fetchCollateralPrice, fetchRatesPayload, fetchSupplyRatesPayload, } from "./positionMetrics";
|
|
4
|
+
/** Calculator defaults — same values the app falls back to when rates are empty. */
|
|
5
|
+
const FALLBACK_BORROW_APY = 5.6 / 100;
|
|
6
|
+
const FALLBACK_SUPPLY_APY = 21.59 / 100;
|
|
7
|
+
const SOL_STAKING_APY = 7 / 100;
|
|
8
|
+
const MAX_USER_LTV_PCT = 50;
|
|
9
|
+
function assessRisk(currentPrice, liquidationPrice) {
|
|
10
|
+
if (currentPrice <= 0 || liquidationPrice <= 0)
|
|
11
|
+
return { riskLabel: "—", riskLevel: "none" };
|
|
12
|
+
const fallPct = ((currentPrice - liquidationPrice) / currentPrice) * 100;
|
|
13
|
+
if (fallPct > 70)
|
|
14
|
+
return { riskLabel: "Very Safe", riskLevel: "safe" };
|
|
15
|
+
if (fallPct > 50)
|
|
16
|
+
return { riskLabel: "Safe", riskLevel: "safe" };
|
|
17
|
+
if (fallPct > 40)
|
|
18
|
+
return { riskLabel: "Moderate Risk", riskLevel: "moderate" };
|
|
19
|
+
if (fallPct > 30)
|
|
20
|
+
return { riskLabel: "Risky", riskLevel: "moderate" };
|
|
21
|
+
if (fallPct > 15)
|
|
22
|
+
return { riskLabel: "Very Risky", riskLevel: "risky" };
|
|
23
|
+
return { riskLabel: "Extremely Risky", riskLevel: "risky" };
|
|
24
|
+
}
|
|
25
|
+
function selfRepayDateFor(loanApyFraction) {
|
|
26
|
+
if (loanApyFraction >= 0)
|
|
27
|
+
return null;
|
|
28
|
+
const yearsToRepay = 1 / Math.abs(loanApyFraction);
|
|
29
|
+
if (yearsToRepay > 10)
|
|
30
|
+
return null;
|
|
31
|
+
const repayDate = new Date();
|
|
32
|
+
repayDate.setDate(repayDate.getDate() + Math.ceil(yearsToRepay * 365));
|
|
33
|
+
return `${repayDate.getDate().toString().padStart(2, "0")}/${(repayDate.getMonth() + 1)
|
|
34
|
+
.toString()
|
|
35
|
+
.padStart(2, "0")}/${repayDate.getFullYear()}`;
|
|
36
|
+
}
|
|
37
|
+
export async function getQuote(params) {
|
|
38
|
+
const { connection, collateralMint } = params;
|
|
39
|
+
const base = (params.apiBaseUrl ?? "").replace(/\/+$/, "");
|
|
40
|
+
const label = collateralLabel(collateralMint);
|
|
41
|
+
const [position, rates, supplyRates, price] = await Promise.all([
|
|
42
|
+
params.owner
|
|
43
|
+
? getPosition({ connection, owner: params.owner, collateralMint, apiBaseUrl: base })
|
|
44
|
+
: Promise.resolve(null),
|
|
45
|
+
fetchRatesPayload(base),
|
|
46
|
+
fetchSupplyRatesPayload(base),
|
|
47
|
+
fetchCollateralPrice(base, label),
|
|
48
|
+
]);
|
|
49
|
+
return computeQuote({
|
|
50
|
+
position,
|
|
51
|
+
rates,
|
|
52
|
+
supplyRates,
|
|
53
|
+
collateralPriceUsd: price,
|
|
54
|
+
collateralMint,
|
|
55
|
+
depositAmount: params.depositAmount,
|
|
56
|
+
borrowAmount: params.borrowAmount,
|
|
57
|
+
repayAmount: params.repayAmount,
|
|
58
|
+
withdrawAmount: params.withdrawAmount,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
export function computeQuote(inputs) {
|
|
62
|
+
const { position, rates, supplyRates, collateralPriceUsd: price, collateralMint } = inputs;
|
|
63
|
+
const label = collateralLabel(collateralMint);
|
|
64
|
+
const decimals = collateralDecimals(collateralMint);
|
|
65
|
+
const divisor = Math.pow(10, decimals);
|
|
66
|
+
const isSol = label === "SOL";
|
|
67
|
+
const params = inputs;
|
|
68
|
+
// Best live rates with the app's hardcoded fallbacks (CalculatorSection).
|
|
69
|
+
const bestBorrowAPY = (() => {
|
|
70
|
+
if (rates.markets.length === 0)
|
|
71
|
+
return FALLBACK_BORROW_APY;
|
|
72
|
+
let best = Infinity;
|
|
73
|
+
for (const m of rates.markets)
|
|
74
|
+
if (m.borrowAPY < best)
|
|
75
|
+
best = m.borrowAPY;
|
|
76
|
+
return best < Infinity ? best / 100 : FALLBACK_BORROW_APY;
|
|
77
|
+
})();
|
|
78
|
+
const bestSupplyAPY = (() => {
|
|
79
|
+
if (supplyRates.vaults.length === 0)
|
|
80
|
+
return FALLBACK_SUPPLY_APY;
|
|
81
|
+
let best = -Infinity;
|
|
82
|
+
for (const v of supplyRates.vaults)
|
|
83
|
+
if (v.supplyAPY > best)
|
|
84
|
+
best = v.supplyAPY;
|
|
85
|
+
return best > -Infinity ? best / 100 : FALLBACK_SUPPLY_APY;
|
|
86
|
+
})();
|
|
87
|
+
const lender = position?.exists
|
|
88
|
+
? position.lender
|
|
89
|
+
: bestMarketName(rates) === "JupLend"
|
|
90
|
+
? "juplend"
|
|
91
|
+
: "kamino";
|
|
92
|
+
const isJuplendLender = lender === "juplend";
|
|
93
|
+
const ltvSource = isJuplendLender
|
|
94
|
+
? rates.juplendCollateralLtvs[label]
|
|
95
|
+
: rates.collateralLtvs[label];
|
|
96
|
+
const liquidationLtvPct = ltvSource?.liquidationThresholdPct ?? (label === "cbBTC" ? 80 : 75);
|
|
97
|
+
// Current position in UI units
|
|
98
|
+
const curCollateralUi = position ? Number(position.collateral) / divisor : 0;
|
|
99
|
+
const curDebtUsdc = position ? Number(position.userDebtUsdc) / 1e6 : 0;
|
|
100
|
+
const actualOperatorBorrowed = position ? Number(position.depositedToVault) / 1e6 : 0;
|
|
101
|
+
// Deltas in UI units
|
|
102
|
+
const depositUi = Number(params.depositAmount ?? "0") / divisor;
|
|
103
|
+
const withdrawUi = Number(params.withdrawAmount ?? "0") / divisor;
|
|
104
|
+
const borrowUsdc = Number(params.borrowAmount ?? "0") / 1e6;
|
|
105
|
+
const repayUsdc = Number(params.repayAmount ?? "0") / 1e6;
|
|
106
|
+
const projCollateralUi = Math.max(0, curCollateralUi + depositUi - withdrawUi);
|
|
107
|
+
const projDebtUsdc = Math.max(0, curDebtUsdc + borrowUsdc - repayUsdc);
|
|
108
|
+
const curCollateralUsd = curCollateralUi * price;
|
|
109
|
+
const projCollateralUsd = projCollateralUi * price;
|
|
110
|
+
const curLtvPct = curCollateralUsd > 0 ? (curDebtUsdc / curCollateralUsd) * 100 : 0;
|
|
111
|
+
const projLtvPct = projCollateralUsd > 0 ? (projDebtUsdc / projCollateralUsd) * 100 : 0;
|
|
112
|
+
// Loan APY for a position — ported from ActionModal.computeLoanAPY: the
|
|
113
|
+
// operator borrows up to the per-asset target LTV whenever vault yield beats
|
|
114
|
+
// borrow cost; rates follow the user's actual lender + vault (Dashboard).
|
|
115
|
+
const TARGET_LTV = isSol ? 0.6 : 0.65;
|
|
116
|
+
const borrowMarketNameForRates = !position?.exists
|
|
117
|
+
? "Kamino Main Market"
|
|
118
|
+
: isJuplendLender
|
|
119
|
+
? "JupLend"
|
|
120
|
+
: "Kamino Main Market";
|
|
121
|
+
const positionBorrowAPY = params.positionBorrowApyPct ??
|
|
122
|
+
(rates.markets.find((m) => m.name === borrowMarketNameForRates)?.borrowAPY ??
|
|
123
|
+
bestBorrowAPY * 100);
|
|
124
|
+
const perenaVaultAPY = supplyRates.vaults.find((v) => v.name === "Perena USDC")?.supplyAPY ?? 0;
|
|
125
|
+
const positionVaultAPY = params.positionVaultApyPct ?? (perenaVaultAPY > 0 ? perenaVaultAPY : bestSupplyAPY * 100);
|
|
126
|
+
const DUST_DEBT = 0.01;
|
|
127
|
+
const computeLoanApyPct = (userDebt, collateralUsd) => {
|
|
128
|
+
if (userDebt < DUST_DEBT)
|
|
129
|
+
return null;
|
|
130
|
+
let opDebt = actualOperatorBorrowed;
|
|
131
|
+
if (collateralUsd > 0 && positionVaultAPY > positionBorrowAPY) {
|
|
132
|
+
const projected = Math.max(0, collateralUsd * TARGET_LTV - userDebt);
|
|
133
|
+
opDebt = Math.max(actualOperatorBorrowed, projected);
|
|
134
|
+
}
|
|
135
|
+
else if (positionVaultAPY <= positionBorrowAPY) {
|
|
136
|
+
opDebt = 0;
|
|
137
|
+
}
|
|
138
|
+
return ((userDebt + opDebt) * positionBorrowAPY - opDebt * positionVaultAPY) / userDebt;
|
|
139
|
+
};
|
|
140
|
+
const currentLoanApyPct = computeLoanApyPct(curDebtUsdc, curCollateralUsd);
|
|
141
|
+
const projectedLoanApyPct = computeLoanApyPct(projDebtUsdc, projCollateralUsd);
|
|
142
|
+
const projLiqPrice = projCollateralUsd > 0 && projDebtUsdc > 0 && liquidationLtvPct > 0
|
|
143
|
+
? price * (projLtvPct / liquidationLtvPct)
|
|
144
|
+
: 0;
|
|
145
|
+
const projBuffer = price > 0 && projLiqPrice > 0 ? Math.max(0, ((price - projLiqPrice) / price) * 100) : null;
|
|
146
|
+
const { riskLabel, riskLevel } = assessRisk(price, projLiqPrice);
|
|
147
|
+
// --- Calculator math (ported from CalculatorSection) on projected values ---
|
|
148
|
+
const depositValueUsd = projCollateralUsd;
|
|
149
|
+
const borrowValueUsd = projDebtUsdc; // USDC ≈ $1
|
|
150
|
+
const borrowLimitUsd = depositValueUsd * (MAX_USER_LTV_PCT / 100);
|
|
151
|
+
const earningPerYearUsd = depositValueUsd * TARGET_LTV > borrowValueUsd
|
|
152
|
+
? (depositValueUsd * TARGET_LTV - borrowValueUsd) * (bestSupplyAPY - bestBorrowAPY)
|
|
153
|
+
: 0;
|
|
154
|
+
const borrowCostPerYearUsd = borrowValueUsd * bestBorrowAPY;
|
|
155
|
+
const calcLoanApy = depositValueUsd > 0 && borrowValueUsd > 0
|
|
156
|
+
? (borrowCostPerYearUsd - earningPerYearUsd) / borrowValueUsd
|
|
157
|
+
: 0;
|
|
158
|
+
const stakingEarnPerYearUsd = isSol ? depositValueUsd * SOL_STAKING_APY : 0;
|
|
159
|
+
const hasSpreadEarn = depositValueUsd > 0 && borrowValueUsd <= 0 && bestSupplyAPY > bestBorrowAPY;
|
|
160
|
+
const earnMode = depositValueUsd > 0 && borrowValueUsd <= 0 && (hasSpreadEarn || stakingEarnPerYearUsd > 0);
|
|
161
|
+
const totalEarnPerYear = (hasSpreadEarn ? earningPerYearUsd : 0) + stakingEarnPerYearUsd;
|
|
162
|
+
const earnApy = earnMode && depositValueUsd > 0 ? totalEarnPerYear / depositValueUsd : 0;
|
|
163
|
+
return {
|
|
164
|
+
lender,
|
|
165
|
+
collateralPriceUsd: price,
|
|
166
|
+
liquidationLtvPct,
|
|
167
|
+
maxUserLtvPct: MAX_USER_LTV_PCT,
|
|
168
|
+
current: {
|
|
169
|
+
collateralUi: curCollateralUi,
|
|
170
|
+
debtUsdc: curDebtUsdc,
|
|
171
|
+
ltvPct: curLtvPct,
|
|
172
|
+
loanApyPct: currentLoanApyPct,
|
|
173
|
+
},
|
|
174
|
+
projected: {
|
|
175
|
+
collateralUi: projCollateralUi,
|
|
176
|
+
debtUsdc: projDebtUsdc,
|
|
177
|
+
ltvPct: projLtvPct,
|
|
178
|
+
loanApyPct: projectedLoanApyPct,
|
|
179
|
+
liquidationPriceUsd: projLiqPrice > 0 ? projLiqPrice : null,
|
|
180
|
+
dropToLiquidationPct: projBuffer,
|
|
181
|
+
riskLabel,
|
|
182
|
+
riskLevel,
|
|
183
|
+
},
|
|
184
|
+
calculator: {
|
|
185
|
+
depositValueUsd,
|
|
186
|
+
borrowValueUsd,
|
|
187
|
+
borrowLimitUsd,
|
|
188
|
+
loanApyPct: calcLoanApy * 100,
|
|
189
|
+
earnMode,
|
|
190
|
+
earnApyPct: earnApy * 100,
|
|
191
|
+
borrowCostPerYearUsd,
|
|
192
|
+
earningPerYearUsd,
|
|
193
|
+
stakingEarnPerYearUsd,
|
|
194
|
+
selfRepayDate: selfRepayDateFor(calcLoanApy),
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=quote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.js","sourceRoot":"","sources":["../src/quote.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared borrow rate computation functions.
|
|
3
|
+
* Extracted from /api/rates/route.ts to be reused by /api/market-data and the rebalancer.
|
|
4
|
+
*/
|
|
5
|
+
/** Measure actual slot duration from recent performance samples. */
|
|
6
|
+
export declare function getRecentSlotDurationMs(connection: {
|
|
7
|
+
getRecentPerformanceSamples: (limit: number) => Promise<Array<{
|
|
8
|
+
numSlots: number;
|
|
9
|
+
samplePeriodSecs: number;
|
|
10
|
+
}>>;
|
|
11
|
+
}): Promise<number>;
|
|
12
|
+
export interface CurvePoint {
|
|
13
|
+
utilizationRateBps: number;
|
|
14
|
+
borrowRateBps: number;
|
|
15
|
+
}
|
|
16
|
+
export interface BorrowRateResult {
|
|
17
|
+
availableLiquidity: number;
|
|
18
|
+
totalBorrowed: number;
|
|
19
|
+
utilization: number;
|
|
20
|
+
borrowAPR: number;
|
|
21
|
+
borrowAPY: number;
|
|
22
|
+
}
|
|
23
|
+
export interface CollateralInfo {
|
|
24
|
+
totalDeposited: number;
|
|
25
|
+
depositLimit: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function decodeReserve(data: Buffer): any;
|
|
28
|
+
export declare function computeKaminoBorrowRate(reserve: any, recentSlotDurationMs?: number): BorrowRateResult;
|
|
29
|
+
export declare function computeKaminoSupplyRate(reserve: any, recentSlotDurationMs?: number): {
|
|
30
|
+
supplyAPY: number;
|
|
31
|
+
};
|
|
32
|
+
export interface CollateralLtvInfo {
|
|
33
|
+
loanToValuePct: number;
|
|
34
|
+
liquidationThresholdPct: number;
|
|
35
|
+
}
|
|
36
|
+
export declare function getCollateralLtvInfo(reserve: any): CollateralLtvInfo;
|
|
37
|
+
export declare function getCollateralInfo(reserve: any): CollateralInfo;
|
|
38
|
+
export declare function getJuplendCollateralLtvInfo(vaultConfigData: Buffer): CollateralLtvInfo;
|
|
39
|
+
export declare function getJuplendCollateral(vaultStateData: Buffer): CollateralInfo;
|
|
40
|
+
export declare function computeJuplendBorrowRate(data: Buffer): BorrowRateResult;
|
|
41
|
+
export declare function computeJuplendSupplyRate(data: Buffer): {
|
|
42
|
+
supplyAPY: number;
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=borrowRates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"borrowRates.d.ts","sourceRoot":"","sources":["../../src/rates/borrowRates.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,oEAAoE;AACpE,wBAAsB,uBAAuB,CAAC,UAAU,EAAE;IAAE,2BAA2B,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAA;CAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB7L;AAED,MAAM,WAAW,UAAU;IACzB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,OAWzC;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,oBAAoB,SAA2B,GAAG,gBAAgB,CAyCvH;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,GAAG,EAAE,oBAAoB,SAA2B,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAoC5H;AAED,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,GAAG,GAAG,iBAAiB,CAKpE;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,GAAG,GAAG,cAAc,CAU9D;AAED,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,iBAAiB,CAYtF;AAED,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,cAAc,CAM3E;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAuCvE;AAQD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CA8B5E"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared borrow rate computation functions.
|
|
3
|
+
* Extracted from /api/rates/route.ts to be reused by /api/market-data and the rebalancer.
|
|
4
|
+
*/
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
const SF_SCALE = BigInt("1152921504606846976"); // 2^60
|
|
7
|
+
const SLOTS_PER_YEAR = 63072000;
|
|
8
|
+
const SLOTS_PER_SECOND = 2;
|
|
9
|
+
const DEFAULT_SLOT_DURATION_MS = 400;
|
|
10
|
+
const JUPLEND_EXCHANGE_PRECISION = BigInt("1000000000000"); // 1e12
|
|
11
|
+
const JUPLEND_SECONDS_PER_YEAR = 31536000;
|
|
12
|
+
/** Measure actual slot duration from recent performance samples. */
|
|
13
|
+
export async function getRecentSlotDurationMs(connection) {
|
|
14
|
+
try {
|
|
15
|
+
const samples = await connection.getRecentPerformanceSamples(10);
|
|
16
|
+
if (samples.length === 0)
|
|
17
|
+
return DEFAULT_SLOT_DURATION_MS;
|
|
18
|
+
let totalSlots = 0, totalSecs = 0;
|
|
19
|
+
for (const s of samples) {
|
|
20
|
+
totalSlots += s.numSlots;
|
|
21
|
+
totalSecs += s.samplePeriodSecs;
|
|
22
|
+
}
|
|
23
|
+
if (totalSlots === 0)
|
|
24
|
+
return DEFAULT_SLOT_DURATION_MS;
|
|
25
|
+
const measured = (totalSecs * 1000) / totalSlots;
|
|
26
|
+
// Sanity check: local validators report unrealistic durations
|
|
27
|
+
if (measured < 200 || measured > 600)
|
|
28
|
+
return DEFAULT_SLOT_DURATION_MS;
|
|
29
|
+
return measured;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return DEFAULT_SLOT_DURATION_MS;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function decodeReserve(data) {
|
|
36
|
+
// Lazy + server-only by design: resolves klend-sdk (an optional peer) from
|
|
37
|
+
// the consumer's node_modules at call time, keeping the heavy SDK out of
|
|
38
|
+
// browser bundles and out of load-time module evaluation. createRequire is
|
|
39
|
+
// invoked inside the function so importing this subpath never throws in
|
|
40
|
+
// environments without the optional peer installed.
|
|
41
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
42
|
+
const { Reserve } = nodeRequire("@kamino-finance/klend-sdk/dist/@codegen/klend/accounts/Reserve");
|
|
43
|
+
return Reserve.decode(data);
|
|
44
|
+
}
|
|
45
|
+
export function computeKaminoBorrowRate(reserve, recentSlotDurationMs = DEFAULT_SLOT_DURATION_MS) {
|
|
46
|
+
const availableAmount = Number(reserve.liquidity.availableAmount);
|
|
47
|
+
const borrowedAmount = Number(BigInt(reserve.liquidity.borrowedAmountSf.toString()) / SF_SCALE);
|
|
48
|
+
const protocolFees = Number(BigInt(reserve.liquidity.accumulatedProtocolFeesSf.toString()) / SF_SCALE);
|
|
49
|
+
const referrerFees = Number(BigInt(reserve.liquidity.accumulatedReferrerFeesSf.toString()) / SF_SCALE);
|
|
50
|
+
const pendingFees = Number(BigInt(reserve.liquidity.pendingReferrerFeesSf.toString()) / SF_SCALE);
|
|
51
|
+
const totalSupply = availableAmount + borrowedAmount - protocolFees - referrerFees - pendingFees;
|
|
52
|
+
const utilization = totalSupply > 0 ? borrowedAmount / totalSupply : 0;
|
|
53
|
+
const curve = reserve.config.borrowRateCurve.points;
|
|
54
|
+
const utilBps = utilization * 10000;
|
|
55
|
+
let borrowRateBps = 0;
|
|
56
|
+
for (let i = 1; i < curve.length; i++) {
|
|
57
|
+
if (curve[i].utilizationRateBps === 0 && curve[i].borrowRateBps === 0 && i > 1)
|
|
58
|
+
break;
|
|
59
|
+
if (utilBps <= curve[i].utilizationRateBps) {
|
|
60
|
+
const x0 = curve[i - 1].utilizationRateBps;
|
|
61
|
+
const x1 = curve[i].utilizationRateBps;
|
|
62
|
+
const y0 = curve[i - 1].borrowRateBps;
|
|
63
|
+
const y1 = curve[i].borrowRateBps;
|
|
64
|
+
borrowRateBps = y0 + ((utilBps - x0) * (y1 - y0)) / (x1 - x0);
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const slotAdjustment = 1000 / SLOTS_PER_SECOND / recentSlotDurationMs;
|
|
69
|
+
const adjustedRate = (borrowRateBps / 10000) * slotAdjustment;
|
|
70
|
+
const hostFixedRate = (reserve.config.hostFixedInterestRateBps / 10000) * slotAdjustment;
|
|
71
|
+
const borrowAPR = adjustedRate + hostFixedRate;
|
|
72
|
+
const borrowAPY = Math.pow(1 + borrowAPR / SLOTS_PER_YEAR, SLOTS_PER_YEAR) - 1;
|
|
73
|
+
const mintDecimals = Number(reserve.liquidity.mintDecimals);
|
|
74
|
+
const divisor = Math.pow(10, mintDecimals);
|
|
75
|
+
return {
|
|
76
|
+
availableLiquidity: availableAmount / divisor,
|
|
77
|
+
totalBorrowed: borrowedAmount / divisor,
|
|
78
|
+
utilization: utilization * 100,
|
|
79
|
+
borrowAPR: borrowAPR * 100,
|
|
80
|
+
borrowAPY: borrowAPY * 100,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function computeKaminoSupplyRate(reserve, recentSlotDurationMs = DEFAULT_SLOT_DURATION_MS) {
|
|
84
|
+
const availableAmount = Number(reserve.liquidity.availableAmount);
|
|
85
|
+
const borrowedAmount = Number(BigInt(reserve.liquidity.borrowedAmountSf.toString()) / SF_SCALE);
|
|
86
|
+
const protocolFees = Number(BigInt(reserve.liquidity.accumulatedProtocolFeesSf.toString()) / SF_SCALE);
|
|
87
|
+
const referrerFees = Number(BigInt(reserve.liquidity.accumulatedReferrerFeesSf.toString()) / SF_SCALE);
|
|
88
|
+
const pendingFees = Number(BigInt(reserve.liquidity.pendingReferrerFeesSf.toString()) / SF_SCALE);
|
|
89
|
+
const totalSupply = availableAmount + borrowedAmount - protocolFees - referrerFees - pendingFees;
|
|
90
|
+
const utilization = totalSupply > 0 ? borrowedAmount / totalSupply : 0;
|
|
91
|
+
const curve = reserve.config.borrowRateCurve.points;
|
|
92
|
+
const utilBps = utilization * 10000;
|
|
93
|
+
let borrowRateBps = 0;
|
|
94
|
+
for (let i = 1; i < curve.length; i++) {
|
|
95
|
+
if (curve[i].utilizationRateBps === 0 && curve[i].borrowRateBps === 0 && i > 1)
|
|
96
|
+
break;
|
|
97
|
+
if (utilBps <= curve[i].utilizationRateBps) {
|
|
98
|
+
const x0 = curve[i - 1].utilizationRateBps;
|
|
99
|
+
const x1 = curve[i].utilizationRateBps;
|
|
100
|
+
const y0 = curve[i - 1].borrowRateBps;
|
|
101
|
+
const y1 = curve[i].borrowRateBps;
|
|
102
|
+
borrowRateBps = y0 + ((utilBps - x0) * (y1 - y0)) / (x1 - x0);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const slotAdjustment = 1000 / SLOTS_PER_SECOND / recentSlotDurationMs;
|
|
107
|
+
const adjustedRate = (borrowRateBps / 10000) * slotAdjustment;
|
|
108
|
+
const hostFixedRate = (reserve.config.hostFixedInterestRateBps / 10000) * slotAdjustment;
|
|
109
|
+
const borrowAPR = adjustedRate + hostFixedRate;
|
|
110
|
+
// Protocol take rate: fraction of interest kept by protocol (in bps)
|
|
111
|
+
const protocolTakeRatePct = (reserve.config.protocolTakeRatePct ?? 0) / 100;
|
|
112
|
+
const supplyAPR = borrowAPR * utilization * (1 - protocolTakeRatePct);
|
|
113
|
+
const supplyAPY = Math.pow(1 + supplyAPR / SLOTS_PER_YEAR, SLOTS_PER_YEAR) - 1;
|
|
114
|
+
return { supplyAPY: supplyAPY * 100 };
|
|
115
|
+
}
|
|
116
|
+
export function getCollateralLtvInfo(reserve) {
|
|
117
|
+
return {
|
|
118
|
+
loanToValuePct: reserve.config.loanToValuePct ?? 0,
|
|
119
|
+
liquidationThresholdPct: reserve.config.liquidationThresholdPct ?? 0,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function getCollateralInfo(reserve) {
|
|
123
|
+
const availableAmount = Number(reserve.liquidity.availableAmount);
|
|
124
|
+
const borrowedAmount = Number(BigInt(reserve.liquidity.borrowedAmountSf.toString()) / SF_SCALE);
|
|
125
|
+
const mintDecimals = Number(reserve.liquidity.mintDecimals);
|
|
126
|
+
const divisor = Math.pow(10, mintDecimals);
|
|
127
|
+
const totalDeposited = (availableAmount + borrowedAmount) / divisor;
|
|
128
|
+
const depositLimit = Number(BigInt(reserve.config.depositLimit.toString())) / divisor;
|
|
129
|
+
return { totalDeposited, depositLimit };
|
|
130
|
+
}
|
|
131
|
+
export function getJuplendCollateralLtvInfo(vaultConfigData) {
|
|
132
|
+
// VaultConfig layout (packed C):
|
|
133
|
+
// 8 (anchor disc) + 2 vaultId + 2 supplyRateMagnifier (i16) + 2 borrowRateMagnifier (i16)
|
|
134
|
+
// + 2 collateralFactor (u16) + 2 liquidationThreshold (u16)
|
|
135
|
+
// Both factor fields are permille — divide by 10 to get percent. (See JupLend SDK
|
|
136
|
+
// lend.*.mjs liquidationThresholdRatio = ratio * threshold / 1000.)
|
|
137
|
+
const collateralFactor = vaultConfigData.readUInt16LE(8 + 2 + 2 + 2);
|
|
138
|
+
const liquidationThreshold = vaultConfigData.readUInt16LE(8 + 2 + 2 + 2 + 2);
|
|
139
|
+
return {
|
|
140
|
+
loanToValuePct: collateralFactor / 10,
|
|
141
|
+
liquidationThresholdPct: liquidationThreshold / 10,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
export function getJuplendCollateral(vaultStateData) {
|
|
145
|
+
let off = 8; // discriminator
|
|
146
|
+
off += 2 + 1 + 4 + 4 + 4; // vaultId + branchLiquidated + topmostTick + currentBranchId + totalBranchId
|
|
147
|
+
const totalSupplyRaw = Number(vaultStateData.readBigUInt64LE(off));
|
|
148
|
+
const totalDeposited = totalSupplyRaw / 1e8; // cbBTC has 8 decimals
|
|
149
|
+
return { totalDeposited, depositLimit: 0 };
|
|
150
|
+
}
|
|
151
|
+
export function computeJuplendBorrowRate(data) {
|
|
152
|
+
let off = 8; // skip discriminator
|
|
153
|
+
off += 32; // mint
|
|
154
|
+
off += 32; // vault
|
|
155
|
+
const borrowRateBps = data.readUInt16LE(off);
|
|
156
|
+
off += 2;
|
|
157
|
+
off += 2; // feeOnInterest
|
|
158
|
+
off += 2; // lastUtilization
|
|
159
|
+
off += 8; // lastUpdateTimestamp
|
|
160
|
+
const supplyExchangePrice = data.readBigUInt64LE(off);
|
|
161
|
+
off += 8;
|
|
162
|
+
const borrowExchangePrice = data.readBigUInt64LE(off);
|
|
163
|
+
off += 8;
|
|
164
|
+
off += 2; // maxUtilization
|
|
165
|
+
const totalSupplyWithInterest = data.readBigUInt64LE(off);
|
|
166
|
+
off += 8;
|
|
167
|
+
const totalSupplyInterestFree = data.readBigUInt64LE(off);
|
|
168
|
+
off += 8;
|
|
169
|
+
const totalBorrowWithInterest = data.readBigUInt64LE(off);
|
|
170
|
+
off += 8;
|
|
171
|
+
const totalBorrowInterestFree = data.readBigUInt64LE(off);
|
|
172
|
+
off += 8;
|
|
173
|
+
const totalSupply = Number(totalSupplyWithInterest * supplyExchangePrice / JUPLEND_EXCHANGE_PRECISION) +
|
|
174
|
+
Number(totalSupplyInterestFree);
|
|
175
|
+
const totalBorrow = Number(totalBorrowWithInterest * borrowExchangePrice / JUPLEND_EXCHANGE_PRECISION) +
|
|
176
|
+
Number(totalBorrowInterestFree);
|
|
177
|
+
const USDC_DIVISOR = 1e6;
|
|
178
|
+
const availableLiquidity = (totalSupply - totalBorrow) / USDC_DIVISOR;
|
|
179
|
+
const totalBorrowed = totalBorrow / USDC_DIVISOR;
|
|
180
|
+
const utilization = totalSupply > 0 ? (totalBorrow / totalSupply) * 100 : 0;
|
|
181
|
+
const borrowAPR = borrowRateBps / 100; // percent
|
|
182
|
+
const apr = borrowRateBps / 10000; // as fraction
|
|
183
|
+
const borrowAPY = (Math.pow(1 + apr / JUPLEND_SECONDS_PER_YEAR, JUPLEND_SECONDS_PER_YEAR) - 1) * 100;
|
|
184
|
+
return {
|
|
185
|
+
availableLiquidity,
|
|
186
|
+
totalBorrowed,
|
|
187
|
+
utilization,
|
|
188
|
+
borrowAPR,
|
|
189
|
+
borrowAPY,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// Supply (deposit) APY for a JupLend liquidity reserve — the lender rate earned
|
|
193
|
+
// by collateral supplied into that reserve. Decodes the same tokenReserve struct
|
|
194
|
+
// as computeJuplendBorrowRate and mirrors the SDK's getLiquidityAssetSupplyRate:
|
|
195
|
+
// supplyRate = borrowRate * (1e4 - fee) * borrowWithInterest
|
|
196
|
+
// / (supplyWithInterest * 1e4)
|
|
197
|
+
// (the JupLend analog of Kamino's borrowAPR * utilization * (1 - fee)).
|
|
198
|
+
export function computeJuplendSupplyRate(data) {
|
|
199
|
+
let off = 8; // skip discriminator
|
|
200
|
+
off += 32; // mint
|
|
201
|
+
off += 32; // vault
|
|
202
|
+
const borrowRateBps = data.readUInt16LE(off);
|
|
203
|
+
off += 2;
|
|
204
|
+
const feeOnInterestBps = data.readUInt16LE(off);
|
|
205
|
+
off += 2;
|
|
206
|
+
off += 2; // lastUtilization
|
|
207
|
+
off += 8; // lastUpdateTimestamp
|
|
208
|
+
const supplyExchangePrice = data.readBigUInt64LE(off);
|
|
209
|
+
off += 8;
|
|
210
|
+
const borrowExchangePrice = data.readBigUInt64LE(off);
|
|
211
|
+
off += 8;
|
|
212
|
+
off += 2; // maxUtilization
|
|
213
|
+
const totalSupplyWithInterest = data.readBigUInt64LE(off);
|
|
214
|
+
off += 8;
|
|
215
|
+
off += 8; // totalSupplyInterestFree
|
|
216
|
+
const totalBorrowWithInterest = data.readBigUInt64LE(off);
|
|
217
|
+
off += 8;
|
|
218
|
+
const supplyWithInterest = (totalSupplyWithInterest * supplyExchangePrice) / JUPLEND_EXCHANGE_PRECISION;
|
|
219
|
+
const borrowWithInterest = (totalBorrowWithInterest * borrowExchangePrice) / JUPLEND_EXCHANGE_PRECISION;
|
|
220
|
+
if (supplyWithInterest <= BigInt(0))
|
|
221
|
+
return { supplyAPY: 0 };
|
|
222
|
+
const supplyRateBps = borrowRateBps *
|
|
223
|
+
(1 - feeOnInterestBps / 10000) *
|
|
224
|
+
(Number(borrowWithInterest) / Number(supplyWithInterest));
|
|
225
|
+
const apr = supplyRateBps / 10000; // as fraction
|
|
226
|
+
const supplyAPY = (Math.pow(1 + apr / JUPLEND_SECONDS_PER_YEAR, JUPLEND_SECONDS_PER_YEAR) - 1) * 100;
|
|
227
|
+
return { supplyAPY };
|
|
228
|
+
}
|
|
229
|
+
//# sourceMappingURL=borrowRates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"borrowRates.js","sourceRoot":"","sources":["../../src/rates/borrowRates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Connection } from "@solana/web3.js";
|
|
2
|
+
export interface CollateralRatesInfo {
|
|
3
|
+
collateralSupplyAPYs: Record<string, number>;
|
|
4
|
+
collateralLtvs: Record<string, {
|
|
5
|
+
loanToValuePct: number;
|
|
6
|
+
liquidationThresholdPct: number;
|
|
7
|
+
}>;
|
|
8
|
+
juplendCollateralSupplyAPYs: Record<string, number>;
|
|
9
|
+
juplendCollateralRewardsAPYs: Record<string, number>;
|
|
10
|
+
juplendCollateralLtvs: Record<string, {
|
|
11
|
+
loanToValuePct: number;
|
|
12
|
+
liquidationThresholdPct: number;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Per-collateral supply APYs + LTV thresholds for both lenders. Shared by
|
|
17
|
+
* /api/rates and /api/market-data so widget integrators get liquidation LTVs
|
|
18
|
+
* from the same source the app uses.
|
|
19
|
+
*/
|
|
20
|
+
export declare function computeCollateralRatesInfo(connection: Connection, recentSlotDurationMs: number): Promise<CollateralRatesInfo>;
|
|
21
|
+
//# sourceMappingURL=collateralInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collateralInfo.d.ts","sourceRoot":"","sources":["../../src/rates/collateralInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAa,MAAM,iBAAiB,CAAC;AAuBxD,MAAM,WAAW,mBAAmB;IAClC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,uBAAuB,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5F,2BAA2B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpD,4BAA4B,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrD,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,uBAAuB,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpG;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC9C,UAAU,EAAE,UAAU,EACtB,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAAC,mBAAmB,CAAC,CAgG9B"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
import { decodeReserve, computeKaminoSupplyRate, computeJuplendSupplyRate, getCollateralLtvInfo, getJuplendCollateralLtvInfo, } from "./borrowRates";
|
|
3
|
+
import { deriveJuplendVaultConfigPda, JUPLEND_VAULT_ID, JUPLEND_SOL_VAULT_ID, JUPLEND_LIQUIDITY_PROGRAM, SOL_MINT, CBBTC_MINT, } from "../constants";
|
|
4
|
+
// Collateral reserve addresses for supply APY (Kamino Main Market)
|
|
5
|
+
const COLLATERAL_RESERVES = {
|
|
6
|
+
cbBTC: "37Jk2zkz23vkAYBT66HM2gaqJuNg2nYLsCreQAVt5MWK",
|
|
7
|
+
SOL: "d4A2prbA2whesmvHaL88BH6Ewn5N4bTSU2Ze8P6Bc4Q",
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Per-collateral supply APYs + LTV thresholds for both lenders. Shared by
|
|
11
|
+
* /api/rates and /api/market-data so widget integrators get liquidation LTVs
|
|
12
|
+
* from the same source the app uses.
|
|
13
|
+
*/
|
|
14
|
+
export async function computeCollateralRatesInfo(connection, recentSlotDurationMs) {
|
|
15
|
+
// Kamino collateral info: supply APY + LTV thresholds per asset
|
|
16
|
+
const collateralSupplyAPYs = {};
|
|
17
|
+
const collateralLtvs = {};
|
|
18
|
+
await Promise.all(Object.entries(COLLATERAL_RESERVES).map(async ([asset, reserveAddr]) => {
|
|
19
|
+
try {
|
|
20
|
+
const info = await connection.getAccountInfo(new PublicKey(reserveAddr));
|
|
21
|
+
if (info) {
|
|
22
|
+
const reserve = decodeReserve(info.data);
|
|
23
|
+
const { supplyAPY } = computeKaminoSupplyRate(reserve, recentSlotDurationMs);
|
|
24
|
+
collateralSupplyAPYs[asset] = supplyAPY;
|
|
25
|
+
collateralLtvs[asset] = getCollateralLtvInfo(reserve);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
console.error(`Error computing ${asset} supply APY:`, e.message);
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
// JupLend collateral supply APYs — the lender rate on the SOL/cbBTC liquidity
|
|
33
|
+
// reserve, used when a position is deposited into JupLend rather than Kamino.
|
|
34
|
+
const juplendCollateralSupplyAPYs = {};
|
|
35
|
+
const juplendCollateralMints = [
|
|
36
|
+
["SOL", SOL_MINT],
|
|
37
|
+
["cbBTC", CBBTC_MINT],
|
|
38
|
+
];
|
|
39
|
+
await Promise.all(juplendCollateralMints.map(async ([asset, mint]) => {
|
|
40
|
+
try {
|
|
41
|
+
const reservePda = PublicKey.findProgramAddressSync([Buffer.from("reserve"), mint.toBuffer()], JUPLEND_LIQUIDITY_PROGRAM)[0];
|
|
42
|
+
const info = await connection.getAccountInfo(reservePda);
|
|
43
|
+
if (info) {
|
|
44
|
+
const { supplyAPY } = computeJuplendSupplyRate(info.data);
|
|
45
|
+
juplendCollateralSupplyAPYs[asset] = supplyAPY;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.error(`Error computing JupLend ${asset} supply APY:`, e.message);
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
// JupLend rewards boost (vault supplyRate minus base supplyRateLiquidity)
|
|
53
|
+
const juplendCollateralRewardsAPYs = {};
|
|
54
|
+
try {
|
|
55
|
+
const vaultsRes = await fetch("https://lite-api.jup.ag/lend/v1/borrow/vaults", {
|
|
56
|
+
headers: { accept: "application/json" },
|
|
57
|
+
signal: AbortSignal.timeout(8000),
|
|
58
|
+
});
|
|
59
|
+
if (vaultsRes.ok) {
|
|
60
|
+
const vaults = await vaultsRes.json();
|
|
61
|
+
const juplendVaultIds = [
|
|
62
|
+
["SOL", JUPLEND_SOL_VAULT_ID],
|
|
63
|
+
["cbBTC", JUPLEND_VAULT_ID],
|
|
64
|
+
];
|
|
65
|
+
for (const [asset, vaultId] of juplendVaultIds) {
|
|
66
|
+
const v = vaults.find((x) => x?.id === vaultId);
|
|
67
|
+
if (!v)
|
|
68
|
+
continue;
|
|
69
|
+
// API rates are 1e2-scaled (e.g. "531" => 5.31%).
|
|
70
|
+
const rewards = Math.max(0, Number(v.supplyRate) - Number(v.supplyRateLiquidity)) / 100;
|
|
71
|
+
if (rewards > 0)
|
|
72
|
+
juplendCollateralRewardsAPYs[asset] = rewards;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
console.error("Error fetching JupLend rewards:", e.message);
|
|
78
|
+
}
|
|
79
|
+
// JupLend collateral LTVs (per-vault liquidationThreshold from vault_config)
|
|
80
|
+
const juplendCollateralLtvs = {};
|
|
81
|
+
const juplendVaultConfigs = [
|
|
82
|
+
["cbBTC", deriveJuplendVaultConfigPda(JUPLEND_VAULT_ID)],
|
|
83
|
+
["SOL", deriveJuplendVaultConfigPda(JUPLEND_SOL_VAULT_ID)],
|
|
84
|
+
];
|
|
85
|
+
await Promise.all(juplendVaultConfigs.map(async ([asset, addr]) => {
|
|
86
|
+
try {
|
|
87
|
+
const info = await connection.getAccountInfo(addr);
|
|
88
|
+
if (info) {
|
|
89
|
+
juplendCollateralLtvs[asset] = getJuplendCollateralLtvInfo(info.data);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
console.error(`Error fetching JupLend ${asset} vault config:`, e.message);
|
|
94
|
+
}
|
|
95
|
+
}));
|
|
96
|
+
return {
|
|
97
|
+
collateralSupplyAPYs,
|
|
98
|
+
collateralLtvs,
|
|
99
|
+
juplendCollateralSupplyAPYs,
|
|
100
|
+
juplendCollateralRewardsAPYs,
|
|
101
|
+
juplendCollateralLtvs,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=collateralInfo.js.map
|