@kamino-finance/klend-sdk 5.10.12 → 5.10.13

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 (47) hide show
  1. package/dist/classes/manager.d.ts +14 -12
  2. package/dist/classes/manager.d.ts.map +1 -1
  3. package/dist/classes/manager.js +20 -18
  4. package/dist/classes/manager.js.map +1 -1
  5. package/dist/classes/obligation.d.ts +1 -0
  6. package/dist/classes/obligation.d.ts.map +1 -1
  7. package/dist/classes/obligation.js +22 -0
  8. package/dist/classes/obligation.js.map +1 -1
  9. package/dist/classes/reserve.js +1 -1
  10. package/dist/classes/reserve.js.map +1 -1
  11. package/dist/classes/types_utils.d.ts +3 -1
  12. package/dist/classes/types_utils.d.ts.map +1 -1
  13. package/dist/classes/types_utils.js +26 -0
  14. package/dist/classes/types_utils.js.map +1 -1
  15. package/dist/classes/utils.d.ts +8 -0
  16. package/dist/classes/utils.d.ts.map +1 -1
  17. package/dist/classes/utils.js +48 -0
  18. package/dist/classes/utils.js.map +1 -1
  19. package/dist/classes/vault.d.ts +6 -8
  20. package/dist/classes/vault.d.ts.map +1 -1
  21. package/dist/classes/vault.js +19 -22
  22. package/dist/classes/vault.js.map +1 -1
  23. package/dist/client_kamino_manager.js +2 -2
  24. package/dist/client_kamino_manager.js.map +1 -1
  25. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  26. package/dist/pyth/accounts/index.d.ts +1 -1
  27. package/dist/pyth/accounts/index.d.ts.map +1 -1
  28. package/dist/utils/ObligationType.d.ts +10 -4
  29. package/dist/utils/ObligationType.d.ts.map +1 -1
  30. package/dist/utils/ObligationType.js +36 -11
  31. package/dist/utils/ObligationType.js.map +1 -1
  32. package/dist/utils/constants.d.ts +1 -0
  33. package/dist/utils/constants.d.ts.map +1 -1
  34. package/dist/utils/constants.js +2 -1
  35. package/dist/utils/constants.js.map +1 -1
  36. package/package.json +1 -1
  37. package/src/classes/manager.ts +25 -19
  38. package/src/classes/obligation.ts +42 -2
  39. package/src/classes/reserve.ts +1 -1
  40. package/src/classes/types_utils.ts +28 -1
  41. package/src/classes/utils.ts +50 -1
  42. package/src/classes/vault.ts +25 -27
  43. package/src/client_kamino_manager.ts +2 -2
  44. package/src/lending_operations/swap_collateral_operations.ts +1 -1
  45. package/src/pyth/accounts/index.ts +1 -1
  46. package/src/utils/ObligationType.ts +49 -12
  47. package/src/utils/constants.ts +2 -0
@@ -339,9 +339,10 @@ export class KaminoManager {
339
339
  user: PublicKey,
340
340
  vault: KaminoVault,
341
341
  tokenAmount: Decimal,
342
- vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>
342
+ vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
343
+ farmState?: FarmState
343
344
  ): Promise<DepositIxs> {
344
- return this._vaultClient.depositIxs(user, vault, tokenAmount, vaultReservesMap);
345
+ return this._vaultClient.depositIxs(user, vault, tokenAmount, vaultReservesMap, farmState);
345
346
  }
346
347
 
347
348
  /**
@@ -366,19 +367,21 @@ export class KaminoManager {
366
367
  * @param vault the vault to update
367
368
  * @param mode the field to update (based on VaultConfigFieldKind enum)
368
369
  * @param value the value to update the field with
370
+ * @param [signer] the signer of the transaction. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
369
371
  * @returns a struct that contains the instruction to update the field and an optional list of instructions to update the lookup table
370
372
  */
371
373
  async updateVaultConfigIxs(
372
374
  vault: KaminoVault,
373
375
  mode: VaultConfigFieldKind | string,
374
- value: string
376
+ value: string,
377
+ signer?: PublicKey
375
378
  ): Promise<UpdateVaultConfigIxs> {
376
379
  if (typeof mode === 'string') {
377
380
  const field = VaultConfigField.fromDecoded({ [mode]: '' });
378
- return this._vaultClient.updateVaultConfigIxs(vault, field, value);
381
+ return this._vaultClient.updateVaultConfigIxs(vault, field, value, signer);
379
382
  }
380
383
 
381
- return this._vaultClient.updateVaultConfigIxs(vault, mode, value);
384
+ return this._vaultClient.updateVaultConfigIxs(vault, mode, value, signer);
382
385
  }
