@kamino-finance/klend-sdk 5.13.8 → 5.13.10

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 (58) hide show
  1. package/dist/classes/action.d.ts.map +1 -1
  2. package/dist/classes/action.js +0 -1
  3. package/dist/classes/action.js.map +1 -1
  4. package/dist/classes/manager.d.ts +17 -1
  5. package/dist/classes/manager.d.ts.map +1 -1
  6. package/dist/classes/manager.js +20 -0
  7. package/dist/classes/manager.js.map +1 -1
  8. package/dist/classes/reserve.d.ts +4 -0
  9. package/dist/classes/reserve.d.ts.map +1 -1
  10. package/dist/classes/reserve.js +8 -2
  11. package/dist/classes/reserve.js.map +1 -1
  12. package/dist/classes/vault.d.ts +9 -1
  13. package/dist/classes/vault.d.ts.map +1 -1
  14. package/dist/classes/vault.js +34 -5
  15. package/dist/classes/vault.js.map +1 -1
  16. package/dist/lending_operations/repay_with_collateral_operations.js +5 -5
  17. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  18. package/dist/lending_operations/swap_collateral_operations.js +9 -9
  19. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  20. package/dist/leverage/calcs.d.ts +8 -8
  21. package/dist/leverage/calcs.d.ts.map +1 -1
  22. package/dist/leverage/calcs.js +25 -25
  23. package/dist/leverage/calcs.js.map +1 -1
  24. package/dist/leverage/instructions.d.ts +5 -5
  25. package/dist/leverage/instructions.d.ts.map +1 -1
  26. package/dist/leverage/instructions.js +6 -6
  27. package/dist/leverage/instructions.js.map +1 -1
  28. package/dist/leverage/operations.d.ts +5 -0
  29. package/dist/leverage/operations.d.ts.map +1 -1
  30. package/dist/leverage/operations.js +131 -304
  31. package/dist/leverage/operations.js.map +1 -1
  32. package/dist/leverage/types.d.ts +35 -57
  33. package/dist/leverage/types.d.ts.map +1 -1
  34. package/dist/leverage/utils.d.ts +1 -1
  35. package/dist/leverage/utils.js +5 -5
  36. package/dist/leverage/utils.js.map +1 -1
  37. package/dist/utils/ata.d.ts +0 -1
  38. package/dist/utils/ata.d.ts.map +1 -1
  39. package/dist/utils/ata.js +0 -14
  40. package/dist/utils/ata.js.map +1 -1
  41. package/dist/utils/instruction.d.ts +1 -0
  42. package/dist/utils/instruction.d.ts.map +1 -1
  43. package/dist/utils/instruction.js +10 -0
  44. package/dist/utils/instruction.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/classes/action.ts +0 -1
  47. package/src/classes/manager.ts +31 -0
  48. package/src/classes/reserve.ts +9 -2
  49. package/src/classes/vault.ts +45 -5
  50. package/src/lending_operations/repay_with_collateral_operations.ts +6 -6
  51. package/src/lending_operations/swap_collateral_operations.ts +22 -24
  52. package/src/leverage/calcs.ts +26 -26
  53. package/src/leverage/instructions.ts +8 -8
  54. package/src/leverage/operations.ts +232 -325
  55. package/src/leverage/types.ts +38 -67
  56. package/src/leverage/utils.ts +5 -5
  57. package/src/utils/ata.ts +1 -26
  58. package/src/utils/instruction.ts +12 -0
@@ -27,7 +27,7 @@ import {
27
27
  getComputeBudgetAndPriorityFeeIxs,
28
28
  getTransferWsolIxs,
29
29
  getLookupTableAccount,
30
- removeBudgetAndAtaIxs,
30
+ removeBudgetIxs,
31
31
  uniqueAccountsWithProgramIds,
32
32
  } from '../utils';
