@kamino-finance/klend-sdk 5.11.7 → 5.11.9

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 (41) hide show
  1. package/dist/classes/action.d.ts +12 -2
  2. package/dist/classes/action.d.ts.map +1 -1
  3. package/dist/classes/action.js +225 -30
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/obligation.d.ts +1 -1
  6. package/dist/classes/obligation.d.ts.map +1 -1
  7. package/dist/classes/obligation.js +1 -1
  8. package/dist/classes/obligation.js.map +1 -1
  9. package/dist/classes/vault.js +6 -6
  10. package/dist/classes/vault.js.map +1 -1
  11. package/dist/lending_operations/repay_with_collateral_calcs.d.ts.map +1 -1
  12. package/dist/lending_operations/repay_with_collateral_calcs.js +9 -5
  13. package/dist/lending_operations/repay_with_collateral_calcs.js.map +1 -1
  14. package/dist/lending_operations/repay_with_collateral_operations.d.ts +5 -0
  15. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  16. package/dist/lending_operations/repay_with_collateral_operations.js +26 -1
  17. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  18. package/dist/utils/lookupTable.d.ts +27 -0
  19. package/dist/utils/lookupTable.d.ts.map +1 -1
  20. package/dist/utils/lookupTable.js +58 -0
  21. package/dist/utils/lookupTable.js.map +1 -1
  22. package/dist/utils/seeds.d.ts +11 -1
  23. package/dist/utils/seeds.d.ts.map +1 -1
  24. package/dist/utils/seeds.js +13 -3
  25. package/dist/utils/seeds.js.map +1 -1
  26. package/dist/utils/userMetadata.js +6 -6
  27. package/dist/utils/userMetadata.js.map +1 -1
  28. package/package.json +1 -1
  29. package/src/classes/action.ts +358 -50
  30. package/src/classes/obligation.ts +1 -1
  31. package/src/classes/vault.ts +1 -1
  32. package/src/lending_operations/repay_with_collateral_calcs.ts +14 -5
  33. package/src/lending_operations/repay_with_collateral_operations.ts +63 -20
  34. package/src/utils/lookupTable.ts +62 -0
  35. package/src/utils/seeds.ts +14 -4
  36. package/src/utils/userMetadata.ts +14 -14
  37. package/dist/classes/lut_utils.d.ts +0 -29
  38. package/dist/classes/lut_utils.d.ts.map +0 -1
  39. package/dist/classes/lut_utils.js +0 -62
  40. package/dist/classes/lut_utils.js.map +0 -1
  41. package/src/classes/lut_utils.ts +0 -63
@@ -21,6 +21,7 @@ import BN from 'bn.js';
21
21
  import Decimal from 'decimal.js';
