@kamino-finance/klend-sdk 5.1.0 → 5.1.2

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.
Files changed (39) hide show
  1. package/README_KAMINO_MANAGER.md +24 -3
  2. package/dist/classes/manager.d.ts +62 -2
  3. package/dist/classes/manager.d.ts.map +1 -1
  4. package/dist/classes/manager.js +76 -0
  5. package/dist/classes/manager.js.map +1 -1
  6. package/dist/classes/vault.d.ts +74 -5
  7. package/dist/classes/vault.d.ts.map +1 -1
  8. package/dist/classes/vault.js +134 -6
  9. package/dist/classes/vault.js.map +1 -1
  10. package/dist/client_kamino_manager.d.ts.map +1 -1
  11. package/dist/client_kamino_manager.js +6 -0
  12. package/dist/client_kamino_manager.js.map +1 -1
  13. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts +9 -3
  14. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts.map +1 -1
  15. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js +42 -32
  16. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js.map +1 -1
  17. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.d.ts +10 -10
  18. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.d.ts.map +1 -1
  19. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.js +51 -52
  20. package/dist/idl_codegen_kamino_vault/types/VaultConfigField.js.map +1 -1
  21. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.d.ts +2 -2
  22. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.d.ts.map +1 -1
  23. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.js +4 -4
  24. package/dist/idl_codegen_kamino_vault/types/WithdrawalCaps.js.map +1 -1
  25. package/dist/lib.d.ts +3 -0
  26. package/dist/lib.d.ts.map +1 -1
  27. package/dist/lib.js +4 -0
  28. package/dist/lib.js.map +1 -1
  29. package/dist/utils/rpc.js +2 -2
  30. package/dist/utils/rpc.js.map +1 -1
  31. package/package.json +3 -2
  32. package/src/classes/manager.ts +110 -1
  33. package/src/classes/vault.ts +204 -7
  34. package/src/client_kamino_manager.ts +8 -0
  35. package/src/idl_codegen_kamino_vault/accounts/VaultState.ts +178 -175
  36. package/src/idl_codegen_kamino_vault/types/VaultConfigField.ts +117 -116
  37. package/src/idl_codegen_kamino_vault/types/WithdrawalCaps.ts +30 -30
  38. package/src/lib.ts +6 -0
  39. package/src/utils/rpc.ts +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/utils/rpc.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../../src/utils/rpc.ts"],"names":[],"mappings":";;;;;AAyBA,gDA+CC;AAxED,6CAQyB;AACzB,mCAAgC;AAChC,kDAA0B;AAC1B,kDAAsD;AACtD,+BAAoC;AAEpC,CAAC,KAAK,IAAI,EAAE;IACV,MAAM,IAAA,gBAAI,GAAE,CAAC;AACf,CAAC,CAAC,EAAE,CAAC;AAEL;;;;;;GAMG;AACI,KAAK,UAAU,kBAAkB,CACtC,UAAsB,EACtB,SAAoB,EACpB,kBAA0D;IAE1D,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC;IAC1C,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,2BAA2B,CAAC,kBAAkB,CAAC,CAAC;IAC/E,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,qBAAqB,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;IACvE,oHAAoH;IACpH,uDAAuD;IACvD,MAAM,QAAQ,GAAG,MAAM,eAAK,CAAC,IAAI,CAC/B,UAAU,CAAC,WAAW,EACtB;QACE,MAAM,EAAE,oBAAoB;QAC5B,OAAO,EAAE,KAAK;QACd,MAAM,EAAE;YACN,YAAY;YACZ;gBACE,QAAQ,EAAE,aAAa;gBACvB,UAAU;gBACV,GAAG,qBAAqB;aACzB;SACF;QACD,EAAE,EAAE,IAAA,SAAM,GAAE;KACb,EACD;QACE,OAAO,EAAE;YACP,MAAM,EAAE,kBAAkB;YAC1B,cAAc,EAAE,kBAAkB;YAClC,iBAAiB,EAAE,eAAe;YAClC,eAAe,EAAE,UAAU;SAC5B;KACF,CACF,CAAC;IAEF,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC;IAChC,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;QACzB,MAAM,IAAI,4BAAkB,CAAC,SAAS,CAAC,KAAK,EAAE,4CAA4C,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IAC9G,CAAC;IAED,MAAM,GAAG,GAAG,SAAsB,CAAC;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/C,OAAO,EAAE,MAAM,sBAAsB,CAAC,OAAO,CAAC,OAAO,CAAC;QACtD,MAAM,EAAE,IAAI,mBAAS,CAAC,OAAO,CAAC,MAAM,CAAC;KACtC,CAAC,CAAC,CAAC;IACJ,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,CAA+B,CAAC;AACzC,CAAC;AAED,KAAK,UAAU,sBAAsB,CAAC,WAAkC;IACtE,MAAM,IAAI,GAAG,IAAA,sBAAU,EAAC,eAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;IACpE,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,QAAQ,EAAE,WAAW,CAAC,QAAQ;QAC9B,UAAU,EAAE,WAAW,CAAC,UAAU;QAClC,SAAS,EAAE,WAAW,CAAC,SAAS;QAChC,IAAI,EAAE,eAAM,CAAC,IAAI,CAAC,IAAI,CAAC;KACxB,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAClC,kBAAyE;IAEzE,IAAI,UAAkC,CAAC;IACvC,IAAI,MAA+C,CAAC;IACpD,IAAI,OAAO,kBAAkB,KAAK,QAAQ,EAAE,CAAC;QAC3C,UAAU,GAAG,kBAAkB,CAAC;IAClC,CAAC;SAAM,IAAI,kBAAkB,EAAE,CAAC;QAC9B,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,GAAG,eAAe,EAAE,GAAG,kBAAkB,CAAC;QACnF,UAAU,GAAG,mBAAmB,CAAC;QACjC,MAAM,GAAG,eAAe,CAAC;IAC3B,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kamino-finance/klend-sdk",
