@glamsystems/glam-sdk 0.1.30 → 0.1.32

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
@@ -5,7 +5,7 @@ var web3_js = require('@solana/web3.js');
5
5
  var splToken = require('@solana/spl-token');
6
6
  var splTokenMetadata = require('@solana/spl-token-metadata');
7
7
  var DLMM = require('@meteora-ag/dlmm');
8
- var sanctumLstList = require('sanctum-lst-list');
8
+ var sanctumLstList = require('@glamsystems/sanctum-lst-list');
9
9
  var bytes = require('@coral-xyz/anchor/dist/cjs/utils/bytes');
10
10
  var borsh = require('@coral-xyz/borsh');
11
11
  var marinadeTsSdk = require('@marinade.finance/marinade-ts-sdk');
@@ -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.35",
37
+ version: "0.4.36",
38
38
  spec: "0.1.0",
39
39
  description: "Glam Protocol"
40
40
  };
@@ -1007,7 +1007,7 @@ var instructions = [
1007
1007
  98,
1008
1008
  97,
1009
1009
  108,
1010
- 95,
1010
+ 45,
1011
1011
  99,
1012
1012
  111,
1013
1013
  110,
@@ -6830,7 +6830,7 @@ var instructions = [
6830
6830
  98,
6831
6831
  97,
6832
6832
  108,
6833
- 95,
6833
+ 45,
6834
6834
  99,
6835
6835
  111,
6836
6836
  110,
@@ -6961,7 +6961,7 @@ var instructions = [
6961
6961
  98,
6962
6962
  97,
6963
6963
  108,
6964
- 95,
6964
+ 45,
6965
6965
  99,
6966
6966
  111,
6967
6967
  110,
@@ -7097,7 +7097,7 @@ var instructions = [
7097
7097
  98,
7098
7098
  97,
7099
7099
  108,
7100
- 95,
7100
+ 45,
7101
7101
  99,
7102
7102
  111,
7103
7103
  110,
@@ -7243,7 +7243,7 @@ var instructions = [
7243
7243
  98,
7244
7244
  97,
7245
7245
  108,
7246
- 95,
7246
+ 45,
7247
7247
  99,
7248
7248
  111,
7249
7249
  110,
@@ -7367,7 +7367,7 @@ var instructions = [
7367
7367
  98,
7368
7368
  97,
7369
7369
  108,
7370
- 95,
7370
+ 45,
7371
7371
  99,
7372
7372
  111,
7373
7373
  110,
@@ -7487,7 +7487,7 @@ var instructions = [
7487
7487
  98,
7488
7488
  97,
7489
7489
  108,
7490
- 95,
7490
+ 45,
7491
7491
  99,
7492
7492
  111,
7493
7493
  110,
@@ -7553,8 +7553,11 @@ var instructions = [
7553
7553
  docs: [
7554
7554
  "Price vault SOL balance and tokens it holds.",
7555
7555
  "",
7556
+ "If aggregation oracle is used for token #`i`, `agg_indexes[i]` must be set to its index in the oracle mapping account.",
7557
+ "",
7556
7558
  "Extra accounts for pricing N tokens:",
7557
- "- (ata, mint, oracle) x N"
7559
+ "- (ata, mint, oracle) x N",
7560
+ "- optional oracle mapping (only add it if any token uses an agg oracle)"
7558
7561
  ],
7559
7562
  discriminator: [
7560
7563
  54,
@@ -7613,7 +7616,7 @@ var instructions = [
7613
7616
  98,
7614
7617
  97,
7615
7618
  108,
7616
- 95,
7619
+ 45,
7617
7620
  99,
7618
7621
  111,
7619
7622
  110,
@@ -7671,6 +7674,12 @@ var instructions = [
7671
7674
  name: "PriceDenom"
7672
7675
  }
7673
7676
  }
7677
+ },
7678
+ {
7679
+ name: "agg_indexes",
7680
+ type: {
7681
+ vec: "i16"
7682
+ }
7674
7683
  }
7675
7684
  ]
7676
7685
  },
@@ -8079,7 +8088,7 @@ var instructions = [
8079
8088
  98,
8080
8089
  97,
8081
8090
  108,
8082
- 95,
8091
+ 45,
8083
8092
  99,
8084
8093
  111,
8085
8094
  110,
@@ -10025,7 +10034,8 @@ var instructions = [
10025
10034
  ],
10026
10035
  accounts: [
10027
10036
  {
10028
- name: "glam_state"
10037
+ name: "glam_state",
10038
+ writable: true
10029
10039
  },
10030
10040
  {
10031
10041
  name: "glam_vault",
@@ -11225,6 +11235,23 @@ var types = [
11225
11235
  name: "OracleSource"
11226
11236
  }
11227
11237
  }
11238
+ },
11239
+ {
11240
+ name: "max_age_seconds",
11241
+ type: "u16"
11242
+ },
11243
+ {
11244
+ name: "priority",
11245
+ type: "u8"
11246
+ },
11247
+ {
11248
+ name: "padding",
11249
+ type: {
11250
+ array: [
11251
+ "u8",
11252
+ 3
11253
+ ]
11254
+ }
11228
11255
  }
11229
11256
  ]
11230
11257
  }
@@ -12325,8 +12352,7 @@ var types = [
12325
12352
  {
12326
12353
  name: "fee_authority",
12327
12354
  docs: [
12328
- "The authority that can modify fee structure of individual glam state",
12329
- "and claim protocol fees"
12355
+ "The authority that can modify fee structure of individual glam state and claim protocol fees"
12330
12356
  ],
12331
12357
  type: "pubkey"
12332
12358
  },
@@ -13237,6 +13263,9 @@ var types = [
13237
13263
  {
13238
13264
  name: "PythLazerStableCoin"
13239
13265
  },
13266
+ {
13267
+ name: "NotSet"
13268
+ },
13240
13269
  {
13241
13270
  name: "LstPoolState"
13242
13271
  },
@@ -13245,6 +13274,9 @@ var types = [
13245
13274
  },
13246
13275
  {
13247
13276
  name: "BaseAsset"
13277
+ },
13278
+ {
13279
+ name: "ChainlinkRWA"
13248
13280
  }
13249
13281
  ]
13250
13282
  }
@@ -13572,6 +13604,9 @@ var types = [
13572
13604
  },
13573
13605
  {
13574
13606
  name: "Fulfill"
13607
+ },
13608
+ {
13609
+ name: "ClaimFees"
13575
13610
  }
13576
13611
  ]
13577
13612
  }
@@ -14949,6 +14984,15 @@ class PriceDenom {
14949
14984
  }
14950
14985
  return PriceDenom.ASSET;
14951
14986
  }
14987
+ static fromString(str) {
14988
+ if (str === "SOL") {
14989
+ return PriceDenom.SOL;
14990
+ }
14991
+ if (str === "USD") {
14992
+ return PriceDenom.USD;
14993
+ }
14994
+ throw new Error("Invalid price denomination");
14995
+ }
14952
14996
  }
14953
14997
  PriceDenom.SOL = {
14954
14998
  sol: {}
@@ -14984,6 +15028,67 @@ var ClusterNetwork = /*#__PURE__*/ function(ClusterNetwork) {
14984
15028
  return ClusterNetwork;
14985
15029
  }({});
14986
15030
 
15031
+ /**
15032
+ * Fetches all the token accounts owned by the specified pubkey.
15033
+ */ async function getTokenAccountsByOwner(connection, owner) {
15034
+ const tokenAccounts = await connection.getTokenAccountsByOwner(owner, {
15035
+ programId: splToken.TOKEN_PROGRAM_ID
15036
+ });
15037
+ const token2022Accounts = await connection.getTokenAccountsByOwner(owner, {
15038
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15039
+ });
15040
+ const mintPubkeys = [];
15041
+ const parseTokenAccountInfo = (pubkey, account)=>{
15042
+ const { mint, amount, state } = splToken.AccountLayout.decode(account.data);
15043
+ mintPubkeys.push(mint);
15044
+ return {
15045
+ owner,
15046
+ pubkey,
15047
+ mint,
15048
+ amount: amount.toString(),
15049
+ frozen: state !== 1
15050
+ };
15051
+ };
15052
+ // Parse token accounts
15053
+ const partialTokenAccounts = tokenAccounts.value.map(({ pubkey, account })=>({
15054
+ ...parseTokenAccountInfo(pubkey, account),
15055
+ programId: splToken.TOKEN_PROGRAM_ID
15056
+ })).concat(token2022Accounts.value.map(({ pubkey, account })=>({
15057
+ ...parseTokenAccountInfo(pubkey, account),
15058
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15059
+ })));
15060
+ // Get mint decimals
15061
+ const mintDecimalMap = new Map();
15062
+ const mintAccountsInfo = await connection.getMultipleAccountsInfo(mintPubkeys);
15063
+ mintAccountsInfo.forEach((accountInfo, i)=>{
15064
+ if (accountInfo) {
15065
+ const mint = splToken.unpackMint(mintPubkeys[i], accountInfo, accountInfo.owner);
15066
+ mintDecimalMap.set(mintPubkeys[i].toBase58(), mint.decimals);
15067
+ }
15068
+ });
15069
+ // Enrich token accounts with decimals and uiAmount
15070
+ return partialTokenAccounts.map((ta)=>{
15071
+ const decimals = mintDecimalMap.get(ta.mint.toBase58());
15072
+ if (!decimals) {
15073
+ return null;
15074
+ }
15075
+ return {
15076
+ ...ta,
15077
+ decimals,
15078
+ uiAmount: Number(ta.amount) / 10 ** decimals
15079
+ };
15080
+ }).filter((ta)=>ta !== null);
15081
+ }
15082
+ async function getSolAndTokenBalances(connection, owner) {
15083
+ const balanceLamports = await connection.getBalance(owner);
15084
+ const tokenAccounts = await getTokenAccountsByOwner(connection, owner);
15085
+ const uiAmount = balanceLamports / web3_js.LAMPORTS_PER_SOL;
15086
+ return {
15087
+ balanceLamports,
15088
+ uiAmount,
15089
+ tokenAccounts
15090
+ };
15091
+ }
14987
15092
  const findStakeAccounts = async (connection, withdrawAuthority)=>{
14988
15093
  // stake authority offset: 12
14989
15094
  // withdraw authority offset: 44
@@ -15181,7 +15286,7 @@ const setsAreEqual = (a, b)=>{
15181
15286
  return true;
15182
15287
  };
15183
15288
 
15184
- const STAKE_POOLS = sanctumLstList.LstList.filter((lst)=>!lst.name.includes("Sanctum Automated") && (lst.pool.program === "Spl" || lst.pool.program === "Marinade" || lst.pool.program === "SanctumSpl" || lst.pool.program === "SanctumSplMulti")).map((lst)=>{
15289
+ const STAKE_POOLS = sanctumLstList.LstList.filter((lst)=>lst.pool.program === "Spl" || lst.pool.program === "Marinade" || lst.pool.program === "SanctumSpl" || lst.pool.program === "SanctumSplMulti").map((lst)=>{
15185
15290
  const { pool, program } = lst.pool;
15186
15291
  const poolState = program === "Marinade" ? "8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC" : pool;
15187
15292
  if (!poolState) {
@@ -15197,15 +15302,6 @@ const STAKE_POOLS = sanctumLstList.LstList.filter((lst)=>!lst.name.includes("San
15197
15302
  poolState: new web3_js.PublicKey(poolState)
15198
15303
  };
15199
15304
  });
15200
- STAKE_POOLS.push({
15201
- name: "Phantom Staked SOL",
15202
- symbol: "PSOL",
15203
- mint: "pSo1f9nQXWgXibFtKf7NWYxb5enAM4qfP6UJSiXRQfL",
15204
- decimals: 9,
15205
- logoURI: "https://assets.phantom.app/assets/metadata/PSOL-512.png",
15206
- tokenProgram: splToken.TOKEN_PROGRAM_ID,
15207
- poolState: new web3_js.PublicKey("pSPcvR8GmG9aKDUbn9nbKYjkxt9hxMS7kF1qqKJaPqJ")
15208
- });
15209
15305
  const STAKE_POOLS_MAP = new Map(STAKE_POOLS.map((p)=>[
15210
15306
  p.mint,
15211
15307
  p
@@ -15283,6 +15379,15 @@ const ASSETS_MAINNET = new Map([
15283
15379
  oracle: new web3_js.PublicKey("9PgHM68FNGDK6nHb29ERDBcFrV6gNMD8LyUqwxbyyeb2")
15284
15380
  }
15285
15381
  ],
15382
+ [
15383
+ // USDG
15384
+ "2u1tszSeqZ3qBWF3uNGPFc8TzMk2tdiwknnRMWGWjGWH",
15385
+ {
15386
+ decimals: 6,
15387
+ oracle: new web3_js.PublicKey("6JkZmXGgWnzsyTQaqRARzP64iFYnpMNT4siiuUDUaB8s"),
15388
+ programId: splToken.TOKEN_2022_PROGRAM_ID
15389
+ }
15390
+ ],
15286
15391
  [
15287
15392
  // PYUSD
15288
15393
  "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
@@ -15350,6 +15455,46 @@ const ASSETS_MAINNET = new Map([
15350
15455
  oracle: new web3_js.PublicKey("9mhGNSPArRMHpLDMSmxAvuoizBqtBGqYdT8WGuqgxNdn"),
15351
15456
  isLst: true
15352
15457
  }
15458
+ ],
15459
+ [
15460
+ // GOOGLx
15461
+ "XsCPL9dNWBMvFtTmwcCA5v3xWPSMEBCszbQdiLLq6aN",
15462
+ {
15463
+ decimals: 8,
15464
+ oracle: new web3_js.PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C"),
15465
+ programId: splToken.TOKEN_2022_PROGRAM_ID,
15466
+ aggIndex: 342
15467
+ }
15468
+ ],
15469
+ [
15470
+ // AAPLx
15471
+ "XsbEhLAtcf6HdfpFZ5xEMdqW8nfAvcsP5bdudRLJzJp",
15472
+ {
15473
+ decimals: 8,
15474
+ oracle: new web3_js.PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C"),
15475
+ programId: splToken.TOKEN_2022_PROGRAM_ID,
15476
+ aggIndex: 343
15477
+ }
15478
+ ],
15479
+ [
15480
+ // TSLAx
15481
+ "XsDoVfqeBukxuZHWhdvWHBhgEHjGNst4MLodqsJHzoB",
15482
+ {
15483
+ decimals: 8,
15484
+ oracle: new web3_js.PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C"),
15485
+ programId: splToken.TOKEN_2022_PROGRAM_ID,
15486
+ aggIndex: 335
15487
+ }
15488
+ ],
15489
+ [
15490
+ // NVDAx
15491
+ "Xsc9qvGR1efVDFGLrVsmkzv3qi45LTBjeUKSPmx9qEh",
15492
+ {
15493
+ decimals: 8,
15494
+ oracle: new web3_js.PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C"),
15495
+ programId: splToken.TOKEN_2022_PROGRAM_ID,
15496
+ aggIndex: 341
15497
+ }
15353
15498
  ]
15354
15499
  ]);
15355
15500
  const ASSETS_TESTS = new Map([]);
@@ -15506,12 +15651,6 @@ const LOOKUP_TABLES = [
15506
15651
  new web3_js.PublicKey("D9cnvzswDikQDf53k4HpQ3KJ9y1Fv3HGGDFYMXnK5T6c"),
15507
15652
  new web3_js.PublicKey("EiWSskK5HXnBTptiS5DH6gpAJRVNQ3cAhTKBGaiaysAb")
15508
15653
  ];
15509
- const STATES_LOOKUP_TABLES_MAP = new Map([
15510
- [
15511
- "3tfbxaHBDjczQo3eyNJGGG64ChZ9nG4V3Gywa4k59d5a",
15512
- new web3_js.PublicKey("8HUXT9abWS2z3z92QyDzg51nMcc18LyWFvaEQZJMPixu")
15513
- ]
15514
- ]);
15515
15654
  const isBrowser = process.env.ANCHOR_BROWSER || typeof window !== "undefined" && !window.process?.hasOwnProperty("type");
15516
15655
  class BaseClient {
15517
15656
  get detectedCluster() {
@@ -15600,17 +15739,16 @@ class BaseClient {
15600
15739
  if (glamApi) {
15601
15740
  const response = await fetch(`${glamApi}/v0/lut/glam/?state=${this.statePda}`);
15602
15741
  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);
15742
+ const lookupTables = data.t || {};
15743
+ const lookupTableAccounts = [];
15744
+ for (const [key, lookupTableData] of Object.entries(lookupTables)){
15745
+ const account = new web3_js.AddressLookupTableAccount({
15746
+ key: new web3_js.PublicKey(key),
15747
+ state: web3_js.AddressLookupTableAccount.deserialize(new Uint8Array(Buffer.from(lookupTableData, "base64")))
15748
+ });
15749
+ lookupTableAccounts.push(account);
15607
15750
  }
15608
- }
15609
- const tablePubkey = STATES_LOOKUP_TABLES_MAP.get(this.statePda.toBase58());
15610
- if (tablePubkey) {
15611
- return await this.fetchAddressLookupTableAccounts([
15612
- tablePubkey
15613
- ]);
15751
+ return lookupTableAccounts;
15614
15752
  }
15615
15753
  // Fetch all accounts owned by the ALT program
15616
15754
  // 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 +15808,24 @@ class BaseClient {
15670
15808
  ]);
15671
15809
  lookupTableAccounts.push(...accounts);
15672
15810
  }
15811
+ const glamApi = process.env.NEXT_PUBLIC_GLAM_API || process.env.GLAM_API;
15812
+ if (glamApi) {
15813
+ try {
15814
+ const response = await fetch(`${glamApi}/v0/lut/glam/?state=${this.statePda}`);
15815
+ const data = await response.json();
15816
+ const lookupTables = data.t || {};
15817
+ for (const [key, lookupTableData] of Object.entries(lookupTables)){
15818
+ const account = new web3_js.AddressLookupTableAccount({
15819
+ key: new web3_js.PublicKey(key),
15820
+ state: web3_js.AddressLookupTableAccount.deserialize(new Uint8Array(Buffer.from(lookupTableData, "base64")))
15821
+ });
15822
+ lookupTableAccounts.push(account);
15823
+ }
15824
+ } catch (e) {
15825
+ console.error("Failed to fetch lookup tables:", e); // Fail open
15826
+ }
15827
+ }
15828
+ console.log("lookupTableAccounts:", lookupTableAccounts.map((t)=>t.key.toBase58()));
15673
15829
  const recentBlockhash = (await this.blockhashWithCache.get()).blockhash;
15674
15830
  const { unitsConsumed, error, serializedTx } = await getSimulationResult(this.provider.connection, instructions, signer, lookupTableAccounts);
15675
15831
  computeUnitLimit = unitsConsumed;
@@ -19761,176 +19917,6 @@ const DEFAULT_OBLIGATION_ARGS = {
19761
19917
  id: 0
19762
19918
  };
19763
19919
  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
19920
  class KaminoLendingClient {
19935
19921
  /**
19936
19922
  * Initializes Kamino user metadata
@@ -20022,8 +20008,228 @@ class KaminoLendingClient {
20022
20008
  ], KAMINO_FARM_PROGRAM);
20023
20009
  return obligationFarm;
20024
20010
  }
20011
+ refreshObligationIx(accounts, programId = KAMINO_LENDING_PROGRAM) {
20012
+ const keys = [
20013
+ {
20014
+ pubkey: accounts.lendingMarket,
20015
+ isSigner: false,
20016
+ isWritable: false
20017
+ },
20018
+ {
20019
+ pubkey: accounts.obligation,
20020
+ isSigner: false,
20021
+ isWritable: true
20022
+ }
20023
+ ];
20024
+ accounts.reserves.forEach((reserve)=>{
20025
+ keys.push({
20026
+ pubkey: reserve,
20027
+ isSigner: false,
20028
+ isWritable: false
20029
+ });
20030
+ });
20031
+ const identifier = Buffer.from([
20032
+ 33,
20033
+ 132,
20034
+ 147,
20035
+ 228,
20036
+ 151,
20037
+ 192,
20038
+ 72,
20039
+ 89
20040
+ ]);
20041
+ const data = identifier;
20042
+ return new web3_js.TransactionInstruction({
20043
+ keys,
20044
+ programId,
20045
+ data
20046
+ });
20047
+ }
20048
+ refreshReserveIx(accounts, programId = KAMINO_LENDING_PROGRAM) {
20049
+ const keys = [
20050
+ {
20051
+ pubkey: accounts.reserve,
20052
+ isSigner: false,
20053
+ isWritable: true
20054
+ },
20055
+ {
20056
+ pubkey: accounts.lendingMarket,
20057
+ isSigner: false,
20058
+ isWritable: false
20059
+ },
20060
+ {
20061
+ pubkey: accounts.pythOracle,
20062
+ isSigner: false,
20063
+ isWritable: false
20064
+ },
20065
+ {
20066
+ pubkey: accounts.switchboardPriceOracle,
20067
+ isSigner: false,
20068
+ isWritable: false
20069
+ },
20070
+ {
20071
+ pubkey: accounts.switchboardTwapOracle,
20072
+ isSigner: false,
20073
+ isWritable: false
20074
+ },
20075
+ {
20076
+ pubkey: accounts.scopePrices,
20077
+ isSigner: false,
20078
+ isWritable: false
20079
+ }
20080
+ ];
20081
+ const identifier = Buffer.from([
20082
+ 2,
20083
+ 218,
20084
+ 138,
20085
+ 235,
20086
+ 79,
20087
+ 201,
20088
+ 25,
20089
+ 102
20090
+ ]);
20091
+ const data = identifier;
20092
+ return new web3_js.TransactionInstruction({
20093
+ keys,
20094
+ programId,
20095
+ data
20096
+ });
20097
+ }
20098
+ refreshObligationFarmsForReserveIx(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
20099
+ const keys = [
20100
+ {
20101
+ pubkey: accounts.crank,
20102
+ isSigner: true,
20103
+ isWritable: false
20104
+ },
20105
+ {
20106
+ pubkey: accounts.baseAccounts.obligation,
20107
+ isSigner: false,
20108
+ isWritable: false
20109
+ },
20110
+ {
20111
+ pubkey: accounts.baseAccounts.lendingMarketAuthority,
20112
+ isSigner: false,
20113
+ isWritable: true
20114
+ },
20115
+ {
20116
+ pubkey: accounts.baseAccounts.reserve,
20117
+ isSigner: false,
20118
+ isWritable: false
20119
+ },
20120
+ {
20121
+ pubkey: accounts.baseAccounts.reserveFarmState,
20122
+ isSigner: false,
20123
+ isWritable: true
20124
+ },
20125
+ {
20126
+ pubkey: accounts.baseAccounts.obligationFarmUserState,
20127
+ isSigner: false,
20128
+ isWritable: true
20129
+ },
20130
+ {
20131
+ pubkey: accounts.baseAccounts.lendingMarket,
20132
+ isSigner: false,
20133
+ isWritable: false
20134
+ },
20135
+ {
20136
+ pubkey: accounts.farmsProgram,
20137
+ isSigner: false,
20138
+ isWritable: false
20139
+ },
20140
+ {
20141
+ pubkey: accounts.rent,
20142
+ isSigner: false,
20143
+ isWritable: false
20144
+ },
20145
+ {
20146
+ pubkey: accounts.systemProgram,
20147
+ isSigner: false,
20148
+ isWritable: false
20149
+ }
20150
+ ];
20151
+ const identifier = Buffer.from([
20152
+ 140,
20153
+ 144,
20154
+ 253,
20155
+ 21,
20156
+ 10,
20157
+ 74,
20158
+ 248,
20159
+ 3
20160
+ ]);
20161
+ const buffer = Buffer.alloc(1000);
20162
+ const layout = borsh__namespace.struct([
20163
+ borsh__namespace.u8("mode")
20164
+ ]);
20165
+ const len = layout.encode({
20166
+ mode: args.mode
20167
+ }, buffer);
20168
+ const data = Buffer.concat([
20169
+ identifier,
20170
+ buffer
20171
+ ]).subarray(0, 8 + len);
20172
+ return new web3_js.TransactionInstruction({
20173
+ keys,
20174
+ programId,
20175
+ data
20176
+ });
20177
+ }
20178
+ refreshReservesBatchIx(reserves, lendingMarkets, skipPriceUpdates, programId = KAMINO_LENDING_PROGRAM) {
20179
+ const keys = [];
20180
+ for(let i = 0; i < reserves.length; i++){
20181
+ keys.push({
20182
+ pubkey: reserves[i],
20183
+ isSigner: false,
20184
+ isWritable: false
20185
+ });
20186
+ keys.push({
20187
+ pubkey: lendingMarkets[i],
20188
+ isSigner: false,
20189
+ isWritable: true
20190
+ });
20191
+ if (!skipPriceUpdates) {
20192
+ [
20193
+ KAMINO_LENDING_PROGRAM,
20194
+ KAMINO_LENDING_PROGRAM,
20195
+ KAMINO_LENDING_PROGRAM,
20196
+ KAMINO_SCOPE_PRICES
20197
+ ].forEach((p)=>keys.push({
20198
+ pubkey: p,
20199
+ isSigner: false,
20200
+ isWritable: false
20201
+ }));
20202
+ }
20203
+ }
20204
+ const identifier = Buffer.from([
20205
+ 144,
20206
+ 110,
20207
+ 26,
20208
+ 103,
20209
+ 162,
20210
+ 204,
20211
+ 252,
20212
+ 147
20213
+ ]);
20214
+ const buffer = Buffer.alloc(1000);
20215
+ const layout = borsh__namespace.struct([
20216
+ borsh__namespace.bool("skipPriceUpdates")
20217
+ ]);
20218
+ const len = layout.encode({
20219
+ skipPriceUpdates
20220
+ }, buffer);
20221
+ const data = Buffer.concat([
20222
+ identifier,
20223
+ buffer
20224
+ ]).subarray(0, 8 + len);
20225
+ return new web3_js.TransactionInstruction({
20226
+ keys,
20227
+ programId,
20228
+ data
20229
+ });
20230
+ }
20025
20231
  refreshReserveIxs(lendingMarket, reserves) {
20026
- return reserves.map((reserve)=>refreshReserve({
20232
+ return reserves.map((reserve)=>this.refreshReserveIx({
20027
20233
  reserve,
20028
20234
  lendingMarket,
20029
20235
  pythOracle: KAMINO_LENDING_PROGRAM,
@@ -20039,7 +20245,7 @@ class KaminoLendingClient {
20039
20245
  farmCollateral
20040
20246
  ].filter((farm)=>!!farm).map((farm)=>{
20041
20247
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20042
- return refreshObligationFarmsForReserve({
20248
+ return this.refreshObligationFarmsForReserveIx({
20043
20249
  mode: 0
20044
20250
  }, {
20045
20251
  crank: this.base.getSigner(),
@@ -20065,7 +20271,7 @@ class KaminoLendingClient {
20065
20271
  farmDebt
20066
20272
  ].filter((farm)=>!!farm).map((farm)=>{
20067
20273
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
20068
- return refreshObligationFarmsForReserve({
20274
+ return this.refreshObligationFarmsForReserveIx({
20069
20275
  mode: 0
20070
20276
  }, {
20071
20277
  crank: this.base.getSigner(),
@@ -20351,7 +20557,7 @@ class KaminoLendingClient {
20351
20557
  // Refresh reserves, including deposit reserve and reserves in use
20352
20558
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20353
20559
  // Refresh obligation with reserves in use
20354
- preInstructions.push(refreshObligation({
20560
+ preInstructions.push(this.refreshObligationIx({
20355
20561
  lendingMarket: market,
20356
20562
  obligation,
20357
20563
  reserves: reservesInUse
@@ -20441,7 +20647,7 @@ class KaminoLendingClient {
20441
20647
  // Refresh reserves, including deposit reserve and reserves in use
20442
20648
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20443
20649
  // Refresh obligation with reserves in use
20444
- preInstructions.push(refreshObligation({
20650
+ preInstructions.push(this.refreshObligationIx({
20445
20651
  lendingMarket: market,
20446
20652
  obligation,
20447
20653
  reserves: reservesInUse
@@ -20525,7 +20731,7 @@ class KaminoLendingClient {
20525
20731
  // Refresh reserves, including deposit reserve and reserves in use
20526
20732
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20527
20733
  // Refresh obligation with reserves in use
20528
- preInstructions.push(refreshObligation({
20734
+ preInstructions.push(this.refreshObligationIx({
20529
20735
  lendingMarket: market,
20530
20736
  obligation,
20531
20737
  reserves: reservesInUse
@@ -20607,7 +20813,7 @@ class KaminoLendingClient {
20607
20813
  // Refresh reserves, including deposit reserve and reserves in use
20608
20814
  preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
20609
20815
  // Refresh obligation with reserves in use
20610
- preInstructions.push(refreshObligation({
20816
+ preInstructions.push(this.refreshObligationIx({
20611
20817
  lendingMarket: market,
20612
20818
  obligation,
20613
20819
  reserves: reservesInUse
@@ -20810,7 +21016,7 @@ class KaminoVaultsClient {
20810
21016
  if (this.vaultStates.size === 0) {
20811
21017
  await this.findAndParseKaminoVaults();
20812
21018
  }
20813
- return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58()));
21019
+ return mints.map((mint)=>this.shareMintToVaultPdaMap.get(mint.toBase58())).filter((p)=>!!p);
20814
21020
  }
20815
21021
  async fetchAndParseVaultState(vault) {
20816
21022
  const vaultAccount = await this.base.provider.connection.getAccountInfo(vault);
@@ -21365,6 +21571,21 @@ class InvestClient {
21365
21571
  }
21366
21572
 
21367
21573
  class PriceClient {
21574
+ get stateModel() {
21575
+ if (!this._stateModel) {
21576
+ throw new Error("State model not cached");
21577
+ }
21578
+ return this._stateModel;
21579
+ }
21580
+ set stateModel(stateModel) {
21581
+ this._stateModel = stateModel;
21582
+ }
21583
+ get lookupTables() {
21584
+ return Array.from(this._lookupTables).map((k)=>new web3_js.PublicKey(k));
21585
+ }
21586
+ get kaminoVaults() {
21587
+ return Array.from(this._kaminoVaults).map((k)=>new web3_js.PublicKey(k));
21588
+ }
21368
21589
  /**
21369
21590
  * !! This is a convenience method that calculates the AUM of the vault based on priced assets.
21370
21591
  * !! It doesn't reflect the actual AUM of the vault.
@@ -21408,7 +21629,7 @@ class PriceClient {
21408
21629
  async priceKaminoVaultSharesIx(priceDenom) {
21409
21630
  const allKvaultStates = await this.kvaults.findAndParseKaminoVaults();
21410
21631
  const allKvaultMints = allKvaultStates.map((kvault)=>kvault.sharesMint);
21411
- // All share token accounts GLAM vault could possibly hold
21632
+ // All kvaut share token accounts GLAM vault could possibly hold
21412
21633
  const possibleShareAtas = allKvaultMints.map((mint)=>this.base.getVaultAta(mint));
21413
21634
  const possibleShareAtaAccountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(possibleShareAtas);
21414
21635
  const shareAtas = [];
@@ -21416,16 +21637,24 @@ class PriceClient {
21416
21637
  const kvaultStates = [];
21417
21638
  const oracles = []; // oracle of kvault deposit token
21418
21639
  possibleShareAtaAccountsInfo.forEach((info, i)=>{
21419
- if (info !== null) {
21640
+ // share ata must exist and it must be tracked by glam state
21641
+ // otherwise skip it for pricing
21642
+ if (info !== null && this.stateModel.externalVaultAccounts?.find((a)=>a.equals(possibleShareAtas[i]))) {
21420
21643
  shareAtas.push(possibleShareAtas[i]);
21421
21644
  shareMints.push(allKvaultMints[i]);
21422
21645
  kvaultStates.push(allKvaultStates[i]);
21423
- const { tokenMint } = allKvaultStates[i];
21646
+ // get oracle and lookup table from kvault state
21647
+ const { tokenMint, vaultLookupTable } = allKvaultStates[i];
21424
21648
  const assetMeta = ASSETS_MAINNET.get(tokenMint.toBase58());
21425
- oracles.push(assetMeta?.oracle);
21649
+ if (!assetMeta || !assetMeta.oracle) {
21650
+ throw new Error(`Oracle unavailable for asset ${tokenMint}`);
21651
+ }
21652
+ oracles.push(assetMeta.oracle);
21653
+ this._lookupTables.add(vaultLookupTable.toBase58()); // cache lookup table
21426
21654
  }
21427
21655
  });
21428
21656
  const kvaultPdas = await this.kvaults.getVaultPdasByShareMints(shareMints);
21657
+ kvaultPdas.forEach((p)=>this._kaminoVaults.add(p.toBase58())); // cache kvault keys
21429
21658
  const remainingAccounts = [];
21430
21659
  // first 3N remaining accounts are N tuples of (kvault_shares_ata, kvault_shares_mint, kvault_state)
21431
21660
  for(let i = 0; i < shareAtas.length; i++){
@@ -21446,7 +21675,8 @@ class PriceClient {
21446
21675
  return this.kvaults.composeRemainingAccounts(kvault.vaultAllocationStrategy.filter((alloc)=>!alloc.reserve.equals(web3_js.PublicKey.default)), true);
21447
21676
  }))).flat();
21448
21677
  const processed = new Set();
21449
- const preInstructions = [];
21678
+ const reserves = [];
21679
+ const markets = [];
21450
21680
  const chunkSize = 2;
21451
21681
  for(let i = 0; i < marketsAndReserves.length; i += chunkSize){
21452
21682
  const chunk = marketsAndReserves.slice(i, i + chunkSize);
@@ -21454,15 +21684,17 @@ class PriceClient {
21454
21684
  const reserve = chunk[1].pubkey;
21455
21685
  // reserve should always be added to remaining accounts
21456
21686
  remainingAccounts.push(chunk[1]);
21457
- // each reserve should only be refreshed once
21687
+ // record reserves and markets for refreshReservesBatchIx
21458
21688
  if (!processed.has(reserve.toBase58())) {
21459
- const ix = this.klend.refreshReserveIxs(market, [
21460
- reserve
21461
- ]);
21462
- preInstructions.push(...ix);
21689
+ reserves.push(reserve);
21690
+ markets.push(market);
21463
21691
  processed.add(reserve.toBase58());
21464
21692
  }
21465
21693
  }
21694
+ const refreshReservesIx = this.klend.refreshReservesBatchIx(reserves, markets, false);
21695
+ const preInstructions = [
21696
+ refreshReservesIx
21697
+ ];
21466
21698
  const priceIx = await this.base.program.methods.priceKaminoVaultShares(priceDenom, shareAtas.length).accounts({
21467
21699
  glamState: this.base.statePda,
21468
21700
  solOracle: SOL_ORACLE
@@ -21549,7 +21781,23 @@ class PriceClient {
21549
21781
  * Returns an instruction that prices vault balance and tokens the vault holds
21550
21782
  */ async priceVaultIx(priceDenom) {
21551
21783
  const remainingAccounts = await this.remainingAccountsForPricingVaultAssets(priceDenom == PriceDenom.ASSET);
21552
- const priceVaultIx = await this.base.program.methods.priceVaultTokens(priceDenom).accounts({
21784
+ const aggIndexes = [];
21785
+ const chunkSize = 3;
21786
+ for(let i = 0; i < remainingAccounts.length; i += chunkSize){
21787
+ const chunk = remainingAccounts.slice(i, i + chunkSize);
21788
+ const mint = chunk[1].pubkey;
21789
+ const aggIndex = ASSETS_MAINNET.get(mint.toBase58())?.aggIndex || -1;
21790
+ aggIndexes.push(aggIndex);
21791
+ }
21792
+ // Add oracle mapping if agg oracle is used for any token
21793
+ if (aggIndexes.find((i)=>i >= 0)) {
21794
+ remainingAccounts.push({
21795
+ pubkey: new web3_js.PublicKey("Chpu5ZgfWX5ZzVpUx9Xvv4WPM75Xd7zPJNDPsFnCpLpk"),
21796
+ isSigner: false,
21797
+ isWritable: false
21798
+ });
21799
+ }
21800
+ const priceVaultIx = await this.base.program.methods.priceVaultTokens(priceDenom, aggIndexes).accounts({
21553
21801
  glamState: this.base.statePda,
21554
21802
  solOracle: SOL_ORACLE
21555
21803
  }).remainingAccounts(remainingAccounts).instruction();
@@ -21599,18 +21847,20 @@ class PriceClient {
21599
21847
  }
21600
21848
  // If there are no external assets, we don't need to price DeFi positions
21601
21849
  const stateModel = await this.base.fetchStateModel();
21602
- if ((stateModel.externalVaultAccounts || []).length === 0) {
21850
+ this.stateModel = stateModel;
21851
+ if ((this.stateModel.externalVaultAccounts || []).length === 0) {
21603
21852
  return [
21604
21853
  priceVaultIx
21605
21854
  ];
21606
21855
  }
21607
21856
  const integrations = (stateModel.integrations || []).map((i)=>Object.keys(i)[0]);
21608
21857
  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)
21858
+ drift: this.priceDriftUsersIx.bind(this),
21859
+ kaminoLending: this.priceKaminoObligationsIx.bind(this),
21860
+ nativeStaking: this.priceStakesIx.bind(this),
21861
+ meteoraDlmm: this.priceMeteoraPositionsIx.bind(this),
21862
+ driftVaults: this.priceDriftVaultDepositorsIx.bind(this),
21863
+ kaminoVaults: this.priceKaminoVaultSharesIx.bind(this)
21614
21864
  };
21615
21865
  const pricingFns = integrations.map((integration)=>integrationsToPricingFns[integration]).filter(Boolean);
21616
21866
  const pricingIxs = [
@@ -21742,6 +21992,9 @@ class PriceClient {
21742
21992
  this.kvaults = kvaults;
21743
21993
  this.drift = drift;
21744
21994
  this.dvaults = dvaults;
21995
+ this._stateModel = null;
21996
+ this._lookupTables = new Set();
21997
+ this._kaminoVaults = new Set();
21745
21998
  }
21746
21999
  }
21747
22000
 
@@ -22163,8 +22416,10 @@ exports.getOpenfundsPda = getOpenfundsPda;
22163
22416
  exports.getOrderParams = getOrderParams;
22164
22417
  exports.getPriorityFeeEstimate = getPriorityFeeEstimate;
22165
22418
  exports.getSimulationResult = getSimulationResult;
22419
+ exports.getSolAndTokenBalances = getSolAndTokenBalances;
22166
22420
  exports.getStakeAccountsWithStates = getStakeAccountsWithStates;
22167
22421
  exports.getStatePda = getStatePda;
22422
+ exports.getTokenAccountsByOwner = getTokenAccountsByOwner;
22168
22423
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
22169
22424
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;
22170
22425
  exports.getVariant = getVariant;