33
33
  import {
@@ -128,16 +128,7 @@ export async function getDepositWithLeverageSwapInputs<QuoteResponse>({
128
128
 
129
129
  console.log('Ops Calcs', toJson(calcs));
130
130
 
131
- let obligationType: ObligationType;
132
- if (obligationTypeTagOverride === ObligationTypeTag.Multiply) {
133
- // multiply
134
- obligationType = new MultiplyObligation(collTokenMint, debtTokenMint, kaminoMarket.programId);
135
- } else if (obligationTypeTagOverride === ObligationTypeTag.Leverage) {
136
- // leverage
137
- obligationType = new LeverageObligation(collTokenMint, debtTokenMint, kaminoMarket.programId);
138
- } else {
139
- throw Error('Obligation type tag not supported for leverage, please use 1 - multiply or 3 - leverage');
140
- }
131
+ const obligationType = checkObligationType(obligationTypeTagOverride, collTokenMint, debtTokenMint, kaminoMarket);
141
132
 
142
133
  // Build the repay & withdraw collateral tx to get the number of accounts
143
134
  const klendIxs: LeverageIxsOutput = await buildDepositWithLeverageIxs(
@@ -435,7 +426,6 @@ async function buildDepositWithLeverageIxs(
435
426
  useV2Ixs: boolean,
436
427
  elevationGroupOverride?: number
437
428
  ): Promise<LeverageIxsOutput> {
438
- const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(3000000);
439
429
  const collTokenMint = collReserve.getLiquidityMint();
440
430
  const debtTokenMint = debtReserve.getLiquidityMint();
441
431
  const collTokenAta = getAssociatedTokenAddressSync(
@@ -452,54 +442,20 @@ async function buildDepositWithLeverageIxs(
452
442
  );
453
443
 
454
444
  // 1. Create atas & budget ixs
455
- let mintsToCreateAtas: Array<{ mint: PublicKey; tokenProgram: PublicKey }>;
456
- if (collIsKtoken) {
457
- const secondTokenAta = strategy!.strategy.tokenAMint.equals(debtTokenMint)
458
- ? strategy!.strategy.tokenBMint
459
- : strategy!.strategy.tokenAMint;
460
- const secondTokenTokenProgarm = strategy!.strategy.tokenAMint.equals(debtTokenMint)
461
- ? strategy!.strategy.tokenBTokenProgram.equals(PublicKey.default)
462
- ? TOKEN_PROGRAM_ID
463
- : strategy!.strategy.tokenBTokenProgram
464
- : strategy!.strategy.tokenATokenProgram.equals(PublicKey.default)
465
- ? TOKEN_PROGRAM_ID
466
- : strategy!.strategy.tokenATokenProgram;
467
- mintsToCreateAtas = [
468
- {
469
- mint: collTokenMint,
470
- tokenProgram: collReserve.getLiquidityTokenProgram(),
471
- },
472
- {
473
- mint: debtTokenMint,
474
- tokenProgram: debtReserve.getLiquidityTokenProgram(),
475
- },
476
- {
477
- mint: collReserve.getCTokenMint(),
478
- tokenProgram: TOKEN_PROGRAM_ID,
479
- },
480
- {
481
- mint: secondTokenAta,
482
- tokenProgram: secondTokenTokenProgarm,
483
- },
484
- ];
485
- } else {
486
- mintsToCreateAtas = [
487
- {
488
- mint: collTokenMint,
489
- tokenProgram: collReserve.getLiquidityTokenProgram(),
490
- },
491
- {
492
- mint: debtTokenMint,
493
- tokenProgram: debtReserve.getLiquidityTokenProgram(),
494
- },
495
- {
496
- mint: collReserve!.getCTokenMint(),
497
- tokenProgram: TOKEN_PROGRAM_ID,
498
- },
499
- ];
500
- }
501
445
 
502
- const atasAndCreateIxs = createAtasIdempotent(owner, mintsToCreateAtas);
446
+ const { budgetIxs, createAtasIxs, scopeRefreshIx } = await getSetupIxs(
447
+ owner,
448
+ market,
449
+ obligation,
450
+ collTokenMint,
451
+ collReserve,
452
+ collIsKtoken,
453
+ debtTokenMint,
454
+ debtReserve,
455
+ strategy,
456
+ scopeRefreshConfig,
457
+ budgetAndPriorityFeeIxs
458
+ );
503
459
 
504
460
  const fillWsolAtaIxs: TransactionInstruction[] = [];
505
461
  if (depositTokenIsSol) {
@@ -512,13 +468,11 @@ async function buildDepositWithLeverageIxs(
512
468
  );
513
469
  }
514
470
 
515
- const scopeRefreshIxn = await getScopeRefreshIx(market, collReserve, debtReserve, obligation, scopeRefreshConfig);
516
-
517
471
  // 2. Flash borrow & repay the collateral amount needed for given leverage
518
472
  // if user deposits coll, then we borrow the diff, else we borrow the entire amount
519
- const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
520
- borrowIxnIndex:
521
- budgetIxs.length + atasAndCreateIxs.length + fillWsolAtaIxs.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
473
+ const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
474
+ borrowIxIndex:
475
+ budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
522
476
  walletPublicKey: owner,
523
477
  lendingMarketAuthority: market.getLendingMarketAuthority(),
524
478
  lendingMarketAddress: market.getAddress(),
@@ -559,44 +513,27 @@ async function buildDepositWithLeverageIxs(
559
513
 
560
514
  // 4. Swap
561
515
  const { swapIxs } = swapQuoteIxs;
562
- const swapInstructions = removeBudgetAndAtaIxs(swapIxs, []);
516
+ const swapInstructions = removeBudgetIxs(swapIxs);
563
517
  const flashBorrowReserve = !collIsKtoken ? collReserve : debtReserve;
564
518
  const flashLoanInfo = {
565
519
  flashBorrowReserve: flashBorrowReserve.address,
566
520
  flashLoanFee: flashBorrowReserve.getFlashLoanFee(),
567
521
  };
568
522
 
569
- if (!collIsKtoken) {
570
- return {
571
- flashLoanInfo,
572
- instructions: [
573
- ...scopeRefreshIxn,
574
- ...budgetIxs,
575
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
576
- ...fillWsolAtaIxs,
577
- ...[flashBorrowIxn],
578
- ...KaminoAction.actionToIxs(kaminoDepositAndBorrowAction),
579
- ...swapInstructions,
580
- ...[flashRepayIxn],
581
- ],
582
- };
583
- } else {
584
- return {
585
- flashLoanInfo,
586
- instructions: [
587
- ...scopeRefreshIxn,
588
- ...budgetIxs,
589
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
590
- ...fillWsolAtaIxs,
591
- ...[flashBorrowIxn],
592
- ...swapInstructions,
593
- ...kaminoDepositAndBorrowAction.setupIxs,
594
- ...KaminoAction.actionToLendingIxs(kaminoDepositAndBorrowAction),
595
- ...kaminoDepositAndBorrowAction.cleanupIxs,
596
- ...[flashRepayIxn],
597
- ],
598
- };
599
- }
523
+ return {
524
+ flashLoanInfo,
525
+ instructions: [
526
+ ...scopeRefreshIx,
527
+ ...budgetIxs,
528
+ ...createAtasIxs,
529
+ ...fillWsolAtaIxs,
530
+ ...[flashBorrowIx],
531
+ ...(collIsKtoken ? swapInstructions : []),
532
+ ...KaminoAction.actionToIxs(kaminoDepositAndBorrowAction),
533
+ ...(collIsKtoken ? [] : swapInstructions),
534
+ ...[flashRepayIx],
535
+ ],
536
+ };
600
537
  }
601
538
 
602
539
  export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
@@ -633,8 +570,7 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
633
570
  const collIsKtoken = await isKtoken(collTokenMint);
634
571
  const strategy = collIsKtoken ? (await kamino!.getStrategyByKTokenMint(collTokenMint))! : undefined;
635
572
 
636
- const solTokenReserve = kaminoMarket.getReserveByMint(NATIVE_MINT);
637
- const depositTokenIsSol = !solTokenReserve ? false : selectedTokenMint.equals(solTokenReserve!.getLiquidityMint());
573
+ const inputTokenIsSol = selectedTokenMint.equals(NATIVE_MINT);
638
574
 
639
575
  const calcs = withdrawLeverageCalcs(
640
576
  kaminoMarket,
@@ -662,7 +598,7 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
662
598
  referrer,
663
599
  currentSlot,
664
600
  isClosingPosition,
665
- depositTokenIsSol,
601
+ inputTokenIsSol,
666
602
  scopeRefreshConfig,
667
603
  calcs,
668
604
  budgetAndPriorityFeeIxs,
@@ -678,16 +614,13 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
678
614
 
679
615
  const uniqueKlendAccounts = uniqueAccountsWithProgramIds(klendIxs.instructions);
680
616
 
681
- const swapInputAmount = toLamports(
682
- calcs.collTokenSwapIn,
683
- collReserve!.state.liquidity.mintDecimals.toNumber()
684
- ).ceil();
617
+ const swapInputAmount = toLamports(calcs.collTokenSwapIn, collReserve!.getMintDecimals()).ceil();
685
618
 
686
619
  const swapInputsForQuote: SwapInputs = {
687
620
  inputAmountLamports: swapInputAmount.mul(new Decimal(1).add(quoteBufferBps.div(FullBPS))),
688
621
  inputMint: collTokenMint,
689
622
  outputMint: debtTokenMint,
690
- amountDebtAtaBalance: new Decimal(0), // Only needed for ktokens deposits
623
+ amountDebtAtaBalance: undefined, // Only needed for ktokens deposits
691
624
  };
692
625
 
693
626
  const swapQuote = await quoter(swapInputsForQuote, uniqueKlendAccounts);
@@ -709,10 +642,7 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
709
642
  slippagePct
710
643
  );
711
644
 
712
- const swapInputAmountQuotePrice = toLamports(
713
- calcsQuotePrice.collTokenSwapIn,
714
- collReserve!.state.liquidity.mintDecimals.toNumber()
715
- ).ceil();
645
+ const swapInputAmountQuotePrice = toLamports(calcsQuotePrice.collTokenSwapIn, collReserve!.getMintDecimals()).ceil();
716
646
 
717
647
  return {
718
648
  swapInputs: {
@@ -762,8 +692,7 @@ export async function getWithdrawWithLeverageIxs<QuoteResponse>({
762
692
  const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
763
693
  const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
764
694
 
765
- const solTokenReserve = kaminoMarket.getReserveByMint(NATIVE_MINT);
766
- const depositTokenIsSol = !solTokenReserve ? false : selectedTokenMint.equals(solTokenReserve!.getLiquidityMint());
695
+ const inputTokenIsSol = selectedTokenMint.equals(NATIVE_MINT);
767
696
  const { swapInputs, initialInputs } = await getWithdrawWithLeverageSwapInputs({
768
697
  owner,
769
698
  kaminoMarket,
@@ -826,7 +755,7 @@ export async function getWithdrawWithLeverageIxs<QuoteResponse>({
826
755
  referrer,
827
756
  currentSlot,
828
757
  isClosingPosition,
829
- depositTokenIsSol,
758
+ inputTokenIsSol,
830
759
  scopeRefreshConfig,
831
760
  initialInputs.calcs,
832
761
  budgetAndPriorityFeeIxs,
@@ -877,54 +806,20 @@ export async function buildWithdrawWithLeverageIxs(
877
806
  debtReserve.getLiquidityTokenProgram()
878
807
  );
879
808
  // 1. Create atas & budget txns & user metadata
880
- let mintsToCreateAtas: Array<{ mint: PublicKey; tokenProgram: PublicKey }>;
881
- if (collIsKtoken) {
882
- const secondTokenAta = strategy!.strategy.tokenAMint.equals(debtTokenMint)
883
- ? strategy!.strategy.tokenBMint
884
- : strategy!.strategy.tokenAMint;
885
- const secondTokenTokenProgram = strategy!.strategy.tokenAMint.equals(debtTokenMint)
886
- ? strategy!.strategy.tokenBTokenProgram.equals(PublicKey.default)
887
- ? TOKEN_PROGRAM_ID
888
- : strategy!.strategy.tokenBTokenProgram
889
- : strategy!.strategy.tokenATokenProgram.equals(PublicKey.default)
890
- ? TOKEN_PROGRAM_ID
891
- : strategy!.strategy.tokenATokenProgram;
892
- mintsToCreateAtas = [
893
- {
894
- mint: collTokenMint,
895
- tokenProgram: collReserve.getLiquidityTokenProgram(),
896
- },
897
- {
898
- mint: debtTokenMint,
899
- tokenProgram: debtReserve.getLiquidityTokenProgram(),
900
- },
901
- {
902
- mint: collReserve.getCTokenMint(),
903
- tokenProgram: TOKEN_PROGRAM_ID,
904
- },
905
- {
906
- mint: secondTokenAta,
907
- tokenProgram: secondTokenTokenProgram,
908
- },
909
- ];
910
- } else {
911
- mintsToCreateAtas = [
912
- {
913
- mint: collTokenMint,
914
- tokenProgram: collReserve!.getLiquidityTokenProgram(),
915
- },
916
- {
917
- mint: debtTokenMint,
918
- tokenProgram: debtReserve!.getLiquidityTokenProgram(),
919
- },
920
- {
921
- mint: collReserve!.getCTokenMint(),
922
- tokenProgram: TOKEN_PROGRAM_ID,
923
- },
924
- ];
925
- }
926
809
 
927
- const atasAndCreateIxs = createAtasIdempotent(owner, mintsToCreateAtas);
810
+ const { budgetIxs, createAtasIxs, scopeRefreshIx } = await getSetupIxs(
811
+ owner,
812
+ market,
813
+ obligation,
814
+ collTokenMint,
815
+ collReserve,
816
+ collIsKtoken,
817
+ debtTokenMint,
818
+ debtReserve,
819
+ strategy,
820
+ scopeRefreshConfig,
821
+ budgetAndPriorityFeeIxs
822
+ );
928
823
 
929
824
  const closeWsolAtaIxs: TransactionInstruction[] = [];
930
825
  if (depositTokenIsSol || debtTokenMint.equals(NATIVE_MINT)) {
@@ -932,8 +827,6 @@ export async function buildWithdrawWithLeverageIxs(
932
827
  closeWsolAtaIxs.push(createCloseAccountInstruction(wsolAta, owner, owner, [], TOKEN_PROGRAM_ID));
933
828
  }
934
829
 
935
- const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(3000000);
936
-
937
830
  // TODO: Mihai/Marius check if we can improve this logic and not convert any SOL
938
831
  // This is here so that we have enough wsol to repay in case the kAB swapped to sol after estimates is not enough
939
832
  const fillWsolAtaIxs: TransactionInstruction[] = [];
@@ -949,14 +842,12 @@ export async function buildWithdrawWithLeverageIxs(
949
842
  );
950
843
  }
951
844
 
952
- const scopeRefreshIxn = await getScopeRefreshIx(market, collReserve, debtReserve, obligation, scopeRefreshConfig);
953
-
954
845
  // 2. Prepare the flash borrow and flash repay amounts and ixs
955
846
  // We borrow exactly how much we need to repay
956
847
  // and repay that + flash amount fee
957
- const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
958
- borrowIxnIndex:
959
- budgetIxs.length + atasAndCreateIxs.length + fillWsolAtaIxs.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
848
+ const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
849
+ borrowIxIndex:
850
+ budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
960
851
  walletPublicKey: owner,
961
852
  lendingMarketAuthority: market.getLendingMarketAuthority(),
962
853
  lendingMarketAddress: market.getAddress(),
@@ -990,7 +881,7 @@ export async function buildWithdrawWithLeverageIxs(
990
881
  referrer
991
882
  );
992
883
 
993
- const swapInstructions = removeBudgetAndAtaIxs(swapQuoteIxs.swapIxs, []);
884
+ const swapInstructions = removeBudgetIxs(swapQuoteIxs.swapIxs);
994
885
 
995
886
  return {
996
887
  flashLoanInfo: {
@@ -998,14 +889,14 @@ export async function buildWithdrawWithLeverageIxs(
998
889
  flashBorrowReserve: debtReserve.address,
999
890
  },
1000
891
  instructions: [
1001
- ...scopeRefreshIxn,
892
+ ...scopeRefreshIx,
1002
893
  ...budgetIxs,
1003
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
894
+ ...createAtasIxs,
1004
895
  ...fillWsolAtaIxs,
1005
- ...[flashBorrowIxn],
896
+ ...[flashBorrowIx],
1006
897
  ...KaminoAction.actionToIxs(repayAndWithdrawAction),
1007
898
  ...swapInstructions,
1008
- ...[flashRepayIxn],
899
+ ...[flashRepayIx],
1009
900
  ...closeWsolAtaIxs,
1010
901
  ],
1011
902
  };
@@ -1143,7 +1034,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1143
1034
 
1144
1035
  const swapInputAmountQuotePrice = toLamports(
1145
1036
  !collIsKtoken ? calcsQuotePrice.borrowAmount : calcsQuotePrice.amountToFlashBorrowDebt,
1146
- debtReserve.state.liquidity.mintDecimals.toNumber()
1037
+ debtReserve.getMintDecimals()
1147
1038
  ).ceil();
1148
1039
 
1149
1040
  let expectedDebtTokenAtaBalance = new Decimal(0);
@@ -1156,7 +1047,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1156
1047
  !collIsKtoken ? calcsQuotePrice.borrowAmount : calcsQuotePrice.amountToFlashBorrowDebt,
1157
1048
  debtReserve.stats.decimals
1158
1049
  ).floor(),
1159
- debtReserve.state.liquidity.mintDecimals.toNumber()
1050
+ debtReserve.getMintDecimals()
1160
1051
  );
1161
1052
  }
1162
1053
 
@@ -1218,7 +1109,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1218
1109
  inputAmountLamports: swapInputAmount.mul(new Decimal(1).add(quoteBufferBps.div(FullBPS))),
1219
1110
  inputMint: collTokenMint,
1220
1111
  outputMint: debtTokenMint,
1221
- amountDebtAtaBalance: new Decimal(0), // Only needed for ktokens deposits
1112
+ amountDebtAtaBalance: undefined, // Only needed for ktokens deposits
1222
1113
  };
1223
1114
 
1224
1115
  const swapQuote = await quoter(swapInputsForQuote, uniqueKlendAccounts);
@@ -1243,7 +1134,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1243
1134
 
1244
1135
  const swapInputAmountQuotePrice = toLamports(
1245
1136
  calcsQuotePrice.withdrawAmountWithSlippageAndFlashLoanFee,
1246
- collReserve.state.liquidity.mintDecimals.toNumber()
1137
+ collReserve.getMintDecimals()
1247
1138
  ).ceil();
1248
1139
 
1249
1140
  return {
@@ -1252,7 +1143,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1252
1143
  minOutAmountLamports: toLamports(calcsQuotePrice.adjustBorrowPosition.abs(), debtReserve.stats.decimals),
1253
1144
  inputMint: collTokenMint,
1254
1145
  outputMint: debtTokenMint,
1255
- amountDebtAtaBalance: new Decimal(0), // Only needed for ktokens deposits
1146
+ amountDebtAtaBalance: undefined, // Only needed for ktokens deposits
1256
1147
  },
1257
1148
  flashLoanInfo: klendIxs.flashLoanInfo,
1258
1149
  initialInputs: {
@@ -1442,83 +1333,39 @@ async function buildIncreaseLeverageIxs(
1442
1333
  budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
1443
1334
  useV2Ixs: boolean
1444
1335
  ): Promise<LeverageIxsOutput> {
1445
- const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
1446
- const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
1336
+ const collReserve = kaminoMarket.getExistingReserveByMint(collTokenMint);
1337
+ const debtReserve = kaminoMarket.getExistingReserveByMint(debtTokenMint);
1447
1338
  const debtTokenAta = getAssociatedTokenAddressSync(
1448
1339
  debtTokenMint,
1449
1340
  owner,
1450
1341
  false,
1451
- debtReserve!.getLiquidityTokenProgram()
1342
+ debtReserve.getLiquidityTokenProgram()
1452
1343
  );
1453
1344
  const collTokenAta = getAssociatedTokenAddressSync(
1454
1345
  collTokenMint,
1455
1346
  owner,
1456
1347
  false,
1457
- collReserve!.getLiquidityTokenProgram()
1348
+ collReserve.getLiquidityTokenProgram()
1458
1349
  );
1459
1350
 
1460
1351
  // 1. Create atas & budget txns
1461
- const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(3000000);
1462
- let mintsToCreateAtas: Array<{ mint: PublicKey; tokenProgram: PublicKey }>;
1463
- if (collIsKtoken) {
1464
- const secondTokenAta = strategy!.strategy.tokenAMint.equals(debtTokenMint)
1465
- ? strategy!.strategy.tokenBMint
1466
- : strategy!.strategy.tokenAMint;
1467
- const secondTokenTokenProgarm = strategy?.strategy.tokenAMint.equals(debtTokenMint)
1468
- ? strategy!.strategy.tokenBTokenProgram.equals(PublicKey.default)
1469
- ? TOKEN_PROGRAM_ID
1470
- : strategy!.strategy.tokenBTokenProgram
1471
- : strategy!.strategy.tokenATokenProgram.equals(PublicKey.default)
1472
- ? TOKEN_PROGRAM_ID
1473
- : strategy!.strategy.tokenATokenProgram;
1474
- mintsToCreateAtas = [
1475
- {
1476
- mint: collTokenMint,
1477
- tokenProgram: collReserve!.getLiquidityTokenProgram(),
1478
- },
1479
- {
1480
- mint: debtTokenMint,
1481
- tokenProgram: debtReserve!.getLiquidityTokenProgram(),
1482
- },
1483
- {
1484
- mint: collReserve!.getCTokenMint(),
1485
- tokenProgram: TOKEN_PROGRAM_ID,
1486
- },
1487
- {
1488
- mint: secondTokenAta,
1489
- tokenProgram: secondTokenTokenProgarm,
1490
- },
1491
- ];
1492
- } else {
1493
- mintsToCreateAtas = [
1494
- {
1495
- mint: collTokenMint,
1496
- tokenProgram: collReserve!.getLiquidityTokenProgram(),
1497
- },
1498
- {
1499
- mint: debtTokenMint,
1500
- tokenProgram: debtReserve!.getLiquidityTokenProgram(),
1501
- },
1502
- {
1503
- mint: collReserve!.getCTokenMint(),
1504
- tokenProgram: TOKEN_PROGRAM_ID,
1505
- },
1506
- ];
1507
- }
1508
-
1509
- const atasAndCreateIxs = createAtasIdempotent(owner, mintsToCreateAtas);
1510
-
1511
- const scopeRefreshIxn = await getScopeRefreshIx(
1352
+ const { budgetIxs, createAtasIxs, scopeRefreshIx } = await getSetupIxs(
1353
+ owner,
1512
1354
  kaminoMarket,
1513
- collReserve!,
1514
- debtReserve!,
1515
1355
  obligation,
1516
- scopeRefreshConfig
1356
+ collTokenMint,
1357
+ collReserve,
1358
+ collIsKtoken,
1359
+ debtTokenMint,
1360
+ debtReserve,
1361
+ strategy,
1362
+ scopeRefreshConfig,
1363
+ budgetAndPriorityFeeIxs
1517
1364
  );
1518
1365
 
1519
1366
  // 2. Create borrow flash loan instruction
1520
- const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1521
- borrowIxnIndex: budgetIxs.length + atasAndCreateIxs.length + (scopeRefreshIxn.length > 0 ? 1 : 0), // TODO: how about user metadata ixs
1367
+ const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
1368
+ borrowIxIndex: budgetIxs.length + createAtasIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0), // TODO: how about user metadata ixs
1522
1369
  walletPublicKey: owner,
1523
1370
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1524
1371
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1567,29 +1414,19 @@ async function buildIncreaseLeverageIxs(
1567
1414
  currentSlot
1568
1415
  );
1569
1416
 
1570
- const swapInstructions = removeBudgetAndAtaIxs(swapQuoteIxs.swapIxs, []);
1571
-
1572
- const ixs = !collIsKtoken
1573
- ? [
1574
- ...scopeRefreshIxn,
1575
- ...budgetIxs,
1576
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
1577
- ...[flashBorrowIxn],
1578
- ...KaminoAction.actionToIxs(depositAction),
1579
- ...KaminoAction.actionToIxs(borrowAction),
1580
- ...swapInstructions,
1581
- ...[flashRepayIxn],
1582
- ]
1583
- : [
1584
- ...scopeRefreshIxn,
1585
- ...budgetIxs,
1586
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
1587
- ...[flashBorrowIxn],
1588
- ...swapInstructions,
1589
- ...KaminoAction.actionToIxs(depositAction),
1590
- ...KaminoAction.actionToIxs(borrowAction),
1591
- ...[flashRepayIxn],
1592
- ];
1417
+ const swapInstructions = removeBudgetIxs(swapQuoteIxs.swapIxs);
1418
+
1419
+ const ixs = [
1420
+ ...scopeRefreshIx,
1421
+ ...budgetIxs,
1422
+ ...createAtasIxs,
1423
+ ...[flashBorrowIx],
1424
+ ...(collIsKtoken ? swapInstructions : []),
1425
+ ...KaminoAction.actionToIxs(depositAction),
1426
+ ...KaminoAction.actionToIxs(borrowAction),
1427
+ ...(collIsKtoken ? [] : swapInstructions),
1428
+ ...[flashRepayIx],
1429
+ ];
1593
1430
 
1594
1431
  const flashBorrowReserve = !collIsKtoken ? collReserve! : debtReserve!;
1595
1432
  const res: LeverageIxsOutput = {
@@ -1622,64 +1459,29 @@ async function buildDecreaseLeverageIxs(
1622
1459
  budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
1623
1460
  useV2Ixs: boolean
1624
1461
  ): Promise<LeverageIxsOutput> {
1625
- const collReserve = kaminoMarket.getReserveByMint(collTokenMint);
1626
- const debtReserve = kaminoMarket.getReserveByMint(debtTokenMint);
1462
+ const collReserve = kaminoMarket.getExistingReserveByMint(collTokenMint);
1463
+ const debtReserve = kaminoMarket.getExistingReserveByMint(debtTokenMint);
1627
1464
  const debtTokenAta = getAssociatedTokenAddressSync(
1628
1465
  debtTokenMint,
1629
1466
  owner,
1630
1467
  false,
1631
- debtReserve!.getLiquidityTokenProgram()
1468
+ debtReserve.getLiquidityTokenProgram()
1632
1469
  );
1633
1470
 
1634
1471
  // 1. Create atas & budget txns
1635
- const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(3000000);
1636
- let mintsToCreateAtas: Array<{ mint: PublicKey; tokenProgram: PublicKey }>;
1637
- if (collIsKtoken) {
1638
- const secondTokenAta = strategy!.strategy.tokenAMint.equals(debtTokenMint)
1639
- ? strategy!.strategy.tokenBMint
1640
- : strategy!.strategy.tokenAMint;
1641
- const secondTokenTokenProgarm = strategy?.strategy.tokenAMint.equals(debtTokenMint)
1642
- ? strategy!.strategy.tokenBTokenProgram.equals(PublicKey.default)
1643
- ? TOKEN_PROGRAM_ID
1644
- : strategy!.strategy.tokenBTokenProgram
1645
- : strategy!.strategy.tokenATokenProgram.equals(PublicKey.default)
1646
- ? TOKEN_PROGRAM_ID
1647
- : strategy!.strategy.tokenATokenProgram;
1648
- mintsToCreateAtas = [
1649
- {
1650
- mint: collTokenMint,
1651
- tokenProgram: collReserve!.getLiquidityTokenProgram(),
1652
- },
1653
- {
1654
- mint: debtTokenMint,
1655
- tokenProgram: debtReserve!.getLiquidityTokenProgram(),
1656
- },
1657
- {
1658
- mint: collReserve!.getCTokenMint(),
1659
- tokenProgram: TOKEN_PROGRAM_ID,
1660
- },
1661
- {
1662
- mint: secondTokenAta,
1663
- tokenProgram: secondTokenTokenProgarm,
1664
- },
1665
- ];
1666
- } else {
1667
- mintsToCreateAtas = [
1668
- {
1669
- mint: collTokenMint,
1670
- tokenProgram: collReserve!.getLiquidityTokenProgram(),
1671
- },
1672
- {
1673
- mint: debtTokenMint,
1674
- tokenProgram: debtReserve!.getLiquidityTokenProgram(),
1675
- },
1676
- {
1677
- mint: collReserve!.getCTokenMint(),
1678
- tokenProgram: TOKEN_PROGRAM_ID,
1679
- },
1680
- ];
1681
- }
1682
- const atasAndCreateIxs = createAtasIdempotent(owner, mintsToCreateAtas);
1472
+ const { budgetIxs, createAtasIxs, scopeRefreshIx } = await getSetupIxs(
1473
+ owner,
1474
+ kaminoMarket,
1475
+ obligation,
1476
+ collTokenMint,
1477
+ collReserve,
1478
+ collIsKtoken,
1479
+ debtTokenMint,
1480
+ debtReserve,
1481
+ strategy,
1482
+ scopeRefreshConfig,
1483
+ budgetAndPriorityFeeIxs
1484
+ );
1683
1485
 
1684
1486
  // TODO: Mihai/Marius check if we can improve this logic and not convert any SOL
1685
1487
  // This is here so that we have enough wsol to repay in case the kAB swapped to sol after estimates is not enough
@@ -1697,18 +1499,10 @@ async function buildDecreaseLeverageIxs(
1697
1499
  );
1698
1500
  }
1699
1501
 
1700
- const scopeRefreshIxn = await getScopeRefreshIx(
1701
- kaminoMarket,
1702
- collReserve!,
1703
- debtReserve!,
1704
- obligation,
1705
- scopeRefreshConfig
1706
- );
1707
-
1708
1502
  // 3. Flash borrow & repay amount to repay (debt)
1709
- const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1710
- borrowIxnIndex:
1711
- budgetIxs.length + atasAndCreateIxs.length + fillWsolAtaIxs.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
1503
+ const { flashBorrowIx, flashRepayIx } = getFlashLoanInstructions({
1504
+ borrowIxIndex:
1505
+ budgetIxs.length + createAtasIxs.length + fillWsolAtaIxs.length + (scopeRefreshIx.length > 0 ? 1 : 0),
1712
1506
  walletPublicKey: owner,
1713
1507
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1714
1508
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1756,18 +1550,18 @@ async function buildDecreaseLeverageIxs(
1756
1550
  currentSlot
1757
1551
  );
1758
1552
 
1759
- const swapInstructions = removeBudgetAndAtaIxs(swapQuoteIxs.swapIxs, []);
1553
+ const swapInstructions = removeBudgetIxs(swapQuoteIxs.swapIxs);
1760
1554
 
1761
1555
  const ixs = [
1762
- ...scopeRefreshIxn,
1556
+ ...scopeRefreshIx,
1763
1557
  ...budgetIxs,
1764
- ...atasAndCreateIxs.map((x) => x.createAtaIx),
1558
+ ...createAtasIxs,
1765
1559
  ...fillWsolAtaIxs,
1766
- ...[flashBorrowIxn],
1560
+ ...[flashBorrowIx],
1767
1561
  ...KaminoAction.actionToIxs(repayAction),
1768
1562
  ...KaminoAction.actionToIxs(withdrawAction),
1769
1563
  ...swapInstructions,
1770
- ...[flashRepayIxn],
1564
+ ...[flashRepayIx],
1771
1565
  ...closeWsolAtaIxs,
1772
1566
  ];
1773
1567
 
@@ -1782,6 +1576,47 @@ async function buildDecreaseLeverageIxs(
1782
1576
  return res;
1783
1577
  }
1784
1578
 
1579
+ export const getSetupIxs = async (
1580
+ owner: PublicKey,
1581
+ kaminoMarket: KaminoMarket,
1582
+ obligation: KaminoObligation | ObligationType | undefined,
1583
+ collTokenMint: PublicKey,
1584
+ collReserve: KaminoReserve,
1585
+ collIsKtoken: boolean,
1586
+ debtTokenMint: PublicKey,
1587
+ debtReserve: KaminoReserve,
1588
+ strategy: StrategyWithAddress | undefined,
1589
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1590
+ budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined
1591
+ ) => {
1592
+ const budgetIxs = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxs(3000000);
1593
+
1594
+ const mintsWithTokenPrograms = getTokenMintsWithTokenPrograms(
1595
+ collTokenMint,
1596
+ collReserve,
1597
+ debtTokenMint,
1598
+ debtReserve,
1599
+ collIsKtoken,
1600
+ strategy
1601
+ );
1602
+
1603
+ const createAtasIxs = createAtasIdempotent(owner, mintsWithTokenPrograms).map((x) => x.createAtaIx);
1604
+
1605
+ const scopeRefreshIx = await getScopeRefreshIx(
1606
+ kaminoMarket,
1607
+ collReserve,
1608
+ debtReserve,
1609
+ obligation,
1610
+ scopeRefreshConfig
1611
+ );
1612
+
1613
+ return {
1614
+ budgetIxs,
1615
+ createAtasIxs,
1616
+ scopeRefreshIx,
1617
+ };
1618
+ };
1619
+
1785
1620
  export const getScopeRefreshIx = async (
1786
1621
  market: KaminoMarket,
1787
1622
  collReserve: KaminoReserve,
@@ -1814,3 +1649,75 @@ export const getScopeRefreshIx = async (
1814
1649
 
1815
1650
  return scopeRefreshIxs;
1816
1651
  };
1652
+
1653
+ const checkObligationType = (
1654
+ obligationTypeTag: ObligationTypeTag,
1655
+ collTokenMint: PublicKey,
1656
+ debtTokenMint: PublicKey,
1657
+ kaminoMarket: KaminoMarket
1658
+ ) => {
1659
+ let obligationType: ObligationType;
1660
+ if (obligationTypeTag === ObligationTypeTag.Multiply) {
1661
+ // multiply
1662
+ obligationType = new MultiplyObligation(collTokenMint, debtTokenMint, kaminoMarket.programId);
1663
+ } else if (obligationTypeTag === ObligationTypeTag.Leverage) {
1664
+ // leverage
1665
+ obligationType = new LeverageObligation(collTokenMint, debtTokenMint, kaminoMarket.programId);
1666
+ } else {
1667
+ throw Error('Obligation type tag not supported for leverage, please use 1 - multiply or 3 - leverage');
1668
+ }
1669
+
1670
+ return obligationType;
1671
+ };
1672
+
1673
+ type MintWithTokenProgram = {
1674
+ mint: PublicKey;
1675
+ tokenProgram: PublicKey;
1676
+ };
1677
+
1678
+ const getTokenMintsWithTokenPrograms = (
1679
+ collTokenMint: PublicKey,
1680
+ collReserve: KaminoReserve,
1681
+ debtTokenMint: PublicKey,
1682
+ debtReserve: KaminoReserve,
1683
+ collIsKtoken: boolean,
1684
+ strategy: StrategyWithAddress | undefined
1685
+ ): Array<MintWithTokenProgram> => {
1686
+ const mintsWithTokenPrograms = [
1687
+ {
1688
+ mint: collTokenMint,
1689
+ tokenProgram: collReserve.getLiquidityTokenProgram(),
1690
+ },
1691
+ {
1692
+ mint: debtTokenMint,
1693
+ tokenProgram: debtReserve.getLiquidityTokenProgram(),
1694
+ },
1695
+ {
1696
+ mint: collReserve.getCTokenMint(),
1697
+ tokenProgram: TOKEN_PROGRAM_ID,
1698
+ },
1699
+ ];
1700
+
1701
+ if (collIsKtoken) {
1702
+ let kTokenAta: PublicKey;
1703
+ let kTokenTokenProgram: PublicKey;
1704
+ if (strategy!.strategy.tokenAMint.equals(debtTokenMint)) {
1705
+ kTokenAta = strategy!.strategy.tokenBMint;
1706
+ kTokenTokenProgram = strategy!.strategy.tokenBTokenProgram.equals(PublicKey.default)
1707
+ ? TOKEN_PROGRAM_ID
1708
+ : strategy!.strategy.tokenBTokenProgram;
1709
+ } else {
1710
+ kTokenAta = strategy!.strategy.tokenAMint;
1711
+ kTokenTokenProgram = strategy!.strategy.tokenATokenProgram.equals(PublicKey.default)
1712
+ ? TOKEN_PROGRAM_ID
1713
+ : strategy!.strategy.tokenATokenProgram;
1714
+ }
1715
+
1716
+ mintsWithTokenPrograms.push({
1717
+ mint: kTokenAta,
1718
+ tokenProgram: kTokenTokenProgram,
1719
+ });
1720
+ }
1721
+
1722
+ return mintsWithTokenPrograms;
1723
+ };