22
22
  import {
23
23
  borrowObligationLiquidity,
24
+ depositAndWithdraw,
24
25
  borrowObligationLiquidityV2,
25
26
  depositObligationCollateral,
26
27
  depositObligationCollateralV2,
@@ -41,6 +42,7 @@ import {
41
42
  RefreshObligationFarmsForReserveAccounts,
42
43
  RefreshObligationFarmsForReserveArgs,
43
44
  refreshReserve,
45
+ repayAndWithdrawAndRedeem,
44
46
  repayObligationLiquidity,
45
47
  repayObligationLiquidityV2,
46
48
  requestElevationGroup,
@@ -89,7 +91,9 @@ export type ActionType =
89
91
  | 'repayAndWithdraw'
90
92
  | 'refreshObligation'
91
93
  | 'requestElevationGroup'
92
- | 'withdrawReferrerFees';
94
+ | 'withdrawReferrerFees'
95
+ | 'repayAndWithdrawV2'
96
+ | 'depositAndWithdraw';
93
97
 
94
98
  export type AuxiliaryIx = 'setup' | 'inBetween' | 'cleanup';
95
99
 
@@ -737,6 +741,112 @@ export class KaminoAction {
737
741
  return axn;
738
742
  }
739
743
 
744
+ static async buildDepositAndWithdrawV2Txns(
745
+ kaminoMarket: KaminoMarket,
746
+ depositAmount: string | BN,
747
+ depositMint: PublicKey,
748
+ withdrawAmount: string | BN,
749
+ withdrawMint: PublicKey,
750
+ payer: PublicKey,
751
+ currentSlot: number,
752
+ obligation: KaminoObligation | ObligationType,
753
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
754
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
755
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
756
+ requestElevationGroup: boolean = false,
757
+ includeUserMetadata: boolean = true, // if true it includes user metadata,
758
+ createLookupTable: boolean = true,
759
+ referrer: PublicKey = PublicKey.default
760
+ ) {
761
+ const axn = await KaminoAction.initializeMultiTokenAction(
762
+ kaminoMarket,
763
+ 'depositAndWithdraw',
764
+ depositAmount,
765
+ depositMint,
766
+ withdrawMint,
767
+ payer,
768
+ payer,
769
+ obligation,
770
+ withdrawAmount,
771
+ referrer,
772
+ currentSlot
773
+ );
774
+ const addInitObligationForFarm = true;
775
+ const twoTokenAction = true;
776
+ if (extraComputeBudget > 0) {
777
+ axn.addComputeBudgetIxn(extraComputeBudget);
778
+ }
779
+
780
+ await axn.addSupportIxs(
781
+ 'depositAndWithdraw',
782
+ includeAtaIxns,
783
+ requestElevationGroup,
784
+ includeUserMetadata,
785
+ addInitObligationForFarm,
786
+ true,
787
+ scopeRefreshConfig,
788
+ createLookupTable,
789
+ twoTokenAction
790
+ );
791
+ const withdrawCollateralAmount = axn.getWithdrawCollateralAmount(axn.outflowReserve!, axn.outflowAmount!);
792
+ axn.addDepositAndWithdrawV2Ixs(withdrawCollateralAmount);
793
+
794
+ return axn;
795
+ }
796
+
797
+ static async buildRepayAndWithdrawV2Txns(
798
+ kaminoMarket: KaminoMarket,
799
+ repayAmount: string | BN,
800
+ repayMint: PublicKey,
801
+ withdrawAmount: string | BN,
802
+ withdrawMint: PublicKey,
803
+ payer: PublicKey,
804
+ currentSlot: number,
805
+ obligation: KaminoObligation | ObligationType,
806
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
807
+ extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
808
+ includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
809
+ requestElevationGroup: boolean = false,
810
+ includeUserMetadata: boolean = true, // if true it includes user metadata,
811
+ createLookupTable: boolean = true,
812
+ referrer: PublicKey = PublicKey.default
813
+ ) {
814
+ const axn = await KaminoAction.initializeMultiTokenAction(
815
+ kaminoMarket,
816
+ 'repayAndWithdrawV2',
817
+ repayAmount,
818
+ repayMint,
819
+ withdrawMint,
820
+ payer,
821
+ payer,
822
+ obligation,
823
+ withdrawAmount,
824
+ referrer,
825
+ currentSlot
826
+ );
827
+ const addInitObligationForFarm = true;
828
+ const twoTokenAction = true;
829
+ if (extraComputeBudget > 0) {
830
+ axn.addComputeBudgetIxn(extraComputeBudget);
831
+ }
832
+
833
+ await axn.addSupportIxs(
834
+ 'repayAndWithdrawV2',
835
+ includeAtaIxns,
836
+ requestElevationGroup,
837
+ includeUserMetadata,
838
+ addInitObligationForFarm,
839
+ true,
840
+ scopeRefreshConfig,
841
+ createLookupTable,
842
+ twoTokenAction
843
+ );
844
+ const withdrawCollateralAmount = axn.getWithdrawCollateralAmount(axn.outflowReserve!, axn.outflowAmount!);
845
+ axn.addRepayAndWithdrawV2Ixs(withdrawCollateralAmount);
846
+
847
+ return axn;
848
+ }
849
+
740
850
  static async buildRepayAndWithdrawTxns(
741
851
  kaminoMarket: KaminoMarket,
742
852
  repayAmount: string | BN,
@@ -1200,10 +1310,7 @@ export class KaminoAction {
1200
1310
  reserveFarmState: this.kaminoMarket.programId,
1201
1311
  }
1202
1312
  : {
1203
- obligationFarmUserState: obligationFarmStatePda(
1204
- this.getObligationPda(),
1205
- this.reserve.state.farmCollateral
1206
- )[0],
1313
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmCollateral, this.getObligationPda()),
1207
1314
  reserveFarmState: this.reserve.state.farmCollateral,
1208
1315
  };
1209
1316
 
@@ -1268,10 +1375,7 @@ export class KaminoAction {
1268
1375
  reserveFarmState: this.kaminoMarket.programId,
1269
1376
  }
1270
1377
  : {
1271
- obligationFarmUserState: obligationFarmStatePda(
1272
- this.getObligationPda(),
1273
- this.reserve.state.farmCollateral
1274
- )[0],
1378
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmCollateral, this.getObligationPda()),
1275
1379
  reserveFarmState: this.reserve.state.farmCollateral,
1276
1380
  };
1277
1381
 
@@ -1353,7 +1457,7 @@ export class KaminoAction {
1353
1457
  reserveFarmState: this.kaminoMarket.programId,
1354
1458
  }
1355
1459
  : {
1356
- obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
1460
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmDebt, this.getObligationPda()),
1357
1461
  reserveFarmState: this.reserve.state.farmDebt,
1358
1462
  };
