@kamino-finance/klend-sdk 6.0.5-beta.5 → 6.0.5-beta.8

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 (43) hide show
  1. package/dist/classes/action.d.ts +1 -1
  2. package/dist/classes/action.d.ts.map +1 -1
  3. package/dist/classes/action.js +28 -13
  4. package/dist/classes/action.js.map +1 -1
  5. package/dist/classes/manager.d.ts +29 -18
  6. package/dist/classes/manager.d.ts.map +1 -1
  7. package/dist/classes/manager.js +65 -47
  8. package/dist/classes/manager.js.map +1 -1
  9. package/dist/classes/market.d.ts +2 -3
  10. package/dist/classes/market.d.ts.map +1 -1
  11. package/dist/classes/market.js +8 -9
  12. package/dist/classes/market.js.map +1 -1
  13. package/dist/client_kamino_manager.d.ts.map +1 -1
  14. package/dist/client_kamino_manager.js +30 -22
  15. package/dist/client_kamino_manager.js.map +1 -1
  16. package/dist/leverage/operations.d.ts +3 -2
  17. package/dist/leverage/operations.d.ts.map +1 -1
  18. package/dist/leverage/operations.js +17 -12
  19. package/dist/leverage/operations.js.map +1 -1
  20. package/dist/leverage/types.d.ts +1 -0
  21. package/dist/leverage/types.d.ts.map +1 -1
  22. package/dist/utils/managerTypes.d.ts +1 -2
  23. package/dist/utils/managerTypes.d.ts.map +1 -1
  24. package/dist/utils/managerTypes.js +9 -9
  25. package/dist/utils/managerTypes.js.map +1 -1
  26. package/dist/utils/oracle.d.ts +2 -2
  27. package/dist/utils/oracle.d.ts.map +1 -1
  28. package/dist/utils/oracle.js.map +1 -1
  29. package/dist/utils/pubkey.d.ts +1 -0
  30. package/dist/utils/pubkey.d.ts.map +1 -1
  31. package/dist/utils/pubkey.js +10 -0
  32. package/dist/utils/pubkey.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/classes/action.ts +28 -12
  35. package/src/classes/manager.ts +80 -51
  36. package/src/classes/market.ts +14 -19
  37. package/src/client.ts +4 -4
  38. package/src/client_kamino_manager.ts +40 -35
  39. package/src/leverage/operations.ts +21 -14
  40. package/src/leverage/types.ts +1 -0
  41. package/src/utils/managerTypes.ts +1 -2
  42. package/src/utils/oracle.ts +2 -2
  43. package/src/utils/pubkey.ts +9 -0
@@ -75,7 +75,7 @@ import { KaminoReserve } from './reserve';
75
75
  import { ReserveFarmKind } from '../idl_codegen/types';
76
76
  import { farmsId } from '@kamino-finance/farms-sdk';
77
77
  import { Reserve } from '../idl_codegen/accounts';
78
- import { VanillaObligation } from '../utils/ObligationType';
78
+ import { VanillaObligation } from '../utils';
79
79
  import { PROGRAM_ID } from '../lib';
80
80
  import { Scope } from '@kamino-finance/scope-sdk';
81
81
  import { ObligationOrderAtIndex } from './obligationOrder';
@@ -430,12 +430,12 @@ export class KaminoAction {
430
430
  return axn;
431
431
  }
432
432
 
433
- async addScopeRefreshIxs(scope: Scope, tokens: number[], feed: string = 'hubble') {
433
+ async addScopeRefreshIxs(scope: Scope, tokens: number[], scopeConfig: PublicKey) {
434
434
  this.setupIxsLabels.unshift(`refreshScopePrices`);
435
435
  this.setupIxs.unshift(
436
436
  await scope.refreshPriceListIx(
437
437
  {
438
- feed: feed,
438
+ config: scopeConfig,
439
439
  },
440
440
  tokens
441
441
  )
@@ -732,10 +732,16 @@ export class KaminoAction {
732
732
  ...(axn.outflowReserve ? [axn.outflowReserve.address] : []),
733
733
  ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
734
734
  ]).toArray();
735
- const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
736
735
 
737
- if (tokenIds.length > 0 && scopeRefreshConfig) {
738
- await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
736
+ const scopeTokensMap = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
737
+
738
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
739
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
740
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
741
+ if (tokenIds && tokenIds.length > 0) {
742
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
743
+ }
744
+ }
739
745
  }
740
746
  return axn;
741
747
  }
