@kamino-finance/klend-sdk 5.11.3-beta.1 → 5.11.4

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 (65) 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/classes/vault.js +1 -1
  22. package/dist/classes/vault.js.map +1 -1
  23. package/dist/lending_operations/repay_with_collateral_operations.d.ts +4 -4
  24. package/dist/lending_operations/repay_with_collateral_operations.d.ts.map +1 -1
  25. package/dist/lending_operations/repay_with_collateral_operations.js +10 -8
  26. package/dist/lending_operations/repay_with_collateral_operations.js.map +1 -1
  27. package/dist/lending_operations/swap_collateral_operations.d.ts +2 -2
  28. package/dist/lending_operations/swap_collateral_operations.d.ts.map +1 -1
  29. package/dist/lending_operations/swap_collateral_operations.js +11 -6
  30. package/dist/lending_operations/swap_collateral_operations.js.map +1 -1
  31. package/dist/leverage/calcs.d.ts +5 -10
  32. package/dist/leverage/calcs.d.ts.map +1 -1
  33. package/dist/leverage/calcs.js +6 -13
  34. package/dist/leverage/calcs.js.map +1 -1
  35. package/dist/leverage/operations.d.ts +9 -7
  36. package/dist/leverage/operations.d.ts.map +1 -1
  37. package/dist/leverage/operations.js +78 -72
  38. package/dist/leverage/operations.js.map +1 -1
  39. package/dist/leverage/types.d.ts +4 -4
  40. package/dist/leverage/types.d.ts.map +1 -1
  41. package/dist/utils/ObligationType.d.ts +1 -1
  42. package/dist/utils/ObligationType.d.ts.map +1 -1
  43. package/dist/utils/managerTypes.d.ts.map +1 -1
  44. package/dist/utils/managerTypes.js +7 -52
  45. package/dist/utils/managerTypes.js.map +1 -1
  46. package/dist/utils/oracle.d.ts +3 -3
  47. package/dist/utils/oracle.d.ts.map +1 -1
  48. package/dist/utils/oracle.js +4 -3
  49. package/dist/utils/oracle.js.map +1 -1
  50. package/package.json +2 -2
  51. package/src/classes/action.ts +143 -211
  52. package/src/classes/index.ts +1 -0
  53. package/src/classes/manager.ts +32 -1
  54. package/src/classes/market.ts +34 -25
  55. package/src/classes/obligation.ts +6 -0
  56. package/src/classes/vault.ts +1 -1
  57. package/src/client.ts +8 -3
  58. package/src/lending_operations/repay_with_collateral_operations.ts +15 -11
  59. package/src/lending_operations/swap_collateral_operations.ts +19 -7
  60. package/src/leverage/calcs.ts +2 -18
  61. package/src/leverage/operations.ts +114 -72
  62. package/src/leverage/types.ts +4 -4
  63. package/src/utils/ObligationType.ts +1 -1
  64. package/src/utils/managerTypes.ts +10 -52
  65. package/src/utils/oracle.ts +7 -6
@@ -61,11 +61,11 @@ import {
61
61
  isNotNullPubkey,
62
62
  PublicKeySet,
63
63
  getAssociatedTokenAddress,
64
- ScopeRefresh,
64
+ ScopePriceRefreshConfig,
65
65
  createAtasIdempotent,
66
66
  obligationFarmStatePda,
67
67
  } from '../utils';
68
- import { KaminoMarket } from './market';
68
+ import { getTokenIdsForScopeRefresh, KaminoMarket } from './market';
69
69
  import { KaminoObligation } from './obligation';
70
70
  import { KaminoReserve } from './reserve';
71
71
  import { ReserveFarmKind } from '../idl_codegen/types';
@@ -73,7 +73,7 @@ import { farmsId } from '@kamino-finance/farms-sdk';
73
73
  import { Reserve } from '../idl_codegen/accounts';
74
74
  import { VanillaObligation } from '../utils/ObligationType';
75
75
  import { PROGRAM_ID } from '../lib';
76
- import { U16_MAX } from '@kamino-finance/scope-sdk';
76
+ import { Scope } from '@kamino-finance/scope-sdk';
77
77
 
78
78
  const SOL_PADDING_FOR_INTEREST = new BN('1000000');
79
79
 
