@kamino-finance/klend-sdk 5.11.3-beta.1 → 5.11.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.
Files changed (62) hide show
  1. package/dist/classes/action.d.ts +23 -23
  2. package/dist/classes/action.d.ts.map +1 -1
  3. package/dist/classes/action.js +122 -195
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/index.d.ts +1 -0
  6. package/dist/classes/index.d.ts.map +1 -1
  7. package/dist/classes/index.js +1 -0
  8. package/dist/classes/index.js.map +1 -1
  9. package/dist/classes/manager.d.ts +6 -1
  10. package/dist/classes/manager.d.ts.map +1 -1
  11. package/dist/classes/manager.js +16 -1
  12. package/dist/classes/manager.js.map +1 -1
  13. package/dist/classes/market.d.ts +3 -3
  14. package/dist/classes/market.d.ts.map +1 -1
  15. package/dist/classes/market.js +30 -16
  16. package/dist/classes/market.js.map +1 -1
  17. package/dist/classes/obligation.d.ts +2 -0
  18. package/dist/classes/obligation.d.ts.map +1 -1
  19. package/dist/classes/obligation.js +5 -0
  20. package/dist/classes/obligation.js.map +1 -1
  21. package/dist/lending_operations/repay_with_collateral_operations.d.ts +4 -4
  22. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  23. package/dist/lending_operations/repay_with_collateral_operations.js +10 -8
  24. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  25. package/dist/lending_operations/swap_collateral_operations.d.ts +2 -2
  26. package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
  27. package/dist/lending_operations/swap_collateral_operations.js +11 -6
  28. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  29. package/dist/leverage/calcs.d.ts +5 -10
  30. package/dist/leverage/calcs.d.ts.map +1 -1
  31. package/dist/leverage/calcs.js +6 -13
  32. package/dist/leverage/calcs.js.map +1 -1
  33. package/dist/leverage/operations.d.ts +9 -7
  34. package/dist/leverage/operations.d.ts.map +1 -1
  35. package/dist/leverage/operations.js +78 -72
  36. package/dist/leverage/operations.js.map +1 -1
  37. package/dist/leverage/types.d.ts +4 -4
  38. package/dist/leverage/types.d.ts.map +1 -1
  39. package/dist/utils/ObligationType.d.ts +1 -1
  40. package/dist/utils/ObligationType.d.ts.map +1 -1
  41. package/dist/utils/managerTypes.d.ts.map +1 -1
  42. package/dist/utils/managerTypes.js +7 -52
  43. package/dist/utils/managerTypes.js.map +1 -1
  44. package/dist/utils/oracle.d.ts +3 -3
  45. package/dist/utils/oracle.d.ts.map +1 -1
  46. package/dist/utils/oracle.js +4 -3
  47. package/dist/utils/oracle.js.map +1 -1
  48. package/package.json +2 -2
  49. package/src/classes/action.ts +143 -211
  50. package/src/classes/index.ts +1 -0
  51. package/src/classes/manager.ts +32 -1
  52. package/src/classes/market.ts +34 -25
  53. package/src/classes/obligation.ts +6 -0
  54. package/src/client.ts +8 -3
  55. package/src/lending_operations/repay_with_collateral_operations.ts +15 -11
  56. package/src/lending_operations/swap_collateral_operations.ts +19 -7
  57. package/src/leverage/calcs.ts +2 -18
  58. package/src/leverage/operations.ts +114 -72
  59. package/src/leverage/types.ts +4 -4
  60. package/src/utils/ObligationType.ts +1 -1
  61. package/src/utils/managerTypes.ts +10 -52
  62. package/src/utils/oracle.ts +7 -6
@@ -6,6 +6,8 @@ import {
6
6
  KaminoObligation,
7
7
  KaminoReserve,
8
8
  lamportsToNumberDecimal as fromLamports,
9
+ getTokenIdsForScopeRefresh,
10
+ isKaminoObligation,
9
11
  } from '../classes';
10
12
  import { getFlashLoanInstructions } from './instructions';
11
13
 