@@ -922,10 +928,15 @@ export class KaminoAction {
922
928
  ...(axn.outflowReserve ? [axn.outflowReserve.address] : []),
923
929
  ...(axn.preLoadedDepositReservesSameTx ? axn.preLoadedDepositReservesSameTx : []),
924
930
  ]).toArray();
925
- const tokenIds = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
931
+ const scopeTokensMap = getTokenIdsForScopeRefresh(axn.kaminoMarket, allReserves);
926
932
 
927
- if (tokenIds.length > 0 && scopeRefreshConfig) {
928
- await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
933
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
934
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
935
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
936
+ if (tokenIds && tokenIds.length > 0) {
937
+ await axn.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
938
+ }
939
+ }
929
940
  }
930
941
  return axn;
931
942
  }
@@ -2748,10 +2759,15 @@ export class KaminoAction {
2748
2759
  ...(this.outflowReserve ? [this.outflowReserve.address] : []),
2749
2760
  ...(this.preLoadedDepositReservesSameTx ? this.preLoadedDepositReservesSameTx : []),
2750
2761
  ]).toArray();
2751
- const tokenIds = getTokenIdsForScopeRefresh(this.kaminoMarket, allReserves);
2762
+ const scopeTokensMap = getTokenIdsForScopeRefresh(this.kaminoMarket, allReserves);
2752
2763
 
2753
- if (tokenIds.length > 0 && scopeRefreshConfig) {
2754
- await this.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, scopeRefreshConfig.scopeFeed);
2764
+ if (scopeTokensMap.size > 0 && scopeRefreshConfig) {
2765
+ for (const [configPubkey, config] of scopeRefreshConfig.scopeConfigurations) {
2766
+ const tokenIds = scopeTokensMap.get(config.oraclePrices);
2767
+ if (tokenIds && tokenIds.length > 0) {
2768
+ await this.addScopeRefreshIxs(scopeRefreshConfig.scope, tokenIds, configPubkey);
2769
+ }
2770
+ }
2755
2771
  }
2756
2772
  }
2757
2773
 
