@kamino-finance/klend-sdk 3.2.24 → 3.2.26
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.
|
@@ -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,17 @@ 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
|
-
userTotalDeposit: Decimal;
|
|
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;
|
|
177
158
|
getMaxLoanLtvGivenElevationGroup(market: KaminoMarket, elevationGroup: number, slot: number): Decimal;
|
|
178
159
|
getBorrowPower(market: KaminoMarket, liquidityMint: PublicKey, slot: number, elevationGroup?: number): Decimal;
|
|
179
160
|
getMaxBorrowAmountV2(market: KaminoMarket, liquidityMint: PublicKey, slot: number, elevationGroup?: number): Decimal;
|
|
@@ -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)}`);
|
|
@@ -557,7 +480,7 @@ class KaminoObligation {
|
|
|
557
480
|
getMaxLoanLtvGivenElevationGroup(market, elevationGroup, slot) {
|
|
558
481
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
559
482
|
const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
560
|
-
const { borrowLimit, userTotalDeposit } = KaminoObligation.calculateObligationDeposits(market, this.state, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
483
|
+
const { borrowLimit, userTotalDeposit } = KaminoObligation.calculateObligationDeposits(market, this.state.deposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
561
484
|
if (borrowLimit.eq(0) || userTotalDeposit.eq(0)) {
|
|
562
485
|
return new decimal_js_1.default(0);
|
|
563
486
|
}
|
|
@@ -587,8 +510,8 @@ class KaminoObligation {
|
|
|
587
510
|
const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);
|
|
588
511
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
589
512
|
const { collateralExchangeRates, cumulativeBorrowRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
590
|
-
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
591
|
-
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);
|
|
592
515
|
const maxObligationBorrowPower = borrowLimit // adjusted available amount
|
|
593
516
|
.minus(userTotalBorrowBorrowFactorAdjusted)
|
|
594
517
|
.div(borrowFactor)
|
|
@@ -671,7 +594,7 @@ class KaminoObligation {
|
|
|
671
594
|
// Check if the loan can be migrated based on LTV
|
|
672
595
|
const getOraclePx = (reserve) => reserve.getOracleMarketPrice();
|
|
673
596
|
const { collateralExchangeRates } = KaminoObligation.getRatesForObligation(market, this.state, slot);
|
|
674
|
-
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
597
|
+
const { borrowLimit } = KaminoObligation.calculateObligationDeposits(market, this.state.deposits, collateralExchangeRates, elevationGroup, getOraclePx);
|
|
675
598
|
const isEligibleBasedOnLtv = this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.lte(borrowLimit);
|
|
676
599
|
return isEligibleBasedOnLtv;
|
|
677
600
|
}
|
|
@@ -722,7 +645,7 @@ class KaminoObligation {
|
|
|
722
645
|
}
|
|
723
646
|
}
|
|
724
647
|
const elevationGroupActivated = reserve.state.config.elevationGroups.includes(elevationGroup) && elevationGroup !== 0;
|
|
725
|
-
const borrowFactor =
|
|
648
|
+
const borrowFactor = KaminoObligation.getBorrowFactorForReserve(reserve, elevationGroup);
|
|
726
649
|
const maxObligationBorrowPower = this.refreshedStats.borrowLimit // adjusted available amount
|
|
727
650
|
.minus(this.refreshedStats.userTotalBorrowBorrowFactorAdjusted)
|
|
728
651
|
.div(borrowFactor)
|
|
@@ -794,7 +717,7 @@ class KaminoObligation {
|
|
|
794
717
|
if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.equals(new decimal_js_1.default(0))) {
|
|
795
718
|
return new decimal_js_1.default(userDepositPositionAmount);
|
|
796
719
|
}
|
|
797
|
-
const { maxLtv: reserveMaxLtv } =
|
|
720
|
+
const { maxLtv: reserveMaxLtv } = KaminoObligation.getLtvForReserve(market, depositReserve, this.state.elevationGroup);
|
|
798
721
|
// bf adjusted debt value > allowed_borrow_value
|
|
799
722
|
if (this.refreshedStats.userTotalBorrowBorrowFactorAdjusted.gte(this.refreshedStats.borrowLimit)) {
|
|
800
723
|
return new decimal_js_1.default(0);
|