@glamsystems/glam-sdk 0.1.29 → 0.1.31

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: [
@@ -10026,7 +10025,8 @@ var instructions = [
10026
10025
  ],
10027
10026
  accounts: [
10028
10027
  {
10029
- name: "glam_state"
10028
+ name: "glam_state",
10029
+ writable: true
10030
10030
  },
10031
10031
  {
10032
10032
  name: "glam_vault",
@@ -13573,6 +13573,9 @@ var types = [
13573
13573
  },
13574
13574
  {
13575
13575
  name: "Fulfill"
13576
+ },
13577
+ {
13578
+ name: "ClaimFees"
13576
13579
  }
13577
13580
  ]
13578
13581
  }
@@ -14950,6 +14953,15 @@ class PriceDenom {
14950
14953
  }
14951
14954
  return PriceDenom.ASSET;
14952
14955
  }
14956
+ static fromString(str) {
14957
+ if (str === "SOL") {
14958
+ return PriceDenom.SOL;
14959
+ }
14960
+ if (str === "USD") {
14961
+ return PriceDenom.USD;
14962
+ }
14963
+ throw new Error("Invalid price denomination");
14964
+ }
14953
14965
  }
14954
14966
  PriceDenom.SOL = {
14955
14967
  sol: {}
@@ -14985,6 +14997,67 @@ var ClusterNetwork = /*#__PURE__*/ function(ClusterNetwork) {
14985
14997
  return ClusterNetwork;
14986
14998
  }({});
14987
14999
 
15000
+ /**
15001
+ * Fetches all the token accounts owned by the specified pubkey.
15002
+ */ async function getTokenAccountsByOwner(connection, owner) {
15003
+ const tokenAccounts = await connection.getTokenAccountsByOwner(owner, {
15004
+ programId: splToken.TOKEN_PROGRAM_ID
15005
+ });
15006
+ const token2022Accounts = await connection.getTokenAccountsByOwner(owner, {
15007
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15008
+ });
15009
+ const mintPubkeys = [];
15010
+ const parseTokenAccountInfo = (pubkey, account)=>{
15011
+ const { mint, amount, state } = splToken.AccountLayout.decode(account.data);
15012
+ mintPubkeys.push(mint);
15013
+ return {
15014
+ owner,
15015
+ pubkey,
15016
+ mint,
15017
+ amount: amount.toString(),
15018
+ frozen: state !== 1
15019
+ };
15020
+ };
15021
+ // Parse token accounts
15022
+ const partialTokenAccounts = tokenAccounts.value.map(({ pubkey, account })=>({
15023
+ ...parseTokenAccountInfo(pubkey, account),
15024
+ programId: splToken.TOKEN_PROGRAM_ID
15025
+ })).concat(token2022Accounts.value.map(({ pubkey, account })=>({
15026
+ ...parseTokenAccountInfo(pubkey, account),
15027
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15028
+ })));
15029
+ // Get mint decimals
15030
+ const mintDecimalMap = new Map();
15031
+ const mintAccountsInfo = await connection.getMultipleAccountsInfo(mintPubkeys);
15032
+ mintAccountsInfo.forEach((accountInfo, i)=>{
15033
+ if (accountInfo) {
15034
+ const mint = splToken.unpackMint(mintPubkeys[i], accountInfo, accountInfo.owner);
15035
+ mintDecimalMap.set(mintPubkeys[i].toBase58(), mint.decimals);
15036
+ }
15037
+ });
15038
+ // Enrich token accounts with decimals and uiAmount
15039
+ return partialTokenAccounts.map((ta)=>{
15040
+ const decimals = mintDecimalMap.get(ta.mint.toBase58());
15041
+ if (!decimals) {
15042
+ return null;
15043
+ }
15044
+ return {
15045
+ ...ta,
15046
+ decimals,
15047
+ uiAmount: Number(ta.amount) / 10 ** decimals
15048
+ };
15049
+ }).filter((ta)=>ta !== null);
15050
+ }
15051
+ async function getSolAndTokenBalances(connection, owner) {
15052
+ const balanceLamports = await connection.getBalance(owner);
15053
+ const tokenAccounts = await getTokenAccountsByOwner(connection, owner);
15054
+ const uiAmount = balanceLamports / web3_js.LAMPORTS_PER_SOL;
15055
+ return {
15056
+ balanceLamports,
15057
+ uiAmount,
15058
+ tokenAccounts
15059
+ };
15060
+ }
14988
15061
  const findStakeAccounts = async (connection, withdrawAuthority)=>{
14989
15062
  // stake authority offset: 12
14990
15063
  // withdraw authority offset: 44
@@ -15203,7 +15276,7 @@ STAKE_POOLS.push({
15203
15276
  symbol: "PSOL",
15204
15277
  mint: "pSo1f9nQXWgXibFtKf7NWYxb5enAM4qfP6UJSiXRQfL",
15205
15278
  decimals: 9,
15206
- logoURI: "https://assets.phantom.app/assets/metadata/PSOL-512.png",
15279
+ logoURI: "https://coin-images.coingecko.com/coins/images/55849/large/PSOL.png",
15207
15280
  tokenProgram: splToken.TOKEN_PROGRAM_ID,
15208
15281
  poolState: new web3_js.PublicKey("pSPcvR8GmG9aKDUbn9nbKYjkxt9hxMS7kF1qqKJaPqJ")
15209
15282
  });
@@ -15284,6 +15357,15 @@ const ASSETS_MAINNET = new Map([
15284
15357
  oracle: new web3_js.PublicKey("9PgHM68FNGDK6nHb29ERDBcFrV6gNMD8LyUqwxbyyeb2")
15285
15358
  }
15286
15359
  ],
15360
+ [
15361
+ // USDG
15362
+ "2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH",
15363
+ {
15364
+ decimals: 6,
15365
+ oracle: new web3_js.PublicKey("6JkZmXGgWnzsyTQaqRARzP64iFYnpMNT4siiuUDUaB8s"),
15366
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15367
+ }
15368
+ ],
15287
15369
  [
15288
15370
  // PYUSD
15289
15371
  "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
@@ -15507,12 +15589,6 @@ const LOOKUP_TABLES = [
15507
15589
  new web3_js.PublicKey("D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c"),
15508
15590
  new web3_js.PublicKey("EiWSskK5HXnBTptiS5DH6gpAJRVNQ3cAhTKBGaiaysAb")
15509
15591
  ];
15510
- const STATES_LOOKUP_TABLES_MAP = new Map([
15511
- [
15512
- "3tfbxaHBDjczQo3eyNJGGG64ChZ9nG4V3Gywa4k59d5a",
15513
- new web3_js.PublicKey("8HUXT9abWS2z3z92QyDzg51nMcc18LyWFvaEQZJMPixu")
15514
- ]
15515
- ]);
15516
15592
  const isBrowser = process.env.ANCHOR_BROWSER || typeof window !== "undefined" && !window.process?.hasOwnProperty("type");
15517
15593
  class BaseClient {
15518
15594
  get detectedCluster() {
@@ -15601,17 +15677,16 @@ class BaseClient {
15601
15677
  if (glamApi) {
15602
15678
  const response = await fetch(`${glamApi}/v0/lut/glam/?state=${this.statePda}`);
15603
15679
  const data = await response.json();
15604
- const { t: lookupTables } = data;
15605
- const pubkeys = Object.keys(lookupTables);
15606
- if (pubkeys.length > 0) {
15607
- return await this.fetchAdressLookupTableAccounts(pubkeys);
15680
+ const lookupTables = data.t || {};
15681
+ const lookupTableAccounts = [];
15682
+ for (const [key, lookupTableData] of Object.entries(lookupTables)){
15683
+ const account = new web3_js.AddressLookupTableAccount({
15684
+ key: new web3_js.PublicKey(key),
15685
+ state: web3_js.AddressLookupTableAccount.deserialize(new Uint8Array(Buffer.from(lookupTableData, "base64")))
15686
+ });
15687
+ lookupTableAccounts.push(account);
15608
15688
  }
15609
- }
15610
- const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
15611
- if (tablePubkey) {
15612
- return await this.fetchAdressLookupTableAccounts([
15613
- tablePubkey
15614
- ]);
15689
+ return lookupTableAccounts;
15615
15690
  }
15616
15691
  // Fetch all accounts owned by the ALT program
15617
15692
  // This is very likely to hit the RPC error "Request deprioritized due to number of accounts requested. Slow down requests or add filters to narrow down results"
@@ -15660,17 +15735,35 @@ class BaseClient {
15660
15735
  }
15661
15736
  const lookupTableAccounts = [];
15662
15737
  if (lookupTables.every((t)=>t instanceof web3_js.AddressLookupTableAccount)) {
15663
- const accounts = await this.fetchAdressLookupTableAccounts([
15738
+ const accounts = await this.fetchAddressLookupTableAccounts([
15664
15739
  ...LOOKUP_TABLES
15665
15740
  ]);
15666
15741
  lookupTableAccounts.push(...lookupTables, ...accounts);
15667
15742
  } else {
15668
- const accounts = await this.fetchAdressLookupTableAccounts([
15743
+ const accounts = await this.fetchAddressLookupTableAccounts([
15669
15744
  ...lookupTables,
15670
15745
  ...LOOKUP_TABLES
15671
15746
  ]);
15672
15747
  lookupTableAccounts.push(...accounts);
15673
15748
  }
15749
+ const glamApi = process.env.NEXT_PUBLIC_GLAM_API || process.env.GLAM_API;
15750
+ if (glamApi) {
15751
+ try {
15752
+ const response = await fetch(`${glamApi}/v0/lut/glam/?state=${this.statePda}`);
15753
+ const data = await response.json();
15754
+ const lookupTables = data.t || {};
15755
+ for (const [key, lookupTableData] of Object.entries(lookupTables)){
15756
+ const account = new web3_js.AddressLookupTableAccount({
15757
+ key: new web3_js.PublicKey(key),
15758
+ state: web3_js.AddressLookupTableAccount.deserialize(new Uint8Array(Buffer.from(lookupTableData, "base64")))
15759
+ });
15760
+ lookupTableAccounts.push(account);
15761
+ }
15762
+ } catch (e) {
15763
+ console.error("Failed to fetch lookup tables:", e); // Fail open
15764
+ }
15765
+ }
15766
+ console.log("lookupTableAccounts:", lookupTableAccounts.map((t)=>t.key.toBase58()));
15674
15767
  const recentBlockhash = (await this.blockhashWithCache.get()).blockhash;
15675
15768
  const { unitsConsumed, error, serializedTx } = await getSimulationResult(this.provider.connection, instructions, signer, lookupTableAccounts);
15676
15769
  computeUnitLimit = unitsConsumed;
@@ -15749,7 +15842,7 @@ class BaseClient {
15749
15842
  *
15750
15843
  * @param pubkeys Array of lookup table public keys.
15751
15844
  * @returns
15752
- */ async fetchAdressLookupTableAccounts(pubkeys) {
15845
+ */ async fetchAddressLookupTableAccounts(pubkeys) {
15753
15846
  if (!pubkeys) {
15754
15847
  throw new Error("addressLookupTableAddresses is undefined");
15755
15848
  }
@@ -19762,176 +19855,6 @@ const DEFAULT_OBLIGATION_ARGS = {
19762
19855
  id: 0
19763
19856
  };
19764
19857
  const EVENT_AUTHORITY$1 = new web3_js.PublicKey("24tHwQyJJ9akVXxnvkekGfAoeUJXXS7mE6kQNioNySsK");
19765
- function refreshObligation(accounts, programId = KAMINO_LENDING_PROGRAM) {
19766
- const keys = [
19767
- {
19768
- pubkey: accounts.lendingMarket,
19769
- isSigner: false,
19770
- isWritable: false
19771
- },
19772
- {
19773
- pubkey: accounts.obligation,
19774
- isSigner: false,
19775
- isWritable: true
19776
- }
19777
- ];
19778
- accounts.reserves.forEach((reserve)=>{
19779
- keys.push({
19780
- pubkey: reserve,
19781
- isSigner: false,
19782
- isWritable: false
19783
- });
19784
- });
19785
- const identifier = Buffer.from([
19786
- 33,
19787
- 132,
19788
- 147,
19789
- 228,
19790
- 151,
19791
- 192,
19792
- 72,
19793
- 89
19794
- ]);
19795
- const data = identifier;
19796
- const ix = new web3_js.TransactionInstruction({
19797
- keys,
19798
- programId,
19799
- data
19800
- });
19801
- return ix;
19802
- }
19803
- function refreshReserve(accounts, programId = KAMINO_LENDING_PROGRAM) {
19804
- const keys = [
19805
- {
19806
- pubkey: accounts.reserve,
19807
- isSigner: false,
19808
- isWritable: true
19809
- },
19810
- {
19811
- pubkey: accounts.lendingMarket,
19812
- isSigner: false,
19813
- isWritable: false
19814
- },
19815
- {
19816
- pubkey: accounts.pythOracle,
19817
- isSigner: false,
19818
- isWritable: false
19819
- },
19820
- {
19821
- pubkey: accounts.switchboardPriceOracle,
19822
- isSigner: false,
19823
- isWritable: false
19824
- },
19825
- {
19826
- pubkey: accounts.switchboardTwapOracle,
19827
- isSigner: false,
19828
- isWritable: false
19829
- },
19830
- {
19831
- pubkey: accounts.scopePrices,
19832
- isSigner: false,
19833
- isWritable: false
19834
- }
19835
- ];
19836
- const identifier = Buffer.from([
19837
- 2,
19838
- 218,
19839
- 138,
19840
- 235,
19841
- 79,
19842
- 201,
19843
- 25,
19844
- 102
19845
- ]);
19846
- const data = identifier;
19847
- const ix = new web3_js.TransactionInstruction({
19848
- keys,
19849
- programId,
19850
- data
19851
- });
19852
- return ix;
19853
- }
19854
- function refreshObligationFarmsForReserve(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
19855
- const keys = [
19856
- {
19857
- pubkey: accounts.crank,
19858
- isSigner: true,
19859
- isWritable: false
19860
- },
19861
- {
19862
- pubkey: accounts.baseAccounts.obligation,
19863
- isSigner: false,
19864
- isWritable: false
19865
- },
19866
- {
19867
- pubkey: accounts.baseAccounts.lendingMarketAuthority,
19868
- isSigner: false,
19869
- isWritable: true
19870
- },
19871
- {
19872
- pubkey: accounts.baseAccounts.reserve,
19873
- isSigner: false,
19874
- isWritable: false
19875
- },
19876
- {
19877
- pubkey: accounts.baseAccounts.reserveFarmState,
19878
- isSigner: false,
19879
- isWritable: true
19880
- },
19881
- {
19882
- pubkey: accounts.baseAccounts.obligationFarmUserState,
19883
- isSigner: false,
19884
- isWritable: true
19885
- },
19886
- {
19887
- pubkey: accounts.baseAccounts.lendingMarket,
19888
- isSigner: false,
19889
- isWritable: false
19890
- },
19891
- {
19892
- pubkey: accounts.farmsProgram,
19893
- isSigner: false,
19894
- isWritable: false
19895
- },
19896
- {
19897
- pubkey: accounts.rent,
19898
- isSigner: false,
19899
- isWritable: false
19900
- },
19901
- {
19902
- pubkey: accounts.systemProgram,
19903
- isSigner: false,
19904
- isWritable: false
19905
- }
19906
- ];
19907
- const identifier = Buffer.from([
19908
- 140,
19909
- 144,
19910
- 253,
19911
- 21,
19912
- 10,
19913
- 74,
19914
- 248,
19915
- 3
19916
- ]);
19917
- const buffer = Buffer.alloc(1000);
19918
- const layout = borsh__namespace.struct([
19919
- borsh__namespace.u8("mode")
19920
- ]);
19921
- const len = layout.encode({
19922
- mode: args.mode
19923
- }, buffer);
19924
- const data = Buffer.concat([
19925
- identifier,
19926
- buffer
19927
- ]).subarray(0, 8 + len);
19928
- const ix = new web3_js.TransactionInstruction({
19929
- keys,
19930
- programId,
19931
- data
19932
- });
19933
- return ix;
19934
- }
19935
19858
  class KaminoLendingClient {
19936
19859
  /**
19937
19860
  * Initializes Kamino user metadata
@@ -20023,8 +19946,228 @@ class KaminoLendingClient {
20023
19946
  ], KAMINO_FARM_PROGRAM);
20024
19947
  return obligationFarm;
20025
19948
  }
19949
+ refreshObligationIx(accounts, programId = KAMINO_LENDING_PROGRAM) {
19950
+ const keys = [
19951
+ {
19952
+ pubkey: accounts.lendingMarket,
19953
+ isSigner: false,
19954
+ isWritable: false
19955
+ },
19956
+ {
19957
+ pubkey: accounts.obligation,
19958
+ isSigner: false,
19959
+ isWritable: true
19960
+ }
19961
+ ];
19962
+ accounts.reserves.forEach((reserve)=>{
19963
+ keys.push({
19964
+ pubkey: reserve,
19965
+ isSigner: false,
19966
+ isWritable: false
19967
+ });
19968
+ });
19969
+ const identifier = Buffer.from([
19970
+ 33,
19971
+ 132,
19972
+ 147,
19973
+ 228,
19974
+ 151,
19975
+ 192,
19976
+ 72,
19977
+ 89
19978
+ ]);
19979
+ const data = identifier;
19980
+ return new web3_js.TransactionInstruction({
19981
+ keys,
19982
+ programId,
19983
+ data
19984
+ });
19985
+ }
19986
+ refreshReserveIx(accounts, programId = KAMINO_LENDING_PROGRAM) {
19987
+ const keys = [
19988
+ {
19989
+ pubkey: accounts.reserve,
19990
+ isSigner: false,
19991
+ isWritable: true
19992
+ },
19993
+ {
19994
+ pubkey: accounts.lendingMarket,
19995
+ isSigner: false,
19996
+ isWritable: false
19997
+ },
19998
+ {
19999
+ pubkey: accounts.pythOracle,
20000
+ isSigner: false,
20001
+ isWritable: false
20002
+ },
20003
+ {
20004
+ pubkey: accounts.switchboardPriceOracle,
20005
+ isSigner: false,
20006
+ isWritable: false
20007
+ },
20008
+ {
20009
+ pubkey: accounts.switchboardTwapOracle,
20010
+ isSigner: false,
20011
+ isWritable: false
20012
+ },
20013
+ {
20014
+ pubkey: accounts.scopePrices,
20015
+ isSigner: false,
20016
+ isWritable: false
20017
+ }
20018
+ ];
20019
+ const identifier = Buffer.from([
20020
+ 2,
20021
+ 218,
20022
+ 138,
20023
+ 235,
20024
+ 79,
20025
+ 201,
20026
+ 25,
20027
+ 102
20028
+ ]);
20029
+ const data = identifier;
20030
+ return new web3_js.TransactionInstruction({
20031
+ keys,
20032
+ programId,
20033
+ data
20034
+ });
20035
+ }
20036
+ refreshObligationFarmsForReserveIx(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
20037
+ const keys = [
20038
+ {
20039
+ pubkey: accounts.crank,
20040
+ isSigner: true,
20041
+ isWritable: false
20042
+ },
20043
+ {
20044
+ pubkey: accounts.baseAccounts.obligation,
20045
+ isSigner: false,
20046
+ isWritable: false
20047
+ },
20048
+ {
20049
+ pubkey: accounts.baseAccounts.lendingMarketAuthority,
20050
+ isSigner: false,
20051
+ isWritable: true
20052
+ },
20053
+ {
20054
+ pubkey: accounts.baseAccounts.reserve,
20055
+ isSigner: false,
20056
+ isWritable: false
20057
+ },
20058
+ {
20059
+ pubkey: accounts.baseAccounts.reserveFarmState,
20060
+ isSigner: false,
20061
+ isWritable: true
20062
+ },
20063
+ {
20064
+ pubkey: accounts.baseAccounts.obligationFarmUserState,
20065
+ isSigner: false,
20066
+ isWritable: true
20067
+ },
20068
+ {
20069
+ pubkey: accounts.baseAccounts.lendingMarket,
20070
+ isSigner: false,
20071
+ isWritable: false
20072
+ },
20073
+ {
20074
+ pubkey: accounts.farmsProgram,
20075
+ isSigner: false,
20076
+ isWritable: false
20077
+ },
20078
+ {
20079
+ pubkey: accounts.rent,
20080
+ isSigner: false,
20081
+ isWritable: false
20082
+ },
20083
+ {
20084
+ pubkey: accounts.systemProgram,
20085
+ isSigner: false,
20086
+ isWritable: false
20087
+ }
20088
+ ];
20089
+ const identifier = Buffer.from([
20090
+ 140,
20091
+ 144,
20092
+ 253,
20093
+ 21,
20094
+ 10,
20095
+ 74,
20096
+ 248,
20097
+ 3
20098
+ ]);
20099
+ const buffer = Buffer.alloc(1000);
20100
+ const layout = borsh__namespace.struct([
20101
+ borsh__namespace.u8("mode")
20102
+ ]);
20103
+ const len = layout.encode({
20104
+ mode: args.mode
20105
+ }, buffer);
20106
+ const data = Buffer.concat([
20107
+ identifier,
20108
+ buffer
20109
+ ]).subarray(0, 8 + len);
20110
+ return new web3_js.TransactionInstruction({
20111
+ keys,
20112
+ programId,
20113
+ data
20114
+ });
20115
+ }
20116
+ refreshReservesBatchIx(reserves, lendingMarkets, skipPriceUpdates, programId = KAMINO_LENDING_PROGRAM) {
20117
+ const keys = [];
20118
+ for(let i = 0; i < reserves.length; i++){
20119
+ keys.push({
20120
+ pubkey: reserves[i],
20121
+ isSigner: false,
20122
+ isWritable: false
20123
+ });
20124
+ keys.push({
20125
+ pubkey: lendingMarkets[i],
20126
+ isSigner: false,
20127
+ isWritable: true
20128
+ });
20129
+ if (!skipPriceUpdates) {
20130
+ [
20131
+ KAMINO_LENDING_PROGRAM,
20132
+ KAMINO_LENDING_PROGRAM,
20133
+ KAMINO_LENDING_PROGRAM,
20134
+ KAMINO_SCOPE_PRICES
20135
+ ].forEach((p)=>keys.push({
20136
+ pubkey: p,
20137
+ isSigner: false,
20138
+ isWritable: false
20139
+ }));
20140
+ }
20141
+ }
20142
+ const identifier = Buffer.from([
20143
+ 144,
20144
+ 110,
20145
+ 26,
20146
+ 103,
20147
+ 162,
20148
+ 204,
20149
+ 252,
20150
+ 147
20151
+ ]);
20152
+ const buffer = Buffer.alloc(1000);
20153
+ const layout = borsh__namespace.struct([
20154
+ borsh__namespace.bool("skipPriceUpdates")
20155
+ ]);
20156
+ const len = layout.encode({
20157
+ skipPriceUpdates
20158
+ }, buffer);
20159
+ const data = Buffer.concat([
20160
+ identifier,
20161
+ buffer
20162
+ ]).subarray(0, 8 + len);
20163
+ return new web3_js.TransactionInstruction({
20164
+ keys,
20165
+ programId,
20166
+ data
20167
+ });
20168
+ }
20026
20169
  refreshReserveIxs(lendingMarket, reserves) {
20027
- return reserves.map((reserve)=>refreshReserve({
20170
+ return reserves.map((reserve)=>this.refreshReserveIx({
20028
20171
  reserve,
20029
20172
  lendingMarket,
20030
20173
  pythOracle: KAMINO_LENDING_PROGRAM,
@@ -20040,7 +20183,7 @@ class KaminoLendingClient {
20040
20183
  farmCollateral
20041
20184
  ].filter((farm)=>!!farm).map((farm)=>{
20042
20185
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20043
- return refreshObligationFarmsForReserve({
20186
+ return this.refreshObligationFarmsForReserveIx({
20044
20187
  mode: 0
20045
20188
  }, {
20046
20189
  crank: this.base.getSigner(),
@@ -20066,7 +20209,7 @@ class KaminoLendingClient {
20066
20209
  farmDebt
20067
20210
  ].filter((farm)=>!!farm).map((farm)=>{
20068
20211
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20069
- return refreshObligationFarmsForReserve({
20212
+ return this.refreshObligationFarmsForReserveIx({
20070
20213
  mode: 0
20071
20214
  }, {
20072
20215
  crank: this.base.getSigner(),
@@ -20352,7 +20495,7 @@ class KaminoLendingClient {
20352
20495
  // Refresh reserves, including deposit reserve and reserves in use
20353
20496
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20354
20497
  // Refresh obligation with reserves in use
20355
- preInstructions.push(refreshObligation({
20498
+ preInstructions.push(this.refreshObligationIx({
20356
20499
  lendingMarket: market,
20357
20500
  obligation,
20358
20501
  reserves: reservesInUse
@@ -20442,7 +20585,7 @@ class KaminoLendingClient {
20442
20585
  // Refresh reserves, including deposit reserve and reserves in use
20443
20586
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20444
20587
  // Refresh obligation with reserves in use
20445
- preInstructions.push(refreshObligation({
20588
+ preInstructions.push(this.refreshObligationIx({
20446
20589
  lendingMarket: market,
20447
20590
  obligation,
20448
20591
  reserves: reservesInUse
@@ -20526,7 +20669,7 @@ class KaminoLendingClient {
20526
20669
  // Refresh reserves, including deposit reserve and reserves in use
20527
20670
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20528
20671
  // Refresh obligation with reserves in use
20529
- preInstructions.push(refreshObligation({
20672
+ preInstructions.push(this.refreshObligationIx({
20530
20673
  lendingMarket: market,
20531
20674
  obligation,
20532
20675
  reserves: reservesInUse
@@ -20608,7 +20751,7 @@ class KaminoLendingClient {
20608
20751
  // Refresh reserves, including deposit reserve and reserves in use
20609
20752
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20610
20753
  // Refresh obligation with reserves in use
20611
- preInstructions.push(refreshObligation({
20754
+ preInstructions.push(this.refreshObligationIx({
20612
20755
  lendingMarket: market,
20613
20756
  obligation,
20614
20757
  reserves: reservesInUse
@@ -20811,7 +20954,7 @@ class KaminoVaultsClient {
20811
20954
  if (this.vaultStates.size === 0) {
20812
20955
  await this.findAndParseKaminoVaults();
20813
20956
  }
20814
- return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58()));
20957
+ return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58())).filter((p)=>!!p);
20815
20958
  }
20816
20959
  async fetchAndParseVaultState(vault) {
20817
20960
  const vaultAccount = await this.base.provider.connection.getAccountInfo(vault);
@@ -20824,9 +20967,7 @@ class KaminoVaultsClient {
20824
20967
  return vaultState;
20825
20968
  }
20826
20969
  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));
20970
+ const reserves = allocationStrategies.map((strategy)=>strategy.reserve);
20830
20971
  const parsedReserves = await this.kaminoLending.fetchAndParseReserves(reserves);
20831
20972
  const reserveMetas = reserves.map((pubkey)=>({
20832
20973
  pubkey,
@@ -21368,6 +21509,21 @@ class InvestClient {
21368
21509
  }
21369
21510
 
21370
21511
  class PriceClient {
21512
+ get stateModel() {
21513
+ if (!this._stateModel) {
21514
+ throw new Error("State model not cached");
21515
+ }
21516
+ return this._stateModel;
21517
+ }
21518
+ set stateModel(stateModel) {
21519
+ this._stateModel = stateModel;
21520
+ }
21521
+ get lookupTables() {
21522
+ return Array.from(this._lookupTables).map((k)=>new web3_js.PublicKey(k));
21523
+ }
21524
+ get kaminoVaults() {
21525
+ return Array.from(this._kaminoVaults).map((k)=>new web3_js.PublicKey(k));
21526
+ }
21371
21527
  /**
21372
21528
  * !! This is a convenience method that calculates the AUM of the vault based on priced assets.
21373
21529
  * !! It doesn't reflect the actual AUM of the vault.
@@ -21411,7 +21567,7 @@ class PriceClient {
21411
21567
  async priceKaminoVaultSharesIx(priceDenom) {
21412
21568
  const allKvaultStates = await this.kvaults.findAndParseKaminoVaults();
21413
21569
  const allKvaultMints = allKvaultStates.map((kvault)=>kvault.sharesMint);
21414
- // All share token accounts GLAM vault could possibly hold
21570
+ // All kvaut share token accounts GLAM vault could possibly hold
21415
21571
  const possibleShareAtas = allKvaultMints.map((mint)=>this.base.getVaultAta(mint));
21416
21572
  const possibleShareAtaAccountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(possibleShareAtas);
21417
21573
  const shareAtas = [];
@@ -21419,16 +21575,24 @@ class PriceClient {
21419
21575
  const kvaultStates = [];
21420
21576
  const oracles = []; // oracle of kvault deposit token
21421
21577
  possibleShareAtaAccountsInfo.forEach((info, i)=>{
21422
- if (info !== null) {
21578
+ // share ata must exist and it must be tracked by glam state
21579
+ // otherwise skip it for pricing
21580
+ if (info !== null && this.stateModel.externalVaultAccounts?.find((a)=>a.equals(possibleShareAtas[i]))) {
21423
21581
  shareAtas.push(possibleShareAtas[i]);
21424
21582
  shareMints.push(allKvaultMints[i]);
21425
21583
  kvaultStates.push(allKvaultStates[i]);
21426
- const { tokenMint } = allKvaultStates[i];
21584
+ // get oracle and lookup table from kvault state
21585
+ const { tokenMint, vaultLookupTable } = allKvaultStates[i];
21427
21586
  const assetMeta = ASSETS_MAINNET.get(tokenMint.toBase58());
21428
- oracles.push(assetMeta?.oracle);
21587
+ if (!assetMeta || !assetMeta.oracle) {
21588
+ throw new Error(`Oracle unavailable for asset ${tokenMint}`);
21589
+ }
21590
+ oracles.push(assetMeta.oracle);
21591
+ this._lookupTables.add(vaultLookupTable.toBase58()); // cache lookup table
21429
21592
  }
21430
21593
  });
21431
21594
  const kvaultPdas = await this.kvaults.getVaultPdasByShareMints(shareMints);
21595
+ kvaultPdas.forEach((p)=>this._kaminoVaults.add(p.toBase58())); // cache kvault keys
21432
21596
  const remainingAccounts = [];
21433
21597
  // first 3N remaining accounts are N tuples of (kvault_shares_ata, kvault_shares_mint, kvault_state)
21434
21598
  for(let i = 0; i < shareAtas.length; i++){
@@ -21439,26 +21603,44 @@ class PriceClient {
21439
21603
  oracles[i]
21440
21604
  ].map((pubkey)=>{
21441
21605
  remainingAccounts.push({
21442
- pubkey,
21606
+ pubkey: pubkey,
21443
21607
  isSigner: false,
21444
21608
  isWritable: false
21445
21609
  });
21446
21610
  });
21447
21611
  }
21448
- // markets and reserves
21449
21612
  const marketsAndReserves = (await Promise.all(kvaultStates.map((kvault)=>{
21450
21613
  return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)), true);
21451
21614
  }))).flat();
21452
- remainingAccounts.push(...marketsAndReserves);
21615
+ const processed = new Set();
21616
+ const reserves = [];
21617
+ const markets = [];
21618
+ const chunkSize = 2;
21619
+ for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
21620
+ const chunk = marketsAndReserves.slice(i, i + chunkSize);
21621
+ const market = chunk[0].pubkey;
21622
+ const reserve = chunk[1].pubkey;
21623
+ // reserve should always be added to remaining accounts
21624
+ remainingAccounts.push(chunk[1]);
21625
+ // record reserves and markets for refreshReservesBatchIx
21626
+ if (!processed.has(reserve.toBase58())) {
21627
+ reserves.push(reserve);
21628
+ markets.push(market);
21629
+ processed.add(reserve.toBase58());
21630
+ }
21631
+ }
21632
+ const refreshReservesIx = this.klend.refreshReservesBatchIx(reserves, markets, false);
21633
+ const preInstructions = [
21634
+ refreshReservesIx
21635
+ ];
21453
21636
  const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
21454
21637
  glamState: this.base.statePda,
21455
- solOracle: SOL_ORACLE,
21456
- pythOracle: null,
21457
- switchboardPriceOracle: null,
21458
- switchboardTwapOracle: null,
21459
- scopePrices: KAMINO_SCOPE_PRICES
21638
+ solOracle: SOL_ORACLE
21460
21639
  }).remainingAccounts(remainingAccounts).instruction();
21461
- return priceIx;
21640
+ return [
21641
+ ...preInstructions,
21642
+ priceIx
21643
+ ];
21462
21644
  }
21463
21645
  /**
21464
21646
  * Returns an instruction that prices all Drift users (aka sub-accounts) controlled by the GLAM vault.
@@ -21526,43 +21708,8 @@ class PriceClient {
21526
21708
  if (parsedVaultDepositors.length === 0) {
21527
21709
  return null;
21528
21710
  }
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({
21711
+ const { remainingAccounts, numSpotMarkets, numPerpMarkets } = await this.remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors);
21712
+ const priceIx = await this.base.program.methods.priceDriftVaultDepositors(priceDenom, parsedVaultDepositors.length, numSpotMarkets, numPerpMarkets).accounts({
21566
21713
  glamState: this.base.statePda,
21567
21714
  solOracle: SOL_ORACLE
21568
21715
  }).remainingAccounts(remainingAccounts).instruction();
@@ -21622,7 +21769,8 @@ class PriceClient {
21622
21769
  }
21623
21770
  // If there are no external assets, we don't need to price DeFi positions
21624
21771
  const stateModel = await this.base.fetchStateModel();
21625
- if ((stateModel.externalVaultAccounts || []).length === 0) {
21772
+ this.stateModel = stateModel;
21773
+ if ((this.stateModel.externalVaultAccounts || []).length === 0) {
21626
21774
  return [
21627
21775
  priceVaultIx
21628
21776
  ];
@@ -21642,72 +21790,133 @@ class PriceClient {
21642
21790
  ];
21643
21791
  for (const fn of pricingFns){
21644
21792
  const ix = await fn(priceDenom);
21645
- pricingIxs.push(ix);
21793
+ if (Array.isArray(ix)) {
21794
+ pricingIxs.push(...ix);
21795
+ } else {
21796
+ pricingIxs.push(ix);
21797
+ }
21646
21798
  }
21647
21799
  return pricingIxs.filter(Boolean);
21648
21800
  }
21649
- constructor(base, klend, kvaults, drift, dvaults){
21650
- this.base = base;
21651
- this.klend = klend;
21652
- this.kvaults = kvaults;
21653
- this.drift = drift;
21654
- 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
- }));
21801
+ async remainingAccountsForPricingDriftVaultDepositors(parsedVaultDepositors) {
21802
+ // Extra accounts for pricing N vault depositors:
21803
+ // - (vault_depositor, drift_vault, drift_user) x N
21804
+ // - spot_market used by drift users of vaults (no specific order)
21805
+ // - perp markets used by drift users of vaults (no specific order)
21806
+ // - oracles of spot markets and perp markets (no specific order)
21807
+ const remainingAccounts = [];
21808
+ const spotMarketsSet = new Set();
21809
+ const perpMarketsSet = new Set();
21810
+ const oraclesSet = new Set();
21811
+ for (const { address: depositor, driftVault } of parsedVaultDepositors){
21812
+ const { user } = await this.dvaults.parseDriftVault(driftVault); // get drift user used by the vault
21813
+ [
21814
+ depositor,
21815
+ driftVault,
21816
+ user
21817
+ ].forEach((k)=>remainingAccounts.push({
21818
+ pubkey: k,
21819
+ isSigner: false,
21820
+ isWritable: false
21821
+ }));
21822
+ const { spotPositions, perpPositions } = await this.dvaults.fetchUserPositions(user);
21823
+ const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
21824
+ const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
21825
+ // If there are perp positions, add spot market 0 as it's used as quote market for perp
21826
+ if (perpMarketIndexes.length > 0 && !spotMarketIndexes.includes(0)) {
21827
+ spotMarketIndexes.push(0);
21828
+ }
21829
+ const spotMarkets = await this.drift.fetchAndParseSpotMarkets(spotMarketIndexes);
21830
+ const perpMarkets = await this.drift.fetchAndParsePerpMarkets(perpMarketIndexes);
21831
+ spotMarkets.forEach((m)=>{
21832
+ oraclesSet.add(m.oracle.toBase58());
21833
+ spotMarketsSet.add(m.marketPda.toBase58());
21834
+ });
21835
+ perpMarkets.forEach((m)=>{
21836
+ oraclesSet.add(m.oracle.toBase58());
21837
+ perpMarketsSet.add(m.marketPda.toBase58());
21838
+ });
21839
+ }
21840
+ [
21841
+ ...spotMarketsSet,
21842
+ ...perpMarketsSet,
21843
+ ...oraclesSet
21844
+ ].forEach((k)=>remainingAccounts.push({
21845
+ pubkey: new web3_js.PublicKey(k),
21846
+ isSigner: false,
21847
+ isWritable: false
21671
21848
  }));
21672
- return chunks.flat();
21849
+ return {
21850
+ remainingAccounts,
21851
+ numSpotMarkets: spotMarketsSet.size,
21852
+ numPerpMarkets: perpMarketsSet.size
21673
21853
  };
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
- }));
21854
+ }
21855
+ async remainingAccountsForPricingMeteora() {
21856
+ const positions = await fetchMeteoraPositions(this.base.provider.connection, this.base.vaultPda);
21857
+ let chunks = await Promise.all(positions.map(async (pubkey)=>{
21858
+ const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
21859
+ return [
21860
+ pubkey,
21861
+ lbPair,
21862
+ binArrayLower,
21863
+ binArrayUpper,
21864
+ SOL_ORACLE,
21865
+ USDC_ORACLE
21866
+ ].map((k)=>({
21867
+ pubkey: k,
21868
+ isSigner: false,
21869
+ isWritable: false
21870
+ }));
21871
+ }));
21872
+ return chunks.flat();
21873
+ }
21874
+ async remainingAccountsForPricingVaultAssets(baseAssetOnly = false) {
21875
+ const stateModel = await this.base.fetchStateModel();
21876
+ if (baseAssetOnly) {
21877
+ if (!stateModel.baseAsset) {
21878
+ throw new Error("Base asset not configured for the vault");
21692
21879
  }
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,
21880
+ // FIXME: support token 2022 base asset
21881
+ const ata = this.base.getVaultAta(stateModel.baseAsset);
21882
+ // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
21883
+ return [
21884
+ ata,
21885
+ stateModel.baseAsset,
21886
+ web3_js.PublicKey.default
21887
+ ].map((k)=>({
21888
+ pubkey: k,
21707
21889
  isSigner: false,
21708
21890
  isWritable: false
21709
21891
  }));
21710
- };
21892
+ }
21893
+ const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
21894
+ return assetsForPricing.map((mint)=>{
21895
+ const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
21896
+ if (!assetMeta) {
21897
+ throw new Error(`Asset meta not found for ${mint}`);
21898
+ }
21899
+ const ata = this.base.getVaultAta(mint, assetMeta?.programId);
21900
+ return [
21901
+ ata,
21902
+ mint,
21903
+ assetMeta?.oracle
21904
+ ];
21905
+ }).flat().map((a)=>({
21906
+ pubkey: a,
21907
+ isSigner: false,
21908
+ isWritable: false
21909
+ }));
21910
+ }
21911
+ constructor(base, klend, kvaults, drift, dvaults){
21912
+ this.base = base;
21913
+ this.klend = klend;
21914
+ this.kvaults = kvaults;
21915
+ this.drift = drift;
21916
+ this.dvaults = dvaults;
21917
+ this._stateModel = null;
21918
+ this._lookupTables = new Set();
21919
+ this._kaminoVaults = new Set();
21711
21920
  }
21712
21921
  }
21713
21922
 
@@ -22129,8 +22338,10 @@ exports.getOpenfundsPda = getOpenfundsPda;
22129
22338
  exports.getOrderParams = getOrderParams;
22130
22339
  exports.getPriorityFeeEstimate = getPriorityFeeEstimate;
22131
22340
  exports.getSimulationResult = getSimulationResult;
22341
+ exports.getSolAndTokenBalances = getSolAndTokenBalances;
22132
22342
  exports.getStakeAccountsWithStates = getStakeAccountsWithStates;
22133
22343
  exports.getStatePda = getStatePda;
22344
+ exports.getTokenAccountsByOwner = getTokenAccountsByOwner;
22134
22345
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
22135
22346
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
22136
22347
  exports.getVariant = getVariant;