@glamsystems/glam-sdk 0.1.30 → 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
@@ -10025,7 +10025,8 @@ var instructions = [
10025
10025
  ],
10026
10026
  accounts: [
10027
10027
  {
10028
- name: "glam_state"
10028
+ name: "glam_state",
10029
+ writable: true
10029
10030
  },
10030
10031
  {
10031
10032
  name: "glam_vault",
@@ -13572,6 +13573,9 @@ var types = [
13572
13573
  },
13573
13574
  {
13574
13575
  name: "Fulfill"
13576
+ },
13577
+ {
13578
+ name: "ClaimFees"
13575
13579
  }
13576
13580
  ]
13577
13581
  }
@@ -14949,6 +14953,15 @@ class PriceDenom {
14949
14953
  }
14950
14954
  return PriceDenom.ASSET;
14951
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
+ }
14952
14965
  }
14953
14966
  PriceDenom.SOL = {
14954
14967
  sol: {}
@@ -14984,6 +14997,67 @@ var ClusterNetwork = /*#__PURE__*/ function(ClusterNetwork) {
14984
14997
  return ClusterNetwork;
14985
14998
  }({});
14986
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
+ }
14987
15061
  const findStakeAccounts = async (connection, withdrawAuthority)=>{
14988
15062
  // stake authority offset: 12
14989
15063
  // withdraw authority offset: 44
@@ -15202,7 +15276,7 @@ STAKE_POOLS.push({
15202
15276
  symbol: "PSOL",
15203
15277
  mint: "pSo1f9nQXWgXibFtKf7NWYxb5enAM4qfP6UJSiXRQfL",
15204
15278
  decimals: 9,
15205
- logoURI: "https://assets.phantom.app/assets/metadata/PSOL-512.png",
15279
+ logoURI: "https://coin-images.coingecko.com/coins/images/55849/large/PSOL.png",
15206
15280
  tokenProgram: splToken.TOKEN_PROGRAM_ID,
15207
15281
  poolState: new web3_js.PublicKey("pSPcvR8GmG9aKDUbn9nbKYjkxt9hxMS7kF1qqKJaPqJ")
15208
15282
  });
@@ -15283,6 +15357,15 @@ const ASSETS_MAINNET = new Map([
15283
15357
  oracle: new web3_js.PublicKey("9PgHM68FNGDK6nHb29ERDBcFrV6gNMD8LyUqwxbyyeb2")
15284
15358
  }
15285
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
+ ],
15286
15369
  [
15287
15370
  // PYUSD
15288
15371
  "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
@@ -15506,12 +15589,6 @@ const LOOKUP_TABLES = [
15506
15589
  new web3_js.PublicKey("D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c"),
15507
15590
  new web3_js.PublicKey("EiWSskK5HXnBTptiS5DH6gpAJRVNQ3cAhTKBGaiaysAb")
15508
15591
  ];
15509
- const STATES_LOOKUP_TABLES_MAP = new Map([
15510
- [
15511
- "3tfbxaHBDjczQo3eyNJGGG64ChZ9nG4V3Gywa4k59d5a",
15512
- new web3_js.PublicKey("8HUXT9abWS2z3z92QyDzg51nMcc18LyWFvaEQZJMPixu")
15513
- ]
15514
- ]);
15515
15592
  const isBrowser = process.env.ANCHOR_BROWSER || typeof window !== "undefined" && !window.process?.hasOwnProperty("type");
15516
15593
  class BaseClient {
15517
15594
  get detectedCluster() {
@@ -15600,17 +15677,16 @@ class BaseClient {
15600
15677
  if (glamApi) {
15601
15678
  const response = await fetch(`${glamApi}/v0/lut/glam/?state=${this.statePda}`);
15602
15679
  const data = await response.json();
15603
- const { t: lookupTables } = data;
15604
- const pubkeys = Object.keys(lookupTables);
15605
- if (pubkeys.length > 0) {
15606
- return await this.fetchAddressLookupTableAccounts(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);
15607
15688
  }
15608
- }
15609
- const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
15610
- if (tablePubkey) {
15611
- return await this.fetchAddressLookupTableAccounts([
15612
- tablePubkey
15613
- ]);
15689
+ return lookupTableAccounts;
15614
15690
  }
15615
15691
  // Fetch all accounts owned by the ALT program
15616
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"
@@ -15670,6 +15746,24 @@ class BaseClient {
15670
15746
  ]);
15671
15747
  lookupTableAccounts.push(...accounts);
15672
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()));
15673
15767
  const recentBlockhash = (await this.blockhashWithCache.get()).blockhash;
15674
15768
  const { unitsConsumed, error, serializedTx } = await getSimulationResult(this.provider.connection, instructions, signer, lookupTableAccounts);
15675
15769
  computeUnitLimit = unitsConsumed;
@@ -19761,176 +19855,6 @@ const DEFAULT_OBLIGATION_ARGS = {
19761
19855
  id: 0
19762
19856
  };
19763
19857
  const EVENT_AUTHORITY$1 = new web3_js.PublicKey("24tHwQyJJ9akVXxnvkekGfAoeUJXXS7mE6kQNioNySsK");
19764
- function refreshObligation(accounts, programId = KAMINO_LENDING_PROGRAM) {
19765
- const keys = [
19766
- {
19767
- pubkey: accounts.lendingMarket,
19768
- isSigner: false,
19769
- isWritable: false
19770
- },
19771
- {
19772
- pubkey: accounts.obligation,
19773
- isSigner: false,
19774
- isWritable: true
19775
- }
19776
- ];
19777
- accounts.reserves.forEach((reserve)=>{
19778
- keys.push({
19779
- pubkey: reserve,
19780
- isSigner: false,
19781
- isWritable: false
19782
- });
19783
- });
19784
- const identifier = Buffer.from([
19785
- 33,
19786
- 132,
19787
- 147,
19788
- 228,
19789
- 151,
19790
- 192,
19791
- 72,
19792
- 89
19793
- ]);
19794
- const data = identifier;
19795
- const ix = new web3_js.TransactionInstruction({
19796
- keys,
19797
- programId,
19798
- data
19799
- });
19800
- return ix;
19801
- }
19802
- function refreshReserve(accounts, programId = KAMINO_LENDING_PROGRAM) {
19803
- const keys = [
19804
- {
19805
- pubkey: accounts.reserve,
19806
- isSigner: false,
19807
- isWritable: true
19808
- },
19809
- {
19810
- pubkey: accounts.lendingMarket,
19811
- isSigner: false,
19812
- isWritable: false
19813
- },
19814
- {
19815
- pubkey: accounts.pythOracle,
19816
- isSigner: false,
19817
- isWritable: false
19818
- },
19819
- {
19820
- pubkey: accounts.switchboardPriceOracle,
19821
- isSigner: false,
19822
- isWritable: false
19823
- },
19824
- {
19825
- pubkey: accounts.switchboardTwapOracle,
19826
- isSigner: false,
19827
- isWritable: false
19828
- },
19829
- {
19830
- pubkey: accounts.scopePrices,
19831
- isSigner: false,
19832
- isWritable: false
19833
- }
19834
- ];
19835
- const identifier = Buffer.from([
19836
- 2,
19837
- 218,
19838
- 138,
19839
- 235,
19840
- 79,
19841
- 201,
19842
- 25,
19843
- 102
19844
- ]);
19845
- const data = identifier;
19846
- const ix = new web3_js.TransactionInstruction({
19847
- keys,
19848
- programId,
19849
- data
19850
- });
19851
- return ix;
19852
- }
19853
- function refreshObligationFarmsForReserve(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
19854
- const keys = [
19855
- {
19856
- pubkey: accounts.crank,
19857
- isSigner: true,
19858
- isWritable: false
19859
- },
19860
- {
19861
- pubkey: accounts.baseAccounts.obligation,
19862
- isSigner: false,
19863
- isWritable: false
19864
- },
19865
- {
19866
- pubkey: accounts.baseAccounts.lendingMarketAuthority,
19867
- isSigner: false,
19868
- isWritable: true
19869
- },
19870
- {
19871
- pubkey: accounts.baseAccounts.reserve,
19872
- isSigner: false,
19873
- isWritable: false
19874
- },
19875
- {
19876
- pubkey: accounts.baseAccounts.reserveFarmState,
19877
- isSigner: false,
19878
- isWritable: true
19879
- },
19880
- {
19881
- pubkey: accounts.baseAccounts.obligationFarmUserState,
19882
- isSigner: false,
19883
- isWritable: true
19884
- },
19885
- {
19886
- pubkey: accounts.baseAccounts.lendingMarket,
19887
- isSigner: false,
19888
- isWritable: false
19889
- },
19890
- {
19891
- pubkey: accounts.farmsProgram,
19892
- isSigner: false,
19893
- isWritable: false
19894
- },
19895
- {
19896
- pubkey: accounts.rent,
19897
- isSigner: false,
19898
- isWritable: false
19899
- },
19900
- {
19901
- pubkey: accounts.systemProgram,
19902
- isSigner: false,
19903
- isWritable: false
19904
- }
19905
- ];
19906
- const identifier = Buffer.from([
19907
- 140,
19908
- 144,
19909
- 253,
19910
- 21,
19911
- 10,
19912
- 74,
19913
- 248,
19914
- 3
19915
- ]);
19916
- const buffer = Buffer.alloc(1000);
19917
- const layout = borsh__namespace.struct([
19918
- borsh__namespace.u8("mode")
19919
- ]);
19920
- const len = layout.encode({
19921
- mode: args.mode
19922
- }, buffer);
19923
- const data = Buffer.concat([
19924
- identifier,
19925
- buffer
19926
- ]).subarray(0, 8 + len);
19927
- const ix = new web3_js.TransactionInstruction({
19928
- keys,
19929
- programId,
19930
- data
19931
- });
19932
- return ix;
19933
- }
19934
19858
  class KaminoLendingClient {
19935
19859
  /**
19936
19860
  * Initializes Kamino user metadata
@@ -20022,8 +19946,228 @@ class KaminoLendingClient {
20022
19946
  ], KAMINO_FARM_PROGRAM);
20023
19947
  return obligationFarm;
20024
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
+ }
20025
20169
  refreshReserveIxs(lendingMarket, reserves) {
20026
- return reserves.map((reserve)=>refreshReserve({
20170
+ return reserves.map((reserve)=>this.refreshReserveIx({
20027
20171
  reserve,
20028
20172
  lendingMarket,
20029
20173
  pythOracle: KAMINO_LENDING_PROGRAM,
@@ -20039,7 +20183,7 @@ class KaminoLendingClient {
20039
20183
  farmCollateral
20040
20184
  ].filter((farm)=>!!farm).map((farm)=>{
20041
20185
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20042
- return refreshObligationFarmsForReserve({
20186
+ return this.refreshObligationFarmsForReserveIx({
20043
20187
  mode: 0
20044
20188
  }, {
20045
20189
  crank: this.base.getSigner(),
@@ -20065,7 +20209,7 @@ class KaminoLendingClient {
20065
20209
  farmDebt
20066
20210
  ].filter((farm)=>!!farm).map((farm)=>{
20067
20211
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20068
- return refreshObligationFarmsForReserve({
20212
+ return this.refreshObligationFarmsForReserveIx({
20069
20213
  mode: 0
20070
20214
  }, {
20071
20215
  crank: this.base.getSigner(),
@@ -20351,7 +20495,7 @@ class KaminoLendingClient {
20351
20495
  // Refresh reserves, including deposit reserve and reserves in use
20352
20496
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20353
20497
  // Refresh obligation with reserves in use
20354
- preInstructions.push(refreshObligation({
20498
+ preInstructions.push(this.refreshObligationIx({
20355
20499
  lendingMarket: market,
20356
20500
  obligation,
20357
20501
  reserves: reservesInUse
@@ -20441,7 +20585,7 @@ class KaminoLendingClient {
20441
20585
  // Refresh reserves, including deposit reserve and reserves in use
20442
20586
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20443
20587
  // Refresh obligation with reserves in use
20444
- preInstructions.push(refreshObligation({
20588
+ preInstructions.push(this.refreshObligationIx({
20445
20589
  lendingMarket: market,
20446
20590
  obligation,
20447
20591
  reserves: reservesInUse
@@ -20525,7 +20669,7 @@ class KaminoLendingClient {
20525
20669
  // Refresh reserves, including deposit reserve and reserves in use
20526
20670
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20527
20671
  // Refresh obligation with reserves in use
20528
- preInstructions.push(refreshObligation({
20672
+ preInstructions.push(this.refreshObligationIx({
20529
20673
  lendingMarket: market,
20530
20674
  obligation,
20531
20675
  reserves: reservesInUse
@@ -20607,7 +20751,7 @@ class KaminoLendingClient {
20607
20751
  // Refresh reserves, including deposit reserve and reserves in use
20608
20752
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20609
20753
  // Refresh obligation with reserves in use
20610
- preInstructions.push(refreshObligation({
20754
+ preInstructions.push(this.refreshObligationIx({
20611
20755
  lendingMarket: market,
20612
20756
  obligation,
20613
20757
  reserves: reservesInUse
@@ -20810,7 +20954,7 @@ class KaminoVaultsClient {
20810
20954
  if (this.vaultStates.size === 0) {
20811
20955
  await this.findAndParseKaminoVaults();
20812
20956
  }
20813
- return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58()));
20957
+ return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58())).filter((p)=>!!p);
20814
20958
  }
20815
20959
  async fetchAndParseVaultState(vault) {
20816
20960
  const vaultAccount = await this.base.provider.connection.getAccountInfo(vault);
@@ -21365,6 +21509,21 @@ class InvestClient {
21365
21509
  }
21366
21510
 
21367
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
+ }
21368
21527
  /**
21369
21528
  * !! This is a convenience method that calculates the AUM of the vault based on priced assets.
21370
21529
  * !! It doesn't reflect the actual AUM of the vault.
@@ -21408,7 +21567,7 @@ class PriceClient {
21408
21567
  async priceKaminoVaultSharesIx(priceDenom) {
21409
21568
  const allKvaultStates = await this.kvaults.findAndParseKaminoVaults();
21410
21569
  const allKvaultMints = allKvaultStates.map((kvault)=>kvault.sharesMint);
21411
- // All share token accounts GLAM vault could possibly hold
21570
+ // All kvaut share token accounts GLAM vault could possibly hold
21412
21571
  const possibleShareAtas = allKvaultMints.map((mint)=>this.base.getVaultAta(mint));
21413
21572
  const possibleShareAtaAccountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(possibleShareAtas);
21414
21573
  const shareAtas = [];
@@ -21416,16 +21575,24 @@ class PriceClient {
21416
21575
  const kvaultStates = [];
21417
21576
  const oracles = []; // oracle of kvault deposit token
21418
21577
  possibleShareAtaAccountsInfo.forEach((info, i)=>{
21419
- 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]))) {
21420
21581
  shareAtas.push(possibleShareAtas[i]);
21421
21582
  shareMints.push(allKvaultMints[i]);
21422
21583
  kvaultStates.push(allKvaultStates[i]);
21423
- const { tokenMint } = allKvaultStates[i];
21584
+ // get oracle and lookup table from kvault state
21585
+ const { tokenMint, vaultLookupTable } = allKvaultStates[i];
21424
21586
  const assetMeta = ASSETS_MAINNET.get(tokenMint.toBase58());
21425
- 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
21426
21592
  }
21427
21593
  });
21428
21594
  const kvaultPdas = await this.kvaults.getVaultPdasByShareMints(shareMints);
21595
+ kvaultPdas.forEach((p)=>this._kaminoVaults.add(p.toBase58())); // cache kvault keys
21429
21596
  const remainingAccounts = [];
21430
21597
  // first 3N remaining accounts are N tuples of (kvault_shares_ata, kvault_shares_mint, kvault_state)
21431
21598
  for(let i = 0; i < shareAtas.length; i++){
@@ -21446,7 +21613,8 @@ class PriceClient {
21446
21613
  return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)), true);
21447
21614
  }))).flat();
21448
21615
  const processed = new Set();
21449
- const preInstructions = [];
21616
+ const reserves = [];
21617
+ const markets = [];
21450
21618
  const chunkSize = 2;
21451
21619
  for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
21452
21620
  const chunk = marketsAndReserves.slice(i, i + chunkSize);
@@ -21454,15 +21622,17 @@ class PriceClient {
21454
21622
  const reserve = chunk[1].pubkey;
21455
21623
  // reserve should always be added to remaining accounts
21456
21624
  remainingAccounts.push(chunk[1]);
21457
- // each reserve should only be refreshed once
21625
+ // record reserves and markets for refreshReservesBatchIx
21458
21626
  if (!processed.has(reserve.toBase58())) {
21459
- const ix = this.klend.refreshReserveIxs(market, [
21460
- reserve
21461
- ]);
21462
- preInstructions.push(...ix);
21627
+ reserves.push(reserve);
21628
+ markets.push(market);
21463
21629
  processed.add(reserve.toBase58());
21464
21630
  }
21465
21631
  }
21632
+ const refreshReservesIx = this.klend.refreshReservesBatchIx(reserves, markets, false);
21633
+ const preInstructions = [
21634
+ refreshReservesIx
21635
+ ];
21466
21636
  const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
21467
21637
  glamState: this.base.statePda,
21468
21638
  solOracle: SOL_ORACLE
@@ -21599,18 +21769,20 @@ class PriceClient {
21599
21769
  }
21600
21770
  // If there are no external assets, we don't need to price DeFi positions
21601
21771
  const stateModel = await this.base.fetchStateModel();
21602
- if ((stateModel.externalVaultAccounts || []).length === 0) {
21772
+ this.stateModel = stateModel;
21773
+ if ((this.stateModel.externalVaultAccounts || []).length === 0) {
21603
21774
  return [
21604
21775
  priceVaultIx
21605
21776
  ];
21606
21777
  }
21607
21778
  const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
21608
21779
  const integrationsToPricingFns = {
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)
21780
+ drift: this.priceDriftUsersIx.bind(this),
21781
+ kaminoLending: this.priceKaminoObligationsIx.bind(this),
21782
+ nativeStaking: this.priceStakesIx.bind(this),
21783
+ meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21784
+ driftVaults: this.priceDriftVaultDepositorsIx.bind(this),
21785
+ kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
21614
21786
  };
21615
21787
  const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
21616
21788
  const pricingIxs = [
@@ -21742,6 +21914,9 @@ class PriceClient {
21742
21914
  this.kvaults = kvaults;
21743
21915
  this.drift = drift;
21744
21916
  this.dvaults = dvaults;
21917
+ this._stateModel = null;
21918
+ this._lookupTables = new Set();
21919
+ this._kaminoVaults = new Set();
21745
21920
  }
21746
21921
  }
21747
21922
 
@@ -22163,8 +22338,10 @@ exports.getOpenfundsPda = getOpenfundsPda;
22163
22338
  exports.getOrderParams = getOrderParams;
22164
22339
  exports.getPriorityFeeEstimate = getPriorityFeeEstimate;
22165
22340
  exports.getSimulationResult = getSimulationResult;
22341
+ exports.getSolAndTokenBalances = getSolAndTokenBalances;
22166
22342
  exports.getStakeAccountsWithStates = getStakeAccountsWithStates;
22167
22343
  exports.getStatePda = getStatePda;
22344
+ exports.getTokenAccountsByOwner = getTokenAccountsByOwner;
22168
22345
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
22169
22346
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
22170
22347
  exports.getVariant = getVariant;