@@ -411,6 +411,7 @@ export class KaminoAction {
411
411
  owner: PublicKey,
412
412
  obligation: KaminoObligation | ObligationType,
413
413
  useV2Ixs: boolean,
414
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
414
415
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
415
416
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
416
417
  requestElevationGroup: boolean = false, // to be requested *before* the deposit
@@ -418,7 +419,6 @@ export class KaminoAction {
418
419
  createLookupTable: boolean = true,
419
420
  referrer: PublicKey = PublicKey.default,
420
421
  currentSlot: number = 0,
421
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' },
422
422
  overrideElevationGroupRequest: number | undefined = undefined // if set, when an elevationgroup request is made, it will use this value
423
423
  ) {
424
424
  const axn = await KaminoAction.initialize(
@@ -437,16 +437,6 @@ export class KaminoAction {
437
437
  axn.addComputeBudgetIxn(extraComputeBudget);
438
438
  }
439
439
 
440
- const allReserves = new PublicKeySet<PublicKey>([
441
- ...axn.depositReserves,
442
- ...axn.borrowReserves,
443
- axn.reserve.address,
444
- ]).toArray();
445
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
446
-
447
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
448
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
449
- }
450
440
  await axn.addSupportIxs(
451
441
  'deposit',
452
442
  includeAtaIxns,
@@ -454,6 +444,7 @@ export class KaminoAction {
454
444
  includeUserMetadata,
455
445
  addInitObligationForFarm,
456
446
  useV2Ixs,
447
+ scopeRefreshConfig,
457
448
  createLookupTable,
458
449
  undefined,
459
450
  overrideElevationGroupRequest
@@ -468,36 +459,10 @@ export class KaminoAction {
468
459
  return axn;
469
460
  }
470
461
 
471
- getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: PublicKey[]): number[] {
472
- const tokenIds: number[] = [];
473
-
474
- for (const reserveAddress of reserves) {
475
- const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
476
- if (!reserve) {
477
- throw new Error(`Reserve not found for reserve ${reserveAddress.toBase58()}`);
478
- }
479
-
480
- if (!reserve.state.config.tokenInfo.scopeConfiguration.priceFeed.equals(PublicKey.default)) {
481
- reserve.state.config.tokenInfo.scopeConfiguration.priceChain.map((x) => {
482
- if (x !== U16_MAX) {
483
- tokenIds.push(x);
484
- }
485
- });
486
- reserve.state.config.tokenInfo.scopeConfiguration.twapChain.map((x) => {
487
- if (x !== U16_MAX) {
488
- tokenIds.push(x);
489
- }
490
- });
491
- }
492
- }
493
-
494
- return tokenIds;
495
- }
496
-
497
- async addScopeRefreshIxs(tokens: number[], feed: string = 'hubble') {
498
- this.preTxnIxsLabels.unshift(`refreshScopePrices`);
499
- this.preTxnIxs.unshift(
500
- await this.kaminoMarket.scope.refreshPriceListIx(
462
+ async addScopeRefreshIxs(scope: Scope, tokens: number[], feed: string = 'hubble') {
463
+ this.setupIxsLabels.unshift(`refreshScopePrices`);
464
+ this.setupIxs.unshift(
465
+ await scope.refreshPriceListIx(
501
466
  {
502
467
  feed: feed,
503
468
  },
@@ -513,6 +478,7 @@ export class KaminoAction {
513
478
  owner: PublicKey,
514
479
  obligation: KaminoObligation | ObligationType,
515
480
  useV2Ixs: boolean,
481
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
516
482
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
517
483
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
518
484
  requestElevationGroup: boolean = false,
@@ -520,7 +486,6 @@ export class KaminoAction {
520
486
  createLookupTable: boolean = true,
521
487
  referrer: PublicKey = PublicKey.default,
522
488
  currentSlot: number = 0,
523
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' },
524
489
  overrideElevationGroupRequest: number | undefined = undefined // if set, when an elevationgroup request is made, it will use this value
525
490
  ) {
526
491
  const axn = await KaminoAction.initialize(
@@ -538,15 +503,16 @@ export class KaminoAction {
538
503
  axn.addComputeBudgetIxn(extraComputeBudget);
539
504
  }
540
505
 
541
- const allReserves = new PublicKeySet<PublicKey>([
542
- ...axn.depositReserves,
543
- ...axn.borrowReserves,
544
- axn.reserve.address,
545
- ]).toArray();
546
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
547
-
548
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
549
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
506
+ if (!axn.referrer.equals(PublicKey.default)) {
507
+ const referrerTokenState = referrerTokenStatePda(
508
+ axn.referrer,
509
+ axn.reserve.address,
510
+ axn.kaminoMarket.programId
511
+ )[0];
512
+ const account = await axn.kaminoMarket.getConnection().getAccountInfo(referrerTokenState);
513
+ if (!account) {
514
+ axn.addInitReferrerTokenStateIx(axn.reserve, referrerTokenState);
515
+ }
550
516
  }
551
517
 
552
518
  await axn.addSupportIxs(
@@ -556,6 +522,7 @@ export class KaminoAction {
556
522
  includeUserMetadata,
557
523
  addInitObligationForFarm,
558
524
  useV2Ixs,
525
+ scopeRefreshConfig,
559
526
  createLookupTable,
560
527
  undefined,
561
528
  overrideElevationGroupRequest
@@ -576,12 +543,12 @@ export class KaminoAction {
576
543
  mint: PublicKey,
577
544
  owner: PublicKey,
578
545
  obligation: KaminoObligation | ObligationType,
546
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
579
547
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
580
548
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
581
549
  requestElevationGroup: boolean = false,
582
550
  referrer: PublicKey = PublicKey.default,
583
- currentSlot: number = 0,
584
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
551
+ currentSlot: number = 0
585
552
  ) {
586
553
  const axn = await KaminoAction.initialize(
587
554
  'mint',
@@ -599,17 +566,6 @@ export class KaminoAction {
599
566
  axn.addComputeBudgetIxn(extraComputeBudget);
600
567
  }
601
568
 
602
- const allReserves = new PublicKeySet<PublicKey>([
603
- ...axn.depositReserves,
604
- ...axn.borrowReserves,
605
- axn.reserve.address,
606
- ]).toArray();
607
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
608
-
609
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
610
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
611
- }
612
-
613
569
  await axn.addSupportIxs(
614
570
  'mint',
615
571
  includeAtaIxns,
@@ -617,6 +573,7 @@ export class KaminoAction {
617
573
  false,
618
574
  addInitObligationForFarm,
619
575
  false,
576
+ scopeRefreshConfig,
620
577
  false
621
578
  );
622
579
  axn.addDepositReserveLiquidityIx();
@@ -630,12 +587,12 @@ export class KaminoAction {
630
587
  mint: PublicKey,
631
588
  owner: PublicKey,
632
589
  obligation: KaminoObligation | ObligationType,
590
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
633
591
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
634
592
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
635
593
  requestElevationGroup: boolean = false,
636
594
  referrer: PublicKey = PublicKey.default,
637
- currentSlot: number = 0,
638
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
595
+ currentSlot: number = 0
639
596
  ) {
640
597
  const axn = await KaminoAction.initialize(
641
598
  'redeem',
@@ -653,17 +610,6 @@ export class KaminoAction {
653
610
  axn.addComputeBudgetIxn(extraComputeBudget);
654
611
  }
655
612
 
656
- const allReserves = new PublicKeySet<PublicKey>([
657
- ...axn.depositReserves,
658
- ...axn.borrowReserves,
659
- axn.reserve.address,
660
- ]).toArray();
661
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
662
-
663
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
664
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
665
- }
666
-
667
613
  await axn.addSupportIxs(
668
614
  'redeem',
669
615
  includeAtaIxns,
@@ -671,6 +617,7 @@ export class KaminoAction {
671
617
  false,
672
618
  addInitObligationForFarm,
673
619
  false,
620
+ scopeRefreshConfig,
674
621
  false
675
622
  );
676
623
  axn.addRedeemReserveCollateralIx();
@@ -685,14 +632,14 @@ export class KaminoAction {
685
632
  owner: PublicKey,
686
633
  obligation: KaminoObligation | ObligationType,
687
634
  useV2Ixs: boolean,
635
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
688
636
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
689
637
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas
690
638
  requestElevationGroup: boolean = false,
691
639
  includeUserMetadata: boolean = true, // if true it includes user metadata
692
640
  createLookupTable: boolean = true,
693
641
  referrer: PublicKey = PublicKey.default,
694
- currentSlot: number = 0,
695
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
642
+ currentSlot: number = 0
696
643
  ) {
697
644
  const axn = await KaminoAction.initialize(
698
645
  'depositCollateral',
@@ -710,17 +657,6 @@ export class KaminoAction {
710
657
  axn.addComputeBudgetIxn(extraComputeBudget);
711
658
  }
712
659
 
713
- const allReserves = new PublicKeySet<PublicKey>([
714
- ...axn.depositReserves,
715
- ...axn.borrowReserves,
716
- axn.reserve.address,
717
- ]).toArray();
718
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
719
-
720
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
721
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
722
- }
723
-
724
660
  await axn.addSupportIxs(
725
661
  'depositCollateral',
726
662
  includeAtaIxns,
@@ -728,6 +664,7 @@ export class KaminoAction {
728
664
  includeUserMetadata,
729
665
  addInitObligationForFarm,
730
666
  useV2Ixs,
667
+ scopeRefreshConfig,
731
668
  createLookupTable
732
669
  );
733
670
  if (useV2Ixs) {
@@ -748,14 +685,14 @@ export class KaminoAction {
748
685
  payer: PublicKey,
749
686
  obligation: KaminoObligation | ObligationType,
750
687
  useV2Ixs: boolean,
688
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
751
689
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
752
690
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
753
691
  requestElevationGroup: boolean = false,
754
692
  includeUserMetadata: boolean = true, // if true it includes user metadata,
755
693
  createLookupTable: boolean = true,
756
694
  referrer: PublicKey = PublicKey.default,
757
- currentSlot: number = 0,
758
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
695
+ currentSlot: number = 0
759
696
  ) {
760
697
  const axn = await KaminoAction.initializeMultiTokenAction(
761
698
  kaminoMarket,
@@ -778,18 +715,17 @@ export class KaminoAction {
778
715
  axn.addComputeBudgetIxn(extraComputeBudget);
779
716
  }
780
717
 
781
- const allReserves = new PublicKeySet<PublicKey>([
782
- ...axn.depositReserves,
783
- ...axn.borrowReserves,
784
- axn.reserve.address,
785
- axn.outflowReserve!.address,
786
- ]).toArray();
787
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
788
-
789
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
790
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
718
+ if (!axn.referrer.equals(PublicKey.default)) {
719
+ const referrerTokenState = referrerTokenStatePda(
720
+ axn.referrer,
721
+ axn.outflowReserve!.address,
722
+ axn.kaminoMarket.programId
723
+ )[0];
724
+ const account = await axn.kaminoMarket.getConnection().getAccountInfo(referrerTokenState);
725
+ if (!account) {
726
+ axn.addInitReferrerTokenStateIx(axn.outflowReserve!, referrerTokenState);
727
+ }
791
728
  }
792
-
793
729
  await axn.addSupportIxs(
794
730
  'deposit',
795
731
  includeAtaIxns,
@@ -797,6 +733,7 @@ export class KaminoAction {
797
733
  includeUserMetadata,
798
734
  addInitObligationForFarmForDeposit,
799
735
  useV2Ixs,
736
+ undefined,
800
737
  createLookupTable,
801
738
  twoTokenAction
802
739
  );
@@ -814,6 +751,20 @@ export class KaminoAction {
814
751
  useV2Ixs
815
752
  );
816
753
  axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
754
+
755
+ // Create the scope refresh ixn in here to ensure it's the first ixn in the txn
756
+ const allReserves = new PublicKeySet<PublicKey>([
757
+ ...axn.depositReserves,
758
+ ...axn.borrowReserves,
759
+ axn.reserve.address,
760
+ ...(axn.outflowReserve ? [axn.outflowReserve.address] : []),
761
+ ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
762
+ ]).toArray();
763
+ const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
764
+
765
+ if (tokenIds.length > 0 && scopeRefreshConfig) {
766
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
767
+ }
817
768
  return axn;
818
769
  }
819
770
 
@@ -827,13 +778,13 @@ export class KaminoAction {
827
778
  currentSlot: number,
828
779
  obligation: KaminoObligation | ObligationType,
829
780
  useV2Ixs: boolean,
781
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
830
782
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
831
783
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
832
784
  requestElevationGroup: boolean = false,
833
785
  includeUserMetadata: boolean = true, // if true it includes user metadata,
834
786
  createLookupTable: boolean = true,
835
- referrer: PublicKey = PublicKey.default,
836
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
787
+ referrer: PublicKey = PublicKey.default
837
788
  ) {
838
789
  const axn = await KaminoAction.initializeMultiTokenAction(
839
790
  kaminoMarket,
@@ -855,18 +806,6 @@ export class KaminoAction {
855
806
  axn.addComputeBudgetIxn(extraComputeBudget);
856
807
  }
857
808
 
858
- const allReserves = new PublicKeySet<PublicKey>([
859
- ...axn.depositReserves,
860
- ...axn.borrowReserves,
861
- axn.reserve.address,
862
- axn.outflowReserve!.address,
863
- ]).toArray();
864
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
865
-
866
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
867
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
868
- }
869
-
870
809
  await axn.addSupportIxs(
871
810
  'repay',
872
811
  includeAtaIxns,
@@ -874,6 +813,7 @@ export class KaminoAction {
874
813
  includeUserMetadata,
875
814
  addInitObligationForFarmForRepay,
876
815
  useV2Ixs,
816
+ undefined,
877
817
  createLookupTable,
878
818
  twoTokenAction
879
819
  );
@@ -893,6 +833,19 @@ export class KaminoAction {
893
833
  useV2Ixs
894
834
  );
895
835
  axn.addRefreshFarmsCleanupTxnIxsToCleanupIxs();
836
+ // Create the scope refresh ixn in here to ensure it's the first ixn in the txn
837
+ const allReserves = new PublicKeySet<PublicKey>([
838
+ ...axn.depositReserves,
839
+ ...axn.borrowReserves,
840
+ axn.reserve.address,
841
+ ...(axn.outflowReserve ? [axn.outflowReserve.address] : []),
842
+ ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
843
+ ]).toArray();
844
+ const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
845
+
846
+ if (tokenIds.length > 0 && scopeRefreshConfig) {
847
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
848
+ }
896
849
  return axn;
897
850
  }
898
851
 
@@ -903,6 +856,7 @@ export class KaminoAction {
903
856
  owner: PublicKey,
904
857
  obligation: KaminoObligation | ObligationType,
905
858
  useV2Ixs: boolean,
859
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
906
860
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
907
861
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas,
908
862
  requestElevationGroup: boolean = false, // to be requested *after* the withdraw
@@ -910,7 +864,6 @@ export class KaminoAction {
910
864
  createLookupTable: boolean = true,
911
865
  referrer: PublicKey = PublicKey.default,
912
866
  currentSlot: number = 0,
913
- scopeRefresh: ScopeRefresh | undefined = undefined,
914
867
  overrideElevationGroupRequest?: number,
915
868
  // Optional customizations which may be needed if the obligation was mutated by some previous ixn.
916
869
  obligationCustomizations?: {
@@ -936,17 +889,6 @@ export class KaminoAction {
936
889
 
937
890
  axn.depositReserves.push(...(obligationCustomizations?.addedDepositReserves || []));
938
891
 
939
- const allReserves = new PublicKeySet<PublicKey>([
940
- ...axn.depositReserves,
941
- ...axn.borrowReserves,
942
- axn.reserve.address,
943
- ]).toArray();
944
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
945
-
946
- if (tokenIds.length > 0 && scopeRefresh && scopeRefresh.includeScopeRefresh) {
947
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
948
- }
949
-
950
892
  await axn.addSupportIxs(
951
893
  'withdraw',
952
894
  includeAtaIxns,
@@ -954,6 +896,7 @@ export class KaminoAction {
954
896
  includeUserMetadata,
955
897
  addInitObligationForFarm,
956
898
  useV2Ixs,
899
+ scopeRefreshConfig,
957
900
  createLookupTable,
958
901
  false,
959
902
  overrideElevationGroupRequest
@@ -993,6 +936,7 @@ export class KaminoAction {
993
936
  owner: PublicKey,
994
937
  obligation: KaminoObligation | ObligationType,
995
938
  useV2Ixs: boolean,
939
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
996
940
  currentSlot: number,
997
941
  payer: PublicKey | undefined = undefined,
998
942
  extraComputeBudget: number = 1_000_000,
@@ -1000,8 +944,7 @@ export class KaminoAction {
1000
944
  requestElevationGroup: boolean = false,
1001
945
  includeUserMetadata: boolean = true,
1002
946
  createLookupTable: boolean = true,
1003
- referrer: PublicKey = PublicKey.default,
1004
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
947
+ referrer: PublicKey = PublicKey.default
1005
948
  ) {
1006
949
  const axn = await KaminoAction.initialize(
1007
950
  'repay',
@@ -1020,17 +963,6 @@ export class KaminoAction {
1020
963
  axn.addComputeBudgetIxn(extraComputeBudget);
1021
964
  }
1022
965
 
1023
- const allReserves = new PublicKeySet<PublicKey>([
1024
- ...axn.depositReserves,
1025
- ...axn.borrowReserves,
1026
- axn.reserve.address,
1027
- ]).toArray();
1028
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
1029
-
1030
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
1031
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
1032
- }
1033
-
1034
966
  await axn.addSupportIxs(
1035
967
  'repay',
1036
968
  includeAtaIxns,
@@ -1038,6 +970,7 @@ export class KaminoAction {
1038
970
  includeUserMetadata,
1039
971
  addInitObligationForFarm,
1040
972
  useV2Ixs,
973
+ scopeRefreshConfig,
1041
974
  createLookupTable
1042
975
  );
1043
976
  if (useV2Ixs) {
@@ -1060,6 +993,7 @@ export class KaminoAction {
1060
993
  obligationOwner: PublicKey,
1061
994
  obligation: KaminoObligation | ObligationType,
1062
995
  useV2Ixs: boolean,
996
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
1063
997
  extraComputeBudget: number = 1_000_000, // if > 0 then adds the ixn
1064
998
  includeAtaIxns: boolean = true, // if true it includes create and close wsol and token atas, and creates all other token atas if they don't exist
1065
999
  requestElevationGroup: boolean = false,
@@ -1067,8 +1001,7 @@ export class KaminoAction {
1067
1001
  createLookupTable: boolean = true,
1068
1002
  referrer: PublicKey = PublicKey.default,
1069
1003
  maxAllowedLtvOverridePercent: number = 0,
1070
- currentSlot: number = 0,
1071
- scopeRefresh: ScopeRefresh = { includeScopeRefresh: false, scopeFeed: 'hubble' }
1004
+ currentSlot: number = 0
1072
1005
  ) {
1073
1006
  const axn = await KaminoAction.initializeMultiTokenAction(
1074
1007
  kaminoMarket,
@@ -1089,18 +1022,6 @@ export class KaminoAction {
1089
1022
  axn.addComputeBudgetIxn(extraComputeBudget);
1090
1023
  }
1091
1024
 
1092
- const allReserves = new PublicKeySet<PublicKey>([
1093
- ...axn.depositReserves,
1094
- ...axn.borrowReserves,
1095
- axn.reserve.address,
1096
- axn.outflowReserve!.address,
1097
- ]).toArray();
1098
- const tokenIds = axn.getTokenIdsForScopeRefresh(kaminoMarket, allReserves);
1099
-
1100
- if (tokenIds.length > 0 && scopeRefresh.includeScopeRefresh) {
1101
- await axn.addScopeRefreshIxs(tokenIds, scopeRefresh.scopeFeed);
1102
- }
1103
-
1104
1025
  await axn.addSupportIxs(
1105
1026
  'liquidate',
1106
1027
  includeAtaIxns,
@@ -1108,6 +1029,7 @@ export class KaminoAction {
1108
1029
  includeUserMetadata,
1109
1030
  addInitObligationForFarm,
1110
1031
  useV2Ixs,
1032
+ scopeRefreshConfig,
1111
1033
  createLookupTable
1112
1034
  );
1113
1035
  if (useV2Ixs) {
@@ -1136,6 +1058,17 @@ export class KaminoAction {
1136
1058
  axn.preTxnIxs.push(...createAtaIxs);
1137
1059
  axn.preTxnIxsLabels.push(`createAtasIxs[${axn.userTokenAccountAddress.toString()}]`);
1138
1060
 
1061
+ if (!axn.referrer.equals(PublicKey.default)) {
1062
+ const referrerTokenState = referrerTokenStatePda(
1063
+ axn.referrer,
1064
+ axn.reserve.address,
1065
+ axn.kaminoMarket.programId
1066
+ )[0];
1067
+ const account = await axn.kaminoMarket.getConnection().getAccountInfo(referrerTokenState);
1068
+ if (!account) {
1069
+ axn.addInitReferrerTokenStateIx(axn.reserve, referrerTokenState);
1070
+ }
1071
+ }
1139
1072
  axn.addRefreshReserveIxs([axn.reserve.address]);
1140
1073
  axn.addWithdrawReferrerFeesIxs();
1141
1074
 
@@ -1324,8 +1257,8 @@ export class KaminoAction {
1324
1257
  addDepositIxV2() {
1325
1258
  const farmsAccounts = this.reserve.state.farmCollateral.equals(PublicKey.default)
1326
1259
  ? {
1327
- obligationFarmUserState: PROGRAM_ID,
1328
- reserveFarmState: PROGRAM_ID,
1260
+ obligationFarmUserState: this.kaminoMarket.programId,
1261
+ reserveFarmState: this.kaminoMarket.programId,
1329
1262
  }
1330
1263
  : {
1331
1264
  obligationFarmUserState: obligationFarmStatePda(
@@ -1392,8 +1325,8 @@ export class KaminoAction {
1392
1325
  addDepositObligationCollateralIxV2() {
1393
1326
  const farmsAccounts = this.reserve.state.farmCollateral.equals(PublicKey.default)
1394
1327
  ? {
1395
- obligationFarmUserState: PROGRAM_ID,
1396
- reserveFarmState: PROGRAM_ID,
1328
+ obligationFarmUserState: this.kaminoMarket.programId,
1329
+ reserveFarmState: this.kaminoMarket.programId,
1397
1330
  }
1398
1331
  : {
1399
1332
  obligationFarmUserState: obligationFarmStatePda(
@@ -1477,8 +1410,8 @@ export class KaminoAction {
1477
1410
 
1478
1411
  const farmsAccounts = this.reserve.state.farmDebt.equals(PublicKey.default)
1479
1412
  ? {
1480
- obligationFarmUserState: PROGRAM_ID,
1481
- reserveFarmState: PROGRAM_ID,
1413
+ obligationFarmUserState: this.kaminoMarket.programId,
1414
+ reserveFarmState: this.kaminoMarket.programId,
1482
1415
  }
1483
1416
  : {
1484
1417
  obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
@@ -1552,8 +1485,8 @@ export class KaminoAction {
1552
1485
  async addWithdrawIxV2(collateralAmount: BN) {
1553
1486
  const farmsAccounts = this.reserve.state.farmCollateral.equals(PublicKey.default)
1554
1487
  ? {
1555
- obligationFarmUserState: PROGRAM_ID,
1556
- reserveFarmState: PROGRAM_ID,
1488
+ obligationFarmUserState: this.kaminoMarket.programId,
1489
+ reserveFarmState: this.kaminoMarket.programId,
1557
1490
  }
1558
1491
  : {
1559
1492
  obligationFarmUserState: obligationFarmStatePda(
@@ -1639,8 +1572,8 @@ export class KaminoAction {
1639
1572
 
1640
1573
  const farmsAccounts = this.reserve.state.farmDebt.equals(PublicKey.default)
1641
1574
  ? {
1642
- obligationFarmUserState: PROGRAM_ID,
1643
- reserveFarmState: PROGRAM_ID,
1575
+ obligationFarmUserState: this.kaminoMarket.programId,
1576
+ reserveFarmState: this.kaminoMarket.programId,
1644
1577
  }
1645
1578
  : {
1646
1579
  obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
@@ -1760,8 +1693,8 @@ export class KaminoAction {
1760
1693
  async addDepositAndBorrowIxV2() {
1761
1694
  const collateralFarmsAccounts = this.reserve.state.farmCollateral.equals(PublicKey.default)
1762
1695
  ? {
1763
- obligationFarmUserState: PROGRAM_ID,
1764
- reserveFarmState: PROGRAM_ID,
1696
+ obligationFarmUserState: this.kaminoMarket.programId,
1697
+ reserveFarmState: this.kaminoMarket.programId,
1765
1698
  }
1766
1699
  : {
1767
1700
  obligationFarmUserState: obligationFarmStatePda(
@@ -1824,8 +1757,8 @@ export class KaminoAction {
1824
1757
 
1825
1758
  const debtFarmsAccounts = this.outflowReserve.state.farmDebt.equals(PublicKey.default)
1826
1759
  ? {
1827
- obligationFarmUserState: PROGRAM_ID,
1828
- reserveFarmState: PROGRAM_ID,
1760
+ obligationFarmUserState: this.kaminoMarket.programId,
1761
+ reserveFarmState: this.kaminoMarket.programId,
1829
1762
  }
1830
1763
  : {
1831
1764
  obligationFarmUserState: obligationFarmStatePda(
@@ -1953,8 +1886,8 @@ export class KaminoAction {
1953
1886
 
1954
1887
  const debtFarmsAccounts = this.reserve.state.farmDebt.equals(PublicKey.default)
1955
1888
  ? {
1956
- obligationFarmUserState: PROGRAM_ID,
1957
- reserveFarmState: PROGRAM_ID,
1889
+ obligationFarmUserState: this.kaminoMarket.programId,
1890
+ reserveFarmState: this.kaminoMarket.programId,
1958
1891
  }
1959
1892
  : {
1960
1893
  obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
@@ -2001,8 +1934,8 @@ export class KaminoAction {
2001
1934
 
2002
1935
  const collateralFarmsAccounts = this.outflowReserve.state.farmCollateral.equals(PublicKey.default)
2003
1936
  ? {
2004
- obligationFarmUserState: PROGRAM_ID,
2005
- reserveFarmState: PROGRAM_ID,
1937
+ obligationFarmUserState: this.kaminoMarket.programId,
1938
+ reserveFarmState: this.kaminoMarket.programId,
2006
1939
  }
2007
1940
  : {
2008
1941
  obligationFarmUserState: obligationFarmStatePda(
@@ -2110,8 +2043,8 @@ export class KaminoAction {
2110
2043
 
2111
2044
  const collateralFarmsAccounts = this.outflowReserve.state.farmCollateral.equals(PublicKey.default)
2112
2045
  ? {
2113
- obligationFarmUserState: PROGRAM_ID,
2114
- reserveFarmState: PROGRAM_ID,
2046
+ obligationFarmUserState: this.kaminoMarket.programId,
2047
+ reserveFarmState: this.kaminoMarket.programId,
2115
2048
  }
2116
2049
  : {
2117
2050
  obligationFarmUserState: obligationFarmStatePda(
@@ -2123,8 +2056,8 @@ export class KaminoAction {
2123
2056
 
2124
2057
  const debtFarmsAccounts = this.reserve.state.farmDebt.equals(PublicKey.default)
2125
2058
  ? {
2126
- obligationFarmUserState: PROGRAM_ID,
2127
- reserveFarmState: PROGRAM_ID,
2059
+ obligationFarmUserState: this.kaminoMarket.programId,
2060
+ reserveFarmState: this.kaminoMarket.programId,
2128
2061
  }
2129
2062
  : {
2130
2063
  obligationFarmUserState: obligationFarmStatePda(this.getObligationPda(), this.reserve.state.farmDebt)[0],
@@ -2500,6 +2433,7 @@ export class KaminoAction {
2500
2433
  includeUserMetadata: boolean,
2501
2434
  addInitObligationForFarm: boolean,
2502
2435
  useV2Ixs: boolean,
2436
+ scopeRefreshConfig: ScopePriceRefreshConfig | undefined,
2503
2437
  createLookupTable: boolean,
2504
2438
  twoTokenAction: boolean = false,
2505
2439
  overrideElevationGroupRequest?: number
@@ -2520,13 +2454,6 @@ export class KaminoAction {
2520
2454
  this.addInitUserMetadataIxs(lookupTable);
2521
2455
  }
2522
2456
 
2523
- if (['borrow', 'withdrawReferrerFees'].includes(action)) {
2524
- await this.addInitReferrerTokenStateIx(this.reserve);
2525
- }
2526
- // depositAndBorrow
2527
- if (action === 'deposit' && this.outflowReserve) {
2528
- await this.addInitReferrerTokenStateIx(this.outflowReserve);
2529
- }
2530
2457
  await this.addInitObligationIxs();
2531
2458
  }
2532
2459
 
@@ -2540,6 +2467,19 @@ export class KaminoAction {
2540
2467
  twoTokenAction,
2541
2468
  overrideElevationGroupRequest
2542
2469
  );
2470
+
2471
+ const allReserves = new PublicKeySet<PublicKey>([
2472
+ ...this.depositReserves,
2473
+ ...this.borrowReserves,
2474
+ this.reserve.address,
2475
+ ...(this.outflowReserve ? [this.outflowReserve.address] : []),
2476
+ ...(this.preLoadedDepositReservesSameTx ? this.preLoadedDepositReservesSameTx : []),
2477
+ ]).toArray();
2478
+ const tokenIds = getTokenIdsForScopeRefresh(this.kaminoMarket, allReserves);
2479
+
2480
+ if (tokenIds.length > 0 && scopeRefreshConfig) {
2481
+ await this.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
2482
+ }
2543
2483
  }
2544
2484
 
2545
2485
  private static optionalAccount(pubkey: PublicKey, programId: PublicKey = PROGRAM_ID): PublicKey {
@@ -2948,29 +2888,21 @@ export class KaminoAction {
2948
2888
  this.setupIxsLabels.push(`initUserMetadata[${userMetadataAddress.toString()}]`);
2949
2889
  }
2950
2890
 
2951
- private async addInitReferrerTokenStateIx(reserve: KaminoReserve) {
2952
- if (this.referrer.equals(PublicKey.default)) {
2953
- return;
2954
- }
2955
-
2956
- const referrerTokenState = referrerTokenStatePda(this.referrer, reserve.address, this.kaminoMarket.programId)[0];
2957
- const account = await this.kaminoMarket.getConnection().getAccountInfo(referrerTokenState);
2958
- if (!account) {
2959
- const initReferrerTokenStateIx = initReferrerTokenState(
2960
- {
2961
- lendingMarket: this.kaminoMarket.getAddress(),
2962
- payer: this.owner,
2963
- reserve: reserve.address,
2964
- referrer: this.referrer,
2965
- referrerTokenState,
2966
- rent: SYSVAR_RENT_PUBKEY,
2967
- systemProgram: SystemProgram.programId,
2968
- },
2969
- this.kaminoMarket.programId
2970
- );
2971
- this.setupIxs.unshift(initReferrerTokenStateIx);
2972
- this.setupIxsLabels.unshift(`InitReferrerTokenState[${referrerTokenState.toString()} res=${reserve.address}]`);
2973
- }
2891
+ private addInitReferrerTokenStateIx(reserve: KaminoReserve, referrerTokenState: PublicKey) {
2892
+ const initReferrerTokenStateIx = initReferrerTokenState(
2893
+ {
2894
+ lendingMarket: this.kaminoMarket.getAddress(),
2895
+ payer: this.owner,
2896
+ reserve: reserve.address,
2897
+ referrer: this.referrer,
2898
+ referrerTokenState,
2899
+ rent: SYSVAR_RENT_PUBKEY,
2900
+ systemProgram: SystemProgram.programId,
2901
+ },
2902
+ this.kaminoMarket.programId
2903
+ );
2904
+ this.setupIxs.unshift(initReferrerTokenStateIx);
2905
+ this.setupIxsLabels.unshift(`InitReferrerTokenState[${referrerTokenState.toString()} res=${reserve.address}]`);
2974
2906
  }
2975
2907
 
2976
2908
  private addWithdrawReferrerFeesIxs() {