1359
1463
 
@@ -1428,10 +1532,7 @@ export class KaminoAction {
1428
1532
  reserveFarmState: this.kaminoMarket.programId,
1429
1533
  }
1430
1534
  : {
1431
- obligationFarmUserState: obligationFarmStatePda(
1432
- this.getObligationPda(),
1433
- this.reserve.state.farmCollateral
1434
- )[0],
1535
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmCollateral, this.getObligationPda()),
1435
1536
  reserveFarmState: this.reserve.state.farmCollateral,
1436
1537
  };
1437
1538
 
@@ -1515,7 +1616,7 @@ export class KaminoAction {
1515
1616
  reserveFarmState: this.kaminoMarket.programId,
1516
1617
  }
1517
1618
  : {
1518
- obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
1619
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmDebt, this.getObligationPda()),
1519
1620
  reserveFarmState: this.reserve.state.farmDebt,
1520
1621
  };
1521
1622
  const depositReserveAccountMetas = depositReservesList.map((reserve) => {
@@ -1551,6 +1652,200 @@ export class KaminoAction {
1551
1652
  this.lendingIxs.push(repayIx);
1552
1653
  }
1553
1654
 
1655
+ addRepayAndWithdrawV2Ixs(withdrawCollateralAmount: BN) {
1656
+ this.lendingIxsLabels.push(
1657
+ `repayAndWithdrawAndRedeem(repayReserve=${this.reserve!.address})(withdrawReserve=${
1658
+ this.outflowReserve!.address
1659
+ })(obligation=${this.getObligationPda()})`
1660
+ );
1661
+
1662
+ const depositReservesList = this.getAdditionalDepositReservesList();
1663
+
1664
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1665
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1666
+ });
1667
+ const borrowReserveAccountMetas = this.borrowReserves.map((reserve) => {
1668
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1669
+ });
1670
+
1671
+ if (!this.outflowAmount) {
1672
+ throw new Error(`outflowAmount not set`);
1673
+ }
1674
+
1675
+ if (!this.outflowReserve) {
1676
+ throw new Error(`outflowReserve not set`);
1677
+ }
1678
+
1679
+ const collateralFarmsAccounts = this.outflowReserve.state.farmCollateral.equals(PublicKey.default)
1680
+ ? {
1681
+ obligationFarmUserState: this.kaminoMarket.programId,
1682
+ reserveFarmState: this.kaminoMarket.programId,
1683
+ }
1684
+ : {
1685
+ obligationFarmUserState: obligationFarmStatePda(
1686
+ this.outflowReserve.state.farmCollateral,
1687
+ this.getObligationPda()
1688
+ ),
1689
+ reserveFarmState: this.outflowReserve.state.farmCollateral,
1690
+ };
1691
+
1692
+ const debtFarmsAccounts = this.reserve.state.farmDebt.equals(PublicKey.default)
1693
+ ? {
1694
+ obligationFarmUserState: this.kaminoMarket.programId,
1695
+ reserveFarmState: this.kaminoMarket.programId,
1696
+ }
1697
+ : {
1698
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmDebt, this.getObligationPda()),
1699
+ reserveFarmState: this.reserve.state.farmDebt,
1700
+ };
1701
+
1702
+ const repayAndWithdrawIx = repayAndWithdrawAndRedeem(
1703
+ {
1704
+ repayAmount: this.amount,
1705
+ withdrawCollateralAmount,
1706
+ },
1707
+ {
1708
+ repayAccounts: {
1709
+ owner: this.owner,
1710
+ obligation: this.getObligationPda(),
1711
+ lendingMarket: this.kaminoMarket.getAddress(),
1712
+ repayReserve: this.reserve!.address,
1713
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1714
+ userSourceLiquidity: this.getUserTokenAccountAddress(this.reserve),
1715
+ reserveDestinationLiquidity: this.reserve.state.liquidity.supplyVault,
1716
+ tokenProgram: this.reserve.getLiquidityTokenProgram(),
1717
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1718
+ },
1719
+ withdrawAccounts: {
1720
+ owner: this.owner,
1721
+ obligation: this.getObligationPda(),
1722
+ lendingMarket: this.kaminoMarket.getAddress(),
1723
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1724
+ withdrawReserve: this.outflowReserve.address,
1725
+ reserveLiquidityMint: this.outflowReserve.getLiquidityMint(),
1726
+ reserveCollateralMint: this.outflowReserve.getCTokenMint(),
1727
+ reserveLiquiditySupply: this.outflowReserve.state.liquidity.supplyVault,
1728
+ reserveSourceCollateral: this.outflowReserve.state.collateral.supplyVault,
1729
+ userDestinationLiquidity: this.getUserTokenAccountAddress(this.outflowReserve),
1730
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1731
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1732
+ liquidityTokenProgram: this.outflowReserve.getLiquidityTokenProgram(),
1733
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1734
+ },
1735
+ collateralFarmsAccounts,
1736
+ debtFarmsAccounts,
1737
+ farmsProgram: farmsId,
1738
+ },
1739
+ this.kaminoMarket.programId
1740
+ );
1741
+
1742
+ repayAndWithdrawIx.keys = repayAndWithdrawIx.keys.concat([
1743
+ ...depositReserveAccountMetas,
1744
+ ...borrowReserveAccountMetas,
1745
+ ]);
1746
+
1747
+ this.lendingIxs.push(repayAndWithdrawIx);
1748
+ }
1749
+
1750
+ addDepositAndWithdrawV2Ixs(withdrawCollateralAmount: BN) {
1751
+ this.lendingIxsLabels.push(
1752
+ `depositAndWithdrawV2(depositReserve=${this.reserve!.address})(withdrawReserve=${
1753
+ this.outflowReserve!.address
1754
+ })(obligation=${this.getObligationPda()})`
1755
+ );
1756
+
1757
+ const depositReservesList = this.getAdditionalDepositReservesList();
1758
+
1759
+ const depositReserveAccountMetas = depositReservesList.map((reserve) => {
1760
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1761
+ });
1762
+ const borrowReserveAccountMetas = this.borrowReserves.map((reserve) => {
1763
+ return { pubkey: reserve, isSigner: false, isWritable: true };
1764
+ });
1765
+
1766
+ if (!this.outflowAmount) {
1767
+ throw new Error(`outflowAmount not set`);
1768
+ }
1769
+
1770
+ if (!this.outflowReserve) {
1771
+ throw new Error(`outflowReserve not set`);
1772
+ }
1773
+
1774
+ const depositFarmsAccounts = this.reserve.state.farmCollateral.equals(PublicKey.default)
1775
+ ? {
1776
+ obligationFarmUserState: this.kaminoMarket.programId,
1777
+ reserveFarmState: this.kaminoMarket.programId,
1778
+ }
1779
+ : {
1780
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmCollateral, this.getObligationPda()),
1781
+ reserveFarmState: this.reserve.state.farmCollateral,
1782
+ };
1783
+ const withdrawFarmsAccounts = this.outflowReserve.state.farmCollateral.equals(PublicKey.default)
1784
+ ? {
1785
+ obligationFarmUserState: this.kaminoMarket.programId,
1786
+ reserveFarmState: this.kaminoMarket.programId,
1787
+ }
1788
+ : {
1789
+ obligationFarmUserState: obligationFarmStatePda(
1790
+ this.outflowReserve.state.farmCollateral,
1791
+ this.getObligationPda()
1792
+ ),
1793
+ reserveFarmState: this.outflowReserve.state.farmCollateral,
1794
+ };
1795
+
1796
+ const depositAndWithdrawIx = depositAndWithdraw(
1797
+ {
1798
+ liquidityAmount: this.amount,
1799
+ withdrawCollateralAmount,
1800
+ },
1801
+ {
1802
+ depositAccounts: {
1803
+ owner: this.owner,
1804
+ obligation: this.getObligationPda(),
1805
+ lendingMarket: this.kaminoMarket.getAddress(),
1806
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1807
+ reserve: this.reserve.address,
1808
+ reserveLiquidityMint: this.reserve.getLiquidityMint(),
1809
+ reserveLiquiditySupply: this.reserve.state.liquidity.supplyVault,
1810
+ reserveCollateralMint: this.reserve.getCTokenMint(),
1811
+ reserveDestinationDepositCollateral: this.reserve.state.collateral.supplyVault, // destinationCollateral
1812
+ userSourceLiquidity: this.getUserTokenAccountAddress(this.reserve),
1813
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1814
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1815
+ liquidityTokenProgram: this.reserve.getLiquidityTokenProgram(),
1816
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1817
+ },
1818
+ withdrawAccounts: {
1819
+ owner: this.owner,
1820
+ obligation: this.getObligationPda(),
1821
+ lendingMarket: this.kaminoMarket.getAddress(),
1822
+ lendingMarketAuthority: this.kaminoMarket.getLendingMarketAuthority(),
1823
+ withdrawReserve: this.outflowReserve.address,
1824
+ reserveLiquidityMint: this.outflowReserve.getLiquidityMint(),
1825
+ reserveCollateralMint: this.outflowReserve.getCTokenMint(),
1826
+ reserveLiquiditySupply: this.outflowReserve.state.liquidity.supplyVault,
1827
+ reserveSourceCollateral: this.outflowReserve.state.collateral.supplyVault,
1828
+ userDestinationLiquidity: this.getUserTokenAccountAddress(this.outflowReserve),
1829
+ placeholderUserDestinationCollateral: this.kaminoMarket.programId,
1830
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
1831
+ liquidityTokenProgram: this.outflowReserve.getLiquidityTokenProgram(),
1832
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
1833
+ },
1834
+ depositFarmsAccounts,
1835
+ withdrawFarmsAccounts,
1836
+ farmsProgram: farmsId,
1837
+ },
1838
+ this.kaminoMarket.programId
1839
+ );
1840
+
1841
+ depositAndWithdrawIx.keys = depositAndWithdrawIx.keys.concat([
1842
+ ...depositReserveAccountMetas,
1843
+ ...borrowReserveAccountMetas,
1844
+ ]);
1845
+
1846
+ this.lendingIxs.push(depositAndWithdrawIx);
1847
+ }
1848
+
1554
1849
  async addDepositAndBorrowIx() {
1555
1850
  this.lendingIxsLabels.push(`depositReserveLiquidityAndObligationCollateral`);
1556
1851
  this.lendingIxsLabels.push(`borrowObligationLiquidity`);
@@ -1632,10 +1927,7 @@ export class KaminoAction {
1632
1927
  reserveFarmState: this.kaminoMarket.programId,
1633
1928
  }
1634
1929
  : {
1635
- obligationFarmUserState: obligationFarmStatePda(
1636
- this.getObligationPda(),
1637
- this.reserve.state.farmCollateral
1638
- )[0],
1930
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmCollateral, this.getObligationPda()),
1639
1931
  reserveFarmState: this.reserve.state.farmCollateral,
1640
1932
  };
