@kamino-finance/klend-sdk 5.10.0 → 5.10.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 (37) hide show
  1. package/dist/classes/farm_utils.d.ts +22 -0
  2. package/dist/classes/farm_utils.d.ts.map +1 -0
  3. package/dist/classes/farm_utils.js +93 -0
  4. package/dist/classes/farm_utils.js.map +1 -0
  5. package/dist/classes/lut_utils.d.ts +29 -0
  6. package/dist/classes/lut_utils.d.ts.map +1 -0
  7. package/dist/classes/lut_utils.js +62 -0
  8. package/dist/classes/lut_utils.js.map +1 -0
  9. package/dist/classes/manager.d.ts +51 -28
  10. package/dist/classes/manager.d.ts.map +1 -1
  11. package/dist/classes/manager.js +53 -27
  12. package/dist/classes/manager.js.map +1 -1
  13. package/dist/classes/types.d.ts +15 -0
  14. package/dist/classes/types.d.ts.map +1 -1
  15. package/dist/classes/utils.d.ts +6 -0
  16. package/dist/classes/utils.d.ts.map +1 -1
  17. package/dist/classes/utils.js +10 -0
  18. package/dist/classes/utils.js.map +1 -1
  19. package/dist/classes/vault.d.ts +84 -56
  20. package/dist/classes/vault.d.ts.map +1 -1
  21. package/dist/classes/vault.js +229 -134
  22. package/dist/classes/vault.js.map +1 -1
  23. package/dist/client_kamino_manager.d.ts.map +1 -1
  24. package/dist/client_kamino_manager.js +10 -26
  25. package/dist/client_kamino_manager.js.map +1 -1
  26. package/dist/utils/ata.d.ts.map +1 -1
  27. package/dist/utils/ata.js +1 -0
  28. package/dist/utils/ata.js.map +1 -1
  29. package/package.json +6 -6
  30. package/src/classes/farm_utils.ts +155 -0
  31. package/src/classes/lut_utils.ts +63 -0
  32. package/src/classes/manager.ts +75 -31
  33. package/src/classes/types.ts +18 -0
  34. package/src/classes/utils.ts +10 -0
  35. package/src/classes/vault.ts +315 -158
  36. package/src/client_kamino_manager.ts +19 -33
  37. package/src/utils/ata.ts +1 -0
@@ -24,6 +24,9 @@ const bs58_1 = __importDefault(require("bs58"));
24
24
  const rpc_1 = require("../utils/rpc");
25
25
  const kliquidity_sdk_1 = require("@kamino-finance/kliquidity-sdk");
26
26
  const CreationParameters_1 = require("@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters");
27
+ const dist_1 = require("@kamino-finance/farms-sdk/dist");
28
+ const lut_utils_1 = require("./lut_utils");
29
+ const farm_utils_1 = require("./farm_utils");
27
30
  exports.kaminoVaultId = new web3_js_1.PublicKey('kvauTFR8qm1dhniz6pYuBZkuene3Hfrs1VQhVRgCNrr');
28
31
  exports.kaminoVaultStagingId = new web3_js_1.PublicKey('STkvh7ostar39Fwr4uZKASs1RNNuYMFMTsE77FiRsL2');
29
32
  const TOKEN_VAULT_SEED = 'token_vault';