@@ -15,7 +17,9 @@ import {
15
17
  MultiplyObligation,
16
18
  ObligationType,
17
19
  ObligationTypeTag,
20
+ PublicKeySet,
18
21
  SOL_DECIMALS,
22
+ ScopePriceRefreshConfig,
19
23
  U64_MAX,
20
24
  createAtasIdempotent,
21
25
  getAssociatedTokenAddress,
@@ -80,7 +84,7 @@ export async function getDepositWithLeverageSwapInputs<QuoteResponse>({
80
84
  selectedTokenMint,
81
85
  kamino,
82
86
  obligationTypeTagOverride,
83
- scopeFeed,
87
+ scopeRefreshConfig,
84
88
  budgetAndPriorityFeeIxs,
85
89
  quoteBufferBps,
86
90
  priceAinB,
@@ -142,7 +146,7 @@ export async function getDepositWithLeverageSwapInputs<QuoteResponse>({
142
146
  referrer,
143
147
  currentSlot,
144
148
  depositTokenIsSol,
145
- scopeFeed,
149
+ scopeRefreshConfig,
146
150
  calcs,
147
151
  budgetAndPriorityFeeIxs,
148
152
  {
@@ -309,7 +313,7 @@ export async function getDepositWithLeverageIxns<QuoteResponse>({
309
313
  selectedTokenMint,
310
314
  kamino,
311
315
  obligationTypeTagOverride,
312
- scopeFeed,
316
+ scopeRefreshConfig,
313
317
  budgetAndPriorityFeeIxs,
314
318
  quoteBufferBps,
315
319
  priceAinB,
@@ -334,7 +338,7 @@ export async function getDepositWithLeverageIxns<QuoteResponse>({
334
338
  selectedTokenMint,
335
339
  kamino,
336
340
  obligationTypeTagOverride,
337
- scopeFeed,
341
+ scopeRefreshConfig,
338
342
  budgetAndPriorityFeeIxs,
339
343
  quoteBufferBps,
340
344
  priceAinB,
@@ -386,7 +390,7 @@ export async function getDepositWithLeverageIxns<QuoteResponse>({
386
390
  referrer,
387
391
  currentSlot,
388
392
  depositTokenIsSol,
389
- scopeFeed,
393
+ scopeRefreshConfig,
390
394
  initialInputs.calcs,
391
395
  budgetAndPriorityFeeIxs,
392
396
  {
@@ -417,7 +421,7 @@ async function buildDepositWithLeverageIxns(
417
421
  referrer: PublicKey,
418
422
  currentSlot: number,
419
423
  depositTokenIsSol: boolean,
420
- scopeFeed: string | undefined,
424
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
421
425
  calcs: DepositLeverageCalcsResult,
422
426
  budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
423
427
  swapQuoteIxs: SwapIxs,
@@ -442,7 +446,7 @@ async function buildDepositWithLeverageIxns(
442
446
  debtReserve.getLiquidityTokenProgram()
443
447
  );
444
448
 
445
- // 1. Create atas & budget txns
449
+ // 1. Create atas & budget ixns
446
450
  let mintsToCreateAtas: Array<{ mint: PublicKey; tokenProgram: PublicKey }>;
447
451
  if (collIsKtoken) {
448
452
  const secondTokenAta = strategy!.strategy.tokenAMint.equals(debtTokenMint)
@@ -503,10 +507,13 @@ async function buildDepositWithLeverageIxns(
503
507
  );
504
508
  }
505
509
 
510
+ const scopeRefreshIxn = await getScopeRefreshIx(market, collReserve, debtReserve, obligation, scopeRefreshConfig);
511
+
506
512
  // 2. Flash borrow & repay the collateral amount needed for given leverage
507
513
  // if user deposits coll, then we borrow the diff, else we borrow the entire amount
508
514
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
509
- borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length,
515
+ borrowIxnIndex:
516
+ budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
510
517
  walletPublicKey: owner,
511
518
  lendingMarketAuthority: market.getLendingMarketAuthority(),
512
519
  lendingMarketAddress: market.getAddress(),
@@ -523,7 +530,6 @@ async function buildDepositWithLeverageIxns(
523
530
  });
524
531
 
525
532
  // 3. Deposit initial tokens + borrowed tokens into reserve
526
- const scopeRefresh = scopeFeed ? { includeScopeRefresh: true, scopeFeed: scopeFeed } : undefined;
527
533
  const kaminoDepositAndBorrowAction = await KaminoAction.buildDepositAndBorrowTxns(
528
534
  market,
529
535
  toLamports(!collIsKtoken ? calcs.collTokenToDeposit : calcs.collTokenToDeposit, collReserve.stats.decimals)
@@ -537,14 +543,14 @@ async function buildDepositWithLeverageIxns(
537
543
  owner,
538
544
  obligation!,
539
545
  useV2Ixs,
546
+ undefined,
540
547
  0,
541
548
  false,
542
549
  elevationGroupOverride === 0 ? false : true, // emode
543
550
  false, // to be checked and created in a setup tx in the UI
544
551
  false, // to be checked and created in a setup tx in the UI
545
552
  referrer,
546
- currentSlot,
547
- scopeRefresh
553
+ currentSlot
548
554
  );
549
555
 
550
556
  // 4. Swap
@@ -553,18 +559,18 @@ async function buildDepositWithLeverageIxns(
553
559
 
554
560
  if (!collIsKtoken) {
555
561
  return [
562
+ ...scopeRefreshIxn,
556
563
  ...budgetIxns,
557
564
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
558
565
  ...fillWsolAtaIxns,
559
566
  ...[flashBorrowIxn],
560
- ...kaminoDepositAndBorrowAction.setupIxs,
561
- ...KaminoAction.actionToLendingIxs(kaminoDepositAndBorrowAction),
562
- ...kaminoDepositAndBorrowAction.cleanupIxs,
567
+ ...KaminoAction.actionToIxs(kaminoDepositAndBorrowAction),
563
568
  ...swapInstructions,
564
569
  ...[flashRepayIxn],
565
570
  ];
566
571
  } else {
567
572
  return [
573
+ ...scopeRefreshIxn,
568
574
  ...budgetIxns,
569
575
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
570
576
  ...fillWsolAtaIxns,
@@ -595,7 +601,7 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
595
601
  selectedTokenMint,
596
602
  budgetAndPriorityFeeIxs,
597
603
  kamino,
598
- scopeFeed,
604
+ scopeRefreshConfig,
599
605
  quoteBufferBps,
600
606
  isKtoken,
601
607
  quoter,
@@ -641,7 +647,7 @@ export async function getWithdrawWithLeverageSwapInputs<QuoteResponse>({
641
647
  currentSlot,
642
648
  isClosingPosition,
643
649
  depositTokenIsSol,
644
- scopeFeed,
650
+ scopeRefreshConfig,
645
651
  calcs,
646
652
  budgetAndPriorityFeeIxs,
647
653
  {
@@ -729,7 +735,7 @@ export async function getWithdrawWithLeverageIxns<QuoteResponse>({
729
735
  selectedTokenMint,
730
736
  budgetAndPriorityFeeIxs,
731
737
  kamino,
732
- scopeFeed,
738
+ scopeRefreshConfig,
733
739
  quoteBufferBps,
734
740
  isKtoken,
735
741
  quoter,
@@ -758,7 +764,7 @@ export async function getWithdrawWithLeverageIxns<QuoteResponse>({
758
764
  selectedTokenMint,
759
765
  budgetAndPriorityFeeIxs,
760
766
  kamino,
761
- scopeFeed,
767
+ scopeRefreshConfig,
762
768
  quoteBufferBps,
763
769
  isKtoken,
764
770
  quoter,
@@ -804,7 +810,7 @@ export async function getWithdrawWithLeverageIxns<QuoteResponse>({
804
810
  currentSlot,
805
811
  isClosingPosition,
806
812
  depositTokenIsSol,
807
- scopeFeed,
813
+ scopeRefreshConfig,
808
814
  initialInputs.calcs,
809
815
  budgetAndPriorityFeeIxs,
810
816
  {
@@ -836,7 +842,7 @@ export async function buildWithdrawWithLeverageIxns(
836
842
  currentSlot: number,
837
843
  isClosingPosition: boolean,
838
844
  depositTokenIsSol: boolean,
839
- scopeFeed: string | undefined,
845
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
840
846
  calcs: WithdrawLeverageCalcsResult,
841
847
  budgetAndPriorityFeeIxs: TransactionInstruction[] | undefined,
842
848
  swapQuoteIxs: SwapIxs,
@@ -910,7 +916,7 @@ export async function buildWithdrawWithLeverageIxns(
910
916
 
911
917
  const budgetIxns = budgetAndPriorityFeeIxs || getComputeBudgetAndPriorityFeeIxns(3000000);
912
918
 
913
- // TODO: Might be worth removing as it's only needed for Ktokens
919
+ // TODO: Mihai/Marius check if we can improve this logic and not convert any SOL
914
920
  // This is here so that we have enough wsol to repay in case the kAB swapped to sol after estimates is not enough
915
921
  const fillWsolAtaIxns: TransactionInstruction[] = [];
916
922
  if (debtTokenMint.equals(NATIVE_MINT)) {
@@ -925,11 +931,14 @@ export async function buildWithdrawWithLeverageIxns(
925
931
  );
926
932
  }
927
933
 
934
+ const scopeRefreshIxn = await getScopeRefreshIx(market, collReserve, debtReserve, obligation, scopeRefreshConfig);
935
+
928
936
  // 2. Prepare the flash borrow and flash repay amounts and ixns
929
937
  // We borrow exactly how much we need to repay
930
938
  // and repay that + flash amount fee
931
939
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
932
- borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length,
940
+ borrowIxnIndex:
941
+ budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
933
942
  walletPublicKey: owner,
934
943
  lendingMarketAuthority: market.getLendingMarketAuthority(),
935
944
  lendingMarketAddress: market.getAddress(),
@@ -942,7 +951,7 @@ export async function buildWithdrawWithLeverageIxns(
942
951
  programId: market.programId,
943
952
  });
944
953
 
945
- // 6. Repay borrowed tokens and Withdraw tokens from reserve that will be swapped to repay flash loan
954
+ // 3. Repay borrowed tokens and Withdraw tokens from reserve that will be swapped to repay flash loan
946
955
  const repayAndWithdrawAction = await KaminoAction.buildRepayAndWithdrawTxns(
947
956
  market,
948
957
  isClosingPosition ? U64_MAX : toLamports(calcs.repayAmount, debtReserve!.stats.decimals).floor().toString(),
@@ -955,25 +964,24 @@ export async function buildWithdrawWithLeverageIxns(
955
964
  currentSlot,
956
965
  obligation,
957
966
  useV2Ixs,
967
+ undefined,
958
968
  0,
959
969
  false,
960
970
  false, // to be checked and created in a setup tx in the UI (won't be the case for withdraw anyway as this would be created in deposit)
961
971
  false, // to be checked and created in a setup tx in the UI (won't be the case for withdraw anyway as this would be created in deposit)
962
972
  isClosingPosition,
963
- referrer,
964
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
973
+ referrer
965
974
  );
966
975
 
967
976
  const swapInstructions = removeBudgetAndAtaIxns(swapQuoteIxs.swapIxs, []);
968
977
 
969
978
  return [
979
+ ...scopeRefreshIxn,
970
980
  ...budgetIxns,
971
981
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
972
982
  ...fillWsolAtaIxns,
973
983
  ...[flashBorrowIxn],
974
- ...repayAndWithdrawAction.setupIxs,
975
- ...KaminoAction.actionToLendingIxs(repayAndWithdrawAction),
976
- ...repayAndWithdrawAction.cleanupIxs,
984
+ ...KaminoAction.actionToIxs(repayAndWithdrawAction),
977
985
  ...swapInstructions,
978
986
  ...[flashRepayIxn],
979
987
  ...closeWsolAtaIxns,
@@ -996,7 +1004,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
996
1004
  slippagePct,
997
1005
  budgetAndPriorityFeeIxs,
998
1006
  kamino,
999
- scopeFeed,
1007
+ scopeRefreshConfig,
1000
1008
  quoteBufferBps,
1001
1009
  isKtoken,
1002
1010
  quoter,
@@ -1016,13 +1024,10 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1016
1024
  const currentLeverage = obligation.refreshedStats.leverage;
1017
1025
  const isDepositViaLeverage = targetLeverage.gte(new Decimal(currentLeverage));
1018
1026
  let flashLoanFee;
1019
- let borrowFee;
1020
1027
  if (isDepositViaLeverage) {
1021
1028
  flashLoanFee = collReserve.getFlashLoanFee() || new Decimal(0);
1022
- borrowFee = collReserve.getBorrowFee() || new Decimal(0);
1023
1029
  } else {
1024
1030
  flashLoanFee = debtReserve.getFlashLoanFee() || new Decimal(0);
1025
- borrowFee = debtReserve.getBorrowFee() || new Decimal(0);
1026
1031
  }
1027
1032
 
1028
1033
  const { adjustDepositPosition, adjustBorrowPosition } = calcAdjustAmounts({
@@ -1031,7 +1036,6 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1031
1036
  targetLeverage: targetLeverage,
1032
1037
  priceCollToDebt: priceCollToDebt,
1033
1038
  flashLoanFee: new Decimal(flashLoanFee),
1034
- borrowFee,
1035
1039
  });
1036
1040
 
1037
1041
  const isDeposit = adjustDepositPosition.gte(0) && adjustBorrowPosition.gte(0);
@@ -1063,7 +1067,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1063
1067
  currentSlot,
1064
1068
  calcs,
1065
1069
  strategy,
1066
- scopeFeed,
1070
+ scopeRefreshConfig,
1067
1071
  collIsKtoken,
1068
1072
  {
1069
1073
  preActionIxs: [],
@@ -1099,7 +1103,6 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1099
1103
  targetLeverage: targetLeverage,
1100
1104
  priceCollToDebt: new Decimal(1).div(swapQuote.priceAInB),
1101
1105
  flashLoanFee: new Decimal(flashLoanFee),
1102
- borrowFee,
1103
1106
  });
1104
1107
 
1105
1108
  const calcsQuotePrice = await adjustDepositLeverageCalcs(
@@ -1168,7 +1171,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1168
1171
  currentSlot,
1169
1172
  calcs,
1170
1173
  strategy,
1171
- scopeFeed,
1174
+ scopeRefreshConfig,
1172
1175
  collIsKtoken,
1173
1176
  {
1174
1177
  preActionIxs: [],
@@ -1204,7 +1207,6 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1204
1207
  targetLeverage: targetLeverage,
1205
1208
  priceCollToDebt: swapQuote.priceAInB,
1206
1209
  flashLoanFee: new Decimal(flashLoanFee),
1207
- borrowFee,
1208
1210
  });
1209
1211
 
1210
1212
  const calcsQuotePrice = adjustWithdrawLeverageCalcs(
@@ -1257,7 +1259,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1257
1259
  slippagePct,
1258
1260
  budgetAndPriorityFeeIxs,
1259
1261
  kamino,
1260
- scopeFeed,
1262
+ scopeRefreshConfig,
1261
1263
  quoteBufferBps,
1262
1264
  priceAinB,
1263
1265
  isKtoken,
@@ -1281,7 +1283,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1281
1283
  slippagePct,
1282
1284
  budgetAndPriorityFeeIxs,
1283
1285
  kamino,
1284
- scopeFeed,
1286
+ scopeRefreshConfig,
1285
1287
  quoteBufferBps,
1286
1288
  priceAinB,
1287
1289
  isKtoken,
@@ -1327,7 +1329,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1327
1329
  currentSlot,
1328
1330
  initialInputs.calcs,
1329
1331
  initialInputs.strategy,
1330
- scopeFeed,
1332
+ scopeRefreshConfig,
1331
1333
  initialInputs.collIsKtoken,
1332
1334
  {
1333
1335
  preActionIxs: [],
@@ -1374,7 +1376,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1374
1376
  currentSlot,
1375
1377
  initialInputs.calcs,
1376
1378
  initialInputs.strategy,
1377
- scopeFeed,
1379
+ scopeRefreshConfig,
1378
1380
  initialInputs.collIsKtoken,
1379
1381
  {
1380
1382
  preActionIxs: [],
@@ -1407,7 +1409,7 @@ async function buildIncreaseLeverageIxns(
1407
1409
  currentSlot: number,
1408
1410
  calcs: AdjustLeverageCalcsResult,
1409
1411
  strategy: StrategyWithAddress | undefined,
1410
- scopeFeed: string | undefined,
1412
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1411
1413
  collIsKtoken: boolean,
1412
1414
  swapQuoteIxs: SwapIxs,
1413
1415
  budgetAndPriorityFeeIxns: TransactionInstruction[] | undefined,
@@ -1479,9 +1481,17 @@ async function buildIncreaseLeverageIxns(
1479
1481
 
1480
1482
  const atasAndCreateIxns = createAtasIdempotent(owner, mintsToCreateAtas);
1481
1483
 
1484
+ const scopeRefreshIxn = await getScopeRefreshIx(
1485
+ kaminoMarket,
1486
+ collReserve!,
1487
+ debtReserve!,
1488
+ obligation,
1489
+ scopeRefreshConfig
1490
+ );
1491
+
1482
1492
  // 2. Create borrow flash loan instruction
1483
1493
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1484
- borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length, // TODO: how about user metadata ixns
1494
+ borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length + (scopeRefreshIxn.length > 0 ? 1 : 0), // TODO: how about user metadata ixns
1485
1495
  walletPublicKey: owner,
1486
1496
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1487
1497
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1504,14 +1514,14 @@ async function buildIncreaseLeverageIxns(
1504
1514
  owner,
1505
1515
  obligation,
1506
1516
  useV2Ixs,
1517
+ undefined,
1507
1518
  0,
1508
1519
  false,
1509
1520
  false,
1510
1521
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1511
1522
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1512
1523
  referrer,
1513
- currentSlot,
1514
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1524
+ currentSlot
1515
1525
  );
1516
1526
 
1517
1527
  // 4. Borrow tokens in borrow token reserve that will be swapped to repay flash loan
@@ -1522,43 +1532,37 @@ async function buildIncreaseLeverageIxns(
1522
1532
  owner,
1523
1533
  obligation,
1524
1534
  useV2Ixs,
1535
+ undefined,
1525
1536
  0,
1526
1537
  false,
1527
1538
  false,
1528
1539
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1529
1540
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1530
1541
  referrer,
1531
- currentSlot,
1532
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1542
+ currentSlot
1533
1543
  );
1534
1544
 
1535
1545
  const swapInstructions = removeBudgetAndAtaIxns(swapQuoteIxs.swapIxs, []);
1536
1546
 
1537
1547
  const ixs = !collIsKtoken
1538
1548
  ? [
1549
+ ...scopeRefreshIxn,
1539
1550
  ...budgetIxns,
1540
1551
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1541
1552
  ...[flashBorrowIxn],
1542
- ...depositAction.setupIxs,
1543
- ...depositAction.lendingIxs,
1544
- ...depositAction.cleanupIxs,
1545
- ...borrowAction.setupIxs,
1546
- ...borrowAction.lendingIxs,
1547
- ...borrowAction.cleanupIxs,
1553
+ ...KaminoAction.actionToIxs(depositAction),
1554
+ ...KaminoAction.actionToIxs(borrowAction),
1548
1555
  ...swapInstructions,
1549
1556
  ...[flashRepayIxn],
1550
1557
  ]
1551
1558
  : [
1559
+ ...scopeRefreshIxn,
1552
1560
  ...budgetIxns,
1553
1561
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1554
1562
  ...[flashBorrowIxn],
1555
1563
  ...swapInstructions,
1556
- ...depositAction.setupIxs,
1557
- ...depositAction.lendingIxs,
1558
- ...depositAction.cleanupIxs,
1559
- ...borrowAction.setupIxs,
1560
- ...borrowAction.lendingIxs,
1561
- ...borrowAction.cleanupIxs,
1564
+ ...KaminoAction.actionToIxs(depositAction),
1565
+ ...KaminoAction.actionToIxs(borrowAction),
1562
1566
  ...[flashRepayIxn],
1563
1567
  ];
1564
1568
 
@@ -1578,7 +1582,7 @@ async function buildDecreaseLeverageIxns(
1578
1582
  currentSlot: number,
1579
1583
  calcs: AdjustLeverageCalcsResult,
1580
1584
  strategy: StrategyWithAddress | undefined,
1581
- scopeFeed: string | undefined,
1585
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1582
1586
  collIsKtoken: boolean,
1583
1587
  swapQuoteIxs: SwapIxs,
1584
1588
  budgetAndPriorityFeeIxns: TransactionInstruction[] | undefined,
@@ -1659,9 +1663,18 @@ async function buildDecreaseLeverageIxns(
1659
1663
  );
1660
1664
  }
1661
1665
 
1666
+ const scopeRefreshIxn = await getScopeRefreshIx(
1667
+ kaminoMarket,
1668
+ collReserve!,
1669
+ debtReserve!,
1670
+ obligation,
1671
+ scopeRefreshConfig
1672
+ );
1673
+
1662
1674
  // 3. Flash borrow & repay amount to repay (debt)
1663
1675
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1664
- borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length,
1676
+ borrowIxnIndex:
1677
+ budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
1665
1678
  walletPublicKey: owner,
1666
1679
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1667
1680
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1675,7 +1688,6 @@ async function buildDecreaseLeverageIxns(
1675
1688
  });
1676
1689
 
1677
1690
  // 4. Actually do the repay of the flash borrowed amounts
1678
- const scopeRefresh = scopeFeed ? { includeScopeRefresh: true, scopeFeed: scopeFeed } : undefined;
1679
1691
  const repayAction = await KaminoAction.buildRepayTxns(
1680
1692
  kaminoMarket,
1681
1693
  toLamports(Decimal.abs(calcs.adjustBorrowPosition), debtReserve!.stats.decimals).floor().toString(),
@@ -1683,6 +1695,7 @@ async function buildDecreaseLeverageIxns(
1683
1695
  owner,
1684
1696
  obligation,
1685
1697
  useV2Ixs,
1698
+ undefined,
1686
1699
  currentSlot,
1687
1700
  undefined,
1688
1701
  0,
@@ -1690,8 +1703,7 @@ async function buildDecreaseLeverageIxns(
1690
1703
  false,
1691
1704
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1692
1705
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1693
- referrer,
1694
- scopeRefresh
1706
+ referrer
1695
1707
  );
1696
1708
 
1697
1709
  // 6. Withdraw collateral (a little bit more to be able to pay for the slippage on swap)
@@ -1702,29 +1714,26 @@ async function buildDecreaseLeverageIxns(
1702
1714
  owner,
1703
1715
  obligation,
1704
1716
  useV2Ixs,
1717
+ undefined,
1705
1718
  0,
1706
1719
  false,
1707
1720
  false,
1708
1721
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1709
1722
  false, // to be checked and create in a setup tx in the UI (won't be the case for adjust anyway as this would be created in deposit)
1710
1723
  referrer,
1711
- currentSlot,
1712
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1724
+ currentSlot
1713
1725
  );
1714
1726
 
1715
1727
  const swapInstructions = removeBudgetAndAtaIxns(swapQuoteIxs.swapIxs, []);
1716
1728
 
1717
1729
  const ixns = [
1730
+ ...scopeRefreshIxn,
1718
1731
  ...budgetIxns,
1719
1732
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1720
1733
  ...fillWsolAtaIxns,
1721
1734
  ...[flashBorrowIxn],
1722
- ...repayAction.setupIxs,
1723
- ...repayAction.lendingIxs,
1724
- ...repayAction.cleanupIxs,
1725
- ...withdrawAction.setupIxs,
1726
- ...withdrawAction.lendingIxs,
1727
- ...withdrawAction.cleanupIxs,
1735
+ ...KaminoAction.actionToIxs(repayAction),
1736
+ ...KaminoAction.actionToIxs(withdrawAction),
1728
1737
  ...swapInstructions,
1729
1738
  ...[flashRepayIxn],
1730
1739
  ...closeWsolAtaIxns,
@@ -1732,3 +1741,36 @@ async function buildDecreaseLeverageIxns(
1732
1741
 
1733
1742
  return ixns;
1734
1743
  }
1744
+
1745
+ export const getScopeRefreshIx = async (
1746
+ market: KaminoMarket,
1747
+ collReserve: KaminoReserve,
1748
+ debtReserve: KaminoReserve,
1749
+ obligation: KaminoObligation | ObligationType | undefined,
1750
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined
1751
+ ): Promise<TransactionInstruction[]> => {
1752
+ const allReserves =
1753
+ obligation && isKaminoObligation(obligation)
1754
+ ? new PublicKeySet<PublicKey>([
1755
+ ...obligation.getDeposits().map((x) => x.reserveAddress),
1756
+ ...obligation.getBorrows().map((x) => x.reserveAddress),
1757
+ collReserve.address,
1758
+ debtReserve.address,
1759
+ ]).toArray()
1760
+ : new PublicKeySet<PublicKey>([collReserve.address, debtReserve.address]).toArray();
1761
+ const tokenIds = getTokenIdsForScopeRefresh(market, allReserves);
1762
+
1763
+ const scopeRefreshIxns: TransactionInstruction[] = [];
1764
+ if (tokenIds.length > 0 && scopeRefreshConfig) {
1765
+ scopeRefreshIxns.push(
1766
+ await scopeRefreshConfig.scope.refreshPriceListIx(
1767
+ {
1768
+ feed: scopeRefreshConfig.scopeFeed,
1769
+ },
1770
+ tokenIds
1771
+ )
1772
+ );
1773
+ }
1774
+
1775
+ return scopeRefreshIxns;
1776
+ };
@@ -2,7 +2,7 @@ import { AddressLookupTableAccount, PublicKey, TransactionInstruction } from '@s
2
2
  import Decimal from 'decimal.js';
3
3
  import { KaminoMarket, KaminoObligation } from '../classes';
4
4
  import { InstructionsWithLookupTables, Kamino, StrategyWithAddress } from '@kamino-finance/kliquidity-sdk';
5
- import { ObligationType, ObligationTypeTag } from '../utils';
5
+ import { ObligationType, ObligationTypeTag, ScopePriceRefreshConfig } from '../utils';
6
6
 
7
7
  export type SwapQuoteProvider<QuoteResponse> = (
8
8
  inputs: SwapInputs,
@@ -82,7 +82,7 @@ export interface DepositWithLeverageSwapInputsProps<QuoteResponse> {
82
82
  selectedTokenMint: PublicKey;
83
83
  budgetAndPriorityFeeIxs?: TransactionInstruction[];
84
84
  kamino: Kamino | undefined;
85
- scopeFeed: string | undefined;
85
+ scopeRefreshConfig?: ScopePriceRefreshConfig;
86
86
  quoteBufferBps: Decimal;
87
87
  priceAinB: PriceAinBProvider;
88
88
  isKtoken: IsKtokenProvider;
@@ -143,7 +143,7 @@ export interface WithdrawWithLeverageSwapInputsProps<QuoteResponse> {
143
143
  selectedTokenMint: PublicKey;
144
144
  budgetAndPriorityFeeIxs?: TransactionInstruction[];
145
145
  kamino: Kamino | undefined;
146
- scopeFeed: string | undefined;
146
+ scopeRefreshConfig?: ScopePriceRefreshConfig;
147
147
  quoteBufferBps: Decimal;
148
148
  isKtoken: IsKtokenProvider;
149
149
  quoter: SwapQuoteProvider<QuoteResponse>;
@@ -196,7 +196,7 @@ export interface AdjustLeverageSwapInputsProps<QuoteResponse> {
196
196
  slippagePct: Decimal;
197
197
  budgetAndPriorityFeeIxs?: TransactionInstruction[];
198
198
  kamino: Kamino | undefined;
199
- scopeFeed: string | undefined;
199
+ scopeRefreshConfig?: ScopePriceRefreshConfig;
200
200
  quoteBufferBps: Decimal;
201
201
  priceAinB: PriceAinBProvider;
202
202
  isKtoken: IsKtokenProvider;
@@ -1,7 +1,7 @@
1
1
  import { PublicKey } from '@solana/web3.js';
2
2
  import { KaminoMarket, KaminoObligation } from '../classes';
3
3
 
4
- export type ObligationType = VanillaObligation | MultiplyObligation | LendingObligation;
4
+ export type ObligationType = VanillaObligation | MultiplyObligation | LendingObligation | LeverageObligation;
5
5
 
6
6
  export enum ObligationTypeTag {
7
7
  Vanilla = 0,
@@ -397,59 +397,17 @@ export function getReserveOracleConfigs(priceFeed: PriceFeed | null): {
397
397
  };
398
398
  }
399
399
 
400
+ const ORACLE_TYPE_MAP = Object.fromEntries(
401
+ Object.values(OracleType)
402
+ // Filter for oracle types that have a discriminator property
403
+ // This ensures we only include actual oracle implementations in the mapping
404
+ // Pyth is used as a type assertion here but actually any oracle type with a discriminator will pass
405
+ .filter((T): T is typeof OracleType.Pyth => 'discriminator' in T)
406
+ .map((T) => [T.discriminator, T.name])
407
+ );
408
+
400
409
  export function parseOracleType(type: number): string {
401
- switch (type) {
402
- case new OracleType.Pyth().discriminator:
403
- return 'Pyth';
404
- case new OracleType.SwitchboardV2().discriminator:
405
- return 'SwitchboardV2';
406
- case new OracleType.CToken().discriminator:
407
- return 'CToken';
408
- case new OracleType.KToken().discriminator:
409
- return 'KToken';
410
- case new OracleType.SplStake().discriminator:
411
- return 'SplStake';
412
- case new OracleType.PythEMA().discriminator:
413
- return 'PythEMA';
414
- case new OracleType.DeprecatedPlaceholder1().discriminator:
415
- return 'DeprecatedPlaceholder1';
416
- case new OracleType.DeprecatedPlaceholder2().discriminator:
417
- return 'DeprecatedPlaceholder2';
418
- case new OracleType.MsolStake().discriminator:
419
- return 'MsolStake';
420
- case new OracleType.KTokenToTokenA().discriminator:
421
- return 'KTokenToTokenA';
422
- case new OracleType.KTokenToTokenB().discriminator:
423
- return 'KTokenToTokenB';
424
- case new OracleType.JupiterLpFetch().discriminator:
425
- return 'JupiterLpFetch';
426
- case new OracleType.ScopeTwap().discriminator:
427
- return 'ScopeTwap';
428
- case new OracleType.OrcaWhirlpoolAtoB().discriminator:
429
- return 'OrcaWhirlpoolAtoB';
430
- case new OracleType.OrcaWhirlpoolBtoA().discriminator:
431
- return 'OrcaWhirlpoolBtoA';
432
- case new OracleType.RaydiumAmmV3AtoB().discriminator:
433
- return 'RaydiumAmmV3AtoB';
434
- case new OracleType.RaydiumAmmV3BtoA().discriminator:
435
- return 'RaydiumAmmV3BtoA';
436
- case new OracleType.JupiterLpCompute().discriminator:
437
- return 'JupiterLpCompute';
438
- case new OracleType.MeteoraDlmmAtoB().discriminator:
439
- return 'MeteoraDlmmAtoB';
440
- case new OracleType.MeteoraDlmmBtoA().discriminator:
441
- return 'MeteoraDlmmBtoA';
442
- case new OracleType.JupiterLpScope().discriminator:
443
- return 'JupiterLpScope';
444
- case new OracleType.PythPullBased().discriminator:
445
- return 'PythPullBased';
446
- case new OracleType.PythPullBasedEMA().discriminator:
447
- return 'PythPullBasedEMA';
448
- case new OracleType.FixedPrice().discriminator:
449
- return 'FixedPrice';
450
- default:
451
- return 'Unknown';
452
- }
410
+ return ORACLE_TYPE_MAP[type] || 'Unknown';
453
411
  }
454
412
 
455
413
  export type MarketWithAddress = {