@kamino-finance/klend-sdk 5.11.2 → 5.11.3-beta.0

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 (82) 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 +69 -149
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/manager.d.ts +1 -1
  6. package/dist/classes/manager.js +1 -1
  7. package/dist/classes/market.d.ts +3 -3
  8. package/dist/classes/market.d.ts.map +1 -1
  9. package/dist/classes/market.js +30 -16
  10. package/dist/classes/market.js.map +1 -1
  11. package/dist/classes/obligation.d.ts +2 -0
  12. package/dist/classes/obligation.d.ts.map +1 -1
  13. package/dist/classes/obligation.js +5 -0
  14. package/dist/classes/obligation.js.map +1 -1
  15. package/dist/classes/vault.js +14 -14
  16. package/dist/classes/vault.js.map +1 -1
  17. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts +3 -3
  18. package/dist/idl_codegen_kamino_vault/accounts/VaultState.d.ts.map +1 -1
  19. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js +6 -6
  20. package/dist/idl_codegen_kamino_vault/accounts/VaultState.js.map +1 -1
  21. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.d.ts +1 -1
  22. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.d.ts.map +1 -1
  23. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.js +1 -1
  24. package/dist/idl_codegen_kamino_vault/instructions/giveUpPendingFees.js.map +1 -1
  25. package/dist/idl_codegen_kamino_vault/instructions/initializeSharesMetadata.d.ts +1 -1
  26. package/dist/idl_codegen_kamino_vault/instructions/initializeSharesMetadata.d.ts.map +1 -1
  27. package/dist/idl_codegen_kamino_vault/instructions/initializeSharesMetadata.js +1 -1
  28. package/dist/idl_codegen_kamino_vault/instructions/initializeSharesMetadata.js.map +1 -1
  29. package/dist/idl_codegen_kamino_vault/instructions/updateSharesMetadata.d.ts +1 -1
  30. package/dist/idl_codegen_kamino_vault/instructions/updateSharesMetadata.d.ts.map +1 -1
  31. package/dist/idl_codegen_kamino_vault/instructions/updateSharesMetadata.js +1 -1
  32. package/dist/idl_codegen_kamino_vault/instructions/updateSharesMetadata.js.map +1 -1
  33. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.d.ts +1 -1
  34. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.d.ts.map +1 -1
  35. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.js +1 -1
  36. package/dist/idl_codegen_kamino_vault/instructions/updateVaultConfig.js.map +1 -1
  37. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.d.ts +1 -1
  38. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.d.ts.map +1 -1
  39. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.js +1 -1
  40. package/dist/idl_codegen_kamino_vault/instructions/withdrawPendingFees.js.map +1 -1
  41. package/dist/lending_operations/repay_with_collateral_operations.d.ts +4 -4
  42. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  43. package/dist/lending_operations/repay_with_collateral_operations.js +10 -8
  44. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  45. package/dist/lending_operations/swap_collateral_operations.d.ts +2 -2
  46. package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
  47. package/dist/lending_operations/swap_collateral_operations.js +11 -6
  48. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  49. package/dist/leverage/operations.d.ts +9 -7
  50. package/dist/leverage/operations.d.ts.map +1 -1
  51. package/dist/leverage/operations.js +78 -66
  52. package/dist/leverage/operations.js.map +1 -1
  53. package/dist/leverage/types.d.ts +4 -4
  54. package/dist/leverage/types.d.ts.map +1 -1
  55. package/dist/utils/ObligationType.d.ts +1 -1
  56. package/dist/utils/ObligationType.d.ts.map +1 -1
  57. package/dist/utils/managerTypes.d.ts.map +1 -1
  58. package/dist/utils/managerTypes.js +7 -52
  59. package/dist/utils/managerTypes.js.map +1 -1
  60. package/dist/utils/oracle.d.ts +3 -3
  61. package/dist/utils/oracle.d.ts.map +1 -1
  62. package/package.json +2 -2
  63. package/src/classes/action.ts +75 -162
  64. package/src/classes/manager.ts +1 -1
  65. package/src/classes/market.ts +34 -25
  66. package/src/classes/obligation.ts +6 -0
  67. package/src/classes/vault.ts +14 -14
  68. package/src/client.ts +8 -3
  69. package/src/idl_codegen_kamino_vault/accounts/VaultState.ts +8 -8
  70. package/src/idl_codegen_kamino_vault/instructions/giveUpPendingFees.ts +2 -2
  71. package/src/idl_codegen_kamino_vault/instructions/initializeSharesMetadata.ts +2 -2
  72. package/src/idl_codegen_kamino_vault/instructions/updateSharesMetadata.ts +2 -2
  73. package/src/idl_codegen_kamino_vault/instructions/updateVaultConfig.ts +2 -2
  74. package/src/idl_codegen_kamino_vault/instructions/withdrawPendingFees.ts +2 -2
  75. package/src/idl_kamino_vault.json +7 -7
  76. package/src/lending_operations/repay_with_collateral_operations.ts +15 -11
  77. package/src/lending_operations/swap_collateral_operations.ts +19 -7
  78. package/src/leverage/operations.ts +114 -66
  79. package/src/leverage/types.ts +4 -4
  80. package/src/utils/ObligationType.ts +1 -1
  81. package/src/utils/managerTypes.ts +10 -52
  82. package/src/utils/oracle.ts +2 -2