1641
1933
 
@@ -1692,10 +1984,7 @@ export class KaminoAction {
1692
1984
  reserveFarmState: this.kaminoMarket.programId,
1693
1985
  }
1694
1986
  : {
1695
- obligationFarmUserState: obligationFarmStatePda(
1696
- this.getObligationPda(),
1697
- this.outflowReserve.state.farmDebt!
1698
- )[0],
1987
+ obligationFarmUserState: obligationFarmStatePda(this.outflowReserve.state.farmDebt, this.getObligationPda()),
1699
1988
  reserveFarmState: this.outflowReserve.state.farmDebt,
1700
1989
  };
1701
1990
 
@@ -1817,7 +2106,7 @@ export class KaminoAction {
1817
2106
  reserveFarmState: this.kaminoMarket.programId,
1818
2107
  }
1819
2108
  : {
1820
- obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
2109
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmDebt, this.getObligationPda()),
1821
2110
  reserveFarmState: this.reserve.state.farmDebt,
1822
2111
  };
1823
2112
 
@@ -1862,9 +2151,9 @@ export class KaminoAction {
1862
2151
  }
1863
2152
  : {
1864
2153
  obligationFarmUserState: obligationFarmStatePda(
1865
- this.getObligationPda(),
1866
- this.outflowReserve.state.farmCollateral
1867
- )[0],
2154
+ this.outflowReserve.state.farmCollateral,
2155
+ this.getObligationPda()
2156
+ ),
1868
2157
  reserveFarmState: this.outflowReserve.state.farmCollateral,