383
386
 
384
387
  /** Sets the farm where the shares can be staked. This is store in vault state and a vault can only have one farm, so the new farm will ovveride the old farm
@@ -420,15 +423,18 @@ export class KaminoManager {
420
423
  * @param shareAmount - share amount to withdraw (in tokens, not lamports), in order to withdraw everything, any value > user share amount
421
424
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
422
425
  * @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
426
+ * @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
423
427
  * @returns an array of instructions to create missing ATAs if needed and the withdraw instructions
424
428
  */
425
429
  async withdrawFromVaultIxs(
426
430
  user: PublicKey,
427
431
  vault: KaminoVault,
428
432
  shareAmount: Decimal,
429
- slot: number
433
+ slot: number,
434
+ vaultReservesMap?: PubkeyHashMap<PublicKey, KaminoReserve>,
435
+ farmState?: FarmState
430
436
  ): Promise<WithdrawIxs> {
431
- return this._vaultClient.withdrawIxs(user, vault, shareAmount, slot);
437
+ return this._vaultClient.withdrawIxs(user, vault, shareAmount, slot, vaultReservesMap, farmState);
432
438
  }
433
439
 
434
440
  /**
@@ -447,7 +453,6 @@ export class KaminoManager {
447
453
  * @param payer - payer wallet pubkey
448
454
  * @param lookupTable - lookup table to insert the keys into
449
455
  * @param keys - keys to insert into the lookup table
450
- * @param [accountsInLUT] - the existent accounts in the lookup table. Optional. If provided, the function will not fetch the accounts in the lookup table
451
456
  * @returns - an array of instructions to insert the missing keys into the lookup table
452
457
  */
