@exponent-labs/exponent-sdk 0.9.0 → 0.9.2

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 (155) hide show
  1. package/build/client/vaults/index.d.ts +2 -0
  2. package/build/client/vaults/index.js +2 -0
  3. package/build/client/vaults/index.js.map +1 -1
  4. package/build/client/vaults/types/index.d.ts +2 -0
  5. package/build/client/vaults/types/index.js +2 -0
  6. package/build/client/vaults/types/index.js.map +1 -1
  7. package/build/client/vaults/types/kaminoFarmEntry.d.ts +15 -0
  8. package/build/client/vaults/types/kaminoFarmEntry.js +17 -0
  9. package/build/client/vaults/types/kaminoFarmEntry.js.map +1 -0
  10. package/build/client/vaults/types/kaminoObligationEntry.d.ts +21 -4
  11. package/build/client/vaults/types/kaminoObligationEntry.js +2 -1
  12. package/build/client/vaults/types/kaminoObligationEntry.js.map +1 -1
  13. package/build/client/vaults/types/positionUpdate.d.ts +9 -0
  14. package/build/client/vaults/types/positionUpdate.js +23 -0
  15. package/build/client/vaults/types/positionUpdate.js.map +1 -1
  16. package/build/client/vaults/types/proposalAction.js +0 -3
  17. package/build/client/vaults/types/proposalAction.js.map +1 -1
  18. package/build/client/vaults/types/reserveFarmMapping.d.ts +19 -0
  19. package/build/client/vaults/types/reserveFarmMapping.js +18 -0
  20. package/build/client/vaults/types/reserveFarmMapping.js.map +1 -0
  21. package/build/client/vaults/types/strategyPosition.d.ts +5 -0
  22. package/build/client/vaults/types/strategyPosition.js +5 -0
  23. package/build/client/vaults/types/strategyPosition.js.map +1 -1
  24. package/build/exponentVaults/aumCalculator.d.ts +25 -4
  25. package/build/exponentVaults/aumCalculator.js +236 -15
  26. package/build/exponentVaults/aumCalculator.js.map +1 -1
  27. package/build/exponentVaults/fetcher.d.ts +52 -0
  28. package/build/exponentVaults/fetcher.js +199 -0
  29. package/build/exponentVaults/fetcher.js.map +1 -0
  30. package/build/exponentVaults/index.d.ts +10 -9
  31. package/build/exponentVaults/index.js +26 -8
  32. package/build/exponentVaults/index.js.map +1 -1
  33. package/build/exponentVaults/kamino-farms.d.ts +144 -0
  34. package/build/exponentVaults/kamino-farms.js +396 -0
  35. package/build/exponentVaults/kamino-farms.js.map +1 -0
  36. package/build/exponentVaults/loopscale/client.d.ts +240 -0
  37. package/build/exponentVaults/loopscale/client.js +590 -0
  38. package/build/exponentVaults/loopscale/client.js.map +1 -0
  39. package/build/exponentVaults/loopscale/client.test.d.ts +1 -0
  40. package/build/exponentVaults/loopscale/client.test.js +183 -0
  41. package/build/exponentVaults/loopscale/client.test.js.map +1 -0
  42. package/build/exponentVaults/loopscale/helpers.d.ts +29 -0
  43. package/build/exponentVaults/loopscale/helpers.js +119 -0
  44. package/build/exponentVaults/loopscale/helpers.js.map +1 -0
  45. package/build/exponentVaults/loopscale/index.d.ts +3 -0
  46. package/build/exponentVaults/loopscale/index.js +12 -0
  47. package/build/exponentVaults/loopscale/index.js.map +1 -0
  48. package/build/exponentVaults/loopscale/prepared-transactions.d.ts +13 -0
  49. package/build/exponentVaults/loopscale/prepared-transactions.js +271 -0
  50. package/build/exponentVaults/loopscale/prepared-transactions.js.map +1 -0
  51. package/build/exponentVaults/loopscale/prepared-transactions.test.d.ts +1 -0
  52. package/build/exponentVaults/loopscale/prepared-transactions.test.js +400 -0
  53. package/build/exponentVaults/loopscale/prepared-transactions.test.js.map +1 -0
  54. package/build/exponentVaults/loopscale/prepared-types.d.ts +62 -0
  55. package/build/exponentVaults/loopscale/prepared-types.js +3 -0
  56. package/build/exponentVaults/loopscale/prepared-types.js.map +1 -0
  57. package/build/exponentVaults/loopscale/response-plan.d.ts +69 -0
  58. package/build/exponentVaults/loopscale/response-plan.js +141 -0
  59. package/build/exponentVaults/loopscale/response-plan.js.map +1 -0
  60. package/build/exponentVaults/loopscale/response-plan.test.d.ts +1 -0
  61. package/build/exponentVaults/loopscale/response-plan.test.js +139 -0
  62. package/build/exponentVaults/loopscale/response-plan.test.js.map +1 -0
  63. package/build/exponentVaults/loopscale/send-plan.d.ts +75 -0
  64. package/build/exponentVaults/loopscale/send-plan.js +235 -0
  65. package/build/exponentVaults/loopscale/send-plan.js.map +1 -0
  66. package/build/exponentVaults/loopscale/types.d.ts +443 -0
  67. package/build/exponentVaults/loopscale/types.js +3 -0
  68. package/build/exponentVaults/loopscale/types.js.map +1 -0
  69. package/build/exponentVaults/loopscale-client.d.ts +113 -524
  70. package/build/exponentVaults/loopscale-client.js +296 -539
  71. package/build/exponentVaults/loopscale-client.js.map +1 -1
  72. package/build/exponentVaults/loopscale-client.test.d.ts +1 -0
  73. package/build/exponentVaults/loopscale-client.test.js +162 -0
  74. package/build/exponentVaults/loopscale-client.test.js.map +1 -0
  75. package/build/exponentVaults/loopscale-client.types.d.ts +425 -0
  76. package/build/exponentVaults/loopscale-client.types.js +3 -0
  77. package/build/exponentVaults/loopscale-client.types.js.map +1 -0
  78. package/build/exponentVaults/loopscale-execution.d.ts +125 -0
  79. package/build/exponentVaults/loopscale-execution.js +341 -0
  80. package/build/exponentVaults/loopscale-execution.js.map +1 -0
  81. package/build/exponentVaults/loopscale-execution.test.d.ts +1 -0
  82. package/build/exponentVaults/loopscale-execution.test.js +139 -0
  83. package/build/exponentVaults/loopscale-execution.test.js.map +1 -0
  84. package/build/exponentVaults/loopscale-vault.d.ts +115 -0
  85. package/build/exponentVaults/loopscale-vault.js +275 -0
  86. package/build/exponentVaults/loopscale-vault.js.map +1 -0
  87. package/build/exponentVaults/loopscale-vault.test.d.ts +1 -0
  88. package/build/exponentVaults/loopscale-vault.test.js +102 -0
  89. package/build/exponentVaults/loopscale-vault.test.js.map +1 -0
  90. package/build/exponentVaults/policyBuilders.d.ts +62 -0
  91. package/build/exponentVaults/policyBuilders.js +119 -2
  92. package/build/exponentVaults/policyBuilders.js.map +1 -1
  93. package/build/exponentVaults/pricePathResolver.d.ts +45 -0
  94. package/build/exponentVaults/pricePathResolver.js +198 -0
  95. package/build/exponentVaults/pricePathResolver.js.map +1 -0
  96. package/build/exponentVaults/pricePathResolver.test.d.ts +1 -0
  97. package/build/exponentVaults/pricePathResolver.test.js +369 -0
  98. package/build/exponentVaults/pricePathResolver.test.js.map +1 -0
  99. package/build/exponentVaults/syncTransaction.js +4 -1
  100. package/build/exponentVaults/syncTransaction.js.map +1 -1
  101. package/build/exponentVaults/titan-quote.js +170 -36
  102. package/build/exponentVaults/titan-quote.js.map +1 -1
  103. package/build/exponentVaults/vault-instruction-types.d.ts +363 -0
  104. package/build/exponentVaults/vault-instruction-types.js +128 -0
  105. package/build/exponentVaults/vault-instruction-types.js.map +1 -0
  106. package/build/exponentVaults/vault-interaction.d.ts +203 -343
  107. package/build/exponentVaults/vault-interaction.js +1894 -426
  108. package/build/exponentVaults/vault-interaction.js.map +1 -1
  109. package/build/exponentVaults/vault-interaction.kamino-vault.test.d.ts +1 -0
  110. package/build/exponentVaults/vault-interaction.kamino-vault.test.js +143 -0
  111. package/build/exponentVaults/vault-interaction.kamino-vault.test.js.map +1 -0
  112. package/build/exponentVaults/vault.d.ts +51 -2
  113. package/build/exponentVaults/vault.js +324 -48
  114. package/build/exponentVaults/vault.js.map +1 -1
  115. package/build/exponentVaults/vaultTransactionBuilder.d.ts +100 -134
  116. package/build/exponentVaults/vaultTransactionBuilder.js +383 -285
  117. package/build/exponentVaults/vaultTransactionBuilder.js.map +1 -1
  118. package/build/exponentVaults/vaultTransactionBuilder.test.d.ts +1 -0
  119. package/build/exponentVaults/vaultTransactionBuilder.test.js +297 -0
  120. package/build/exponentVaults/vaultTransactionBuilder.test.js.map +1 -0
  121. package/build/marketThree.d.ts +6 -2
  122. package/build/marketThree.js +10 -8
  123. package/build/marketThree.js.map +1 -1
  124. package/package.json +34 -32
  125. package/src/client/vaults/index.ts +2 -0
  126. package/src/client/vaults/types/index.ts +2 -0
  127. package/src/client/vaults/types/kaminoFarmEntry.ts +32 -0
  128. package/src/client/vaults/types/kaminoObligationEntry.ts +6 -3
  129. package/src/client/vaults/types/positionUpdate.ts +62 -0
  130. package/src/client/vaults/types/proposalAction.ts +0 -3
  131. package/src/client/vaults/types/reserveFarmMapping.ts +35 -0
  132. package/src/client/vaults/types/strategyPosition.ts +18 -1
  133. package/src/exponentVaults/aumCalculator.ts +353 -16
  134. package/src/exponentVaults/fetcher.ts +257 -0
  135. package/src/exponentVaults/index.ts +65 -40
  136. package/src/exponentVaults/kamino-farms.ts +538 -0
  137. package/src/exponentVaults/loopscale/client.ts +808 -0
  138. package/src/exponentVaults/loopscale/helpers.ts +172 -0
  139. package/src/exponentVaults/loopscale/index.ts +57 -0
  140. package/src/exponentVaults/loopscale/prepared-transactions.ts +435 -0
  141. package/src/exponentVaults/loopscale/prepared-types.ts +73 -0
  142. package/src/exponentVaults/loopscale/types.ts +466 -0
  143. package/src/exponentVaults/policyBuilders.ts +170 -0
  144. package/src/exponentVaults/pricePathResolver.test.ts +466 -0
  145. package/src/exponentVaults/pricePathResolver.ts +273 -0
  146. package/src/exponentVaults/syncTransaction.ts +6 -1
  147. package/src/exponentVaults/titan-quote.ts +231 -45
  148. package/src/exponentVaults/vault-instruction-types.ts +493 -0
  149. package/src/exponentVaults/vault-interaction.kamino-vault.test.ts +149 -0
  150. package/src/exponentVaults/vault-interaction.ts +2818 -799
  151. package/src/exponentVaults/vault.ts +474 -63
  152. package/src/exponentVaults/vaultTransactionBuilder.test.ts +349 -0
  153. package/src/exponentVaults/vaultTransactionBuilder.ts +581 -433
  154. package/src/marketThree.ts +14 -6
  155. package/src/exponentVaults/loopscale-client.ts +0 -1373