1869
2158
  };
1870
2159
 
@@ -1898,7 +2187,7 @@ export class KaminoAction {
1898
2187
  );
1899
2188
  }
1900
2189
 
1901
- async addLiquidateIx(maxAllowedLtvOverridePercent: number = 0) {
2190
+ addLiquidateIx(maxAllowedLtvOverridePercent: number = 0) {
1902
2191
  this.lendingIxsLabels.push(`liquidateObligationAndRedeemReserveCollateral`);
1903
2192
  if (!this.outflowReserve) {
1904
2193
  throw Error(`Withdraw reserve during liquidation is not defined`);
@@ -1965,9 +2254,9 @@ export class KaminoAction {
1965
2254
  }
1966
2255
  : {
1967
2256
  obligationFarmUserState: obligationFarmStatePda(
1968
- this.getObligationPda(),
1969
- this.outflowReserve.state.farmCollateral
1970
- )[0],
2257
+ this.outflowReserve.state.farmCollateral,
2258
+ this.getObligationPda()
2259
+ ),
1971
2260
  reserveFarmState: this.outflowReserve.state.farmCollateral,
1972
2261
  };
1973
2262
 
@@ -1977,7 +2266,7 @@ export class KaminoAction {
1977
2266
  reserveFarmState: this.kaminoMarket.programId,
1978
2267
  }
1979
2268
  : {
1980
- obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
2269
+ obligationFarmUserState: obligationFarmStatePda(this.reserve.state.farmDebt, this.getObligationPda()),
1981
2270
  reserveFarmState: this.reserve.state.farmDebt,
1982
2271
  };
1983
2272
 
@@ -2089,7 +2378,9 @@ export class KaminoAction {
2089
2378
  'repay',
2090
2379
  'depositAndBorrow',
2091
2380
  'repayAndWithdraw',
2381
+ 'repayAndWithdrawV2',
2092
2382
  'refreshObligation',
2383
+ 'depositAndWithdraw',
2093
2384
  ].includes(action)
2094
2385
  ) {
2095
2386
  // The support ixns in order are:
@@ -2107,12 +2398,17 @@ export class KaminoAction {
2107
2398
 
2108
2399
  let currentReserves: KaminoReserve[] = [];
2109
2400
 
2110
- if (action === 'liquidate' || action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
2401
+ if (
2402
+ action === 'liquidate' ||
2403
+ action === 'depositAndBorrow' ||
2404
+ action === 'repayAndWithdraw' ||
2405
+ action === 'repayAndWithdrawV2'
2406
+ ) {
2111
2407
  if (!this.outflowReserve) {
2112
2408
  throw new Error('outflowReserve is undefined');
2113
2409
  }
2114
2410
 
2115
- if (action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
2411
+ if (action === 'depositAndBorrow' || action === 'repayAndWithdraw' || action === 'repayAndWithdrawV2') {
2116
2412
  currentReserves = [this.reserve, this.outflowReserve];
2117
2413
  if (action === 'depositAndBorrow') {
2118
2414
  if (this.obligation) {
@@ -2151,13 +2447,19 @@ export class KaminoAction {
2151
2447
  action === 'depositAndBorrow' ||
2152
2448
  action === 'depositCollateral' ||
2153
2449
  action === 'withdraw' ||
2154
- action === 'deposit'
2450
+ action === 'deposit' ||
2451
+ action === 'depositAndWithdraw'
2155
2452
  ) {
2156
2453
  await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Collateral, addAsSupportIx);
2157
- if (this.outflowReserve) {
2454
+ if (this.outflowReserve && action !== 'depositAndWithdraw') {
2158
2455
  await this.addInitObligationForFarm(this.outflowReserve, ReserveFarmKind.Debt, addAsSupportIx);
2159
2456
  }
2160
- } else if (action === 'repayAndWithdraw' || action === 'borrow' || action === 'repay') {
2457
+ } else if (
2458
+ action === 'repayAndWithdraw' ||
2459
+ action === 'borrow' ||
2460
+ action === 'repay' ||
2461
+ action === 'repayAndWithdrawV2'
2462
+ ) {
2161
2463
  // todo - probably don't need to add both debt and collateral for everything here
2162
2464
  await this.addInitObligationForFarm(this.reserve, ReserveFarmKind.Debt, addAsSupportIx);
2163
2465
  if (this.outflowReserve) {
@@ -2188,7 +2490,7 @@ export class KaminoAction {
2188
2490
  }
2189
2491
 
2190
2492
  if (requestElevationGroup) {
2191
- if (action === 'repay') {
2493
+ if (action === 'repay' || action === 'repayAndWithdrawV2') {
2192
2494
  const repayObligationLiquidity = this.obligation!.borrows.get(this.reserve.address);
2193
2495
 
2194
2496
  if (!repayObligationLiquidity) {
@@ -2616,7 +2918,7 @@ export class KaminoAction {
2616
2918
  farms.push([
2617
2919
  ReserveFarmKind.Collateral,
2618
2920
  kaminoReserve.state.farmCollateral,
2619
- obligationFarmStatePda(this.getObligationPda(), kaminoReserve.state.farmCollateral)[0],
2921
+ obligationFarmStatePda(kaminoReserve.state.farmCollateral, this.getObligationPda()),
2620
2922
  kaminoReserve,
2621
2923
  ]);
2622
2924
  }
@@ -2624,7 +2926,7 @@ export class KaminoAction {
2624
2926
  farms.push([
2625
2927
  ReserveFarmKind.Debt,
2626
2928
  kaminoReserve.state.farmDebt,
2627
- obligationFarmStatePda(this.getObligationPda(), kaminoReserve.state.farmDebt)[0],
2929
+ obligationFarmStatePda(kaminoReserve.state.farmDebt, this.getObligationPda()),
2628
2930
  kaminoReserve,
2629
2931
  ]);
2630
2932
  }
@@ -2708,18 +3010,18 @@ export class KaminoAction {
2708
3010
  const farms: [number, PublicKey, PublicKey][] = [];
2709
3011
 
2710
3012
  if (mode === ReserveFarmKind.Collateral && isNotNullPubkey(reserve.state.farmCollateral)) {
2711
- const userPda = obligationFarmStatePda(this.getObligationPda(), reserve.state.farmCollateral)[0];
2712
- const account = await this.kaminoMarket.getConnection().getAccountInfo(userPda);
3013
+ const pda = obligationFarmStatePda(reserve.state.farmCollateral, this.getObligationPda());
3014
+ const account = await this.kaminoMarket.getConnection().getAccountInfo(pda);
2713
3015
  if (!account) {
2714
- farms.push([ReserveFarmKind.Collateral.discriminator, reserve.state.farmCollateral, userPda]);
3016
+ farms.push([ReserveFarmKind.Collateral.discriminator, reserve.state.farmCollateral, pda]);
2715
3017
  }
2716
3018
  }
2717
3019
 
2718
3020
  if (mode === ReserveFarmKind.Debt && isNotNullPubkey(reserve.state.farmDebt)) {
2719
- const userPda = obligationFarmStatePda(this.getObligationPda(), reserve.state.farmDebt)[0];
2720
- const account = await this.kaminoMarket.getConnection().getAccountInfo(userPda);
3021
+ const pda = obligationFarmStatePda(reserve.state.farmDebt, this.getObligationPda());
3022
+ const account = await this.kaminoMarket.getConnection().getAccountInfo(pda);
2721
3023
  if (!account) {
2722
- farms.push([ReserveFarmKind.Debt.discriminator, reserve.state.farmDebt, userPda]);
3024
+ farms.push([ReserveFarmKind.Debt.discriminator, reserve.state.farmDebt, pda]);
2723
3025
  }
2724
3026
  }
2725
3027
 
@@ -2753,7 +3055,7 @@ export class KaminoAction {
2753
3055
  });
2754
3056
  }
2755
3057
 
2756
- private async addInitObligationIxs() {
3058
+ private addInitObligationIxs() {
2757
3059
  if (!this.obligation) {
2758
3060
  const obligationPda = this.getObligationPda();
2759
3061
  const [userMetadataAddress, _bump] = userMetadataPda(this.owner, this.kaminoMarket.programId);
@@ -2965,7 +3267,7 @@ export class KaminoAction {
2965
3267
 
2966
3268
  let safeRepay = new BN(this.amount);
2967
3269
 
2968
- if (this.obligation && action === 'repay' && this.amount.eq(new BN(U64_MAX))) {
3270
+ if (this.obligation && (action === 'repay' || action === 'repayAndWithdrawV2') && this.amount.eq(new BN(U64_MAX))) {
2969
3271
  const borrow = this.obligation.state.borrows.find(
2970
3272
  (borrow) => borrow.borrowReserve.toString() === this.reserve.address.toString()
2971
3273
  );
@@ -2979,7 +3281,7 @@ export class KaminoAction {
2979
3281
  this.currentSlot,
2980
3282
  this.kaminoMarket.state.referralFeeBps
2981
3283
  );
2982
- // TODO: shouldn't this calc be added to all other stuff as well?
3284
+
2983
3285
  safeRepay = new BN(
2984
3286
  Math.floor(
2985
3287
  KaminoObligation.getBorrowAmount(borrow)
@@ -3009,6 +3311,7 @@ export class KaminoAction {
3009
3311
  const sendAction =
3010
3312
  action === 'deposit' ||
3011
3313
  action === 'repay' ||
3314
+ action === 'repayAndWithdrawV2' ||
3012
3315
  action === 'mint' ||
3013
3316
  (action === 'liquidate' && this.mint?.equals(NATIVE_MINT)); // only sync WSOL amount if liquidator repays SOL which is secondaryMint
3014
3317
 
@@ -3093,7 +3396,12 @@ export class KaminoAction {
3093
3396
  let secondaryMint: PublicKey;
3094
3397
  let primaryMint: PublicKey;
3095
3398
 
3096
- if (action === 'liquidate' || action === 'depositAndBorrow' || action === 'repayAndWithdraw') {
3399
+ if (
3400
+ action === 'liquidate' ||
3401
+ action === 'depositAndBorrow' ||
3402
+ action === 'repayAndWithdraw' ||
3403
+ action === 'repayAndWithdrawV2'
3404
+ ) {
3097
3405
  primaryMint = inflowTokenMint;
3098
3406
  secondaryMint = outflowTokenMint;
3099
3407
  } else {
@@ -267,7 +267,7 @@ export class KaminoObligation {
267
267
  /**
268
268
  * @returns total borrow power of the obligation, relative to max LTV of each asset's reserve
269
269
  */
270
- getAllowedBorrowValue(): Decimal {
270
+ getMaxAllowedBorrowValue(): Decimal {
271
271
  return new Fraction(this.state.allowedBorrowValueSf).toDecimal();
272
272
  }
273
273
 
@@ -82,7 +82,7 @@ import {
82
82
  import { batchFetch, collToLamportsDecimal, ZERO } from '@kamino-finance/kliquidity-sdk';
83
83
  import { FullBPSDecimal } from '@kamino-finance/kliquidity-sdk/dist/utils/CreationParameters';
84
84
  import { FarmState } from '@kamino-finance/farms-sdk/dist';
85
- import { getAccountsInLUT, initLookupTableIx } from './lut_utils';
85
+ import { getAccountsInLUT, initLookupTableIx } from '../utils/lookupTable';
86
86
  import {
87
87
  getFarmStakeIxs,
88
88
  getFarmUnstakeAndWithdrawIxs,
@@ -2,6 +2,7 @@ import Decimal from 'decimal.js';
2
2
  import { KaminoMarket, KaminoObligation, KaminoReserve, numberToLamportsDecimal } from '../classes';
3
3
  import { PublicKey } from '@solana/web3.js';
4
4
  import { lamportsToDecimal } from '../classes/utils';
5
+ import { MaxWithdrawLtvCheck, getMaxWithdrawLtvCheck } from './repay_with_collateral_operations';
5
6
 
6
7
  export function calcRepayAmountWithSlippage(
7
8
  kaminoMarket: KaminoMarket,
@@ -102,6 +103,7 @@ export function calcMaxWithdrawCollateral(
102
103
  .filter((p) => !p.reserveAddress.equals(borrow.reserveAddress))
103
104
  .reduce((acc, b) => acc.add(b.marketValueRefreshed), new Decimal('0'));
104
105
  }
106
+ const maxWithdrawLtvCheck = getMaxWithdrawLtvCheck(obligation);
105
107
 
106
108
  let remainingDepositsValueWithLtv = new Decimal('0');
107
109
  if (obligation.getDeposits().length > 1) {
@@ -109,8 +111,13 @@ export function calcMaxWithdrawCollateral(
109
111
  .getDeposits()
110
112
  .filter((p) => !p.reserveAddress.equals(deposit.reserveAddress))
111
113
  .reduce((acc, d) => {
112
- const { maxLtv } = obligation.getLtvForReserve(market, market.getReserveByAddress(d.reserveAddress)!);
113
- return acc.add(d.marketValueRefreshed.mul(maxLtv));
114
+ const { maxLtv, liquidationLtv } = obligation.getLtvForReserve(
115
+ market,
116
+ market.getReserveByAddress(d.reserveAddress)!
117
+ );
118
+ const maxWithdrawLtv =
119
+ maxWithdrawLtvCheck === MaxWithdrawLtvCheck.LIQUIDATION_THRESHOLD ? liquidationLtv : maxLtv;
120
+ return acc.add(d.marketValueRefreshed.mul(maxWithdrawLtv));
114
121
  }, new Decimal('0'));
115
122
  }
116
123
 
@@ -123,16 +130,18 @@ export function calcMaxWithdrawCollateral(
123
130
  repayingAllDebt: repayAmountLamports.gte(borrow.amount),
124
131
  };
125
132
  } else {
126
- const { maxLtv: collMaxLtv } = obligation.getLtvForReserve(
133
+ const { maxLtv: collMaxLtv, liquidationLtv: collLiquidationLtv } = obligation.getLtvForReserve(
127
134
  market,
128
135
  market.getReserveByAddress(depositReserve.address)!
129
136
  );
137
+ const maxWithdrawLtv =
138
+ maxWithdrawLtvCheck === MaxWithdrawLtvCheck.LIQUIDATION_THRESHOLD ? collLiquidationLtv : collMaxLtv;
130
139
  const numerator = deposit.marketValueRefreshed
131
- .mul(collMaxLtv)
140
+ .mul(maxWithdrawLtv)
132
141
  .add(remainingDepositsValueWithLtv)
133
142
  .sub(remainingBorrowsValue);
134
143
 
135
- const denominator = depositReserve.getOracleMarketPrice().mul(collMaxLtv);
144
+ const denominator = depositReserve.getOracleMarketPrice().mul(maxWithdrawLtv);
136
145
  const maxCollWithdrawAmount = numerator.div(denominator);
137
146
  const withdrawableCollLamports = maxCollWithdrawAmount.mul(depositReserve.getMintFactor()).floor();
138
147