@@ -52,6 +52,7 @@ import {
52
52
  Reserve,
53
53
  ReserveWithAddress,
54
54
  ScopeOracleConfig,
55
+ setOrAppend,
55
56
  updateEntireReserveConfigIx,
56
57
  updateLendingMarket,
57
58
  UpdateLendingMarketAccounts,
@@ -60,7 +61,7 @@ import {
60
61
  UpdateLendingMarketOwnerAccounts,
61
62
  } from '../lib';
62
63
  import { PROGRAM_ID } from '../idl_codegen/programId';
63
- import { Scope, TokenMetadatas, U16_MAX } from '@kamino-finance/scope-sdk';
64
+ import { OracleMappings, Scope, TokenMetadatas, U16_MAX } from '@kamino-finance/scope-sdk';
64
65
  import BN from 'bn.js';
65
66
  import { ReserveConfig, UpdateLendingMarketMode, UpdateLendingMarketModeKind } from '../idl_codegen/types';
66
67
  import Decimal from 'decimal.js';
@@ -69,7 +70,7 @@ import { VaultState } from '../idl_codegen_kamino_vault/accounts';
69
70
  import { TOKEN_PROGRAM_ID } from '@solana/spl-token';
70
71
  import { Data } from '@kamino-finance/kliquidity-sdk';
71
72
  import bs58 from 'bs58';
72
- import { getProgramAccounts } from '../utils/rpc';
73
+ import { getProgramAccounts } from '../utils';
73
74
  import { VaultConfigField, VaultConfigFieldKind } from '../idl_codegen_kamino_vault/types';
74
75
  import {
75
76
  AcceptVaultOwnershipIxs,
@@ -317,6 +318,7 @@ export class KaminoManager {
317
318
  * This function enables the update of the scope oracle configuration. In order to get a list of scope prices, getScopeOracleConfigs can be used
318
319
  * @param market - lending market which owns the reserve
319
320
  * @param reserve - reserve which to be updated
321
+ * @param oraclePrices - scope OraclePrices account pubkey
320
322
  * @param scopeOracleConfig - new scope oracle config
321
323
  * @param scopeTwapConfig - new scope twap config
322
324
  * @param maxAgeBufferSeconds - buffer to be added to onchain max_age - if oracle price is older than that, txns interacting with the reserve will fail
@@ -325,6 +327,7 @@ export class KaminoManager {
325
327
  async updateReserveScopeOracleConfigurationIxs(
326
328
  market: MarketWithAddress,
327
329
  reserve: ReserveWithAddress,
330
+ oraclePrices: PublicKey,
328
331
  scopeOracleConfig: ScopeOracleConfig,
329
332
  scopeTwapConfig?: ScopeOracleConfig,
330
333
  maxAgeBufferSeconds: number = 20
@@ -341,7 +344,7 @@ export class KaminoManager {
341
344
  }
342
345
 
343
346
  const { scopeConfiguration } = getReserveOracleConfigs({
344
- scopePriceConfigAddress: scopeOracleConfig.scopePriceConfigAddress,
347
+ scopePriceConfigAddress: oraclePrices,
345
348
  scopeChain: [scopeOracleConfig.oracleId],
346
349
  scopeTwapChain: [scopeTwapId],
347
350
  });
@@ -523,7 +526,6 @@ export class KaminoManager {
523
526
  * This method withdraws all the pending fees from the vault to the owner's token ATA
524
527
  * @param vault - vault for which the admin withdraws the pending fees
525
528
  * @param slot - current slot, used to estimate the interest earned in the different reserves with allocation from the vault
526
- * @param [vaultReservesMap] - a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
527
529
  * @returns - list of instructions to withdraw all pending fees, including the ATA creation instructions if needed
528
530
  */
529
531
  async withdrawPendingFeesIxs(vault: KaminoVault, slot: number): Promise<TransactionInstruction[]> {
@@ -533,7 +535,7 @@ export class KaminoManager {
533
535
  /**
534
536
  * This method inserts the missing keys from the provided keys into an existent lookup table
535
537
  * @param payer - payer wallet pubkey
536
- * @param lookupTable - lookup table to insert the keys into
538
+ * @param lut
537
539
  * @param keys - keys to insert into the lookup table
538
540
  * @param [accountsInLUT] - the existent accounts in the lookup table. Optional. If provided, the function will not fetch the accounts in the lookup table
539
541
  * @returns - an array of instructions to insert the missing keys into the lookup table
@@ -551,7 +553,6 @@ export class KaminoManager {
551
553
  * Sync a vault for lookup table; create and set the LUT for the vault if needed and fill it with all the needed accounts
552
554
  * @param vault the vault to sync and set the LUT for if needed
553
555
  * @param vaultReserves optional; the state of the reserves in the vault allocation
554
- * @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
555
556
  * @returns a struct that contains a list of ix to create the LUT and assign it to the vault if needed + a list of ixs to insert all the accounts in the LUT
556
557
  */
557
558
  async syncVaultLUTIxs(
@@ -632,8 +633,8 @@ export class KaminoManager {
632
633
 
633
634
  /**
634
635
  * This method returns the vault name
635
- * @param vault - vault to retrieve the onchain name for
636
636
  * @returns - the vault name as string
637
+ * @param vaultState
637
638
  */
638
639
  getDecodedVaultName(vaultState: VaultState): string {
639
640
  return this._vaultClient.decodeVaultName(vaultState.name);
@@ -691,7 +692,7 @@ export class KaminoManager {
691
692
  }
692
693
  }
693
694
 
694
- const combinedMarkets = lendingMarketPairs.map(([pubkey, market]) => {
695
+ return lendingMarketPairs.map(([pubkey, market]) => {
695
696
  const reserves = marketToReserve.get(pubkey);
696
697
  const reservesByAddress = new PubkeyHashMap<PublicKey, KaminoReserve>();
697
698
  if (!reserves) {
@@ -720,8 +721,6 @@ export class KaminoManager {
720
721
 
721
722
  return KaminoMarket.loadWithReserves(this.getConnection(), market, reservesByAddress, pubkey, slotDuration);
722
723
  });
723
-
724
- return combinedMarkets;
725
724
  }
726
725
 
727
726
  /**
@@ -859,7 +858,7 @@ export class KaminoManager {
859
858
  * @param vault - the kamino vault to get available liquidity to withdraw for
860
859
  * @param price - the price of the token in the vault (e.g. USDC)
861
860
  * @param [slot] - the slot for which to calculate the holdings. Optional. If not provided the function will fetch the current slot
862
- * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
861
+ * @param vaultReserves
863
862
  * @param [currentSlot] - the latest confirmed slot. Optional. If provided the function will be faster as it will not have to fetch the latest slot
864
863
  * @returns an VaultHoldingsWithUSDValue object with details about the tokens available and invested in the vault, denominated in tokens and USD
865
864
  */
@@ -878,7 +877,7 @@ export class KaminoManager {
878
877
  * @param vault - the kamino vault to get available liquidity to withdraw for
879
878
  * @param price - the price of the token in the vault (e.g. USDC)
880
879
  * @param [slot] - the slot for which to retrieve the vault overview for. Optional. If not provided the function will fetch the current slot
881
- * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
880
+ * @param vaultReserves
882
881
  * @param [kaminoMarkets] - a list of all kamino markets. Optional. If provided the function will be significantly faster as it will not have to fetch the markets
883
882
  * @param [currentSlot] - the latest confirmed slot. Optional. If provided the function will be faster as it will not have to fetch the latest slot
884
883
  * @returns an VaultOverview object with details about the tokens available and invested in the vault, denominated in tokens and USD
@@ -938,7 +937,7 @@ export class KaminoManager {
938
937
  * This will return the APY of the vault under the assumption that all the available tokens in the vault are all the time invested in the reserves as ratio; for percentage it needs multiplication by 100
939
938
  * @param vault - the kamino vault to get APY for
940
939
  * @param slot - current slot
941
- * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
940
+ * @param vaultReserves
942
941
  * @returns a struct containing estimated gross APY and net APY (gross - vault fees) for the vault
943
942
  */
944
943
  async getVaultTheoreticalAPY(
@@ -953,7 +952,7 @@ export class KaminoManager {
953
952
  * This will return the APY of the vault based on the current invested amounts; for percentage it needs multiplication by 100
954
953
  * @param vault - the kamino vault to get APY for
955
954
  * @param slot - current slot
956
- * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
955
+ * @param vaultReserves
957
956
  * @returns a struct containing estimated gross APY and net APY (gross - vault fees) for the vault
958
957
  */
959
958
  async getVaultActualAPY(
@@ -976,8 +975,10 @@ export class KaminoManager {
976
975
  /**
977
976
  * Simulate the current holdings of the vault and the earned interest
978
977
  * @param vaultState the kamino vault state to get simulated holdings and earnings for
979
- * @param [vaultReservesMap] - hashmap from each reserve pubkey to the reserve state. Optional. If provided the function will be significantly faster as it will not have to fetch the reserves
980
- * @param [currentSlot] - the current slot. Optional. If not provided it will fetch the current slot
978
+ * @param vaultReserves
979
+ * @param vaultReserves
980
+ * @param slot
981
+ * @param slot
981
982
  * @param [previousTotalAUM] - the previous AUM of the vault to compute the earned interest relative to this value. Optional. If not provided the function will estimate the total AUM at the slot of the last state update on chain
982
983
  * @param [currentSlot] - the latest confirmed slot. Optional. If provided the function will be faster as it will not have to fetch the latest slot
983
984
  * @returns a struct of simulated vault holdings and earned interest
@@ -1056,8 +1057,8 @@ export class KaminoManager {
1056
1057
 
1057
1058
  /**
1058
1059
  * This will load the onchain state for all the reserves that the vault has allocations for
1059
- * @param vaultState - the vault state to load reserves for
1060
1060
  * @returns a hashmap from each reserve pubkey to the reserve state
1061
+ * @param vault
1061
1062
  */
1062
1063
  getVaultReserves(vault: VaultState): PublicKey[] {
1063
1064
  return this._vaultClient.getVaultReserves(vault);
@@ -1067,6 +1068,15 @@ export class KaminoManager {
1067
1068
  * This will retrieve all the tokens that can be use as collateral by the users who borrow the token in the vault alongside details about the min and max loan to value ratio
1068
1069
  * @param vaultState - the vault state to load reserves for
1069
1070
  *
1071
+ * @param slot
1072
+ * @param vaultReservesMap
1073
+ * @param kaminoMarkets
1074
+ * @param slot
1075
+ * @param vaultReservesMap
1076
+ * @param kaminoMarkets
1077
+ * @param slot
1078
+ * @param vaultReservesMap
1079
+ * @param kaminoMarkets
1070
1080
  * @returns a hashmap from each reserve pubkey to the market overview of the collaterals that can be used and the min and max loan to value ratio in that market
1071
1081
  */
1072
1082
  async getVaultCollaterals(
@@ -1080,6 +1090,7 @@ export class KaminoManager {
1080
1090
 
1081
1091
  /**
1082
1092
  * This will trigger invest by balancing, based on weights, the reserve allocations of the vault. It can either withdraw or deposit into reserves to balance them. This is a function that should be cranked
1093
+ * @param payer
1083
1094
  * @param kaminoVault - vault to invest from
1084
1095
  * @returns - an array of invest instructions for each invest action required for the vault reserves
1085
1096
  */
@@ -1090,8 +1101,8 @@ export class KaminoManager {
1090
1101
  /**
1091
1102
  * This will trigger invest by balancing, based on weights, the reserve allocation of the vault. It can either withdraw or deposit into the given reserve to balance it
1092
1103
  * @param payer wallet pubkey
1093
- * @param vault - vault to invest from
1094
- * @param reserve - reserve to invest into or disinvest from
1104
+ * @param kaminoVault
1105
+ * @param reserveWithAddress
1095
1106
  * @param [vaultReservesMap] - optional parameter; a hashmap from each reserve pubkey to the reserve state. If provided the function will be significantly faster as it will not have to fetch the reserves
1096
1107
  * @returns - an array of invest instructions for each invest action required for the vault reserves
1097
1108
  */
@@ -1124,7 +1135,7 @@ export class KaminoManager {
1124
1135
 
1125
1136
  /**
1126
1137
  * This will return the amount of token invested from the vault into the given reserve
1127
- * @param vault - the kamino vault to get invested amount in reserve for
1138
+ * @param vaultState
1128
1139
  * @param slot - current slot
1129
1140
  * @param reserve - the reserve state to get vault invested amount in
1130
1141
  * @returns vault amount supplied in reserve in decimal
@@ -1135,43 +1146,63 @@ export class KaminoManager {
1135
1146
 
1136
1147
  /**
1137
1148
  * This returns an array of scope oracle configs to be used to set the scope price and twap oracles for a reserve
1138
- * @param feed - scope feed to fetch prices from
1149
+ * @param market - kamino market
1139
1150
  * @param cluster - cluster to fetch from, this should be left unchanged unless working on devnet or locally
1140
- * @returns - an array of scope oracle configs
1151
+ * @returns - a map with keys as scope OraclePrices pubkeys and values of scope oracle configs
1141
1152
  */
1142
1153
  async getScopeOracleConfigs(
1143
- feed: string = 'hubble',
1154
+ market: KaminoMarket,
1144
1155
  cluster: ENV = 'mainnet-beta'
1145
- ): Promise<Array<ScopeOracleConfig>> {
1146
- const scopeOracleConfigs: Array<ScopeOracleConfig> = [];
1156
+ ): Promise<PubkeyHashMap<PublicKey, ScopeOracleConfig[]>> {
1157
+ const scopeOracleConfigs = new PubkeyHashMap<PublicKey, ScopeOracleConfig[]>();
1147
1158
 
1148
1159
  const scope = new Scope(cluster, this._connection);
1149
- const oracleMappings = await scope.getOracleMappings({ feed: feed });
1150
- const [, feedConfig] = await scope.getFeedConfiguration({ feed: feed });
1151
- const tokenMetadatas = await TokenMetadatas.fetch(this._connection, feedConfig.tokensMetadata);
1152
- const decoder = new TextDecoder('utf-8');
1153
-
1154
- console.log('feedConfig.tokensMetadata', feedConfig.tokensMetadata);
1155
1160
 
1156
- if (tokenMetadatas === null) {
1157
- throw new Error('TokenMetadatas not found');
1161
+ const configs = (await scope.getAllConfigurations()).filter(([_, config]) =>
1162
+ market.scopeFeeds.contains(config.oraclePrices)
1163
+ );
1164
+ if (!configs || configs.length === 0) {
1165
+ return scopeOracleConfigs;
1158
1166
  }
1159
1167
 
1160
- for (let index = 0; index < oracleMappings.priceInfoAccounts.length; index++) {
1161
- if (!oracleMappings.priceInfoAccounts[index].equals(PublicKey.default)) {
1162
- const name = decoder.decode(Uint8Array.from(tokenMetadatas.metadatasArray[index].name)).replace(/\0/g, '');
1163
- const oracleType = parseOracleType(oracleMappings.priceTypes[index]);
1164
-
1165
- scopeOracleConfigs.push({
1166
- scopePriceConfigAddress: feedConfig.oraclePrices,
1167
- name: name,
1168
- oracleType: oracleType,
1169
- oracleId: index,
1170
- oracleAccount: oracleMappings.priceInfoAccounts[index],
1171
- twapEnabled: oracleMappings.twapEnabled[index] === 1,
1172
- twapSourceId: oracleMappings.twapSource[index],
1173
- max_age: tokenMetadatas.metadatasArray[index].maxAgePriceSlots.toNumber(),
1174
- });
1168
+ const configOracleMappings = await OracleMappings.fetchMultiple(
1169
+ this._connection,
1170
+ configs.map(([_, config]) => config.oracleMappings),
1171
+ scope.config.programId
1172
+ );
1173
+
1174
+ const configTokenMetadatas = await TokenMetadatas.fetchMultiple(
1175
+ this._connection,
1176
+ configs.map(([_, config]) => config.tokensMetadata),
1177
+ scope.config.programId
1178
+ );
1179
+ const decoder = new TextDecoder('utf-8');
1180
+
1181
+ for (let i = 0; i < configs.length; i++) {
1182
+ const [configPubkey, config] = configs[i];
1183
+ const oracleMappings = configOracleMappings[i];
1184
+ const tokenMetadatas = configTokenMetadatas[i];
1185
+ if (!oracleMappings) {
1186
+ throw new Error(`OracleMappings account not found for config ${configPubkey}`);
1187
+ }
1188
+ if (!tokenMetadatas) {
1189
+ throw new Error(`TokenMetadatas account not found for config ${configPubkey}`);
1190
+ }
1191
+
1192
+ for (let j = 0; j < oracleMappings.priceInfoAccounts.length; j++) {
1193
+ if (!oracleMappings.priceInfoAccounts[j].equals(PublicKey.default)) {
1194
+ const name = decoder.decode(Uint8Array.from(tokenMetadatas.metadatasArray[j].name)).replace(/\0/g, '');
1195
+ const oracleType = parseOracleType(oracleMappings.priceTypes[j]);
1196
+ setOrAppend(scopeOracleConfigs, config.oraclePrices, {
1197
+ name: name,
1198
+ oracleType: oracleType,
1199
+ oracleId: j,
1200
+ oracleAccount: oracleMappings.priceInfoAccounts[j],
1201
+ twapEnabled: oracleMappings.twapEnabled[j] === 1,
1202
+ twapSourceId: oracleMappings.twapSource[j],
1203
+ max_age: tokenMetadatas.metadatasArray[j].maxAgePriceSlots.toNumber(),
1204
+ });
1205
+ }
1175
1206
  }
1176
1207
  }
1177
1208
 
@@ -1329,7 +1360,5 @@ function updateMarketConfigIx(
1329
1360
  value: [...value, ...Array(72 - value.length).fill(0)],
1330
1361
  };
1331
1362
 
1332
- const ix = updateLendingMarket(args, accounts, programId);
1333
-
1334
- return ix;
1363
+ return updateLendingMarket(args, accounts, programId);
1335
1364
  }
@@ -22,6 +22,7 @@ import {
22
22
  CandidatePrice,
23
23
  PublicKeySet,
24
24
  DEPOSITS_LIMIT,
25
+ setOrAppend,
25
26
  } from '../utils';
26
27
  import base58 from 'bs58';
27
28
  import { BN } from '@coral-xyz/anchor';
@@ -62,7 +63,7 @@ export class KaminoMarket {
62
63
 
63
64
  private readonly recentSlotDurationMs: number;
64
65
 
65
- private readonly scopeFeeds: PublicKeySet<PublicKey>;
66
+ readonly scopeFeeds: PublicKeySet<PublicKey>;
66
67
 
67
68
  private constructor(
68
69
  connection: Connection,
@@ -93,7 +94,6 @@ export class KaminoMarket {
93
94
  * @param recentSlotDurationMs
94
95
  * @param programId
95
96
  * @param withReserves
96
- * @param setupLocalTest
97
97
  * @param withReserves
98
98
  */
99
99
  static async load(
@@ -1544,16 +1544,7 @@ export async function getSingleReserve(
1544
1544
  if (!oracle) {
1545
1545
  throw Error(`Could not find oracle for ${parseTokenSymbol(reserveState.config.tokenInfo.name)} reserve`);
1546
1546
  }
1547
- const kaminoReserve = KaminoReserve.initialize(
1548
- reserve,
1549
- reservePk,
1550
- reserveState,
1551
- oracle,
1552
- connection,
1553
- recentSlotDurationMs
1554
- );
1555
-
1556
- return kaminoReserve;
1547
+ return KaminoReserve.initialize(reserve, reservePk, reserveState, oracle, connection, recentSlotDurationMs);
1557
1548
  }
1558
1549
 
1559
1550
  export function getReservesActive(reserves: Map<PublicKey, KaminoReserve>): Map<PublicKey, KaminoReserve> {
@@ -1566,8 +1557,11 @@ export function getReservesActive(reserves: Map<PublicKey, KaminoReserve>): Map<
1566
1557
  return reservesActive;
1567
1558
  }
1568
1559
 
1569
- export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves: PublicKey[]): number[] {
1570
- const tokenIds: number[] = [];
1560
+ export function getTokenIdsForScopeRefresh(
1561
+ kaminoMarket: KaminoMarket,
1562
+ reserves: PublicKey[]
1563
+ ): PubkeyHashMap<PublicKey, number[]> {
1564
+ const tokenIds = new PubkeyHashMap<PublicKey, number[]>();
1571
1565
 
1572
1566
  for (const reserveAddress of reserves) {
1573
1567
  const reserve = kaminoMarket.getReserveByAddress(reserveAddress);
@@ -1575,17 +1569,18 @@ export function getTokenIdsForScopeRefresh(kaminoMarket: KaminoMarket, reserves:
1575
1569
  throw new Error(`Reserve not found for reserve ${reserveAddress.toBase58()}`);
1576
1570
  }
1577
1571
 
1578
- if (!reserve.state.config.tokenInfo.scopeConfiguration.priceFeed.equals(PublicKey.default)) {
1572
+ const { scopeConfiguration } = reserve.state.config.tokenInfo;
1573
+ if (!scopeConfiguration.priceFeed.equals(PublicKey.default)) {
1579
1574
  let x = 0;
1580
1575
 
1581
- while (reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x] !== U16_MAX) {
1582
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.priceChain[x]);
1576
+ while (scopeConfiguration.priceChain[x] !== U16_MAX) {
1577
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.priceChain[x]);
1583
1578
  x++;
1584
1579
  }
1585
1580
 
1586
1581
  x = 0;
1587
- while (reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x] !== U16_MAX) {
1588
- tokenIds.push(reserve.state.config.tokenInfo.scopeConfiguration.twapChain[x]);
1582
+ while (scopeConfiguration.twapChain[x] !== U16_MAX) {
1583
+ setOrAppend(tokenIds, scopeConfiguration.priceFeed, scopeConfiguration.twapChain[x]);
1589
1584
  x++;
1590
1585
  }
1591
1586
  }
package/src/client.ts CHANGED
@@ -362,7 +362,7 @@ async function deposit(connection: Connection, wallet: Keypair, token: string, d
362
362
  wallet.publicKey,
363
363
  new VanillaObligation(STAGING_LENDING_MARKET),
364
364
  true,
365
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
365
+ { scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
366
366
  );
367
367
  console.log('User obligation', kaminoAction.getObligationPda().toString());
368
368
 
@@ -384,7 +384,7 @@ async function withdraw(connection: Connection, wallet: Keypair, token: string,
384
384
  wallet.publicKey,
385
385
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
386
386
  true,
387
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
387
+ { scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
388
388
  );
389
389
  console.log('User obligation', kaminoAction.getObligationPda().toString());
390
390
 
@@ -406,7 +406,7 @@ async function borrow(connection: Connection, wallet: Keypair, token: string, bo
406
406
  wallet.publicKey,
407
407
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
408
408
  true,
409
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' }
409
+ { scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] }
410
410
  );
411
411
  console.log('User obligation', kaminoAction.getObligationPda().toString());
412
412
 
@@ -428,7 +428,7 @@ async function repay(connection: Connection, wallet: Keypair, token: string, bor
428
428
  wallet.publicKey,
429
429
  new VanillaObligation(new PublicKey(STAGING_LENDING_MARKET)),
430
430
  true,
431
- { scope: new Scope('mainnet-beta', connection), scopeFeed: 'hubble' },
431
+ { scope: new Scope('mainnet-beta', connection), scopeConfigurations: [] },
432
432
  await connection.getSlot()
433
433
  );
434
434
  console.log('User obligation', kaminoAction.getObligationPda().toString());