@glamsystems/glam-sdk 0.1.29 → 0.1.30

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.
package/index.cjs.js CHANGED
@@ -34,7 +34,7 @@ var borsh__namespace = /*#__PURE__*/_interopNamespaceDefault(borsh);
34
34
  var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
35
35
  var metadata = {
36
36
  name: "glam_protocol",
37
- version: "0.4.33",
37
+ version: "0.4.35",
38
38
  spec: "0.1.0",
39
39
  description: "Glam Protocol"
40
40
  };
@@ -6900,7 +6900,9 @@ var instructions = [
6900
6900
  docs: [
6901
6901
  "Extra accounts for pricing N vault depositors:",
6902
6902
  "- (vault_depositor, drift_vault, drift_user) x N",
6903
- "- markets and oracles used by all drift users (no specific order)"
6903
+ "- spot_market used by drift users of vaults (no specific order)",
6904
+ "- perp markets used by drift users of vaults (no specific order)",
6905
+ "- oracles of spot markets and perp markets (no specific order)"
6904
6906
  ],
6905
6907
  discriminator: [
6906
6908
  234,
@@ -7021,6 +7023,14 @@ var instructions = [
7021
7023
  {
7022
7024
  name: "num_vault_depositors",
7023
7025
  type: "u8"
7026
+ },
7027
+ {
7028
+ name: "num_spot_markets",
7029
+ type: "u8"
7030
+ },
7031
+ {
7032
+ name: "num_perp_markets",
7033
+ type: "u8"
7024
7034
  }
7025
7035
  ]
7026
7036
  },
@@ -7167,9 +7177,14 @@ var instructions = [
7167
7177
  {
7168
7178
  name: "price_kamino_vault_shares",
7169
7179
  docs: [
7180
+ "Price Kamino vault shares.",
7181
+ "- `num_vaults` Number of kamino vaults to price.",
7182
+ "",
7170
7183
  "Extra accounts for pricing N kamino vault shares:",
7171
7184
  "- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
7172
- "- (lending_market, reserve) x M, M = number of unique markets used by all kvaults involved"
7185
+ "- reserve x M",
7186
+ "- M = number of reserves used by all kvaults' allocations",
7187
+ "- reserve pubkeys must follow the same order of reserves used by each allocation"
7173
7188
  ],
7174
7189
  discriminator: [
7175
7190
  112,
@@ -7212,10 +7227,6 @@ var instructions = [
7212
7227
  writable: true,
7213
7228
  signer: true
7214
7229
  },
7215
- {
7216
- name: "kamino_lending_program",
7217
- address: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
7218
- },
7219
7230
  {
7220
7231
  name: "sol_oracle"
7221
7232
  },
@@ -7280,22 +7291,6 @@ var instructions = [
7280
7291
  ]
7281
7292
  }
7282
7293
  }
7283
- },
7284
- {
7285
- name: "pyth_oracle",
7286
- optional: true
7287
- },
7288
- {
7289
- name: "switchboard_price_oracle",
7290
- optional: true
7291
- },
7292
- {
7293
- name: "switchboard_twap_oracle",
7294
- optional: true
7295
- },
7296
- {
7297
- name: "scope_prices",
7298
- optional: true
7299
7294
  }
7300
7295
  ],
