@kamino-finance/klend-sdk 7.3.1 → 7.3.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.
@@ -49,9 +49,6 @@ import {
49
49
  buy,
50
50
  BuyAccounts,
51
51
  BuyArgs,
52
- deposit,
53
- DepositAccounts,
54
- DepositArgs,
55
52
  giveUpPendingFees,
56
53
  GiveUpPendingFeesAccounts,
57
54
  GiveUpPendingFeesArgs,
@@ -73,9 +70,6 @@ import {
73
70
  updateVaultConfig,
74
71
  UpdateVaultConfigAccounts,
75
72
  UpdateVaultConfigArgs,
76
- withdraw,
77
- WithdrawAccounts,
78
- WithdrawArgs,
79
73
  withdrawFromAvailable,
80
74
  WithdrawFromAvailableAccounts,
81
75
  WithdrawFromAvailableArgs,
@@ -1230,92 +1224,6 @@ export class KaminoVaultClient {
1230
1224
  ]);
1231
1225
  createAtasIxs.push(createSharesAtaIxs);
1232
1226
 
1233
- const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
1234
- const depositAccounts: DepositAccounts = {
1235
- user: user,
1236
- vaultState: vault.address,
1237
- tokenVault: vaultState.tokenVault,
1238
- tokenMint: vaultState.tokenMint,
1239
- baseVaultAuthority: vaultState.baseVaultAuthority,
1240
- sharesMint: vaultState.sharesMint,
1241
- userTokenAta: userTokenAta,
1242
- userSharesAta: userSharesAta,
1243
- tokenProgram: tokenProgramID,
1244
- klendProgram: this._kaminoLendProgramId,
1245
- sharesTokenProgram: TOKEN_PROGRAM_ADDRESS,
1246
- eventAuthority: eventAuthority,
1247
- program: this._kaminoVaultProgramId,
1248
- };
1249
-
1250
- const depositArgs: DepositArgs = {
1251
- maxAmount: new BN(
1252
- numberToLamportsDecimal(tokenAmount, vaultState.tokenMintDecimals.toNumber()).floor().toString()
1253
- ),
1254
- };
1255
-
1256
- let depositIx = deposit(depositArgs, depositAccounts, undefined, this._kaminoVaultProgramId);
1257
-
1258
- const vaultReserves = this.getVaultReserves(vaultState);
1259
-
1260
- const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
1261
- depositIx = this.appendRemainingAccountsForVaultReserves(depositIx, vaultReserves, vaultReservesState);
1262
-
1263
- const depositIxs: DepositIxs = {
1264
- depositIxs: [...createAtasIxs, depositIx, ...closeAtasIxs],
1265
- stakeInFarmIfNeededIxs: [],
1266
- };
1267
-
1268
- // if there is no farm, we can return the deposit instructions, otherwise include the stake ix in the response
1269
- if (!(await vault.hasFarm())) {
1270
- return depositIxs;
1271
- }
1272
-
1273
- // if there is a farm, stake the shares
1274
- const stakeSharesIxs = await this.stakeSharesIxs(user, vault, undefined, farmState);
1275
- depositIxs.stakeInFarmIfNeededIxs = stakeSharesIxs;
1276
- return depositIxs;
1277
- }
1278
-
1279
- // todo (silviu): after all tx indexing works for buy/sell ixs remove this function and use the buyIx in the deposit function above
1280
- async buySharesIxs(
1281
- user: TransactionSigner,
1282
- vault: KaminoVault,
1283
- tokenAmount: Decimal,
1284
- vaultReservesMap?: Map<Address, KaminoReserve>,
1285
- farmState?: FarmState
1286
- ): Promise<DepositIxs> {
1287
- const vaultState = await vault.getState();
1288
-
1289
- const tokenProgramID = vaultState.tokenProgram;
1290
- const userTokenAta = await getAssociatedTokenAddress(vaultState.tokenMint, user.address, tokenProgramID);
1291
- const createAtasIxs: Instruction[] = [];
1292
- const closeAtasIxs: Instruction[] = [];
1293
- if (vaultState.tokenMint === WRAPPED_SOL_MINT) {
1294
- const [{ ata: wsolAta, createAtaIx: createWsolAtaIxn }] = await createAtasIdempotent(user, [
1295
- {
1296
- mint: WRAPPED_SOL_MINT,
1297
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
1298
- },
1299
- ]);
1300
- createAtasIxs.push(createWsolAtaIxn);
1301
- const transferWsolIxs = getTransferWsolIxs(
1302
- user,
1303
- wsolAta,
1304
- lamports(
1305
- BigInt(numberToLamportsDecimal(tokenAmount, vaultState.tokenMintDecimals.toNumber()).ceil().toString())
1306
- )
1307
- );
1308
- createAtasIxs.push(...transferWsolIxs);
1309
- }
1310
-
1311
- const [{ ata: userSharesAta, createAtaIx: createSharesAtaIxs }] = await createAtasIdempotent(user, [
1312
- {
1313
- mint: vaultState.sharesMint,
1314
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
1315
- },
1316
- ]);
1317
- createAtasIxs.push(createSharesAtaIxs);
1318
-
1319
1227
  const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
1320
1228
  const buyAccounts: BuyAccounts = {
1321
1229
  user: user,
@@ -1531,135 +1439,6 @@ export class KaminoVaultClient {
1531
1439
  return withdrawIxs;
1532
1440
  }
1533
1441
 
1534
- async sellSharesIxs(
1535
- user: TransactionSigner,
1536
- vault: KaminoVault,
1537
- shareAmountToWithdraw: Decimal,
1538
- slot: Slot,
1539
- vaultReservesMap?: Map<Address, KaminoReserve>,
1540
- farmState?: FarmState
1541
- ): Promise<WithdrawIxs> {
1542
- const vaultState = await vault.getState();
1543
- const hasFarm = await vault.hasFarm();
1544
-
1545
- const withdrawIxs: WithdrawIxs = {
1546
- unstakeFromFarmIfNeededIxs: [],
1547
- withdrawIxs: [],
1548
- postWithdrawIxs: [],
1549
- };
1550
-
1551
- // compute the total shares the user has (in ATA + in farm) and check if they want to withdraw everything or just a part
1552
- let userSharesAtaBalance = new Decimal(0);
1553
- const userSharesAta = await getAssociatedTokenAddress(vaultState.sharesMint, user.address);
1554
- const userSharesAtaState = await fetchMaybeToken(this.getConnection(), userSharesAta);
1555
- if (userSharesAtaState.exists) {
1556
- const userSharesAtaBalanceInLamports = getTokenBalanceFromAccountInfoLamports(userSharesAtaState);
1557
- userSharesAtaBalance = userSharesAtaBalanceInLamports.div(
1558
- new Decimal(10).pow(vaultState.sharesMintDecimals.toString())
1559
- );
1560
- }
1561
-
1562
- let userSharesInFarm = new Decimal(0);
1563
- if (hasFarm) {
1564
- userSharesInFarm = await getUserSharesInTokensStakedInFarm(
1565
- this.getConnection(),
1566
- user.address,
1567
- vaultState.vaultFarm,
1568
- vaultState.sharesMintDecimals.toNumber()
1569
- );
1570
- }
1571
-
1572
- let sharesToWithdraw = shareAmountToWithdraw;
1573
- const totalUserShares = userSharesAtaBalance.add(userSharesInFarm);
1574
- let withdrawAllShares = false;
1575
- if (sharesToWithdraw.gt(totalUserShares)) {
1576
- sharesToWithdraw = new Decimal(U64_MAX.toString()).div(
1577
- new Decimal(10).pow(vaultState.sharesMintDecimals.toString())
1578
- );
1579
- withdrawAllShares = true;
1580
- }
1581
-
1582
- // if not enough shares in ATA unstake from farm
1583
- const sharesInAtaAreEnoughForWithdraw = sharesToWithdraw.lte(userSharesAtaBalance);
1584
- if (hasFarm && !sharesInAtaAreEnoughForWithdraw && userSharesInFarm.gt(0)) {
1585
- // if we need to unstake we need to make sure share ata is created
1586
- const [{ createAtaIx }] = await createAtasIdempotent(user, [
1587
- {
1588
- mint: vaultState.sharesMint,
1589
- tokenProgram: TOKEN_PROGRAM_ADDRESS,
1590
- },
1591
- ]);
1592
- withdrawIxs.unstakeFromFarmIfNeededIxs.push(createAtaIx);
1593
- let shareLamportsToWithdraw = new Decimal(U64_MAX.toString());
1594
- if (!withdrawAllShares) {
1595
- const sharesToWithdrawFromFarm = sharesToWithdraw.sub(userSharesAtaBalance);
1596
- shareLamportsToWithdraw = collToLamportsDecimal(
1597
- sharesToWithdrawFromFarm,
1598
- vaultState.sharesMintDecimals.toNumber()
1599
- );
1600
- }
1601
- const unstakeAndWithdrawFromFarmIxs = await getFarmUnstakeAndWithdrawIxs(
1602
- this.getConnection(),
1603
- user,
1604
- shareLamportsToWithdraw,
1605
- vaultState.vaultFarm,
1606
- farmState
1607
- );
1608
- withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.unstakeIx);
1609
- withdrawIxs.unstakeFromFarmIfNeededIxs.push(unstakeAndWithdrawFromFarmIxs.withdrawIx);
1610
- }
1611
-
1612
- // if the vault has allocations withdraw otherwise wtihdraw from available ix
1613
- const vaultAllocation = vaultState.vaultAllocationStrategy.find(
1614
- (allocation) => allocation.reserve !== DEFAULT_PUBLIC_KEY
1615
- );
1616
-
1617
- if (vaultAllocation) {
1618
- const withdrawFromVaultIxs = await this.sellSharesWithReserveIxs(
1619
- user,
1620
- vault,
1621
- sharesToWithdraw,
1622
- totalUserShares,
1623
- slot,
1624
- vaultReservesMap
1625
- );
1626
- withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
1627
- } else {
1628
- const withdrawFromVaultIxs = await this.withdrawFromAvailableIxs(user, vault, sharesToWithdraw);
1629
- withdrawIxs.withdrawIxs = withdrawFromVaultIxs;
1630
- }
1631
-
1632
- // if the vault is for SOL return the ix to unwrap the SOL
1633
- if (vaultState.tokenMint === WRAPPED_SOL_MINT) {
1634
- const userWsolAta = await getAssociatedTokenAddress(WRAPPED_SOL_MINT, user.address);
1635
- const unwrapIx = getCloseAccountInstruction(
1636
- {
1637
- account: userWsolAta,
1638
- owner: user,
1639
- destination: user.address,
1640
- },
1641
- { programAddress: TOKEN_PROGRAM_ADDRESS }
1642
- );
1643
- withdrawIxs.postWithdrawIxs.push(unwrapIx);
1644
- }
1645
-
1646
- // if we burn all of user's shares close its shares ATA
1647
- const burnAllUserShares = sharesToWithdraw.gt(totalUserShares);
1648
- if (burnAllUserShares) {
1649
- const closeAtaIx = getCloseAccountInstruction(
1650
- {
1651
- account: userSharesAta,
1652
- owner: user,
1653
- destination: user.address,
1654
- },
1655
- { programAddress: TOKEN_PROGRAM_ADDRESS }
1656
- );
1657
- withdrawIxs.postWithdrawIxs.push(closeAtaIx);
1658
- }
1659
-
1660
- return withdrawIxs;
1661
- }
1662
-
1663
1442
  private async withdrawFromAvailableIxs(
1664
1443
  user: TransactionSigner,
1665
1444
  vault: KaminoVault,
@@ -1688,115 +1467,6 @@ export class KaminoVaultClient {
1688
1467
  return [createAtaIx, withdrawFromAvailableIxn];
1689
1468
  }
1690
1469
 
1691
- private async sellSharesWithReserveIxs(
1692
- user: TransactionSigner,
1693
- vault: KaminoVault,
1694
- shareAmount: Decimal,
1695
- allUserShares: Decimal,
1696
- slot: Slot,
1697
- vaultReservesMap?: Map<Address, KaminoReserve>
1698
- ): Promise<Instruction[]> {
1699
- const vaultState = await vault.getState();
1700
-
1701
- const vaultReservesState = vaultReservesMap ? vaultReservesMap : await this.loadVaultReserves(vaultState);
1702
- const userSharesAta = await getAssociatedTokenAddress(vaultState.sharesMint, user.address);
1703
- const [{ ata: userTokenAta, createAtaIx }] = await createAtasIdempotent(user, [
1704
- {
1705
- mint: vaultState.tokenMint,
1706
- tokenProgram: vaultState.tokenProgram,
1707
- },
1708
- ]);
1709
-
1710
- const withdrawAllShares = shareAmount.gte(allUserShares);
1711
- const actualSharesToWithdraw = shareAmount.lte(allUserShares) ? shareAmount : allUserShares;
1712
- const shareLamportsToWithdraw = collToLamportsDecimal(
1713
- actualSharesToWithdraw,
1714
- vaultState.sharesMintDecimals.toNumber()
1715
- );
1716
- const tokensPerShare = await this.getTokensPerShareSingleVault(vault, slot);
1717
- const sharesPerToken = new Decimal(1).div(tokensPerShare);
1718
- const tokensToWithdraw = shareLamportsToWithdraw.mul(tokensPerShare);
1719
- let tokenLeftToWithdraw = tokensToWithdraw;
1720
- const availableTokens = new Decimal(vaultState.tokenAvailable.toString());
1721
- tokenLeftToWithdraw = tokenLeftToWithdraw.sub(availableTokens);
1722
-
1723
- type ReserveWithTokensToWithdraw = { reserve: Address; shares: Decimal };
1724
-
1725
- const reserveWithSharesAmountToWithdraw: ReserveWithTokensToWithdraw[] = [];
1726
- let isFirstWithdraw = true;
1727
-
1728
- if (tokenLeftToWithdraw.lte(0)) {
1729
- // Availabe enough to withdraw all - using the first existent reserve
1730
- const firstReserve = vaultState.vaultAllocationStrategy.find((reserve) => reserve.reserve !== DEFAULT_PUBLIC_KEY);
1731
- if (withdrawAllShares) {
1732
- reserveWithSharesAmountToWithdraw.push({
1733
- reserve: firstReserve!.reserve,
1734
- shares: new Decimal(U64_MAX.toString()),
1735
- });
1736
- } else {
1737
- reserveWithSharesAmountToWithdraw.push({
1738
- reserve: firstReserve!.reserve,
1739
- shares: shareLamportsToWithdraw,
1740
- });
1741
- }
1742
- } else {
1743
- // Get decreasing order sorted available liquidity to withdraw from each reserve allocated to
1744
- const reserveAllocationAvailableLiquidityToWithdraw = await this.getReserveAllocationAvailableLiquidityToWithdraw(
1745
- vault,
1746
- slot,
1747
- vaultReservesState
1748
- );
1749
- // sort
1750
- const reserveAllocationAvailableLiquidityToWithdrawSorted = [
1751
- ...reserveAllocationAvailableLiquidityToWithdraw.entries(),
1752
- ].sort((a, b) => b[1].sub(a[1]).toNumber());
1753
-
1754
- reserveAllocationAvailableLiquidityToWithdrawSorted.forEach(([key, availableLiquidityToWithdraw], _) => {
1755
- if (tokenLeftToWithdraw.gt(0)) {
1756
- let tokensToWithdrawFromReserve = Decimal.min(tokenLeftToWithdraw, availableLiquidityToWithdraw);
1757
- if (isFirstWithdraw) {
1758
- tokensToWithdrawFromReserve = tokensToWithdrawFromReserve.add(availableTokens);
1759
- isFirstWithdraw = false;
1760
- }
1761
- if (withdrawAllShares) {
1762
- reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: new Decimal(U64_MAX.toString()) });
1763
- } else {
1764
- // round up to the nearest integer the shares to withdraw
1765
- const sharesToWithdrawFromReserve = tokensToWithdrawFromReserve.mul(sharesPerToken).floor();
1766
- reserveWithSharesAmountToWithdraw.push({ reserve: key, shares: sharesToWithdrawFromReserve });
1767
- }
1768
-
1769
- tokenLeftToWithdraw = tokenLeftToWithdraw.sub(tokensToWithdrawFromReserve);
1770
- }
1771
- });
1772
- }
1773
-
1774
- const withdrawIxs: Instruction[] = [];
1775
- withdrawIxs.push(createAtaIx);
1776
- for (let reserveIndex = 0; reserveIndex < reserveWithSharesAmountToWithdraw.length; reserveIndex++) {
1777
- const reserveWithTokens = reserveWithSharesAmountToWithdraw[reserveIndex];
1778
- const reserveState = vaultReservesState.get(reserveWithTokens.reserve);
1779
- if (reserveState === undefined) {
1780
- throw new Error(`Reserve ${reserveWithTokens.reserve} not found in vault reserves map`);
1781
- }
1782
- const marketAddress = reserveState.state.lendingMarket;
1783
-
1784
- const withdrawFromReserveIx = await this.sellIx(
1785
- user,
1786
- vault,
1787
- vaultState,
1788
- marketAddress,
1789
- { address: reserveWithTokens.reserve, state: reserveState.state },
1790
- userSharesAta,
1791
- userTokenAta,
1792
- reserveWithTokens.shares,
1793
- vaultReservesState
1794
- );
1795
- withdrawIxs.push(withdrawFromReserveIx);
1796
- }
1797
-
1798
- return withdrawIxs;
1799
- }
1800
1470
  private async withdrawWithReserveIxs(
1801
1471
  user: TransactionSigner,
1802
1472
  vault: KaminoVault,
@@ -1890,7 +1560,7 @@ export class KaminoVaultClient {
1890
1560
  }
1891
1561
  const marketAddress = reserveState.state.lendingMarket;
1892
1562
 
1893
- const withdrawFromReserveIx = await this.withdrawIx(
1563
+ const sellIx = await this.sellIx(
1894
1564
  user,
1895
1565
  vault,
1896
1566
  vaultState,
@@ -1901,7 +1571,7 @@ export class KaminoVaultClient {
1901
1571
  reserveWithTokens.shares,
1902
1572
  vaultReservesState
1903
1573
  );
1904
- withdrawIxs.push(withdrawFromReserveIx);
1574
+ withdrawIxs.push(sellIx);
1905
1575
  }
1906
1576
 
1907
1577
  return withdrawIxs;
@@ -2177,65 +1847,6 @@ export class KaminoVaultClient {
2177
1847
  return sellIxn;
2178
1848
  }
2179
1849
 
2180
- private async withdrawIx(
2181
- user: TransactionSigner,
2182
- vault: KaminoVault,
2183
- vaultState: VaultState,
2184
- marketAddress: Address,
2185
- reserve: ReserveWithAddress,
2186
- userSharesAta: Address,
2187
- userTokenAta: Address,
2188
- shareAmountLamports: Decimal,
2189
- vaultReservesState: Map<Address, KaminoReserve>
2190
- ): Promise<Instruction> {
2191
- const [lendingMarketAuth] = await lendingMarketAuthPda(marketAddress, this._kaminoLendProgramId);
2192
-
2193
- const globalConfig = await getKvaultGlobalConfigPda(this._kaminoVaultProgramId);
2194
- const eventAuthority = await getEventAuthorityPda(this._kaminoVaultProgramId);
2195
- const withdrawAccounts: WithdrawAccounts = {
2196
- withdrawFromAvailable: {
2197
- user,
2198
- vaultState: vault.address,
2199
- globalConfig: globalConfig,
2200
- tokenVault: vaultState.tokenVault,
2201
- baseVaultAuthority: vaultState.baseVaultAuthority,
2202
- userTokenAta: userTokenAta,
2203
- tokenMint: vaultState.tokenMint,
2204
- userSharesAta: userSharesAta,
2205
- sharesMint: vaultState.sharesMint,
2206
- tokenProgram: vaultState.tokenProgram,
2207
- sharesTokenProgram: TOKEN_PROGRAM_ADDRESS,
2208
- klendProgram: this._kaminoLendProgramId,
2209
- eventAuthority: eventAuthority,
2210
- program: this._kaminoVaultProgramId,
2211
- },
2212
- withdrawFromReserveAccounts: {
2213
- vaultState: vault.address,
2214
- reserve: reserve.address,
2215
- ctokenVault: await getCTokenVaultPda(vault.address, reserve.address, this._kaminoVaultProgramId),
2216
- lendingMarket: marketAddress,
2217
- lendingMarketAuthority: lendingMarketAuth,
2218
- reserveLiquiditySupply: reserve.state.liquidity.supplyVault,
2219
- reserveCollateralMint: reserve.state.collateral.mintPubkey,
2220
- reserveCollateralTokenProgram: TOKEN_PROGRAM_ADDRESS,
2221
- instructionSysvarAccount: SYSVAR_INSTRUCTIONS_ADDRESS,
2222
- },
2223
- eventAuthority: eventAuthority,
2224
- program: this._kaminoVaultProgramId,
2225
- };
2226
-
2227
- const withdrawArgs: WithdrawArgs = {
2228
- sharesAmount: new BN(shareAmountLamports.floor().toString()),
2229
- };
2230
-
2231
- let withdrawIxn = withdraw(withdrawArgs, withdrawAccounts, undefined, this._kaminoVaultProgramId);
2232
-
2233
- const vaultReserves = this.getVaultReserves(vaultState);
2234
- withdrawIxn = this.appendRemainingAccountsForVaultReserves(withdrawIxn, vaultReserves, vaultReservesState);
2235
-
2236
- return withdrawIxn;
2237
- }
2238
-
2239
1850
  private async withdrawFromAvailableIx(
2240
1851
  user: TransactionSigner,
2241
1852
  vault: KaminoVault,