@kamino-finance/klend-sdk 5.1.10 → 5.2.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/dist/classes/action.js +2 -2
- package/dist/classes/action.js.map +1 -1
- package/dist/classes/obligation.d.ts.map +1 -1
- package/dist/classes/obligation.js +4 -4
- package/dist/classes/obligation.js.map +1 -1
- package/dist/classes/vault.d.ts +1 -0
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +10 -23
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +29 -0
- package/dist/client_kamino_manager.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.d.ts +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_calcs.js +42 -19
- package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
- package/dist/lending_operations/repay_with_collateral_operations.js +11 -3
- package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/action.ts +2 -2
- package/src/classes/obligation.ts +4 -7
- package/src/classes/vault.ts +19 -29
- package/src/client_kamino_manager.ts +43 -0
- package/src/lending_operations/repay_with_collateral_calcs.ts +53 -22
- package/src/lending_operations/repay_with_collateral_operations.ts +16 -10
- package/src/utils/ata.ts +1 -1
|
@@ -64,43 +64,74 @@ export function calcMaxWithdrawCollateral(
|
|
|
64
64
|
debtReserveAddr: PublicKey,
|
|
65
65
|
obligation: KaminoObligation,
|
|
66
66
|
repayAmountLamports: Decimal
|
|
67
|
-
) {
|
|
67
|
+
): {
|
|
68
|
+
canWithdrawRemainingColl: boolean;
|
|
69
|
+
withdrawableCollLamports: Decimal;
|
|
70
|
+
} {
|
|
68
71
|
const collReserve = kaminoMarket.getReserveByAddress(collReserveAddr)!;
|
|
69
|
-
const debtReserve = kaminoMarket.getReserveByAddress(debtReserveAddr)!;
|
|
70
|
-
|
|
71
|
-
const debtOraclePx = debtReserve.getOracleMarketPrice();
|
|
72
72
|
const collOraclePx = collReserve.getOracleMarketPrice();
|
|
73
73
|
const { maxLtv: collMaxLtv } = obligation.getLtvForReserve(kaminoMarket, collReserve);
|
|
74
|
-
const debtBorrowFactor = debtReserve.getBorrowFactor();
|
|
75
74
|
|
|
76
|
-
const debtPosition = obligation.getBorrowByReserve(debtReserve.address)!;
|
|
77
75
|
const collPosition = obligation.getDepositByReserve(collReserve.address)!;
|
|
78
76
|
const initialCollValue = collPosition.amount.floor().div(collReserve.getMintFactor()).mul(collOraclePx);
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
.
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
77
|
+
|
|
78
|
+
let totalRemainingDebtValue = new Decimal(0);
|
|
79
|
+
const borrows = obligation.getBorrows();
|
|
80
|
+
for (const debtPosition of borrows) {
|
|
81
|
+
const debtReserve = kaminoMarket.getReserveByAddress(debtPosition.reserveAddress)!;
|
|
82
|
+
const debtOraclePx = debtReserve.getOracleMarketPrice();
|
|
83
|
+
const debtBorrowFactor = debtReserve.getBorrowFactor();
|
|
84
|
+
let remainingDebtAmountLamports = debtPosition.amount;
|
|
85
|
+
if (debtPosition.reserveAddress.equals(debtReserveAddr)) {
|
|
86
|
+
remainingDebtAmountLamports = remainingDebtAmountLamports.sub(repayAmountLamports);
|
|
87
|
+
}
|
|
88
|
+
const remainingDebtBfWeightedValue = remainingDebtAmountLamports
|
|
89
|
+
.ceil()
|
|
90
|
+
.div(debtReserve.getMintFactor())
|
|
91
|
+
.mul(debtBorrowFactor)
|
|
92
|
+
.mul(debtOraclePx);
|
|
93
|
+
totalRemainingDebtValue = totalRemainingDebtValue.add(remainingDebtBfWeightedValue);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let canWithdrawRemainingColl = false;
|
|
97
|
+
if (totalRemainingDebtValue.lte(new Decimal(0)) && borrows.length === 1) {
|
|
98
|
+
canWithdrawRemainingColl = true;
|
|
89
99
|
}
|
|
90
|
-
|
|
100
|
+
|
|
101
|
+
const deposits = obligation.getDeposits();
|
|
102
|
+
const otherCollDeposits = deposits.filter((deposit) => !deposit.reserveAddress.equals(collReserve.address));
|
|
103
|
+
|
|
104
|
+
let totalOtherCollateralValue = new Decimal(0);
|
|
105
|
+
for (const d of otherCollDeposits) {
|
|
106
|
+
const otherCollReserve = kaminoMarket.getReserveByAddress(d.reserveAddress)!;
|
|
107
|
+
const otherCollOraclePx = otherCollReserve.getOracleMarketPrice();
|
|
108
|
+
const otherCollMaxLtv = obligation.getLtvForReserve(kaminoMarket, otherCollReserve).maxLtv;
|
|
109
|
+
const otherCollValue = d.amount
|
|
110
|
+
.floor()
|
|
111
|
+
.div(otherCollReserve.getMintFactor())
|
|
112
|
+
.mul(otherCollOraclePx)
|
|
113
|
+
.mul(otherCollMaxLtv);
|
|
114
|
+
totalOtherCollateralValue = totalOtherCollateralValue.add(otherCollValue);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const numerator = initialCollValue.mul(collMaxLtv).add(totalOtherCollateralValue).sub(totalRemainingDebtValue);
|
|
118
|
+
|
|
119
|
+
// If all collateral cannot cover the remaining debt
|
|
120
|
+
if (numerator.lte('0')) {
|
|
121
|
+
return { canWithdrawRemainingColl: false, withdrawableCollLamports: new Decimal(0) };
|
|
122
|
+
}
|
|
123
|
+
|
|
91
124
|
const denominator = collOraclePx.mul(collMaxLtv);
|
|
92
125
|
const maxCollWithdrawAmount = numerator.div(denominator);
|
|
93
126
|
const maxCollateralWithdrawalAmountLamports = maxCollWithdrawAmount.mul(collReserve.getMintFactor()).floor();
|
|
94
127
|
|
|
95
128
|
let withdrawableCollLamports: Decimal;
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
const maxSwapCollLamportsWithBuffer = maxCollateralWithdrawalAmountLamports.mul('1.1');
|
|
99
|
-
withdrawableCollLamports = Decimal.min(maxSwapCollLamportsWithBuffer, collPosition.amount).floor();
|
|
129
|
+
if (canWithdrawRemainingColl) {
|
|
130
|
+
withdrawableCollLamports = Decimal.min(maxCollateralWithdrawalAmountLamports, collPosition.amount).floor();
|
|
100
131
|
} else {
|
|
101
132
|
withdrawableCollLamports = Decimal.max(new Decimal(0), maxCollateralWithdrawalAmountLamports);
|
|
102
133
|
}
|
|
103
|
-
return {
|
|
134
|
+
return { canWithdrawRemainingColl, withdrawableCollLamports };
|
|
104
135
|
}
|
|
105
136
|
|
|
106
137
|
export function estimateDebtRepaymentWithColl(props: {
|
|
@@ -74,14 +74,11 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
|
|
|
74
74
|
throw new Error(`Debt reserve with mint ${debtReserve} not found in market ${kaminoMarket.getAddress()}`);
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
const {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
repayAmount,
|
|
83
|
-
referrer
|
|
84
|
-
);
|
|
77
|
+
const {
|
|
78
|
+
repayAmountLamports,
|
|
79
|
+
flashRepayAmountLamports,
|
|
80
|
+
repayAmount: finalRepayAmount,
|
|
81
|
+
} = calcRepayAmountWithSlippage(kaminoMarket, debtReserve, currentSlot, obligation, repayAmount, referrer);
|
|
85
82
|
|
|
86
83
|
const debtPosition = obligation.getBorrowByReserve(debtReserve.address);
|
|
87
84
|
const collPosition = obligation.getDepositByReserve(collReserve.address);
|
|
@@ -103,8 +100,17 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
|
|
|
103
100
|
repayAmountLamports
|
|
104
101
|
);
|
|
105
102
|
|
|
103
|
+
// sanity check: we have extra collateral to swap, but we want to ensure we don't quote for way more than needed and get a bad px
|
|
104
|
+
const maxCollNeededFromOracle = finalRepayAmount
|
|
105
|
+
.mul(debtReserve.getOracleMarketPrice())
|
|
106
|
+
.div(collReserve.getOracleMarketPrice())
|
|
107
|
+
.mul('1.1')
|
|
108
|
+
.mul(collReserve.getMintFactor())
|
|
109
|
+
.ceil();
|
|
110
|
+
const inputAmountLamports = Decimal.min(withdrawableCollLamports, maxCollNeededFromOracle);
|
|
111
|
+
|
|
106
112
|
const swapQuoteInputs: SwapInputs = {
|
|
107
|
-
inputAmountLamports
|
|
113
|
+
inputAmountLamports,
|
|
108
114
|
inputMint: collTokenMint,
|
|
109
115
|
outputMint: debtTokenMint,
|
|
110
116
|
amountDebtAtaBalance: new Decimal(0), // only used for kTokens
|
|
@@ -127,7 +133,7 @@ export async function getRepayWithCollSwapInputs<QuoteResponse>({
|
|
|
127
133
|
},
|
|
128
134
|
isClosingPosition,
|
|
129
135
|
repayAmountLamports,
|
|
130
|
-
|
|
136
|
+
inputAmountLamports
|
|
131
137
|
);
|
|
132
138
|
const uniqueKlendAccounts = uniqueAccounts(klendIxs);
|
|
133
139
|
const swapQuote = await quoter(swapQuoteInputs, uniqueKlendAccounts);
|
package/src/utils/ata.ts
CHANGED
|
@@ -154,7 +154,7 @@ export async function getTokenAccountBalanceDecimal(
|
|
|
154
154
|
connection: Connection,
|
|
155
155
|
mint: PublicKey,
|
|
156
156
|
owner: PublicKey,
|
|
157
|
-
tokenProgram: PublicKey = TOKEN_PROGRAM_ID
|
|
157
|
+
tokenProgram: PublicKey = TOKEN_PROGRAM_ID
|
|
158
158
|
): Promise<Decimal> {
|
|
159
159
|
const ata = getAssociatedTokenAddress(mint, owner, true, tokenProgram);
|
|
160
160
|
const accInfo = await connection.getAccountInfo(ata);
|