7301
7296
  args: [
@@ -9608,6 +9603,10 @@ var instructions = [
9608
9603
  {
9609
9604
  name: "stake_history",
9610
9605
  address: "SysvarStakeHistory1111111111111111111111111"
9606
+ },
9607
+ {
9608
+ name: "system_program",
9609
+ address: "11111111111111111111111111111111"
9611
9610
  }
9612
9611
  ],
9613
9612
  args: [
@@ -15604,12 +15603,12 @@ class BaseClient {
15604
15603
  const { t: lookupTables } = data;
15605
15604
  const pubkeys = Object.keys(lookupTables);
15606
15605
  if (pubkeys.length > 0) {
15607
- return await this.fetchAdressLookupTableAccounts(pubkeys);
15606
+ return await this.fetchAddressLookupTableAccounts(pubkeys);
15608
15607
  }
15609
15608
  }
15610
15609
  const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
15611
15610
  if (tablePubkey) {
15612
- return await this.fetchAdressLookupTableAccounts([
15611
+ return await this.fetchAddressLookupTableAccounts([
15613
15612
  tablePubkey
15614
15613
  ]);
15615
15614
  }
@@ -15660,12 +15659,12 @@ class BaseClient {
15660
15659
  }
15661
15660
  const lookupTableAccounts = [];
15662
15661
  if (lookupTables.every((t)=>t instanceof web3_js.AddressLookupTableAccount)) {
15663
- const accounts = await this.fetchAdressLookupTableAccounts([
15662
+ const accounts = await this.fetchAddressLookupTableAccounts([
15664
15663
  ...LOOKUP_TABLES
15665
15664
  ]);
15666
15665
  lookupTableAccounts.push(...lookupTables, ...accounts);
15667
15666
  } else {
15668
- const accounts = await this.fetchAdressLookupTableAccounts([
15667
+ const accounts = await this.fetchAddressLookupTableAccounts([
15669
15668
  ...lookupTables,
15670
15669
  ...LOOKUP_TABLES
15671
15670
  ]);
@@ -15749,7 +15748,7 @@ class BaseClient {
15749
15748
  *
15750
15749
  * @param pubkeys Array of lookup table public keys.
15751
15750
  * @returns
15752
- */ async fetchAdressLookupTableAccounts(pubkeys) {
15751
+ */ async fetchAddressLookupTableAccounts(pubkeys) {
15753
15752
  if (!pubkeys) {
15754
15753
  throw new Error("addressLookupTableAddresses is undefined");
15755
15754
  }
@@ -20824,9 +20823,7 @@ class KaminoVaultsClient {
20824
20823
  return vaultState;
20825
20824
  }
20826
20825
  async composeRemainingAccounts(allocationStrategies, pricingMode = false) {
20827
- // Iterate over allocation strategies and get reserve pubkeys, using a Set to avoid dupes
20828
- const reservesSet = new Set(allocationStrategies.map((strategy)=>strategy.reserve.toBase58()));
20829
- const reserves = Array.from(reservesSet).map((p)=>new web3_js.PublicKey(p));
20826
+ const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
20830
20827
  const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
20831
20828
  const reserveMetas = reserves.map((pubkey)=>({
20832
20829
  pubkey,
@@ -21439,26 +21436,41 @@ class PriceClient {
21439
21436
  oracles[i]
21440
21437
  ].map((pubkey)=>{
21441
21438
  remainingAccounts.push({
21442
- pubkey,
21439
+ pubkey: pubkey,
21443
21440
  isSigner: false,
21444
21441
  isWritable: false
21445
21442
  });
21446
21443
  });
21447
21444
  }
21448
- // markets and reserves
21449
21445
  const marketsAndReserves = (await Promise.all(kvaultStates.map((kvault)=>{
21450
21446
  return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)), true);
21451
21447
  }))).flat();
21452
- remainingAccounts.push(...marketsAndReserves);
21448
+ const processed = new Set();
21449
+ const preInstructions = [];
21450
+ const chunkSize = 2;
21451
+ for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
21452
+ const chunk = marketsAndReserves.slice(i, i + chunkSize);
21453
+ const market = chunk[0].pubkey;
21454
+ const reserve = chunk[1].pubkey;
21455
+ // reserve should always be added to remaining accounts
21456
+ remainingAccounts.push(chunk[1]);
21457
+ // each reserve should only be refreshed once
21458
+ if (!processed.has(reserve.toBase58())) {
21459
+ const ix = this.klend.refreshReserveIxs(market, [
21460
+ reserve
21461
+ ]);
21462
+ preInstructions.push(...ix);
21463
+ processed.add(reserve.toBase58());
21464
+ }
21465
+ }
21453
21466
  const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
21454
21467
  glamState: this.base.statePda,
21455
- solOracle: SOL_ORACLE,
21456
- pythOracle: null,
21457
- switchboardPriceOracle: null,
21458
- switchboardTwapOracle: null,
21459
- scopePrices: KAMINO_SCOPE_PRICES
21468
+ solOracle: SOL_ORACLE
21460
21469
  }).remainingAccounts(remainingAccounts).instruction();
21461
- return priceIx;
21470
+ return [
21471
+ ...preInstructions,
21472
+ priceIx
21473
+ ];
21462
21474
  }
21463
21475
  /**
21464
21476
  * Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
@@ -21526,43 +21538,8 @@ class PriceClient {
21526
21538
  if (parsedVaultDepositors.length === 0) {
21527
21539
  return null;
21528
21540
  }
21529
- // For each vault deposit, we need the following pubkeys in remaining accounts:
21530
- // - depositor
21531
- // - drift vault
21532
- // - drift user of the vault
21533
- // - oracles
21534
- // - spot & perp markets
21535
- // There might be overlaps between markets and oracles so we use a set to avoid duplicates
21536
- const remainingAccounts = [];
21537
- const marketsAndOracles = new Set();
21538
- for (const depositor of parsedVaultDepositors){
21539
- const { user: driftUser } = await this.dvaults.parseDriftVault(depositor.driftVault);
21540
- remainingAccounts.push({
21541
- pubkey: depositor.address,
21542
- isSigner: false,
21543
- isWritable: false
21544
- });
21545
- remainingAccounts.push({
21546
- pubkey: depositor.driftVault,
21547
- isSigner: false,
21548
- isWritable: false
21549
- });
21550
- remainingAccounts.push({
21551
- pubkey: driftUser,
21552
- isSigner: false,
21553
- isWritable: false
21554
- });
21555
- const markets_and_oracles = (await this.dvaults.composeRemainingAccounts(driftUser)).map((a)=>a.pubkey.toBase58());
21556
- for (const k of markets_and_oracles){
21557
- marketsAndOracles.add(k);
21558
- }
21559
- }
21560
- Array.from(marketsAndOracles).forEach((k)=>remainingAccounts.push({
21561
- pubkey: new web3_js.PublicKey(k),
21562
- isSigner: false,
21563
- isWritable: false
21564
- }));
21565
- const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length).accounts({
21541
+ const { remainingAccounts, numSpotMarkets, numPerpMarkets } = await this.remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors);
21542
+ const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length, numSpotMarkets, numPerpMarkets).accounts({
21566
21543
  glamState: this.base.statePda,
21567
21544
  solOracle: SOL_ORACLE
21568
21545
  }).remainingAccounts(remainingAccounts).instruction();
@@ -21629,12 +21606,11 @@ class PriceClient {
21629
21606
  }
21630
21607
  const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
21631
21608
  const integrationsToPricingFns = {
21632
- drift: this.priceDriftUsersIx.bind(this),
21633
- kaminoLending: this.priceKaminoObligationsIx.bind(this),
21634
- nativeStaking: this.priceStakesIx.bind(this),
21635
- meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21636
- driftVaults: this.priceDriftVaultDepositorsIx.bind(this),
21637
- kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
21609
+ // drift: this.priceDriftUsersIx.bind(this),
21610
+ // kaminoLending: this.priceKaminoObligationsIx.bind(this),
21611
+ // nativeStaking: this.priceStakesIx.bind(this),
21612
+ // meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21613
+ driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
21638
21614
  };
21639
21615
  const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
21640
21616
  const pricingIxs = [
@@ -21642,72 +21618,130 @@ class PriceClient {
21642
21618
  ];
21643
21619
  for (const fn of pricingFns){
21644
21620
  const ix = await fn(priceDenom);
21645
- pricingIxs.push(ix);
21621
+ if (Array.isArray(ix)) {
21622
+ pricingIxs.push(...ix);
21623
+ } else {
21624
+ pricingIxs.push(ix);
21625
+ }
21646
21626
  }
21647
21627
  return pricingIxs.filter(Boolean);
21648
21628
  }
21629
+ async remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors) {
21630
+ // Extra accounts for pricing N vault depositors:
21631
+ // - (vault_depositor, drift_vault, drift_user) x N
21632
+ // - spot_market used by drift users of vaults (no specific order)
21633
+ // - perp markets used by drift users of vaults (no specific order)
21634
+ // - oracles of spot markets and perp markets (no specific order)
21635
+ const remainingAccounts = [];
21636
+ const spotMarketsSet = new Set();
21637
+ const perpMarketsSet = new Set();
21638
+ const oraclesSet = new Set();
21639
+ for (const { address: depositor, driftVault } of parsedVaultDepositors){
21640
+ const { user } = await this.dvaults.parseDriftVault(driftVault); // get drift user used by the vault
21641
+ [
21642
+ depositor,
21643
+ driftVault,
21644
+ user
21645
+ ].forEach((k)=>remainingAccounts.push({
21646
+ pubkey: k,
21647
+ isSigner: false,
21648
+ isWritable: false
21649
+ }));
21650
+ const { spotPositions, perpPositions } = await this.dvaults.fetchUserPositions(user);
21651
+ const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
21652
+ const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
21653
+ // If there are perp positions, add spot market 0 as it's used as quote market for perp
21654
+ if (perpMarketIndexes.length > 0 && !spotMarketIndexes.includes(0)) {
21655
+ spotMarketIndexes.push(0);
21656
+ }
21657
+ const spotMarkets = await this.drift.fetchAndParseSpotMarkets(spotMarketIndexes);
21658
+ const perpMarkets = await this.drift.fetchAndParsePerpMarkets(perpMarketIndexes);
21659
+ spotMarkets.forEach((m)=>{
21660
+ oraclesSet.add(m.oracle.toBase58());
21661
+ spotMarketsSet.add(m.marketPda.toBase58());
21662
+ });
21663
+ perpMarkets.forEach((m)=>{
21664
+ oraclesSet.add(m.oracle.toBase58());
21665
+ perpMarketsSet.add(m.marketPda.toBase58());
21666
+ });
21667
+ }
21668
+ [
21669
+ ...spotMarketsSet,
21670
+ ...perpMarketsSet,
21671
+ ...oraclesSet
21672
+ ].forEach((k)=>remainingAccounts.push({
21673
+ pubkey: new web3_js.PublicKey(k),
21674
+ isSigner: false,
21675
+ isWritable: false
21676
+ }));
21677
+ return {
21678
+ remainingAccounts,
21679
+ numSpotMarkets: spotMarketsSet.size,
21680
+ numPerpMarkets: perpMarketsSet.size
21681
+ };
21682
+ }
21683
+ async remainingAccountsForPricingMeteora() {
21684
+ const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
21685
+ let chunks = await Promise.all(positions.map(async (pubkey)=>{
21686
+ const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
21687
+ return [
21688
+ pubkey,
21689
+ lbPair,
21690
+ binArrayLower,
21691
+ binArrayUpper,
21692
+ SOL_ORACLE,
21693
+ USDC_ORACLE
21694
+ ].map((k)=>({
21695
+ pubkey: k,
21696
+ isSigner: false,
21697
+ isWritable: false
21698
+ }));
21699
+ }));
21700
+ return chunks.flat();
21701
+ }
21702
+ async remainingAccountsForPricingVaultAssets(baseAssetOnly = false) {
21703
+ const stateModel = await this.base.fetchStateModel();
21704
+ if (baseAssetOnly) {
21705
+ if (!stateModel.baseAsset) {
21706
+ throw new Error("Base asset not configured for the vault");
21707
+ }
21708
+ // FIXME: support token 2022 base asset
21709
+ const ata = this.base.getVaultAta(stateModel.baseAsset);
21710
+ // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
21711
+ return [
21712
+ ata,
21713
+ stateModel.baseAsset,
21714
+ web3_js.PublicKey.default
21715
+ ].map((k)=>({
21716
+ pubkey: k,
21717
+ isSigner: false,
21718
+ isWritable: false
21719
+ }));
21720
+ }
21721
+ const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
21722
+ return assetsForPricing.map((mint)=>{
21723
+ const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
21724
+ if (!assetMeta) {
21725
+ throw new Error(`Asset meta not found for ${mint}`);
21726
+ }
21727
+ const ata = this.base.getVaultAta(mint, assetMeta?.programId);
21728
+ return [
21729
+ ata,
21730
+ mint,
21731
+ assetMeta?.oracle
21732
+ ];
21733
+ }).flat().map((a)=>({
21734
+ pubkey: a,
21735
+ isSigner: false,
21736
+ isWritable: false
21737
+ }));
21738
+ }
21649
21739
  constructor(base, klend, kvaults, drift, dvaults){
21650
21740
  this.base = base;
21651
21741
  this.klend = klend;
21652
21742
  this.kvaults = kvaults;
21653
21743
  this.drift = drift;
21654
21744
  this.dvaults = dvaults;
21655
- this.remainingAccountsForPricingMeteora = async ()=>{
21656
- const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
21657
- let chunks = await Promise.all(positions.map(async (pubkey)=>{
21658
- const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
21659
- return [
21660
- pubkey,
21661
- lbPair,
21662
- binArrayLower,
21663
- binArrayUpper,
21664
- SOL_ORACLE,
21665
- USDC_ORACLE
21666
- ].map((k)=>({
21667
- pubkey: k,
21668
- isSigner: false,
21669
- isWritable: false
21670
- }));
21671
- }));
21672
- return chunks.flat();
21673
- };
21674
- this.remainingAccountsForPricingVaultAssets = async (baseAssetOnly = false)=>{
21675
- const stateModel = await this.base.fetchStateModel();
21676
- if (baseAssetOnly) {
21677
- if (!stateModel.baseAsset) {
21678
- throw new Error("Base asset not configured for the vault");
21679
- }
21680
- // FIXME: support token 2022 base asset
21681
- const ata = this.base.getVaultAta(stateModel.baseAsset);
21682
- // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
21683
- return [
21684
- ata,
21685
- stateModel.baseAsset,
21686
- web3_js.PublicKey.default
21687
- ].map((k)=>({
21688
- pubkey: k,
21689
- isSigner: false,
21690
- isWritable: false
21691
- }));
21692
- }
21693
- const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
21694
- return assetsForPricing.map((mint)=>{
21695
- const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
21696
- if (!assetMeta) {
21697
- throw new Error(`Asset meta not found for ${mint}`);
21698
- }
21699
- const ata = this.base.getVaultAta(mint, assetMeta?.programId);
21700
- return [
21701
- ata,
21702
- mint,
21703
- assetMeta?.oracle
21704
- ];
21705
- }).flat().map((a)=>({
21706
- pubkey: a,
21707
- isSigner: false,
21708
- isWritable: false
21709
- }));
21710
- };
21711
21745
  }
21712
21746
  }
21713
21747
 
package/index.esm.js CHANGED
@@ -14,7 +14,7 @@ import { getStakePoolAccount } from '@solana/spl-stake-pool';
14
14
  var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
15
15
  var metadata = {
16
16
  name: "glam_protocol",
17
- version: "0.4.33",
17
+ version: "0.4.35",
18
18
  spec: "0.1.0",
19
19
  description: "Glam Protocol"
20
20
  };
@@ -6880,7 +6880,9 @@ var instructions = [
6880
6880
  docs: [
6881
6881
  "Extra accounts for pricing N vault depositors:",
6882
6882
  "- (vault_depositor, drift_vault, drift_user) x N",
6883
- "- markets and oracles used by all drift users (no specific order)"
6883
+ "- spot_market used by drift users of vaults (no specific order)",
6884
+ "- perp markets used by drift users of vaults (no specific order)",
6885
+ "- oracles of spot markets and perp markets (no specific order)"
6884
6886
  ],
6885
6887
  discriminator: [
6886
6888
  234,
@@ -7001,6 +7003,14 @@ var instructions = [
7001
7003
  {
7002
7004
  name: "num_vault_depositors",
7003
7005
  type: "u8"
7006
+ },
7007
+ {
7008
+ name: "num_spot_markets",
7009
+ type: "u8"
7010
+ },
7011
+ {
7012
+ name: "num_perp_markets",
7013
+ type: "u8"
7004
7014
  }
7005
7015
  ]
7006
7016
  },
@@ -7147,9 +7157,14 @@ var instructions = [
7147
7157
  {
7148
7158
  name: "price_kamino_vault_shares",
7149
7159
  docs: [
7160
+ "Price Kamino vault shares.",
7161
+ "- `num_vaults` Number of kamino vaults to price.",
7162
+ "",
7150
7163
  "Extra accounts for pricing N kamino vault shares:",
7151
7164
  "- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
7152
- "- (lending_market, reserve) x M, M = number of unique markets used by all kvaults involved"
7165
+ "- reserve x M",
7166
+ "- M = number of reserves used by all kvaults' allocations",
7167
+ "- reserve pubkeys must follow the same order of reserves used by each allocation"
7153
7168
  ],
7154
7169
  discriminator: [
7155
7170
  112,
@@ -7192,10 +7207,6 @@ var instructions = [
7192
7207
  writable: true,
7193
7208
  signer: true
7194
7209
  },
7195
- {
7196
- name: "kamino_lending_program",
7197
- address: "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
7198
- },
7199
7210
  {
7200
7211
  name: "sol_oracle"
7201
7212
  },
@@ -7260,22 +7271,6 @@ var instructions = [
7260
7271
  ]
7261
7272
  }
7262
7273
  }
7263
- },
7264
- {
7265
- name: "pyth_oracle",
7266
- optional: true
7267
- },
7268
- {
7269
- name: "switchboard_price_oracle",
7270
- optional: true
7271
- },
7272
- {
7273
- name: "switchboard_twap_oracle",
7274
- optional: true
7275
- },
7276
- {
7277
- name: "scope_prices",
7278
- optional: true
7279
7274
  }
7280
7275
  ],
7281
7276
  args: [
@@ -9588,6 +9583,10 @@ var instructions = [
9588
9583
  {
9589
9584
  name: "stake_history",
9590
9585
  address: "SysvarStakeHistory1111111111111111111111111"
9586
+ },
9587
+ {
9588
+ name: "system_program",
9589
+ address: "11111111111111111111111111111111"
9591
9590
  }
9592
9591
  ],
9593
9592
  args: [
@@ -15584,12 +15583,12 @@ class BaseClient {
15584
15583
  const { t: lookupTables } = data;
15585
15584
  const pubkeys = Object.keys(lookupTables);
15586
15585
  if (pubkeys.length > 0) {
15587
- return await this.fetchAdressLookupTableAccounts(pubkeys);
15586
+ return await this.fetchAddressLookupTableAccounts(pubkeys);
15588
15587
  }
15589
15588
  }
15590
15589
  const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
15591
15590
  if (tablePubkey) {
15592
- return await this.fetchAdressLookupTableAccounts([
15591
+ return await this.fetchAddressLookupTableAccounts([
15593
15592
  tablePubkey
15594
15593
  ]);
15595
15594
  }
@@ -15640,12 +15639,12 @@ class BaseClient {
15640
15639
  }
15641
15640
  const lookupTableAccounts = [];
15642
15641
  if (lookupTables.every((t)=>t instanceof AddressLookupTableAccount)) {
15643
- const accounts = await this.fetchAdressLookupTableAccounts([
15642
+ const accounts = await this.fetchAddressLookupTableAccounts([
15644
15643
  ...LOOKUP_TABLES
15645
15644
  ]);
15646
15645
  lookupTableAccounts.push(...lookupTables, ...accounts);
15647
15646
  } else {
15648
- const accounts = await this.fetchAdressLookupTableAccounts([
15647
+ const accounts = await this.fetchAddressLookupTableAccounts([
15649
15648
  ...lookupTables,
15650
15649
  ...LOOKUP_TABLES
15651
15650
  ]);
@@ -15729,7 +15728,7 @@ class BaseClient {
15729
15728
  *
15730
15729
  * @param pubkeys Array of lookup table public keys.
15731
15730
  * @returns
15732
- */ async fetchAdressLookupTableAccounts(pubkeys) {
15731
+ */ async fetchAddressLookupTableAccounts(pubkeys) {
15733
15732
  if (!pubkeys) {
15734
15733
  throw new Error("addressLookupTableAddresses is undefined");
15735
15734
  }
@@ -20804,9 +20803,7 @@ class KaminoVaultsClient {
20804
20803
  return vaultState;
20805
20804
  }
20806
20805
  async composeRemainingAccounts(allocationStrategies, pricingMode = false) {
20807
- // Iterate over allocation strategies and get reserve pubkeys, using a Set to avoid dupes
20808
- const reservesSet = new Set(allocationStrategies.map((strategy)=>strategy.reserve.toBase58()));
20809
- const reserves = Array.from(reservesSet).map((p)=>new PublicKey(p));
20806
+ const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
20810
20807
  const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
20811
20808
  const reserveMetas = reserves.map((pubkey)=>({
20812
20809
  pubkey,
@@ -21419,26 +21416,41 @@ class PriceClient {
21419
21416
  oracles[i]
21420
21417
  ].map((pubkey)=>{
21421
21418
  remainingAccounts.push({
21422
- pubkey,
21419
+ pubkey: pubkey,
21423
21420
  isSigner: false,
21424
21421
  isWritable: false
21425
21422
  });
21426
21423
  });
21427
21424
  }
21428
- // markets and reserves
21429
21425
  const marketsAndReserves = (await Promise.all(kvaultStates.map((kvault)=>{
21430
21426
  return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(PublicKey.default)), true);
21431
21427
  }))).flat();
21432
- remainingAccounts.push(...marketsAndReserves);
21428
+ const processed = new Set();
21429
+ const preInstructions = [];
21430
+ const chunkSize = 2;
21431
+ for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
21432
+ const chunk = marketsAndReserves.slice(i, i + chunkSize);
21433
+ const market = chunk[0].pubkey;
21434
+ const reserve = chunk[1].pubkey;
21435
+ // reserve should always be added to remaining accounts
21436
+ remainingAccounts.push(chunk[1]);
21437
+ // each reserve should only be refreshed once
21438
+ if (!processed.has(reserve.toBase58())) {
21439
+ const ix = this.klend.refreshReserveIxs(market, [
21440
+ reserve
21441
+ ]);
21442
+ preInstructions.push(...ix);
21443
+ processed.add(reserve.toBase58());
21444
+ }
21445
+ }
21433
21446
  const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
21434
21447
  glamState: this.base.statePda,
21435
- solOracle: SOL_ORACLE,
21436
- pythOracle: null,
21437
- switchboardPriceOracle: null,
21438
- switchboardTwapOracle: null,
21439
- scopePrices: KAMINO_SCOPE_PRICES
21448
+ solOracle: SOL_ORACLE
21440
21449
  }).remainingAccounts(remainingAccounts).instruction();
21441
- return priceIx;
21450
+ return [
21451
+ ...preInstructions,
21452
+ priceIx
21453
+ ];
21442
21454
  }
21443
21455
  /**
21444
21456
  * Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
@@ -21506,43 +21518,8 @@ class PriceClient {
21506
21518
  if (parsedVaultDepositors.length === 0) {
21507
21519
  return null;
21508
21520
  }
21509
- // For each vault deposit, we need the following pubkeys in remaining accounts:
21510
- // - depositor
21511
- // - drift vault
21512
- // - drift user of the vault
21513
- // - oracles
21514
- // - spot & perp markets
21515
- // There might be overlaps between markets and oracles so we use a set to avoid duplicates
21516
- const remainingAccounts = [];
21517
- const marketsAndOracles = new Set();
21518
- for (const depositor of parsedVaultDepositors){
21519
- const { user: driftUser } = await this.dvaults.parseDriftVault(depositor.driftVault);
21520
- remainingAccounts.push({
21521
- pubkey: depositor.address,
21522
- isSigner: false,
21523
- isWritable: false
21524
- });
21525
- remainingAccounts.push({
21526
- pubkey: depositor.driftVault,
21527
- isSigner: false,
21528
- isWritable: false
21529
- });
21530
- remainingAccounts.push({
21531
- pubkey: driftUser,
21532
- isSigner: false,
21533
- isWritable: false
21534
- });
21535
- const markets_and_oracles = (await this.dvaults.composeRemainingAccounts(driftUser)).map((a)=>a.pubkey.toBase58());
21536
- for (const k of markets_and_oracles){
21537
- marketsAndOracles.add(k);
21538
- }
21539
- }
21540
- Array.from(marketsAndOracles).forEach((k)=>remainingAccounts.push({
21541
- pubkey: new PublicKey(k),
21542
- isSigner: false,
21543
- isWritable: false
21544
- }));
21545
- const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length).accounts({
21521
+ const { remainingAccounts, numSpotMarkets, numPerpMarkets } = await this.remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors);
21522
+ const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length, numSpotMarkets, numPerpMarkets).accounts({
21546
21523
  glamState: this.base.statePda,
21547
21524
  solOracle: SOL_ORACLE
21548
21525
  }).remainingAccounts(remainingAccounts).instruction();
@@ -21609,12 +21586,11 @@ class PriceClient {
21609
21586
  }
21610
21587
  const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
21611
21588
  const integrationsToPricingFns = {
21612
- drift: this.priceDriftUsersIx.bind(this),
21613
- kaminoLending: this.priceKaminoObligationsIx.bind(this),
21614
- nativeStaking: this.priceStakesIx.bind(this),
21615
- meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21616
- driftVaults: this.priceDriftVaultDepositorsIx.bind(this),
21617
- kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
21589
+ // drift: this.priceDriftUsersIx.bind(this),
21590
+ // kaminoLending: this.priceKaminoObligationsIx.bind(this),
21591
+ // nativeStaking: this.priceStakesIx.bind(this),
21592
+ // meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21593
+ driftVaults: this.priceDriftVaultDepositorsIx.bind(this)
21618
21594
  };
21619
21595
  const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
21620
21596
  const pricingIxs = [
@@ -21622,72 +21598,130 @@ class PriceClient {
21622
21598
  ];
21623
21599
  for (const fn of pricingFns){
21624
21600
  const ix = await fn(priceDenom);
21625
- pricingIxs.push(ix);
21601
+ if (Array.isArray(ix)) {
21602
+ pricingIxs.push(...ix);
21603
+ } else {
21604
+ pricingIxs.push(ix);
21605
+ }
21626
21606
  }
21627
21607
  return pricingIxs.filter(Boolean);
21628
21608
  }
21609
+ async remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors) {
21610
+ // Extra accounts for pricing N vault depositors:
21611
+ // - (vault_depositor, drift_vault, drift_user) x N
21612
+ // - spot_market used by drift users of vaults (no specific order)
21613
+ // - perp markets used by drift users of vaults (no specific order)
21614
+ // - oracles of spot markets and perp markets (no specific order)
21615
+ const remainingAccounts = [];
21616
+ const spotMarketsSet = new Set();
21617
+ const perpMarketsSet = new Set();
21618
+ const oraclesSet = new Set();
21619
+ for (const { address: depositor, driftVault } of parsedVaultDepositors){
21620
+ const { user } = await this.dvaults.parseDriftVault(driftVault); // get drift user used by the vault
21621
+ [
21622
+ depositor,
21623
+ driftVault,
21624
+ user
21625
+ ].forEach((k)=>remainingAccounts.push({
21626
+ pubkey: k,
21627
+ isSigner: false,
21628
+ isWritable: false
21629
+ }));
21630
+ const { spotPositions, perpPositions } = await this.dvaults.fetchUserPositions(user);
21631
+ const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
21632
+ const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
21633
+ // If there are perp positions, add spot market 0 as it's used as quote market for perp
21634
+ if (perpMarketIndexes.length > 0 && !spotMarketIndexes.includes(0)) {
21635
+ spotMarketIndexes.push(0);
21636
+ }
21637
+ const spotMarkets = await this.drift.fetchAndParseSpotMarkets(spotMarketIndexes);
21638
+ const perpMarkets = await this.drift.fetchAndParsePerpMarkets(perpMarketIndexes);
21639
+ spotMarkets.forEach((m)=>{
21640
+ oraclesSet.add(m.oracle.toBase58());
21641
+ spotMarketsSet.add(m.marketPda.toBase58());
21642
+ });
21643
+ perpMarkets.forEach((m)=>{
21644
+ oraclesSet.add(m.oracle.toBase58());
21645
+ perpMarketsSet.add(m.marketPda.toBase58());
21646
+ });
21647
+ }
21648
+ [
21649
+ ...spotMarketsSet,
21650
+ ...perpMarketsSet,
21651
+ ...oraclesSet
21652
+ ].forEach((k)=>remainingAccounts.push({
21653
+ pubkey: new PublicKey(k),
21654
+ isSigner: false,
21655
+ isWritable: false
21656
+ }));
21657
+ return {
21658
+ remainingAccounts,
21659
+ numSpotMarkets: spotMarketsSet.size,
21660
+ numPerpMarkets: perpMarketsSet.size
21661
+ };
21662
+ }
21663
+ async remainingAccountsForPricingMeteora() {
21664
+ const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
21665
+ let chunks = await Promise.all(positions.map(async (pubkey)=>{
21666
+ const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
21667
+ return [
21668
+ pubkey,
21669
+ lbPair,
21670
+ binArrayLower,
21671
+ binArrayUpper,
21672
+ SOL_ORACLE,
21673
+ USDC_ORACLE
21674
+ ].map((k)=>({
21675
+ pubkey: k,
21676
+ isSigner: false,
21677
+ isWritable: false
21678
+ }));
21679
+ }));
21680
+ return chunks.flat();
21681
+ }
21682
+ async remainingAccountsForPricingVaultAssets(baseAssetOnly = false) {
21683
+ const stateModel = await this.base.fetchStateModel();
21684
+ if (baseAssetOnly) {
21685
+ if (!stateModel.baseAsset) {
21686
+ throw new Error("Base asset not configured for the vault");
21687
+ }
21688
+ // FIXME: support token 2022 base asset
21689
+ const ata = this.base.getVaultAta(stateModel.baseAsset);
21690
+ // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
21691
+ return [
21692
+ ata,
21693
+ stateModel.baseAsset,
21694
+ PublicKey.default
21695
+ ].map((k)=>({
21696
+ pubkey: k,
21697
+ isSigner: false,
21698
+ isWritable: false
21699
+ }));
21700
+ }
21701
+ const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
21702
+ return assetsForPricing.map((mint)=>{
21703
+ const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
21704
+ if (!assetMeta) {
21705
+ throw new Error(`Asset meta not found for ${mint}`);
21706
+ }
21707
+ const ata = this.base.getVaultAta(mint, assetMeta?.programId);
21708
+ return [
21709
+ ata,
21710
+ mint,
21711
+ assetMeta?.oracle
21712
+ ];
21713
+ }).flat().map((a)=>({
21714
+ pubkey: a,
21715
+ isSigner: false,
21716
+ isWritable: false
21717
+ }));
21718
+ }
21629
21719
  constructor(base, klend, kvaults, drift, dvaults){
21630
21720
  this.base = base;
21631
21721
  this.klend = klend;
21632
21722
  this.kvaults = kvaults;
21633
21723
  this.drift = drift;
21634
21724
  this.dvaults = dvaults;
21635
- this.remainingAccountsForPricingMeteora = async ()=>{
21636
- const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
21637
- let chunks = await Promise.all(positions.map(async (pubkey)=>{
21638
- const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
21639
- return [
21640
- pubkey,
21641
- lbPair,
21642
- binArrayLower,
21643
- binArrayUpper,
21644
- SOL_ORACLE,
21645
- USDC_ORACLE
21646
- ].map((k)=>({
21647
- pubkey: k,
21648
- isSigner: false,
21649
- isWritable: false
21650
- }));
21651
- }));
21652
- return chunks.flat();
21653
- };
21654
- this.remainingAccountsForPricingVaultAssets = async (baseAssetOnly = false)=>{
21655
- const stateModel = await this.base.fetchStateModel();
21656
- if (baseAssetOnly) {
21657
- if (!stateModel.baseAsset) {
21658
- throw new Error("Base asset not configured for the vault");
21659
- }
21660
- // FIXME: support token 2022 base asset
21661
- const ata = this.base.getVaultAta(stateModel.baseAsset);
21662
- // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
21663
- return [
21664
- ata,
21665
- stateModel.baseAsset,
21666
- PublicKey.default
21667
- ].map((k)=>({
21668
- pubkey: k,
21669
- isSigner: false,
21670
- isWritable: false
21671
- }));
21672
- }
21673
- const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
21674
- return assetsForPricing.map((mint)=>{
21675
- const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
21676
- if (!assetMeta) {
21677
- throw new Error(`Asset meta not found for ${mint}`);
21678
- }
21679
- const ata = this.base.getVaultAta(mint, assetMeta?.programId);
21680
- return [
21681
- ata,
21682
- mint,
21683
- assetMeta?.oracle
21684
- ];
21685
- }).flat().map((a)=>({
21686
- pubkey: a,
21687
- isSigner: false,
21688
- isWritable: false
21689
- }));
21690
- };
21691
21725
  }
21692
21726
  }
21693
21727
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glamsystems/glam-sdk",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "description": "TypeScript SDK for the GLAM Protocol",
5
5
  "main": "./index.cjs.js",
6
6
  "module": "./index.esm.js",
@@ -62,7 +62,7 @@ export declare class BaseClient {
62
62
  * @param pubkeys Array of lookup table public keys.
63
63
  * @returns
64
64
  */
65
- fetchAdressLookupTableAccounts(pubkeys?: string[] | PublicKey[]): Promise<AddressLookupTableAccount[]>;
65
+ fetchAddressLookupTableAccounts(pubkeys?: string[] | PublicKey[]): Promise<AddressLookupTableAccount[]>;
66
66
  getWallet(): Wallet;
67
67
  getSigner(): PublicKey;
68
68
  get signer(): PublicKey;
@@ -1,4 +1,4 @@
1
- import { PublicKey, TransactionInstruction } from "@solana/web3.js";
1
+ import { AccountMeta, PublicKey, TransactionInstruction } from "@solana/web3.js";
2
2
  import { KaminoLendingClient, KaminoVaultsClient } from "./kamino";
3
3
  import { BaseClient } from "./base";
4
4
  import { PriceDenom } from "../models";
@@ -21,7 +21,7 @@ export declare class PriceClient {
21
21
  * If there are no Kamino obligations, returns null.
22
22
  */
23
23
  priceKaminoObligationsIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
24
- priceKaminoVaultSharesIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
24
+ priceKaminoVaultSharesIx(priceDenom: PriceDenom): Promise<TransactionInstruction[] | null>;
25
25
  /**
26
26
  * Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
27
27
  */
@@ -46,14 +46,15 @@ export declare class PriceClient {
46
46
  */
47
47
  priceMeteoraPositionsIx(priceDenom: PriceDenom): Promise<TransactionInstruction | null>;
48
48
  priceVaultIxs(priceDenom: PriceDenom): Promise<TransactionInstruction[]>;
49
- remainingAccountsForPricingMeteora: () => Promise<{
50
- pubkey: PublicKey;
51
- isSigner: boolean;
52
- isWritable: boolean;
53
- }[]>;
54
- remainingAccountsForPricingVaultAssets: (baseAssetOnly?: boolean) => Promise<{
55
- pubkey: PublicKey;
56
- isSigner: boolean;
57
- isWritable: boolean;
58
- }[]>;
49
+ remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors: {
50
+ address: PublicKey;
51
+ driftVault: PublicKey;
52
+ shares: any;
53
+ }[]): Promise<{
54
+ remainingAccounts: AccountMeta[];
55
+ numSpotMarkets: number;
56
+ numPerpMarkets: number;
57
+ }>;
58
+ remainingAccountsForPricingMeteora(): Promise<AccountMeta[]>;
59
+ remainingAccountsForPricingVaultAssets(baseAssetOnly?: boolean): Promise<AccountMeta[]>;
59
60
  }
@@ -2,7 +2,7 @@
2
2
  "address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc",
3
3
  "metadata": {
4
4
  "name": "glam_protocol",
5
- "version": "0.4.33",
5
+ "version": "0.4.35",
6
6
  "spec": "0.1.0",
7
7
  "description": "Glam Protocol"
8
8
  },
@@ -6868,7 +6868,9 @@
6868
6868
  "docs": [
6869
6869
  "Extra accounts for pricing N vault depositors:",
6870
6870
  "- (vault_depositor, drift_vault, drift_user) x N",
6871
- "- markets and oracles used by all drift users (no specific order)"
6871
+ "- spot_market used by drift users of vaults (no specific order)",
6872
+ "- perp markets used by drift users of vaults (no specific order)",
6873
+ "- oracles of spot markets and perp markets (no specific order)"
6872
6874
  ],
6873
6875
  "discriminator": [
6874
6876
  234,
@@ -6989,6 +6991,14 @@
6989
6991
  {
6990
6992
  "name": "num_vault_depositors",
6991
6993
  "type": "u8"
6994
+ },
6995
+ {
6996
+ "name": "num_spot_markets",
6997
+ "type": "u8"
6998
+ },
6999
+ {
7000
+ "name": "num_perp_markets",
7001
+ "type": "u8"
6992
7002
  }
6993
7003
  ]
6994
7004
  },
@@ -7135,9 +7145,14 @@
7135
7145
  {
7136
7146
  "name": "price_kamino_vault_shares",
7137
7147
  "docs": [
7148
+ "Price Kamino vault shares.",
7149
+ "- `num_vaults` Number of kamino vaults to price.",
7150
+ "",
7138
7151
  "Extra accounts for pricing N kamino vault shares:",
7139
7152
  "- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
7140
- "- (lending_market, reserve) x M, M = number of unique markets used by all kvaults involved"
7153
+ "- reserve x M",
7154
+ "- M = number of reserves used by all kvaults' allocations",
7155
+ "- reserve pubkeys must follow the same order of reserves used by each allocation"
7141
7156
  ],
7142
7157
  "discriminator": [
7143
7158
  112,
@@ -7180,10 +7195,6 @@
7180
7195
  "writable": true,
7181
7196
  "signer": true
7182
7197
  },
7183
- {
7184
- "name": "kamino_lending_program",
7185
- "address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
7186
- },
7187
7198
  {
7188
7199
  "name": "sol_oracle"
7189
7200
  },
@@ -7248,22 +7259,6 @@
7248
7259
  ]
7249
7260
  }
7250
7261
  }
7251
- },
7252
- {
7253
- "name": "pyth_oracle",
7254
- "optional": true
7255
- },
7256
- {
7257
- "name": "switchboard_price_oracle",
7258
- "optional": true
7259
- },
7260
- {
7261
- "name": "switchboard_twap_oracle",
7262
- "optional": true
7263
- },
7264
- {
7265
- "name": "scope_prices",
7266
- "optional": true
7267
7262
  }
7268
7263
  ],
7269
7264
  "args": [
@@ -9576,6 +9571,10 @@
9576
9571
  {
9577
9572
  "name": "stake_history",
9578
9573
  "address": "SysvarStakeHistory1111111111111111111111111"
9574
+ },
9575
+ {
9576
+ "name": "system_program",
9577
+ "address": "11111111111111111111111111111111"
9579
9578
  }
9580
9579
  ],
9581
9580
  "args": [
@@ -8,7 +8,7 @@ export type GlamProtocol = {
8
8
  "address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
9
9
  "metadata": {
10
10
  "name": "glamProtocol";
11
- "version": "0.4.33";
11
+ "version": "0.4.35";
12
12
  "spec": "0.1.0";
13
13
  "description": "Glam Protocol";
14
14
  };
@@ -6874,7 +6874,9 @@ export type GlamProtocol = {
6874
6874
  "docs": [
6875
6875
  "Extra accounts for pricing N vault depositors:",
6876
6876
  "- (vault_depositor, drift_vault, drift_user) x N",
6877
- "- markets and oracles used by all drift users (no specific order)"
6877
+ "- spot_market used by drift users of vaults (no specific order)",
6878
+ "- perp markets used by drift users of vaults (no specific order)",
6879
+ "- oracles of spot markets and perp markets (no specific order)"
6878
6880
  ];
6879
6881
  "discriminator": [
6880
6882
  234,
@@ -6995,6 +6997,14 @@ export type GlamProtocol = {
6995
6997
  {
6996
6998
  "name": "numVaultDepositors";
6997
6999
  "type": "u8";
7000
+ },
7001
+ {
7002
+ "name": "numSpotMarkets";
7003
+ "type": "u8";
7004
+ },
7005
+ {
7006
+ "name": "numPerpMarkets";
7007
+ "type": "u8";
6998
7008
  }
6999
7009
  ];
7000
7010
  },
@@ -7141,9 +7151,14 @@ export type GlamProtocol = {
7141
7151
  {
7142
7152
  "name": "priceKaminoVaultShares";
7143
7153
  "docs": [
7154
+ "Price Kamino vault shares.",
7155
+ "- `num_vaults` Number of kamino vaults to price.",
7156
+ "",
7144
7157
  "Extra accounts for pricing N kamino vault shares:",
7145
7158
  "- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
7146
- "- (lending_market, reserve) x M, M = number of unique markets used by all kvaults involved"
7159
+ "- reserve x M",
7160
+ "- M = number of reserves used by all kvaults' allocations",
7161
+ "- reserve pubkeys must follow the same order of reserves used by each allocation"
7147
7162
  ];
7148
7163
  "discriminator": [
7149
7164
  112,
@@ -7186,10 +7201,6 @@ export type GlamProtocol = {
7186
7201
  "writable": true;
7187
7202
  "signer": true;
7188
7203
  },
7189
- {
7190
- "name": "kaminoLendingProgram";
7191
- "address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD";
7192
- },
7193
7204
  {
7194
7205
  "name": "solOracle";
7195
7206
  },
@@ -7254,22 +7265,6 @@ export type GlamProtocol = {
7254
7265
  ];
7255
7266
  };
7256
7267
  };
7257
- },
7258
- {
7259
- "name": "pythOracle";
7260
- "optional": true;
7261
- },
7262
- {
7263
- "name": "switchboardPriceOracle";
7264
- "optional": true;
7265
- },
7266
- {
7267
- "name": "switchboardTwapOracle";
7268
- "optional": true;
7269
- },
7270
- {
7271
- "name": "scopePrices";
7272
- "optional": true;
7273
7268
  }
7274
7269
  ];
7275
7270
  "args": [
@@ -9582,6 +9577,10 @@ export type GlamProtocol = {
9582
9577
  {
9583
9578
  "name": "stakeHistory";
9584
9579
  "address": "SysvarStakeHistory1111111111111111111111111";
9580
+ },
9581
+ {
9582
+ "name": "systemProgram";
9583
+ "address": "11111111111111111111111111111111";
9585
9584
  }
9586
9585
  ];
9587
9586
  "args": [
@@ -8,7 +8,7 @@ export type GlamProtocol = {
8
8
  "address": "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc",
9
9
  "metadata": {
10
10
  "name": "glamProtocol",
11
- "version": "0.4.33",
11
+ "version": "0.4.35",
12
12
  "spec": "0.1.0",
13
13
  "description": "Glam Protocol"
14
14
  },
@@ -6874,7 +6874,9 @@ export type GlamProtocol = {
6874
6874
  "docs": [
6875
6875
  "Extra accounts for pricing N vault depositors:",
6876
6876
  "- (vault_depositor, drift_vault, drift_user) x N",
6877
- "- markets and oracles used by all drift users (no specific order)"
6877
+ "- spot_market used by drift users of vaults (no specific order)",
6878
+ "- perp markets used by drift users of vaults (no specific order)",
6879
+ "- oracles of spot markets and perp markets (no specific order)"
6878
6880
  ],
6879
6881
  "discriminator": [
6880
6882
  234,
@@ -6995,6 +6997,14 @@ export type GlamProtocol = {
6995
6997
  {
6996
6998
  "name": "numVaultDepositors",
6997
6999
  "type": "u8"
7000
+ },
7001
+ {
7002
+ "name": "numSpotMarkets",
7003
+ "type": "u8"
7004
+ },
7005
+ {
7006
+ "name": "numPerpMarkets",
7007
+ "type": "u8"
6998
7008
  }
6999
7009
  ]
7000
7010
  },
@@ -7141,9 +7151,14 @@ export type GlamProtocol = {
7141
7151
  {
7142
7152
  "name": "priceKaminoVaultShares",
7143
7153
  "docs": [
7154
+ "Price Kamino vault shares.",
7155
+ "- `num_vaults` Number of kamino vaults to price.",
7156
+ "",
7144
7157
  "Extra accounts for pricing N kamino vault shares:",
7145
7158
  "- (kvault_share_ata, kvault_share_mint, kvault_state, kvault_deposit_token_oracle) x N",
7146
- "- (lending_market, reserve) x M, M = number of unique markets used by all kvaults involved"
7159
+ "- reserve x M",
7160
+ "- M = number of reserves used by all kvaults' allocations",
7161
+ "- reserve pubkeys must follow the same order of reserves used by each allocation"
7147
7162
  ],
7148
7163
  "discriminator": [
7149
7164
  112,
@@ -7186,10 +7201,6 @@ export type GlamProtocol = {
7186
7201
  "writable": true,
7187
7202
  "signer": true
7188
7203
  },
7189
- {
7190
- "name": "kaminoLendingProgram",
7191
- "address": "KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"
7192
- },
7193
7204
  {
7194
7205
  "name": "solOracle"
7195
7206
  },
@@ -7254,22 +7265,6 @@ export type GlamProtocol = {
7254
7265
  ]
7255
7266
  }
7256
7267
  }
7257
- },
7258
- {
7259
- "name": "pythOracle",
7260
- "optional": true
7261
- },
7262
- {
7263
- "name": "switchboardPriceOracle",
7264
- "optional": true
7265
- },
7266
- {
7267
- "name": "switchboardTwapOracle",
7268
- "optional": true
7269
- },
7270
- {
7271
- "name": "scopePrices",
7272
- "optional": true
7273
7268
  }
7274
7269
  ],
7275
7270
  "args": [
@@ -9582,6 +9577,10 @@ export type GlamProtocol = {
9582
9577
  {
9583
9578
  "name": "stakeHistory",
9584
9579
  "address": "SysvarStakeHistory1111111111111111111111111"
9580
+ },
9581
+ {
9582
+ "name": "systemProgram",
9583
+ "address": "11111111111111111111111111111111"
9585
9584
  }
9586
9585
  ],
9587
9586
  "args": [