@@ -1,9 +1,10 @@
1
1
  import { AccountMeta, Connection, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
2
- import { ExponentPrices, ExponentVault as ExponentVaultAccountType, ExponentVaultsFetcher, PriceId } from "@exponent-labs/exponent-vaults-fetcher";
2
+ import { ExponentPrices, ExponentVault as ExponentVaultAccountType, PriceId } from "@exponent-labs/exponent-vaults-fetcher";
3
3
  import { ExponentVaultsPDA, SeedId } from "@exponent-labs/exponent-vaults-pda";
4
4
  import * as exponentVaults from "../client/vaults";
5
5
  import { Environment } from "../environment";
6
6
  import { AumCalculator } from "./aumCalculator";
7
+ import { ExponentVaultsFetcher } from "./fetcher";
7
8
  import { SquadsVaultTxnResolver } from "./squadsVaultTxnResolver";
8
9
  type Numeric = bigint | number;
9
10
  export declare const SYNTHETIC_USD_MINT: PublicKey;
@@ -11,6 +12,12 @@ export declare const SYNTHETIC_USD_DECIMALS = 6;
11
12
  export declare const SYNTHETIC_USD9_MINT: PublicKey;
12
13
  export declare const SYNTHETIC_USD9_DECIMALS = 9;
13
14
  export declare const getSyntheticMintDecimals: (mint: PublicKey) => number | null;
15
+ export declare function collectTrackedStrategyVaultPriceIds(state: {
16
+ tokenEntries: Array<{
17
+ priceId: unknown;
18
+ }>;
19
+ strategyPositions: Array<Record<string, unknown>>;
20
+ }): Set<number>;
14
21
  export type DataOperator = "Equals" | "NotEquals" | "GreaterThan" | "GreaterThanOrEqualTo" | "LessThan" | "LessThanOrEqualTo";
15
22
  export type DataValue = {
16
23
  u8: number;
@@ -149,6 +156,10 @@ export interface UpdatePriceParams {
149
156
  remainingAccounts?: PublicKey[];
150
157
  priceId: number;
151
158
  }
159
+ export interface UpdateStrategyVaultPricesOptions {
160
+ manager?: PublicKey;
161
+ priceIds?: Iterable<number>;
162
+ }
152
163
  export interface QueueWithdrawalParams {
153
164
  depositor: PublicKey;
154
165
  lpAmount: Numeric;
@@ -441,6 +452,27 @@ export interface WrapperManagerUpdatePositionParams {
441
452
  exponentPrices?: PublicKey;
442
453
  systemProgram?: PublicKey;
443
454
  }
455
+ export interface WrapperAddKaminoObligationPositionParams {
456
+ manager: PublicKey;
457
+ obligation: PublicKey;
458
+ lendingProgramId: PublicKey;
459
+ quotePriceId: exponentVaults.PriceId;
460
+ reservePriceMappings: exponentVaults.ReservePriceMapping[];
461
+ reserveFarmMappings?: exponentVaults.ReserveFarmMapping[];
462
+ minPriceStatusFlags: number;
463
+ remainingAccounts?: AccountMeta[];
464
+ exponentPrices?: PublicKey;
465
+ systemProgram?: PublicKey;
466
+ }
467
+ export interface WrapperUpsertKaminoObligationReservePriceMappingsParams {
468
+ manager: PublicKey;
469
+ obligation: PublicKey;
470
+ reservePriceMappings: exponentVaults.ReservePriceMapping[];
471
+ reserveFarmMappings?: exponentVaults.ReserveFarmMapping[];
472
+ remainingAccounts?: AccountMeta[];
473
+ exponentPrices?: PublicKey;
474
+ systemProgram?: PublicKey;
475
+ }
444
476
  export type WrapperAddPolicyParams = AddPolicyParams;
445
477
  export type WrapperRemovePolicyParams = RemovePolicyParams;
446
478
  export type WrapperUpdatePolicyParams = UpdatePolicyParams;
@@ -467,6 +499,8 @@ export declare class ExponentVault {
467
499
  pda: ExponentVaultsPDA;
468
500
  aumCalculator: AumCalculator;
469
501
  private clmmTicksMap;
502
+ private kaminoFarmAuxAccountsMap;
503
+ private kaminoObligationFarmUserStates;
470
504
  static squadsVaultTxnResolver: SquadsVaultTxnResolver;
471
505
  constructor(params: {
472
506
  state: ExponentVaultAccountType;
@@ -486,6 +520,7 @@ export declare class ExponentVault {
486
520
  }): Promise<ExponentVault[]>;
487
521
  reload(connection?: Connection): Promise<ExponentVault>;
488
522
  private populateClmmTicksCache;
523
+ private populateKaminoFarmAuxAccountsCache;
489
524
  /**
490
525
  * Derive the PDA for a vault using its 8-byte seed identifier.
491
526
  */
@@ -518,6 +553,12 @@ export declare class ExponentVault {
518
553
  private strategyPositionAccountMetas;
519
554
  private tokenEntryAccountMetas;
520
555
  private aumRemainingAccounts;
556
+ /**
557
+ * Returns the readonly account metas required to recalculate the vault's current tracked AUM.
558
+ * Extra metas can be appended for pending positions or newly introduced Kamino reserves.
559
+ */
560
+ getAumRemainingAccountMetas(extraRemainingAccounts?: AccountMeta[]): AccountMeta[];
561
+ private ixManagePriceUpdates;
521
562
  ixUpdatePrice({ priceInterfaceAccounts, pythPriceFeedId, remainingAccounts, priceId, }: UpdatePriceParams): TransactionInstruction;
522
563
  ixsDepositLiquidity({ depositor, mint, tokenAmountIn, minLpOut, tokenSrc, entryTokenVault, tokenLpDst, tokenProgram, extraRemainingAccounts, useLegacyTokenAccounts, }: DepositLiquidityParams): Promise<TransactionInstruction[]>;
523
564
  ixQueueWithdrawal({ depositor, lpAmount, tokenLpSrc, tokenProgram, systemProgram, tokenLpEscrow, }: QueueWithdrawalParams): {
@@ -537,6 +578,14 @@ export declare class ExponentVault {
537
578
  * Create instruction to call wrapper_manager_update_position.
538
579
  */
539
580
  ixWrapperManagerUpdatePosition({ manager, update, remainingAccounts, exponentPrices, systemProgram, }: WrapperManagerUpdatePositionParams): TransactionInstruction;
581
+ /**
582
+ * Convenience wrapper for adding a tracked Kamino obligation position.
583
+ */
584
+ ixWrapperAddKaminoObligationPosition({ manager, obligation, lendingProgramId, quotePriceId, reservePriceMappings, reserveFarmMappings, minPriceStatusFlags, remainingAccounts, exponentPrices, systemProgram, }: WrapperAddKaminoObligationPositionParams): TransactionInstruction;
585
+ /**
586
+ * Convenience wrapper for updating tracked reserve price mappings on a Kamino obligation.
587
+ */
588
+ ixWrapperUpsertKaminoObligationReservePriceMappings({ manager, obligation, reservePriceMappings, reserveFarmMappings, remainingAccounts, exponentPrices, systemProgram, }: WrapperUpsertKaminoObligationReservePriceMappingsParams): TransactionInstruction;
540
589
  /**
541
590
  * Create instruction to add a policy to this vault.
542
591
  * Direct policy management requires an empty vault; live vaults must use proposals.
@@ -596,7 +645,7 @@ export declare class ExponentVault {
596
645
  * Requires an RPC endpoint that supports the `simulateBundle` method (e.g., Jito, Helius).
597
646
  */
598
647
  getTotalAumViaJitoBundle(pricesAccount: ExponentPrices, jitoBundleRpc?: string): Promise<bigint>;
599
- ixsUpdateStrategyVaultPrices(pricesAccount: ExponentPrices): Promise<TransactionInstruction[]>;
648
+ ixsUpdateStrategyVaultPrices(pricesAccount: ExponentPrices, options?: UpdateStrategyVaultPricesOptions): Promise<TransactionInstruction[]>;
600
649
  /**
601
650
  * Converts vault `PolicyConfig` (policyType shape from policy builders) to the Codama/client codec shape
602
651
  * required by the proposal action codecs used by staged proposal creation.
@@ -26,14 +26,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.ExponentVault = exports.getSyntheticMintDecimals = exports.SYNTHETIC_USD9_DECIMALS = exports.SYNTHETIC_USD9_MINT = exports.SYNTHETIC_USD_DECIMALS = exports.SYNTHETIC_USD_MINT = void 0;
29
+ exports.ExponentVault = exports.collectTrackedStrategyVaultPriceIds = exports.getSyntheticMintDecimals = exports.SYNTHETIC_USD9_DECIMALS = exports.SYNTHETIC_USD9_MINT = exports.SYNTHETIC_USD_DECIMALS = exports.SYNTHETIC_USD_MINT = void 0;
30
30
  // The following methods have breaking changes: ixDepositLiquidity, ixQueueWithdrawal, ixExecuteWithdrawal, ixManagerRefreshSyRate
31
31
  // Account names changed: tokenSySrc -> tokenSrc, tokenSyVault -> entryTokenVault
32
32
  // New required accounts: exponentPrices
33
33
  const spl_token_1 = require("@solana/spl-token");
34
34
  const web3_js_1 = require("@solana/web3.js");
35
35
  const bs58_1 = __importDefault(require("bs58"));
36
- const exponent_vaults_fetcher_1 = require("@exponent-labs/exponent-vaults-fetcher");
37
36
  const exponent_vaults_idl_1 = require("@exponent-labs/exponent-vaults-idl");
38
37
  const exponent_vaults_pda_1 = require("@exponent-labs/exponent-vaults-pda");
39
38
  const marketThree_1 = require("../client/clmm/accounts/marketThree");
@@ -41,11 +40,17 @@ const exponentVaults = __importStar(require("../client/vaults"));
41
40
  const environment_1 = require("../environment");
42
41
  const utils_1 = require("../utils");
43
42
  const aumCalculator_1 = require("./aumCalculator");
43
+ const fetcher_1 = require("./fetcher");
44
+ const kamino_farms_1 = require("./kamino-farms");
45
+ const pricePathResolver_1 = require("./pricePathResolver");
44
46
  const squadsVaultTxnResolver_1 = require("./squadsVaultTxnResolver");
47
+ const constants_1 = require("./../../../kamino-lend-standard/src/constants");
45
48
  exports.SYNTHETIC_USD_MINT = new web3_js_1.PublicKey("USD1111111111111111111111111111111111111111");
46
49
  exports.SYNTHETIC_USD_DECIMALS = 6;
47
50
  exports.SYNTHETIC_USD9_MINT = new web3_js_1.PublicKey("USD1111111111111111111111111111111111111119");
48
51
  exports.SYNTHETIC_USD9_DECIMALS = 9;
52
+ const LOCAL_UPDATE_PRICE_DISCRIMINATOR = Buffer.from([7]);
53
+ const KAMINO_FARMS_PROGRAM_ID = new web3_js_1.PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr");
49
54
  const getSyntheticMintDecimals = (mint) => {
50
55
  if (mint.equals(exports.SYNTHETIC_USD_MINT))
51
56
  return exports.SYNTHETIC_USD_DECIMALS;
@@ -54,6 +59,82 @@ const getSyntheticMintDecimals = (mint) => {
54
59
  return null;
55
60
  };
56
61
  exports.getSyntheticMintDecimals = getSyntheticMintDecimals;
62
+ function unwrapTupleLikeValue(value) {
63
+ if (Array.isArray(value)) {
64
+ return value[0];
65
+ }
66
+ if (value && typeof value === "object" && "0" in value) {
67
+ return value[0];
68
+ }
69
+ return value ?? undefined;
70
+ }
71
+ function addTrackedPriceIds(target, priceIdValue) {
72
+ for (const id of (0, pricePathResolver_1.extractPriceIds)(priceIdValue)) {
73
+ const numericId = Number(id);
74
+ if (numericId !== 0) {
75
+ target.add(numericId);
76
+ }
77
+ }
78
+ }
79
+ function collectTrackedStrategyVaultPriceIds(state) {
80
+ const allPriceIds = new Set();
81
+ for (const entry of state.tokenEntries) {
82
+ addTrackedPriceIds(allPriceIds, entry.priceId);
83
+ }
84
+ for (const position of state.strategyPositions) {
85
+ if ("orderbook" in position) {
86
+ const orderbook = unwrapTupleLikeValue(position.orderbook);
87
+ if (orderbook?.priceIdPt) {
88
+ addTrackedPriceIds(allPriceIds, orderbook.priceIdPt);
89
+ }
90
+ continue;
91
+ }
92
+ if ("tokenAccount" in position) {
93
+ const tokenAccount = unwrapTupleLikeValue(position.tokenAccount);
94
+ for (const balance of tokenAccount?.balances ?? []) {
95
+ if (balance.priceId) {
96
+ addTrackedPriceIds(allPriceIds, balance.priceId);
97
+ }
98
+ }
99
+ continue;
100
+ }
101
+ if ("yieldPosition" in position) {
102
+ const yieldPosition = unwrapTupleLikeValue(position.yieldPosition);
103
+ if (yieldPosition?.priceIdPt) {
104
+ addTrackedPriceIds(allPriceIds, yieldPosition.priceIdPt);
105
+ }
106
+ continue;
107
+ }
108
+ if ("clmmPosition" in position) {
109
+ const clmmPosition = unwrapTupleLikeValue(position.clmmPosition);
110
+ if (clmmPosition?.priceIdPt) {
111
+ addTrackedPriceIds(allPriceIds, clmmPosition.priceIdPt);
112
+ }
113
+ if (clmmPosition?.priceIdSy) {
114
+ addTrackedPriceIds(allPriceIds, clmmPosition.priceIdSy);
115
+ }
116
+ continue;
117
+ }
118
+ if ("obligation" in position) {
119
+ const rawObligation = position.obligation;
120
+ const inner = unwrapTupleLikeValue(rawObligation);
121
+ const kaminoVariant = inner && typeof inner === "object" && "kaminoObligation" in inner
122
+ ? inner.kaminoObligation
123
+ : inner;
124
+ const kaminoEntry = unwrapTupleLikeValue(kaminoVariant);
125
+ if (kaminoEntry?.quotePriceId) {
126
+ addTrackedPriceIds(allPriceIds, kaminoEntry.quotePriceId);
127
+ }
128
+ for (const mapping of kaminoEntry?.reservePriceMappings ?? []) {
129
+ if (mapping.reservePriceId) {
130
+ addTrackedPriceIds(allPriceIds, mapping.reservePriceId);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ return allPriceIds;
136
+ }
137
+ exports.collectTrackedStrategyVaultPriceIds = collectTrackedStrategyVaultPriceIds;
57
138
  const getMintDecimals = async (connection, mint) => {
58
139
  const syntheticDecimals = (0, exports.getSyntheticMintDecimals)(mint);
59
140
  if (syntheticDecimals !== null) {
@@ -67,6 +148,15 @@ const pushPriceMintAccount = (remainingAccounts, mint) => {
67
148
  return;
68
149
  remainingAccounts.push({ pubkey: mint, isSigner: false, isWritable: false });
69
150
  };
151
+ const isLocalRpcEndpoint = (rpcEndpoint) => {
152
+ try {
153
+ const hostname = new URL(rpcEndpoint).hostname;
154
+ return hostname === "127.0.0.1" || hostname === "localhost";
155
+ }
156
+ catch {
157
+ return rpcEndpoint.includes("127.0.0.1") || rpcEndpoint.includes("localhost");
158
+ }
159
+ };
70
160
  const VAULT_SEED = Buffer.from("vault");
71
161
  const toBigInt = (value) => {
72
162
  if (typeof value === "bigint")
@@ -241,6 +331,8 @@ class ExponentVault {
241
331
  pda;
242
332
  aumCalculator;
243
333
  clmmTicksMap = new Map();
334
+ kaminoFarmAuxAccountsMap = new Map();
335
+ kaminoObligationFarmUserStates = new Set();
244
336
  static squadsVaultTxnResolver = new squadsVaultTxnResolver_1.SquadsVaultTxnResolver();
245
337
  constructor(params) {
246
338
  this.state = params.state;
@@ -248,13 +340,13 @@ class ExponentVault {
248
340
  this.env = params.env ?? environment_1.LOCAL_ENV;
249
341
  this.connection = params.connection;
250
342
  this.programId = params.programId ?? this.env.exponentVaultsProgramId ?? new web3_js_1.PublicKey(exponent_vaults_idl_1.PROGRAM_ID);
251
- this.fetcher = new exponent_vaults_fetcher_1.ExponentVaultsFetcher(this.connection, this.programId);
343
+ this.fetcher = new fetcher_1.ExponentVaultsFetcher(this.connection, this.programId);
252
344
  this.pda = new exponent_vaults_pda_1.ExponentVaultsPDA(this.programId);
253
345
  this.aumCalculator = new aumCalculator_1.AumCalculator(this.state, this.connection, this.env);
254
346
  }
255
347
  static async load(params) {
256
348
  const env = params.env ?? environment_1.LOCAL_ENV;
257
- const fetcher = new exponent_vaults_fetcher_1.ExponentVaultsFetcher(params.connection, env.exponentVaultsProgramId ?? exponent_vaults_idl_1.PROGRAM_ID);
349
+ const fetcher = new fetcher_1.ExponentVaultsFetcher(params.connection, env.exponentVaultsProgramId ?? exponent_vaults_idl_1.PROGRAM_ID);
258
350
  const state = await fetcher.fetchVaultDeserialized(params.address);
259
351
  const vault = new ExponentVault({
260
352
  state,
@@ -263,12 +355,15 @@ class ExponentVault {
263
355
  connection: params.connection,
264
356
  programId: fetcher.programId,
265
357
  });
266
- await vault.populateClmmTicksCache(params.connection);
358
+ await Promise.all([
359
+ vault.populateClmmTicksCache(params.connection),
360
+ vault.populateKaminoFarmAuxAccountsCache(params.connection),
361
+ ]);
267
362
  return vault;
268
363
  }
269
364
  static async loadAll(params) {
270
365
  const env = params.env ?? environment_1.LOCAL_ENV;
271
- const fetcher = new exponent_vaults_fetcher_1.ExponentVaultsFetcher(params.connection, env.exponentVaultsProgramId ?? exponent_vaults_idl_1.PROGRAM_ID);
366
+ const fetcher = new fetcher_1.ExponentVaultsFetcher(params.connection, env.exponentVaultsProgramId ?? exponent_vaults_idl_1.PROGRAM_ID);
272
367
  const vaults = await fetcher.fetchAllVaultsDeserialized();
273
368
  const results = vaults.map(({ publicKey, account }) => new ExponentVault({
274
369
  state: account,
@@ -277,13 +372,18 @@ class ExponentVault {
277
372
  connection: params.connection,
278
373
  programId: fetcher.programId,
279
374
  }));
280
- await Promise.all(results.map((v) => v.populateClmmTicksCache(params.connection)));
375
+ await Promise.all(results.flatMap((vault) => [
376
+ vault.populateClmmTicksCache(params.connection),
377
+ vault.populateKaminoFarmAuxAccountsCache(params.connection),
378
+ ]));
281
379
  return results;
282
380
  }
283
381
  async reload(connection = this.connection) {
284
382
  const refreshed = await ExponentVault.load({ env: this.env, connection, address: this.selfAddress });
285
383
  this.state = refreshed.state;
286
384
  this.clmmTicksMap = refreshed.clmmTicksMap;
385
+ this.kaminoFarmAuxAccountsMap = refreshed.kaminoFarmAuxAccountsMap;
386
+ this.kaminoObligationFarmUserStates = refreshed.kaminoObligationFarmUserStates;
287
387
  this.connection = connection;
288
388
  this.aumCalculator = new aumCalculator_1.AumCalculator(this.state, this.connection, this.env);
289
389
  return refreshed;
@@ -309,6 +409,90 @@ class ExponentVault {
309
409
  }
310
410
  }
311
411
  }
412
+ async populateKaminoFarmAuxAccountsCache(connection) {
413
+ this.kaminoFarmAuxAccountsMap.clear();
414
+ this.kaminoObligationFarmUserStates.clear();
415
+ const farmStates = [];
416
+ const delegatedFarmUsers = [];
417
+ for (const pos of this.state.strategyPositions) {
418
+ if ("kaminoFarm" in pos && pos.kaminoFarm && typeof pos.kaminoFarm === "object") {
419
+ const entry = pos.kaminoFarm[0];
420
+ if (!farmStates.some((farmState) => farmState.equals(entry.farmState))) {
421
+ farmStates.push(entry.farmState);
422
+ }
423
+ continue;
424
+ }
425
+ if (!("obligation" in pos) || !pos.obligation || typeof pos.obligation !== "object") {
426
+ continue;
427
+ }
428
+ const rawObligation = pos["obligation"];
429
+ const inner = Array.isArray(rawObligation)
430
+ ? rawObligation[0]
431
+ : rawObligation && typeof rawObligation === "object" && "0" in rawObligation
432
+ ? rawObligation[0]
433
+ : rawObligation;
434
+ const kaminoVariant = inner && "kaminoObligation" in inner ? inner.kaminoObligation : inner;
435
+ const entry = Array.isArray(kaminoVariant)
436
+ ? kaminoVariant[0]
437
+ : kaminoVariant && typeof kaminoVariant === "object" && "0" in kaminoVariant
438
+ ? (kaminoVariant[0] ?? undefined)
439
+ : kaminoVariant;
440
+ if (!(entry?.obligation instanceof web3_js_1.PublicKey)) {
441
+ continue;
442
+ }
443
+ for (const mapping of entry.reserveFarmMappings ?? []) {
444
+ if (!farmStates.some((farmState) => farmState.equals(mapping.farmState))) {
445
+ farmStates.push(mapping.farmState);
446
+ }
447
+ delegatedFarmUsers.push({
448
+ obligation: entry.obligation,
449
+ farmState: mapping.farmState,
450
+ userState: (0, constants_1.getKaminoFarmsObligationFarm)(entry.obligation, mapping.farmState, KAMINO_FARMS_PROGRAM_ID),
451
+ });
452
+ }
453
+ }
454
+ if (farmStates.length === 0) {
455
+ return;
456
+ }
457
+ const farmInfos = await connection.getMultipleAccountsInfo(farmStates);
458
+ for (const [index, farmInfo] of farmInfos.entries()) {
459
+ const farmState = farmStates[index];
460
+ if (!farmState || !farmInfo?.data) {
461
+ if (ExponentVault.debugAum && farmState) {
462
+ console.log("[VAULT_AUM] kaminoFarmAux: missing farm info", farmState.toBase58());
463
+ }
464
+ continue;
465
+ }
466
+ const farm = (0, kamino_farms_1.decodeKaminoFarmState)(Buffer.from(farmInfo.data));
467
+ const auxAccounts = [{ pubkey: farm.globalConfig, isSigner: false, isWritable: false }];
468
+ const scopePrices = (0, kamino_farms_1.getKaminoFarmScopePricesAddress)(farm);
469
+ if (scopePrices) {
470
+ auxAccounts.push({ pubkey: scopePrices, isSigner: false, isWritable: false });
471
+ }
472
+ this.kaminoFarmAuxAccountsMap.set(farmState.toBase58(), auxAccounts);
473
+ if (ExponentVault.debugAum) {
474
+ console.log("[VAULT_AUM] kaminoFarmAux:", farmState.toBase58(), auxAccounts.map((account) => account.pubkey.toBase58()).join(", "));
475
+ }
476
+ }
477
+ if (delegatedFarmUsers.length === 0) {
478
+ return;
479
+ }
480
+ const uniqueUsers = Array.from(new Map(delegatedFarmUsers.map((entry) => [
481
+ `${entry.obligation.toBase58()}:${entry.farmState.toBase58()}`,
482
+ entry,
483
+ ])).values());
484
+ const userInfos = await connection.getMultipleAccountsInfo(uniqueUsers.map((entry) => entry.userState));
485
+ for (const [index, userInfo] of userInfos.entries()) {
486
+ if (!userInfo?.data) {
487
+ continue;
488
+ }
489
+ const entry = uniqueUsers[index];
490
+ if (!entry) {
491
+ continue;
492
+ }
493
+ this.kaminoObligationFarmUserStates.add(`${entry.obligation.toBase58()}:${entry.farmState.toBase58()}`);
494
+ }
495
+ }
312
496
  /**
313
497
  * Derive the PDA for a vault using its 8-byte seed identifier.
314
498
  */
@@ -386,7 +570,12 @@ class ExponentVault {
386
570
  }
387
571
  }
388
572
  else if ("obligation" in pos && pos.obligation && typeof pos.obligation === "object") {
389
- const inner = pos["obligation"][0];
573
+ const rawObligation = pos["obligation"];
574
+ const inner = Array.isArray(rawObligation)
575
+ ? rawObligation[0]
576
+ : rawObligation && typeof rawObligation === "object" && "0" in rawObligation
577
+ ? rawObligation[0]
578
+ : rawObligation;
390
579
  const kaminoVariant = inner && "kaminoObligation" in inner ? inner.kaminoObligation : inner;
391
580
  const entry = Array.isArray(kaminoVariant)
392
581
  ? kaminoVariant[0]
@@ -406,11 +595,30 @@ class ExponentVault {
406
595
  isWritable: false,
407
596
  });
408
597
  }
598
+ for (const mapping of entry.reserveFarmMappings ?? []) {
599
+ metas.push({
600
+ pubkey: mapping.farmState,
601
+ isSigner: false,
602
+ isWritable: false,
603
+ });
604
+ const obligationFarmUserKey = `${entry.obligation.toBase58()}:${mapping.farmState.toBase58()}`;
605
+ if (this.kaminoObligationFarmUserStates.has(obligationFarmUserKey)) {
606
+ metas.push({
607
+ pubkey: (0, constants_1.getKaminoFarmsObligationFarm)(entry.obligation, mapping.farmState, KAMINO_FARMS_PROGRAM_ID),
608
+ isSigner: false,
609
+ isWritable: false,
610
+ });
611
+ }
612
+ metas.push(...(this.kaminoFarmAuxAccountsMap.get(mapping.farmState.toBase58()) ?? []));
613
+ }
409
614
  if (ExponentVault.debugAum) {
410
615
  console.log("[VAULT_AUM] strategyPosition: Obligation", entry.obligation.toBase58());
411
616
  for (const mapping of entry.reservePriceMappings ?? []) {
412
617
  console.log("[VAULT_AUM] strategyPosition: Kamino reserve", mapping.reserve.toBase58());
413
618
  }
619
+ for (const mapping of entry.reserveFarmMappings ?? []) {
620
+ console.log("[VAULT_AUM] strategyPosition: Kamino delegated farm", mapping.farmState.toBase58());
621
+ }
414
622
  }
415
623
  }
416
624
  }
@@ -454,6 +662,25 @@ class ExponentVault {
454
662
  console.log("[VAULT_AUM] strategyPosition: ClmmPosition", entry.lpPosition.toBase58(), entry.market.toBase58(), ticksKey ? ticksKey.toBase58() : "(ticks not cached)");
455
663
  }
456
664
  }
665
+ else if ("kaminoFarm" in pos && pos.kaminoFarm && typeof pos.kaminoFarm === "object") {
666
+ const entry = pos.kaminoFarm[0];
667
+ metas.push({
668
+ pubkey: entry.farmState,
669
+ isSigner: false,
670
+ isWritable: false,
671
+ });
672
+ metas.push({
673
+ pubkey: entry.userState,
674
+ isSigner: false,
675
+ isWritable: false,
676
+ });
677
+ const auxAccounts = this.kaminoFarmAuxAccountsMap.get(entry.farmState.toBase58()) ?? [];
678
+ metas.push(...auxAccounts);
679
+ if (ExponentVault.debugAum) {
680
+ console.log("[VAULT_AUM] strategyPosition: KaminoFarm", entry.farmState.toBase58(), entry.userState.toBase58());
681
+ console.log("[VAULT_AUM] strategyPosition: KaminoFarm aux", auxAccounts.map((account) => account.pubkey.toBase58()).join(", ") || "(none)");
682
+ }
683
+ }
457
684
  else if ("loopscaleStrategy" in pos && pos.loopscaleStrategy && typeof pos.loopscaleStrategy === "object") {
458
685
  const entry = pos.loopscaleStrategy[0];
459
686
  if (entry?.strategy instanceof web3_js_1.PublicKey) {
@@ -502,6 +729,38 @@ class ExponentVault {
502
729
  aumRemainingAccounts() {
503
730
  return [...this.tokenEntryAccountMetas(), ...this.strategyPositionAccountMetas()];
504
731
  }
732
+ /**
733
+ * Returns the readonly account metas required to recalculate the vault's current tracked AUM.
734
+ * Extra metas can be appended for pending positions or newly introduced Kamino reserves.
735
+ */
736
+ getAumRemainingAccountMetas(extraRemainingAccounts = []) {
737
+ return (0, utils_1.uniqueRemainingAccounts)([...this.aumRemainingAccounts(), ...extraRemainingAccounts]);
738
+ }
739
+ ixManagePriceUpdates({ manager, updates, }) {
740
+ if (updates.length === 0) {
741
+ throw new Error("ixManagePriceUpdates requires at least one update");
742
+ }
743
+ const resolvedManager = manager ?? this.state.roles.manager[0];
744
+ if (!resolvedManager) {
745
+ throw new Error("Vault manager not found");
746
+ }
747
+ const [exponentPrices] = this.pda.exponentPrices();
748
+ const remainingAccounts = [];
749
+ const actions = updates.map((update) => {
750
+ if (!update.priceInterfaceAccounts) {
751
+ throw new Error(`priceInterfaceAccounts required for priceId ${update.priceId}`);
752
+ }
753
+ remainingAccounts.push({ pubkey: update.priceInterfaceAccounts, isSigner: false, isWritable: false });
754
+ return {
755
+ __kind: "UpdatePrice",
756
+ priceId: BigInt(update.priceId),
757
+ priceType: update.priceType,
758
+ };
759
+ });
760
+ const ix = exponentVaults.createManagePricesInstruction({ manager: resolvedManager, exponentPrices, systemProgram: web3_js_1.SystemProgram.programId }, { actions }, this.programId);
761
+ ix.keys.push(...remainingAccounts);
762
+ return ix;
763
+ }
505
764
  ixUpdatePrice({ priceInterfaceAccounts, pythPriceFeedId, remainingAccounts = [], priceId, }) {
506
765
  const [exponentPrices] = this.pda.exponentPrices();
507
766
  if (!priceInterfaceAccounts) {
@@ -512,8 +771,11 @@ class ExponentVault {
512
771
  ...remainingAccounts.map((pubkey) => ({ pubkey, isSigner: false, isWritable: false })),
513
772
  ...(pythPriceFeedId ? [{ pubkey: pythPriceFeedId, isSigner: false, isWritable: false }] : []),
514
773
  ];
515
- const ix = exponentVaults.createUpdatePriceInstruction({ exponentPrices }, { updates: [{ priceId: BigInt(priceId), interfaceAccountsIndex: 0 }] });
774
+ const ix = exponentVaults.createUpdatePriceInstruction({ exponentPrices }, { updates: [{ priceId: BigInt(priceId), interfaceAccountsIndex: 0 }] }, this.programId);
516
775
  ix.keys.push(...updateRemainingAccounts);
776
+ if (isLocalRpcEndpoint(this.connection.rpcEndpoint)) {
777
+ ix.data = Buffer.concat([LOCAL_UPDATE_PRICE_DISCRIMINATOR, ix.data.subarray(1)]);
778
+ }
517
779
  return ix;
518
780
  }
519
781
  async ixsDepositLiquidity({ depositor, mint, tokenAmountIn, minLpOut, tokenSrc, entryTokenVault, tokenLpDst, tokenProgram = spl_token_1.TOKEN_PROGRAM_ID, extraRemainingAccounts = [], useLegacyTokenAccounts = false, }) {
@@ -522,6 +784,7 @@ class ExponentVault {
522
784
  const vault = entryTokenVault ?? entry.tokenSquadsAccount;
523
785
  const lpDst = tokenLpDst ?? defaultTokenAccount(this.state.mintLp, depositor, tokenProgram);
524
786
  const exponentPrices = this.pda.exponentPrices()[0];
787
+ const tokenProgramLp = useLegacyTokenAccounts ? spl_token_1.TOKEN_2022_PROGRAM_ID : spl_token_1.TOKEN_PROGRAM_ID;
525
788
  const preIxs = [];
526
789
  // If depositing WSOL, wrap native SOL as needed
527
790
  if (mint.equals(spl_token_1.NATIVE_MINT)) {
@@ -562,7 +825,7 @@ class ExponentVault {
562
825
  tokenLpDst: lpDst,
563
826
  mintLp: this.state.mintLp,
564
827
  tokenProgram,
565
- tokenProgramLp: spl_token_1.TOKEN_PROGRAM_ID,
828
+ tokenProgramLp,
566
829
  eventAuthority: this.eventAuthority,
567
830
  program: this.programId,
568
831
  }, { tokenAmountIn: toBigInt(tokenAmountIn), minLpOut: toBigInt(minLpOut) });
@@ -756,6 +1019,44 @@ class ExponentVault {
756
1019
  ix.keys.push(...remainingAccounts);
757
1020
  return ix;
758
1021
  }
1022
+ /**
1023
+ * Convenience wrapper for adding a tracked Kamino obligation position.
1024
+ */
1025
+ ixWrapperAddKaminoObligationPosition({ manager, obligation, lendingProgramId, quotePriceId, reservePriceMappings, reserveFarmMappings = [], minPriceStatusFlags, remainingAccounts = [], exponentPrices = this.pda.exponentPrices()[0], systemProgram = web3_js_1.SystemProgram.programId, }) {
1026
+ const obligationEntry = {
1027
+ obligation,
1028
+ lendingProgramId,
1029
+ quotePriceId,
1030
+ reservePriceMappings,
1031
+ reserveFarmMappings,
1032
+ minPriceStatusFlags,
1033
+ };
1034
+ return this.ixWrapperManagerUpdatePosition({
1035
+ manager,
1036
+ exponentPrices,
1037
+ systemProgram,
1038
+ remainingAccounts: this.getAumRemainingAccountMetas(remainingAccounts),
1039
+ update: exponentVaults.positionUpdate("AddKaminoObligationEntry", [
1040
+ obligationEntry,
1041
+ ]),
1042
+ });
1043
+ }
1044
+ /**
1045
+ * Convenience wrapper for updating tracked reserve price mappings on a Kamino obligation.
1046
+ */
1047
+ ixWrapperUpsertKaminoObligationReservePriceMappings({ manager, obligation, reservePriceMappings, reserveFarmMappings = [], remainingAccounts = [], exponentPrices = this.pda.exponentPrices()[0], systemProgram = web3_js_1.SystemProgram.programId, }) {
1048
+ return this.ixWrapperManagerUpdatePosition({
1049
+ manager,
1050
+ exponentPrices,
1051
+ systemProgram,
1052
+ remainingAccounts: this.getAumRemainingAccountMetas(remainingAccounts),
1053
+ update: exponentVaults.positionUpdate("UpsertKaminoObligationReservePriceMappings", {
1054
+ obligation,
1055
+ reservePriceMappings,
1056
+ reserveFarmMappings,
1057
+ }),
1058
+ });
1059
+ }
759
1060
  // ==========================================================================
760
1061
  // Policy Management Methods
761
1062
  // ==========================================================================
@@ -1211,8 +1512,7 @@ class ExponentVault {
1211
1512
  if (!postVaultAccountData) {
1212
1513
  throw new Error("Jito bundle simulation failed");
1213
1514
  }
1214
- const decoded = this.fetcher.program.account.exponentStrategyVault.coder.accounts.decode("exponentStrategyVault", Buffer.from(postVaultAccountData, "base64"));
1215
- const vaultStateAfterSimulations = (0, exponent_vaults_fetcher_1.transformAnchorData)(decoded);
1515
+ const vaultStateAfterSimulations = (0, fetcher_1.deserializeExponentStrategyVaultFetcherShape)(Buffer.from(postVaultAccountData, "base64"));
1216
1516
  const aum = vaultStateAfterSimulations.financials.aumInBase + vaultStateAfterSimulations.financials.aumInBaseInPositions;
1217
1517
  return aum;
1218
1518
  }
@@ -1221,51 +1521,27 @@ class ExponentVault {
1221
1521
  return this.getTotalAum();
1222
1522
  }
1223
1523
  }
1224
- async ixsUpdateStrategyVaultPrices(pricesAccount) {
1225
- const extractPriceIds = (priceId) => {
1226
- const ids = "simple" in priceId ? [Number(priceId.simple.priceId)] : priceId.multiply.priceIds.map(Number);
1227
- return ids.filter((id) => id !== 0); // skip passthrough (price_id 0)
1228
- };
1229
- const allPriceIds = new Set();
1230
- for (const entry of this.state.tokenEntries) {
1231
- extractPriceIds(entry.priceId).forEach((id) => allPriceIds.add(id));
1232
- }
1233
- for (const position of this.state.strategyPositions) {
1234
- if ("orderbook" in position) {
1235
- const orderbook = position.orderbook[0];
1236
- extractPriceIds(orderbook.priceIdPt).forEach((id) => allPriceIds.add(id));
1237
- continue;
1238
- }
1239
- if ("tokenAccount" in position) {
1240
- for (const balance of position.tokenAccount[0].balances) {
1241
- extractPriceIds(balance.priceId).forEach((id) => allPriceIds.add(id));
1242
- }
1243
- continue;
1244
- }
1245
- if ("obligation" in position) {
1246
- const inner = position.obligation[0];
1247
- const kaminoEntry = inner && typeof inner === "object" && "kaminoObligation" in inner ? inner.kaminoObligation?.[0] : inner?.[0];
1248
- if (kaminoEntry?.quotePriceId) {
1249
- extractPriceIds(kaminoEntry.quotePriceId).forEach((id) => allPriceIds.add(id));
1250
- }
1251
- for (const mapping of kaminoEntry?.reservePriceMappings ?? []) {
1252
- if (mapping.reservePriceId) {
1253
- extractPriceIds(mapping.reservePriceId).forEach((id) => allPriceIds.add(id));
1254
- }
1255
- }
1256
- }
1524
+ async ixsUpdateStrategyVaultPrices(pricesAccount, options = {}) {
1525
+ const trackedPriceIds = options.priceIds ??
1526
+ collectTrackedStrategyVaultPriceIds({
1527
+ tokenEntries: this.state.tokenEntries,
1528
+ strategyPositions: this.state.strategyPositions,
1529
+ });
1530
+ const priceIds = [...trackedPriceIds].sort((a, b) => a - b);
1531
+ if (priceIds.length === 0) {
1532
+ return [];
1257
1533
  }
1258
- return Promise.all([...allPriceIds].map((priceId) => {
1534
+ return priceIds.map((priceId) => {
1259
1535
  const priceEntry = pricesAccount.prices[priceId];
1260
1536
  if (!priceEntry) {
1261
1537
  throw new Error(`Price entry not found for priceId ${priceId}`);
1262
1538
  }
1263
1539
  return this.ixUpdatePrice({
1540
+ priceId,
1264
1541
  priceInterfaceAccounts: priceEntry.priceInterfaceAccounts,
1265
1542
  remainingAccounts: priceEntry.interfaceAccounts,
1266
- priceId,
1267
1543
  });
1268
- }));
1544
+ });
1269
1545
  }
1270
1546
  // ==========================================================================
1271
1547
  // Helper Methods — Codama type conversions