@@ -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,
@@ -1059,7 +1067,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1059
1067
  currentSlot,
1060
1068
  calcs,
1061
1069
  strategy,
1062
- scopeFeed,
1070
+ scopeRefreshConfig,
1063
1071
  collIsKtoken,
1064
1072
  {
1065
1073
  preActionIxs: [],
@@ -1163,7 +1171,7 @@ export async function getAdjustLeverageSwapInputs<QuoteResponse>({
1163
1171
  currentSlot,
1164
1172
  calcs,
1165
1173
  strategy,
1166
- scopeFeed,
1174
+ scopeRefreshConfig,
1167
1175
  collIsKtoken,
1168
1176
  {
1169
1177
  preActionIxs: [],
@@ -1251,7 +1259,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1251
1259
  slippagePct,
1252
1260
  budgetAndPriorityFeeIxs,
1253
1261
  kamino,
1254
- scopeFeed,
1262
+ scopeRefreshConfig,
1255
1263
  quoteBufferBps,
1256
1264
  priceAinB,
1257
1265
  isKtoken,
@@ -1275,7 +1283,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1275
1283
  slippagePct,
1276
1284
  budgetAndPriorityFeeIxs,
1277
1285
  kamino,
1278
- scopeFeed,
1286
+ scopeRefreshConfig,
1279
1287
  quoteBufferBps,
1280
1288
  priceAinB,
1281
1289
  isKtoken,
@@ -1321,7 +1329,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1321
1329
  currentSlot,
1322
1330
  initialInputs.calcs,
1323
1331
  initialInputs.strategy,
1324
- scopeFeed,
1332
+ scopeRefreshConfig,
1325
1333
  initialInputs.collIsKtoken,
1326
1334
  {
1327
1335
  preActionIxs: [],
@@ -1368,7 +1376,7 @@ export async function getAdjustLeverageIxns<QuoteResponse>({
1368
1376
  currentSlot,
1369
1377
  initialInputs.calcs,
1370
1378
  initialInputs.strategy,
1371
- scopeFeed,
1379
+ scopeRefreshConfig,
1372
1380
  initialInputs.collIsKtoken,
1373
1381
  {
1374
1382
  preActionIxs: [],
@@ -1401,7 +1409,7 @@ async function buildIncreaseLeverageIxns(
1401
1409
  currentSlot: number,
1402
1410
  calcs: AdjustLeverageCalcsResult,
1403
1411
  strategy: StrategyWithAddress | undefined,
1404
- scopeFeed: string | undefined,
1412
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1405
1413
  collIsKtoken: boolean,
1406
1414
  swapQuoteIxs: SwapIxs,
1407
1415
  budgetAndPriorityFeeIxns: TransactionInstruction[] | undefined,
@@ -1473,9 +1481,17 @@ async function buildIncreaseLeverageIxns(
1473
1481
 
1474
1482
  const atasAndCreateIxns = createAtasIdempotent(owner, mintsToCreateAtas);
1475
1483
 
1484
+ const scopeRefreshIxn = await getScopeRefreshIx(
1485
+ kaminoMarket,
1486
+ collReserve!,
1487
+ debtReserve!,
1488
+ obligation,
1489
+ scopeRefreshConfig
1490
+ );
1491
+
1476
1492
  // 2. Create borrow flash loan instruction
1477
1493
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1478
- 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
1479
1495
  walletPublicKey: owner,
1480
1496
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1481
1497
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1498,14 +1514,14 @@ async function buildIncreaseLeverageIxns(
1498
1514
  owner,
1499
1515
  obligation,
1500
1516
  useV2Ixs,
1517
+ undefined,
1501
1518
  0,
1502
1519
  false,
1503
1520
  false,
1504
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)
1505
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)
1506
1523
  referrer,
1507
- currentSlot,
1508
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1524
+ currentSlot
1509
1525
  );
1510
1526
 
1511
1527
  // 4. Borrow tokens in borrow token reserve that will be swapped to repay flash loan
@@ -1516,43 +1532,37 @@ async function buildIncreaseLeverageIxns(
1516
1532
  owner,
1517
1533
  obligation,
1518
1534
  useV2Ixs,
1535
+ undefined,
1519
1536
  0,
1520
1537
  false,
1521
1538
  false,
1522
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)
1523
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)
1524
1541
  referrer,
1525
- currentSlot,
1526
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1542
+ currentSlot
1527
1543
  );
1528
1544
 
1529
1545
  const swapInstructions = removeBudgetAndAtaIxns(swapQuoteIxs.swapIxs, []);
1530
1546
 
1531
1547
  const ixs = !collIsKtoken
1532
1548
  ? [
1549
+ ...scopeRefreshIxn,
1533
1550
  ...budgetIxns,
1534
1551
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1535
1552
  ...[flashBorrowIxn],
1536
- ...depositAction.setupIxs,
1537
- ...depositAction.lendingIxs,
1538
- ...depositAction.cleanupIxs,
1539
- ...borrowAction.setupIxs,
1540
- ...borrowAction.lendingIxs,
1541
- ...borrowAction.cleanupIxs,
1553
+ ...KaminoAction.actionToIxs(depositAction),
1554
+ ...KaminoAction.actionToIxs(borrowAction),
1542
1555
  ...swapInstructions,
1543
1556
  ...[flashRepayIxn],
1544
1557
  ]
1545
1558
  : [
1559
+ ...scopeRefreshIxn,
1546
1560
  ...budgetIxns,
1547
1561
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1548
1562
  ...[flashBorrowIxn],
1549
1563
  ...swapInstructions,
1550
- ...depositAction.setupIxs,
1551
- ...depositAction.lendingIxs,
1552
- ...depositAction.cleanupIxs,
1553
- ...borrowAction.setupIxs,
1554
- ...borrowAction.lendingIxs,
1555
- ...borrowAction.cleanupIxs,
1564
+ ...KaminoAction.actionToIxs(depositAction),
1565
+ ...KaminoAction.actionToIxs(borrowAction),
1556
1566
  ...[flashRepayIxn],
1557
1567
  ];
1558
1568
 
@@ -1572,7 +1582,7 @@ async function buildDecreaseLeverageIxns(
1572
1582
  currentSlot: number,
1573
1583
  calcs: AdjustLeverageCalcsResult,
1574
1584
  strategy: StrategyWithAddress | undefined,
1575
- scopeFeed: string | undefined,
1585
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1576
1586
  collIsKtoken: boolean,
1577
1587
  swapQuoteIxs: SwapIxs,
1578
1588
  budgetAndPriorityFeeIxns: TransactionInstruction[] | undefined,
@@ -1653,9 +1663,18 @@ async function buildDecreaseLeverageIxns(
1653
1663
  );
1654
1664
  }
1655
1665
 
1666
+ const scopeRefreshIxn = await getScopeRefreshIx(
1667
+ kaminoMarket,
1668
+ collReserve!,
1669
+ debtReserve!,
1670
+ obligation,
1671
+ scopeRefreshConfig
1672
+ );
1673
+
1656
1674
  // 3. Flash borrow & repay amount to repay (debt)
1657
1675
  const { flashBorrowIxn, flashRepayIxn } = getFlashLoanInstructions({
1658
- borrowIxnIndex: budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length,
1676
+ borrowIxnIndex:
1677
+ budgetIxns.length + atasAndCreateIxns.length + fillWsolAtaIxns.length + (scopeRefreshIxn.length > 0 ? 1 : 0),
1659
1678
  walletPublicKey: owner,
1660
1679
  lendingMarketAuthority: kaminoMarket.getLendingMarketAuthority(),
1661
1680
  lendingMarketAddress: kaminoMarket.getAddress(),
@@ -1669,7 +1688,6 @@ async function buildDecreaseLeverageIxns(
1669
1688
  });
1670
1689
 
1671
1690
  // 4. Actually do the repay of the flash borrowed amounts
1672
- const scopeRefresh = scopeFeed ? { includeScopeRefresh: true, scopeFeed: scopeFeed } : undefined;
1673
1691
  const repayAction = await KaminoAction.buildRepayTxns(
1674
1692
  kaminoMarket,
1675
1693
  toLamports(Decimal.abs(calcs.adjustBorrowPosition), debtReserve!.stats.decimals).floor().toString(),
@@ -1677,6 +1695,7 @@ async function buildDecreaseLeverageIxns(
1677
1695
  owner,
1678
1696
  obligation,
1679
1697
  useV2Ixs,
1698
+ undefined,
1680
1699
  currentSlot,
1681
1700
  undefined,
1682
1701
  0,
@@ -1684,8 +1703,7 @@ async function buildDecreaseLeverageIxns(
1684
1703
  false,
1685
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)
1686
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)
1687
- referrer,
1688
- scopeRefresh
1706
+ referrer
1689
1707
  );
1690
1708
 
1691
1709
  // 6. Withdraw collateral (a little bit more to be able to pay for the slippage on swap)
@@ -1696,29 +1714,26 @@ async function buildDecreaseLeverageIxns(
1696
1714
  owner,
1697
1715
  obligation,
1698
1716
  useV2Ixs,
1717
+ undefined,
1699
1718
  0,
1700
1719
  false,
1701
1720
  false,
1702
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)
1703
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)
1704
1723
  referrer,
1705
- currentSlot,
1706
- { includeScopeRefresh: true, scopeFeed: scopeFeed! }
1724
+ currentSlot
1707
1725
  );
1708
1726
 
1709
1727
  const swapInstructions = removeBudgetAndAtaIxns(swapQuoteIxs.swapIxs, []);
1710
1728
 
1711
1729
  const ixns = [
1730
+ ...scopeRefreshIxn,
1712
1731
  ...budgetIxns,
1713
1732
  ...atasAndCreateIxns.map((x) => x.createAtaIx),
1714
1733
  ...fillWsolAtaIxns,
1715
1734
  ...[flashBorrowIxn],
1716
- ...repayAction.setupIxs,
1717
- ...repayAction.lendingIxs,
1718
- ...repayAction.cleanupIxs,
1719
- ...withdrawAction.setupIxs,
1720
- ...withdrawAction.lendingIxs,
1721
- ...withdrawAction.cleanupIxs,
1735
+ ...KaminoAction.actionToIxs(repayAction),
1736
+ ...KaminoAction.actionToIxs(withdrawAction),
1722
1737
  ...swapInstructions,
1723
1738
  ...[flashRepayIxn],
1724
1739
  ...closeWsolAtaIxns,
@@ -1726,3 +1741,36 @@ async function buildDecreaseLeverageIxns(
1726
1741
 
1727
1742
  return ixns;
1728
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 = {
@@ -35,8 +35,8 @@ export type CandidatePrice = {
35
35
  valid: boolean;
36
36
  };
37
37
 
38
- export type ScopeRefresh = {
39
- includeScopeRefresh: boolean;
38
+ export type ScopePriceRefreshConfig = {
39
+ scope: Scope;
40
40
  scopeFeed: string;
41
41
  };
42
42