@kamino-finance/klend-sdk 5.2.1 → 5.2.3
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/manager.d.ts +27 -3
- package/dist/classes/manager.d.ts.map +1 -1
- package/dist/classes/manager.js +32 -2
- package/dist/classes/manager.js.map +1 -1
- package/dist/classes/reserve.d.ts.map +1 -1
- package/dist/classes/utils.d.ts +1 -0
- package/dist/classes/utils.d.ts.map +1 -1
- package/dist/classes/utils.js +4 -0
- package/dist/classes/utils.js.map +1 -1
- package/dist/classes/vault.d.ts +48 -6
- package/dist/classes/vault.d.ts.map +1 -1
- package/dist/classes/vault.js +122 -45
- package/dist/classes/vault.js.map +1 -1
- package/dist/client_kamino_manager.d.ts.map +1 -1
- package/dist/client_kamino_manager.js +11 -0
- package/dist/client_kamino_manager.js.map +1 -1
- package/package.json +1 -1
- package/src/classes/manager.ts +48 -2
- package/src/classes/reserve.ts +2 -2
- package/src/classes/utils.ts +4 -0
- package/src/classes/vault.ts +205 -68
- package/src/client_kamino_manager.ts +19 -0
package/src/classes/vault.ts
CHANGED
|
@@ -18,8 +18,6 @@ import {
|
|
|
18
18
|
KaminoMarket,
|
|
19
19
|
KaminoReserve,
|
|
20
20
|
lamportsToDecimal,
|
|
21
|
-
LendingMarket,
|
|
22
|
-
MarketWithAddress,
|
|
23
21
|
PubkeyHashMap,
|
|
24
22
|
Reserve,
|
|
25
23
|
WRAPPED_SOL_MINT,
|
|
@@ -50,7 +48,7 @@ import {
|
|
|
50
48
|
import { VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
|
|
51
49
|
import { VaultState } from '../idl_codegen_kamino_vault/accounts';
|
|
52
50
|
import Decimal from 'decimal.js';
|
|
53
|
-
import { getTokenBalanceFromAccountInfoLamports, numberToLamportsDecimal, parseTokenSymbol } from './utils';
|
|
51
|
+
import { bpsToPct, getTokenBalanceFromAccountInfoLamports, numberToLamportsDecimal, parseTokenSymbol } from './utils';
|
|
54
52
|
import { deposit } from '../idl_codegen_kamino_vault/instructions';
|
|
55
53
|
import { withdraw } from '../idl_codegen_kamino_vault/instructions';
|
|
56
54
|
import { PROGRAM_ID } from '../idl_codegen/programId';
|
|
@@ -348,22 +346,12 @@ export class KaminoVaultClient {
|
|
|
348
346
|
}
|
|
349
347
|
|
|
350
348
|
const reserveState = reserveStates[index]!;
|
|
351
|
-
|
|
352
|
-
const market = reserveState.lendingMarket;
|
|
353
|
-
const marketState = await LendingMarket.fetch(this._connection, market, this._kaminoLendProgramId);
|
|
354
|
-
if (marketState === null) {
|
|
355
|
-
throw new Error(`Market ${market.toBase58()} not found`);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
const marketWithAddress = {
|
|
359
|
-
address: market,
|
|
360
|
-
state: marketState,
|
|
361
|
-
};
|
|
349
|
+
const marketAddress = reserveState.lendingMarket;
|
|
362
350
|
|
|
363
351
|
return this.withdrawPendingFeesIxn(
|
|
364
352
|
vault,
|
|
365
353
|
vaultState,
|
|
366
|
-
|
|
354
|
+
marketAddress,
|
|
367
355
|
{ address: reserve, state: reserveState },
|
|
368
356
|
adminTokenAta
|
|
369
357
|
);
|
|
@@ -389,7 +377,6 @@ export class KaminoVaultClient {
|
|
|
389
377
|
* @param user - user to deposit
|
|
390
378
|
* @param vault - vault to deposit into
|
|
391
379
|
* @param tokenAmount - token amount to be deposited, in decimals (will be converted in lamports)
|
|
392
|
-
* @param tokenProgramIDOverride - optional param; should be passed if token to be deposited is token22
|
|
393
380
|
* @param vaultReservesMap - optional parameter; a hashmap from each reserve pubkey to the reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
|
|
394
381
|
* @returns - an array of instructions to be used to be executed
|
|
395
382
|
*/
|
|
@@ -397,12 +384,11 @@ export class KaminoVaultClient {
|
|
|
397
384
|
user: PublicKey,
|
|
398
385
|
vault: KaminoVault,
|
|
399
386
|
tokenAmount: Decimal,
|
|
400
|
-
tokenProgramIDOverride?: PublicKey,
|
|
401
387
|
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
402
388
|
): Promise<TransactionInstruction[]> {
|
|
403
389
|
const vaultState = await vault.getState(this._connection);
|
|
404
390
|
|
|
405
|
-
const tokenProgramID =
|
|
391
|
+
const tokenProgramID = vaultState.tokenProgram;
|
|
406
392
|
const userTokenAta = getAssociatedTokenAddress(vaultState.tokenMint, user, true, tokenProgramID);
|
|
407
393
|
const createAtasIxns: TransactionInstruction[] = [];
|
|
408
394
|
const closeAtasIxns: TransactionInstruction[] = [];
|
|
@@ -487,15 +473,18 @@ export class KaminoVaultClient {
|
|
|
487
473
|
user: PublicKey,
|
|
488
474
|
vault: KaminoVault,
|
|
489
475
|
shareAmount: Decimal,
|
|
490
|
-
slot: number
|
|
476
|
+
slot: number,
|
|
477
|
+
vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
491
478
|
): Promise<TransactionInstruction[]> {
|
|
492
479
|
const vaultState = await vault.getState(this._connection);
|
|
493
480
|
|
|
481
|
+
const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
|
|
482
|
+
|
|
494
483
|
const userSharesAta = getAssociatedTokenAddress(vaultState.sharesMint, user);
|
|
495
484
|
const [{ ata: userTokenAta, createAtaIx }] = createAtasIdempotent(user, [
|
|
496
485
|
{
|
|
497
486
|
mint: vaultState.tokenMint,
|
|
498
|
-
tokenProgram:
|
|
487
|
+
tokenProgram: vaultState.tokenProgram,
|
|
499
488
|
},
|
|
500
489
|
]);
|
|
501
490
|
|
|
@@ -531,40 +520,31 @@ export class KaminoVaultClient {
|
|
|
531
520
|
});
|
|
532
521
|
}
|
|
533
522
|
|
|
534
|
-
const
|
|
535
|
-
|
|
536
|
-
reservesToWithdraw.map(async (reserve, index) => {
|
|
537
|
-
if (reserveStates[index] === null) {
|
|
538
|
-
throw new Error(`Reserve ${reserve.toBase58()} not found`);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
const reserveState = reserveStates[index]!;
|
|
523
|
+
const withdrawIxns: TransactionInstruction[] = [];
|
|
524
|
+
withdrawIxns.push(createAtaIx);
|
|
542
525
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
const marketWithAddress = {
|
|
550
|
-
address: market,
|
|
551
|
-
state: marketState,
|
|
552
|
-
};
|
|
526
|
+
reservesToWithdraw.forEach((reserve, index) => {
|
|
527
|
+
const reserveState = vaultReservesState.get(reserve);
|
|
528
|
+
if (reserveState === undefined) {
|
|
529
|
+
throw new Error(`Reserve ${reserve.toBase58()} not found in vault reserves map`);
|
|
530
|
+
}
|
|
553
531
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
532
|
+
const marketAddress = reserveState.state.lendingMarket;
|
|
533
|
+
const withdrawFromReserveIx = this.withdrawIxn(
|
|
534
|
+
user,
|
|
535
|
+
vault,
|
|
536
|
+
vaultState,
|
|
537
|
+
marketAddress,
|
|
538
|
+
{ address: reserve, state: reserveState.state },
|
|
539
|
+
userSharesAta,
|
|
540
|
+
userTokenAta,
|
|
541
|
+
amountToWithdraw[index],
|
|
542
|
+
vaultReservesState
|
|
543
|
+
);
|
|
544
|
+
withdrawIxns.push(withdrawFromReserveIx);
|
|
545
|
+
});
|
|
566
546
|
|
|
567
|
-
return
|
|
547
|
+
return withdrawIxns;
|
|
568
548
|
}
|
|
569
549
|
|
|
570
550
|
/**
|
|
@@ -646,17 +626,18 @@ export class KaminoVaultClient {
|
|
|
646
626
|
return [createAtaIx, investIx];
|
|
647
627
|
}
|
|
648
628
|
|
|
649
|
-
private
|
|
629
|
+
private withdrawIxn(
|
|
650
630
|
user: PublicKey,
|
|
651
631
|
vault: KaminoVault,
|
|
652
632
|
vaultState: VaultState,
|
|
653
|
-
|
|
633
|
+
marketAddress: PublicKey,
|
|
654
634
|
reserve: ReserveWithAddress,
|
|
655
635
|
userSharesAta: PublicKey,
|
|
656
636
|
userTokenAta: PublicKey,
|
|
657
|
-
shareAmountLamports: Decimal
|
|
658
|
-
|
|
659
|
-
|
|
637
|
+
shareAmountLamports: Decimal,
|
|
638
|
+
vaultReservesState: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
639
|
+
): TransactionInstruction {
|
|
640
|
+
const lendingMarketAuth = lendingMarketAuthPda(marketAddress, this._kaminoLendProgramId)[0];
|
|
660
641
|
|
|
661
642
|
const withdrawAccounts: WithdrawAccounts = {
|
|
662
643
|
user: user,
|
|
@@ -672,7 +653,7 @@ export class KaminoVaultClient {
|
|
|
672
653
|
reserve: reserve.address,
|
|
673
654
|
ctokenVault: getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId),
|
|
674
655
|
/** CPI accounts */
|
|
675
|
-
lendingMarket:
|
|
656
|
+
lendingMarket: marketAddress,
|
|
676
657
|
lendingMarketAuthority: lendingMarketAuth,
|
|
677
658
|
reserveLiquiditySupply: reserve.state.liquidity.supplyVault,
|
|
678
659
|
reserveCollateralMint: reserve.state.collateral.mintPubkey,
|
|
@@ -688,7 +669,6 @@ export class KaminoVaultClient {
|
|
|
688
669
|
const withdrawIxn = withdraw(withdrawArgs, withdrawAccounts, this._kaminoVaultProgramId);
|
|
689
670
|
|
|
690
671
|
const vaultReserves = this.getVaultReserves(vaultState);
|
|
691
|
-
const vaultReservesState = await this.loadVaultReserves(vaultState);
|
|
692
672
|
|
|
693
673
|
let vaultReservesAccountMetas: AccountMeta[] = [];
|
|
694
674
|
let vaultReservesLendingMarkets: AccountMeta[] = [];
|
|
@@ -715,11 +695,11 @@ export class KaminoVaultClient {
|
|
|
715
695
|
private async withdrawPendingFeesIxn(
|
|
716
696
|
vault: KaminoVault,
|
|
717
697
|
vaultState: VaultState,
|
|
718
|
-
|
|
698
|
+
marketAddress: PublicKey,
|
|
719
699
|
reserve: ReserveWithAddress,
|
|
720
700
|
adminTokenAta: PublicKey
|
|
721
701
|
): Promise<TransactionInstruction> {
|
|
722
|
-
const lendingMarketAuth = lendingMarketAuthPda(
|
|
702
|
+
const lendingMarketAuth = lendingMarketAuthPda(marketAddress, this._kaminoLendProgramId)[0];
|
|
723
703
|
|
|
724
704
|
const withdrawPendingFeesAccounts: WithdrawPendingFeesAccounts = {
|
|
725
705
|
adminAuthority: vaultState.adminAuthority,
|
|
@@ -732,7 +712,7 @@ export class KaminoVaultClient {
|
|
|
732
712
|
tokenMint: vaultState.tokenMint,
|
|
733
713
|
tokenProgram: TOKEN_PROGRAM_ID,
|
|
734
714
|
/** CPI accounts */
|
|
735
|
-
lendingMarket:
|
|
715
|
+
lendingMarket: marketAddress,
|
|
736
716
|
lendingMarketAuthority: lendingMarketAuth,
|
|
737
717
|
reserveLiquiditySupply: reserve.state.liquidity.supplyVault,
|
|
738
718
|
reserveCollateralMint: reserve.state.collateral.mintPubkey,
|
|
@@ -829,6 +809,18 @@ export class KaminoVaultClient {
|
|
|
829
809
|
return vaultUserShareBalance;
|
|
830
810
|
}
|
|
831
811
|
|
|
812
|
+
/**
|
|
813
|
+
* This method returns the management and performance fee percentages
|
|
814
|
+
* @param vaultState - vault to retrieve the fees percentages from
|
|
815
|
+
* @returns - VaultFeesPct containing management and performance fee percentages
|
|
816
|
+
*/
|
|
817
|
+
getVaultFeesPct(vaultState: VaultState): VaultFeesPct {
|
|
818
|
+
return {
|
|
819
|
+
managementFeePct: bpsToPct(new Decimal(vaultState.managementFeeBps.toString())),
|
|
820
|
+
performanceFeePct: bpsToPct(new Decimal(vaultState.performanceFeeBps.toString())),
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
|
|
832
824
|
/**
|
|
833
825
|
* This method calculates the token per shar value. This will always change based on interest earned from the vault, but calculating it requires a bunch of rpc requests. Caching this for a short duration would be optimal
|
|
834
826
|
* @param vault - vault to calculate tokensPerShare for
|
|
@@ -1038,15 +1030,32 @@ export class KaminoVaultClient {
|
|
|
1038
1030
|
*
|
|
1039
1031
|
* @returns a hashmap from each reserve pubkey to the market overview of the collaterals that can be used and the min and max loan to value ratio in that market
|
|
1040
1032
|
*/
|
|
1041
|
-
async getVaultCollaterals(
|
|
1042
|
-
|
|
1033
|
+
async getVaultCollaterals(
|
|
1034
|
+
vaultState: VaultState,
|
|
1035
|
+
slot: number,
|
|
1036
|
+
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
1037
|
+
kaminoMarkets?: KaminoMarket[]
|
|
1038
|
+
): Promise<PubkeyHashMap<PublicKey, MarketOverview>> {
|
|
1039
|
+
const vaultReservesStateMap = vaultReserves ? vaultReserves : await this.loadVaultReserves(vaultState);
|
|
1040
|
+
const vaultReservesState = Array.from(vaultReservesStateMap.values());
|
|
1043
1041
|
|
|
1044
1042
|
const vaultCollateralsPerReserve: PubkeyHashMap<PublicKey, MarketOverview> = new PubkeyHashMap();
|
|
1045
1043
|
|
|
1046
1044
|
for (const reserve of vaultReservesState) {
|
|
1047
|
-
|
|
1045
|
+
// try to read the market from the provided list, if it doesn't exist fetch it
|
|
1046
|
+
let lendingMarket: KaminoMarket | undefined = undefined;
|
|
1047
|
+
if (kaminoMarkets) {
|
|
1048
|
+
lendingMarket = kaminoMarkets?.find((market) =>
|
|
1049
|
+
reserve.state.lendingMarket.equals(new PublicKey(market.address))
|
|
1050
|
+
);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1048
1053
|
if (!lendingMarket) {
|
|
1049
|
-
|
|
1054
|
+
const fetchedLendingMarket = await KaminoMarket.load(this._connection, reserve.state.lendingMarket, slot);
|
|
1055
|
+
if (!fetchedLendingMarket) {
|
|
1056
|
+
throw Error(`Could not fetch lending market ${reserve.state.lendingMarket.toBase58()}`);
|
|
1057
|
+
}
|
|
1058
|
+
lendingMarket = fetchedLendingMarket;
|
|
1050
1059
|
}
|
|
1051
1060
|
|
|
1052
1061
|
const marketReserves = lendingMarket.getReserves();
|
|
@@ -1060,7 +1069,9 @@ export class KaminoVaultClient {
|
|
|
1060
1069
|
marketReserves
|
|
1061
1070
|
.filter((marketReserve) => {
|
|
1062
1071
|
return (
|
|
1063
|
-
marketReserve.state.config.liquidationThresholdPct > 0 &&
|
|
1072
|
+
marketReserve.state.config.liquidationThresholdPct > 0 &&
|
|
1073
|
+
!marketReserve.address.equals(reserve.address) &&
|
|
1074
|
+
marketReserve.state.config.status === 0
|
|
1064
1075
|
);
|
|
1065
1076
|
})
|
|
1066
1077
|
.map((filteredReserve) => {
|
|
@@ -1162,6 +1173,109 @@ export class KaminoVaultClient {
|
|
|
1162
1173
|
availableUSD: holdings.available.mul(price),
|
|
1163
1174
|
investedUSD: holdings.invested.mul(price),
|
|
1164
1175
|
investedInReservesUSD: investedInReservesUSD,
|
|
1176
|
+
totalUSD: holdings.total.mul(price),
|
|
1177
|
+
};
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
/**
|
|
1181
|
+
* This will return an VaultOverview object that encapsulates all the information about the vault, including the holdings, reserves details, theoretical APY, utilization ratio and total borrowed amount
|
|
1182
|
+
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
1183
|
+
* @param slot - current slot
|
|
1184
|
+
* @param price - the price of the token in the vault (e.g. USDC)
|
|
1185
|
+
* @param vaultReserves - optional parameter; a hashmap from each reserve pubkey to the reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
|
|
1186
|
+
* @param kaminoMarkets - optional parameter; a list of all kamino markets. If provided the function will be significantly faster as it will not have to fetch the markets
|
|
1187
|
+
* @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
|
|
1188
|
+
*/
|
|
1189
|
+
async getVaultOverview(
|
|
1190
|
+
vault: VaultState,
|
|
1191
|
+
slot: number,
|
|
1192
|
+
price: Decimal,
|
|
1193
|
+
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>,
|
|
1194
|
+
kaminoMarkets?: KaminoMarket[]
|
|
1195
|
+
): Promise<VaultOverview> {
|
|
1196
|
+
const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
|
|
1197
|
+
|
|
1198
|
+
const vaultHoldingsWithUSDValuePromise = await this.getVaultHoldingsWithPrice(
|
|
1199
|
+
vault,
|
|
1200
|
+
slot,
|
|
1201
|
+
price,
|
|
1202
|
+
vaultReservesState
|
|
1203
|
+
);
|
|
1204
|
+
const vaultTheoreticalAPYPromise = await this.getVaultTheoreticalAPY(vault, slot, vaultReservesState);
|
|
1205
|
+
const totalInvestedAndBorrowedPromise = await this.getTotalBorrowedAndInvested(vault, slot, vaultReservesState);
|
|
1206
|
+
const vaultCollateralsPromise = await this.getVaultCollaterals(vault, slot, vaultReservesState, kaminoMarkets);
|
|
1207
|
+
const reservesOverviewPromise = await this.getVaultReservesDetails(vault, slot, vaultReservesState);
|
|
1208
|
+
|
|
1209
|
+
// all the async part of the functions above just read the vaultReservesState which is read beforehand, so excepting vaultCollateralsPromise they should do no additional network calls
|
|
1210
|
+
const [
|
|
1211
|
+
vaultHoldingsWithUSDValue,
|
|
1212
|
+
vaultTheoreticalAPY,
|
|
1213
|
+
totalInvestedAndBorrowed,
|
|
1214
|
+
vaultCollaterals,
|
|
1215
|
+
reservesOverview,
|
|
1216
|
+
] = await Promise.all([
|
|
1217
|
+
vaultHoldingsWithUSDValuePromise,
|
|
1218
|
+
vaultTheoreticalAPYPromise,
|
|
1219
|
+
totalInvestedAndBorrowedPromise,
|
|
1220
|
+
vaultCollateralsPromise,
|
|
1221
|
+
reservesOverviewPromise,
|
|
1222
|
+
]);
|
|
1223
|
+
|
|
1224
|
+
return {
|
|
1225
|
+
holdingsUSD: vaultHoldingsWithUSDValue,
|
|
1226
|
+
reservesOverview: reservesOverview,
|
|
1227
|
+
vaultCollaterals: vaultCollaterals,
|
|
1228
|
+
theoreticalSupplyAPY: vaultTheoreticalAPY,
|
|
1229
|
+
totalBorrowed: totalInvestedAndBorrowed.totalBorrowed,
|
|
1230
|
+
utilizationRatio: totalInvestedAndBorrowed.utilizationRatio,
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
/**
|
|
1235
|
+
* This will return an aggregation of the current state of the vault with all the invested amounts and the utilization ratio of the vault
|
|
1236
|
+
* @param vault - the kamino vault to get available liquidity to withdraw for
|
|
1237
|
+
* @param slot - current slot
|
|
1238
|
+
* @param vaultReserves - optional parameter; a hashmap from each reserve pubkey to the reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
|
|
1239
|
+
* @returns an VaultReserveTotalBorrowedAndInvested object with the total invested amount, total borrowed amount and the utilization ratio of the vault
|
|
1240
|
+
*/
|
|
1241
|
+
async getTotalBorrowedAndInvested(
|
|
1242
|
+
vault: VaultState,
|
|
1243
|
+
slot: number,
|
|
1244
|
+
vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
|
|
1245
|
+
): Promise<VaultReserveTotalBorrowedAndInvested> {
|
|
1246
|
+
const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
|
|
1247
|
+
|
|
1248
|
+
let totalInvested = new Decimal(0);
|
|
1249
|
+
let totalBorrowed = new Decimal(0);
|
|
1250
|
+
|
|
1251
|
+
vault.vaultAllocationStrategy.forEach((allocationStrategy) => {
|
|
1252
|
+
if (allocationStrategy.reserve.equals(PublicKey.default)) {
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
const reserve = vaultReservesState.get(allocationStrategy.reserve);
|
|
1257
|
+
if (reserve === undefined) {
|
|
1258
|
+
throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(slot, 0);
|
|
1262
|
+
const reserveAllocationLiquidityAmount = new Decimal(allocationStrategy.cTokenAllocation.toString()).div(
|
|
1263
|
+
reserveCollExchangeRate
|
|
1264
|
+
);
|
|
1265
|
+
|
|
1266
|
+
const utilizationRatio = reserve.getEstimatedUtilizationRatio(slot, 0);
|
|
1267
|
+
totalInvested = totalInvested.add(reserveAllocationLiquidityAmount);
|
|
1268
|
+
totalBorrowed = totalBorrowed.add(reserveAllocationLiquidityAmount.mul(utilizationRatio));
|
|
1269
|
+
});
|
|
1270
|
+
|
|
1271
|
+
let utilizationRatio = new Decimal(0);
|
|
1272
|
+
if (!totalInvested.isZero()) {
|
|
1273
|
+
utilizationRatio = totalBorrowed.div(totalInvested);
|
|
1274
|
+
}
|
|
1275
|
+
return {
|
|
1276
|
+
totalInvested: totalInvested,
|
|
1277
|
+
totalBorrowed: totalBorrowed,
|
|
1278
|
+
utilizationRatio: utilizationRatio,
|
|
1165
1279
|
};
|
|
1166
1280
|
}
|
|
1167
1281
|
|
|
@@ -1193,9 +1307,10 @@ export class KaminoVaultClient {
|
|
|
1193
1307
|
reserve.getBorrowedAmount();
|
|
1194
1308
|
const reserveOverview: ReserveOverview = {
|
|
1195
1309
|
supplyAPY: new Decimal(reserve.totalSupplyAPY(slot)),
|
|
1196
|
-
|
|
1310
|
+
utilizationRatio: new Decimal(reserve.getEstimatedUtilizationRatio(slot, 0)),
|
|
1197
1311
|
liquidationThresholdPct: new Decimal(reserve.state.config.liquidationThresholdPct),
|
|
1198
1312
|
borrowedAmount: reserve.getBorrowedAmount(),
|
|
1313
|
+
market: reserve.state.lendingMarket,
|
|
1199
1314
|
};
|
|
1200
1315
|
reservesDetails.set(allocationStrategy.reserve, reserveOverview);
|
|
1201
1316
|
});
|
|
@@ -1371,13 +1486,21 @@ export type VaultHoldingsWithUSDValue = {
|
|
|
1371
1486
|
availableUSD: Decimal;
|
|
1372
1487
|
investedUSD: Decimal;
|
|
1373
1488
|
investedInReservesUSD: PubkeyHashMap<PublicKey, Decimal>;
|
|
1489
|
+
totalUSD: Decimal;
|
|
1374
1490
|
};
|
|
1375
1491
|
|
|
1376
1492
|
export type ReserveOverview = {
|
|
1377
1493
|
supplyAPY: Decimal;
|
|
1378
|
-
|
|
1494
|
+
utilizationRatio: Decimal;
|
|
1379
1495
|
liquidationThresholdPct: Decimal;
|
|
1380
1496
|
borrowedAmount: Decimal;
|
|
1497
|
+
market: PublicKey;
|
|
1498
|
+
};
|
|
1499
|
+
|
|
1500
|
+
export type VaultReserveTotalBorrowedAndInvested = {
|
|
1501
|
+
totalInvested: Decimal;
|
|
1502
|
+
totalBorrowed: Decimal;
|
|
1503
|
+
utilizationRatio: Decimal;
|
|
1381
1504
|
};
|
|
1382
1505
|
|
|
1383
1506
|
export type MarketOverview = {
|
|
@@ -1391,3 +1514,17 @@ export type ReserveAsCollateral = {
|
|
|
1391
1514
|
mint: PublicKey;
|
|
1392
1515
|
liquidationLTVPct: Decimal;
|
|
1393
1516
|
};
|
|
1517
|
+
|
|
1518
|
+
export type VaultOverview = {
|
|
1519
|
+
holdingsUSD: VaultHoldingsWithUSDValue;
|
|
1520
|
+
reservesOverview: PubkeyHashMap<PublicKey, ReserveOverview>;
|
|
1521
|
+
vaultCollaterals: PubkeyHashMap<PublicKey, MarketOverview>;
|
|
1522
|
+
theoreticalSupplyAPY: Decimal;
|
|
1523
|
+
totalBorrowed: Decimal;
|
|
1524
|
+
utilizationRatio: Decimal;
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
export type VaultFeesPct = {
|
|
1528
|
+
managementFeePct: Decimal;
|
|
1529
|
+
performanceFeePct: Decimal;
|
|
1530
|
+
};
|
|
@@ -643,6 +643,25 @@ async function main() {
|
|
|
643
643
|
});
|
|
644
644
|
});
|
|
645
645
|
|
|
646
|
+
commands
|
|
647
|
+
.command('get-vault-overview')
|
|
648
|
+
.requiredOption('--vault <string>', 'Vault address')
|
|
649
|
+
.action(async ({ vault }) => {
|
|
650
|
+
const env = initializeClient(false, false);
|
|
651
|
+
|
|
652
|
+
const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
|
|
653
|
+
|
|
654
|
+
const vaultAddress = new PublicKey(vault);
|
|
655
|
+
const vaultState = await new KaminoVault(vaultAddress, undefined, env.kVaultProgramId).getState(env.connection);
|
|
656
|
+
const vaultOverview = await kaminoManager.getVaultOverview(
|
|
657
|
+
vaultState,
|
|
658
|
+
await env.connection.getSlot('confirmed'),
|
|
659
|
+
new Decimal(1.0)
|
|
660
|
+
);
|
|
661
|
+
|
|
662
|
+
console.log('vaultOverview', vaultOverview);
|
|
663
|
+
});
|
|
664
|
+
|
|
646
665
|
commands
|
|
647
666
|
.command('get-user-shares-for-vault')
|
|
648
667
|
.requiredOption('--vault <string>', 'Vault address')
|