@@ -50,10 +53,12 @@ class KaminoVaultClient {
50
53
  getProgramID() {
51
54
  return this._kaminoVaultProgramId;
52
55
  }
56
+ hasFarm() {
57
+ return;
58
+ }
53
59
  /**
54
60
  * This method will create a vault with a given config. The config can be changed later on, but it is recommended to set it up correctly from the start
55
61
  * @param vaultConfig - the config object used to create a vault
56
- * @returns vault - keypair, should be used to sign the transaction which creates the vault account
57
62
  * @returns vault: the keypair of the vault, used to sign the initialization transaction; initVaultIxs: a struct with ixs to initialize the vault and its lookup table + populateLUTIxs, a list to populate the lookup table which has to be executed in a separate transaction
58
63
  */
59
64
  async createVaultIxs(vaultConfig) {
@@ -62,7 +67,7 @@ class KaminoVaultClient {
62
67
  const createVaultIx = web3_js_1.SystemProgram.createAccount({
63
68
  fromPubkey: vaultConfig.admin,
64
69
  newAccountPubkey: vaultState.publicKey,
65
- lamports: await this._connection.getMinimumBalanceForRentExemption(size),
70
+ lamports: await this.getConnection().getMinimumBalanceForRentExemption(size),
66
71
  space: size,
67
72
  programId: this._kaminoVaultProgramId,
68
73
  });
@@ -83,8 +88,8 @@ class KaminoVaultClient {
83
88
  };
84
89
  const initVaultIx = (0, instructions_1.initVault)(initVaultAccounts, this._kaminoVaultProgramId);
85
90
  // create and set up the vault lookup table
86
- const slot = await this._connection.getSlot();
87
- const [createLUTIx, lut] = this.getInitLookupTableIx(vaultConfig.admin, slot);
91
+ const slot = await this.getConnection().getSlot();
92
+ const [createLUTIx, lut] = (0, lut_utils_1.initLookupTableIx)(vaultConfig.admin, slot);
88
93
  const accountsToBeInserted = [
89
94
  vaultConfig.admin,
90
95
  vaultState.publicKey,
@@ -119,7 +124,7 @@ class KaminoVaultClient {
119
124
  * This method updates the vault reserve allocation cofnig for an exiting vault reserve, or adds a new reserve to the vault if it does not exist.
120
125
  * @param vault - vault to be updated
121
126
  * @param reserveAllocationConfig - new reserve allocation config
122
- * @returns - a list of instructions
127
+ * @returns - a struct with an instruction to update the reserve allocation and an optional list of instructions to update the lookup table for the allocation changes
123
128
  */
124
129
  async updateReserveAllocationIxs(vault, reserveAllocationConfig) {
125
130
  const vaultState = await vault.getState(this.getConnection());
@@ -208,23 +213,48 @@ class KaminoVaultClient {
208
213
  updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesAccountMetas);
209
214
  updateVaultConfigIx.keys = updateVaultConfigIx.keys.concat(vaultReservesLendingMarkets);
210
215
  const updateLUTIxs = [];
211
- if (mode.kind === new types_1.VaultConfigField.PendingVaultAdmin().kind || mode.kind === new types_1.VaultConfigField.Farm().kind) {
216
+ if (mode.kind === new types_1.VaultConfigField.PendingVaultAdmin().kind) {
212
217
  const newPubkey = new web3_js_1.PublicKey(value);
213
218
  const insertIntoLutIxs = await this.insertIntoLookupTableIxs(vaultState.adminAuthority, vaultState.vaultLookupTable, [newPubkey]);
214
219
  updateLUTIxs.push(...insertIntoLutIxs);
215
220
  }
221
+ else if (mode.kind === new types_1.VaultConfigField.Farm().kind) {
222
+ const keysToAddToLUT = [new web3_js_1.PublicKey(value)];
223
+ // if the farm already exist we want to read its state to add it to the LUT
224
+ try {
225
+ const farmState = await dist_1.FarmState.fetch(this.getConnection(), keysToAddToLUT[0]);
226
+ keysToAddToLUT.push(farmState.farmVault, farmState.farmVaultsAuthority, farmState.token.mint, farmState.scopePrices, farmState.globalConfig);
227
+ const insertIntoLutIxs = await this.insertIntoLookupTableIxs(vaultState.adminAuthority, vaultState.vaultLookupTable, keysToAddToLUT);
228
+ updateLUTIxs.push(...insertIntoLutIxs);
229
+ }
230
+ catch (error) {
231
+ console.log(`Error fetching farm ${keysToAddToLUT[0].toString()} state`, error);
232
+ }
233
+ }
216
234
  const updateVaultConfigIxs = {
217
235
  updateVaultConfigIx,
218
236
  updateLUTIxs,
219
237
  };
220
238
  return updateVaultConfigIxs;
221
239
  }
240
+ /** 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
241
+ * @param vault - vault to set the farm for
242
+ * @param farm - the farm where the vault shares can be staked
243
+ * @param [errorOnOverride] - if true, the function will throw an error if the vault already has a farm. If false, it will override the farm
244
+ */
245
+ async setVaultFarm(vault, farm, errorOnOverride = true) {
246
+ const vaultHasFarm = await vault.hasFarm(this.getConnection());
247
+ if (vaultHasFarm && errorOnOverride) {
248
+ throw new Error('Vault already has a farm, if you want to override it set errorOnOverride to false');
249
+ }
250
+ return this.updateVaultConfigIxs(vault, new types_1.VaultConfigField.Farm(), farm.toBase58());
251
+ }
222
252
  /**
223
253
  * This method updates the vault config for a vault that
224
254
  * @param vault - address of vault to be updated
225
255
  * @param mode - the field to be updated
226
256
  * @param value - the new value for the field to be updated (number or pubkey)
227
- * @returns - a list of instructions
257
+ * @returns - an instruction to update the vault config
228
258
  */
229
259
  updateUninitialisedVaultConfigIx(admin, vault, mode, value) {
230
260
  const updateVaultConfigAccs = {
@@ -257,7 +287,7 @@ class KaminoVaultClient {
257
287
  /**
258
288
  * This function creates the instruction for the `pendingAdmin` of the vault to accept to become the owner of the vault (step 2/2 of the ownership transfer)
259
289
  * @param vault - vault to change the ownership for
260
- * @returns - an instruction to be used to be executed
290
+ * @returns - an instruction to accept the ownership of the vault and a list of instructions to update the lookup table
261
291
  */
262
292
  async acceptVaultOwnershipIxs(vault) {
263
293
  const vaultState = await vault.getState(this.getConnection());
@@ -267,9 +297,9 @@ class KaminoVaultClient {
267
297
  };
268
298
  const acceptVaultOwnershipIx = (0, instructions_1.updateAdmin)(acceptOwneshipAccounts, this._kaminoVaultProgramId);
269
299
  // read the current LUT and create a new one for the new admin and backfill it
270
- const accountsInExistentLUT = (await this.getAccountsInLUT(vaultState.vaultLookupTable)).filter((account) => !account.equals(vaultState.adminAuthority));
300
+ const accountsInExistentLUT = (await (0, lut_utils_1.getAccountsInLUT)(this.getConnection(), vaultState.vaultLookupTable)).filter((account) => !account.equals(vaultState.adminAuthority));
271
301
  const LUTIxs = [];
272
- const [initNewLUTIx, newLUT] = this.getInitLookupTableIx(vaultState.pendingAdmin, await this._connection.getSlot());
302
+ const [initNewLUTIx, newLUT] = (0, lut_utils_1.initLookupTableIx)(vaultState.pendingAdmin, await this.getConnection().getSlot());
273
303
  LUTIxs.push(initNewLUTIx);
274
304
  const insertIntoLUTIxs = await this.insertIntoLookupTableIxs(vaultState.pendingAdmin, newLUT, accountsInExistentLUT);
275
305
  LUTIxs.push(...insertIntoLUTIxs);
@@ -286,7 +316,7 @@ class KaminoVaultClient {
286
316
  * This function creates the instruction for the admin to give up a part of the pending fees (which will be accounted as part of the vault)
287
317
  * @param vault - vault to give up pending fees for
288
318
  * @param maxAmountToGiveUp - the maximum amount of fees to give up, in tokens
289
- * @returns - an instruction to be used to be executed
319
+ * @returns - an instruction to give up the specified pending fees
290
320
  */
291
321
  async giveUpPendingFeesIx(vault, maxAmountToGiveUp) {
292
322
  const vaultState = await vault.getState(this.getConnection());
@@ -305,7 +335,8 @@ class KaminoVaultClient {
305
335
  * This method withdraws all the pending fees from the vault to the owner's token ATA
306
336
  * @param vault - vault for which the admin withdraws the pending fees
307
337
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
308
- * @returns - list of instructions to withdraw all pending fees
338
+ * @param [vaultReservesMap] - a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
339
+ * @returns - list of instructions to withdraw all pending fees, including the ATA creation instructions if needed
309
340
  */
310
341
  async withdrawPendingFeesIxs(vault, slot, vaultReservesMap) {
311
342
  const vaultState = await vault.getState(this.getConnection());
@@ -336,7 +367,7 @@ class KaminoVaultClient {
336
367
  }
337
368
  });
338
369
  }
339
- const reserveStates = await lib_1.Reserve.fetchMultiple(this._connection, reservesToWithdraw, this._kaminoLendProgramId);
370
+ const reserveStates = await lib_1.Reserve.fetchMultiple(this.getConnection(), reservesToWithdraw, this._kaminoLendProgramId);
340
371
  const withdrawIxns = await Promise.all(reservesToWithdraw.map(async (reserve, index) => {
341
372
  if (reserveStates[index] === null) {
342
373
  throw new Error(`Reserve ${reserve.toBase58()} not found`);
@@ -358,13 +389,14 @@ class KaminoVaultClient {
358
389
  /**
359
390
  * This function creates instructions to deposit into a vault. It will also create ATA creation instructions for the vault shares that the user receives in return
360
391
  * @param user - user to deposit
361
- * @param vault - vault to deposit into
392
+ * @param vault - vault to deposit into (if the state is not provided, it will be fetched)
362
393
  * @param tokenAmount - token amount to be deposited, in decimals (will be converted in lamports)
363
- * @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
364
- * @returns - an array of instructions to be used to be executed
394
+ * @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
395
+ * @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
396
+ * @returns - an instance of DepositIxs which contains the instructions to deposit in vault and the instructions to stake the shares in the farm if the vault has a farm
365
397
  */
366
- async depositIxs(user, vault, tokenAmount, vaultReservesMap) {
367
- const vaultState = await vault.getState(this._connection);
398
+ async depositIxs(user, vault, tokenAmount, vaultReservesMap, farmState) {
399
+ const vaultState = await vault.getState(this.getConnection());
368
400
  const tokenProgramID = vaultState.tokenProgram;
369
401
  const userTokenAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.tokenMint, user, true, tokenProgramID);
370
402
  const createAtasIxns = [];
@@ -423,30 +455,78 @@ class KaminoVaultClient {
423
455
  });
424
456
  depositIx.keys = depositIx.keys.concat(vaultReservesAccountMetas);
425
457
  depositIx.keys = depositIx.keys.concat(vaultReservesLendingMarkets);
426
- return [...createAtasIxns, depositIx, ...closeAtasIxns];
458
+ const depositIxs = {
459
+ depositIxs: [...createAtasIxns, depositIx, ...closeAtasIxns],
460
+ stakeInFarmIfNeededIxs: [],
461
+ };
462
+ // if there is no farm, we can return the deposit instructions, otherwise include the stake ix in the response
463
+ if (!(await vault.hasFarm(this.getConnection()))) {
464
+ return depositIxs;
465
+ }
466
+ // if there is a farm, stake the shares
467
+ const stakeSharesIxs = await this.stakeSharesIxs(user, vault, undefined, farmState);
468
+ depositIxs.stakeInFarmIfNeededIxs = stakeSharesIxs;
469
+ return depositIxs;
470
+ }
471
+ /**
472
+ * This function creates instructions to stake the shares in the vault farm if the vault has a farm
473
+ * @param user - user to stake
474
+ * @param vault - vault to deposit into its farm (if the state is not provided, it will be fetched)
475
+ * @param [sharesAmount] - token amount to be deposited, in decimals (will be converted in lamports). Optional. If not provided, the user's share balance will be used
476
+ * @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
477
+ * @returns - a list of instructions for the user to stake shares into the vault's farm, including the creation of prerequisite accounts if needed
478
+ */
479
+ async stakeSharesIxs(user, vault, sharesAmount, farmState) {
480
+ const vaultState = await vault.getState(this.getConnection());
481
+ let sharesToStakeLamports = new decimal_js_1.default(utils_2.U64_MAX);
482
+ if (sharesAmount) {
483
+ sharesToStakeLamports = (0, utils_1.numberToLamportsDecimal)(sharesAmount, vaultState.sharesMintDecimals.toNumber());
484
+ }
485
+ // if tokens to be staked are 0 or vault has no farm there is no stake needed
486
+ if (sharesToStakeLamports.lte(0) || !vault.hasFarm(this.getConnection())) {
487
+ return [];
488
+ }
489
+ // returns the ix to create the farm state account if needed and the ix to stake the shares
490
+ return (0, farm_utils_1.getFarmStakeIxs)(this.getConnection(), user, sharesToStakeLamports, vaultState.vaultFarm, farmState);
427
491
  }
428
492
  /**
429
- * This function will return the missing ATA creation instructions, as well as one or multiple withdraw instructions, based on how many reserves it's needed to withdraw from. This might have to be split in multiple transactions
493
+ * This function will return a struct with the instructions to unstake from the farm if necessary and the instructions for the missing ATA creation instructions, as well as one or multiple withdraw instructions, based on how many reserves it's needed to withdraw from. This might have to be split in multiple transactions
430
494
  * @param user - user to withdraw
431
495
  * @param vault - vault to withdraw from
432
496
  * @param shareAmount - share amount to withdraw, in order to withdraw everything, any value > user share amount
433
497
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
434
- * @returns an array of instructions to be executed
498
+ * @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
499
+ * @param [farmState] - the state of the vault farm, if the vault has a farm. Optional. If not provided, it will be fetched
500
+ * @returns an array of instructions to create missing ATAs if needed and the withdraw instructions
435
501
  */
436
- async withdrawIxs(user, vault, shareAmount, slot, vaultReservesMap) {
437
- const vaultState = await vault.getState(this._connection);
502
+ async withdrawIxs(user, vault, shareAmount, slot, vaultReservesMap, farmState) {
503
+ const vaultState = await vault.getState(this.getConnection());
438
504
  const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
505
+ const withdrawIxs = {
506
+ unstakeFromFarmIfNeededIxs: [],
507
+ withdrawIxs: [],
508
+ };
509
+ const shareLamportsToWithdraw = (0, kliquidity_sdk_1.collToLamportsDecimal)(shareAmount, vaultState.sharesMintDecimals.toNumber());
510
+ const hasFarm = await vault.hasFarm(this.getConnection());
511
+ if (hasFarm) {
512
+ const unstakeAndWithdrawFromFarmIxs = await (0, farm_utils_1.getFarmUnstakeAndWithdrawIxs)(this.getConnection(), user, shareLamportsToWithdraw, vaultState.vaultFarm, farmState);
513
+ withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.unstakeIx);
514
+ withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.withdrawIx);
515
+ }
439
516
  // if the vault has allocations withdraw otherwise wtihdraw from available ix
440
517
  const vaultAllocation = vaultState.vaultAllocationStrategy.find((allocation) => allocation.reserve.equals(web3_js_1.PublicKey.default));
441
518
  if (vaultAllocation) {
442
- return this.wihdrdrawWithReserveIxns(user, kaminoVault, shareAmount, slot, vaultReservesMap);
519
+ const withdrawFromVaultIxs = await this.wihdrdrawWithReserveIxns(user, kaminoVault, shareAmount, slot, vaultReservesMap);
520
+ withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
443
521
  }
444
522
  else {
445
- return this.withdrawFromAvailableIxns(user, kaminoVault, shareAmount);
523
+ const withdrawFromVaultIxs = await this.withdrawFromAvailableIxns(user, kaminoVault, shareAmount);
524
+ withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
446
525
  }
526
+ return withdrawIxs;
447
527
  }
448
528
  async withdrawFromAvailableIxns(user, vault, shareAmount) {
449
- const vaultState = await vault.getState(this._connection);
529
+ const vaultState = await vault.getState(this.getConnection());
450
530
  const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
451
531
  const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user);
452
532
  const [{ ata: userTokenAta, createAtaIx }] = (0, utils_2.createAtasIdempotent)(user, [
@@ -460,7 +540,7 @@ class KaminoVaultClient {
460
540
  return [createAtaIx, withdrawFromAvailableIxn];
461
541
  }
462
542
  async wihdrdrawWithReserveIxns(user, vault, shareAmount, slot, vaultReservesMap) {
463
- const vaultState = await vault.getState(this._connection);
543
+ const vaultState = await vault.getState(this.getConnection());
464
544
  const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
465
545
  const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user);
466
546
  const [{ ata: userTokenAta, createAtaIx }] = (0, utils_2.createAtasIdempotent)(user, [
@@ -508,7 +588,6 @@ class KaminoVaultClient {
508
588
  }
509
589
  const withdrawIxns = [];
510
590
  withdrawIxns.push(createAtaIx);
511
- // let sharesLeftToWithdraw = shareAmount;
512
591
  for (let reserveIndex = 0; reserveIndex < reserveWithSharesAmountToWithdraw.length; reserveIndex++) {
513
592
  const reserveWithTokens = reserveWithSharesAmountToWithdraw[reserveIndex];
514
593
  const reserveState = vaultReservesState.get(reserveWithTokens.reserve);
@@ -527,6 +606,7 @@ class KaminoVaultClient {
527
606
  }
528
607
  return withdrawIxns;
529
608
  }
609
+ // todo: make sure we also check the ata of the investor for the vault token exists
530
610
  /**
531
611
  * 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
532
612
  * @param payer wallet that pays the tx
@@ -535,11 +615,11 @@ class KaminoVaultClient {
535
615
  */
536
616
  async investAllReservesIxs(payer, vault) {
537
617
  //TODO: Order invest ixns by - invest that removes first, then invest that adds
538
- const vaultState = await vault.getState(this._connection);
618
+ const vaultState = await vault.getState(this.getConnection());
539
619
  const vaultReserves = this.getVaultReserves(vaultState);
540
620
  const investIxnsPromises = [];
541
621
  for (const reserve of vaultReserves) {
542
- const reserveState = await lib_1.Reserve.fetch(this._connection, reserve, this._kaminoLendProgramId);
622
+ const reserveState = await lib_1.Reserve.fetch(this.getConnection(), reserve, this._kaminoLendProgramId);
543
623
  if (reserveState === null) {
544
624
  throw new Error(`Reserve ${reserve.toBase58()} not found`);
545
625
  }
@@ -549,18 +629,20 @@ class KaminoVaultClient {
549
629
  const investIxns = await Promise.all(investIxnsPromises).then((ixns) => ixns.flat());
550
630
  return investIxns;
551
631
  }
632
+ // todo: make sure we also check the ata of the investor for the vault token exists
552
633
  /**
553
634
  * This will trigger invest by balancing, based on weights, the reserve allocation of the vault. It can either withdraw or deposit into the given reserve to balance it
554
635
  * @param payer wallet pubkey
555
636
  * @param vault - vault to invest from
556
637
  * @param reserve - reserve to invest into or disinvest from
638
+ * @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
557
639
  * @returns - an array of invest instructions for each invest action required for the vault reserves
558
640
  */
559
641
  async investSingleReserveIxs(payer, vault, reserve, vaultReservesMap) {
560
- const vaultState = await vault.getState(this._connection);
642
+ const vaultState = await vault.getState(this.getConnection());
561
643
  const cTokenVault = getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId);
562
644
  const lendingMarketAuth = (0, utils_2.lendingMarketAuthPda)(reserve.state.lendingMarket, this._kaminoLendProgramId)[0];
563
- const tokenProgram = await (0, rpc_1.getAccountOwner)(this._connection, vaultState.tokenMint);
645
+ const tokenProgram = await (0, rpc_1.getAccountOwner)(this.getConnection(), vaultState.tokenMint);
564
646
  const [{ ata: payerTokenAta, createAtaIx }] = (0, utils_2.createAtasIdempotent)(payer, [
565
647
  { mint: vaultState.tokenMint, tokenProgram },
566
648
  ]);
@@ -604,12 +686,14 @@ class KaminoVaultClient {
604
686
  investIx.keys = investIx.keys.concat(vaultReservesLendingMarkets);
605
687
  return [createAtaIx, investIx];
606
688
  }
689
+ /** Convert a string to a u8 representation to be stored on chain */
607
690
  encodeVaultName(token) {
608
691
  const maxArray = new Uint8Array(40);
609
692
  const s = new TextEncoder().encode(token);
610
693
  maxArray.set(s);
611
694
  return maxArray;
612
695
  }
696
+ /**Convert an u8 array to a string */
613
697
  decodeVaultName(token) {
614
698
  const maxArray = new Uint8Array(token);
615
699
  let s = new TextDecoder().decode(maxArray);
@@ -733,10 +817,11 @@ class KaminoVaultClient {
733
817
  * Sync a vault for lookup table; create and set the LUT for the vault if needed and fill it with all the needed accounts
734
818
  * @param vault the vault to sync and set the LUT for if needed
735
819
  * @param vaultReserves optional; the state of the reserves in the vault allocation
820
+ * @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
736
821
  * @returns a struct that contains a list of ix to create the LUT and assign it to the vault if needed + a list of ixs to insert all the accounts in the LUT
737
822
  */
738
- async syncVaultLookupTable(vault, vaultReserves) {
739
- const vaultState = await vault.getState(this._connection);
823
+ async syncVaultLookupTableIxs(vault, vaultReservesMap) {
824
+ const vaultState = await vault.getState(this.getConnection());
740
825
  const allAccountsToBeInserted = [
741
826
  vault.address,
742
827
  vaultState.adminAuthority,
@@ -751,8 +836,8 @@ class KaminoVaultClient {
751
836
  allAccountsToBeInserted.push(allocation.reserve);
752
837
  allAccountsToBeInserted.push(allocation.ctokenVault);
753
838
  });
754
- if (vaultReserves) {
755
- vaultReserves.forEach((reserve) => {
839
+ if (vaultReservesMap) {
840
+ vaultReservesMap.forEach((reserve) => {
756
841
  allAccountsToBeInserted.push(reserve.state.lendingMarket);
757
842
  allAccountsToBeInserted.push(reserve.state.farmCollateral);
758
843
  allAccountsToBeInserted.push(reserve.state.farmDebt);
@@ -780,8 +865,8 @@ class KaminoVaultClient {
780
865
  const setupLUTIfNeededIxs = [];
781
866
  let lut = vaultState.vaultLookupTable;
782
867
  if (lut.equals(web3_js_1.PublicKey.default)) {
783
- const recentSlot = await this._connection.getSlot();
784
- const [ixn, address] = this.getInitLookupTableIx(vaultState.adminAuthority, recentSlot);
868
+ const recentSlot = await this.getConnection().getSlot();
869
+ const [ixn, address] = (0, lut_utils_1.initLookupTableIx)(vaultState.adminAuthority, recentSlot);
785
870
  setupLUTIfNeededIxs.push(ixn);
786
871
  lut = address;
787
872
  // set the new LUT for the vault
@@ -799,14 +884,6 @@ class KaminoVaultClient {
799
884
  syncLUTIxs: ixns,
800
885
  };
801
886
  }
802
- getInitLookupTableIx(payer, slot) {
803
- const [ixn, address] = web3_js_1.AddressLookupTableProgram.createLookupTable({
804
- authority: payer,
805
- payer,
806
- recentSlot: slot,
807
- });
808
- return [ixn, address];
809
- }
810
887
  getReserveAccountsToInsertInLut(reserveState) {
811
888
  return [
812
889
  reserveState.lendingMarket,
@@ -819,10 +896,18 @@ class KaminoVaultClient {
819
896
  reserveState.collateral.supplyVault,
820
897
  ];
821
898
  }
899
+ /**
900
+ * This method inserts the missing keys from the provided keys into an existent lookup table
901
+ * @param payer - payer wallet pubkey
902
+ * @param lookupTable - lookup table to insert the keys into
903
+ * @param keys - keys to insert into the lookup table
904
+ * @param [accountsInLUT] - the existent accounts in the lookup table. Optional. If provided, the function will not fetch the accounts in the lookup table
905
+ * @returns - an array of instructions to insert the missing keys into the lookup table
906
+ */
822
907
  async insertIntoLookupTableIxs(payer, lookupTable, keys, accountsInLUT) {
823
908
  let lutContents = accountsInLUT;
824
909
  if (!accountsInLUT) {
825
- lutContents = await this.getAccountsInLUT(lookupTable);
910
+ lutContents = await (0, lut_utils_1.getAccountsInLUT)(this.getConnection(), lookupTable);
826
911
  }
827
912
  else {
828
913
  lutContents = accountsInLUT;
@@ -844,79 +929,80 @@ class KaminoVaultClient {
844
929
  }
845
930
  return ixns;
846
931
  }
847
- /**
848
- *
849
- * @param connection
850
- * @param lookupTable
851
- * @returns
852
- */
853
- async getAccountsInLUT(lookupTable) {
854
- const lutState = await this._connection.getAddressLookupTable(lookupTable);
855
- if (!lutState || !lutState.value) {
856
- throw new Error(`Lookup table ${lookupTable} not found`);
857
- }
858
- return lutState.value.state.addresses;
859
- }
860
- deactivateLookupTableIx(payer, lookupTable) {
861
- const ixn = web3_js_1.AddressLookupTableProgram.deactivateLookupTable({
862
- authority: payer,
863
- lookupTable: lookupTable,
864
- });
865
- return ixn;
866
- }
867
- /// this require the LUT to be deactivated at least 500 blocks before
868
- closeLookupTableIx(payer, lookupTable) {
869
- const ixn = web3_js_1.AddressLookupTableProgram.closeLookupTable({
870
- authority: payer,
871
- recipient: payer,
872
- lookupTable: lookupTable,
873
- });
874
- return ixn;
875
- }
876
932
  /**
877
933
  * This method returns the user shares balance for a given vault
878
934
  * @param user - user to calculate the shares balance for
879
935
  * @param vault - vault to calculate shares balance for
880
- * @returns - user share balance in decimal (not lamports)
936
+ * @returns - user share balance in tokens (not lamports)
881
937
  */
882
938
  async getUserSharesBalanceSingleVault(user, vault) {
883
- const vaultState = await vault.getState(this._connection);
939
+ const vaultState = await vault.getState(this.getConnection());
940
+ const userShares = { unstakedShares: new decimal_js_1.default(0), stakedShares: new decimal_js_1.default(0) };
884
941
  const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(vaultState.sharesMint, user);
885
- const userSharesAccountInfo = await this._connection.getAccountInfo(userSharesAta);
886
- if (!userSharesAccountInfo) {
887
- return new decimal_js_1.default(0);
942
+ const userSharesAccountInfo = await this.getConnection().getAccountInfo(userSharesAta);
943
+ if (userSharesAccountInfo) {
944
+ const userSharesAccount = (0, spl_token_1.unpackAccount)(userSharesAta, userSharesAccountInfo);
945
+ userShares.unstakedShares = new decimal_js_1.default(userSharesAccount.amount.toString()).div(new decimal_js_1.default(10).pow(vaultState.sharesMintDecimals.toString()));
946
+ }
947
+ if (await vault.hasFarm(this.getConnection())) {
948
+ const userSharesInFarm = await (0, farm_utils_1.getUserSharesInFarm)(this.getConnection(), user, vaultState.vaultFarm, vaultState.sharesMintDecimals.toNumber());
949
+ userShares.stakedShares = userSharesInFarm;
888
950
  }
889
- const userSharesAccount = (0, spl_token_1.unpackAccount)(userSharesAta, userSharesAccountInfo);
890
- return new decimal_js_1.default(userSharesAccount.amount.toString()).div(new decimal_js_1.default(10).pow(vaultState.sharesMintDecimals.toString()));
951
+ return userShares;
891
952
  }
892
953
  /**
893
954
  * This method returns the user shares balance for all existing vaults
894
955
  * @param user - user to calculate the shares balance for
895
- * @param vaultsOverride - the kamino vaults if already fetched, in order to reduce rpc calls
896
- * @returns - hash map with keyh as vault address and value as user share balance in decimal (not lamports)
956
+ * @param [vaultsOverride] - the kamino vaults if already fetched, in order to reduce rpc calls.Optional
957
+ * @returns - hash map with keys as vault address and value as user share balance in decimal (not lamports)
897
958
  */
898
959
  async getUserSharesBalanceAllVaults(user, vaultsOverride) {
899
960
  const vaults = vaultsOverride ? vaultsOverride : await this.getAllVaults();
900
961
  // stores vault address for each userSharesAta
901
962
  const vaultUserShareBalance = new lib_1.PubkeyHashMap();
963
+ const vaultToUserFarmStateAddress = new lib_1.PubkeyHashMap();
902
964
  const userSharesAtaArray = [];
903
- vaults.forEach((vault) => {
965
+ vaults.forEach(async (vault) => {
904
966
  const state = vault.state;
905
967
  if (!state) {
906
968
  throw new Error(`Vault ${vault.address.toBase58()} not fetched`);
907
969
  }
908
970
  const userSharesAta = (0, lib_1.getAssociatedTokenAddress)(state.sharesMint, user);
909
971
  userSharesAtaArray.push(userSharesAta);
972
+ if (await vault.hasFarm(this.getConnection())) {
973
+ const farmUserState = await (0, farm_utils_1.getFarmUserStatePDA)(this.getConnection(), user, state.vaultFarm);
974
+ vaultToUserFarmStateAddress.set(vault.address, farmUserState);
975
+ }
910
976
  });
911
- const userSharesAtaAccounts = await this._connection.getMultipleAccountsInfo(userSharesAtaArray);
977
+ const [userSharesAtaAccounts, userFarmStates] = await Promise.all([
978
+ this.getConnection().getMultipleAccountsInfo(userSharesAtaArray),
979
+ lib_1.UserState.fetchMultiple(this.getConnection(), Array.from(vaultToUserFarmStateAddress.values())),
980
+ ]);
912
981
  userSharesAtaAccounts.forEach((userShareAtaAccount, index) => {
982
+ const userSharesForVault = { unstakedShares: new decimal_js_1.default(0), stakedShares: new decimal_js_1.default(0) };
913
983
  if (!userShareAtaAccount) {
914
- vaultUserShareBalance.set(vaults[index].address, new decimal_js_1.default(0));
984
+ vaultUserShareBalance.set(vaults[index].address, userSharesForVault);
915
985
  }
916
986
  else {
917
- vaultUserShareBalance.set(vaults[index].address, (0, utils_1.getTokenBalanceFromAccountInfoLamports)(userShareAtaAccount).div(new decimal_js_1.default(10).pow(vaults[index].state.sharesMintDecimals.toString())));
987
+ userSharesForVault.unstakedShares = (0, utils_1.getTokenBalanceFromAccountInfoLamports)(userShareAtaAccount).div(new decimal_js_1.default(10).pow(vaults[index].state.sharesMintDecimals.toString()));
988
+ vaultUserShareBalance.set(vaults[index].address, userSharesForVault);
918
989
  }
919
990
  });
991
+ userFarmStates.forEach((userFarmState, _) => {
992
+ if (!userFarmState) {
993
+ return;
994
+ }
995
+ const farmState = userFarmState.farmState;
996
+ // find the vault which has the farm
997
+ const vault = vaults.find((vault) => vault.state.vaultFarm.equals(farmState));
998
+ if (!vault) {
999
+ throw new Error(`Vault with farm ${farmState.toBase58()} not found`);
1000
+ }
1001
+ const shares = (0, farm_utils_1.getSharesInFarmUserPosition)(userFarmState, vault.state.sharesMintDecimals.toNumber());
1002
+ const userSharesBalance = vaultUserShareBalance.get(vault.address);
1003
+ userSharesBalance.stakedShares = shares;
1004
+ vaultUserShareBalance.set(vault.address, userSharesBalance);
1005
+ });
920
1006
  return vaultUserShareBalance;
921
1007
  }
922
1008
  /**
@@ -934,23 +1020,23 @@ class KaminoVaultClient {
934
1020
  * 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
935
1021
  * @param vault - vault to calculate tokensPerShare for
936
1022
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
937
- * @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
1023
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
938
1024
  * @returns - token per share value
939
1025
  */
940
1026
  async getTokensPerShareSingleVault(vault, slot, vaultReservesMap) {
941
- const vaultState = await vault.getState(this._connection);
1027
+ const vaultState = await vault.getState(this.getConnection());
942
1028
  if (vaultState.sharesIssued.isZero()) {
943
1029
  return new decimal_js_1.default(0);
944
1030
  }
945
1031
  const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
946
1032
  const sharesDecimal = (0, lib_1.lamportsToDecimal)(vaultState.sharesIssued.toString(), vaultState.sharesMintDecimals.toString());
947
- const holdings = await this.getVaultHoldings(vaultState, await this._connection.getSlot('confirmed'), vaultReservesState);
1033
+ const holdings = await this.getVaultHoldings(vaultState, await this.getConnection().getSlot('confirmed'), vaultReservesState);
948
1034
  return holdings.total.div(sharesDecimal);
949
1035
  }
950
1036
  /**
951
1037
  * This method calculates the token per share 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
952
- * @param vaultsOverride - a list of vaults to get the tokens per share for; if provided with state it will not fetch the state again
953
- * @param vaultReservesMap - optional parameter; a hashmap from pubkey to reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
1038
+ * @param [vaultsOverride] - a list of vaults to get the tokens per share for; if provided with state it will not fetch the state again. Optional
1039
+ * @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
954
1040
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
955
1041
  * @returns - token per share value
956
1042
  */
@@ -979,8 +1065,8 @@ class KaminoVaultClient {
979
1065
  },
980
1066
  },
981
1067
  ];
982
- const kaminoVaults = await (0, rpc_1.getProgramAccounts)(this._connection, this._kaminoVaultProgramId, accounts_1.VaultState.layout.span + 8, {
983
- commitment: this._connection.commitment ?? 'processed',
1068
+ const kaminoVaults = await (0, rpc_1.getProgramAccounts)(this.getConnection(), this._kaminoVaultProgramId, accounts_1.VaultState.layout.span + 8, {
1069
+ commitment: this.getConnection().commitment ?? 'processed',
984
1070
  filters,
985
1071
  });
986
1072
  return kaminoVaults.map((kaminoVault) => {
@@ -1037,16 +1123,17 @@ class KaminoVaultClient {
1037
1123
  * This will return an unsorted hash map of all reserves that the given vault has allocations for, toghether with the amount that can be withdrawn from each of the reserves
1038
1124
  * @param vault - the kamino vault to get available liquidity to withdraw for
1039
1125
  * @param slot - current slot
1126
+ *@param [vaultReservesMap] - a hashmap from each reserve pubkey to the reserve state
1040
1127
  * @returns an HashMap of reserves (key) with the amount available to withdraw for each (value)
1041
1128
  */
1042
- async getReserveAllocationAvailableLiquidityToWithdraw(vault, slot, reserves) {
1043
- const vaultState = await vault.getState(this._connection);
1129
+ async getReserveAllocationAvailableLiquidityToWithdraw(vault, slot, vaultReservesMap) {
1130
+ const vaultState = await vault.getState(this.getConnection());
1044
1131
  const reserveAllocationAvailableLiquidityToWithdraw = new lib_1.PubkeyHashMap();
1045
1132
  vaultState.vaultAllocationStrategy.forEach((allocationStrategy) => {
1046
1133
  if (allocationStrategy.reserve.equals(web3_js_1.PublicKey.default)) {
1047
1134
  return;
1048
1135
  }
1049
- const reserve = reserves.get(allocationStrategy.reserve);
1136
+ const reserve = vaultReservesMap.get(allocationStrategy.reserve);
1050
1137
  if (reserve === undefined) {
1051
1138
  throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
1052
1139
  }
@@ -1091,7 +1178,7 @@ class KaminoVaultClient {
1091
1178
  */
1092
1179
  async loadVaultReserves(vaultState) {
1093
1180
  const vaultReservesAddresses = this.getVaultReserves(vaultState);
1094
- const reserveAccounts = await this._connection.getMultipleAccountsInfo(vaultReservesAddresses, 'processed');
1181
+ const reserveAccounts = await this.getConnection().getMultipleAccountsInfo(vaultReservesAddresses, 'processed');
1095
1182
  const deserializedReserves = reserveAccounts.map((reserve, i) => {
1096
1183
  if (reserve === null) {
1097
1184
  // maybe reuse old here
@@ -1103,25 +1190,27 @@ class KaminoVaultClient {
1103
1190
  }
1104
1191
  return reserveAccount;
1105
1192
  });
1106
- const reservesAndOracles = await (0, lib_1.getTokenOracleData)(this._connection, deserializedReserves);
1193
+ const reservesAndOracles = await (0, lib_1.getTokenOracleData)(this.getConnection(), deserializedReserves);
1107
1194
  const kaminoReserves = new lib_1.PubkeyHashMap();
1108
1195
  reservesAndOracles.forEach(([reserve, oracle], index) => {
1109
1196
  if (!oracle) {
1110
1197
  throw Error(`Could not find oracle for ${(0, utils_1.parseTokenSymbol)(reserve.config.tokenInfo.name)} reserve`);
1111
1198
  }
1112
- const kaminoReserve = lib_1.KaminoReserve.initialize(reserveAccounts[index], vaultReservesAddresses[index], reserve, oracle, this._connection, this.recentSlotDurationMs);
1199
+ const kaminoReserve = lib_1.KaminoReserve.initialize(reserveAccounts[index], vaultReservesAddresses[index], reserve, oracle, this.getConnection(), this.recentSlotDurationMs);
1113
1200
  kaminoReserves.set(kaminoReserve.address, kaminoReserve);
1114
1201
  });
1115
1202
  return kaminoReserves;
1116
1203
  }
1117
1204
  /**
1118
- * This will retrieve all the tokens that can be use as collateral by the users who borrow the token in the vault alongside details about the min and max loan to value ratio
1205
+ * This will retrieve all the tokens that can be used as collateral by the users who borrow the token in the vault alongside details about the min and max loan to value ratio
1119
1206
  * @param vaultState - the vault state to load reserves for
1120
- *
1207
+ * @param slot - current slot
1208
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1209
+ * @param [kaminoMarkets] - a list of all the kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
1121
1210
  * @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
1122
1211
  */
1123
- async getVaultCollaterals(vaultState, slot, vaultReserves, kaminoMarkets) {
1124
- const vaultReservesStateMap = vaultReserves ? vaultReserves : await this.loadVaultReserves(vaultState);
1212
+ async getVaultCollaterals(vaultState, slot, vaultReservesMap, kaminoMarkets) {
1213
+ const vaultReservesStateMap = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
1125
1214
  const vaultReservesState = Array.from(vaultReservesStateMap.values());
1126
1215
  const vaultCollateralsPerReserve = new lib_1.PubkeyHashMap();
1127
1216
  for (const reserve of vaultReservesState) {
@@ -1131,7 +1220,7 @@ class KaminoVaultClient {
1131
1220
  lendingMarket = kaminoMarkets?.find((market) => reserve.state.lendingMarket.equals(new web3_js_1.PublicKey(market.address)));
1132
1221
  }
1133
1222
  if (!lendingMarket) {
1134
- const fetchedLendingMarket = await lib_1.KaminoMarket.load(this._connection, reserve.state.lendingMarket, slot);
1223
+ const fetchedLendingMarket = await lib_1.KaminoMarket.load(this.getConnection(), reserve.state.lendingMarket, slot);
1135
1224
  if (!fetchedLendingMarket) {
1136
1225
  throw Error(`Could not fetch lending market ${reserve.state.lendingMarket.toBase58()}`);
1137
1226
  }
@@ -1171,8 +1260,8 @@ class KaminoVaultClient {
1171
1260
  * 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
1172
1261
  * @param vault - the kamino vault to get available liquidity to withdraw for
1173
1262
  * @param slot - current slot
1174
- * @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
1175
- * @returns an VaultHoldings object
1263
+ * @param vaultReserves - a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1264
+ * @returns an VaultHoldings object representing the amount available (uninvested) in vault, total amount invested in reseves and a breakdown of the amount invested in each reserve
1176
1265
  */
1177
1266
  async getVaultHoldings(vault, slot, vaultReserves) {
1178
1267
  const vaultHoldings = {
@@ -1209,12 +1298,12 @@ class KaminoVaultClient {
1209
1298
  * 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
1210
1299
  * @param vault - the kamino vault to get available liquidity to withdraw for
1211
1300
  * @param slot - current slot
1212
- * @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
1213
1301
  * @param price - the price of the token in the vault (e.g. USDC)
1302
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1214
1303
  * @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
1215
1304
  */
1216
- async getVaultHoldingsWithPrice(vault, slot, price, vaultReserves) {
1217
- const holdings = await this.getVaultHoldings(vault, slot, vaultReserves);
1305
+ async getVaultHoldingsWithPrice(vault, slot, price, vaultReservesMap) {
1306
+ const holdings = await this.getVaultHoldings(vault, slot, vaultReservesMap);
1218
1307
  const investedInReservesUSD = new lib_1.PubkeyHashMap();
1219
1308
  holdings.investedInReserves.forEach((amount, reserve) => {
1220
1309
  investedInReservesUSD.set(reserve, amount.mul(price));
@@ -1232,12 +1321,12 @@ class KaminoVaultClient {
1232
1321
  * @param vault - the kamino vault to get available liquidity to withdraw for
1233
1322
  * @param slot - current slot
1234
1323
  * @param price - the price of the token in the vault (e.g. USDC)
1235
- * @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
1236
- * @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
1237
- * @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
1324
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1325
+ * @param [kaminoMarkets] - a list of all kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
1326
+ * @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD
1238
1327
  */
1239
- async getVaultOverview(vault, slot, price, vaultReserves, kaminoMarkets) {
1240
- const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1328
+ async getVaultOverview(vault, slot, price, vaultReservesMap, kaminoMarkets) {
1329
+ const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vault);
1241
1330
  const vaultHoldingsWithUSDValuePromise = await this.getVaultHoldingsWithPrice(vault, slot, price, vaultReservesState);
1242
1331
  const vaultTheoreticalAPYPromise = await this.getVaultTheoreticalAPY(vault, slot, vaultReservesState);
1243
1332
  const totalInvestedAndBorrowedPromise = await this.getTotalBorrowedAndInvested(vault, slot, vaultReservesState);
@@ -1265,11 +1354,11 @@ class KaminoVaultClient {
1265
1354
  * This will return an aggregation of the current state of the vault with all the invested amounts and the utilization ratio of the vault
1266
1355
  * @param vault - the kamino vault to get available liquidity to withdraw for
1267
1356
  * @param slot - current slot
1268
- * @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
1357
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1269
1358
  * @returns an VaultReserveTotalBorrowedAndInvested object with the total invested amount, total borrowed amount and the utilization ratio of the vault
1270
1359
  */
1271
- async getTotalBorrowedAndInvested(vault, slot, vaultReserves) {
1272
- const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1360
+ async getTotalBorrowedAndInvested(vault, slot, vaultReservesMap) {
1361
+ const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vault);
1273
1362
  const totalAvailable = (0, lib_1.lamportsToDecimal)(new decimal_js_1.default(vault.tokenAvailable.toString()), new decimal_js_1.default(vault.tokenMintDecimals.toString()));
1274
1363
  let totalInvested = new decimal_js_1.default(0);
1275
1364
  let totalBorrowed = new decimal_js_1.default(0);
@@ -1302,7 +1391,7 @@ class KaminoVaultClient {
1302
1391
  * This will return an overview of each reserve that is part of the vault allocation
1303
1392
  * @param vault - the kamino vault to get available liquidity to withdraw for
1304
1393
  * @param slot - current slot
1305
- * @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
1394
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1306
1395
  * @returns a hashmap from vault reserve pubkey to ReserveOverview object
1307
1396
  */
1308
1397
  async getVaultReservesDetails(vault, slot, vaultReserves) {
@@ -1333,11 +1422,11 @@ class KaminoVaultClient {
1333
1422
  * 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 as ratio; for percentage it needs multiplication by 100
1334
1423
  * @param vault - the kamino vault to get APY for
1335
1424
  * @param slot - current slot
1336
- * @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
1425
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1337
1426
  * @returns APY for the vault
1338
1427
  */
1339
- async getVaultTheoreticalAPY(vault, slot, vaultReserves) {
1340
- const vaultReservesState = vaultReserves ? vaultReserves : await this.loadVaultReserves(vault);
1428
+ async getVaultTheoreticalAPY(vault, slot, vaultReservesMap) {
1429
+ const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vault);
1341
1430
  let totalWeights = new decimal_js_1.default(0);
1342
1431
  let totalAPY = new decimal_js_1.default(0);
1343
1432
  vault.vaultAllocationStrategy.forEach((allocationStrategy) => {
@@ -1362,7 +1451,7 @@ class KaminoVaultClient {
1362
1451
  /**
1363
1452
  * Retrive the total amount of interest earned by the vault since its inception, including what was charged as fees
1364
1453
  * @param vaultState the kamino vault state to get total net yield for
1365
- * @returns a decimal representing the net number of tokens earned by the vault since its inception
1454
+ * @returns a Decimal representing the net number of tokens earned by the vault since its inception
1366
1455
  */
1367
1456
  async getVaultCumulativeInterest(vaultState) {
1368
1457
  const netYieldLamports = new fraction_1.Fraction(vaultState.cumulativeEarnedInterestSf).toDecimal();
@@ -1371,15 +1460,16 @@ class KaminoVaultClient {
1371
1460
  /**
1372
1461
  * Simulate the current holdings of the vault and the earned interest
1373
1462
  * @param vaultState the kamino vault state to get simulated holdings and earnings for
1374
- * @param vaultReserves optional; the state of the reserves in the vault allocation
1463
+ * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
1464
+ * @param [currentSlot] - the current slot. Optional. If not provided it will fetch the current slot
1375
1465
  * @returns a struct of simulated vault holdings and earned interest
1376
1466
  */
1377
- async calculateSimulatedHoldingsWithInterest(vaultState, vaultReserves) {
1467
+ async calculateSimulatedHoldingsWithInterest(vaultState, vaultReservesMap, currentSlot) {
1378
1468
  const latestUpdateTs = vaultState.lastFeeChargeTimestamp.toNumber();
1379
1469
  const lastUpdateSlot = latestUpdateTs / this.recentSlotDurationMs;
1380
- const currentSlot = await this._connection.getSlot('confirmed');
1381
- const lastUpdateHoldingsPromise = this.getVaultHoldings(vaultState, lastUpdateSlot, vaultReserves);
1382
- const currentHoldingsPromise = this.getVaultHoldings(vaultState, currentSlot, vaultReserves);
1470
+ const slot = currentSlot ? currentSlot : await this.getConnection().getSlot('confirmed');
1471
+ const lastUpdateHoldingsPromise = this.getVaultHoldings(vaultState, lastUpdateSlot, vaultReservesMap);
1472
+ const currentHoldingsPromise = this.getVaultHoldings(vaultState, slot, vaultReservesMap);
1383
1473
  const [lastUpdateHoldings, currentHoldings] = await Promise.all([
1384
1474
  lastUpdateHoldingsPromise,
1385
1475
  currentHoldingsPromise,
@@ -1393,11 +1483,12 @@ class KaminoVaultClient {
1393
1483
  /**
1394
1484
  * Simulate the current holdings and compute the fees that would be charged
1395
1485
  * @param vaultState the kamino vault state to get simulated fees for
1396
- * @param simulatedCurrentHoldingsWithInterest optional; the simulated holdings and interest earned by the vault
1397
- * @returns a struct of simulated management and interest fees
1486
+ * @param [simulatedCurrentHoldingsWithInterest] the simulated holdings and interest earned by the vault. Optional
1487
+ * @param [currentTimestamp] the current timestamp. Optional. If not provided it will fetch the current unix timestamp
1488
+ * @returns a VaultFees struct of simulated management and interest fees
1398
1489
  */
1399
- async calculateSimulatedFees(vaultState, simulatedCurrentHoldingsWithInterest) {
1400
- const timestampNow = new Date().getTime();
1490
+ async calculateSimulatedFees(vaultState, simulatedCurrentHoldingsWithInterest, currentTimestamp) {
1491
+ const timestampNow = currentTimestamp ? currentTimestamp : Date.now();
1401
1492
  const timestampLastUpdate = vaultState.lastFeeChargeTimestamp.toNumber();
1402
1493
  const timeElapsed = timestampNow - timestampLastUpdate;
1403
1494
  const simulatedCurrentHoldings = simulatedCurrentHoldingsWithInterest
@@ -1445,6 +1536,10 @@ class KaminoVault {
1445
1536
  }
1446
1537
  return this.state;
1447
1538
  }
1539
+ async hasFarm(connection) {
1540
+ const state = await this.getState(connection);
1541
+ return !state.vaultFarm.equals(web3_js_1.PublicKey.default);
1542
+ }
1448
1543
  }
1449
1544
  exports.KaminoVault = KaminoVault;
1450
1545
  /**