453
458
  async insertIntoLUTIxs(payer: PublicKey, lut: PublicKey, keys: PublicKey[]): Promise<TransactionInstruction[]> {
@@ -697,6 +702,16 @@ export class KaminoManager {
697
702
  return this._vaultClient.getVaultOverview(vault, price, slot, vaultReserves, kaminoMarkets);
698
703
  }
699
704
 
705
+ /**
706
+ * Prints a vault in a human readable form
707
+ * @param vaultPubkey - the address of the vault
708
+ * @param [vaultState] - optional parameter to pass the vault state directly; this will save a network call
709
+ * @returns - void; prints the vault to the console
710
+ */
711
+ async printVault(vaultPubkey: PublicKey, vaultState?: VaultState) {
712
+ return this._vaultClient.printVault(vaultPubkey, vaultState);
713
+ }
714
+
700
715
  /**
701
716
  * This will return an aggregation of the current state of the vault with all the invested amounts and the utilization ratio of the vault
702
717
  * @param vault - the kamino vault to get available liquidity to withdraw for
@@ -797,15 +812,6 @@ export class KaminoManager {
797
812
  return this._vaultClient.loadVaultReserves(vaultState);
798
813
  }
799
814
 
800
- /**
801
- * This will get the list of all reserve pubkeys that the vault has allocations for
802
- * @param vaultState - the vault state to load reserves for
803
- * @returns a hashmap from each reserve pubkey to the reserve state
804
- */
805
- getAllVaultReserves(vault: VaultState): PublicKey[] {
806
- return this._vaultClient.getAllVaultReserves(vault);
807
- }
808
-
809
815
  /**
810
816
  * This will load the onchain state for all the reserves that the vault has allocations for
811
817
  * @param vaultState - the vault state to load reserves for
@@ -830,7 +836,7 @@ export class KaminoManager {
830
836
  * @param kaminoVault - vault to invest from
831
837
  * @returns - an array of invest instructions for each invest action required for the vault reserves
832
838
  */
833
- async investAllReserves(payer: PublicKey, kaminoVault: KaminoVault): Promise<TransactionInstruction[]> {
839
+ async investAllReservesIxs(payer: PublicKey, kaminoVault: KaminoVault): Promise<TransactionInstruction[]> {
834
840
  return this._vaultClient.investAllReservesIxs(payer, kaminoVault);
835
841
  }
836
842
 
@@ -842,7 +848,7 @@ export class KaminoManager {
842
848
  * @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
843
849
  * @returns - an array of invest instructions for each invest action required for the vault reserves
844
850
  */
845
- async investSingleReserve(
851
+ async investSingleReserveIxs(
846
852
  payer: PublicKey,
847
853
  kaminoVault: KaminoVault,
848
854
  reserveWithAddress: ReserveWithAddress,
@@ -13,7 +13,14 @@ import {
13
13
  ObligationLiquidityFields,
14
14
  } from '../idl_codegen/types';
15
15
  import { positiveOrZero, valueOrZero } from './utils';
16
- import { isNotNullPubkey, PubkeyHashMap, U64_MAX } from '../utils';
16
+ import {
17
+ getObligationPdaWithArgs,
18
+ getObligationType,
19
+ isNotNullPubkey,
20
+ PubkeyHashMap,
21
+ TOTAL_NUMBER_OF_IDS_TO_CHECK,
22
+ U64_MAX,
23
+ } from '../utils';
17
24
  import { ActionType } from './action';
18
25
 
19
26
  export type Position = {
@@ -112,6 +119,39 @@ export class KaminoObligation {
112
119
  this.obligationTag = obligation.tag.toNumber();
113
120
  }
114
121
 
122
+ getObligationId(
123
+ market: KaminoMarket,
124
+ mintAddress1: PublicKey = PublicKey.default,
125
+ mintAddress2: PublicKey = PublicKey.default
126
+ ) {
127
+ if (!this.state.lendingMarket.equals(new PublicKey(market.address))) {
128
+ throw new Error('Obligation does not belong to this market');
129
+ }
130
+ let obligationId: number | undefined;
131
+ const type = getObligationType(market, this.obligationTag, mintAddress1, mintAddress2);
132
+ const baseArgs = type.toArgs();
133
+
134
+ for (let i = 0; i < TOTAL_NUMBER_OF_IDS_TO_CHECK; i++) {
135
+ const pda = getObligationPdaWithArgs(
136
+ new PublicKey(market.address),
137
+ this.state.owner,
138
+ {
139
+ ...baseArgs,
140
+ id: i,
141
+ },
142
+ market.programId
143
+ );
144
+ if (pda.equals(this.obligationAddress)) {
145
+ obligationId = i;
146
+ break;
147
+ }
148
+ }
149
+ if (obligationId === undefined) {
150
+ throw new Error(`obligation id not found for obligation ${this.obligationAddress.toString()}`);
151
+ }
152
+ return obligationId;
153
+ }
154
+
115
155
  static async load(kaminoMarket: KaminoMarket, obligationAddress: PublicKey): Promise<KaminoObligation | null> {
116
156
  const res = await kaminoMarket.getConnection().getAccountInfoAndContext(obligationAddress);
117
157
  if (res.value === null) {
@@ -484,7 +524,7 @@ export class KaminoObligation {
484
524
  const collateralReservePk = mintCollateral ? market.getReserveByMint(mintCollateral)!.address : undefined;
485
525
  const debtReservePk = mintDebt ? market.getReserveByMint(mintDebt)!.address : undefined;
486
526
 
487
- const additionalReserves = [];
527
+ const additionalReserves: PublicKey[] = [];
488
528
  if (collateralReservePk !== undefined) {
489
529
  additionalReserves.push(collateralReservePk);
490
530
  }
@@ -1215,7 +1215,7 @@ export function updateEntireReserveConfigIx(
1215
1215
  const args: UpdateReserveConfigArgs = {
1216
1216
  mode: new anchor.BN(25),
1217
1217
  value: value,
1218
- skipValidation: true,
1218
+ skipValidation: false,
1219
1219
  };
1220
1220
 
1221
1221
  const accounts: UpdateReserveConfigAccounts = {
@@ -1,5 +1,5 @@
1
1
  import { pubkeyHashMapToJson } from './utils';
2
- import { VaultHoldings } from './vault';
2
+ import { VaultHoldings, VaultHoldingsWithUSDValue, VaultOverview } from './vault';
3
3
 
4
4
  export function holdingsToJson(holdings: VaultHoldings) {
5
5
  return {
@@ -17,3 +17,30 @@ export function printHoldings(holdings: VaultHoldings) {
17
17
  console.log(' Total:', holdings.total.toString());
18
18
  console.log(' Invested in reserves:', pubkeyHashMapToJson(holdings.investedInReserves));
19
19
  }
20
+
21
+ export function printHoldingsWithUSDValue(holdings: VaultHoldingsWithUSDValue) {
22
+ console.log('Holdings with USD value:');
23
+ console.log(' Available:', holdings.availableUSD.toString());
24
+ console.log(' Invested:', holdings.investedUSD.toString());
25
+ console.log(' Total:', holdings.totalUSD.toString());
26
+ console.log(' Invested in reserves:', pubkeyHashMapToJson(holdings.investedInReservesUSD));
27
+ }
28
+
29
+ export function printVaultOverview(vaultOverview: VaultOverview) {
30
+ console.log('Vault overview:');
31
+ printHoldingsWithUSDValue(vaultOverview.holdingsUSD);
32
+ console.log(' Theoretical Supply APY:', vaultOverview.theoreticalSupplyAPY.toString());
33
+ console.log(' Utilization ratio:', vaultOverview.utilizationRatio.toString());
34
+ console.log(' Total supplied:', vaultOverview.totalSupplied.toString());
35
+ console.log(' Borrowed amount:', vaultOverview.totalBorrowed.toString());
36
+
37
+ vaultOverview.reservesOverview.forEach((reserveOverview, pubkey) => {
38
+ console.log(' Reserve:', pubkey.toString());
39
+ console.log(' Total borrowed from reserve:', reserveOverview.totalBorrowedAmount.toString());
40
+ console.log(' Supplied:', reserveOverview.suppliedAmount.toString());
41
+ console.log(' Utilization ratio:', reserveOverview.utilizationRatio.toString());
42
+ console.log(' Liquidation Threshold Pct:', reserveOverview.liquidationThresholdPct.toString());
43
+ console.log(' Supply APY:', reserveOverview.supplyAPY.toString());
44
+ console.log(' Lending market:', reserveOverview.market.toString());
45
+ });
46
+ }
@@ -1,8 +1,9 @@
1
1
  import { PubkeyHashMap, SLOTS_PER_SECOND, SLOTS_PER_YEAR } from '../utils';
2
2
  import Decimal from 'decimal.js';
3
3
  import { AccountInfo, PublicKey } from '@solana/web3.js';
4
- import { SOL_MINTS } from '../lib';
4
+ import { MarketOverview, ReserveOverview, SOL_MINTS } from '../lib';
5
5
  import { AccountLayout } from '@solana/spl-token';
6
+ import { ReserveAllocationOverview } from './types';
6
7
 
7
8
  type ObligationFarmScoreType = {
8
9
  obligationId: string;
@@ -271,3 +272,51 @@ export function pubkeyHashMapToJson(map: PubkeyHashMap<PublicKey, any>): { [key:
271
272
  export function printPubkeyHashMap<V>(map: PubkeyHashMap<PublicKey, V>) {
272
273
  console.log(pubkeyHashMapToJson(map));
273
274
  }
275
+
276
+ export function printReservesOverviewMap(map: PubkeyHashMap<PublicKey, ReserveOverview>) {
277
+ map.forEach((value, key) => {
278
+ console.log('Reserve:', key.toString());
279
+ printReserveOverview(value);
280
+ });
281
+ }
282
+
283
+ export function printReserveOverview(reserveOverview: ReserveOverview) {
284
+ console.log('Total borrowed from reserve:', reserveOverview.totalBorrowedAmount.toString());
285
+ console.log('Borrowed from the supplied amount:', reserveOverview.amountBorrowedFromSupplied.toString());
286
+ console.log('Supplied:', reserveOverview.suppliedAmount.toString());
287
+ console.log('Utilization ratio:', reserveOverview.utilizationRatio.toString());
288
+ console.log('Liquidation Threshold Pct:', reserveOverview.liquidationThresholdPct.toString());
289
+ console.log('Supply APY:', reserveOverview.supplyAPY.toString());
290
+ console.log('Lending market:', reserveOverview.market.toString());
291
+ }
292
+
293
+ export function printMarketsOverviewMap(map: PubkeyHashMap<PublicKey, MarketOverview>) {
294
+ map.forEach((value, key) => {
295
+ console.log('Reserve:', key.toString());
296
+ printMarketOverview(value);
297
+ });
298
+ }
299
+
300
+ export function printMarketOverview(marketOverview: MarketOverview) {
301
+ console.log('Market overview:');
302
+ console.log(' Address:', marketOverview.address.toString());
303
+ console.log(' Min LTV percentage:', marketOverview.minLTVPct.toString());
304
+ console.log(' Max LTV percentage:', marketOverview.maxLTVPct.toString());
305
+ marketOverview.reservesAsCollateral.forEach((reserve, _) => {
306
+ console.log(' Liquidation LTV percentage:', reserve.liquidationLTVPct.toString());
307
+ });
308
+ }
309
+
310
+ export function printReservesAllocationOverviewMap(map: PubkeyHashMap<PublicKey, ReserveAllocationOverview>) {
311
+ map.forEach((value, key) => {
312
+ console.log('Reserve:', key.toString());
313
+ printReserveAllocationOverview(value);
314
+ });
315
+ }
316
+
317
+ export function printReserveAllocationOverview(reserveAllocationOverview: ReserveAllocationOverview) {
318
+ console.log('Reserve allocation overview:');
319
+ console.log(' Target weight:', reserveAllocationOverview.targetWeight.toString());
320
+ console.log(' Token allocation cap:', reserveAllocationOverview.tokenAllocationCap.toString());
321
+ console.log(' Ctoken allocation:', reserveAllocationOverview.ctokenAllocation.toString());
322
+ }
@@ -338,7 +338,7 @@ export class KaminoVaultClient {
338
338
  * @param vault the vault to update
339
339
  * @param mode the field to update (based on VaultConfigFieldKind enum)
340
340
  * @param value the value to update the field with
341
- * @param [signer] the signer of the transaction. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to batch multiple ixs in the same tx
341
+ * @param [signer] the signer of the transaction. Optional. If not provided the admin of the vault will be used. It should be used when changing the admin of the vault if we want to build or batch multiple ixs in the same tx
342
342
  * @returns a struct that contains the instruction to update the field and an optional list of instructions to update the lookup table
343
343
  */
344
344
  async updateVaultConfigIxs(
@@ -404,7 +404,7 @@ export class KaminoVaultClient {
404
404
  updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesAccountMetas);
405
405
  updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesLendingMarkets);
406
406
 
407
- const updateLUTIxs = [];
407
+ const updateLUTIxs: TransactionInstruction[] = [];
408
408
 
409
409
  if (mode.kind === new VaultConfigField.PendingVaultAdmin().kind) {
410
410
  const newPubkey = new PublicKey(value);
@@ -529,7 +529,7 @@ export class KaminoVaultClient {
529
529
  (account) => !account.equals(vaultState.adminAuthority)
530
530
  );
531
531
 
532
- const LUTIxs = [];
532
+ const LUTIxs: TransactionInstruction[] = [];
533
533
  const [initNewLUTIx, newLUT] = initLookupTableIx(vaultState.pendingAdmin, await this.getConnection().getSlot());
534
534
 
535
535
  const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(
@@ -1005,7 +1005,7 @@ export class KaminoVaultClient {
1005
1005
  */
1006
1006
  async investAllReservesIxs(payer: PublicKey, vault: KaminoVault): Promise<TransactionInstruction[]> {
1007
1007
  const vaultState = await vault.getState(this.getConnection());
1008
- const allReserves = this.getAllVaultReserves(vaultState);
1008
+ const allReserves = this.getVaultReserves(vaultState);
1009
1009
  if (allReserves.length === 0) {
1010
1010
  throw new Error('No reserves found for the vault, please select at least one reserve for the vault');
1011
1011
  }
@@ -1488,7 +1488,7 @@ export class KaminoVaultClient {
1488
1488
  const holdings = await this.getVaultHoldings(vaultState);
1489
1489
  const initialVaultAllocations = this.getVaultAllocations(vaultState);
1490
1490
 
1491
- const allReserves = this.getAllVaultReserves(vaultState);
1491
+ const allReserves = this.getVaultReserves(vaultState);
1492
1492
 
1493
1493
  let totalAllocation = new Decimal(0);
1494
1494
  initialVaultAllocations.forEach((allocation) => {
@@ -1746,14 +1746,16 @@ export class KaminoVaultClient {
1746
1746
  * @returns vault amount supplied in reserve in decimal
1747
1747
  */
1748
1748
  getSuppliedInReserve(vaultState: VaultState, slot: number, reserve: KaminoReserve): Decimal {
1749
- const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(
1750
- slot,
1751
- new Fraction(reserve.state.liquidity.absoluteReferralRateSf)
1749
+ let referralFeeBps = 0;
1750
+ const denominator = reserve.state.config.protocolTakeRatePct / 100;
1751
+ if (denominator > 0) {
1752
+ referralFeeBps = new Fraction(reserve.state.liquidity.absoluteReferralRateSf)
1752
1753
  .toDecimal()
1753
- .div(reserve.state.config.protocolTakeRatePct / 100)
1754
+ .div(denominator)
1754
1755
  .floor()
1755
- .toNumber()
1756
- );
1756
+ .toNumber();
1757
+ }
1758
+ const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(slot, referralFeeBps);
1757
1759
 
1758
1760
  const reserveAllocation = vaultState.vaultAllocationStrategy.find((allocation) =>
1759
1761
  allocation.reserve.equals(reserve.address)
@@ -1868,19 +1870,6 @@ export class KaminoVaultClient {
1868
1870
  return reserveAllocationAvailableLiquidityToWithdraw;
1869
1871
  }
1870
1872
 
1871
- /**
1872
- * This will get the list of all reserve pubkeys that the vault has allocations for
1873
- * @param vault - the vault state to load reserves for
1874
- * @returns a hashmap from each reserve pubkey to the reserve state
1875
- */
1876
- getAllVaultReserves(vault: VaultState): PublicKey[] {
1877
- return vault.vaultAllocationStrategy
1878
- .map((vaultAllocation) => vaultAllocation.reserve)
1879
- .filter((reserve) => {
1880
- return !reserve.equals(PublicKey.default);
1881
- });
1882
- }
1883
-
1884
1873
  /**
1885
1874
  * This will get the list of all reserve pubkeys that the vault has allocations for ex
1886
1875
  * @param vault - the vault state to load reserves for
@@ -2212,6 +2201,9 @@ export class KaminoVaultClient {
2212
2201
  if (!totalInvested.isZero()) {
2213
2202
  utilizationRatio = totalBorrowed.div(totalInvested.add(totalAvailable));
2214
2203
  }
2204
+
2205
+ console.log('totalInvested', totalInvested.toString());
2206
+ console.log('totalBorrowed', totalBorrowed.toString());
2215
2207
  return {
2216
2208
  totalInvested: totalInvested,
2217
2209
  totalBorrowed: totalBorrowed,
@@ -2245,11 +2237,13 @@ export class KaminoVaultClient {
2245
2237
  }
2246
2238
 
2247
2239
  const suppliedInReserve = this.getSuppliedInReserve(vault, slot, reserve);
2240
+ const utilizationRatio = new Decimal(reserve.getEstimatedUtilizationRatio(slot, 0));
2248
2241
  const reserveOverview: ReserveOverview = {
2249
2242
  supplyAPY: new Decimal(reserve.totalSupplyAPY(slot)),
2250
- utilizationRatio: new Decimal(reserve.getEstimatedUtilizationRatio(slot, 0)),
2243
+ utilizationRatio: utilizationRatio,
2251
2244
  liquidationThresholdPct: new Decimal(reserve.state.config.liquidationThresholdPct),
2252
- borrowedAmount: reserve.getBorrowedAmount(),
2245
+ totalBorrowedAmount: reserve.getBorrowedAmount(),
2246
+ amountBorrowedFromSupplied: suppliedInReserve.mul(utilizationRatio),
2253
2247
  market: reserve.state.lendingMarket,
2254
2248
  suppliedAmount: suppliedInReserve,
2255
2249
  };
@@ -2508,6 +2502,9 @@ export type VaultHoldings = {
2508
2502
  total: Decimal;
2509
2503
  };
2510
2504
 
2505
+ /**
2506
+ * earnedInterest represents the interest earned from now until the slot provided in the future
2507
+ */
2511
2508
  export type SimulatedVaultHoldingsWithEarnedInterest = {
2512
2509
  holdings: VaultHoldings;
2513
2510
  earnedInterest: Decimal;
@@ -2525,7 +2522,8 @@ export type ReserveOverview = {
2525
2522
  supplyAPY: Decimal;
2526
2523
  utilizationRatio: Decimal;
2527
2524
  liquidationThresholdPct: Decimal;
2528
- borrowedAmount: Decimal;
2525
+ totalBorrowedAmount: Decimal;
2526
+ amountBorrowedFromSupplied: Decimal;
2529
2527
  suppliedAmount: Decimal;
2530
2528
  market: PublicKey;
2531
2529
  };
@@ -737,7 +737,7 @@ async function main() {
737
737
  const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
738
738
 
739
739
  const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
740
- const instructions = await kaminoManager.investAllReserves(env.payer.publicKey, kaminoVault);
740
+ const instructions = await kaminoManager.investAllReservesIxs(env.payer.publicKey, kaminoVault);
741
741
 
742
742
  for (let i = 0; i < instructions.length; i++) {
743
743
  const txInstructions: TransactionInstruction[] = [];
@@ -779,7 +779,7 @@ async function main() {
779
779
  state: reserveState,
780
780
  };
781
781
 
782
- const instructions = await kaminoManager.investSingleReserve(
782
+ const instructions = await kaminoManager.investSingleReserveIxs(
783
783
  env.payer.publicKey,
784
784
  kaminoVault,
785
785
  reserveWithAddress
@@ -319,7 +319,7 @@ function getAtaCreationIxns(context: SwapCollContext<any>) {
319
319
  }
320
320
 
321
321
  function getAtaCloseIxns(context: SwapCollContext<any>) {
322
- const ataCloseIxns = [];
322
+ const ataCloseIxns: TransactionInstruction[] = [];
323
323
  if (
324
324
  context.sourceCollReserve.getLiquidityMint().equals(WRAPPED_SOL_MINT) ||
325
325
  context.targetCollReserve.getLiquidityMint().equals(WRAPPED_SOL_MINT)
@@ -1,2 +1,2 @@
1
1
  export { PriceUpdateV2 } from './PriceUpdateV2';
2
- export { PriceUpdateV2Fields, PriceUpdateV2JSON } from './PriceUpdateV2';
2
+ export type { PriceUpdateV2Fields, PriceUpdateV2JSON } from './PriceUpdateV2';
@@ -19,16 +19,18 @@ export type InitObligationArgsModel = {
19
19
 
20
20
  export class VanillaObligation {
21
21
  readonly programId: PublicKey;
22
+ readonly id: number;
22
23
  static tag = 0;
23
24
 
24
- constructor(programId: PublicKey) {
25
+ constructor(programId: PublicKey, id?: number) {
25
26
  this.programId = programId;
27
+ this.id = id ?? 0;
26
28
  }
27
29
 
28
30
  toArgs() {
29
31
  const initObligationArgs: InitObligationArgsModel = {
30
32
  tag: VanillaObligation.tag,
31
- id: 0,
33
+ id: this.id,
32
34
  seed1: PublicKey.default,
33
35
  seed2: PublicKey.default,
34
36
  };
@@ -45,18 +47,20 @@ export class MultiplyObligation {
45
47
  readonly collToken: PublicKey;
46
48
  readonly debtToken: PublicKey;
47
49
  readonly programId: PublicKey;
50
+ readonly id: number;
48
51
  static tag = 1;
49
52
 
50
- constructor(collToken: PublicKey, debtToken: PublicKey, programId: PublicKey) {
53
+ constructor(collToken: PublicKey, debtToken: PublicKey, programId: PublicKey, id?: number) {
51
54
  this.collToken = collToken;
52
55
  this.debtToken = debtToken;
53
56
  this.programId = programId;
57
+ this.id = id ?? 0;
54
58
  }
55
59
 
56
60
  toArgs() {
57
61
  const initObligationArgs: InitObligationArgsModel = {
58
62
  tag: MultiplyObligation.tag,
59
- id: 0,
63
+ id: this.id,
60
64
  seed1: this.collToken,
61
65
  seed2: this.debtToken,
62
66
  };
@@ -73,18 +77,20 @@ export class LeverageObligation {
73
77
  readonly collToken: PublicKey;
74
78
  readonly debtToken: PublicKey;
75
79
  readonly programId: PublicKey;
80
+ readonly id: number;
76
81
  static tag = 3;
77
82
 
78
- constructor(collToken: PublicKey, debtToken: PublicKey, programId: PublicKey) {
83
+ constructor(collToken: PublicKey, debtToken: PublicKey, programId: PublicKey, id?: number) {
79
84
  this.collToken = collToken;
80
85
  this.debtToken = debtToken;
81
86
  this.programId = programId;
87
+ this.id = id ?? 0;
82
88
  }
83
89
 
84
90
  toArgs() {
85
91
  const initObligationArgs: InitObligationArgsModel = {
86
92
  tag: LeverageObligation.tag,
87
- id: 0,
93
+ id: this.id,
88
94
  seed1: this.collToken,
89
95
  seed2: this.debtToken,
90
96
  };
@@ -100,11 +106,13 @@ export class LeverageObligation {
100
106
  export class LendingObligation {
101
107
  readonly token: PublicKey;
102
108
  readonly programId: PublicKey;
109
+ readonly id: number;
103
110
  static tag = 2;
104
111
 
105
- constructor(token: PublicKey, programId: PublicKey) {
112
+ constructor(token: PublicKey, programId: PublicKey, id?: number) {
106
113
  this.token = token;
107
114
  this.programId = programId;
115
+ this.id = id ?? 0;
108
116
  }
109
117
 
110
118
  toArgs() {
@@ -123,7 +131,7 @@ export class LendingObligation {
123
131
  }
124
132
  }
125
133
 
126
- function getObligationPdaWithArgs(
134
+ export function getObligationPdaWithArgs(
127
135
  market: PublicKey,
128
136
  user: PublicKey,
129
137
  args: InitObligationArgsModel,
@@ -141,6 +149,39 @@ function getObligationPdaWithArgs(
141
149
  return obligationAddress;
142
150
  }
143
151
 
152
+ export function getObligationType(
153
+ kaminoMarket: KaminoMarket,
154
+ obligationTag: ObligationTypeTag,
155
+ mintAddress1: PublicKey = PublicKey.default,
156
+ mintAddress2: PublicKey = PublicKey.default
157
+ ): ObligationType {
158
+ switch (obligationTag) {
159
+ case VanillaObligation.tag: {
160
+ return new VanillaObligation(kaminoMarket.programId);
161
+ }
162
+ case MultiplyObligation.tag: {
163
+ return new MultiplyObligation(
164
+ mintAddress1,
165
+ mintAddress2,
166
+ kaminoMarket.programId
167
+ );
168
+ }
169
+ case LeverageObligation.tag: {
170
+ return new LeverageObligation(
171
+ mintAddress1,
172
+ mintAddress2,
173
+ kaminoMarket.programId
174
+ );
175
+ }
176
+ case LendingObligation.tag: {
177
+ return new LendingObligation(mintAddress1, kaminoMarket.programId);
178
+ }
179
+ default: {
180
+ throw new Error('Invalid obligation type');
181
+ }
182
+ }
183
+ }
184
+
144
185
  export function getObligationTypeFromObligation(
145
186
  kaminoMarket: KaminoMarket,
146
187
  obligation: KaminoObligation
@@ -148,7 +189,6 @@ export function getObligationTypeFromObligation(
148
189
  switch (obligation.obligationTag) {
149
190
  case VanillaObligation.tag: {
150
191
  return new VanillaObligation(kaminoMarket.programId);
151
- break;
152
192
  }
153
193
  case MultiplyObligation.tag: {
154
194
  return new MultiplyObligation(
@@ -156,7 +196,6 @@ export function getObligationTypeFromObligation(
156
196
  obligation.getBorrows()[0].mintAddress,
157
197
  kaminoMarket.programId
158
198
  );
159
- break;
160
199
  }
161
200
  case LeverageObligation.tag: {
162
201
  return new LeverageObligation(
@@ -164,11 +203,9 @@ export function getObligationTypeFromObligation(
164
203
  obligation.getBorrows()[0].mintAddress,
165
204
  kaminoMarket.programId
166
205
  );
167
- break;
168
206
  }
169
207
  case LendingObligation.tag: {
170
208
  return new LendingObligation(obligation.getDeposits()[0].mintAddress, kaminoMarket.programId);
171
- break;
172
209
  }
173
210
  default: {
174
211
  throw new Error('Invalid obligation type');
@@ -10,6 +10,8 @@ export const INITIAL_COLLATERAL_RATE = new Decimal(INITIAL_COLLATERAL_RATIO);
10
10
 
11
11
  export const SECONDS_PER_YEAR = 365.242_199 * 24.0 * 60.0 * 60.0;
12
12
 
13
+ export const TOTAL_NUMBER_OF_IDS_TO_CHECK = 25;
14
+
13
15
  export type ENV = 'mainnet-beta' | 'devnet' | 'localnet';
14
16
 
15
17
  export function isENV(value: any): value is ENV {