@kamino-finance/klend-sdk 3.2.23 → 3.2.25
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/obligation.d.ts +15 -33
- package/dist/classes/obligation.js +76 -144
- package/dist/classes/obligation.js.map +1 -1
- package/package.json +1 -1
|
@@ -37,6 +37,14 @@ interface BorrowStats {
|
|
|
37
37
|
userTotalBorrowBorrowFactorAdjusted: Decimal;
|
|
38
38
|
positions: number;
|
|
39
39
|
}
|
|
40
|
+
interface DepositStats {
|
|
41
|
+
deposits: Map<PublicKey, Position>;
|
|
42
|
+
userTotalDeposit: Decimal;
|
|
43
|
+
userTotalCollateralDeposit: Decimal;
|
|
44
|
+
borrowLimit: Decimal;
|
|
45
|
+
liquidationLtv: Decimal;
|
|
46
|
+
borrowLiquidationLimit: Decimal;
|
|
47
|
+
}
|
|
40
48
|
export declare class KaminoObligation {
|
|
41
49
|
obligationAddress: PublicKey;
|
|
42
50
|
state: Obligation;
|
|
@@ -118,33 +126,13 @@ export declare class KaminoObligation {
|
|
|
118
126
|
*/
|
|
119
127
|
getNumberOfPositions(): number;
|
|
120
128
|
getNetAccountValue(): Decimal;
|
|
121
|
-
/**
|
|
122
|
-
* Get the loan to value and liquidation loan to value for a collateral token reserve as ratios, accounting for the obligation elevation group if it is active
|
|
123
|
-
* @param market
|
|
124
|
-
* @param reserve
|
|
125
|
-
*/
|
|
126
|
-
getLtvForReserve(market: KaminoMarket, reserve: KaminoReserve): {
|
|
127
|
-
maxLtv: Decimal;
|
|
128
|
-
liquidationLtv: Decimal;
|
|
129
|
-
};
|
|
130
|
-
/**
|
|
131
|
-
* Get the borrow factor for a borrow reserve, accounting for the obligation elevation group if it is active
|
|
132
|
-
* @param reserve
|
|
133
|
-
*/
|
|
134
|
-
getBorrowFactorForReserve(reserve: KaminoReserve): Decimal;
|
|
135
129
|
/**
|
|
136
130
|
* @returns the potential elevation groups the obligation qualifies for
|
|
137
131
|
*/
|
|
138
132
|
getElevationGroups(kaminoMarket: KaminoMarket): Array<number>;
|
|
139
133
|
static getElevationGroupsForReserves(reserves: Array<KaminoReserve>): Array<number>;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
borrows: Map<PublicKey, Position>;
|
|
143
|
-
};
|
|
144
|
-
calculateSimulatedDeposit(oldStats: ObligationStats, oldDeposits: Map<PublicKey, Position>, amount: Decimal, mint: PublicKey, reserves: Map<PublicKey, KaminoReserve>, market: KaminoMarket): {
|
|
145
|
-
stats: ObligationStats;
|
|
146
|
-
deposits: Map<PublicKey, Position>;
|
|
147
|
-
};
|
|
134
|
+
simulateDepositChange(obligationDeposits: ObligationCollateral[], changeInLamports: number, changeReserve: PublicKey, collateralExchangeRates: Map<PublicKey, Decimal>): ObligationCollateral[];
|
|
135
|
+
simulateBorrowChange(obligationBorrows: ObligationLiquidity[], changeInLamports: number, changeReserve: PublicKey): ObligationLiquidity[];
|
|
148
136
|
/**
|
|
149
137
|
* Calculate the newly modified stats of the obligation
|
|
150
138
|
*/
|
|
@@ -156,24 +144,18 @@ export declare class KaminoObligation {
|
|
|
156
144
|
mintDebt?: PublicKey;
|
|
157
145
|
market: KaminoMarket;
|
|
158
146
|
reserves: Map<PublicKey, KaminoReserve>;
|
|
147
|
+
slot: number;
|
|
148
|
+
elevationGroupOverride?: number;
|
|
159
149
|
}): {
|
|
160
150
|
stats: ObligationStats;
|
|
161
151
|
deposits: Map<PublicKey, Position>;
|
|
162
152
|
borrows: Map<PublicKey, Position>;
|
|
163
153
|
};
|
|
164
154
|
estimateObligationInterestRate: (market: KaminoMarket, reserve: KaminoReserve, borrow: ObligationLiquidity, currentSlot: number) => Decimal;
|
|
165
|
-
private calculateDeposits;
|
|
166
|
-
private calculateBorrows;
|
|
167
155
|
private calculatePositions;
|
|
168
|
-
static calculateObligationDeposits(market: KaminoMarket,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
userTotalCollateralDeposit: Decimal;
|
|
172
|
-
borrowLimit: Decimal;
|
|
173
|
-
liquidationLtv: Decimal;
|
|
174
|
-
borrowLiquidationLimit: Decimal;
|
|
175
|
-
};
|
|
176
|
-
static calculateObligationBorrows(market: KaminoMarket, obligation: Obligation, cumulativeBorrowRates: Map<PublicKey, Decimal> | null, elevationGroup: number, getPx: (reserve: KaminoReserve) => Decimal): BorrowStats;
|
|
156
|
+
static calculateObligationDeposits(market: KaminoMarket, obligationDeposits: ObligationCollateral[], collateralExchangeRates: Map<PublicKey, Decimal> | null, elevationGroup: number, getPx: (reserve: KaminoReserve) => Decimal): DepositStats;
|
|
157
|
+
static calculateObligationBorrows(market: KaminoMarket, obligationBorrows: ObligationLiquidity[], cumulativeBorrowRates: Map<PublicKey, Decimal> | null, elevationGroup: number, getPx: (reserve: KaminoReserve) => Decimal): BorrowStats;
|
|
158
|
+
getMaxLoanLtvGivenElevationGroup(market: KaminoMarket, elevationGroup: number, slot: number): Decimal;
|
|
177
159
|
getBorrowPower(market: KaminoMarket, liquidityMint: PublicKey, slot: number, elevationGroup?: number): Decimal;
|
|
178
160
|
getMaxBorrowAmountV2(market: KaminoMarket, liquidityMint: PublicKey, slot: number, elevationGroup?: number): Decimal;
|
|
179
161
|
isLoanEligibleForElevationGroup(market: KaminoMarket, slot: number, elevationGroup: number): boolean;
|
|
@@ -17,6 +17,7 @@ const decimal_js_1 = __importDefault(require("decimal.js"));
|
|
|
17
17
|
const accounts_1 = require("../idl_codegen/accounts");
|
|
18
18
|
const bn_js_1 = __importDefault(require("bn.js"));
|
|
19
19
|
const fraction_1 = require("./fraction");
|
|
20
|
+
const types_1 = require("../idl_codegen/types");
|
|
20
21
|
const utils_1 = require("./utils");
|
|
21
22
|
const utils_2 = require("../utils");
|
|
22
23
|
class KaminoObligation {
|
|
@@ -39,7 +40,7 @@ class KaminoObligation {
|
|
|
39
40
|
};
|
|
40
41
|
this.obligationAddress = obligationAddress;
|
|
41
42
|
this.state = obligation;
|
|
42
|
-
const { borrows, deposits, refreshedStats } = this.calculatePositions(market, obligation, collateralExchangeRates, cumulativeBorrowRates);
|
|
43
|
+
const { borrows, deposits, refreshedStats } = this.calculatePositions(market, obligation.deposits, obligation.borrows, obligation.elevationGroup, collateralExchangeRates, cumulativeBorrowRates);
|
|
43
44
|
this.deposits = deposits;
|
|
44
45
|
this.borrows = borrows;
|
|
45
46
|
this.refreshedStats = refreshedStats;
|
|
@@ -195,21 +196,6 @@ class KaminoObligation {
|
|
|
195
196
|
getNetAccountValue() {
|
|
196
197
|
return this.refreshedStats.netAccountValue;
|
|
197
198
|
}
|
|
198
|
-
/**
|
|
199
|
-
* Get the loan to value and liquidation loan to value for a collateral token reserve as ratios, accounting for the obligation elevation group if it is active
|
|
200
|
-
* @param market
|
|
201
|
-
* @param reserve
|
|
202
|
-
*/
|
|
203
|
-
getLtvForReserve(market, reserve) {
|
|
204
|
-
return KaminoObligation.getLtvForReserve(market, reserve, this.state.elevationGroup);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Get the borrow factor for a borrow reserve, accounting for the obligation elevation group if it is active
|
|
208
|
-
* @param reserve
|
|
209
|
-
*/
|
|
210
|
-
getBorrowFactorForReserve(reserve) {
|
|
211
|
-
return KaminoObligation.getBorrowFactorForReserve(reserve, this.state.elevationGroup);
|
|
212
|
-
}
|
|
213
199
|
/**
|
|
214
200
|
* @returns the potential elevation groups the obligation qualifies for
|
|
215
201
|
*/
|
|
@@ -250,141 +236,85 @@ class KaminoObligation {
|
|
|
250
236
|
}
|
|
251
237
|
return activeElevationGroups;
|
|
252
238
|
}
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
239
|
+
simulateDepositChange(obligationDeposits, changeInLamports, changeReserve, collateralExchangeRates) {
|
|
240
|
+
const newDeposits = [];
|
|
241
|
+
for (let i = 0; i < obligationDeposits.length; i++) {
|
|
242
|
+
if (obligationDeposits[i].depositReserve.equals(changeReserve)) {
|
|
243
|
+
const coll = Object.assign({}, obligationDeposits[i]);
|
|
244
|
+
const exchangeRate = collateralExchangeRates.get(changeReserve);
|
|
245
|
+
const changeInCollateral = new decimal_js_1.default(changeInLamports).mul(exchangeRate);
|
|
246
|
+
const updatedDeposit = new decimal_js_1.default(obligationDeposits[i].depositedAmount.toNumber()).add(changeInCollateral);
|
|
247
|
+
coll.depositedAmount = new bn_js_1.default((0, utils_1.positiveOrZero)(updatedDeposit).toString());
|
|
248
|
+
newDeposits.push(new types_1.ObligationCollateral(coll));
|
|
260
249
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
for (const kaminoReserve of reserves.values()) {
|
|
264
|
-
if (kaminoReserve.getLiquidityMint().equals(mint)) {
|
|
265
|
-
reserve = kaminoReserve;
|
|
250
|
+
else {
|
|
251
|
+
newDeposits.push(obligationDeposits[i]);
|
|
266
252
|
}
|
|
267
253
|
}
|
|
268
|
-
|
|
269
|
-
throw new Error(`No reserve found for mint ${mint}`);
|
|
270
|
-
}
|
|
271
|
-
if (!borrowPosition) {
|
|
272
|
-
borrowPosition = {
|
|
273
|
-
reserveAddress: reserve.address,
|
|
274
|
-
mintAddress: mint,
|
|
275
|
-
amount: new decimal_js_1.default(0),
|
|
276
|
-
marketValueRefreshed: new decimal_js_1.default(0),
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
if (!reserve.state.config.elevationGroups.includes(this.state.elevationGroup)) {
|
|
280
|
-
throw new Error(`User would have to downgrade the elevation group in order to be able to borrow from this reserve`);
|
|
281
|
-
}
|
|
282
|
-
const borrowFactor = this.getBorrowFactorForReserve(reserve);
|
|
283
|
-
const borrowValueUSD = borrowAmount.mul(reserve.getOracleMarketPrice()).dividedBy(reserve.getMintFactor());
|
|
284
|
-
const borrowValueBorrowFactorAdjustedUSD = borrowValueUSD.mul(borrowFactor);
|
|
285
|
-
newStats.userTotalBorrow = (0, utils_1.positiveOrZero)(newStats.userTotalBorrow.plus(borrowValueUSD));
|
|
286
|
-
newStats.userTotalBorrowBorrowFactorAdjusted = (0, utils_1.positiveOrZero)(newStats.userTotalBorrowBorrowFactorAdjusted.plus(borrowValueBorrowFactorAdjustedUSD));
|
|
287
|
-
borrowPosition.amount = (0, utils_1.positiveOrZero)(borrowPosition.amount.plus(borrowAmount));
|
|
288
|
-
borrowPosition.mintAddress = mint;
|
|
289
|
-
borrowPosition.marketValueRefreshed = (0, utils_1.positiveOrZero)(borrowPosition.marketValueRefreshed.plus(borrowValueUSD));
|
|
290
|
-
newBorrows.set(borrowPosition.reserveAddress, borrowPosition);
|
|
291
|
-
return {
|
|
292
|
-
borrows: newBorrows,
|
|
293
|
-
stats: newStats,
|
|
294
|
-
};
|
|
254
|
+
return newDeposits;
|
|
295
255
|
}
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
256
|
+
simulateBorrowChange(obligationBorrows, changeInLamports, changeReserve) {
|
|
257
|
+
const newBorrows = [];
|
|
258
|
+
for (let i = 0; i < obligationBorrows.length; i++) {
|
|
259
|
+
if (obligationBorrows[i].borrowReserve.equals(changeReserve)) {
|
|
260
|
+
const borrow = Object.assign({}, obligationBorrows[i]);
|
|
261
|
+
const newBorrowedAmount = new fraction_1.Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);
|
|
262
|
+
const newBorrowedAmountSf = fraction_1.Fraction.fromDecimal((0, utils_1.positiveOrZero)(newBorrowedAmount)).getValue();
|
|
263
|
+
borrow.borrowedAmountSf = newBorrowedAmountSf;
|
|
264
|
+
newBorrows.push(new types_1.ObligationLiquidity(borrow));
|
|
303
265
|
}
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
for (const kaminoReserve of reserves.values()) {
|
|
307
|
-
if (kaminoReserve.getLiquidityMint().equals(mint)) {
|
|
308
|
-
reserve = kaminoReserve;
|
|
266
|
+
else {
|
|
267
|
+
newBorrows.push(obligationBorrows[i]);
|
|
309
268
|
}
|
|
310
269
|
}
|
|
311
|
-
|
|
312
|
-
throw new Error(`No reserve found for mint ${mint}`);
|
|
313
|
-
}
|
|
314
|
-
if (!depositPosition) {
|
|
315
|
-
depositPosition = {
|
|
316
|
-
reserveAddress: reserve.address,
|
|
317
|
-
mintAddress: mint,
|
|
318
|
-
amount: new decimal_js_1.default(0),
|
|
319
|
-
marketValueRefreshed: new decimal_js_1.default(0),
|
|
320
|
-
};
|
|
321
|
-
}
|
|
322
|
-
if (!reserve.state.config.elevationGroups.includes(this.state.elevationGroup)) {
|
|
323
|
-
throw new Error(`User would have to downgrade the elevation group in order to be able to deposit in this reserve`);
|
|
324
|
-
}
|
|
325
|
-
const { maxLtv, liquidationLtv } = this.getLtvForReserve(market, reserve);
|
|
326
|
-
const supplyAmount = amount; //.mul(reserve.getCollateralExchangeRate()).floor();
|
|
327
|
-
const supplyAmountMultiplierUSD = supplyAmount
|
|
328
|
-
.mul(reserve.getOracleMarketPrice())
|
|
329
|
-
.dividedBy('1'.concat(Array(reserve.stats.decimals + 1).join('0')));
|
|
330
|
-
newStats.userTotalDeposit = (0, utils_1.positiveOrZero)(newStats.userTotalDeposit.plus(supplyAmountMultiplierUSD));
|
|
331
|
-
newStats.borrowLimit = (0, utils_1.positiveOrZero)(newStats.borrowLimit.plus(supplyAmountMultiplierUSD.mul(maxLtv)));
|
|
332
|
-
newStats.borrowLiquidationLimit = (0, utils_1.positiveOrZero)(newStats.borrowLiquidationLimit.plus(supplyAmountMultiplierUSD.mul(liquidationLtv)));
|
|
333
|
-
newStats.liquidationLtv = (0, utils_1.valueOrZero)(newStats.borrowLiquidationLimit.div(newStats.userTotalDeposit));
|
|
334
|
-
depositPosition.amount = (0, utils_1.positiveOrZero)(depositPosition.amount.plus(amount));
|
|
335
|
-
depositPosition.mintAddress = mint;
|
|
336
|
-
depositPosition.marketValueRefreshed = (0, utils_1.positiveOrZero)(depositPosition.marketValueRefreshed.plus(supplyAmount.mul(reserve.getOracleMarketPrice()).dividedBy(reserve.getMintFactor())));
|
|
337
|
-
newDeposits.set(depositPosition.reserveAddress, depositPosition);
|
|
338
|
-
return {
|
|
339
|
-
deposits: newDeposits,
|
|
340
|
-
stats: newStats,
|
|
341
|
-
};
|
|
270
|
+
return newBorrows;
|
|
342
271
|
}
|
|
343
272
|
/**
|
|
344
273
|
* Calculate the newly modified stats of the obligation
|
|
345
274
|
*/
|
|
346
|
-
// TODO: Elevation group problems
|
|
347
275
|
// TODO: Shall we set up position limits?
|
|
348
276
|
getSimulatedObligationStats(params) {
|
|
349
|
-
|
|
277
|
+
var _a;
|
|
278
|
+
const { amountCollateral, amountDebt, action, mintCollateral, mintDebt, market } = params;
|
|
350
279
|
let newStats = Object.assign({}, this.refreshedStats);
|
|
280
|
+
const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(market, this.state, params.slot);
|
|
281
|
+
const elevationGroup = (_a = params.elevationGroupOverride) !== null && _a !== void 0 ? _a : this.state.elevationGroup;
|
|
351
282
|
let newDeposits = new utils_2.PubkeyHashMap([...this.deposits.entries()]);
|
|
352
283
|
let newBorrows = new utils_2.PubkeyHashMap([...this.borrows.entries()]);
|
|
284
|
+
// Any action can impact both deposit stats and borrow stats if elevation group is changed
|
|
285
|
+
// so we have to recalculate the entire position, not just an updated deposit or borrow
|
|
286
|
+
// as both LTVs and borrow factors can change, affecting all calcs
|
|
287
|
+
const collateralReserve = mintCollateral ? market.getReserveByMint(mintCollateral).address : undefined;
|
|
288
|
+
const debtReserve = mintDebt ? market.getReserveByMint(mintDebt).address : undefined;
|
|
289
|
+
let newObligationDeposits = this.state.deposits;
|
|
290
|
+
let newObligationBorrows = this.state.borrows;
|
|
353
291
|
switch (action) {
|
|
354
292
|
case 'deposit': {
|
|
355
293
|
if (amountCollateral === undefined || mintCollateral === undefined) {
|
|
356
294
|
throw Error('amountCollateral & mintCollateral are required for deposit action');
|
|
357
295
|
}
|
|
358
|
-
|
|
359
|
-
newStats = stats;
|
|
360
|
-
newDeposits = deposits;
|
|
296
|
+
newObligationDeposits = this.simulateDepositChange(this.state.deposits, amountCollateral.toNumber(), collateralReserve, collateralExchangeRates);
|
|
361
297
|
break;
|
|
362
298
|
}
|
|
363
299
|
case 'borrow': {
|
|
364
300
|
if (amountDebt === undefined || mintDebt === undefined) {
|
|
365
301
|
throw Error('amountDebt & mintDebt are required for borrow action');
|
|
366
302
|
}
|
|
367
|
-
|
|
368
|
-
newStats = stats;
|
|
369
|
-
newBorrows = borrows;
|
|
303
|
+
newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.toNumber(), debtReserve);
|
|
370
304
|
break;
|
|
371
305
|
}
|
|
372
306
|
case 'repay': {
|
|
373
307
|
if (amountDebt === undefined || mintDebt === undefined) {
|
|
374
308
|
throw Error('amountDebt & mintDebt are required for repay action');
|
|
375
309
|
}
|
|
376
|
-
|
|
377
|
-
newStats = stats;
|
|
378
|
-
newBorrows = borrows;
|
|
310
|
+
newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.neg().toNumber(), debtReserve);
|
|
379
311
|
break;
|
|
380
312
|
}
|
|
381
313
|
case 'withdraw': {
|
|
382
314
|
if (amountCollateral === undefined || mintCollateral === undefined) {
|
|
383
315
|
throw Error('amountCollateral & mintCollateral are required for withdraw action');
|
|
384
316
|
}
|
|
385
|
-
|
|
386
|
-
newStats = stats;
|
|
387
|
-
newDeposits = deposits;
|
|
317
|
+
newObligationDeposits = this.simulateDepositChange(this.state.deposits, amountCollateral.neg().toNumber(), collateralReserve, collateralExchangeRates);
|
|
388
318
|
break;
|
|
389
319
|
}
|
|
390
320
|
case 'depositAndBorrow': {
|
|
@@ -394,11 +324,8 @@ class KaminoObligation {
|
|
|
394
324
|
mintDebt === undefined) {
|
|
395
325
|
throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for depositAndBorrow action');
|
|
396
326
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
newStats = stats;
|
|
400
|
-
newDeposits = deposits;
|
|
401
|
-
newBorrows = borrows;
|
|
327
|
+
newObligationDeposits = this.simulateDepositChange(this.state.deposits, amountCollateral.toNumber(), collateralReserve, collateralExchangeRates);
|
|
328
|
+
newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.toNumber(), debtReserve);
|
|
402
329
|
break;
|
|
403
330
|
}
|
|
404
331
|
case 'repayAndWithdraw': {
|
|
@@ -408,17 +335,18 @@ class KaminoObligation {
|
|
|
408
335
|
mintDebt === undefined) {
|
|
409
336
|
throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for repayAndWithdraw action');
|
|
410
337
|
}
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
newStats = statsAfterWithdraw;
|
|
414
|
-
newDeposits = deposits;
|
|
415
|
-
newBorrows = borrows;
|
|
338
|
+
newObligationDeposits = this.simulateDepositChange(this.state.deposits, amountCollateral.neg().toNumber(), collateralReserve, collateralExchangeRates);
|
|
339
|
+
newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.neg().toNumber(), debtReserve);
|
|
416
340
|
break;
|
|
417
341
|
}
|
|
418
342
|
default: {
|
|
419
343
|
throw Error(`Invalid action type ${action} for getSimulatedObligationStats`);
|
|
420
344
|
}
|
|
421
345
|
}
|
|
346
|
+
const { borrows, deposits, refreshedStats } = this.calculatePositions(market, newObligationDeposits, newObligationBorrows, elevationGroup, collateralExchangeRates, cumulativeBorrowRates);
|
|
347
|
+
newStats = refreshedStats;
|
|
348
|
+
newDeposits = deposits;
|
|
349
|
+
newBorrows = borrows;
|
|
422
350
|
newStats.netAccountValue = newStats.userTotalDeposit.minus(newStats.userTotalBorrow);
|
|
423
351
|
newStats.loanToValue = (0, utils_1.valueOrZero)(newStats.userTotalBorrowBorrowFactorAdjusted.dividedBy(newStats.userTotalDeposit));
|
|
424
352
|
newStats.leverage = (0, utils_1.valueOrZero)(newStats.userTotalDeposit.dividedBy(newStats.netAccountValue));
|
|
@@ -428,17 +356,12 @@ class KaminoObligation {
|
|
|
428
356
|
borrows: newBorrows,
|
|
429
357
|
};
|
|
430
358
|
}
|
|
431
|
-
|
|
432
|
-
return KaminoObligation.calculateObligationDeposits(market, obligation, collateralExchangeRates, obligation.elevationGroup, getPx);
|
|
433
|
-
}
|
|
434
|
-
calculateBorrows(market, obligation, cumulativeBorrowRates, getPx) {
|
|
435
|
-
return KaminoObligation.calculateObligationBorrows(market, obligation, cumulativeBorrowRates, obligation.elevationGroup, getPx);
|
|
436
|
-
}
|
|
437
|
-
calculatePositions(market, obligation, collateralExchangeRates, cumulativeBorrowRates) {
|
|
359
|
+
calculatePositions(market, obligationDeposits, obligationBorrows, elevationGroup, collateralExchangeRates, cumulativeBorrowRates) {
|
|
438
360
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
439
|
-
const depositStatsOraclePrice =
|
|
440
|
-
const borrowStatsOraclePrice =
|
|
361
|
+
const depositStatsOraclePrice = KaminoObligation.calculateObligationDeposits(market, obligationDeposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
362
|
+
const borrowStatsOraclePrice = KaminoObligation.calculateObligationBorrows(market, obligationBorrows, cumulativeBorrowRates, elevationGroup, getOraclePx);
|
|
441
363
|
const netAccountValueScopeRefreshed = depositStatsOraclePrice.userTotalDeposit.minus(borrowStatsOraclePrice.userTotalBorrow);
|
|
364
|
+
// TODO: Fix this?
|
|
442
365
|
const potentialElevationGroupUpdate = 0;
|
|
443
366
|
return {
|
|
444
367
|
deposits: depositStatsOraclePrice.deposits,
|
|
@@ -458,17 +381,17 @@ class KaminoObligation {
|
|
|
458
381
|
},
|
|
459
382
|
};
|
|
460
383
|
}
|
|
461
|
-
static calculateObligationDeposits(market,
|
|
384
|
+
static calculateObligationDeposits(market, obligationDeposits, collateralExchangeRates, elevationGroup, getPx) {
|
|
462
385
|
let userTotalDeposit = new decimal_js_1.default(0);
|
|
463
386
|
let userTotalCollateralDeposit = new decimal_js_1.default(0);
|
|
464
387
|
let borrowLimit = new decimal_js_1.default(0);
|
|
465
388
|
let borrowLiquidationLimit = new decimal_js_1.default(0);
|
|
466
389
|
const deposits = new utils_2.PubkeyHashMap();
|
|
467
|
-
for (let i = 0; i <
|
|
468
|
-
if (!(0, utils_2.isNotNullPubkey)(
|
|
390
|
+
for (let i = 0; i < obligationDeposits.length; i++) {
|
|
391
|
+
if (!(0, utils_2.isNotNullPubkey)(obligationDeposits[i].depositReserve)) {
|
|
469
392
|
continue;
|
|
470
393
|
}
|
|
471
|
-
const deposit =
|
|
394
|
+
const deposit = obligationDeposits[i];
|
|
472
395
|
const reserve = market.getReserveByAddress(deposit.depositReserve);
|
|
473
396
|
if (!reserve) {
|
|
474
397
|
throw new Error(`Obligation contains a deposit belonging to reserve: ${deposit.depositReserve} but the reserve was not found on the market. Deposit amount: ${deposit.depositedAmount}`);
|
|
@@ -506,16 +429,16 @@ class KaminoObligation {
|
|
|
506
429
|
borrowLiquidationLimit,
|
|
507
430
|
};
|
|
508
431
|
}
|
|
509
|
-
static calculateObligationBorrows(market,
|
|
432
|
+
static calculateObligationBorrows(market, obligationBorrows, cumulativeBorrowRates, elevationGroup, getPx) {
|
|
510
433
|
let userTotalBorrow = new decimal_js_1.default(0);
|
|
511
434
|
let userTotalBorrowBorrowFactorAdjusted = new decimal_js_1.default(0);
|
|
512
435
|
let positions = 0;
|
|
513
436
|
const borrows = new utils_2.PubkeyHashMap();
|
|
514
|
-
for (let i = 0; i <
|
|
515
|
-
if (!(0, utils_2.isNotNullPubkey)(
|
|
437
|
+
for (let i = 0; i < obligationBorrows.length; i++) {
|
|
438
|
+
if (!(0, utils_2.isNotNullPubkey)(obligationBorrows[i].borrowReserve)) {
|
|
516
439
|
continue;
|
|
517
440
|
}
|
|
518
|
-
const borrow =
|
|
441
|
+
const borrow = obligationBorrows[i];
|
|
519
442
|
const reserve = market.getReserveByAddress(borrow.borrowReserve);
|
|
520
443
|
if (!reserve) {
|
|
521
444
|
throw new Error(`Obligation contains a borrow belonging to reserve: ${borrow.borrowReserve} but the reserve was not found on the market. Borrow amount: ${KaminoObligation.getBorrowAmount(borrow)}`);
|
|
@@ -554,6 +477,15 @@ class KaminoObligation {
|
|
|
554
477
|
positions,
|
|
555
478
|
};
|
|
556
479
|
}
|
|
480
|
+
getMaxLoanLtvGivenElevationGroup(market, elevationGroup, slot) {
|
|
481
|
+
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
482
|
+
const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
483
|
+
const { borrowLimit, userTotalDeposit } = KaminoObligation.calculateObligationDeposits(market, this.state.deposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
484
|
+
if (borrowLimit.eq(0) || userTotalDeposit.eq(0)) {
|
|
485
|
+
return new decimal_js_1.default(0);
|
|
486
|
+
}
|
|
487
|
+
return borrowLimit.div(userTotalDeposit);
|
|
488
|
+
}
|
|
557
489
|
/*
|
|
558
490
|
How much of a given token can a user borrow extra given an elevation group,
|
|
559
491
|
regardless of caps and liquidity or assuming infinite liquidity and infinite caps,
|
|
@@ -578,8 +510,8 @@ class KaminoObligation {
|
|
|
578
510
|
const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);
|
|
579
511
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
580
512
|
const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
581
|
-
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
582
|
-
const { userTotalBorrowBorrowFactorAdjusted } = KaminoObligation.calculateObligationBorrows(market, this.state, cumulativeBorrowRates, elevationGroup, getOraclePx);
|
|
513
|
+
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state.deposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
514
|
+
const { userTotalBorrowBorrowFactorAdjusted } = KaminoObligation.calculateObligationBorrows(market, this.state.borrows, cumulativeBorrowRates, elevationGroup, getOraclePx);
|
|
583
515
|
const maxObligationBorrowPower = borrowLimit // adjusted available amount
|
|
584
516
|
.minus(userTotalBorrowBorrowFactorAdjusted)
|
|
585
517
|
.div(borrowFactor)
|
|
@@ -662,7 +594,7 @@ class KaminoObligation {
|
|
|
662
594
|
// Check if the loan can be migrated based on LTV
|
|
663
595
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
664
596
|
const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
665
|
-
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
597
|
+
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state.deposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
666
598
|
const isEligibleBasedOnLtv = this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.lte(borrowLimit);
|
|
667
599
|
return isEligibleBasedOnLtv;
|
|
668
600
|
}
|
|
@@ -713,7 +645,7 @@ class KaminoObligation {
|
|
|
713
645
|
}
|
|
714
646
|
}
|
|
715
647
|
const elevationGroupActivated = reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;
|
|
716
|
-
const borrowFactor =
|
|
648
|
+
const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);
|
|
717
649
|
const maxObligationBorrowPower = this.refreshedStats.borrowLimit // adjusted available amount
|
|
718
650
|
.minus(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)
|
|
719
651
|
.div(borrowFactor)
|
|
@@ -785,7 +717,7 @@ class KaminoObligation {
|
|
|
785
717
|
if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.equals(new decimal_js_1.default(0))) {
|
|
786
718
|
return new decimal_js_1.default(userDepositPositionAmount);
|
|
787
719
|
}
|
|
788
|
-
const { maxLtv: reserveMaxLtv } =
|
|
720
|
+
const { maxLtv: reserveMaxLtv } = KaminoObligation.getLtvForReserve(market, depositReserve, this.state.elevationGroup);
|
|
789
721
|
// bf adjusted debt value > allowed_borrow_value
|
|
790
722
|
if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.gte(this.refreshedStats.borrowLimit)) {
|
|
791
723
|
return new decimal_js_1.default(0);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"obligation.js","sourceRoot":"","sources":["../../src/classes/obligation.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-classes-per-file */\nimport { PublicKey } from '@solana/web3.js';\nimport Decimal from 'decimal.js';\nimport { KaminoReserve } from './reserve';\nimport { Obligation } from '../idl_codegen/accounts';\nimport { ElevationGroupDescription, KaminoMarket } from './market';\nimport BN from 'bn.js';\nimport { Fraction } from './fraction';\nimport { ObligationCollateral, ObligationLiquidity } from '../idl_codegen/types';\nimport { positiveOrZero, valueOrZero } from './utils';\nimport { isNotNullPubkey, PubkeyHashMap, U64_MAX } from '../utils';\nimport { ActionType } from './action';\n\nexport type Position = {\n reserveAddress: PublicKey;\n mintAddress: PublicKey;\n /**\n * Amount of tokens in lamports, including decimal places for interest accrued (no borrow factor weighting)\n */\n amount: Decimal;\n /**\n * Market value of the position in USD (no borrow factor weighting)\n */\n marketValueRefreshed: Decimal;\n};\n\nexport type ObligationStats = {\n userTotalDeposit: Decimal;\n userTotalBorrow: Decimal;\n userTotalBorrowBorrowFactorAdjusted: Decimal;\n borrowLimit: Decimal;\n borrowLiquidationLimit: Decimal;\n borrowUtilization: Decimal;\n netAccountValue: Decimal;\n loanToValue: Decimal;\n liquidationLtv: Decimal;\n leverage: Decimal;\n potentialElevationGroupUpdate: number;\n};\n\ninterface BorrowStats {\n borrows: Map<PublicKey, Position>;\n userTotalBorrow: Decimal;\n userTotalBorrowBorrowFactorAdjusted: Decimal;\n positions: number;\n}\n\nexport class KaminoObligation {\n obligationAddress: PublicKey;\n\n state: Obligation;\n\n /**\n * Deposits stored in a map of reserve address to position\n */\n deposits: Map<PublicKey, Position>;\n\n /**\n * Borrows stored in a map of reserve address to position\n */\n borrows: Map<PublicKey, Position>;\n\n refreshedStats: ObligationStats;\n\n obligationTag: number;\n\n /**\n * Initialise a new Obligation from the deserialized state\n * @param market\n * @param obligationAddress\n * @param obligation\n * @param collateralExchangeRates - rates from the market by reserve address, will be calculated if not provided\n * @param cumulativeBorrowRates - rates from the market by reserve address, will be calculated if not provided\n */\n constructor(\n market: KaminoMarket,\n obligationAddress: PublicKey,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>\n ) {\n this.obligationAddress = obligationAddress;\n this.state = obligation;\n const { borrows, deposits, refreshedStats } = this.calculatePositions(\n market,\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n this.deposits = deposits;\n this.borrows = borrows;\n this.refreshedStats = refreshedStats;\n this.obligationTag = obligation.tag.toNumber();\n }\n\n static async load(kaminoMarket: KaminoMarket, obligationAddress: PublicKey): Promise<KaminoObligation | null> {\n const res = await kaminoMarket.getConnection().getAccountInfoAndContext(obligationAddress);\n if (res.value === null) {\n return null;\n }\n const accInfo = res.value;\n if (!accInfo.owner.equals(kaminoMarket.programId)) {\n throw new Error(\"account doesn't belong to this program\");\n }\n const obligation = Obligation.decode(accInfo.data);\n\n if (obligation === null) {\n return null;\n }\n const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(\n kaminoMarket,\n obligation,\n res.context.slot\n );\n return new KaminoObligation(\n kaminoMarket,\n obligationAddress,\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n }\n\n static async loadAll(\n kaminoMarket: KaminoMarket,\n obligationAddresses: PublicKey[],\n slot?: number\n ): Promise<(KaminoObligation | null)[]> {\n let currentSlot = slot;\n let obligations: (Obligation | null)[];\n if (!currentSlot) {\n [currentSlot, obligations] = await Promise.all([\n kaminoMarket.getConnection().getSlot(),\n Obligation.fetchMultiple(kaminoMarket.getConnection(), obligationAddresses, kaminoMarket.programId),\n ]);\n } else {\n obligations = await Obligation.fetchMultiple(\n kaminoMarket.getConnection(),\n obligationAddresses,\n kaminoMarket.programId\n );\n }\n const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();\n const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (const obligation of obligations) {\n if (obligation !== null) {\n KaminoObligation.addRatesForObligation(\n kaminoMarket,\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates,\n currentSlot\n );\n }\n }\n\n return obligations.map((obligation, i) => {\n if (obligation === null) {\n return null;\n }\n return new KaminoObligation(\n kaminoMarket,\n obligationAddresses[i],\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n });\n }\n\n /**\n * @returns the obligation borrows as a list\n */\n getBorrows(): Array<Position> {\n return [...this.borrows.values()];\n }\n\n /**\n * @returns the obligation borrows as a list\n */\n getDeposits(): Array<Position> {\n return [...this.deposits.values()];\n }\n\n /**\n * @returns the total deposited value of the obligation (sum of all deposits)\n */\n getDepositedValue(): Decimal {\n return new Fraction(this.state.depositedValueSf).toDecimal();\n }\n\n /**\n * @returns the total borrowed value of the obligation (sum of all borrows -- no borrow factor)\n */\n getBorrowedMarketValue(): Decimal {\n return new Fraction(this.state.borrowedAssetsMarketValueSf).toDecimal();\n }\n\n /**\n * @returns the total borrowed value of the obligation (sum of all borrows -- with borrow factor weighting)\n */\n getBorrowedMarketValueBFAdjusted(): Decimal {\n return new Fraction(this.state.borrowFactorAdjustedDebtValueSf).toDecimal();\n }\n\n /**\n * @returns total borrow power of the obligation, relative to max LTV of each asset's reserve\n */\n getAllowedBorrowValue(): Decimal {\n return new Fraction(this.state.allowedBorrowValueSf).toDecimal();\n }\n\n /**\n * @returns the borrow value at which the obligation gets liquidatable\n * (relative to the liquidation threshold of each asset's reserve)\n */\n getUnhealthyBorrowValue(): Decimal {\n return new Fraction(this.state.unhealthyBorrowValueSf).toDecimal();\n }\n\n /**\n *\n * @returns Market value of the deposit in the specified obligation collateral/deposit asset (USD)\n */\n getDepositMarketValue(deposit: ObligationCollateral): Decimal {\n return new Fraction(deposit.marketValueSf).toDecimal();\n }\n\n getBorrowByReserve(reserve: PublicKey): Position | undefined {\n return this.borrows.get(reserve);\n }\n\n getDepositByReserve(reserve: PublicKey): Position | undefined {\n return this.deposits.get(reserve);\n }\n\n getBorrowByMint(mint: PublicKey): Position | undefined {\n for (const value of this.borrows.values()) {\n if (value.mintAddress.equals(mint)) {\n return value;\n }\n }\n return undefined;\n }\n\n getDepositByMint(mint: PublicKey): Position | undefined {\n for (const value of this.deposits.values()) {\n if (value.mintAddress.equals(mint)) {\n return value;\n }\n }\n return undefined;\n }\n\n /**\n *\n * @returns Market value of the borrow in the specified obligation liquidity/borrow asset (USD) (no borrow factor weighting)\n */\n getBorrowMarketValue(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.marketValueSf).toDecimal();\n }\n\n /**\n *\n * @returns Market value of the borrow in the specified obligation liquidity/borrow asset (USD) (with borrow factor weighting)\n */\n getBorrowMarketValueBFAdjusted(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.borrowFactorAdjustedMarketValueSf).toDecimal();\n }\n\n /**\n * Calculate the current ratio of borrowed value to deposited value\n */\n loanToValue(): Decimal {\n if (this.refreshedStats.userTotalDeposit.eq(0)) {\n return new Decimal(0);\n }\n return this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.div(this.refreshedStats.userTotalDeposit);\n }\n\n /**\n * @returns the total number of positions (deposits + borrows)\n */\n getNumberOfPositions(): number {\n return this.deposits.size + this.borrows.size;\n }\n\n getNetAccountValue(): Decimal {\n return this.refreshedStats.netAccountValue;\n }\n\n /**\n * Get the loan to value and liquidation loan to value for a collateral token reserve as ratios, accounting for the obligation elevation group if it is active\n * @param market\n * @param reserve\n */\n public getLtvForReserve(market: KaminoMarket, reserve: KaminoReserve): { maxLtv: Decimal; liquidationLtv: Decimal } {\n return KaminoObligation.getLtvForReserve(market, reserve, this.state.elevationGroup);\n }\n\n /**\n * Get the borrow factor for a borrow reserve, accounting for the obligation elevation group if it is active\n * @param reserve\n */\n public getBorrowFactorForReserve(reserve: KaminoReserve): Decimal {\n return KaminoObligation.getBorrowFactorForReserve(reserve, this.state.elevationGroup);\n }\n\n /**\n * @returns the potential elevation groups the obligation qualifies for\n */\n getElevationGroups(kaminoMarket: KaminoMarket): Array<number> {\n const reserves = new PubkeyHashMap<PublicKey, KaminoReserve>();\n for (const deposit of this.state.deposits.values()) {\n if (isNotNullPubkey(deposit.depositReserve) && !reserves.has(deposit.depositReserve)) {\n reserves.set(deposit.depositReserve, kaminoMarket.getReserveByAddress(deposit.depositReserve)!);\n }\n }\n for (const borrow of this.state.borrows.values()) {\n if (isNotNullPubkey(borrow.borrowReserve) && !reserves.has(borrow.borrowReserve)) {\n reserves.set(borrow.borrowReserve, kaminoMarket.getReserveByAddress(borrow.borrowReserve)!);\n }\n }\n return KaminoObligation.getElevationGroupsForReserves([...reserves.values()]);\n }\n\n static getElevationGroupsForReserves(reserves: Array<KaminoReserve>): Array<number> {\n const elevationGroupsCounts = new Map<number, number>();\n for (const reserve of reserves) {\n for (const elevationGroup of reserve.state.config.elevationGroups) {\n if (elevationGroup !== 0) {\n const count = elevationGroupsCounts.get(elevationGroup);\n if (count) {\n elevationGroupsCounts.set(elevationGroup, count + 1);\n } else {\n elevationGroupsCounts.set(elevationGroup, 1);\n }\n }\n }\n }\n const activeElevationGroups = new Array<number>();\n for (const [group, count] of elevationGroupsCounts.entries()) {\n if (count === reserves.length) {\n activeElevationGroups.push(group);\n }\n }\n return activeElevationGroups;\n }\n\n calculateSimulatedBorrow(\n oldStats: ObligationStats,\n oldBorrows: Map<PublicKey, Position>,\n borrowAmount: Decimal,\n mint: PublicKey,\n reserves: Map<PublicKey, KaminoReserve>\n ): {\n stats: ObligationStats;\n borrows: Map<PublicKey, Position>;\n } {\n const newStats = { ...oldStats };\n const newBorrows = new PubkeyHashMap<PublicKey, Position>([...oldBorrows.entries()]);\n let borrowPosition: Position | undefined = undefined;\n for (const oldBorrow of oldBorrows.values()) {\n if (oldBorrow.mintAddress.equals(mint)) {\n borrowPosition = { ...oldBorrow };\n }\n }\n let reserve: KaminoReserve | undefined = undefined;\n for (const kaminoReserve of reserves.values()) {\n if (kaminoReserve.getLiquidityMint().equals(mint)) {\n reserve = kaminoReserve;\n }\n }\n\n if (!reserve) {\n throw new Error(`No reserve found for mint ${mint}`);\n }\n\n if (!borrowPosition) {\n borrowPosition = {\n reserveAddress: reserve!.address,\n mintAddress: mint,\n amount: new Decimal(0),\n marketValueRefreshed: new Decimal(0),\n };\n }\n\n if (!reserve.state.config.elevationGroups.includes(this.state.elevationGroup)) {\n throw new Error(\n `User would have to downgrade the elevation group in order to be able to borrow from this reserve`\n );\n }\n\n const borrowFactor = this.getBorrowFactorForReserve(reserve);\n\n const borrowValueUSD = borrowAmount.mul(reserve.getOracleMarketPrice()).dividedBy(reserve.getMintFactor());\n\n const borrowValueBorrowFactorAdjustedUSD = borrowValueUSD.mul(borrowFactor);\n\n newStats.userTotalBorrow = positiveOrZero(newStats.userTotalBorrow.plus(borrowValueUSD));\n newStats.userTotalBorrowBorrowFactorAdjusted = positiveOrZero(\n newStats.userTotalBorrowBorrowFactorAdjusted.plus(borrowValueBorrowFactorAdjustedUSD)\n );\n\n borrowPosition.amount = positiveOrZero(borrowPosition.amount.plus(borrowAmount));\n borrowPosition.mintAddress = mint;\n borrowPosition.marketValueRefreshed = positiveOrZero(borrowPosition.marketValueRefreshed.plus(borrowValueUSD));\n\n newBorrows.set(borrowPosition.reserveAddress, borrowPosition);\n return {\n borrows: newBorrows,\n stats: newStats,\n };\n }\n\n calculateSimulatedDeposit(\n oldStats: ObligationStats,\n oldDeposits: Map<PublicKey, Position>,\n amount: Decimal,\n mint: PublicKey,\n reserves: Map<PublicKey, KaminoReserve>,\n market: KaminoMarket\n ): {\n stats: ObligationStats;\n deposits: Map<PublicKey, Position>;\n } {\n const newStats = { ...oldStats };\n const newDeposits = new PubkeyHashMap<PublicKey, Position>([...oldDeposits.entries()]);\n\n let depositPosition: Position | undefined = undefined;\n for (const oldDeposit of oldDeposits.values()) {\n if (oldDeposit.mintAddress.equals(mint)) {\n depositPosition = { ...oldDeposit };\n }\n }\n let reserve: KaminoReserve | undefined = undefined;\n for (const kaminoReserve of reserves.values()) {\n if (kaminoReserve.getLiquidityMint().equals(mint)) {\n reserve = kaminoReserve;\n }\n }\n if (!reserve) {\n throw new Error(`No reserve found for mint ${mint}`);\n }\n\n if (!depositPosition) {\n depositPosition = {\n reserveAddress: reserve!.address,\n mintAddress: mint,\n amount: new Decimal(0),\n marketValueRefreshed: new Decimal(0),\n };\n }\n\n if (!reserve.state.config.elevationGroups.includes(this.state.elevationGroup)) {\n throw new Error(\n `User would have to downgrade the elevation group in order to be able to deposit in this reserve`\n );\n }\n const { maxLtv, liquidationLtv } = this.getLtvForReserve(market, reserve);\n\n const supplyAmount = amount; //.mul(reserve.getCollateralExchangeRate()).floor();\n const supplyAmountMultiplierUSD = supplyAmount\n .mul(reserve.getOracleMarketPrice())\n .dividedBy('1'.concat(Array(reserve.stats.decimals + 1).join('0')));\n\n newStats.userTotalDeposit = positiveOrZero(newStats.userTotalDeposit.plus(supplyAmountMultiplierUSD));\n newStats.borrowLimit = positiveOrZero(newStats.borrowLimit.plus(supplyAmountMultiplierUSD.mul(maxLtv)));\n newStats.borrowLiquidationLimit = positiveOrZero(\n newStats.borrowLiquidationLimit.plus(supplyAmountMultiplierUSD.mul(liquidationLtv))\n );\n newStats.liquidationLtv = valueOrZero(newStats.borrowLiquidationLimit.div(newStats.userTotalDeposit));\n\n depositPosition.amount = positiveOrZero(depositPosition.amount.plus(amount));\n depositPosition.mintAddress = mint;\n depositPosition.marketValueRefreshed = positiveOrZero(\n depositPosition.marketValueRefreshed.plus(\n supplyAmount.mul(reserve.getOracleMarketPrice()).dividedBy(reserve.getMintFactor())\n )\n );\n\n newDeposits.set(depositPosition.reserveAddress, depositPosition);\n\n return {\n deposits: newDeposits,\n stats: newStats,\n };\n }\n\n /**\n * Calculate the newly modified stats of the obligation\n */\n // TODO: Elevation group problems\n // TODO: Shall we set up position limits?\n getSimulatedObligationStats(params: {\n amountCollateral?: Decimal;\n amountDebt?: Decimal;\n action: ActionType;\n mintCollateral?: PublicKey;\n mintDebt?: PublicKey;\n market: KaminoMarket;\n reserves: Map<PublicKey, KaminoReserve>;\n }): {\n stats: ObligationStats;\n deposits: Map<PublicKey, Position>;\n borrows: Map<PublicKey, Position>;\n } {\n const { amountCollateral, amountDebt, action, mintCollateral, mintDebt, market, reserves } = params;\n let newStats = { ...this.refreshedStats };\n let newDeposits: Map<PublicKey, Position> = new PubkeyHashMap<PublicKey, Position>([...this.deposits.entries()]);\n let newBorrows: Map<PublicKey, Position> = new PubkeyHashMap<PublicKey, Position>([...this.borrows.entries()]);\n\n switch (action) {\n case 'deposit': {\n if (amountCollateral === undefined || mintCollateral === undefined) {\n throw Error('amountCollateral & mintCollateral are required for deposit action');\n }\n const { stats, deposits } = this.calculateSimulatedDeposit(\n this.refreshedStats,\n this.deposits,\n amountCollateral,\n mintCollateral,\n reserves,\n market\n );\n\n newStats = stats;\n newDeposits = deposits;\n\n break;\n }\n case 'borrow': {\n if (amountDebt === undefined || mintDebt === undefined) {\n throw Error('amountDebt & mintDebt are required for borrow action');\n }\n const { stats, borrows } = this.calculateSimulatedBorrow(\n this.refreshedStats,\n this.borrows,\n amountDebt,\n mintDebt,\n reserves\n );\n newStats = stats;\n newBorrows = borrows;\n break;\n }\n case 'repay': {\n if (amountDebt === undefined || mintDebt === undefined) {\n throw Error('amountDebt & mintDebt are required for repay action');\n }\n const { stats, borrows } = this.calculateSimulatedBorrow(\n this.refreshedStats,\n this.borrows,\n new Decimal(amountDebt).neg(),\n mintDebt,\n reserves\n );\n newStats = stats;\n newBorrows = borrows;\n break;\n }\n\n case 'withdraw': {\n if (amountCollateral === undefined || mintCollateral === undefined) {\n throw Error('amountCollateral & mintCollateral are required for withdraw action');\n }\n const { stats, deposits } = this.calculateSimulatedDeposit(\n this.refreshedStats,\n this.deposits,\n new Decimal(amountCollateral).neg(),\n mintCollateral,\n reserves,\n market\n );\n newStats = stats;\n newDeposits = deposits;\n break;\n }\n case 'depositAndBorrow': {\n if (\n amountCollateral === undefined ||\n amountDebt === undefined ||\n mintCollateral === undefined ||\n mintDebt === undefined\n ) {\n throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for depositAndBorrow action');\n }\n const { stats: statsAfterDeposit, deposits } = this.calculateSimulatedDeposit(\n this.refreshedStats,\n this.deposits,\n amountCollateral,\n mintCollateral,\n reserves,\n market\n );\n const { stats, borrows } = this.calculateSimulatedBorrow(\n statsAfterDeposit,\n this.borrows,\n amountDebt,\n mintDebt,\n reserves\n );\n\n newStats = stats;\n newDeposits = deposits;\n newBorrows = borrows;\n break;\n }\n case 'repayAndWithdraw': {\n if (\n amountCollateral === undefined ||\n amountDebt === undefined ||\n mintCollateral === undefined ||\n mintDebt === undefined\n ) {\n throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for repayAndWithdraw action');\n }\n const { stats: statsAfterRepay, borrows } = this.calculateSimulatedBorrow(\n this.refreshedStats,\n this.borrows,\n new Decimal(amountDebt).neg(),\n mintDebt,\n reserves\n );\n const { stats: statsAfterWithdraw, deposits } = this.calculateSimulatedDeposit(\n statsAfterRepay,\n this.deposits,\n new Decimal(amountCollateral).neg(),\n mintCollateral,\n reserves,\n market\n );\n newStats = statsAfterWithdraw;\n newDeposits = deposits;\n newBorrows = borrows;\n break;\n }\n default: {\n throw Error(`Invalid action type ${action} for getSimulatedObligationStats`);\n }\n }\n newStats.netAccountValue = newStats.userTotalDeposit.minus(newStats.userTotalBorrow);\n newStats.loanToValue = valueOrZero(\n newStats.userTotalBorrowBorrowFactorAdjusted.dividedBy(newStats.userTotalDeposit)\n );\n newStats.leverage = valueOrZero(newStats.userTotalDeposit.dividedBy(newStats.netAccountValue));\n\n return {\n stats: newStats,\n deposits: newDeposits,\n borrows: newBorrows,\n };\n }\n\n estimateObligationInterestRate = (\n market: KaminoMarket,\n reserve: KaminoReserve,\n borrow: ObligationLiquidity,\n currentSlot: number\n ): Decimal => {\n const estimatedCumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(\n currentSlot,\n market.state.referralFeeBps\n );\n\n const currentCumulativeBorrowRate = KaminoObligation.getCumulativeBorrowRate(borrow);\n\n if (estimatedCumulativeBorrowRate.gt(currentCumulativeBorrowRate)) {\n return estimatedCumulativeBorrowRate.div(currentCumulativeBorrowRate);\n }\n\n return new Decimal(0);\n };\n\n private calculateDeposits(\n market: KaminoMarket,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n getPx: (reserve: KaminoReserve) => Decimal\n ): {\n deposits: Map<PublicKey, Position>;\n userTotalDeposit: Decimal;\n borrowLimit: Decimal;\n liquidationLtv: Decimal;\n borrowLiquidationLimit: Decimal;\n } {\n return KaminoObligation.calculateObligationDeposits(\n market,\n obligation,\n collateralExchangeRates,\n obligation.elevationGroup,\n getPx\n );\n }\n\n private calculateBorrows(\n market: KaminoMarket,\n obligation: Obligation,\n cumulativeBorrowRates: Map<PublicKey, Decimal>,\n getPx: (reserve: KaminoReserve) => Decimal\n ): BorrowStats {\n return KaminoObligation.calculateObligationBorrows(\n market,\n obligation,\n cumulativeBorrowRates,\n obligation.elevationGroup,\n getPx\n );\n }\n\n private calculatePositions(\n market: KaminoMarket,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>\n ): {\n borrows: Map<PublicKey, Position>;\n deposits: Map<PublicKey, Position>;\n refreshedStats: ObligationStats;\n } {\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const depositStatsOraclePrice = this.calculateDeposits(market, obligation, collateralExchangeRates, getOraclePx);\n const borrowStatsOraclePrice = this.calculateBorrows(market, obligation, cumulativeBorrowRates, getOraclePx);\n\n const netAccountValueScopeRefreshed = depositStatsOraclePrice.userTotalDeposit.minus(\n borrowStatsOraclePrice.userTotalBorrow\n );\n\n const potentialElevationGroupUpdate = 0;\n\n return {\n deposits: depositStatsOraclePrice.deposits,\n borrows: borrowStatsOraclePrice.borrows,\n refreshedStats: {\n borrowLimit: depositStatsOraclePrice.borrowLimit,\n borrowLiquidationLimit: depositStatsOraclePrice.borrowLiquidationLimit,\n userTotalBorrow: borrowStatsOraclePrice.userTotalBorrow,\n userTotalBorrowBorrowFactorAdjusted: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted,\n userTotalDeposit: depositStatsOraclePrice.userTotalDeposit,\n liquidationLtv: depositStatsOraclePrice.liquidationLtv,\n borrowUtilization: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted.dividedBy(\n depositStatsOraclePrice.borrowLimit\n ),\n netAccountValue: netAccountValueScopeRefreshed,\n leverage: depositStatsOraclePrice.userTotalDeposit.dividedBy(netAccountValueScopeRefreshed),\n loanToValue: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted.dividedBy(\n depositStatsOraclePrice.userTotalDeposit\n ),\n potentialElevationGroupUpdate,\n },\n };\n }\n\n public static calculateObligationDeposits(\n market: KaminoMarket,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal> | null,\n elevationGroup: number,\n getPx: (reserve: KaminoReserve) => Decimal\n ): {\n deposits: Map<PublicKey, Position>;\n userTotalDeposit: Decimal;\n userTotalCollateralDeposit: Decimal;\n borrowLimit: Decimal;\n liquidationLtv: Decimal;\n borrowLiquidationLimit: Decimal;\n } {\n let userTotalDeposit = new Decimal(0);\n let userTotalCollateralDeposit = new Decimal(0);\n let borrowLimit = new Decimal(0);\n let borrowLiquidationLimit = new Decimal(0);\n\n const deposits = new PubkeyHashMap<PublicKey, Position>();\n for (let i = 0; i < obligation.deposits.length; i++) {\n if (!isNotNullPubkey(obligation.deposits[i].depositReserve)) {\n continue;\n }\n const deposit = obligation.deposits[i];\n const reserve = market.getReserveByAddress(deposit.depositReserve);\n if (!reserve) {\n throw new Error(\n `Obligation contains a deposit belonging to reserve: ${deposit.depositReserve} but the reserve was not found on the market. Deposit amount: ${deposit.depositedAmount}`\n );\n }\n const { maxLtv, liquidationLtv } = KaminoObligation.getLtvForReserve(market, reserve, elevationGroup);\n\n let exchangeRate: Decimal;\n if (collateralExchangeRates !== null) {\n exchangeRate = collateralExchangeRates.get(reserve.address)!;\n } else {\n exchangeRate = reserve.getCollateralExchangeRate();\n }\n const supplyAmount = new Decimal(deposit.depositedAmount.toString()).div(exchangeRate);\n\n const depositValueUsd = supplyAmount.mul(getPx(reserve)).div(reserve.getMintFactor());\n\n userTotalDeposit = userTotalDeposit.add(depositValueUsd);\n\n if (!maxLtv.eq('0')) {\n userTotalCollateralDeposit = userTotalCollateralDeposit.add(depositValueUsd);\n }\n\n borrowLimit = borrowLimit.add(depositValueUsd.mul(maxLtv));\n borrowLiquidationLimit = borrowLiquidationLimit.add(depositValueUsd.mul(liquidationLtv));\n\n const position: Position = {\n reserveAddress: reserve.address,\n mintAddress: reserve.getLiquidityMint(),\n amount: supplyAmount,\n marketValueRefreshed: depositValueUsd,\n };\n deposits.set(reserve.address, position);\n }\n\n return {\n deposits,\n userTotalDeposit,\n userTotalCollateralDeposit,\n borrowLimit,\n liquidationLtv: valueOrZero(borrowLiquidationLimit.div(userTotalDeposit)),\n borrowLiquidationLimit,\n };\n }\n\n public static calculateObligationBorrows(\n market: KaminoMarket,\n obligation: Obligation,\n cumulativeBorrowRates: Map<PublicKey, Decimal> | null,\n elevationGroup: number,\n getPx: (reserve: KaminoReserve) => Decimal\n ): BorrowStats {\n let userTotalBorrow = new Decimal(0);\n let userTotalBorrowBorrowFactorAdjusted = new Decimal(0);\n let positions = 0;\n\n const borrows = new PubkeyHashMap<PublicKey, Position>();\n for (let i = 0; i < obligation.borrows.length; i++) {\n if (!isNotNullPubkey(obligation.borrows[i].borrowReserve)) {\n continue;\n }\n const borrow = obligation.borrows[i];\n const reserve = market.getReserveByAddress(borrow.borrowReserve);\n if (!reserve) {\n throw new Error(\n `Obligation contains a borrow belonging to reserve: ${\n borrow.borrowReserve\n } but the reserve was not found on the market. Borrow amount: ${KaminoObligation.getBorrowAmount(borrow)}`\n );\n }\n\n const obligationCumulativeBorrowRate = KaminoObligation.getCumulativeBorrowRate(borrow);\n let cumulativeBorrowRate;\n if (cumulativeBorrowRates !== null) {\n cumulativeBorrowRate = cumulativeBorrowRates.get(reserve.address)!;\n } else {\n cumulativeBorrowRate = reserve.getCumulativeBorrowRate();\n }\n\n const borrowAmount = KaminoObligation.getBorrowAmount(borrow)\n .mul(cumulativeBorrowRate)\n .dividedBy(obligationCumulativeBorrowRate);\n\n const borrowValueUsd = borrowAmount.mul(getPx(reserve)).dividedBy(reserve.getMintFactor());\n\n const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);\n const borrowValueBorrowFactorAdjustedUsd = borrowValueUsd.mul(borrowFactor);\n\n if (!borrowAmount.eq(new Decimal('0'))) {\n positions += 1;\n }\n\n userTotalBorrow = userTotalBorrow.plus(borrowValueUsd);\n userTotalBorrowBorrowFactorAdjusted = userTotalBorrowBorrowFactorAdjusted.plus(\n borrowValueBorrowFactorAdjustedUsd\n );\n\n const position: Position = {\n reserveAddress: reserve.address,\n mintAddress: reserve.getLiquidityMint(),\n amount: borrowAmount,\n marketValueRefreshed: borrowValueUsd,\n };\n borrows.set(reserve.address, position);\n }\n\n return {\n borrows,\n userTotalBorrow,\n userTotalBorrowBorrowFactorAdjusted,\n positions,\n };\n }\n\n /* \n How much of a given token can a user borrow extra given an elevation group, \n regardless of caps and liquidity or assuming infinite liquidity and infinite caps,\n until it hits max LTV.\n\n This is purely a function about the borrow power of an obligation, \n not a reserve-specific, caps-specific, liquidity-specific function.\n\n * @param market - The KaminoMarket instance.\n * @param liquidityMint - The liquidity mint PublicKey.\n * @param slot - The slot number.\n * @param elevationGroup - The elevation group number (default: this.state.elevationGroup).\n * @returns The borrow power as a Decimal.\n * @throws Error if the reserve is not found.\n */\n getBorrowPower(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n elevationGroup: number = this.state.elevationGroup\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n\n const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);\n\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(\n market,\n this.state,\n slot\n );\n\n const { borrowLimit } = KaminoObligation.calculateObligationDeposits(\n market,\n this.state,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n const { userTotalBorrowBorrowFactorAdjusted } = KaminoObligation.calculateObligationBorrows(\n market,\n this.state,\n cumulativeBorrowRates,\n elevationGroup,\n getOraclePx\n );\n\n const maxObligationBorrowPower = borrowLimit // adjusted available amount\n .minus(userTotalBorrowBorrowFactorAdjusted)\n .div(borrowFactor)\n .div(reserve.getOracleMarketPrice())\n .mul(reserve.getMintFactor());\n\n // If it has any collateral outside emode, then return 0\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n if (depositReserve.state.config.disableUsageAsCollOutsideEmode && !elevationGroupActivated) {\n return new Decimal(0);\n }\n }\n\n // This is not amazing because it assumes max borrow, which is not true\n let originationFeeRate = reserve.getBorrowFee();\n\n // Inclusive fee rate\n originationFeeRate = originationFeeRate.div(originationFeeRate.add(new Decimal(1)));\n const borrowFee = maxObligationBorrowPower.mul(originationFeeRate);\n\n const maxBorrowAmount = maxObligationBorrowPower.sub(borrowFee);\n\n return Decimal.max(new Decimal(0), maxBorrowAmount);\n }\n\n /* \n How much of a given token can a user borrow extra given an elevation group,\n and a specific reserve, until it hits max LTV and given available liquidity and caps.\n\n * @param market - The KaminoMarket instance.\n * @param liquidityMint - The liquidity mint PublicKey.\n * @param slot - The slot number.\n * @param elevationGroup - The elevation group number (default: this.state.elevationGroup).\n * @returns The maximum borrow amount as a Decimal.\n * @throws Error if the reserve is not found.\n */\n getMaxBorrowAmountV2(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n elevationGroup: number = this.state.elevationGroup\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(market, [elevationGroup])[0];\n const maxBorrowAmount = this.getBorrowPower(market, liquidityMint, slot, elevationGroup);\n\n if (elevationGroup === this.state.elevationGroup) {\n return Decimal.min(maxBorrowAmount, liquidityAvailable);\n } else {\n const { amount: debtThisReserve } = this.borrows.get(reserve.address) || { amount: new Decimal(0) };\n const liquidityAvailablePostMigration = Decimal.max(0, liquidityAvailable.minus(debtThisReserve));\n return Decimal.min(maxBorrowAmount, liquidityAvailablePostMigration);\n }\n }\n\n /* \n Returns true if the loan is eligible for the elevation group, including for the default one.\n * @param market - The KaminoMarket object representing the market.\n * @param slot - The slot number of the loan.\n * @param elevationGroup - The elevation group number.\n * @returns A boolean indicating whether the loan is eligible for elevation.\n */\n isLoanEligibleForElevationGroup(market: KaminoMarket, slot: number, elevationGroup: number): boolean {\n // - isLoanEligibleForEmode(obligation, emode: 0 | number): <boolean, ErrorMessage>\n // - essentially checks if a loan can be migrated or not\n // - [x] due to collateral / debt reserves combination\n // - [x] due to LTV, etc\n\n const reserveDeposits: string[] = Array.from(this.deposits.keys()).map((x) => x.toString());\n const reserveBorrows: string[] = Array.from(this.borrows.keys()).map((x) => x.toString());\n\n if (reserveBorrows.length > 1) {\n return false;\n }\n\n if (elevationGroup > 0) {\n // Elevation group 0 doesn't need to do reserve checks, as all are included by default\n const allElevationGroups = market.getMarketElevationGroupDescriptions();\n const elevationGroupDescription = allElevationGroups[elevationGroup - 1];\n\n // Has to be a subset\n const allCollsIncluded = reserveDeposits.every((reserve) =>\n elevationGroupDescription.collateralReserves.includes(reserve)\n );\n const allDebtsIncluded =\n reserveBorrows.length === 0 ||\n (reserveBorrows.length === 1 && elevationGroupDescription.debtReserve === reserveBorrows[0]);\n\n if (!allCollsIncluded || !allDebtsIncluded) {\n return false;\n }\n }\n\n // Check if the loan can be migrated based on LTV\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);\n\n const { borrowLimit } = KaminoObligation.calculateObligationDeposits(\n market,\n this.state,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n const isEligibleBasedOnLtv = this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.lte(borrowLimit);\n\n return isEligibleBasedOnLtv;\n }\n\n /* \n Returns all elevation groups for a given obligation, except the default one\n * @param market - The KaminoMarket instance.\n * @returns An array of ElevationGroupDescription objects representing the elevation groups for the obligation.\n */\n getElevationGroupsForObligation(market: KaminoMarket): ElevationGroupDescription[] {\n if (this.borrows.size > 1) {\n return [];\n }\n\n const collReserves = Array.from(this.deposits.keys());\n if (this.borrows.size === 0) {\n return market.getElevationGroupsForReservesCombination(collReserves);\n } else {\n const debtReserve = Array.from(this.borrows.keys())[0];\n return market.getElevationGroupsForReservesCombination(collReserves, debtReserve);\n }\n }\n\n /* Deprecated function, also broken */\n getMaxBorrowAmount(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n requestElevationGroup: boolean\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const groups = market.state.elevationGroups;\n const emodeGroupsDebtReserve = reserve.state.config.elevationGroups;\n let commonElevationGroups = [...emodeGroupsDebtReserve].filter(\n (item) => item !== 0 && groups[item - 1].debtReserve.equals(reserve.address)\n );\n\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const depositReserveEmodeGroups = depositReserve.state.config.elevationGroups;\n\n commonElevationGroups = commonElevationGroups.filter((item) => depositReserveEmodeGroups.includes(item));\n }\n\n let elevationGroup = this.state.elevationGroup;\n if (commonElevationGroups.length != 0) {\n const eModeGroupWithMaxLtvAndDebtReserve = commonElevationGroups.reduce((prev, curr) => {\n const prevGroup = groups.find((group) => group.id === prev);\n const currGroup = groups.find((group) => group.id === curr);\n return prevGroup!.ltvPct > currGroup!.ltvPct ? prev : curr;\n });\n\n if (requestElevationGroup) {\n elevationGroup = eModeGroupWithMaxLtvAndDebtReserve;\n }\n }\n\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n\n const borrowFactor = this.getBorrowFactorForReserve(reserve);\n\n const maxObligationBorrowPower = this.refreshedStats.borrowLimit // adjusted available amount\n .minus(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)\n .div(borrowFactor)\n .div(reserve.getOracleMarketPrice())\n .mul(reserve.getMintFactor());\n const reserveAvailableAmount = reserve.getLiquidityAvailableAmount();\n let reserveBorrowCapRemained = reserve.stats.reserveBorrowLimit.sub(reserve.getBorrowedAmount());\n\n this.deposits.forEach((deposit) => {\n const depositReserve = market.getReserveByAddress(deposit.reserveAddress);\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n if (depositReserve.state.config.disableUsageAsCollOutsideEmode && !elevationGroupActivated) {\n reserveBorrowCapRemained = new Decimal(0);\n }\n });\n\n let maxBorrowAmount = Decimal.min(maxObligationBorrowPower, reserveAvailableAmount, reserveBorrowCapRemained);\n\n const debtWithdrawalCap = reserve.getDebtWithdrawalCapCapacity().sub(reserve.getDebtWithdrawalCapCurrent(slot));\n maxBorrowAmount = reserve.getDebtWithdrawalCapCapacity().gt(0)\n ? Decimal.min(maxBorrowAmount, debtWithdrawalCap)\n : maxBorrowAmount;\n\n let originationFeeRate = reserve.getBorrowFee();\n\n // Inclusive fee rate\n originationFeeRate = originationFeeRate.div(originationFeeRate.add(new Decimal(1)));\n const borrowFee = maxBorrowAmount.mul(originationFeeRate);\n\n maxBorrowAmount = maxBorrowAmount.sub(borrowFee);\n\n const utilizationRatioLimit = reserve.state.config.utilizationLimitBlockBorrowingAbove / 100;\n const currentUtilizationRatio = reserve.calculateUtilizationRatio();\n\n if (utilizationRatioLimit > 0 && currentUtilizationRatio > utilizationRatioLimit) {\n return new Decimal(0);\n } else if (utilizationRatioLimit > 0 && currentUtilizationRatio < utilizationRatioLimit) {\n const maxBorrowBasedOnUtilization = new Decimal(utilizationRatioLimit - currentUtilizationRatio).mul(\n reserve.getTotalSupply()\n );\n maxBorrowAmount = Decimal.min(maxBorrowAmount, maxBorrowBasedOnUtilization);\n }\n\n let borrowLimitDependentOnElevationGroup = new Decimal(U64_MAX);\n\n if (!elevationGroupActivated) {\n borrowLimitDependentOnElevationGroup = reserve\n .getBorrowLimitOutsideElevationGroup()\n .sub(reserve.getBorrowedAmountOutsideElevationGroup());\n } else {\n let maxDebtTakenAgainstCollaterals = new Decimal(U64_MAX);\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const maxDebtAllowedAgainstCollateral = depositReserve\n .getBorrowLimitAgainstCollateralInElevationGroup(elevationGroup - 1)\n .sub(depositReserve.getBorrowedAmountAgainstCollateralInElevationGroup(elevationGroup - 1));\n\n maxDebtTakenAgainstCollaterals = Decimal.max(\n new Decimal(0),\n Decimal.min(maxDebtAllowedAgainstCollateral, maxDebtTakenAgainstCollaterals)\n );\n }\n borrowLimitDependentOnElevationGroup = maxDebtTakenAgainstCollaterals;\n }\n\n maxBorrowAmount = Decimal.min(maxBorrowAmount, borrowLimitDependentOnElevationGroup);\n\n return Decimal.max(new Decimal(0), maxBorrowAmount);\n }\n\n getMaxWithdrawAmount(market: KaminoMarket, tokenMint: PublicKey, slot: number): Decimal {\n const depositReserve = market.getReserveByMint(tokenMint);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const userDepositPosition = this.getDepositByReserve(depositReserve.address);\n\n if (!userDepositPosition) {\n throw new Error('Deposit reserve not found');\n }\n\n const userDepositPositionAmount = userDepositPosition.amount;\n\n if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.equals(new Decimal(0))) {\n return new Decimal(userDepositPositionAmount);\n }\n\n const { maxLtv: reserveMaxLtv } = this.getLtvForReserve(market, depositReserve);\n // bf adjusted debt value > allowed_borrow_value\n if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.gte(this.refreshedStats.borrowLimit)) {\n return new Decimal(0);\n }\n\n let maxWithdrawValue: Decimal;\n if (reserveMaxLtv.eq(0)) {\n maxWithdrawValue = userDepositPositionAmount;\n } else {\n // borrowLimit / userTotalDeposit = maxLtv\n // maxWithdrawValue = userTotalDeposit - userTotalBorrow / maxLtv\n maxWithdrawValue = this.refreshedStats.borrowLimit\n .sub(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)\n .div(reserveMaxLtv)\n .mul(0.999); // remove 0.1% to prevent going over max ltv\n }\n\n const maxWithdrawAmount = maxWithdrawValue\n .div(depositReserve.getOracleMarketPrice())\n .mul(depositReserve.getMintFactor());\n const reserveAvailableLiquidity = depositReserve.getLiquidityAvailableAmount();\n\n const withdrawalCapRemained = depositReserve\n .getDepositWithdrawalCapCapacity()\n .sub(depositReserve.getDepositWithdrawalCapCurrent(slot));\n return Decimal.max(\n 0,\n Decimal.min(userDepositPositionAmount, maxWithdrawAmount, reserveAvailableLiquidity, withdrawalCapRemained)\n );\n }\n\n /**\n *\n * @returns Total borrowed amount for the specified obligation liquidity/borrow asset\n */\n static getBorrowAmount(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.borrowedAmountSf).toDecimal();\n }\n\n /**\n *\n * @returns Cumulative borrow rate for the specified obligation liquidity/borrow asset\n */\n static getCumulativeBorrowRate(borrow: ObligationLiquidity): Decimal {\n let accSf = new BN(0);\n for (const value of borrow.cumulativeBorrowRateBsf.value.reverse()) {\n accSf = accSf.add(value);\n accSf.shrn(64);\n }\n return new Fraction(accSf).toDecimal();\n }\n\n public static getRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n slot: number\n ): {\n collateralExchangeRates: Map<PublicKey, Decimal>;\n cumulativeBorrowRates: Map<PublicKey, Decimal>;\n } {\n const collateralExchangeRates = KaminoObligation.getCollateralExchangeRatesForObligation(\n kaminoMarket,\n obligation,\n slot\n );\n const cumulativeBorrowRates = KaminoObligation.getCumulativeBorrowRatesForObligation(\n kaminoMarket,\n obligation,\n slot\n );\n\n return {\n collateralExchangeRates,\n cumulativeBorrowRates,\n };\n }\n\n public static addRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>,\n slot: number\n ): void {\n KaminoObligation.addCollateralExchangeRatesForObligation(kaminoMarket, collateralExchangeRates, obligation, slot);\n KaminoObligation.addCumulativeBorrowRatesForObligation(kaminoMarket, cumulativeBorrowRates, obligation, slot);\n }\n\n static getCollateralExchangeRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n slot: number\n ): Map<PublicKey, Decimal> {\n const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (let i = 0; i < obligation.deposits.length; i++) {\n const deposit = obligation.deposits[i];\n if (isNotNullPubkey(deposit.depositReserve) && !collateralExchangeRates.has(deposit.depositReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(deposit.depositReserve)!;\n const collateralExchangeRate = reserve.getEstimatedCollateralExchangeRate(\n slot,\n kaminoMarket.state.referralFeeBps\n );\n collateralExchangeRates.set(reserve.address, collateralExchangeRate);\n }\n }\n return collateralExchangeRates;\n }\n\n static addCollateralExchangeRatesForObligation(\n kaminoMarket: KaminoMarket,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n obligation: Obligation,\n slot: number\n ) {\n for (let i = 0; i < obligation.deposits.length; i++) {\n const deposit = obligation.deposits[i];\n if (isNotNullPubkey(deposit.depositReserve) && !collateralExchangeRates.has(deposit.depositReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(deposit.depositReserve)!;\n const collateralExchangeRate = reserve.getEstimatedCollateralExchangeRate(\n slot,\n kaminoMarket.state.referralFeeBps\n );\n collateralExchangeRates.set(reserve.address, collateralExchangeRate);\n }\n }\n }\n\n static getCumulativeBorrowRatesForObligation(kaminoMarket: KaminoMarket, obligation: Obligation, slot: number) {\n const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (let i = 0; i < obligation.borrows.length; i++) {\n const borrow = obligation.borrows[i];\n if (isNotNullPubkey(borrow.borrowReserve) && !cumulativeBorrowRates.has(borrow.borrowReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(borrow.borrowReserve)!;\n const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);\n cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);\n }\n }\n return cumulativeBorrowRates;\n }\n\n static addCumulativeBorrowRatesForObligation(\n kaminoMarket: KaminoMarket,\n cumulativeBorrowRates: Map<PublicKey, Decimal>,\n obligation: Obligation,\n slot: number\n ) {\n for (let i = 0; i < obligation.borrows.length; i++) {\n const borrow = obligation.borrows[i];\n if (isNotNullPubkey(borrow.borrowReserve) && !cumulativeBorrowRates.has(borrow.borrowReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(borrow.borrowReserve)!;\n const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);\n cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);\n }\n }\n }\n\n /**\n * Get the borrow factor for a borrow reserve, accounting for the obligation elevation group if it is active\n * @param reserve\n * @param elevationGroup\n */\n public static getBorrowFactorForReserve(reserve: KaminoReserve, elevationGroup: number): Decimal {\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n if (elevationGroupActivated) {\n return new Decimal('1');\n }\n return new Decimal(reserve.stats.borrowFactor).div('100');\n }\n\n /**\n * Get the loan to value and liquidation loan to value for a collateral reserve as ratios, accounting for the obligation elevation group if it is active\n * @param market\n * @param reserve\n * @param elevationGroup\n */\n public static getLtvForReserve(\n market: KaminoMarket,\n reserve: KaminoReserve,\n elevationGroup: number\n ): { maxLtv: Decimal; liquidationLtv: Decimal } {\n const elevationGroupActivated =\n elevationGroup !== 0 && reserve.state.config.elevationGroups.includes(elevationGroup);\n if (elevationGroupActivated) {\n const { ltvPct, liquidationThresholdPct } = market.getElevationGroup(elevationGroup);\n return {\n maxLtv: new Decimal(ltvPct).div('100'),\n liquidationLtv: new Decimal(liquidationThresholdPct).div('100'),\n };\n } else {\n const { loanToValue, liquidationThreshold } = reserve.stats;\n return {\n maxLtv: new Decimal(loanToValue),\n liquidationLtv: new Decimal(liquidationThreshold),\n };\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"obligation.js","sourceRoot":"","sources":["../../src/classes/obligation.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable max-classes-per-file */\nimport { PublicKey } from '@solana/web3.js';\nimport Decimal from 'decimal.js';\nimport { KaminoReserve } from './reserve';\nimport { Obligation } from '../idl_codegen/accounts';\nimport { ElevationGroupDescription, KaminoMarket } from './market';\nimport BN from 'bn.js';\nimport { Fraction } from './fraction';\nimport {\n ObligationCollateral,\n ObligationCollateralFields,\n ObligationLiquidity,\n ObligationLiquidityFields,\n} from '../idl_codegen/types';\nimport { positiveOrZero, valueOrZero } from './utils';\nimport { isNotNullPubkey, PubkeyHashMap, U64_MAX } from '../utils';\nimport { ActionType } from './action';\n\nexport type Position = {\n reserveAddress: PublicKey;\n mintAddress: PublicKey;\n /**\n * Amount of tokens in lamports, including decimal places for interest accrued (no borrow factor weighting)\n */\n amount: Decimal;\n /**\n * Market value of the position in USD (no borrow factor weighting)\n */\n marketValueRefreshed: Decimal;\n};\n\nexport type ObligationStats = {\n userTotalDeposit: Decimal;\n userTotalBorrow: Decimal;\n userTotalBorrowBorrowFactorAdjusted: Decimal;\n borrowLimit: Decimal;\n borrowLiquidationLimit: Decimal;\n borrowUtilization: Decimal;\n netAccountValue: Decimal;\n loanToValue: Decimal;\n liquidationLtv: Decimal;\n leverage: Decimal;\n potentialElevationGroupUpdate: number;\n};\n\ninterface BorrowStats {\n borrows: Map<PublicKey, Position>;\n userTotalBorrow: Decimal;\n userTotalBorrowBorrowFactorAdjusted: Decimal;\n positions: number;\n}\n\ninterface DepositStats {\n deposits: Map<PublicKey, Position>;\n userTotalDeposit: Decimal;\n userTotalCollateralDeposit: Decimal;\n borrowLimit: Decimal;\n liquidationLtv: Decimal;\n borrowLiquidationLimit: Decimal;\n}\n\nexport class KaminoObligation {\n obligationAddress: PublicKey;\n\n state: Obligation;\n\n /**\n * Deposits stored in a map of reserve address to position\n */\n deposits: Map<PublicKey, Position>;\n\n /**\n * Borrows stored in a map of reserve address to position\n */\n borrows: Map<PublicKey, Position>;\n\n refreshedStats: ObligationStats;\n\n obligationTag: number;\n\n /**\n * Initialise a new Obligation from the deserialized state\n * @param market\n * @param obligationAddress\n * @param obligation\n * @param collateralExchangeRates - rates from the market by reserve address, will be calculated if not provided\n * @param cumulativeBorrowRates - rates from the market by reserve address, will be calculated if not provided\n */\n constructor(\n market: KaminoMarket,\n obligationAddress: PublicKey,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>\n ) {\n this.obligationAddress = obligationAddress;\n this.state = obligation;\n const { borrows, deposits, refreshedStats } = this.calculatePositions(\n market,\n obligation.deposits,\n obligation.borrows,\n obligation.elevationGroup,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n this.deposits = deposits;\n this.borrows = borrows;\n this.refreshedStats = refreshedStats;\n this.obligationTag = obligation.tag.toNumber();\n }\n\n static async load(kaminoMarket: KaminoMarket, obligationAddress: PublicKey): Promise<KaminoObligation | null> {\n const res = await kaminoMarket.getConnection().getAccountInfoAndContext(obligationAddress);\n if (res.value === null) {\n return null;\n }\n const accInfo = res.value;\n if (!accInfo.owner.equals(kaminoMarket.programId)) {\n throw new Error(\"account doesn't belong to this program\");\n }\n const obligation = Obligation.decode(accInfo.data);\n\n if (obligation === null) {\n return null;\n }\n const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(\n kaminoMarket,\n obligation,\n res.context.slot\n );\n return new KaminoObligation(\n kaminoMarket,\n obligationAddress,\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n }\n\n static async loadAll(\n kaminoMarket: KaminoMarket,\n obligationAddresses: PublicKey[],\n slot?: number\n ): Promise<(KaminoObligation | null)[]> {\n let currentSlot = slot;\n let obligations: (Obligation | null)[];\n if (!currentSlot) {\n [currentSlot, obligations] = await Promise.all([\n kaminoMarket.getConnection().getSlot(),\n Obligation.fetchMultiple(kaminoMarket.getConnection(), obligationAddresses, kaminoMarket.programId),\n ]);\n } else {\n obligations = await Obligation.fetchMultiple(\n kaminoMarket.getConnection(),\n obligationAddresses,\n kaminoMarket.programId\n );\n }\n const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();\n const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (const obligation of obligations) {\n if (obligation !== null) {\n KaminoObligation.addRatesForObligation(\n kaminoMarket,\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates,\n currentSlot\n );\n }\n }\n\n return obligations.map((obligation, i) => {\n if (obligation === null) {\n return null;\n }\n return new KaminoObligation(\n kaminoMarket,\n obligationAddresses[i],\n obligation,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n });\n }\n\n /**\n * @returns the obligation borrows as a list\n */\n getBorrows(): Array<Position> {\n return [...this.borrows.values()];\n }\n\n /**\n * @returns the obligation borrows as a list\n */\n getDeposits(): Array<Position> {\n return [...this.deposits.values()];\n }\n\n /**\n * @returns the total deposited value of the obligation (sum of all deposits)\n */\n getDepositedValue(): Decimal {\n return new Fraction(this.state.depositedValueSf).toDecimal();\n }\n\n /**\n * @returns the total borrowed value of the obligation (sum of all borrows -- no borrow factor)\n */\n getBorrowedMarketValue(): Decimal {\n return new Fraction(this.state.borrowedAssetsMarketValueSf).toDecimal();\n }\n\n /**\n * @returns the total borrowed value of the obligation (sum of all borrows -- with borrow factor weighting)\n */\n getBorrowedMarketValueBFAdjusted(): Decimal {\n return new Fraction(this.state.borrowFactorAdjustedDebtValueSf).toDecimal();\n }\n\n /**\n * @returns total borrow power of the obligation, relative to max LTV of each asset's reserve\n */\n getAllowedBorrowValue(): Decimal {\n return new Fraction(this.state.allowedBorrowValueSf).toDecimal();\n }\n\n /**\n * @returns the borrow value at which the obligation gets liquidatable\n * (relative to the liquidation threshold of each asset's reserve)\n */\n getUnhealthyBorrowValue(): Decimal {\n return new Fraction(this.state.unhealthyBorrowValueSf).toDecimal();\n }\n\n /**\n *\n * @returns Market value of the deposit in the specified obligation collateral/deposit asset (USD)\n */\n getDepositMarketValue(deposit: ObligationCollateral): Decimal {\n return new Fraction(deposit.marketValueSf).toDecimal();\n }\n\n getBorrowByReserve(reserve: PublicKey): Position | undefined {\n return this.borrows.get(reserve);\n }\n\n getDepositByReserve(reserve: PublicKey): Position | undefined {\n return this.deposits.get(reserve);\n }\n\n getBorrowByMint(mint: PublicKey): Position | undefined {\n for (const value of this.borrows.values()) {\n if (value.mintAddress.equals(mint)) {\n return value;\n }\n }\n return undefined;\n }\n\n getDepositByMint(mint: PublicKey): Position | undefined {\n for (const value of this.deposits.values()) {\n if (value.mintAddress.equals(mint)) {\n return value;\n }\n }\n return undefined;\n }\n\n /**\n *\n * @returns Market value of the borrow in the specified obligation liquidity/borrow asset (USD) (no borrow factor weighting)\n */\n getBorrowMarketValue(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.marketValueSf).toDecimal();\n }\n\n /**\n *\n * @returns Market value of the borrow in the specified obligation liquidity/borrow asset (USD) (with borrow factor weighting)\n */\n getBorrowMarketValueBFAdjusted(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.borrowFactorAdjustedMarketValueSf).toDecimal();\n }\n\n /**\n * Calculate the current ratio of borrowed value to deposited value\n */\n loanToValue(): Decimal {\n if (this.refreshedStats.userTotalDeposit.eq(0)) {\n return new Decimal(0);\n }\n return this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.div(this.refreshedStats.userTotalDeposit);\n }\n\n /**\n * @returns the total number of positions (deposits + borrows)\n */\n getNumberOfPositions(): number {\n return this.deposits.size + this.borrows.size;\n }\n\n getNetAccountValue(): Decimal {\n return this.refreshedStats.netAccountValue;\n }\n\n /**\n * @returns the potential elevation groups the obligation qualifies for\n */\n getElevationGroups(kaminoMarket: KaminoMarket): Array<number> {\n const reserves = new PubkeyHashMap<PublicKey, KaminoReserve>();\n for (const deposit of this.state.deposits.values()) {\n if (isNotNullPubkey(deposit.depositReserve) && !reserves.has(deposit.depositReserve)) {\n reserves.set(deposit.depositReserve, kaminoMarket.getReserveByAddress(deposit.depositReserve)!);\n }\n }\n for (const borrow of this.state.borrows.values()) {\n if (isNotNullPubkey(borrow.borrowReserve) && !reserves.has(borrow.borrowReserve)) {\n reserves.set(borrow.borrowReserve, kaminoMarket.getReserveByAddress(borrow.borrowReserve)!);\n }\n }\n return KaminoObligation.getElevationGroupsForReserves([...reserves.values()]);\n }\n\n static getElevationGroupsForReserves(reserves: Array<KaminoReserve>): Array<number> {\n const elevationGroupsCounts = new Map<number, number>();\n for (const reserve of reserves) {\n for (const elevationGroup of reserve.state.config.elevationGroups) {\n if (elevationGroup !== 0) {\n const count = elevationGroupsCounts.get(elevationGroup);\n if (count) {\n elevationGroupsCounts.set(elevationGroup, count + 1);\n } else {\n elevationGroupsCounts.set(elevationGroup, 1);\n }\n }\n }\n }\n const activeElevationGroups = new Array<number>();\n for (const [group, count] of elevationGroupsCounts.entries()) {\n if (count === reserves.length) {\n activeElevationGroups.push(group);\n }\n }\n return activeElevationGroups;\n }\n\n simulateDepositChange(\n obligationDeposits: ObligationCollateral[],\n changeInLamports: number,\n changeReserve: PublicKey,\n collateralExchangeRates: Map<PublicKey, Decimal>\n ): ObligationCollateral[] {\n const newDeposits: ObligationCollateral[] = [];\n for (let i = 0; i < obligationDeposits.length; i++) {\n if (obligationDeposits[i].depositReserve.equals(changeReserve)) {\n const coll: ObligationCollateralFields = { ...obligationDeposits[i] };\n const exchangeRate = collateralExchangeRates.get(changeReserve)!;\n const changeInCollateral = new Decimal(changeInLamports).mul(exchangeRate);\n const updatedDeposit = new Decimal(obligationDeposits[i].depositedAmount.toNumber()).add(changeInCollateral);\n coll.depositedAmount = new BN(positiveOrZero(updatedDeposit).toString());\n newDeposits.push(new ObligationCollateral(coll));\n } else {\n newDeposits.push(obligationDeposits[i]);\n }\n }\n\n return newDeposits;\n }\n\n simulateBorrowChange(\n obligationBorrows: ObligationLiquidity[],\n changeInLamports: number,\n changeReserve: PublicKey\n ): ObligationLiquidity[] {\n const newBorrows: ObligationLiquidity[] = [];\n for (let i = 0; i < obligationBorrows.length; i++) {\n if (obligationBorrows[i].borrowReserve.equals(changeReserve)) {\n const borrow: ObligationLiquidityFields = { ...obligationBorrows[i] };\n const newBorrowedAmount: Decimal = new Fraction(borrow.borrowedAmountSf).toDecimal().add(changeInLamports);\n const newBorrowedAmountSf = Fraction.fromDecimal(positiveOrZero(newBorrowedAmount)).getValue();\n borrow.borrowedAmountSf = newBorrowedAmountSf;\n newBorrows.push(new ObligationLiquidity(borrow));\n } else {\n newBorrows.push(obligationBorrows[i]);\n }\n }\n\n return newBorrows;\n }\n\n /**\n * Calculate the newly modified stats of the obligation\n */\n // TODO: Shall we set up position limits?\n getSimulatedObligationStats(params: {\n amountCollateral?: Decimal;\n amountDebt?: Decimal;\n action: ActionType;\n mintCollateral?: PublicKey;\n mintDebt?: PublicKey;\n market: KaminoMarket;\n reserves: Map<PublicKey, KaminoReserve>;\n slot: number;\n elevationGroupOverride?: number;\n }): {\n stats: ObligationStats;\n deposits: Map<PublicKey, Position>;\n borrows: Map<PublicKey, Position>;\n } {\n const { amountCollateral, amountDebt, action, mintCollateral, mintDebt, market } = params;\n let newStats = { ...this.refreshedStats };\n\n const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(\n market,\n this.state,\n params.slot\n );\n\n const elevationGroup = params.elevationGroupOverride ?? this.state.elevationGroup;\n\n let newDeposits: Map<PublicKey, Position> = new PubkeyHashMap<PublicKey, Position>([...this.deposits.entries()]);\n let newBorrows: Map<PublicKey, Position> = new PubkeyHashMap<PublicKey, Position>([...this.borrows.entries()]);\n\n // Any action can impact both deposit stats and borrow stats if elevation group is changed\n // so we have to recalculate the entire position, not just an updated deposit or borrow\n // as both LTVs and borrow factors can change, affecting all calcs\n\n const collateralReserve = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;\n const debtReserve = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;\n\n let newObligationDeposits = this.state.deposits;\n let newObligationBorrows = this.state.borrows;\n\n switch (action) {\n case 'deposit': {\n if (amountCollateral === undefined || mintCollateral === undefined) {\n throw Error('amountCollateral & mintCollateral are required for deposit action');\n }\n newObligationDeposits = this.simulateDepositChange(\n this.state.deposits,\n amountCollateral.toNumber(),\n collateralReserve!,\n collateralExchangeRates\n );\n break;\n }\n case 'borrow': {\n if (amountDebt === undefined || mintDebt === undefined) {\n throw Error('amountDebt & mintDebt are required for borrow action');\n }\n\n newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.toNumber(), debtReserve!);\n break;\n }\n case 'repay': {\n if (amountDebt === undefined || mintDebt === undefined) {\n throw Error('amountDebt & mintDebt are required for repay action');\n }\n newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.neg().toNumber(), debtReserve!);\n\n break;\n }\n\n case 'withdraw': {\n if (amountCollateral === undefined || mintCollateral === undefined) {\n throw Error('amountCollateral & mintCollateral are required for withdraw action');\n }\n newObligationDeposits = this.simulateDepositChange(\n this.state.deposits,\n amountCollateral.neg().toNumber(),\n collateralReserve!,\n collateralExchangeRates\n );\n break;\n }\n case 'depositAndBorrow': {\n if (\n amountCollateral === undefined ||\n amountDebt === undefined ||\n mintCollateral === undefined ||\n mintDebt === undefined\n ) {\n throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for depositAndBorrow action');\n }\n newObligationDeposits = this.simulateDepositChange(\n this.state.deposits,\n amountCollateral.toNumber(),\n collateralReserve!,\n collateralExchangeRates\n );\n newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.toNumber(), debtReserve!);\n break;\n }\n case 'repayAndWithdraw': {\n if (\n amountCollateral === undefined ||\n amountDebt === undefined ||\n mintCollateral === undefined ||\n mintDebt === undefined\n ) {\n throw Error('amountColl & amountDebt & mintCollateral & mintDebt are required for repayAndWithdraw action');\n }\n newObligationDeposits = this.simulateDepositChange(\n this.state.deposits,\n amountCollateral.neg().toNumber(),\n collateralReserve!,\n collateralExchangeRates\n );\n newObligationBorrows = this.simulateBorrowChange(this.state.borrows, amountDebt.neg().toNumber(), debtReserve!);\n break;\n }\n default: {\n throw Error(`Invalid action type ${action} for getSimulatedObligationStats`);\n }\n }\n\n const { borrows, deposits, refreshedStats } = this.calculatePositions(\n market,\n newObligationDeposits,\n newObligationBorrows,\n elevationGroup,\n collateralExchangeRates,\n cumulativeBorrowRates\n );\n\n newStats = refreshedStats;\n newDeposits = deposits;\n newBorrows = borrows;\n\n newStats.netAccountValue = newStats.userTotalDeposit.minus(newStats.userTotalBorrow);\n newStats.loanToValue = valueOrZero(\n newStats.userTotalBorrowBorrowFactorAdjusted.dividedBy(newStats.userTotalDeposit)\n );\n newStats.leverage = valueOrZero(newStats.userTotalDeposit.dividedBy(newStats.netAccountValue));\n\n return {\n stats: newStats,\n deposits: newDeposits,\n borrows: newBorrows,\n };\n }\n\n estimateObligationInterestRate = (\n market: KaminoMarket,\n reserve: KaminoReserve,\n borrow: ObligationLiquidity,\n currentSlot: number\n ): Decimal => {\n const estimatedCumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(\n currentSlot,\n market.state.referralFeeBps\n );\n\n const currentCumulativeBorrowRate = KaminoObligation.getCumulativeBorrowRate(borrow);\n\n if (estimatedCumulativeBorrowRate.gt(currentCumulativeBorrowRate)) {\n return estimatedCumulativeBorrowRate.div(currentCumulativeBorrowRate);\n }\n\n return new Decimal(0);\n };\n\n private calculatePositions(\n market: KaminoMarket,\n obligationDeposits: ObligationCollateral[],\n obligationBorrows: ObligationLiquidity[],\n elevationGroup: number,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>\n ): {\n borrows: Map<PublicKey, Position>;\n deposits: Map<PublicKey, Position>;\n refreshedStats: ObligationStats;\n } {\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n\n const depositStatsOraclePrice = KaminoObligation.calculateObligationDeposits(\n market,\n obligationDeposits,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n const borrowStatsOraclePrice = KaminoObligation.calculateObligationBorrows(\n market,\n obligationBorrows,\n cumulativeBorrowRates,\n elevationGroup,\n getOraclePx\n );\n\n const netAccountValueScopeRefreshed = depositStatsOraclePrice.userTotalDeposit.minus(\n borrowStatsOraclePrice.userTotalBorrow\n );\n\n // TODO: Fix this?\n const potentialElevationGroupUpdate = 0;\n\n return {\n deposits: depositStatsOraclePrice.deposits,\n borrows: borrowStatsOraclePrice.borrows,\n refreshedStats: {\n borrowLimit: depositStatsOraclePrice.borrowLimit,\n borrowLiquidationLimit: depositStatsOraclePrice.borrowLiquidationLimit,\n userTotalBorrow: borrowStatsOraclePrice.userTotalBorrow,\n userTotalBorrowBorrowFactorAdjusted: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted,\n userTotalDeposit: depositStatsOraclePrice.userTotalDeposit,\n liquidationLtv: depositStatsOraclePrice.liquidationLtv,\n borrowUtilization: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted.dividedBy(\n depositStatsOraclePrice.borrowLimit\n ),\n netAccountValue: netAccountValueScopeRefreshed,\n leverage: depositStatsOraclePrice.userTotalDeposit.dividedBy(netAccountValueScopeRefreshed),\n loanToValue: borrowStatsOraclePrice.userTotalBorrowBorrowFactorAdjusted.dividedBy(\n depositStatsOraclePrice.userTotalDeposit\n ),\n potentialElevationGroupUpdate,\n },\n };\n }\n\n public static calculateObligationDeposits(\n market: KaminoMarket,\n obligationDeposits: ObligationCollateral[],\n collateralExchangeRates: Map<PublicKey, Decimal> | null,\n elevationGroup: number,\n getPx: (reserve: KaminoReserve) => Decimal\n ): DepositStats {\n let userTotalDeposit = new Decimal(0);\n let userTotalCollateralDeposit = new Decimal(0);\n let borrowLimit = new Decimal(0);\n let borrowLiquidationLimit = new Decimal(0);\n\n const deposits = new PubkeyHashMap<PublicKey, Position>();\n for (let i = 0; i < obligationDeposits.length; i++) {\n if (!isNotNullPubkey(obligationDeposits[i].depositReserve)) {\n continue;\n }\n const deposit = obligationDeposits[i];\n const reserve = market.getReserveByAddress(deposit.depositReserve);\n if (!reserve) {\n throw new Error(\n `Obligation contains a deposit belonging to reserve: ${deposit.depositReserve} but the reserve was not found on the market. Deposit amount: ${deposit.depositedAmount}`\n );\n }\n const { maxLtv, liquidationLtv } = KaminoObligation.getLtvForReserve(market, reserve, elevationGroup);\n\n let exchangeRate: Decimal;\n if (collateralExchangeRates !== null) {\n exchangeRate = collateralExchangeRates.get(reserve.address)!;\n } else {\n exchangeRate = reserve.getCollateralExchangeRate();\n }\n const supplyAmount = new Decimal(deposit.depositedAmount.toString()).div(exchangeRate);\n\n const depositValueUsd = supplyAmount.mul(getPx(reserve)).div(reserve.getMintFactor());\n\n userTotalDeposit = userTotalDeposit.add(depositValueUsd);\n\n if (!maxLtv.eq('0')) {\n userTotalCollateralDeposit = userTotalCollateralDeposit.add(depositValueUsd);\n }\n\n borrowLimit = borrowLimit.add(depositValueUsd.mul(maxLtv));\n borrowLiquidationLimit = borrowLiquidationLimit.add(depositValueUsd.mul(liquidationLtv));\n\n const position: Position = {\n reserveAddress: reserve.address,\n mintAddress: reserve.getLiquidityMint(),\n amount: supplyAmount,\n marketValueRefreshed: depositValueUsd,\n };\n deposits.set(reserve.address, position);\n }\n\n return {\n deposits,\n userTotalDeposit,\n userTotalCollateralDeposit,\n borrowLimit,\n liquidationLtv: valueOrZero(borrowLiquidationLimit.div(userTotalDeposit)),\n borrowLiquidationLimit,\n };\n }\n\n public static calculateObligationBorrows(\n market: KaminoMarket,\n obligationBorrows: ObligationLiquidity[],\n cumulativeBorrowRates: Map<PublicKey, Decimal> | null,\n elevationGroup: number,\n getPx: (reserve: KaminoReserve) => Decimal\n ): BorrowStats {\n let userTotalBorrow = new Decimal(0);\n let userTotalBorrowBorrowFactorAdjusted = new Decimal(0);\n let positions = 0;\n\n const borrows = new PubkeyHashMap<PublicKey, Position>();\n for (let i = 0; i < obligationBorrows.length; i++) {\n if (!isNotNullPubkey(obligationBorrows[i].borrowReserve)) {\n continue;\n }\n const borrow = obligationBorrows[i];\n const reserve = market.getReserveByAddress(borrow.borrowReserve);\n if (!reserve) {\n throw new Error(\n `Obligation contains a borrow belonging to reserve: ${\n borrow.borrowReserve\n } but the reserve was not found on the market. Borrow amount: ${KaminoObligation.getBorrowAmount(borrow)}`\n );\n }\n\n const obligationCumulativeBorrowRate = KaminoObligation.getCumulativeBorrowRate(borrow);\n let cumulativeBorrowRate;\n if (cumulativeBorrowRates !== null) {\n cumulativeBorrowRate = cumulativeBorrowRates.get(reserve.address)!;\n } else {\n cumulativeBorrowRate = reserve.getCumulativeBorrowRate();\n }\n\n const borrowAmount = KaminoObligation.getBorrowAmount(borrow)\n .mul(cumulativeBorrowRate)\n .dividedBy(obligationCumulativeBorrowRate);\n\n const borrowValueUsd = borrowAmount.mul(getPx(reserve)).dividedBy(reserve.getMintFactor());\n\n const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);\n const borrowValueBorrowFactorAdjustedUsd = borrowValueUsd.mul(borrowFactor);\n\n if (!borrowAmount.eq(new Decimal('0'))) {\n positions += 1;\n }\n\n userTotalBorrow = userTotalBorrow.plus(borrowValueUsd);\n userTotalBorrowBorrowFactorAdjusted = userTotalBorrowBorrowFactorAdjusted.plus(\n borrowValueBorrowFactorAdjustedUsd\n );\n\n const position: Position = {\n reserveAddress: reserve.address,\n mintAddress: reserve.getLiquidityMint(),\n amount: borrowAmount,\n marketValueRefreshed: borrowValueUsd,\n };\n borrows.set(reserve.address, position);\n }\n\n return {\n borrows,\n userTotalBorrow,\n userTotalBorrowBorrowFactorAdjusted,\n positions,\n };\n }\n\n getMaxLoanLtvGivenElevationGroup(market: KaminoMarket, elevationGroup: number, slot: number): Decimal {\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);\n\n const { borrowLimit, userTotalDeposit } = KaminoObligation.calculateObligationDeposits(\n market,\n this.state.deposits,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n if (borrowLimit.eq(0) || userTotalDeposit.eq(0)) {\n return new Decimal(0);\n }\n\n return borrowLimit.div(userTotalDeposit);\n }\n\n /* \n How much of a given token can a user borrow extra given an elevation group, \n regardless of caps and liquidity or assuming infinite liquidity and infinite caps,\n until it hits max LTV.\n\n This is purely a function about the borrow power of an obligation, \n not a reserve-specific, caps-specific, liquidity-specific function.\n\n * @param market - The KaminoMarket instance.\n * @param liquidityMint - The liquidity mint PublicKey.\n * @param slot - The slot number.\n * @param elevationGroup - The elevation group number (default: this.state.elevationGroup).\n * @returns The borrow power as a Decimal.\n * @throws Error if the reserve is not found.\n */\n getBorrowPower(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n elevationGroup: number = this.state.elevationGroup\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n\n const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);\n\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(\n market,\n this.state,\n slot\n );\n\n const { borrowLimit } = KaminoObligation.calculateObligationDeposits(\n market,\n this.state.deposits,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n const { userTotalBorrowBorrowFactorAdjusted } = KaminoObligation.calculateObligationBorrows(\n market,\n this.state.borrows,\n cumulativeBorrowRates,\n elevationGroup,\n getOraclePx\n );\n\n const maxObligationBorrowPower = borrowLimit // adjusted available amount\n .minus(userTotalBorrowBorrowFactorAdjusted)\n .div(borrowFactor)\n .div(reserve.getOracleMarketPrice())\n .mul(reserve.getMintFactor());\n\n // If it has any collateral outside emode, then return 0\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n if (depositReserve.state.config.disableUsageAsCollOutsideEmode && !elevationGroupActivated) {\n return new Decimal(0);\n }\n }\n\n // This is not amazing because it assumes max borrow, which is not true\n let originationFeeRate = reserve.getBorrowFee();\n\n // Inclusive fee rate\n originationFeeRate = originationFeeRate.div(originationFeeRate.add(new Decimal(1)));\n const borrowFee = maxObligationBorrowPower.mul(originationFeeRate);\n\n const maxBorrowAmount = maxObligationBorrowPower.sub(borrowFee);\n\n return Decimal.max(new Decimal(0), maxBorrowAmount);\n }\n\n /* \n How much of a given token can a user borrow extra given an elevation group,\n and a specific reserve, until it hits max LTV and given available liquidity and caps.\n\n * @param market - The KaminoMarket instance.\n * @param liquidityMint - The liquidity mint PublicKey.\n * @param slot - The slot number.\n * @param elevationGroup - The elevation group number (default: this.state.elevationGroup).\n * @returns The maximum borrow amount as a Decimal.\n * @throws Error if the reserve is not found.\n */\n getMaxBorrowAmountV2(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n elevationGroup: number = this.state.elevationGroup\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const liquidityAvailable = reserve.getLiquidityAvailableForDebtReserveGivenCaps(market, [elevationGroup])[0];\n const maxBorrowAmount = this.getBorrowPower(market, liquidityMint, slot, elevationGroup);\n\n if (elevationGroup === this.state.elevationGroup) {\n return Decimal.min(maxBorrowAmount, liquidityAvailable);\n } else {\n const { amount: debtThisReserve } = this.borrows.get(reserve.address) || { amount: new Decimal(0) };\n const liquidityAvailablePostMigration = Decimal.max(0, liquidityAvailable.minus(debtThisReserve));\n return Decimal.min(maxBorrowAmount, liquidityAvailablePostMigration);\n }\n }\n\n /* \n Returns true if the loan is eligible for the elevation group, including for the default one.\n * @param market - The KaminoMarket object representing the market.\n * @param slot - The slot number of the loan.\n * @param elevationGroup - The elevation group number.\n * @returns A boolean indicating whether the loan is eligible for elevation.\n */\n isLoanEligibleForElevationGroup(market: KaminoMarket, slot: number, elevationGroup: number): boolean {\n // - isLoanEligibleForEmode(obligation, emode: 0 | number): <boolean, ErrorMessage>\n // - essentially checks if a loan can be migrated or not\n // - [x] due to collateral / debt reserves combination\n // - [x] due to LTV, etc\n\n const reserveDeposits: string[] = Array.from(this.deposits.keys()).map((x) => x.toString());\n const reserveBorrows: string[] = Array.from(this.borrows.keys()).map((x) => x.toString());\n\n if (reserveBorrows.length > 1) {\n return false;\n }\n\n if (elevationGroup > 0) {\n // Elevation group 0 doesn't need to do reserve checks, as all are included by default\n const allElevationGroups = market.getMarketElevationGroupDescriptions();\n const elevationGroupDescription = allElevationGroups[elevationGroup - 1];\n\n // Has to be a subset\n const allCollsIncluded = reserveDeposits.every((reserve) =>\n elevationGroupDescription.collateralReserves.includes(reserve)\n );\n const allDebtsIncluded =\n reserveBorrows.length === 0 ||\n (reserveBorrows.length === 1 && elevationGroupDescription.debtReserve === reserveBorrows[0]);\n\n if (!allCollsIncluded || !allDebtsIncluded) {\n return false;\n }\n }\n\n // Check if the loan can be migrated based on LTV\n const getOraclePx = (reserve: KaminoReserve) => reserve.getOracleMarketPrice();\n const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);\n\n const { borrowLimit } = KaminoObligation.calculateObligationDeposits(\n market,\n this.state.deposits,\n collateralExchangeRates,\n elevationGroup,\n getOraclePx\n );\n\n const isEligibleBasedOnLtv = this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.lte(borrowLimit);\n\n return isEligibleBasedOnLtv;\n }\n\n /* \n Returns all elevation groups for a given obligation, except the default one\n * @param market - The KaminoMarket instance.\n * @returns An array of ElevationGroupDescription objects representing the elevation groups for the obligation.\n */\n getElevationGroupsForObligation(market: KaminoMarket): ElevationGroupDescription[] {\n if (this.borrows.size > 1) {\n return [];\n }\n\n const collReserves = Array.from(this.deposits.keys());\n if (this.borrows.size === 0) {\n return market.getElevationGroupsForReservesCombination(collReserves);\n } else {\n const debtReserve = Array.from(this.borrows.keys())[0];\n return market.getElevationGroupsForReservesCombination(collReserves, debtReserve);\n }\n }\n\n /* Deprecated function, also broken */\n getMaxBorrowAmount(\n market: KaminoMarket,\n liquidityMint: PublicKey,\n slot: number,\n requestElevationGroup: boolean\n ): Decimal {\n const reserve = market.getReserveByMint(liquidityMint);\n\n if (!reserve) {\n throw new Error('Reserve not found');\n }\n\n const groups = market.state.elevationGroups;\n const emodeGroupsDebtReserve = reserve.state.config.elevationGroups;\n let commonElevationGroups = [...emodeGroupsDebtReserve].filter(\n (item) => item !== 0 && groups[item - 1].debtReserve.equals(reserve.address)\n );\n\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const depositReserveEmodeGroups = depositReserve.state.config.elevationGroups;\n\n commonElevationGroups = commonElevationGroups.filter((item) => depositReserveEmodeGroups.includes(item));\n }\n\n let elevationGroup = this.state.elevationGroup;\n if (commonElevationGroups.length != 0) {\n const eModeGroupWithMaxLtvAndDebtReserve = commonElevationGroups.reduce((prev, curr) => {\n const prevGroup = groups.find((group) => group.id === prev);\n const currGroup = groups.find((group) => group.id === curr);\n return prevGroup!.ltvPct > currGroup!.ltvPct ? prev : curr;\n });\n\n if (requestElevationGroup) {\n elevationGroup = eModeGroupWithMaxLtvAndDebtReserve;\n }\n }\n\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n\n const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);\n\n const maxObligationBorrowPower = this.refreshedStats.borrowLimit // adjusted available amount\n .minus(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)\n .div(borrowFactor)\n .div(reserve.getOracleMarketPrice())\n .mul(reserve.getMintFactor());\n const reserveAvailableAmount = reserve.getLiquidityAvailableAmount();\n let reserveBorrowCapRemained = reserve.stats.reserveBorrowLimit.sub(reserve.getBorrowedAmount());\n\n this.deposits.forEach((deposit) => {\n const depositReserve = market.getReserveByAddress(deposit.reserveAddress);\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n if (depositReserve.state.config.disableUsageAsCollOutsideEmode && !elevationGroupActivated) {\n reserveBorrowCapRemained = new Decimal(0);\n }\n });\n\n let maxBorrowAmount = Decimal.min(maxObligationBorrowPower, reserveAvailableAmount, reserveBorrowCapRemained);\n\n const debtWithdrawalCap = reserve.getDebtWithdrawalCapCapacity().sub(reserve.getDebtWithdrawalCapCurrent(slot));\n maxBorrowAmount = reserve.getDebtWithdrawalCapCapacity().gt(0)\n ? Decimal.min(maxBorrowAmount, debtWithdrawalCap)\n : maxBorrowAmount;\n\n let originationFeeRate = reserve.getBorrowFee();\n\n // Inclusive fee rate\n originationFeeRate = originationFeeRate.div(originationFeeRate.add(new Decimal(1)));\n const borrowFee = maxBorrowAmount.mul(originationFeeRate);\n\n maxBorrowAmount = maxBorrowAmount.sub(borrowFee);\n\n const utilizationRatioLimit = reserve.state.config.utilizationLimitBlockBorrowingAbove / 100;\n const currentUtilizationRatio = reserve.calculateUtilizationRatio();\n\n if (utilizationRatioLimit > 0 && currentUtilizationRatio > utilizationRatioLimit) {\n return new Decimal(0);\n } else if (utilizationRatioLimit > 0 && currentUtilizationRatio < utilizationRatioLimit) {\n const maxBorrowBasedOnUtilization = new Decimal(utilizationRatioLimit - currentUtilizationRatio).mul(\n reserve.getTotalSupply()\n );\n maxBorrowAmount = Decimal.min(maxBorrowAmount, maxBorrowBasedOnUtilization);\n }\n\n let borrowLimitDependentOnElevationGroup = new Decimal(U64_MAX);\n\n if (!elevationGroupActivated) {\n borrowLimitDependentOnElevationGroup = reserve\n .getBorrowLimitOutsideElevationGroup()\n .sub(reserve.getBorrowedAmountOutsideElevationGroup());\n } else {\n let maxDebtTakenAgainstCollaterals = new Decimal(U64_MAX);\n for (const [_, value] of this.deposits.entries()) {\n const depositReserve = market.getReserveByAddress(value.reserveAddress);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const maxDebtAllowedAgainstCollateral = depositReserve\n .getBorrowLimitAgainstCollateralInElevationGroup(elevationGroup - 1)\n .sub(depositReserve.getBorrowedAmountAgainstCollateralInElevationGroup(elevationGroup - 1));\n\n maxDebtTakenAgainstCollaterals = Decimal.max(\n new Decimal(0),\n Decimal.min(maxDebtAllowedAgainstCollateral, maxDebtTakenAgainstCollaterals)\n );\n }\n borrowLimitDependentOnElevationGroup = maxDebtTakenAgainstCollaterals;\n }\n\n maxBorrowAmount = Decimal.min(maxBorrowAmount, borrowLimitDependentOnElevationGroup);\n\n return Decimal.max(new Decimal(0), maxBorrowAmount);\n }\n\n getMaxWithdrawAmount(market: KaminoMarket, tokenMint: PublicKey, slot: number): Decimal {\n const depositReserve = market.getReserveByMint(tokenMint);\n\n if (!depositReserve) {\n throw new Error('Reserve not found');\n }\n\n const userDepositPosition = this.getDepositByReserve(depositReserve.address);\n\n if (!userDepositPosition) {\n throw new Error('Deposit reserve not found');\n }\n\n const userDepositPositionAmount = userDepositPosition.amount;\n\n if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.equals(new Decimal(0))) {\n return new Decimal(userDepositPositionAmount);\n }\n\n const { maxLtv: reserveMaxLtv } = KaminoObligation.getLtvForReserve(\n market,\n depositReserve,\n this.state.elevationGroup\n );\n // bf adjusted debt value > allowed_borrow_value\n if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.gte(this.refreshedStats.borrowLimit)) {\n return new Decimal(0);\n }\n\n let maxWithdrawValue: Decimal;\n if (reserveMaxLtv.eq(0)) {\n maxWithdrawValue = userDepositPositionAmount;\n } else {\n // borrowLimit / userTotalDeposit = maxLtv\n // maxWithdrawValue = userTotalDeposit - userTotalBorrow / maxLtv\n maxWithdrawValue = this.refreshedStats.borrowLimit\n .sub(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)\n .div(reserveMaxLtv)\n .mul(0.999); // remove 0.1% to prevent going over max ltv\n }\n\n const maxWithdrawAmount = maxWithdrawValue\n .div(depositReserve.getOracleMarketPrice())\n .mul(depositReserve.getMintFactor());\n const reserveAvailableLiquidity = depositReserve.getLiquidityAvailableAmount();\n\n const withdrawalCapRemained = depositReserve\n .getDepositWithdrawalCapCapacity()\n .sub(depositReserve.getDepositWithdrawalCapCurrent(slot));\n return Decimal.max(\n 0,\n Decimal.min(userDepositPositionAmount, maxWithdrawAmount, reserveAvailableLiquidity, withdrawalCapRemained)\n );\n }\n\n /**\n *\n * @returns Total borrowed amount for the specified obligation liquidity/borrow asset\n */\n static getBorrowAmount(borrow: ObligationLiquidity): Decimal {\n return new Fraction(borrow.borrowedAmountSf).toDecimal();\n }\n\n /**\n *\n * @returns Cumulative borrow rate for the specified obligation liquidity/borrow asset\n */\n static getCumulativeBorrowRate(borrow: ObligationLiquidity): Decimal {\n let accSf = new BN(0);\n for (const value of borrow.cumulativeBorrowRateBsf.value.reverse()) {\n accSf = accSf.add(value);\n accSf.shrn(64);\n }\n return new Fraction(accSf).toDecimal();\n }\n\n public static getRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n slot: number\n ): {\n collateralExchangeRates: Map<PublicKey, Decimal>;\n cumulativeBorrowRates: Map<PublicKey, Decimal>;\n } {\n const collateralExchangeRates = KaminoObligation.getCollateralExchangeRatesForObligation(\n kaminoMarket,\n obligation,\n slot\n );\n const cumulativeBorrowRates = KaminoObligation.getCumulativeBorrowRatesForObligation(\n kaminoMarket,\n obligation,\n slot\n );\n\n return {\n collateralExchangeRates,\n cumulativeBorrowRates,\n };\n }\n\n public static addRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n cumulativeBorrowRates: Map<PublicKey, Decimal>,\n slot: number\n ): void {\n KaminoObligation.addCollateralExchangeRatesForObligation(kaminoMarket, collateralExchangeRates, obligation, slot);\n KaminoObligation.addCumulativeBorrowRatesForObligation(kaminoMarket, cumulativeBorrowRates, obligation, slot);\n }\n\n static getCollateralExchangeRatesForObligation(\n kaminoMarket: KaminoMarket,\n obligation: Obligation,\n slot: number\n ): Map<PublicKey, Decimal> {\n const collateralExchangeRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (let i = 0; i < obligation.deposits.length; i++) {\n const deposit = obligation.deposits[i];\n if (isNotNullPubkey(deposit.depositReserve) && !collateralExchangeRates.has(deposit.depositReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(deposit.depositReserve)!;\n const collateralExchangeRate = reserve.getEstimatedCollateralExchangeRate(\n slot,\n kaminoMarket.state.referralFeeBps\n );\n collateralExchangeRates.set(reserve.address, collateralExchangeRate);\n }\n }\n return collateralExchangeRates;\n }\n\n static addCollateralExchangeRatesForObligation(\n kaminoMarket: KaminoMarket,\n collateralExchangeRates: Map<PublicKey, Decimal>,\n obligation: Obligation,\n slot: number\n ) {\n for (let i = 0; i < obligation.deposits.length; i++) {\n const deposit = obligation.deposits[i];\n if (isNotNullPubkey(deposit.depositReserve) && !collateralExchangeRates.has(deposit.depositReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(deposit.depositReserve)!;\n const collateralExchangeRate = reserve.getEstimatedCollateralExchangeRate(\n slot,\n kaminoMarket.state.referralFeeBps\n );\n collateralExchangeRates.set(reserve.address, collateralExchangeRate);\n }\n }\n }\n\n static getCumulativeBorrowRatesForObligation(kaminoMarket: KaminoMarket, obligation: Obligation, slot: number) {\n const cumulativeBorrowRates = new PubkeyHashMap<PublicKey, Decimal>();\n for (let i = 0; i < obligation.borrows.length; i++) {\n const borrow = obligation.borrows[i];\n if (isNotNullPubkey(borrow.borrowReserve) && !cumulativeBorrowRates.has(borrow.borrowReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(borrow.borrowReserve)!;\n const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);\n cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);\n }\n }\n return cumulativeBorrowRates;\n }\n\n static addCumulativeBorrowRatesForObligation(\n kaminoMarket: KaminoMarket,\n cumulativeBorrowRates: Map<PublicKey, Decimal>,\n obligation: Obligation,\n slot: number\n ) {\n for (let i = 0; i < obligation.borrows.length; i++) {\n const borrow = obligation.borrows[i];\n if (isNotNullPubkey(borrow.borrowReserve) && !cumulativeBorrowRates.has(borrow.borrowReserve)) {\n const reserve = kaminoMarket.getReserveByAddress(borrow.borrowReserve)!;\n const cumulativeBorrowRate = reserve.getEstimatedCumulativeBorrowRate(slot, kaminoMarket.state.referralFeeBps);\n cumulativeBorrowRates.set(reserve.address, cumulativeBorrowRate);\n }\n }\n }\n\n /**\n * Get the borrow factor for a borrow reserve, accounting for the obligation elevation group if it is active\n * @param reserve\n * @param elevationGroup\n */\n public static getBorrowFactorForReserve(reserve: KaminoReserve, elevationGroup: number): Decimal {\n const elevationGroupActivated =\n reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;\n if (elevationGroupActivated) {\n return new Decimal('1');\n }\n return new Decimal(reserve.stats.borrowFactor).div('100');\n }\n\n /**\n * Get the loan to value and liquidation loan to value for a collateral reserve as ratios, accounting for the obligation elevation group if it is active\n * @param market\n * @param reserve\n * @param elevationGroup\n */\n public static getLtvForReserve(\n market: KaminoMarket,\n reserve: KaminoReserve,\n elevationGroup: number\n ): { maxLtv: Decimal; liquidationLtv: Decimal } {\n const elevationGroupActivated =\n elevationGroup !== 0 && reserve.state.config.elevationGroups.includes(elevationGroup);\n if (elevationGroupActivated) {\n const { ltvPct, liquidationThresholdPct } = market.getElevationGroup(elevationGroup);\n return {\n maxLtv: new Decimal(ltvPct).div('100'),\n liquidationLtv: new Decimal(liquidationThresholdPct).div('100'),\n };\n } else {\n const { loanToValue, liquidationThreshold } = reserve.stats;\n return {\n maxLtv: new Decimal(loanToValue),\n liquidationLtv: new Decimal(liquidationThreshold),\n };\n }\n }\n}\n"]}
|