@kamino-finance/klend-sdk 5.4.1 → 5.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kamino-finance/klend-sdk",
3
- "version": "5.4.1",
3
+ "version": "5.4.3",
4
4
  "description": "Typescript SDK for interacting with the Kamino Lending (klend) protocol",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2023,7 +2023,7 @@ export class KaminoAction {
2023
2023
  const borrowReservesReferrerTokenStates = borrowReservesList
2024
2024
  .map((reserve) => {
2025
2025
  if (this.referrer.equals(PublicKey.default)) {
2026
- return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: true };
2026
+ return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: false };
2027
2027
  }
2028
2028
  const referrerTokenStateAddress = referrerTokenStatePda(this.referrer, reserve, this.kaminoMarket.programId)[0];
2029
2029
  return { pubkey: referrerTokenStateAddress, isSigner: false, isWritable: true };
@@ -2081,7 +2081,7 @@ export class KaminoAction {
2081
2081
  const borrowReservesReferrerTokenStates = borrowReservesList
2082
2082
  .map((reserve) => {
2083
2083
  if (this.referrer.equals(PublicKey.default)) {
2084
- return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: true };
2084
+ return { pubkey: this.kaminoMarket.programId, isSigner: false, isWritable: false };
2085
2085
  }
2086
2086
  const reserveState = this.kaminoMarket.getReserveByAddress(reserve)!;
2087
2087
  const referrerTokenStateAddress = referrerTokenStatePda(
@@ -676,8 +676,8 @@ export class KaminoVaultClient {
676
676
  const kaminoVault = new KaminoVault(vault.address, vaultState, vault.programId);
677
677
 
678
678
  // if the vault has allocations withdraw otherwise wtihdraw from available ix
679
- const vaultAllocation = vaultState.vaultAllocationStrategy.find(
680
- (allocation) => ~allocation.reserve.equals(PublicKey.default)
679
+ const vaultAllocation = vaultState.vaultAllocationStrategy.find((allocation) =>
680
+ allocation.reserve.equals(PublicKey.default)
681
681
  );
682
682
 
683
683
  if (vaultAllocation) {
@@ -735,18 +735,25 @@ export class KaminoVaultClient {
735
735
  },
736
736
  ]);
737
737
 
738
- const tokensToWithdraw = shareAmount.mul(await this.getTokensPerShareSingleVault(vault, slot));
738
+ const shareLamportsToWithdraw = collToLamportsDecimal(shareAmount, vaultState.sharesMintDecimals.toNumber());
739
+ const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
740
+ const sharesPerToken = new Decimal(1).div(tokensPerShare);
741
+ const tokensToWithdraw = shareLamportsToWithdraw.mul(tokensPerShare);
739
742
  let tokenLeftToWithdraw = tokensToWithdraw;
743
+ const availableTokens = new Decimal(vaultState.tokenAvailable.toString());
744
+ tokenLeftToWithdraw = tokenLeftToWithdraw.sub(availableTokens);
740
745
 
741
- tokenLeftToWithdraw = tokenLeftToWithdraw.sub(new Decimal(vaultState.tokenAvailable.toString()));
746
+ type ReserveWithTokensToWithdraw = { reserve: PublicKey; shares: Decimal };
742
747
 
743
- const reservesToWithdraw: PublicKey[] = [];
744
- const amountToWithdraw: Decimal[] = [];
745
- amountToWithdraw.push(new Decimal(vaultState.tokenAvailable.toString()));
748
+ const reserveWithSharesAmountToWithdraw: ReserveWithTokensToWithdraw[] = [];
749
+ let isFirstWithdraw = true;
746
750
 
747
751
  if (tokenLeftToWithdraw.lte(0)) {
748
752
  // Availabe enough to withdraw all - using first reserve as it does not matter
749
- reservesToWithdraw.push(vaultState.vaultAllocationStrategy[0].reserve);
753
+ reserveWithSharesAmountToWithdraw.push({
754
+ reserve: vaultState.vaultAllocationStrategy[0].reserve,
755
+ shares: shareLamportsToWithdraw,
756
+ });
750
757
  } else {
751
758
  // Get decreasing order sorted available liquidity to withdraw from each reserve allocated to
752
759
  const reserveAllocationAvailableLiquidityToWithdraw = await this.getReserveAllocationAvailableLiquidityToWithdraw(
@@ -755,15 +762,22 @@ export class KaminoVaultClient {
755
762
  vaultReservesState
756
763
  );
757
764
  // sort
758
- const reserveAllocationAvailableLiquidityToWithdrawSorted = new PubkeyHashMap(
759
- [...reserveAllocationAvailableLiquidityToWithdraw.entries()].sort((a, b) => b[1].sub(a[1]).toNumber())
760
- );
765
+ const reserveAllocationAvailableLiquidityToWithdrawSorted = [
766
+ ...reserveAllocationAvailableLiquidityToWithdraw.entries(),
767
+ ].sort((a, b) => b[1].sub(a[1]).toNumber());
761
768
 
762
- reserveAllocationAvailableLiquidityToWithdrawSorted.forEach((availableLiquidityToWithdraw, key) => {
769
+ reserveAllocationAvailableLiquidityToWithdrawSorted.forEach(([key, availableLiquidityToWithdraw], _) => {
763
770
  if (tokenLeftToWithdraw.gt(0)) {
764
- reservesToWithdraw.push(key);
765
- tokenLeftToWithdraw = tokenLeftToWithdraw.sub(availableLiquidityToWithdraw);
766
- amountToWithdraw.push(Decimal.min(tokenLeftToWithdraw, availableLiquidityToWithdraw));
771
+ let tokensToWithdrawFromReserve = Decimal.min(tokenLeftToWithdraw, availableLiquidityToWithdraw);
772
+ if (isFirstWithdraw) {
773
+ tokensToWithdrawFromReserve = tokensToWithdrawFromReserve.add(availableTokens);
774
+ isFirstWithdraw = false;
775
+ }
776
+ // round up to the nearest integer the shares to withdraw
777
+ const sharesToWithdrawFromReserve = tokensToWithdrawFromReserve.mul(sharesPerToken).ceil();
778
+ reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: sharesToWithdrawFromReserve });
779
+
780
+ tokenLeftToWithdraw = tokenLeftToWithdraw.sub(tokensToWithdrawFromReserve);
767
781
  }
768
782
  });
769
783
  }
@@ -771,26 +785,35 @@ export class KaminoVaultClient {
771
785
  const withdrawIxns: TransactionInstruction[] = [];
772
786
  withdrawIxns.push(createAtaIx);
773
787
 
774
- reservesToWithdraw.forEach((reserve, index) => {
775
- const reserveState = vaultReservesState.get(reserve);
788
+ // let sharesLeftToWithdraw = shareAmount;
789
+ for (let reserveIndex = 0; reserveIndex < reserveWithSharesAmountToWithdraw.length; reserveIndex++) {
790
+ const reserveWithTokens = reserveWithSharesAmountToWithdraw[reserveIndex];
791
+ const reserveState = vaultReservesState.get(reserveWithTokens.reserve);
776
792
  if (reserveState === undefined) {
777
- throw new Error(`Reserve ${reserve.toBase58()} not found in vault reserves map`);
793
+ throw new Error(`Reserve ${reserveWithTokens.reserve.toBase58()} not found in vault reserves map`);
778
794
  }
779
-
780
795
  const marketAddress = reserveState.state.lendingMarket;
796
+
797
+ const isLastWithdraw = reserveIndex === reserveWithSharesAmountToWithdraw.length - 1;
798
+ // if it is not last withdraw it means that we can pass all shares as we are withdrawing everything from that reserve
799
+ let sharesToWithdraw = shareAmount;
800
+ if (isLastWithdraw) {
801
+ sharesToWithdraw = reserveWithTokens.shares;
802
+ }
803
+
781
804
  const withdrawFromReserveIx = this.withdrawIxn(
782
805
  user,
783
806
  vault,
784
807
  vaultState,
785
808
  marketAddress,
786
- { address: reserve, state: reserveState.state },
809
+ { address: reserveWithTokens.reserve, state: reserveState.state },
787
810
  userSharesAta,
788
811
  userTokenAta,
789
- amountToWithdraw[index],
812
+ sharesToWithdraw,
790
813
  vaultReservesState
791
814
  );
792
815
  withdrawIxns.push(withdrawFromReserveIx);
793
- });
816
+ }
794
817
 
795
818
  return withdrawIxns;
796
819
  }
@@ -1484,18 +1507,23 @@ export class KaminoVaultClient {
1484
1507
 
1485
1508
  const reserveAllocationAvailableLiquidityToWithdraw = new PubkeyHashMap<PublicKey, Decimal>();
1486
1509
  vaultState.vaultAllocationStrategy.forEach((allocationStrategy) => {
1510
+ if (allocationStrategy.reserve.equals(PublicKey.default)) {
1511
+ return;
1512
+ }
1487
1513
  const reserve = reserves.get(allocationStrategy.reserve);
1488
1514
  if (reserve === undefined) {
1489
1515
  throw new Error(`Reserve ${allocationStrategy.reserve.toBase58()} not found`);
1490
1516
  }
1491
- const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(
1492
- slot,
1493
- new Fraction(reserve.state.liquidity.absoluteReferralRateSf)
1517
+ let referralFeeBps = 0;
1518
+ const denominator = reserve.state.config.protocolTakeRatePct / 100;
1519
+ if (denominator > 0) {
1520
+ referralFeeBps = new Fraction(reserve.state.liquidity.absoluteReferralRateSf)
1494
1521
  .toDecimal()
1495
- .div(reserve.state.config.protocolTakeRatePct / 100)
1522
+ .div(denominator)
1496
1523
  .floor()
1497
- .toNumber()
1498
- );
1524
+ .toNumber();
1525
+ }
1526
+ const reserveCollExchangeRate = reserve.getEstimatedCollateralExchangeRate(slot, referralFeeBps);
1499
1527
  const reserveAllocationLiquidityAmount = new Decimal(allocationStrategy.ctokenAllocation.toString()).div(
1500
1528
  reserveCollExchangeRate
1501
1529
  );
@@ -649,7 +649,7 @@ async function main() {
649
649
  const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
650
650
  const instructions = await kaminoManager.depositToVaultIxs(env.payer.publicKey, kaminoVault, amount);
651
651
 
652
- const depositSig = await processTxn(env.client, env.payer, instructions, mode, 2500, []);
652
+ const depositSig = await processTxn(env.client, env.payer, instructions, mode, 2500, [], 800_000);
653
653
 
654
654
  mode === 'execute' && console.log('User deposit:', depositSig);
655
655
  });
@@ -675,14 +675,14 @@ async function main() {
675
675
  const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
676
676
 
677
677
  const kaminoVault = new KaminoVault(vaultAddress, undefined, env.kVaultProgramId);
678
- const instructions = await kaminoManager.withdrawFromVaultIxs(
678
+ const withdrawIxs = await kaminoManager.withdrawFromVaultIxs(
679
679
  env.payer.publicKey,
680
680
  kaminoVault,
681
681
  new Decimal(amount),
682
682
  await env.connection.getSlot('confirmed')
683
683
  );
684
684
 
685
- const depositSig = await processTxn(env.client, env.payer, instructions, mode, 2500, []);
685
+ const depositSig = await processTxn(env.client, env.payer, withdrawIxs, mode, 2500, [], 800_000);
686
686
 
687
687
  mode === 'execute' && console.log('User withdraw:', depositSig);
688
688
  });
@@ -754,7 +754,7 @@ async function main() {
754
754
  kaminoVault,
755
755
  reserveWithAddress
756
756
  );
757
- const investReserveSig = await processTxn(env.client, env.payer, instructions, mode, 2500, [], 800_000);
757
+ const investReserveSig = await processTxn(env.client, env.payer, instructions, mode, 2500, [], 400_000);
758
758
 
759
759
  mode === 'execute' && console.log('Reserve invested:', investReserveSig);
760
760
  });
@@ -926,6 +926,17 @@ async function main() {
926
926
  console.log('all vaults', allVaults);
927
927
  });
928
928
 
929
+ commands.command('get-all-vaults-pks').action(async () => {
930
+ const env = initializeClient(false, false);
931
+ const kaminoManager = new KaminoManager(env.connection, env.kLendProgramId, env.kVaultProgramId);
932
+
933
+ const allVaults = await kaminoManager.getAllVaults();
934
+ console.log(
935
+ 'all vaults',
936
+ allVaults.map((vault) => vault.address.toBase58())
937
+ );
938
+ });
939
+
929
940
  commands
930
941
  .command('get-simulated-interest-and-fees')
931
942
  .requiredOption('--vault <string>', 'Vault address')
@@ -231,7 +231,7 @@ export class VaultState {
231
231
  }
232
232
 
233
233
  static decode(data: Buffer): VaultState {
234
- if (!data.slice(0, 8).equals(VaultState.discriminator)) {
234
+ if (!VaultState.discriminator.equals(data.slice(0, 8))) {
235
235
  throw new Error("invalid account discriminator")
236
236
  }
237
237