3
- "version": "5.1.0",
3
+ "version": "5.1.2",
4
4
  "description": "Typescript SDK for interacting with the Kamino Lending (klend) protocol",
5
5
  "repository": {
6
6
  "type": "git",
@@ -65,7 +65,8 @@
65
65
  "buffer": "^6.0.3",
66
66
  "commander": "^9.3.0",
67
67
  "decimal.js": "^10.4.3",
68
- "exponential-backoff": "^3.1.1"
68
+ "exponential-backoff": "^3.1.1",
69
+ "uuid": "^10.0.0"
69
70
  },
70
71
  "devDependencies": {
71
72
  "@orca-so/sdk": "^1.2.25",
@@ -14,7 +14,10 @@ import {
14
14
  KaminoVaultConfig,
15
15
  kaminoVaultId,
16
16
  ReserveAllocationConfig,
17
+ ReserveOverview,
17
18
  VaultHolder,
19
+ VaultHoldings,
20
+ VaultHoldingsWithUSDValue,
18
21
  } from './vault';
19
22
  import {
20
23
  AddAssetToMarketParams,
@@ -26,6 +29,7 @@ import {
26
29
  initLendingMarket,
27
30
  InitLendingMarketAccounts,
28
31
  InitLendingMarketArgs,
32
+ KaminoReserve,
29
33
  LendingMarket,
30
34
  lendingMarketAuthPda,
31
35
  MarketWithAddress,
@@ -318,7 +322,11 @@ export class KaminoManager {
318
322
  return this._vaultClient.depositIxs(user, vault, tokenAmount);
319
323
  }
320
324
 
321
- async updateVaultConfigIx(vault: KaminoVault, mode: VaultConfigFieldKind, value: string): Promise<TransactionInstruction> {
325
+ async updateVaultConfigIx(
326
+ vault: KaminoVault,
327
+ mode: VaultConfigFieldKind,
328
+ value: string
329
+ ): Promise<TransactionInstruction> {
322
330
  return this._vaultClient.updateVaultConfigIx(vault, mode, value);
323
331
  }
324
332
 
@@ -378,6 +386,18 @@ export class KaminoManager {
378
386
  return this._vaultClient.getTokensPerShareSingleVault(vault, slot);
379
387
  }
380
388
 
389
+ /**
390
+ * This method calculates the price of one vault share(kToken)
391
+ * @param vault - vault to calculate sharePrice for
392
+ * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
393
+ * @param tokenPrice - the price of the vault token (e.g. SOL) in USD
394
+ * @returns - share value in USD
395
+ */
396
+ async getSharePriceInUSD(vault: KaminoVault, slot: number, tokenPrice: Decimal): Promise<Decimal> {
397
+ const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
398
+ return tokensPerShare.mul(tokenPrice);
399
+ }
400
+
381
401
  /**
382
402
  * This method returns the user shares balance for a given vault
383
403
  * @param user - user to calculate the shares balance for
@@ -507,6 +527,95 @@ export class KaminoManager {
507
527
  return result;
508
528
  };
509
529
 
530
+ /**
531
+ * This will return an VaultHoldings object which contains the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve
532
+ * @param vault - the kamino vault to get available liquidity to withdraw for
533
+ * @param slot - current slot
534
+ * @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
535
+ * @returns an VaultHoldings object
536
+ */
537
+ async getVaultHoldings(
538
+ vault: VaultState,
539
+ slot: number,
540
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
541
+ ): Promise<VaultHoldings> {
542
+ return this._vaultClient.getVaultHoldings(vault, slot, vaultReserves);
543
+ }
544
+
545
+ /**
546
+ * This will return an VaultHoldingsWithUSDValue object which contains an holdings field representing the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve and additional fields for the total USD value of the available and invested amounts
547
+ * @param vault - the kamino vault to get available liquidity to withdraw for
548
+ * @param slot - current slot
549
+ * @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
550
+ * @param price - the price of the token in the vault (e.g. USDC)
551
+ * @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
552
+ */
553
+ async getVaultHoldingsWithPrice(
554
+ vault: VaultState,
555
+ slot: number,
556
+ price: Decimal,
557
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
558
+ ): Promise<VaultHoldingsWithUSDValue> {
559
+ return this._vaultClient.getVaultHoldingsWithPrice(vault, slot, price, vaultReserves);
560
+ }
561
+
562
+ /**
563
+ * This will return an overview of each reserve that is part of the vault allocation
564
+ * @param vault - the kamino vault to get available liquidity to withdraw for
565
+ * @param slot - current slot
566
+ * @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
567
+ * @returns a hashmap from vault reserve pubkey to ReserveOverview object
568
+ */
569
+ async getVaultReservesDetails(
570
+ vault: VaultState,
571
+ slot: number,
572
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
573
+ ): Promise<PubkeyHashMap<PublicKey, ReserveOverview>> {
574
+ return this._vaultClient.getVaultReservesDetails(vault, slot, vaultReserves);
575
+ }
576
+
577
+ /**
578
+ * This will return the APY of the vault under the assumption that all the available tokens in the vault are all the time invested in the reserves
579
+ * @param vault - the kamino vault to get APY for
580
+ * @param slot - current slot
581
+ * @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
582
+ * @returns APY for the vault
583
+ */
584
+ async getVaultTheoreticalAPY(
585
+ vault: VaultState,
586
+ slot: number,
587
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
588
+ ): Promise<Decimal> {
589
+ return this._vaultClient.getVaultTheoreticalAPY(vault, slot, vaultReserves);
590
+ }
591
+
592
+ /**
593
+ * This will load the onchain state for all the reserves that the vault has allocations for
594
+ * @param vaultState - the vault state to load reserves for
595
+ * @returns a hashmap from each reserve pubkey to the reserve state
596
+ */
597
+ async loadVaultReserves(vaultState: VaultState): Promise<PubkeyHashMap<PublicKey, KaminoReserve>> {
598
+ return this._vaultClient.loadVaultReserves(vaultState);
599
+ }
600
+
601
+ /**
602
+ * This will get the list of all reserve pubkeys that the vault has allocations for
603
+ * @param vaultState - the vault state to load reserves for
604
+ * @returns a hashmap from each reserve pubkey to the reserve state
605
+ */
606
+ getAllVaultReserves(vault: VaultState): PublicKey[] {
607
+ return this._vaultClient.getAllVaultReserves(vault);
608
+ }
609
+
610
+ /**
611
+ * This will load the onchain state for all the reserves that the vault has allocations for
612
+ * @param vaultState - the vault state to load reserves for
613
+ * @returns a hashmap from each reserve pubkey to the reserve state
614
+ */
615
+ getVaultReserves(vault: VaultState): PublicKey[] {
616
+ return this._vaultClient.getVaultReserves(vault);
617
+ }
618
+
510
619
  /**
511
620
  * This will trigger invest by balancing, based on weights, the reserve allocations of the vault. It can either withdraw or deposit into reserves to balance them. This is a function that should be cranked
512
621
  * @param kaminoVault - vault to invest from
@@ -61,6 +61,7 @@ import bs58 from 'bs58';
61
61
  import { getProgramAccounts } from '../utils/rpc';
62
62
 
63
63
  export const kaminoVaultId = new PublicKey('kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr');
64
+ export const kaminoVaultStagingId = new PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuYMFMTsE77FiRsL2');
64
65
 
65
66
  const TOKEN_VAULT_SEED = 'token_vault';
66
67
  const CTOKEN_VAULT_SEED = 'ctoken_vault';
@@ -389,9 +390,15 @@ export class KaminoVaultClient {
389
390
  * @param user - user to deposit
390
391
  * @param vault - vault to deposit into
391
392
  * @param tokenAmount - token amount to be deposited, in decimals (will be converted in lamports)
393
+ * @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
392
394
  * @returns - an array of instructions to be used to be executed
393
395
  */
394
- async depositIxs(user: PublicKey, vault: KaminoVault, tokenAmount: Decimal): Promise<TransactionInstruction[]> {
396
+ async depositIxs(
397
+ user: PublicKey,
398
+ vault: KaminoVault,
399
+ tokenAmount: Decimal,
400
+ vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
401
+ ): Promise<TransactionInstruction[]> {
395
402
  const vaultState = await vault.getState(this._connection);
396
403
 
397
404
  const userTokenAta = getAssociatedTokenAddress(vaultState.tokenMint, user);
@@ -450,7 +457,7 @@ export class KaminoVaultClient {
450
457
 
451
458
  const vaultReserves = this.getVaultReserves(vaultState);
452
459
 
453
- const vaultReservesState = await this.loadVaultReserves(vaultState);
460
+ const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
454
461
 
455
462
  let vaultReservesAccountMetas: AccountMeta[] = [];
456
463
  let vaultReservesLendingMarkets: AccountMeta[] = [];
@@ -825,16 +832,21 @@ export class KaminoVaultClient {
825
832
  * 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
826
833
  * @param vault - vault to calculate tokensPerShare for
827
834
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
835
+ * @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
828
836
  * @returns - token per share value
829
837
  */
830
- async getTokensPerShareSingleVault(vault: KaminoVault, slot: number): Promise<Decimal> {
838
+ async getTokensPerShareSingleVault(
839
+ vault: KaminoVault,
840
+ slot: number,
841
+ vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
842
+ ): Promise<Decimal> {
831
843
  const vaultState = await vault.getState(this._connection);
832
- const reserves = await this.loadVaultReserves(vaultState);
844
+ const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
833
845
 
834
846
  const totalVaultLiquidityAmount = new Decimal(vaultState.tokenAvailable.toString());
835
847
  vaultState.vaultAllocationStrategy.forEach((allocationStrategy) => {
836
848
  if (!allocationStrategy.reserve.equals(PublicKey.default)) {
837
- const reserve = reserves.get(allocationStrategy.reserve);
849
+ const reserve = vaultReservesState.get(allocationStrategy.reserve);
838
850
  if (reserve === undefined) {
839
851
  throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
840
852
  }
@@ -983,13 +995,32 @@ export class KaminoVaultClient {
983
995
  return reserveAllocationAvailableLiquidityToWithdraw;
984
996
  }
985
997
 
986
- private getVaultReserves(vault: VaultState): PublicKey[] {
998
+ /**
999
+ * This will get the list of all reserve pubkeys that the vault has allocations for
1000
+ * @param vaultState - the vault state to load reserves for
1001
+ * @returns a hashmap from each reserve pubkey to the reserve state
1002
+ */
1003
+ getAllVaultReserves(vault: VaultState): PublicKey[] {
1004
+ return vault.vaultAllocationStrategy.map((vaultAllocation) => vaultAllocation.reserve);
1005
+ }
1006
+
1007
+ /**
1008
+ * This will get the list of all reserve pubkeys that the vault has allocations for ex
1009
+ * @param vaultState - the vault state to load reserves for
1010
+ * @returns a hashmap from each reserve pubkey to the reserve state
1011
+ */
1012
+ getVaultReserves(vault: VaultState): PublicKey[] {
987
1013
  return vault.vaultAllocationStrategy
988
1014
  .filter((vaultAllocation) => !vaultAllocation.reserve.equals(PublicKey.default))
989
1015
  .map((vaultAllocation) => vaultAllocation.reserve);
990
1016
  }
991
1017
 
992
- private async loadVaultReserves(vaultState: VaultState): Promise<PubkeyHashMap<PublicKey, KaminoReserve>> {
1018
+ /**
1019
+ * This will load the onchain state for all the reserves that the vault has allocations for
1020
+ * @param vaultState - the vault state to load reserves for
1021
+ * @returns a hashmap from each reserve pubkey to the reserve state
1022
+ */
1023
+ async loadVaultReserves(vaultState: VaultState): Promise<PubkeyHashMap<PublicKey, KaminoReserve>> {
993
1024
  const vaultReservesAddresses = this.getVaultReserves(vaultState);
994
1025
  const reserveAccounts = await this._connection.getMultipleAccountsInfo(vaultReservesAddresses, 'processed');
995
1026
 
@@ -1026,6 +1057,152 @@ export class KaminoVaultClient {
1026
1057
 
1027
1058
  return kaminoReserves;
1028
1059
  }
1060
+
1061
+ /**
1062
+ * This will return an VaultHoldings object which contains the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve
1063
+ * @param vault - the kamino vault to get available liquidity to withdraw for
1064
+ * @param slot - current slot
1065
+ * @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
1066
+ * @returns an VaultHoldings object
1067
+ */
1068
+ async getVaultHoldings(
1069
+ vault: VaultState,
1070
+ slot: number,
1071
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
1072
+ ): Promise<VaultHoldings> {
1073
+ const vaultHoldings: VaultHoldings = {
1074
+ available: new Decimal(vault.tokenAvailable.toString()),
1075
+ invested: new Decimal(0),
1076
+ investedInReserves: new PubkeyHashMap<PublicKey, Decimal>(),
1077
+ };
1078
+
1079
+ const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1080
+
1081
+ vault.vaultAllocationStrategy.forEach((allocationStrategy) => {
1082
+ if (allocationStrategy.reserve.equals(PublicKey.default)) {
1083
+ return;
1084
+ }
1085
+
1086
+ const reserve = vaultReservesState.get(allocationStrategy.reserve);
1087
+ if (reserve === undefined) {
1088
+ throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
1089
+ }
1090
+
1091
+ const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(slot, 0);
1092
+ const reserveAllocationLiquidityAmount = new Decimal(allocationStrategy.cTokenAllocation.toString()).mul(
1093
+ reserveCollExchangeRate
1094
+ );
1095
+
1096
+ vaultHoldings.invested = vaultHoldings.invested.add(reserveAllocationLiquidityAmount);
1097
+ vaultHoldings.investedInReserves.set(allocationStrategy.reserve, reserveAllocationLiquidityAmount);
1098
+ });
1099
+
1100
+ return vaultHoldings;
1101
+ }
1102
+
1103
+ /**
1104
+ * This will return an VaultHoldingsWithUSDValue object which contains an holdings field representing the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve and additional fields for the total USD value of the available and invested amounts
1105
+ * @param vault - the kamino vault to get available liquidity to withdraw for
1106
+ * @param slot - current slot
1107
+ * @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
1108
+ * @param price - the price of the token in the vault (e.g. USDC)
1109
+ * @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
1110
+ */
1111
+ async getVaultHoldingsWithPrice(
1112
+ vault: VaultState,
1113
+ slot: number,
1114
+ price: Decimal,
1115
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
1116
+ ): Promise<VaultHoldingsWithUSDValue> {
1117
+ const holdings = await this.getVaultHoldings(vault, slot, vaultReserves);
1118
+
1119
+ const investedInReservesUSD = new PubkeyHashMap<PublicKey, Decimal>();
1120
+ holdings.investedInReserves.forEach((amount, reserve) => {
1121
+ investedInReservesUSD.set(reserve, amount.mul(price));
1122
+ });
1123
+ const holdingsWithUSDValue: VaultHoldingsWithUSDValue = {
1124
+ holdings: holdings,
1125
+ availableUSD: holdings.available.mul(price),
1126
+ investedUSD: holdings.invested.mul(price),
1127
+ investedInReservesUSD: investedInReservesUSD,
1128
+ };
1129
+
1130
+ return holdingsWithUSDValue;
1131
+ }
1132
+
1133
+ /**
1134
+ * This will return an overview of each reserve that is part of the vault allocation
1135
+ * @param vault - the kamino vault to get available liquidity to withdraw for
1136
+ * @param slot - current slot
1137
+ * @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
1138
+ * @returns a hashmap from vault reserve pubkey to ReserveOverview object
1139
+ */
1140
+ async getVaultReservesDetails(
1141
+ vault: VaultState,
1142
+ slot: number,
1143
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
1144
+ ): Promise<PubkeyHashMap<PublicKey, ReserveOverview>> {
1145
+ const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1146
+ const reservesDetails = new PubkeyHashMap<PublicKey, ReserveOverview>();
1147
+
1148
+ vault.vaultAllocationStrategy.forEach((allocationStrategy) => {
1149
+ if (allocationStrategy.reserve.equals(PublicKey.default)) {
1150
+ return;
1151
+ }
1152
+
1153
+ const reserve = vaultReservesState.get(allocationStrategy.reserve);
1154
+ if (reserve === undefined) {
1155
+ throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
1156
+ }
1157
+
1158
+ reserve.getBorrowedAmount();
1159
+ const reserveOverview: ReserveOverview = {
1160
+ supplyAPY: new Decimal(reserve.totalSupplyAPY(slot)),
1161
+ uUtilizationRatio: new Decimal(reserve.getEstimatedUtilizationRatio(slot, 0)),
1162
+ liquidationThresholdPct: new Decimal(reserve.state.config.liquidationThresholdPct),
1163
+ borrowedAmount: reserve.getBorrowedAmount(),
1164
+ };
1165
+ reservesDetails.set(allocationStrategy.reserve, reserveOverview);
1166
+ });
1167
+
1168
+ return reservesDetails;
1169
+ }
1170
+
1171
+ /**
1172
+ * This will return the APY of the vault under the assumption that all the available tokens in the vault are all the time invested in the reserves
1173
+ * @param vault - the kamino vault to get APY for
1174
+ * @param slot - current slot
1175
+ * @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
1176
+ * @returns APY for the vault
1177
+ */
1178
+ async getVaultTheoreticalAPY(
1179
+ vault: VaultState,
1180
+ slot: number,
1181
+ vaultReserves?: PubkeyHashMap<PublicKey, KaminoReserve>
1182
+ ): Promise<Decimal> {
1183
+ const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1184
+
1185
+ let totalWeights = new Decimal(0);
1186
+ let totalAPY = new Decimal(0);
1187
+ vault.vaultAllocationStrategy.forEach((allocationStrategy) => {
1188
+ if (allocationStrategy.reserve.equals(PublicKey.default)) {
1189
+ return;
1190
+ }
1191
+
1192
+ const reserve = vaultReservesState.get(allocationStrategy.reserve);
1193
+ if (reserve === undefined) {
1194
+ throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
1195
+ }
1196
+
1197
+ const reserveAPY = new Decimal(reserve.totalSupplyAPY(slot));
1198
+ const weight = new Decimal(allocationStrategy.targetAllocationWeight.toString());
1199
+ const weightedAPY = reserveAPY.mul(weight);
1200
+ totalAPY = totalAPY.add(weightedAPY);
1201
+ totalWeights = totalWeights.add(weight);
1202
+ });
1203
+
1204
+ return totalAPY.div(totalWeights);
1205
+ }
1029
1206
  } // KaminoVaultClient
1030
1207
 
1031
1208
  export class KaminoVault {
@@ -1134,3 +1311,23 @@ export type VaultHolder = {
1134
1311
  holderPubkey: PublicKey;
1135
1312
  amount: Decimal;
1136
1313
  };
1314
+
1315
+ export type VaultHoldings = {
1316
+ available: Decimal;
1317
+ invested: Decimal;
1318
+ investedInReserves: PubkeyHashMap<PublicKey, Decimal>;
1319
+ };
1320
+
1321
+ export type VaultHoldingsWithUSDValue = {
1322
+ holdings: VaultHoldings;
1323
+ availableUSD: Decimal;
1324
+ investedUSD: Decimal;
1325
+ investedInReservesUSD: PubkeyHashMap<PublicKey, Decimal>;
1326
+ };
1327
+
1328
+ export type ReserveOverview = {
1329
+ supplyAPY: Decimal;
1330
+ uUtilizationRatio: Decimal;
1331
+ liquidationThresholdPct: Decimal;
1332
+ borrowedAmount: Decimal;
1333
+ };
@@ -496,6 +496,14 @@ async function main() {
496
496
  console.log('oracleConfigs', JSON.parse(JSON.stringify(oracleConfigs)));
497
497
  });
498
498
 
499
+ commands.command('get-all-vaults').action(async () => {
500
+ const env = initializeClient(false, false);
501
+ const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
502
+
503
+ const allVaults = await kaminoManager.getAllVaults();
504
+ console.log('all vaults', allVaults);
505
+ });
506
+
499
507
  commands
500
508
  .command('download-lending-market-config')
501
509
  .requiredOption('--lending-market <string>', 'Lending Market Address')