@glamsystems/glam-sdk 0.1.23 → 0.1.25

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,6 +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
9
  var bytes = require('@coral-xyz/anchor/dist/cjs/utils/bytes');
9
10
  var marinadeTsSdk = require('@marinade.finance/marinade-ts-sdk');
10
11
  var splStakePool = require('@solana/spl-stake-pool');
@@ -33,7 +34,7 @@ var borsh__namespace = /*#__PURE__*/_interopNamespaceDefault(borsh);
33
34
  var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
34
35
  var metadata = {
35
36
  name: "glam_protocol",
36
- version: "0.4.20",
37
+ version: "0.4.24",
37
38
  spec: "0.1.0",
38
39
  description: "Glam Protocol"
39
40
  };
@@ -2931,11 +2932,6 @@ var instructions = [
2931
2932
  name: "escrow",
2932
2933
  writable: true
2933
2934
  },
2934
- {
2935
- name: "payer",
2936
- writable: true,
2937
- signer: true
2938
- },
2939
2935
  {
2940
2936
  name: "system_program",
2941
2937
  address: "11111111111111111111111111111111"
@@ -4203,6 +4199,126 @@ var instructions = [
4203
4199
  }
4204
4200
  ]
4205
4201
  },
4202
+ {
4203
+ name: "marinade_withdraw_stake_account",
4204
+ discriminator: [
4205
+ 88,
4206
+ 200,
4207
+ 107,
4208
+ 134,
4209
+ 244,
4210
+ 89,
4211
+ 194,
4212
+ 111
4213
+ ],
4214
+ accounts: [
4215
+ {
4216
+ name: "glam_state",
4217
+ writable: true
4218
+ },
4219
+ {
4220
+ name: "glam_vault",
4221
+ writable: true,
4222
+ pda: {
4223
+ seeds: [
4224
+ {
4225
+ kind: "const",
4226
+ value: [
4227
+ 118,
4228
+ 97,
4229
+ 117,
4230
+ 108,
4231
+ 116
4232
+ ]
4233
+ },
4234
+ {
4235
+ kind: "account",
4236
+ path: "glam_state"
4237
+ }
4238
+ ]
4239
+ }
4240
+ },
4241
+ {
4242
+ name: "glam_signer",
4243
+ writable: true,
4244
+ signer: true
4245
+ },
4246
+ {
4247
+ name: "cpi_program",
4248
+ address: "MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD"
4249
+ },
4250
+ {
4251
+ name: "state",
4252
+ writable: true
4253
+ },
4254
+ {
4255
+ name: "msol_mint",
4256
+ writable: true
4257
+ },
4258
+ {
4259
+ name: "burn_msol_from",
4260
+ writable: true
4261
+ },
4262
+ {
4263
+ name: "treasury_msol_account",
4264
+ writable: true
4265
+ },
4266
+ {
4267
+ name: "validator_list",
4268
+ writable: true
4269
+ },
4270
+ {
4271
+ name: "stake_list",
4272
+ writable: true
4273
+ },
4274
+ {
4275
+ name: "stake_withdraw_authority"
4276
+ },
4277
+ {
4278
+ name: "stake_deposit_authority"
4279
+ },
4280
+ {
4281
+ name: "stake_account",
4282
+ writable: true
4283
+ },
4284
+ {
4285
+ name: "split_stake_account",
4286
+ writable: true,
4287
+ signer: true
4288
+ },
4289
+ {
4290
+ name: "clock"
4291
+ },
4292
+ {
4293
+ name: "system_program",
4294
+ address: "11111111111111111111111111111111"
4295
+ },
4296
+ {
4297
+ name: "token_program"
4298
+ },
4299
+ {
4300
+ name: "stake_program"
4301
+ }
4302
+ ],
4303
+ args: [
4304
+ {
4305
+ name: "stake_index",
4306
+ type: "u32"
4307
+ },
4308
+ {
4309
+ name: "validator_index",
4310
+ type: "u32"
4311
+ },
4312
+ {
4313
+ name: "msol_amount",
4314
+ type: "u64"
4315
+ },
4316
+ {
4317
+ name: "beneficiary",
4318
+ type: "pubkey"
4319
+ }
4320
+ ]
4321
+ },
4206
4322
  {
4207
4323
  name: "merkle_distributor_new_claim_and_stake",
4208
4324
  discriminator: [
@@ -4845,16 +4961,16 @@ var instructions = [
4845
4961
  ]
4846
4962
  },
4847
4963
  {
4848
- name: "meteora_dlmm_close_position",
4964
+ name: "meteora_dlmm_close_position2",
4849
4965
  discriminator: [
4850
- 186,
4966
+ 69,
4851
4967
  117,
4852
- 42,
4853
- 24,
4854
- 221,
4855
- 194,
4968
+ 240,
4969
+ 192,
4856
4970
  34,
4857
- 143
4971
+ 79,
4972
+ 62,
4973
+ 230
4858
4974
  ],
4859
4975
  accounts: [
4860
4976
  {
@@ -4895,18 +5011,6 @@ var instructions = [
4895
5011
  name: "position",
4896
5012
  writable: true
4897
5013
  },
4898
- {
4899
- name: "lb_pair",
4900
- writable: true
4901
- },
4902
- {
4903
- name: "bin_array_lower",
4904
- writable: true
4905
- },
4906
- {
4907
- name: "bin_array_upper",
4908
- writable: true
4909
- },
4910
5014
  {
4911
5015
  name: "rent_receiver",
4912
5016
  writable: true
@@ -4967,11 +5071,6 @@ var instructions = [
4967
5071
  name: "cpi_program",
4968
5072
  address: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
4969
5073
  },
4970
- {
4971
- name: "payer",
4972
- writable: true,
4973
- signer: true
4974
- },
4975
5074
  {
4976
5075
  name: "position",
4977
5076
  writable: true,
@@ -5053,11 +5152,6 @@ var instructions = [
5053
5152
  name: "cpi_program",
5054
5153
  address: "LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo"
5055
5154
  },
5056
- {
5057
- name: "payer",
5058
- writable: true,
5059
- signer: true
5060
- },
5061
5155
  {
5062
5156
  name: "position",
5063
5157
  writable: true
@@ -6797,6 +6891,102 @@ var instructions = [
6797
6891
  }
6798
6892
  ]
6799
6893
  },
6894
+ {
6895
+ name: "set_protocol_fees",
6896
+ discriminator: [
6897
+ 49,
6898
+ 143,
6899
+ 189,
6900
+ 18,
6901
+ 56,
6902
+ 206,
6903
+ 158,
6904
+ 226
6905
+ ],
6906
+ accounts: [
6907
+ {
6908
+ name: "glam_state",
6909
+ writable: true
6910
+ },
6911
+ {
6912
+ name: "signer",
6913
+ writable: true,
6914
+ signer: true
6915
+ },
6916
+ {
6917
+ name: "glam_config",
6918
+ pda: {
6919
+ seeds: [
6920
+ {
6921
+ kind: "const",
6922
+ value: [
6923
+ 103,
6924
+ 108,
6925
+ 111,
6926
+ 98,
6927
+ 97,
6928
+ 108,
6929
+ 95,
6930
+ 99,
6931
+ 111,
6932
+ 110,
6933
+ 102,
6934
+ 105,
6935
+ 103
6936
+ ]
6937
+ }
6938
+ ],
6939
+ program: {
6940
+ kind: "const",
6941
+ value: [
6942
+ 10,
6943
+ 11,
6944
+ 0,
6945
+ 83,
6946
+ 72,
6947
+ 16,
6948
+ 46,
6949
+ 144,
6950
+ 46,
6951
+ 42,
6952
+ 79,
6953
+ 22,
6954
+ 157,
6955
+ 123,
6956
+ 21,
6957
+ 242,
6958
+ 192,
6959
+ 146,
6960
+ 1,
6961
+ 78,
6962
+ 88,
6963
+ 59,
6964
+ 102,
6965
+ 9,
6966
+ 190,
6967
+ 226,
6968
+ 92,
6969
+ 189,
6970
+ 187,
6971
+ 232,
6972
+ 83,
6973
+ 220
6974
+ ]
6975
+ }
6976
+ }
6977
+ }
6978
+ ],
6979
+ args: [
6980
+ {
6981
+ name: "base_fee_bps",
6982
+ type: "u16"
6983
+ },
6984
+ {
6985
+ name: "flow_fee_bps",
6986
+ type: "u16"
6987
+ }
6988
+ ]
6989
+ },
6800
6990
  {
6801
6991
  name: "set_token_accounts_states",
6802
6992
  discriminator: [
@@ -6901,7 +7091,7 @@ var instructions = [
6901
7091
  type: "pubkey"
6902
7092
  },
6903
7093
  {
6904
- name: "staker_with_withdrawer",
7094
+ name: "staker_or_withdrawer",
6905
7095
  type: "u32"
6906
7096
  }
6907
7097
  ]
@@ -9307,6 +9497,26 @@ var errors = [
9307
9497
  name: "TimelockStillActive",
9308
9498
  msg: "Timelock still active"
9309
9499
  },
9500
+ {
9501
+ code: 48006,
9502
+ name: "AssetNotBorrowable",
9503
+ msg: "Asset is not allowed to borrow"
9504
+ },
9505
+ {
9506
+ code: 48007,
9507
+ name: "InvalidAccountOwner",
9508
+ msg: "Account owned by an invalid program"
9509
+ },
9510
+ {
9511
+ code: 48008,
9512
+ name: "InvalidAuthority",
9513
+ msg: "Invalid authority"
9514
+ },
9515
+ {
9516
+ code: 48009,
9517
+ name: "InvalidPriceDenom",
9518
+ msg: "Invalid price denom"
9519
+ },
9310
9520
  {
9311
9521
  code: 49000,
9312
9522
  name: "InvalidAccountType",
@@ -9497,6 +9707,16 @@ var errors = [
9497
9707
  name: "MathError",
9498
9708
  msg: "Math error"
9499
9709
  },
9710
+ {
9711
+ code: 51108,
9712
+ name: "TypeCastingError",
9713
+ msg: "Type casting error"
9714
+ },
9715
+ {
9716
+ code: 51109,
9717
+ name: "BaseAssetNotSupported",
9718
+ msg: "Base asset must have 6 decimals."
9719
+ },
9500
9720
  {
9501
9721
  code: 52000,
9502
9722
  name: "TransfersDisabled",
@@ -10045,6 +10265,9 @@ var types = [
10045
10265
  },
10046
10266
  {
10047
10267
  name: "MeteoraDlmmPools"
10268
+ },
10269
+ {
10270
+ name: "BorrowableAssets"
10048
10271
  }
10049
10272
  ]
10050
10273
  }
@@ -11642,6 +11865,9 @@ var types = [
11642
11865
  },
11643
11866
  {
11644
11867
  name: "MarinadeState"
11868
+ },
11869
+ {
11870
+ name: "BaseAsset"
11645
11871
  }
11646
11872
  ]
11647
11873
  }
@@ -12538,14 +12764,6 @@ var types = [
12538
12764
  }
12539
12765
  }
12540
12766
  },
12541
- {
12542
- name: "external_vault_accounts",
12543
- type: {
12544
- option: {
12545
- vec: "pubkey"
12546
- }
12547
- }
12548
- },
12549
12767
  {
12550
12768
  name: "mints",
12551
12769
  type: {
@@ -12634,6 +12852,14 @@ var types = [
12634
12852
  }
12635
12853
  }
12636
12854
  },
12855
+ {
12856
+ name: "borrowable_assets",
12857
+ type: {
12858
+ option: {
12859
+ vec: "pubkey"
12860
+ }
12861
+ }
12862
+ },
12637
12863
  {
12638
12864
  name: "drift_market_indexes_perp",
12639
12865
  type: {
@@ -12870,19 +13096,15 @@ const METEORA_POSITION_SIZE = 8120;
12870
13096
  const KAMINO_OBTRIGATION_SIZE = 3344;
12871
13097
  const JITO_TIP_DEFAULT = new web3_js.PublicKey("96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5");
12872
13098
  const KAMINO_SCOPE_PRICES = new web3_js.PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C");
13099
+ const MARINADE_NATIVE_STAKE_AUTHORITY = new web3_js.PublicKey("stWirqFCf2Uts1JBL1Jsd3r6VBWhgnpdPxCTe1MFjrq");
12873
13100
  /**
12874
13101
  * Token mints. If no devnet version is defined, assume mainnet and devnet addresses are the same.
12875
13102
  *
12876
13103
  * Unless otherwise noted, all mints have 9 decimals.
12877
13104
  */ const WSOL = new web3_js.PublicKey("So11111111111111111111111111111111111111112");
12878
13105
  const MSOL = new web3_js.PublicKey("mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So");
12879
- const JITOSOL = new web3_js.PublicKey("J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn");
12880
13106
  // USDC, 6 decimals
12881
13107
  const USDC = new web3_js.PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
12882
- // Wrapped ETH (Wormhole), 8 decimals
12883
- const WETH = new web3_js.PublicKey("7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs");
12884
- // Wrapped BTC (Wormhole), 8 decimals
12885
- const WBTC = new web3_js.PublicKey("3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh");
12886
13108
  // JUP, 6 decimals
12887
13109
  const JUP = new web3_js.PublicKey("JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN");
12888
13110
  /**
@@ -12918,7 +13140,6 @@ class StateIdlModel {
12918
13140
  this.uri = data.uri ?? null;
12919
13141
  this.enabled = data.enabled ?? null;
12920
13142
  this.assets = data.assets ?? null;
12921
- this.externalVaultAccounts = data.externalVaultAccounts ?? null;
12922
13143
  this.mints = data.mints ?? null;
12923
13144
  this.company = data.company ?? null;
12924
13145
  this.owner = data.owner ?? null;
@@ -12930,6 +13151,7 @@ class StateIdlModel {
12930
13151
  // ACLs
12931
13152
  this.delegateAcls = data.delegateAcls ?? null;
12932
13153
  this.integrations = data.integrations ?? null;
13154
+ this.borrowableAssets = data.borrowableAssets ?? null;
12933
13155
  // Integration specific configs
12934
13156
  this.driftMarketIndexesPerp = data.driftMarketIndexesPerp ?? null;
12935
13157
  this.driftMarketIndexesSpot = data.driftMarketIndexesSpot ?? null;
@@ -13005,24 +13227,32 @@ class StateModel extends StateIdlModel {
13005
13227
  created: stateAccount.created,
13006
13228
  delegateAcls: stateAccount.delegateAcls,
13007
13229
  integrations: stateAccount.integrations,
13008
- owner: new ManagerModel({
13009
- pubkey: stateAccount.owner
13010
- }),
13011
13230
  mints: []
13012
13231
  };
13013
13232
  // All fields in fund params[0] should be available on the StateModel
13014
- // @ts-ignore
13015
13233
  stateAccount.params[0].forEach((param)=>{
13016
13234
  const name = Object.keys(param.name)[0];
13017
13235
  // @ts-ignore
13018
13236
  const value = Object.values(param.value)[0].val;
13019
- if (new StateIdlModel({}).hasOwnProperty(name)) {
13237
+ if (new StateModel({}).hasOwnProperty(name)) {
13020
13238
  // @ts-ignore
13021
13239
  stateModel[name] = value;
13022
13240
  } else if (process.env.NODE_ENV === "development") {
13023
- console.warn(`State param ${name} not found in StateIdlModel`);
13241
+ console.warn(`State param ${name} not found in StateModel`);
13024
13242
  }
13025
13243
  });
13244
+ // If timelock is enabled, parse pending updates from params[2] and params[3]
13245
+ stateModel.pendingUpdates = {};
13246
+ if (stateAccount.params[2]) {
13247
+ // pending updates to state params
13248
+ stateAccount.params[2].forEach((param)=>{
13249
+ const name = Object.keys(param.name)[0];
13250
+ // @ts-ignore
13251
+ const value = Object.values(param.value)[0].val;
13252
+ stateModel.pendingUpdates[name] = value;
13253
+ });
13254
+ }
13255
+ if (stateAccount.params[3]) ;
13026
13256
  // Build stateModel.rawOpenfunds from openfunds account
13027
13257
  const fundOpenfundsFields = {};
13028
13258
  openfundsMetadataAccount?.fund.forEach((param)=>{
@@ -13041,6 +13271,17 @@ class StateModel extends StateIdlModel {
13041
13271
  company[name] = value;
13042
13272
  });
13043
13273
  stateModel.company = new CompanyModel(company);
13274
+ // Build stateModel.owner from openfunds account
13275
+ const owner = {
13276
+ pubkey: stateAccount.owner
13277
+ };
13278
+ openfundsMetadataAccount?.fundManagers[0].forEach((param)=>{
13279
+ const name = Object.keys(param.name)[0];
13280
+ const value = param.value;
13281
+ // @ts-ignore
13282
+ owner[name] = value;
13283
+ });
13284
+ stateModel.owner = new ManagerModel(owner);
13044
13285
  // Build the array of ShareClassModel
13045
13286
  stateAccount.mints.forEach((_, i)=>{
13046
13287
  const mintIdlModel = {};
@@ -13049,6 +13290,12 @@ class StateModel extends StateIdlModel {
13049
13290
  const name = Object.keys(param.name)[0];
13050
13291
  // @ts-ignore
13051
13292
  const value = Object.values(param.value)[0].val;
13293
+ // Ledger is a mint param but we store it on the state model
13294
+ if (Object.keys(stateAccount.accountType)[0] === "fund") {
13295
+ if (name === "ledger") {
13296
+ stateModel["ledger"] = value;
13297
+ }
13298
+ }
13052
13299
  mintIdlModel[name] = value;
13053
13300
  });
13054
13301
  if (openfundsMetadataAccount) {
@@ -13090,6 +13337,12 @@ class StateModel extends StateIdlModel {
13090
13337
  constructor(data, glamProgramId = GLAM_PROGRAM_ID_DEFAULT){
13091
13338
  super(data);
13092
13339
  this.glamProgramId = glamProgramId;
13340
+ // Will be set from state params
13341
+ this.externalVaultAccounts = data.externalVaultAccounts ?? null;
13342
+ this.pricedAssets = data.pricedAssets ?? null;
13343
+ this.ledger = data.ledger ?? null;
13344
+ this.timelockExpiresAt = data.timelockExpiresAt ? Number(data.timelockExpiresAt.toString()) : null;
13345
+ this.pendingUpdates = data.pendingUpdates ?? null;
13093
13346
  }
13094
13347
  }
13095
13348
  class FundOpenfundsModel {
@@ -13230,6 +13483,15 @@ class DelegateAcl {
13230
13483
  }
13231
13484
  }
13232
13485
  class PriceDenom {
13486
+ static fromAsset(asset) {
13487
+ if (asset.equals(WSOL)) {
13488
+ return PriceDenom.SOL;
13489
+ }
13490
+ if (asset.equals(USDC)) {
13491
+ return PriceDenom.USD;
13492
+ }
13493
+ return PriceDenom.ASSET;
13494
+ }
13233
13495
  }
13234
13496
  PriceDenom.SOL = {
13235
13497
  sol: {}
@@ -13237,6 +13499,9 @@ PriceDenom.SOL = {
13237
13499
  PriceDenom.USD = {
13238
13500
  usd: {}
13239
13501
  };
13502
+ PriceDenom.ASSET = {
13503
+ asset6: {}
13504
+ };
13240
13505
  class TimeUnit {
13241
13506
  }
13242
13507
  TimeUnit.Slot = {
@@ -13255,6 +13520,8 @@ var ClusterNetwork = /*#__PURE__*/ function(ClusterNetwork) {
13255
13520
  }({});
13256
13521
 
13257
13522
  const fetchStakeAccounts = async (connection, withdrawAuthority)=>{
13523
+ // stake authority offset: 12
13524
+ // withdraw authority offset: 44
13258
13525
  const accounts = await connection.getParsedProgramAccounts(web3_js.StakeProgram.programId, {
13259
13526
  filters: [
13260
13527
  {
@@ -13262,7 +13529,7 @@ const fetchStakeAccounts = async (connection, withdrawAuthority)=>{
13262
13529
  },
13263
13530
  {
13264
13531
  memcmp: {
13265
- offset: 12,
13532
+ offset: 44,
13266
13533
  bytes: withdrawAuthority.toBase58()
13267
13534
  }
13268
13535
  }
@@ -13271,7 +13538,55 @@ const fetchStakeAccounts = async (connection, withdrawAuthority)=>{
13271
13538
  // order by lamports desc
13272
13539
  return accounts.sort((a, b)=>b.account.lamports - a.account.lamports).map((a)=>a.pubkey);
13273
13540
  };
13274
- const fetchMarinadeTicketAccounts = async (connection, beneficiary)=>await connection.getParsedProgramAccounts(MARINADE_PROGRAM_ID, {
13541
+ const getStakeAccountsWithStates = async (connection, withdrawAuthority)=>{
13542
+ // stake authority offset: 12
13543
+ // withdraw authority offset: 44
13544
+ const accounts = await connection.getParsedProgramAccounts(web3_js.StakeProgram.programId, {
13545
+ filters: [
13546
+ {
13547
+ dataSize: STAKE_ACCOUNT_SIZE
13548
+ },
13549
+ {
13550
+ memcmp: {
13551
+ offset: 44,
13552
+ bytes: withdrawAuthority.toBase58()
13553
+ }
13554
+ }
13555
+ ]
13556
+ });
13557
+ const epochInfo = await connection.getEpochInfo();
13558
+ const stakes = await Promise.all(accounts.map(async (account)=>{
13559
+ const delegation = account.account.data.parsed.info.stake?.delegation;
13560
+ let state = "undelegated";
13561
+ if (!delegation) {
13562
+ return {
13563
+ address: account.pubkey,
13564
+ lamports: account.account.lamports,
13565
+ state
13566
+ };
13567
+ }
13568
+ // possible state if delegated: active, inactive, activating, deactivating
13569
+ const { activationEpoch, deactivationEpoch, voter } = delegation;
13570
+ if (activationEpoch == epochInfo.epoch) {
13571
+ state = "activating";
13572
+ } else if (deactivationEpoch == epochInfo.epoch) {
13573
+ state = "deactivating";
13574
+ } else if (epochInfo.epoch > deactivationEpoch) {
13575
+ state = "inactive";
13576
+ } else if (epochInfo.epoch > activationEpoch) {
13577
+ state = "active";
13578
+ }
13579
+ return {
13580
+ address: account.pubkey,
13581
+ lamports: account.account.lamports,
13582
+ voter: new web3_js.PublicKey(voter),
13583
+ state
13584
+ };
13585
+ }));
13586
+ // order by lamports desc
13587
+ return stakes.sort((a, b)=>b.lamports - a.lamports);
13588
+ };
13589
+ const fetchMarinadeTicketAccounts = async (connection, beneficiary)=>await connection.getProgramAccounts(MARINADE_PROGRAM_ID, {
13275
13590
  filters: [
13276
13591
  {
13277
13592
  dataSize: MARINADE_TICKET_SIZE
@@ -13285,7 +13600,7 @@ const fetchMarinadeTicketAccounts = async (connection, beneficiary)=>await conne
13285
13600
  ]
13286
13601
  });
13287
13602
  const fetchKaminoObligations = async (connection, owner, market)=>{
13288
- const accounts = await connection.getParsedProgramAccounts(KAMINO_LENDING_PROGRAM, {
13603
+ const accounts = await connection.getProgramAccounts(KAMINO_LENDING_PROGRAM, {
13289
13604
  filters: [
13290
13605
  {
13291
13606
  dataSize: KAMINO_OBTRIGATION_SIZE
@@ -13309,7 +13624,7 @@ const fetchKaminoObligations = async (connection, owner, market)=>{
13309
13624
  return accounts.map((a)=>a.pubkey);
13310
13625
  };
13311
13626
  const fetchMeteoraPositions = async (connection, owner)=>{
13312
- const accounts = await connection.getParsedProgramAccounts(METEORA_DLMM_PROGRAM, {
13627
+ const accounts = await connection.getProgramAccounts(METEORA_DLMM_PROGRAM, {
13313
13628
  filters: [
13314
13629
  {
13315
13630
  dataSize: METEORA_POSITION_SIZE
@@ -13346,28 +13661,23 @@ const parseMeteoraPosition = async (connection, position)=>{
13346
13661
  };
13347
13662
  };
13348
13663
  async function fetchLookupTables(connection, authority, firstEntry) {
13349
- const ALT_PROGRAM_ID = new web3_js.PublicKey("AddressLookupTab1e1111111111111111111111111");
13664
+ new web3_js.PublicKey("AddressLookupTab1e1111111111111111111111111");
13350
13665
  // Fetch all accounts owned by the ALT program
13351
- const accounts = await connection.getProgramAccounts(ALT_PROGRAM_ID, {
13352
- filters: [
13353
- {
13354
- memcmp: {
13355
- offset: 22,
13356
- bytes: authority.toBase58()
13357
- }
13358
- },
13359
- {
13360
- memcmp: {
13361
- offset: 56,
13362
- bytes: firstEntry.toBase58()
13363
- }
13364
- }
13365
- ]
13366
- });
13367
- return accounts.map(({ pubkey, account })=>new web3_js.AddressLookupTableAccount({
13368
- key: pubkey,
13369
- state: web3_js.AddressLookupTableAccount.deserialize(account.data)
13370
- }));
13666
+ // This is currently disabled due to RPC error "Request deprioritized due to number of accounts requested. Slow down requests or add filters to narrow down results"
13667
+ // const accounts = await connection.getProgramAccounts(ALT_PROGRAM_ID, {
13668
+ // filters: [
13669
+ // { memcmp: { offset: 22, bytes: authority.toBase58() } },
13670
+ // { memcmp: { offset: 56, bytes: firstEntry.toBase58() } }, // 1st entry in the table
13671
+ // ],
13672
+ // });
13673
+ // return accounts.map(
13674
+ // ({ pubkey, account }) =>
13675
+ // new AddressLookupTableAccount({
13676
+ // key: pubkey,
13677
+ // state: AddressLookupTableAccount.deserialize(account.data),
13678
+ // }),
13679
+ // );
13680
+ return [];
13371
13681
  }
13372
13682
  const getSimulationComputeUnits = async (connection, instructions, payer, lookupTables)=>{
13373
13683
  const testInstructions = [
@@ -13411,14 +13721,14 @@ const getErrorFromRPCResponse = (rpcResponse)=>{
13411
13721
  // @ts-ignore due to missing typing information mentioned above.
13412
13722
  const instructionError = error["InstructionError"];
13413
13723
  // An instruction error is a custom program error and looks like:
13414
- // [
13415
- // 1,
13416
- // {
13417
- // "Custom": 1
13418
- // }
13419
- // ]
13724
+ // [1, {"Custom": 1}]
13420
13725
  // See also https://solana.stackexchange.com/a/931/294
13421
- throw new Error(`Error in transaction: instruction index ${instructionError[0]}, custom program error ${instructionError[1]["Custom"]}`);
13726
+ const customErrorCode = instructionError[1]["Custom"];
13727
+ const { errors: glamErrors } = GlamProtocolIdlJson;
13728
+ const glamError = glamErrors.find((e)=>e.code === customErrorCode);
13729
+ const msg = glamError?.msg || "Unknown custsom error";
13730
+ console.log(`Custom error code: ${customErrorCode}, error: ${msg}}`);
13731
+ throw new Error(msg);
13422
13732
  }
13423
13733
  }
13424
13734
  throw Error(error.toString());
@@ -13432,6 +13742,21 @@ const setsAreEqual = (a, b)=>{
13432
13742
  return true;
13433
13743
  };
13434
13744
 
13745
+ 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)=>{
13746
+ const { pool, tokenProgram } = lst.pool;
13747
+ return {
13748
+ name: lst.name,
13749
+ symbol: lst.symbol,
13750
+ mint: lst.mint,
13751
+ logoURI: lst.logoUri,
13752
+ tokenProgram,
13753
+ poolState: lst.pool.program === "Marinade" ? "8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC" : pool || ""
13754
+ };
13755
+ });
13756
+ const STAKE_POOLS_MAP = new Map(STAKE_POOLS.map((p)=>[
13757
+ p.mint,
13758
+ p
13759
+ ]));
13435
13760
  const ASSETS_MAINNET = new Map([
13436
13761
  [
13437
13762
  // SOL
@@ -13497,12 +13822,52 @@ const ASSETS_MAINNET = new Map([
13497
13822
  oracle: new web3_js.PublicKey("JDKJSkxjasBGL3ce1pkrN6tqDzuVUZPWzzkGuyX8m9yN")
13498
13823
  }
13499
13824
  ],
13825
+ [
13826
+ // USDY
13827
+ "A1KLoBrKBde8Ty9qtNQUtq3C2ortoC3u7twggz7sEto6",
13828
+ {
13829
+ decimals: 6,
13830
+ oracle: new web3_js.PublicKey("9PgHM68FNGDK6nHb29ERDBcFrV6gNMD8LyUqwxbyyeb2")
13831
+ }
13832
+ ],
13833
+ [
13834
+ // PYUSD
13835
+ "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
13836
+ {
13837
+ decimals: 6,
13838
+ oracle: new web3_js.PublicKey("5QZMnsyndmphvZF4BNgoMHwVZaREXeE2rpBoCPMxgCCd"),
13839
+ programId: splToken.TOKEN_2022_PROGRAM_ID
13840
+ }
13841
+ ],
13842
+ [
13843
+ // USDe
13844
+ "DEkqHyPN7GMRJ5cArtQFAWefqbZb33Hyf6s5iCwjEonT",
13845
+ {
13846
+ decimals: 6,
13847
+ oracle: new web3_js.PublicKey("5uR6oza6teuMRpjsbMi9fDhCDid2hoYdRBiLW7WzcK54")
13848
+ }
13849
+ ],
13850
+ [
13851
+ // sUSDe
13852
+ "Eh6XEPhSwoLv5wFApukmnaVSHQ6sAnoD9BmgmwQoN2sN",
13853
+ {
13854
+ decimals: 6,
13855
+ oracle: new web3_js.PublicKey("BRuNuzLAPHHGSSVAJPKMcmJMdgDfrekvnSxkxPDGdeqp")
13856
+ }
13857
+ ],
13858
+ [
13859
+ // USDS
13860
+ "USDSwr9ApdHk5bvJKMjzff41FfuX8bSxdKcR81vTwcA",
13861
+ {
13862
+ decimals: 6,
13863
+ oracle: new web3_js.PublicKey("7pT9mxKXyvfaZKeKy1oe2oV2K1RFtF7tPEJHUY3h2vVV")
13864
+ }
13865
+ ],
13500
13866
  [
13501
13867
  // mSOL
13502
13868
  "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
13503
13869
  {
13504
13870
  decimals: 9,
13505
- // oracle: new PublicKey("FAq7hqjn7FWGXKDwJHzsXGgBcydGTcK4kziJpAGWXjDb"), // drift pyth
13506
13871
  oracle: new web3_js.PublicKey("8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC")
13507
13872
  }
13508
13873
  ],
@@ -13511,8 +13876,8 @@ const ASSETS_MAINNET = new Map([
13511
13876
  "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
13512
13877
  {
13513
13878
  decimals: 9,
13514
- // oracle: new PublicKey("9QE1P5EfzthYDgoQ9oPeTByCEKaRJeZbVVqKJfgU9iau"), // drift pyth
13515
- oracle: new web3_js.PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb")
13879
+ oracle: new web3_js.PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb"),
13880
+ isLst: true
13516
13881
  }
13517
13882
  ],
13518
13883
  [
@@ -13520,7 +13885,8 @@ const ASSETS_MAINNET = new Map([
13520
13885
  "BonK1YhkXEGLZzwtcvRTip3gAL9nCeQD7ppZBLXhtTs",
13521
13886
  {
13522
13887
  decimals: 9,
13523
- oracle: new web3_js.PublicKey("ArAQfbzsdotoKB5jJcZa3ajQrrPcWr2YQoDAEAiFxJAC")
13888
+ oracle: new web3_js.PublicKey("ArAQfbzsdotoKB5jJcZa3ajQrrPcWr2YQoDAEAiFxJAC"),
13889
+ isLst: true
13524
13890
  }
13525
13891
  ],
13526
13892
  [
@@ -13528,7 +13894,8 @@ const ASSETS_MAINNET = new Map([
13528
13894
  "Dso1bDeDjCQxTrWHqUUi63oBvV7Mdm6WaobLbQ7gnPQ",
13529
13895
  {
13530
13896
  decimals: 9,
13531
- oracle: new web3_js.PublicKey("9mhGNSPArRMHpLDMSmxAvuoizBqtBGqYdT8WGuqgxNdn")
13897
+ oracle: new web3_js.PublicKey("9mhGNSPArRMHpLDMSmxAvuoizBqtBGqYdT8WGuqgxNdn"),
13898
+ isLst: true
13532
13899
  }
13533
13900
  ]
13534
13901
  ]);
@@ -13786,12 +14153,14 @@ class BaseClient {
13786
14153
  // - gui: wallet apps usually do the simulation themselves, we should ignore the simulation error here by default
13787
14154
  // - cli: we should set simulate=true
13788
14155
  if (simulate) {
13789
- tx.recentBlockhash = recentBlockhash;
13790
- tx.feePayer = signer;
13791
- console.log("Tx (base64):", tx.serialize({
13792
- verifySignatures: false
13793
- }).toString("base64"));
13794
- console.error("Simulation failed. If error message is too obscure, inspect the tx in explorer (https://explorer.solana.com/tx/inspector)");
14156
+ const vTx = new web3_js.VersionedTransaction(new web3_js.TransactionMessage({
14157
+ instructions,
14158
+ payerKey: signer,
14159
+ recentBlockhash: web3_js.PublicKey.default.toString()
14160
+ }).compileToV0Message(lookupTables));
14161
+ console.log("Lookup tables:", lookupTables.map((lt)=>lt.key.toString()));
14162
+ console.log("Tx (base64):", Buffer.from(vTx.serialize()).toString("base64"));
14163
+ console.error("Simulation failed. If error message is too obscure, inspect and simulate the tx in explorer: https://explorer.solana.com/tx/inspector");
13795
14164
  throw e;
13796
14165
  }
13797
14166
  }
@@ -14019,7 +14388,7 @@ class BaseClient {
14019
14388
  if (state.params.length < 2) {
14020
14389
  throw new Error("Invalid mint index");
14021
14390
  }
14022
- // iterate over the mint params
14391
+ // Iterate over the mint params
14023
14392
  for (const param of state.params[1]){
14024
14393
  const name = Object.keys(param.name)[0];
14025
14394
  // @ts-ignore
@@ -14081,7 +14450,9 @@ class BaseClient {
14081
14450
  }
14082
14451
  return "";
14083
14452
  }
14084
- async listGlamStates() {
14453
+ /**
14454
+ * @deprecated
14455
+ */ async listGlamStates() {
14085
14456
  const bytes$1 = Uint8Array.from([
14086
14457
  0x31,
14087
14458
  0x68,
@@ -14092,7 +14463,7 @@ class BaseClient {
14092
14463
  0xad,
14093
14464
  0x9a
14094
14465
  ]);
14095
- const accounts = await this.provider.connection.getParsedProgramAccounts(this.program.programId, {
14466
+ const accounts = await this.provider.connection.getProgramAccounts(this.program.programId, {
14096
14467
  filters: [
14097
14468
  {
14098
14469
  memcmp: {
@@ -14169,7 +14540,7 @@ class BaseClient {
14169
14540
  this.statePda = config.statePda;
14170
14541
  }
14171
14542
  this.jupiterApi = config?.jupiterApi || JUPITER_API_DEFAULT;
14172
- this.blockhashWithCache = new BlockhashWithCache(this.provider, !!isBrowser);
14543
+ this.blockhashWithCache = new BlockhashWithCache(this.provider, false);
14173
14544
  }
14174
14545
  }
14175
14546
 
@@ -16113,10 +16484,20 @@ class MarinadeClient {
16113
16484
  const tx = await this.depositTx(amount, txOptions);
16114
16485
  return await this.base.sendAndConfirm(tx);
16115
16486
  }
16487
+ async depositNative(amount, txOptions = {}) {
16488
+ const tx = await this.depositNativeTx(amount, txOptions);
16489
+ return await this.base.sendAndConfirm(tx);
16490
+ }
16116
16491
  async depositStakeAccount(stakeAccount) {
16117
16492
  const tx = await this.depositStakeAccountTx(stakeAccount, {});
16118
16493
  return await this.base.sendAndConfirm(tx);
16119
16494
  }
16495
+ async withdrawStakeAccount(amount, txOptions = {}) {
16496
+ const [tx, extraSigner] = await this.withdrawStakeAccountTx(amount, txOptions);
16497
+ return await this.base.sendAndConfirm(tx, [
16498
+ extraSigner
16499
+ ]);
16500
+ }
16120
16501
  async orderUnstake(amount, txOptions = {}) {
16121
16502
  const tx = await this.orderUnstakeTx(amount, txOptions);
16122
16503
  return await this.base.sendAndConfirm(tx);
@@ -16149,10 +16530,11 @@ class MarinadeClient {
16149
16530
  };
16150
16531
  });
16151
16532
  }
16152
- getMarinadeState() {
16533
+ /**
16534
+ * @deprecated Use Marinade.getMarinadeState() instead
16535
+ */ get marinadeStateStatic() {
16153
16536
  // The addresses are the same in mainnet and devnet:
16154
16537
  // https://docs.marinade.finance/developers/contract-addresses
16155
- // TODO: use marinade.getMarinadeState(); ?
16156
16538
  return {
16157
16539
  marinadeStateAddress: new web3_js.PublicKey("8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC"),
16158
16540
  msolMintAddress: MSOL,
@@ -16164,6 +16546,12 @@ class MarinadeClient {
16164
16546
  solLeg: new web3_js.PublicKey("UefNb6z6yvArqe4cJHTXCqStRsKmWhGxnZzuHbikP5Q")
16165
16547
  };
16166
16548
  }
16549
+ async fetchMarinadeState() {
16550
+ const marinade = new marinadeTsSdk.Marinade(new marinadeTsSdk.MarinadeConfig({
16551
+ connection: this.base.provider.connection
16552
+ }));
16553
+ return await marinade.getMarinadeState();
16554
+ }
16167
16555
  async getParsedStakeAccountInfo(stakeAccount) {
16168
16556
  const { value: stakeAccountInfo } = await this.base.provider.connection.getParsedAccountInfo(stakeAccount);
16169
16557
  if (!stakeAccountInfo) {
@@ -16176,7 +16564,7 @@ class MarinadeClient {
16176
16564
  const balanceLamports = stakeAccountInfo.lamports;
16177
16565
  const stakedLamports = parsedData?.parsed?.info?.stake?.delegation?.stake ?? null;
16178
16566
  if (parsedData.space != 200) {
16179
- throw new Error(`${stakeAccount.toBase58()} is not a stake account because space is ${parsedData.space} != 200`);
16567
+ throw new Error(`${stakeAccount} is not a stake account. Account size ${parsedData.space} != 200`);
16180
16568
  }
16181
16569
  return {
16182
16570
  voter: new web3_js.PublicKey(parsedData.parsed.info?.stake?.delegation?.voter),
@@ -16189,7 +16577,7 @@ class MarinadeClient {
16189
16577
  */ async depositTx(amount, txOptions) {
16190
16578
  const glamSigner = txOptions.signer || this.base.getSigner();
16191
16579
  const vault = this.base.vaultPda;
16192
- const marinadeState = this.getMarinadeState();
16580
+ const marinadeState = this.marinadeStateStatic;
16193
16581
  const vaultMsolAta = this.base.getVaultAta(marinadeState.msolMintAddress);
16194
16582
  const createMsolAtaIx = splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, vaultMsolAta, vault, marinadeState.msolMintAddress);
16195
16583
  // @ts-ignore
@@ -16210,11 +16598,54 @@ class MarinadeClient {
16210
16598
  ]).transaction();
16211
16599
  return await this.base.intoVersionedTransaction(tx, txOptions);
16212
16600
  }
16601
+ async createStakeAccount(signer) {
16602
+ const seed = Date.now().toString();
16603
+ const stakeAccount = await web3_js.PublicKey.createWithSeed(signer, seed, web3_js.StakeProgram.programId);
16604
+ const lamports = await this.base.provider.connection.getMinimumBalanceForRentExemption(STAKE_ACCOUNT_SIZE);
16605
+ const createStakeAccountIx = web3_js.SystemProgram.createAccountWithSeed({
16606
+ fromPubkey: signer,
16607
+ newAccountPubkey: stakeAccount,
16608
+ basePubkey: signer,
16609
+ seed,
16610
+ lamports,
16611
+ space: STAKE_ACCOUNT_SIZE,
16612
+ programId: web3_js.StakeProgram.programId
16613
+ });
16614
+ return [
16615
+ stakeAccount,
16616
+ createStakeAccountIx
16617
+ ];
16618
+ }
16619
+ async depositNativeTx(amount, txOptions) {
16620
+ const glamSigner = txOptions.signer || this.base.getSigner();
16621
+ // Create and fund the stake account
16622
+ const [stakeAccount, createStakeAccountIx] = await this.createStakeAccount(glamSigner);
16623
+ const initStakeIx = await this.base.program.methods.stakeInitialize().accounts({
16624
+ glamState: this.base.statePda,
16625
+ glamSigner,
16626
+ stake: stakeAccount
16627
+ }).instruction();
16628
+ const fundStakeIx = await this.base.program.methods.systemTransfer(amount).accounts({
16629
+ glamState: this.base.statePda,
16630
+ glamSigner,
16631
+ to: stakeAccount
16632
+ }).instruction();
16633
+ // Then set stake authority to the marinade key
16634
+ const tx = await this.base.program.methods.stakeAuthorize(MARINADE_NATIVE_STAKE_AUTHORITY, 0).accounts({
16635
+ glamState: this.base.statePda,
16636
+ glamSigner,
16637
+ stake: stakeAccount
16638
+ }).preInstructions([
16639
+ createStakeAccountIx,
16640
+ initStakeIx,
16641
+ fundStakeIx
16642
+ ]).transaction();
16643
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16644
+ }
16213
16645
  async depositStakeAccountTx(stakeAccount, txOptions) {
16214
16646
  const glamSigner = txOptions.signer || this.base.getSigner();
16215
16647
  const stakeAccountInfo = await this.getParsedStakeAccountInfo(stakeAccount);
16216
- console.log("Stake account info", stakeAccountInfo);
16217
- const marinadeState = await new marinadeTsSdk.Marinade().getMarinadeState();
16648
+ const marinadeState = await this.fetchMarinadeState();
16218
16649
  const { validatorRecords } = await marinadeState.getValidatorRecords();
16219
16650
  const validatorLookupIndex = validatorRecords.findIndex(({ validatorAccount })=>validatorAccount.equals(stakeAccountInfo.voter));
16220
16651
  const validatorIndex = validatorLookupIndex === -1 ? marinadeState.state.validatorSystem.validatorList.count : validatorLookupIndex;
@@ -16236,9 +16667,71 @@ class MarinadeClient {
16236
16667
  }).transaction();
16237
16668
  return await this.base.intoVersionedTransaction(tx, txOptions);
16238
16669
  }
16670
+ parseAccountList(data, itemSize) {
16671
+ const accounts = [];
16672
+ for(let i = 8; i < data.length; i += itemSize){
16673
+ accounts.push(new web3_js.PublicKey(data.subarray(i, i + 32)));
16674
+ }
16675
+ return accounts;
16676
+ }
16677
+ async getIndexes(stakeAccount, stakeList, validatorList) {
16678
+ if (!stakeAccount.voter) {
16679
+ throw new Error("Stake account is not delegated");
16680
+ }
16681
+ const accountsInfo = await this.base.provider.connection.getMultipleAccountsInfo([
16682
+ stakeList.account,
16683
+ validatorList.account
16684
+ ]);
16685
+ if (!accountsInfo[0] || !accountsInfo[1]) {
16686
+ throw new Error("Failed to get accounts info of stakeList and validatorList");
16687
+ }
16688
+ const stakeIndex = this.parseAccountList(accountsInfo[0].data, stakeList.itemSize).findIndex((a)=>a.equals(stakeAccount.address));
16689
+ const validatorIndex = this.parseAccountList(accountsInfo[1].data, validatorList.itemSize).findIndex((a)=>a.equals(stakeAccount.voter));
16690
+ return {
16691
+ stakeIndex,
16692
+ validatorIndex
16693
+ };
16694
+ }
16695
+ async withdrawStakeAccountTx(amount, txOptions) {
16696
+ const glamSigner = txOptions.signer || this.base.getSigner();
16697
+ const marinadeState = await this.fetchMarinadeState();
16698
+ // Get mariande stake withdraw authority
16699
+ const stakeWithdrawAuthority = await marinadeState.stakeWithdrawAuthority();
16700
+ const stakeDepositAuthority = await marinadeState.stakeDepositAuthority();
16701
+ const stakeList = marinadeState.state.stakeSystem.stakeList;
16702
+ const validatorList = marinadeState.state.validatorSystem.validatorList;
16703
+ // Fetch stake accounts by withdraw authority
16704
+ // Filter by state "active" does not work in localnet tests
16705
+ const stakeAccounts = await getStakeAccountsWithStates(this.base.provider.connection, stakeWithdrawAuthority);
16706
+ const { stakeIndex, validatorIndex } = await this.getIndexes(stakeAccounts[0], stakeList, validatorList);
16707
+ const burnMsolFrom = this.base.getVaultAta(MSOL);
16708
+ const newStake = web3_js.Keypair.generate();
16709
+ const tx = await this.base.program.methods.marinadeWithdrawStakeAccount(stakeIndex, validatorIndex, amount, this.base.vaultPda).accounts({
16710
+ glamState: this.base.statePda,
16711
+ glamSigner,
16712
+ state: marinadeState.marinadeStateAddress,
16713
+ validatorList: validatorList.account,
16714
+ stakeList: stakeList.account,
16715
+ stakeAccount: stakeAccounts[0].address,
16716
+ stakeWithdrawAuthority,
16717
+ stakeDepositAuthority,
16718
+ treasuryMsolAccount: marinadeState.treasuryMsolAccount,
16719
+ msolMint: MSOL,
16720
+ burnMsolFrom,
16721
+ splitStakeAccount: newStake.publicKey,
16722
+ clock: web3_js.SYSVAR_CLOCK_PUBKEY,
16723
+ tokenProgram: splToken.TOKEN_PROGRAM_ID,
16724
+ stakeProgram: web3_js.StakeProgram.programId
16725
+ }).transaction();
16726
+ const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16727
+ return [
16728
+ vTx,
16729
+ newStake
16730
+ ];
16731
+ }
16239
16732
  async orderUnstakeTx(amount, txOptions) {
16240
16733
  const glamSigner = txOptions.signer || this.base.getSigner();
16241
- const marinadeState = this.getMarinadeState();
16734
+ const marinadeState = this.marinadeStateStatic;
16242
16735
  const vaultMsolAta = this.base.getVaultAta(marinadeState.msolMintAddress);
16243
16736
  const ticketSeed = Date.now().toString();
16244
16737
  const ticket = await web3_js.PublicKey.createWithSeed(glamSigner, ticketSeed, MARINADE_PROGRAM_ID);
@@ -16271,7 +16764,7 @@ class MarinadeClient {
16271
16764
  throw new Error("At least one ticket is required");
16272
16765
  }
16273
16766
  const glamSigner = txOptions.signer || this.base.getSigner();
16274
- const marinadeState = this.getMarinadeState();
16767
+ const marinadeState = this.marinadeStateStatic;
16275
16768
  const instructions = await Promise.all(tickets.map((ticket)=>this.base.program.methods.marinadeClaim().accounts({
16276
16769
  glamState: this.base.statePda,
16277
16770
  glamSigner,
@@ -16289,7 +16782,7 @@ class MarinadeClient {
16289
16782
  }
16290
16783
  }
16291
16784
 
16292
- class WSolClient {
16785
+ class VaultClient {
16293
16786
  /*
16294
16787
  * Client methods
16295
16788
  */ async wrap(amount, txOptions = {}) {
@@ -16300,6 +16793,26 @@ class WSolClient {
16300
16793
  const tx = await this.unwrapTx(txOptions);
16301
16794
  return await this.base.sendAndConfirm(tx);
16302
16795
  }
16796
+ async systemTransfer(amount, to, txOptions = {}) {
16797
+ const tx = await this.systemTransferTx(new anchor.BN(amount), new web3_js.PublicKey(to), txOptions);
16798
+ return await this.base.sendAndConfirm(tx);
16799
+ }
16800
+ async closeTokenAccounts(tokenAccounts, txOptions = {}) {
16801
+ const tx = await this.closeTokenAccountsTx(tokenAccounts, txOptions);
16802
+ return await this.base.sendAndConfirm(tx);
16803
+ }
16804
+ async deposit(asset, amount, txOptions = {}) {
16805
+ const tx = await this.depositTx(new web3_js.PublicKey(asset), amount, txOptions);
16806
+ return await this.base.sendAndConfirm(tx);
16807
+ }
16808
+ async depositSol(lamports, wrap = true, txOptions = {}) {
16809
+ const tx = await this.depositSolTx(lamports, wrap, txOptions);
16810
+ return await this.base.sendAndConfirm(tx);
16811
+ }
16812
+ async withdraw(asset, amount, txOptions = {}) {
16813
+ const tx = await this.withdrawTx(new web3_js.PublicKey(asset), amount, txOptions);
16814
+ return await this.base.sendAndConfirm(tx);
16815
+ }
16303
16816
  /*
16304
16817
  * API methods
16305
16818
  */ async wrapTx(amount, txOptions) {
@@ -16328,55 +16841,174 @@ class WSolClient {
16328
16841
  }).transaction();
16329
16842
  return await this.base.intoVersionedTransaction(tx, txOptions);
16330
16843
  }
16331
- constructor(base){
16332
- this.base = base;
16333
- }
16334
- }
16335
-
16336
- class StakingClient {
16337
- /*
16338
- * Client methods
16339
- */ async unstake(asset, amount, txOptions = {}) {
16340
- const assetStr = asset.toBase58();
16341
- // mSOL
16342
- if (assetStr === MSOL.toBase58()) {
16343
- const tx = await this.marinade.orderUnstakeTx(new anchor.BN(amount), txOptions);
16344
- return await this.base.sendAndConfirm(tx);
16345
- }
16346
- // Other LSTs
16347
- const assetMeta = this.base.getAssetMeta(assetStr);
16348
- if (!assetMeta || !assetMeta.oracle) {
16349
- throw new Error("Invalid LST: " + asset);
16350
- }
16351
- const tx = await this.stakePoolWithdrawStakeTx(assetMeta.oracle, new anchor.BN(amount), true, txOptions);
16352
- return await this.base.sendAndConfirm(tx);
16353
- }
16354
- async stakePoolDepositSol(stakePool, amount, txOptions = {}) {
16355
- const tx = await this.stakePoolDepositSolTx(stakePool, amount, txOptions);
16356
- return await this.base.sendAndConfirm(tx);
16357
- }
16358
- async stakePoolDepositStake(stakePool, stakeAccount, txOptions = {}) {
16359
- const tx = await this.stakePoolDepositStakeTx(stakePool, stakeAccount, txOptions);
16360
- return await this.base.sendAndConfirm(tx);
16361
- }
16362
- async stakePoolWithdrawStake(stakePool, amount, txOptions = {}) {
16363
- const tx = await this.stakePoolWithdrawStakeTx(stakePool, amount, false, txOptions);
16364
- return await this.base.sendAndConfirm(tx);
16365
- }
16366
- async initializeAndDelegateStake(vote, amount, txOptions = {}) {
16367
- const tx = await this.initializeAndDelegateStakeTx(vote, amount, txOptions);
16368
- return await this.base.sendAndConfirm(tx);
16369
- }
16370
- async deactivate(stakeAccounts, txOptions = {}) {
16371
- const tx = await this.deactivateStakeTx(stakeAccounts, txOptions);
16372
- return await this.base.sendAndConfirm(tx);
16844
+ async systemTransferTx(amount, to, txOptions) {
16845
+ const glamSigner = txOptions.signer || this.base.getSigner();
16846
+ // @ts-ignore
16847
+ const tx = await this.base.program.methods.systemTransfer(amount).accounts({
16848
+ glamState: this.base.statePda,
16849
+ glamSigner,
16850
+ to
16851
+ }).transaction();
16852
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16373
16853
  }
16374
- async withdraw(stakeAccounts, txOptions = {}) {
16375
- const tx = await this.withdrawStakeTx(stakeAccounts, txOptions);
16376
- return await this.base.sendAndConfirm(tx);
16854
+ /**
16855
+ * Returns an instruction that closes multiple vault token accounts
16856
+ * All token accounts must be owned by the same token program
16857
+ */ async closeTokenAccountIx(tokenAccounts, tokenProgram = splToken.TOKEN_PROGRAM_ID, txOptions = {}) {
16858
+ const glamSigner = txOptions.signer || this.base.getSigner();
16859
+ return await this.base.program.methods.tokenCloseAccount().accounts({
16860
+ glamState: this.base.statePda,
16861
+ glamSigner,
16862
+ tokenAccount: tokenAccounts[0],
16863
+ cpiProgram: tokenProgram
16864
+ }).remainingAccounts(tokenAccounts.slice(1).map((account)=>({
16865
+ pubkey: account,
16866
+ isSigner: false,
16867
+ isWritable: true
16868
+ }))).instruction();
16377
16869
  }
16378
- async merge(destinationStake, sourceStake, txOptions = {}) {
16379
- const tx = await this.mergeStakeTx(destinationStake, sourceStake, txOptions);
16870
+ async closeTokenAccountsTx(accounts, txOptions) {
16871
+ const accountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(accounts);
16872
+ if (accounts.length !== accountsInfo.filter((a)=>!!a).length) {
16873
+ throw new Error("Some token accounts do not exist");
16874
+ }
16875
+ // split token accounts into 2 arrays by owner program
16876
+ const tokenAccountsByProgram = new Map([
16877
+ [
16878
+ splToken.TOKEN_PROGRAM_ID,
16879
+ []
16880
+ ],
16881
+ [
16882
+ splToken.TOKEN_2022_PROGRAM_ID,
16883
+ []
16884
+ ]
16885
+ ]);
16886
+ accountsInfo.forEach((accountInfo, i)=>{
16887
+ [
16888
+ splToken.TOKEN_PROGRAM_ID,
16889
+ splToken.TOKEN_2022_PROGRAM_ID
16890
+ ].forEach((programId)=>{
16891
+ if (accountInfo?.owner.equals(programId)) {
16892
+ tokenAccountsByProgram.get(programId)?.push(accounts[i]);
16893
+ }
16894
+ });
16895
+ });
16896
+ const ixs = (await Promise.all(Array.from(tokenAccountsByProgram.entries()).map(async ([programId, accounts])=>{
16897
+ if (accounts.length === 0) return null;
16898
+ return this.closeTokenAccountIx(accounts, new web3_js.PublicKey(programId), txOptions);
16899
+ }))).filter((ix)=>ix !== null);
16900
+ if (ixs.length === 0) {
16901
+ throw new Error("No token accounts to close");
16902
+ }
16903
+ const tx = new web3_js.Transaction();
16904
+ tx.add(...ixs);
16905
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16906
+ }
16907
+ async depositSolTx(lamports, wrap = true, txOptions = {}) {
16908
+ const signer = txOptions.signer || this.base.getSigner();
16909
+ const _lamports = lamports instanceof anchor.BN ? BigInt(lamports.toString()) : lamports;
16910
+ if (!wrap) {
16911
+ const tx = new web3_js.Transaction().add(web3_js.SystemProgram.transfer({
16912
+ fromPubkey: signer,
16913
+ toPubkey: this.base.vaultPda,
16914
+ lamports: _lamports
16915
+ }));
16916
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16917
+ }
16918
+ const vaultAta = this.base.getAta(WSOL, this.base.vaultPda);
16919
+ const tx = new web3_js.Transaction().add(splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAta, this.base.vaultPda, WSOL), web3_js.SystemProgram.transfer({
16920
+ fromPubkey: signer,
16921
+ toPubkey: vaultAta,
16922
+ lamports: _lamports
16923
+ }), splToken.createSyncNativeInstruction(vaultAta));
16924
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16925
+ }
16926
+ async depositTx(asset, amount, txOptions) {
16927
+ const signer = txOptions.signer || this.base.getSigner();
16928
+ const { mint, tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
16929
+ const signerAta = this.base.getAta(asset, signer, tokenProgram);
16930
+ const vaultAta = this.base.getAta(asset, this.base.vaultPda, tokenProgram);
16931
+ const tx = new web3_js.Transaction().add(splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAta, this.base.vaultPda, asset, tokenProgram), splToken.createTransferCheckedInstruction(signerAta, asset, vaultAta, signer, new anchor.BN(amount).toNumber(), mint.decimals, [], tokenProgram));
16932
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16933
+ }
16934
+ async withdrawIxs(asset, amount, txOptions) {
16935
+ const glamSigner = txOptions.signer || this.base.getSigner();
16936
+ const { tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
16937
+ const signerAta = this.base.getAta(asset, glamSigner, tokenProgram);
16938
+ return [
16939
+ splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, signerAta, glamSigner, asset, tokenProgram),
16940
+ await this.base.program.methods.withdraw(new anchor.BN(amount)).accounts({
16941
+ glamState: this.base.statePda,
16942
+ glamSigner,
16943
+ asset,
16944
+ tokenProgram
16945
+ }).instruction()
16946
+ ];
16947
+ }
16948
+ async withdrawTx(asset, amount, txOptions) {
16949
+ const glamSigner = txOptions.signer || this.base.getSigner();
16950
+ const { tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
16951
+ const signerAta = this.base.getAta(asset, glamSigner, tokenProgram);
16952
+ const preInstructions = [
16953
+ splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, signerAta, glamSigner, asset, tokenProgram)
16954
+ ];
16955
+ const tx = await this.base.program.methods.withdraw(new anchor.BN(amount)).accounts({
16956
+ glamState: this.base.statePda,
16957
+ glamSigner,
16958
+ asset,
16959
+ tokenProgram
16960
+ }).preInstructions(preInstructions).transaction();
16961
+ return await this.base.intoVersionedTransaction(tx, txOptions);
16962
+ }
16963
+ constructor(base){
16964
+ this.base = base;
16965
+ }
16966
+ }
16967
+
16968
+ class StakingClient {
16969
+ /*
16970
+ * Client methods
16971
+ */ async unstake(asset, amount, txOptions = {}) {
16972
+ const assetStr = asset.toBase58();
16973
+ // mSOL
16974
+ if (assetStr === MSOL.toBase58()) {
16975
+ const tx = await this.marinade.orderUnstakeTx(new anchor.BN(amount), txOptions);
16976
+ return await this.base.sendAndConfirm(tx);
16977
+ }
16978
+ // Other LSTs
16979
+ const assetMeta = this.base.getAssetMeta(assetStr);
16980
+ if (!assetMeta || !assetMeta.oracle) {
16981
+ throw new Error("Invalid LST: " + asset);
16982
+ }
16983
+ const tx = await this.stakePoolWithdrawStakeTx(assetMeta.oracle, new anchor.BN(amount), true, txOptions);
16984
+ return await this.base.sendAndConfirm(tx);
16985
+ }
16986
+ async stakePoolDepositSol(stakePool, amount, txOptions = {}) {
16987
+ const tx = await this.stakePoolDepositSolTx(stakePool, amount, txOptions);
16988
+ return await this.base.sendAndConfirm(tx);
16989
+ }
16990
+ async stakePoolDepositStake(stakePool, stakeAccount, txOptions = {}) {
16991
+ const tx = await this.stakePoolDepositStakeTx(stakePool, stakeAccount, txOptions);
16992
+ return await this.base.sendAndConfirm(tx);
16993
+ }
16994
+ async stakePoolWithdrawStake(stakePool, amount, txOptions = {}) {
16995
+ const tx = await this.stakePoolWithdrawStakeTx(stakePool, amount, false, txOptions);
16996
+ return await this.base.sendAndConfirm(tx);
16997
+ }
16998
+ async initializeAndDelegateStake(vote, amount, txOptions = {}) {
16999
+ const tx = await this.initializeAndDelegateStakeTx(vote, amount, txOptions);
17000
+ return await this.base.sendAndConfirm(tx);
17001
+ }
17002
+ async deactivate(stakeAccounts, txOptions = {}) {
17003
+ const tx = await this.deactivateStakeTx(stakeAccounts, txOptions);
17004
+ return await this.base.sendAndConfirm(tx);
17005
+ }
17006
+ async withdraw(stakeAccounts, txOptions = {}) {
17007
+ const tx = await this.withdrawStakeTx(stakeAccounts, txOptions);
17008
+ return await this.base.sendAndConfirm(tx);
17009
+ }
17010
+ async merge(destinationStake, sourceStake, txOptions = {}) {
17011
+ const tx = await this.mergeStakeTx(destinationStake, sourceStake, txOptions);
16380
17012
  return await this.base.sendAndConfirm(tx);
16381
17013
  }
16382
17014
  async split(existingStake, lamports, txOptions = {}) {
@@ -16397,13 +17029,7 @@ class StakingClient {
16397
17029
  }
16398
17030
  /*
16399
17031
  * Utils
16400
- */ // getStakeAccountPda(state: PublicKey, accountId: string): [PublicKey, number] {
16401
- // return PublicKey.findProgramAddressSync(
16402
- // [Buffer.from("stake_account"), Buffer.from(accountId), state.toBuffer()],
16403
- // this.base.program.programId,
16404
- // );
16405
- // }
16406
- getStakePoolWithdrawAuthority(programId, stakePool) {
17032
+ */ getStakePoolWithdrawAuthority(programId, stakePool) {
16407
17033
  const [publicKey] = web3_js.PublicKey.findProgramAddressSync([
16408
17034
  stakePool.toBuffer(),
16409
17035
  Buffer.from("withdraw")
@@ -16417,7 +17043,10 @@ class StakingClient {
16417
17043
  ], programId);
16418
17044
  return publicKey;
16419
17045
  }
17046
+ // FIXME: this is a dupe of getStakeAccountsWithStates in utils/helpers
16420
17047
  async getStakeAccountsWithStates(withdrawAuthority) {
17048
+ // stake authority offset: 12
17049
+ // withdraw authority offset: 44
16421
17050
  const authority = withdrawAuthority || this.base.vaultPda;
16422
17051
  const accounts = await this.base.provider.connection.getParsedProgramAccounts(web3_js.StakeProgram.programId, {
16423
17052
  filters: [
@@ -16426,7 +17055,7 @@ class StakingClient {
16426
17055
  },
16427
17056
  {
16428
17057
  memcmp: {
16429
- offset: 12,
17058
+ offset: 44,
16430
17059
  bytes: authority.toBase58()
16431
17060
  }
16432
17061
  }
@@ -16547,7 +17176,7 @@ class StakingClient {
16547
17176
  const glamVault = this.base.vaultPda;
16548
17177
  const poolTokensTo = this.base.getVaultAta(poolMint, tokenProgram);
16549
17178
  // All stake accounts owned by the stake pool withdraw authority
16550
- const validatorStakeCandidates = await this.getStakeAccountsWithStates(withdrawAuthority);
17179
+ const validatorStakeCandidates = await getStakeAccountsWithStates(this.base.provider.connection, withdrawAuthority);
16551
17180
  // Find a validator stake account to use from the list of candidates.
16552
17181
  // The vault stake account must have the same vote address as the chosen validator stake account.
16553
17182
  const vote = await this.getStakeAccountVoter(stakeAccount);
@@ -16584,7 +17213,7 @@ class StakingClient {
16584
17213
  this.base.vaultPda;
16585
17214
  const poolTokensFrom = this.base.getVaultAta(poolMint, tokenProgram);
16586
17215
  // The reserve stake account should NOT be used for withdrawals unless we have no other options.
16587
- const validatorStakeCandidates = (await this.getStakeAccountsWithStates(withdrawAuthority)).filter((s)=>!s.address.equals(reserveStake));
17216
+ const validatorStakeCandidates = (await getStakeAccountsWithStates(this.base.provider.connection, withdrawAuthority)).filter((s)=>!s.address.equals(reserveStake));
16588
17217
  console.log("validatorStakeCandidates", validatorStakeCandidates);
16589
17218
  const validatorStakeAccount = validatorStakeCandidates.length === 0 ? reserveStake : validatorStakeCandidates[0].address;
16590
17219
  const [stakeAccount, createStakeAccountIx] = await this.createStakeAccount(glamSigner);
@@ -16743,7 +17372,7 @@ class StateClient {
16743
17372
  // No mint, only need to initialize the state
16744
17373
  if (mints && mints.length === 0) {
16745
17374
  // @ts-ignore
16746
- const tx = await this.base.program.methods.initializeState(stateModel).accountsPartial({
17375
+ const tx = await this.base.program.methods.initializeState(new StateIdlModel(stateModel)).accountsPartial({
16747
17376
  glamState: statePda,
16748
17377
  glamSigner,
16749
17378
  glamVault: this.base.vaultPda
@@ -16755,13 +17384,9 @@ class StateClient {
16755
17384
  statePda
16756
17385
  ];
16757
17386
  }
16758
- // let extraMetasAccount =
16759
- // mints && mints[0].lockUpPeriod && mints[0].lockUpPeriod > 0
16760
- // ? this.base.extraMetasPda
16761
- // : null;
16762
17387
  // Initialize state and add mint in one transaction
16763
17388
  if (mints && mints.length > 0 && singleTx) {
16764
- const initStateIx = await this.base.program.methods.initializeState(stateModel).accountsPartial({
17389
+ const initStateIx = await this.base.program.methods.initializeState(new StateIdlModel(stateModel)).accountsPartial({
16765
17390
  glamState: statePda,
16766
17391
  glamSigner,
16767
17392
  glamVault: this.base.vaultPda
@@ -16782,7 +17407,7 @@ class StateClient {
16782
17407
  ];
16783
17408
  }
16784
17409
  // Initialize state and add mints in separate transactions
16785
- const tx = await this.base.program.methods.initializeState(stateModel).accountsPartial({
17410
+ const tx = await this.base.program.methods.initializeState(new StateIdlModel(stateModel)).accountsPartial({
16786
17411
  glamState: statePda,
16787
17412
  glamVault: this.base.vaultPda,
16788
17413
  glamSigner,
@@ -16932,140 +17557,6 @@ class StateClient {
16932
17557
  delegateAcls
16933
17558
  }, txOptions);
16934
17559
  }
16935
- async closeTokenAccounts(tokenAccounts, txOptions = {}) {
16936
- const tx = await this.closeTokenAccountsTx(tokenAccounts, txOptions);
16937
- return await this.base.sendAndConfirm(tx);
16938
- }
16939
- /**
16940
- * Close vault's token accounts, all token accounts must use the same token program
16941
- */ async closeTokenAccountIx(tokenAccounts, tokenProgram = splToken.TOKEN_PROGRAM_ID, txOptions = {}) {
16942
- const glamSigner = txOptions.signer || this.base.getSigner();
16943
- return await this.base.program.methods.tokenCloseAccount().accounts({
16944
- glamState: this.base.statePda,
16945
- glamSigner,
16946
- tokenAccount: tokenAccounts[0],
16947
- cpiProgram: tokenProgram
16948
- }).remainingAccounts(tokenAccounts.slice(1).map((account)=>({
16949
- pubkey: account,
16950
- isSigner: false,
16951
- isWritable: true
16952
- }))).instruction();
16953
- }
16954
- async closeTokenAccountsTx(accounts, txOptions) {
16955
- const accountsInfo = await this.base.provider.connection.getMultipleAccountsInfo(accounts);
16956
- if (accounts.length !== accountsInfo.filter((a)=>!!a).length) {
16957
- throw new Error("Some token accounts do not exist");
16958
- }
16959
- // split token accounts into 2 arrays by owner program
16960
- const tokenAccountsByProgram = new Map([
16961
- [
16962
- splToken.TOKEN_PROGRAM_ID,
16963
- []
16964
- ],
16965
- [
16966
- splToken.TOKEN_2022_PROGRAM_ID,
16967
- []
16968
- ]
16969
- ]);
16970
- accountsInfo.forEach((accountInfo, i)=>{
16971
- [
16972
- splToken.TOKEN_PROGRAM_ID,
16973
- splToken.TOKEN_2022_PROGRAM_ID
16974
- ].forEach((programId)=>{
16975
- if (accountInfo?.owner.equals(programId)) {
16976
- tokenAccountsByProgram.get(programId)?.push(accounts[i]);
16977
- }
16978
- });
16979
- });
16980
- const ixs = (await Promise.all(Array.from(tokenAccountsByProgram.entries()).map(async ([programId, accounts])=>{
16981
- if (accounts.length === 0) return null;
16982
- return this.closeTokenAccountIx(accounts, new web3_js.PublicKey(programId), txOptions);
16983
- }))).filter((ix)=>ix !== null);
16984
- if (ixs.length === 0) {
16985
- throw new Error("No token accounts to close");
16986
- }
16987
- const tx = new web3_js.Transaction();
16988
- tx.add(...ixs);
16989
- return await this.base.intoVersionedTransaction(tx, txOptions);
16990
- }
16991
- /* Deposit & Withdraw */ async deposit(asset, amount, txOptions = {}) {
16992
- const tx = await this.depositTx(new web3_js.PublicKey(asset), amount, txOptions);
16993
- return await this.base.sendAndConfirm(tx);
16994
- }
16995
- async depositSol(lamports, wrap = true, txOptions = {}) {
16996
- const tx = await this.depositSolTx(lamports, wrap, txOptions);
16997
- return await this.base.sendAndConfirm(tx);
16998
- }
16999
- async depositSolTx(lamports, wrap = true, txOptions = {}) {
17000
- const signer = txOptions.signer || this.base.getSigner();
17001
- const _lamports = lamports instanceof anchor.BN ? BigInt(lamports.toString()) : lamports;
17002
- if (!wrap) {
17003
- const tx = new web3_js.Transaction().add(web3_js.SystemProgram.transfer({
17004
- fromPubkey: signer,
17005
- toPubkey: this.base.vaultPda,
17006
- lamports: _lamports
17007
- }));
17008
- return await this.base.intoVersionedTransaction(tx, txOptions);
17009
- }
17010
- const vaultAta = this.base.getAta(WSOL, this.base.vaultPda);
17011
- const tx = new web3_js.Transaction().add(splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAta, this.base.vaultPda, WSOL), web3_js.SystemProgram.transfer({
17012
- fromPubkey: signer,
17013
- toPubkey: vaultAta,
17014
- lamports: _lamports
17015
- }), splToken.createSyncNativeInstruction(vaultAta));
17016
- return await this.base.intoVersionedTransaction(tx, txOptions);
17017
- }
17018
- async withdraw(asset, amount, txOptions = {}) {
17019
- const tx = await this.withdrawTx(new web3_js.PublicKey(asset), amount, txOptions);
17020
- return await this.base.sendAndConfirm(tx);
17021
- }
17022
- async depositTx(asset, amount, txOptions) {
17023
- const signer = txOptions.signer || this.base.getSigner();
17024
- const { mint, tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
17025
- const signerAta = this.base.getAta(asset, signer, tokenProgram);
17026
- const vaultAta = this.base.getAta(asset, this.base.vaultPda, tokenProgram);
17027
- const tx = new web3_js.Transaction().add(splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAta, this.base.vaultPda, asset, tokenProgram), splToken.createTransferCheckedInstruction(signerAta, asset, vaultAta, signer, new anchor.BN(amount).toNumber(), mint.decimals, [], tokenProgram));
17028
- return await this.base.intoVersionedTransaction(tx, txOptions);
17029
- }
17030
- async withdrawIxs(asset, amount, txOptions) {
17031
- const glamSigner = txOptions.signer || this.base.getSigner();
17032
- const { tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
17033
- const signerAta = this.base.getAta(asset, glamSigner, tokenProgram);
17034
- return [
17035
- splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, signerAta, glamSigner, asset, tokenProgram),
17036
- await this.base.program.methods.withdraw(new anchor.BN(amount)).accounts({
17037
- glamState: this.base.statePda,
17038
- glamSigner,
17039
- asset,
17040
- tokenProgram
17041
- }).instruction()
17042
- ];
17043
- }
17044
- async withdrawTx(asset, amount, txOptions) {
17045
- const glamSigner = txOptions.signer || this.base.getSigner();
17046
- const { tokenProgram } = await this.base.fetchMintAndTokenProgram(asset);
17047
- const signerAta = this.base.getAta(asset, glamSigner, tokenProgram);
17048
- const preInstructions = [
17049
- splToken.createAssociatedTokenAccountIdempotentInstruction(glamSigner, signerAta, glamSigner, asset, tokenProgram)
17050
- ];
17051
- const postInstructions = [];
17052
- if (asset.equals(WSOL)) {
17053
- const wrapSolIxs = await this.base.maybeWrapSol(amount, glamSigner);
17054
- preInstructions.push(...wrapSolIxs);
17055
- // If we need to wrap SOL, it means the wSOL balance will be drained,
17056
- // and we close the wSOL token account for convenience
17057
- postInstructions.push(await this.closeTokenAccountIx([
17058
- this.base.getAta(WSOL, this.base.vaultPda)
17059
- ]));
17060
- }
17061
- const tx = await this.base.program.methods.withdraw(new anchor.BN(amount)).accounts({
17062
- glamState: this.base.statePda,
17063
- glamSigner,
17064
- asset,
17065
- tokenProgram
17066
- }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
17067
- return await this.base.intoVersionedTransaction(tx, txOptions);
17068
- }
17069
17560
  constructor(base){
17070
17561
  this.base = base;
17071
17562
  }
@@ -17657,12 +18148,11 @@ class KaminoLendingClient {
17657
18148
  scopePrices: KAMINO_SCOPE_PRICES
17658
18149
  }));
17659
18150
  }
17660
- refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) {
18151
+ refreshObligationCollateralFarmsForReservesIxs(obligation, lendingMarket, parsedReserves) {
17661
18152
  return parsedReserves.map((parsedReserve)=>{
17662
- const { farmCollateral, farmDebt } = parsedReserve;
18153
+ const { farmCollateral } = parsedReserve;
17663
18154
  return [
17664
- farmCollateral,
17665
- farmDebt
18155
+ farmCollateral
17666
18156
  ].filter((farm)=>!!farm).map((farm)=>{
17667
18157
  const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
17668
18158
  return refreshObligationFarmsForReserve({
@@ -17684,28 +18174,31 @@ class KaminoLendingClient {
17684
18174
  });
17685
18175
  }).flat();
17686
18176
  }
17687
- // If obligation has deposits or borrows, we need the following refresh ixs:
17688
- // - refreshReserve x N_reserves
17689
- // - refreshObligation
17690
- // - refreshObligationFarmsForReserve x M_farms
17691
- //
17692
- // For pricing purpose, we don't need to refresh farm states
17693
- async getRefreshIxs(obligation, refreshFarms = true) {
17694
- const { lendingMarket, deposits, borrows } = await this.fetchAndParseObligation(obligation);
17695
- if (!lendingMarket) {
17696
- throw new Error("Lending market not found");
17697
- }
17698
- const reserves = deposits.concat(borrows).map((d)=>d.reserve);
17699
- const parsedReserves = await this.fetchAndParseReserves(reserves);
17700
- return [
17701
- ...this.refreshReserveIxs(lendingMarket, reserves),
17702
- refreshObligation({
17703
- lendingMarket,
17704
- obligation,
17705
- reserves
17706
- }),
17707
- ...refreshFarms ? this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) : []
17708
- ];
18177
+ refreshObligationDebtFarmsForReservesIxs(obligation, lendingMarket, parsedReserves) {
18178
+ return parsedReserves.map((parsedReserve)=>{
18179
+ const { farmDebt } = parsedReserve;
18180
+ return [
18181
+ farmDebt
18182
+ ].filter((farm)=>!!farm).map((farm)=>{
18183
+ const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
18184
+ return refreshObligationFarmsForReserve({
18185
+ mode: 0
18186
+ }, {
18187
+ crank: this.base.getSigner(),
18188
+ baseAccounts: {
18189
+ obligation,
18190
+ lendingMarketAuthority: this.getMarketAuthority(lendingMarket),
18191
+ reserve: parsedReserve.address,
18192
+ reserveFarmState: farm,
18193
+ obligationFarmUserState,
18194
+ lendingMarket
18195
+ },
18196
+ farmsProgram: KAMINO_FARM_PROGRAM,
18197
+ rent: web3_js.SYSVAR_RENT_PUBKEY,
18198
+ systemProgram: web3_js.SystemProgram.programId
18199
+ });
18200
+ });
18201
+ }).flat();
17709
18202
  }
17710
18203
  getMarketAuthority(market) {
17711
18204
  const [authority, _] = web3_js.PublicKey.findProgramAddressSync([
@@ -17864,10 +18357,19 @@ class KaminoLendingClient {
17864
18357
  const glamSigner = txOptions.signer || this.base.getSigner();
17865
18358
  const vault = this.base.vaultPda;
17866
18359
  const userMetadata = this.getUserMetadataPda(vault);
18360
+ const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
17867
18361
  const preInstructions = [];
17868
18362
  const postInstructions = [];
17869
- const depositReserve = await this.findAndParseReserve(market, asset);
17870
- const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
18363
+ // If user metadata doesn't exist, initialize it
18364
+ const userMetadataAccount = await this.base.provider.connection.getAccountInfo(userMetadata);
18365
+ if (!userMetadataAccount) {
18366
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitUserMetadata(new web3_js.PublicKey(0)).accounts({
18367
+ glamState: this.base.statePda,
18368
+ glamSigner,
18369
+ userMetadata,
18370
+ referrerUserMetadata: null
18371
+ }).instruction());
18372
+ }
17871
18373
  // If obligation doesn't exist, initialize & refresh obligation and collateral farm state first
17872
18374
  const obligationAccount = await this.base.provider.connection.getAccountInfo(obligation);
17873
18375
  if (!obligationAccount) {
@@ -17881,6 +18383,7 @@ class KaminoLendingClient {
17881
18383
  ownerUserMetadata: userMetadata
17882
18384
  }).instruction());
17883
18385
  }
18386
+ const depositReserve = await this.findAndParseReserve(market, asset);
17884
18387
  // If reserve has collateral farm but obligation farm state doesn't exist, initialize it
17885
18388
  let obligationFarm = null;
17886
18389
  if (depositReserve.farmCollateral) {
@@ -17918,7 +18421,7 @@ class KaminoLendingClient {
17918
18421
  reserves: reservesInUse
17919
18422
  }));
17920
18423
  if (depositReserve.farmCollateral) {
17921
- const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
18424
+ const ixs = this.refreshObligationCollateralFarmsForReservesIxs(obligation, market, [
17922
18425
  depositReserve
17923
18426
  ]);
17924
18427
  preInstructions.push(...ixs);
@@ -18014,7 +18517,7 @@ class KaminoLendingClient {
18014
18517
  reserves: reservesInUse
18015
18518
  }));
18016
18519
  if (withdrawReserve.farmCollateral) {
18017
- const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
18520
+ const ixs = this.refreshObligationCollateralFarmsForReservesIxs(obligation, market, [
18018
18521
  withdrawReserve
18019
18522
  ]);
18020
18523
  preInstructions.push(...ixs);
@@ -18103,7 +18606,7 @@ class KaminoLendingClient {
18103
18606
  obligation,
18104
18607
  reserves: reservesInUse
18105
18608
  }));
18106
- // Don't need to refresh debt farm for borrow
18609
+ // FIXME: Don't need to refresh debt farm for borrow?
18107
18610
  /*
18108
18611
  if (borrowReserve.farmDebt) {
18109
18612
  const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
@@ -18404,7 +18907,7 @@ class MeteoraDlmmClient {
18404
18907
  const minBinId = activeBin.binId - DEFAULT_RANGE_INTERVAL;
18405
18908
  const maxBinId = activeBin.binId + DEFAULT_RANGE_INTERVAL;
18406
18909
  const width = maxBinId - minBinId + 1;
18407
- const position = this.getPositionPda(new web3_js.PublicKey(pool), this.base.vaultPda, minBinId, width);
18910
+ const position = this.getPositionPda(new web3_js.PublicKey(pool), this.base.getSigner(), minBinId, width);
18408
18911
  // @ts-ignore
18409
18912
  const tx = await this.base.program.methods.meteoraDlmmInitializePositionPda(minBinId, width).accounts({
18410
18913
  glamState: this.base.statePda,
@@ -18416,7 +18919,10 @@ class MeteoraDlmmClient {
18416
18919
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
18417
18920
  return await this.base.sendAndConfirm(vTx);
18418
18921
  }
18419
- async addLiquidityByStrategy(position, amountX, amountY, strategyType, txOptions = {}) {
18922
+ async addLiquidityByStrategy(position, amountX, amountY, strategyType, maxActiveBinSlippage, txOptions = {}) {
18923
+ if (!strategyType.endsWith("ImBalanced")) {
18924
+ throw new Error("Only imbalanced strategy types are supported");
18925
+ }
18420
18926
  const glamSigner = txOptions.signer || this.base.getSigner();
18421
18927
  const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new web3_js.PublicKey(position));
18422
18928
  const dlmmPool = await this.getDlmmPool(lbPair);
@@ -18428,7 +18934,7 @@ class MeteoraDlmmClient {
18428
18934
  amountX: new anchor.BN(amountX),
18429
18935
  amountY: new anchor.BN(amountY),
18430
18936
  activeId: activeBinId,
18431
- maxActiveBinSlippage: 20,
18937
+ maxActiveBinSlippage,
18432
18938
  strategyParameters: {
18433
18939
  minBinId: lowerBinId,
18434
18940
  maxBinId: upperBinId,
@@ -18447,7 +18953,7 @@ class MeteoraDlmmClient {
18447
18953
  isSigner: false,
18448
18954
  isWritable: true
18449
18955
  }));
18450
- // TODO: if token X or Y program is token2022 we need to properly constrcut the slides
18956
+ // TODO: if token X or Y program is token2022 we need to properly construct the slices
18451
18957
  // @ts-ignore
18452
18958
  const tx = await this.base.program.methods.meteoraDlmmAddLiquidityByStrategy2(liquidityParameter, {
18453
18959
  slices: []
@@ -18455,7 +18961,7 @@ class MeteoraDlmmClient {
18455
18961
  glamState: this.base.statePda,
18456
18962
  position: new web3_js.PublicKey(position),
18457
18963
  lbPair,
18458
- binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM_PROGRAM,
18964
+ binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension?.publicKey || null,
18459
18965
  userTokenX: vaultTokenXAta,
18460
18966
  userTokenY: vaultTokenYAta,
18461
18967
  reserveX: dlmmPool.tokenX.reserve,
@@ -18490,7 +18996,7 @@ class MeteoraDlmmClient {
18490
18996
  glamState: this.base.statePda,
18491
18997
  position: new web3_js.PublicKey(position),
18492
18998
  lbPair,
18493
- binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM_PROGRAM,
18999
+ binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension?.publicKey || null,
18494
19000
  userTokenX: vaultTokenXAta,
18495
19001
  userTokenY: vaultTokenYAta,
18496
19002
  reserveX: dlmmPool.tokenX.reserve,
@@ -18545,16 +19051,20 @@ class MeteoraDlmmClient {
18545
19051
  const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new web3_js.PublicKey(position));
18546
19052
  console.log(`close position: ${position}, binArrayLower: ${binArrayLower}, binArrayUpper: ${binArrayUpper}`);
18547
19053
  // @ts-ignore
18548
- const tx = await this.base.program.methods.meteoraDlmmClosePosition().accounts({
19054
+ const tx = await this.base.program.methods.meteoraDlmmClosePosition2().accounts({
18549
19055
  glamState: this.base.statePda,
18550
19056
  position: new web3_js.PublicKey(position),
18551
- lbPair,
18552
- binArrayLower,
18553
- binArrayUpper,
18554
19057
  rentReceiver: this.base.getSigner(),
18555
19058
  eventAuthority: EVENT_AUTHORITY,
18556
19059
  program: METEORA_DLMM_PROGRAM
18557
- }).transaction();
19060
+ }).remainingAccounts([
19061
+ binArrayLower,
19062
+ binArrayUpper
19063
+ ].map((pubkey)=>({
19064
+ pubkey,
19065
+ isSigner: false,
19066
+ isWritable: true
19067
+ }))).transaction();
18558
19068
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
18559
19069
  return await this.base.sendAndConfirm(vTx);
18560
19070
  }
@@ -18595,31 +19105,28 @@ class InvestorClient {
18595
19105
  const tx = await (queued ? this.queuedSubscribeTx(asset, amount, mintId, txOptions) : this.subscribeTx(asset, amount, mintId, txOptions));
18596
19106
  return await this.base.sendAndConfirm(tx);
18597
19107
  }
18598
- async queuedRedeem(asset, amount, mintId = 0, txOptions = {}) {
18599
- const tx = await this.queuedRedeemTx(asset, amount, mintId, txOptions);
19108
+ async queuedRedeem(amount, mintId = 0, txOptions = {}) {
19109
+ const tx = await this.queuedRedeemTx(amount, mintId, txOptions);
18600
19110
  return await this.base.sendAndConfirm(tx);
18601
19111
  }
18602
- async fulfill(asset, mintId = 0, txOptions = {}) {
18603
- const tx = await this.fulfillTx(asset, mintId, txOptions);
19112
+ async fulfill(mintId = 0, txOptions = {}) {
19113
+ const tx = await this.fulfillTx(mintId, txOptions);
18604
19114
  return await this.base.sendAndConfirm(tx);
18605
19115
  }
18606
19116
  async claim(asset, mintId = 0, txOptions = {}) {
18607
- // Claim WSOL from redeemed shares
18608
- if (asset.equals(WSOL)) {
18609
- const tx = await this.claimAssetTx(asset, mintId, txOptions);
18610
- return await this.base.sendAndConfirm(tx);
18611
- }
18612
19117
  // Claim shares after subscription is fulfilled
18613
19118
  const glamMint = this.base.mintPda;
18614
19119
  if (glamMint.equals(asset)) {
18615
19120
  const tx = await this.claimShareTx(asset, mintId, txOptions);
18616
19121
  return await this.base.sendAndConfirm(tx);
18617
19122
  }
18618
- throw new Error(`Invalid asset to claim: ${asset.toBase58()}`);
19123
+ // Claim asset redeemed from shares
19124
+ const tx = await this.claimAssetTx(asset, mintId, txOptions);
19125
+ return await this.base.sendAndConfirm(tx);
18619
19126
  }
18620
19127
  async subscribeTx(asset, amount, mintId = 0, txOptions = {}) {
18621
- if (mintId !== 0 || !asset.equals(WSOL)) {
18622
- throw new Error("Only WSOL is supported & mintId must be 0");
19128
+ if (mintId !== 0) {
19129
+ throw new Error("mintId must be 0");
18623
19130
  }
18624
19131
  const signer = txOptions.signer || this.base.getSigner();
18625
19132
  // glam mint token to receive
@@ -18664,8 +19171,8 @@ class InvestorClient {
18664
19171
  return await this.base.intoVersionedTransaction(tx, txOptions);
18665
19172
  }
18666
19173
  async queuedSubscribeTx(asset, amount, mintId = 0, txOptions = {}) {
18667
- if (mintId !== 0 || !asset.equals(WSOL)) {
18668
- throw new Error("Only WSOL is supported & mintId must be 0");
19174
+ if (mintId !== 0) {
19175
+ throw new Error("mintId must be 0");
18669
19176
  }
18670
19177
  const signer = txOptions.signer || this.base.getSigner();
18671
19178
  // asset token to transfer to escrow
@@ -18697,9 +19204,9 @@ class InvestorClient {
18697
19204
  }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
18698
19205
  return await this.base.intoVersionedTransaction(tx, txOptions);
18699
19206
  }
18700
- async queuedRedeemTx(asset, amount, mintId = 0, txOptions = {}) {
18701
- if (mintId !== 0 || !asset.equals(WSOL)) {
18702
- throw new Error("Only WSOL is supported & mintId must be 0");
19207
+ async queuedRedeemTx(amount, mintId = 0, txOptions = {}) {
19208
+ if (mintId !== 0) {
19209
+ throw new Error("mintId must be 0");
18703
19210
  }
18704
19211
  const signer = txOptions.signer || this.base.getSigner();
18705
19212
  const glamMint = this.base.mintPda;
@@ -18730,38 +19237,44 @@ class InvestorClient {
18730
19237
  }))).transaction();
18731
19238
  return await this.base.intoVersionedTransaction(tx, txOptions);
18732
19239
  }
18733
- async fulfillTx(asset, mintId = 0, txOptions = {}) {
18734
- if (mintId !== 0 || !asset.equals(WSOL)) {
18735
- throw new Error("Only WSOL is supported & mintId must be 0");
19240
+ async fulfillTx(mintId = 0, txOptions = {}) {
19241
+ if (mintId !== 0) {
19242
+ throw new Error("mintId must be 0");
18736
19243
  }
18737
19244
  const signer = txOptions.signer || this.base.getSigner();
19245
+ const stateModel = await this.base.fetchStateModel();
19246
+ const baseAsset = stateModel.baseAsset;
18738
19247
  const vault = this.base.vaultPda;
18739
- const vaultAssetAta = this.base.getAta(asset, vault);
19248
+ const vaultAssetAta = this.base.getAta(baseAsset, vault);
18740
19249
  const glamMint = this.base.mintPda;
18741
19250
  const escrow = this.base.escrowPda;
18742
19251
  const escrowMintAta = this.base.getMintAta(escrow);
18743
- const escrowAssetAta = this.base.getAta(asset, escrow);
19252
+ const escrowAssetAta = this.base.getAta(baseAsset, escrow);
18744
19253
  let preInstructions = [
18745
19254
  splToken.createAssociatedTokenAccountIdempotentInstruction(signer, escrowMintAta, escrow, glamMint, splToken.TOKEN_2022_PROGRAM_ID),
18746
- splToken.createAssociatedTokenAccountIdempotentInstruction(signer, escrowAssetAta, escrow, asset),
18747
- splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAssetAta, vault, asset),
19255
+ splToken.createAssociatedTokenAccountIdempotentInstruction(signer, escrowAssetAta, escrow, baseAsset),
19256
+ splToken.createAssociatedTokenAccountIdempotentInstruction(signer, vaultAssetAta, vault, baseAsset),
18748
19257
  ...txOptions.preInstructions || []
18749
19258
  ];
18750
19259
  const tx = await this.base.program.methods.fulfill(mintId).accounts({
18751
19260
  glamState: this.base.statePda,
18752
19261
  glamMint,
18753
19262
  signer,
18754
- asset
19263
+ asset: baseAsset
18755
19264
  }).preInstructions(preInstructions).transaction();
18756
19265
  return await this.base.intoVersionedTransaction(tx, txOptions);
18757
19266
  }
18758
19267
  async claimAssetTx(asset, mintId = 0, txOptions = {}) {
18759
- if (mintId !== 0 || !asset.equals(WSOL)) {
18760
- throw new Error("Only WSOL is supported & mintId must be 0");
19268
+ if (mintId !== 0) {
19269
+ throw new Error("mintId must be 0");
18761
19270
  }
18762
19271
  const signer = txOptions.signer || this.base.getSigner();
18763
19272
  this.base.mintPda;
18764
19273
  const signerAta = this.base.getAta(asset, signer);
19274
+ // Close wSOL ata so user gets SOL
19275
+ const postInstructions = asset.equals(WSOL) ? [
19276
+ splToken.createCloseAccountInstruction(signerAta, signer, signer)
19277
+ ] : [];
18765
19278
  const tx = await this.base.program.methods.claim(0).accounts({
18766
19279
  glamState: this.base.statePda,
18767
19280
  signer,
@@ -18769,9 +19282,7 @@ class InvestorClient {
18769
19282
  tokenProgram: splToken.TOKEN_PROGRAM_ID
18770
19283
  }).preInstructions([
18771
19284
  splToken.createAssociatedTokenAccountIdempotentInstruction(signer, signerAta, signer, asset)
18772
- ]).postInstructions([
18773
- splToken.createCloseAccountInstruction(signerAta, signer, signer)
18774
- ]).transaction();
19285
+ ]).postInstructions(postInstructions).transaction();
18775
19286
  return await this.base.intoVersionedTransaction(tx, txOptions);
18776
19287
  }
18777
19288
  async claimShareTx(asset, mintId = 0, txOptions = {}) {
@@ -18821,16 +19332,8 @@ class PriceClient {
18821
19332
  */ async getAum() {
18822
19333
  console.warn("getAum() should only be used for testing. It doesn't reflect the actual AUM of the vault in production.");
18823
19334
  // @ts-ignore
18824
- const glamStateAccount = await this.base.fetchStateAccount();
18825
- let pricedAssets = [];
18826
- glamStateAccount.params[0].forEach((param)=>{
18827
- const name = Object.keys(param.name)[0];
18828
- if (name === "pricedAssets") {
18829
- // @ts-ignore
18830
- pricedAssets = Object.values(param.value)[0].val;
18831
- }
18832
- });
18833
- return pricedAssets.reduce((sum, p)=>new anchor.BN(p.amount).add(sum), new anchor.BN(0));
19335
+ const stateModel = await this.base.fetchStateModel();
19336
+ return (stateModel?.pricedAssets || []).reduce((sum, p)=>new anchor.BN(p.amount).add(sum), new anchor.BN(0));
18834
19337
  }
18835
19338
  async priceKaminoIx(priceDenom) {
18836
19339
  const glamVault = this.base.vaultPda;
@@ -18861,6 +19364,18 @@ class PriceClient {
18861
19364
  }
18862
19365
  async priceVaultIxs(priceDenom) {
18863
19366
  const glamVault = this.base.vaultPda;
19367
+ const priceVaultIx = await this.base.program.methods.priceVault(priceDenom).accounts({
19368
+ glamState: this.base.statePda,
19369
+ solOracle: SOL_ORACLE
19370
+ }).remainingAccounts(await this.remainingAccountsForPricingVaultAssets(priceDenom == PriceDenom.ASSET)).instruction();
19371
+ // If priceDenom is ASSET, only priceVaultIx is returned
19372
+ // We currently don't support pricing other assets in custom base asset
19373
+ // due to the lack of oracles
19374
+ if (priceDenom == PriceDenom.ASSET) {
19375
+ return [
19376
+ priceVaultIx
19377
+ ];
19378
+ }
18864
19379
  const tickets = await fetchMarinadeTicketAccounts(this.base.provider.connection, glamVault);
18865
19380
  // @ts-ignore
18866
19381
  const priceTicketsIx = await this.base.program.methods.priceTickets(priceDenom).accounts({
@@ -18880,10 +19395,6 @@ class PriceClient {
18880
19395
  isSigner: false,
18881
19396
  isWritable: false
18882
19397
  }))).instruction();
18883
- const priceVaultIx = await this.base.program.methods.priceVault(priceDenom).accounts({
18884
- glamState: this.base.statePda,
18885
- solOracle: SOL_ORACLE
18886
- }).remainingAccounts(await this.remainingAccountsForPricingVaultAssets()).instruction();
18887
19398
  const priceMeteoraIx = await this.base.program.methods.priceMeteoraPositions(priceDenom).accounts({
18888
19399
  glamState: this.base.statePda,
18889
19400
  solOracle: SOL_ORACLE
@@ -18943,14 +19454,38 @@ class PriceClient {
18943
19454
  }));
18944
19455
  return chunks.flat();
18945
19456
  };
18946
- this.remainingAccountsForPricingVaultAssets = async ()=>{
18947
- const glamStateAccount = await this.base.fetchStateAccount();
18948
- return glamStateAccount.assets.map((asset)=>[
18949
- this.base.getVaultAta(asset),
18950
- asset,
18951
- // FIXME: check oracle vs LST state?
18952
- ASSETS_MAINNET.get(asset.toBase58())?.oracle || new web3_js.PublicKey(0)
18953
- ]).flat().map((a)=>({
19457
+ this.remainingAccountsForPricingVaultAssets = async (baseAssetOnly = false)=>{
19458
+ const stateModel = await this.base.fetchStateModel();
19459
+ if (baseAssetOnly) {
19460
+ if (!stateModel.baseAsset) {
19461
+ throw new Error("Base asset not configured for the vault");
19462
+ }
19463
+ // FIXME: support token 2022 base asset
19464
+ const ata = this.base.getVaultAta(stateModel.baseAsset);
19465
+ // Set oracle to default pubkey (aka system program) to indicate oracle isn't needed
19466
+ return [
19467
+ ata,
19468
+ stateModel.baseAsset,
19469
+ web3_js.PublicKey.default
19470
+ ].map((k)=>({
19471
+ pubkey: k,
19472
+ isSigner: false,
19473
+ isWritable: false
19474
+ }));
19475
+ }
19476
+ const assetsForPricing = (stateModel.borrowableAssets || []).concat(stateModel.assets || []);
19477
+ return assetsForPricing.map((mint)=>{
19478
+ const assetMeta = ASSETS_MAINNET.get(mint.toBase58());
19479
+ if (!assetMeta) {
19480
+ throw new Error(`Asset meta not found for ${mint}`);
19481
+ }
19482
+ const ata = this.base.getVaultAta(mint, assetMeta?.programId);
19483
+ return [
19484
+ ata,
19485
+ mint,
19486
+ assetMeta?.oracle
19487
+ ];
19488
+ }).flat().map((a)=>({
18954
19489
  pubkey: a,
18955
19490
  isSigner: false,
18956
19491
  isWritable: false
@@ -18994,11 +19529,11 @@ class PriceClient {
18994
19529
  }
18995
19530
  return this._marinade;
18996
19531
  }
18997
- get wsol() {
18998
- if (!this._wsol) {
18999
- this._wsol = new WSolClient(this);
19532
+ get vault() {
19533
+ if (!this._vault) {
19534
+ this._vault = new VaultClient(this);
19000
19535
  }
19001
- return this._wsol;
19536
+ return this._vault;
19002
19537
  }
19003
19538
  get staking() {
19004
19539
  if (!this._staking) {
@@ -19145,7 +19680,6 @@ exports.GlamIntegrations = GlamIntegrations;
19145
19680
  exports.GlamPermissions = GlamPermissions;
19146
19681
  exports.GlamProtocolIdlJson = GlamProtocolIdlJson;
19147
19682
  exports.InsuranceFundOperation = InsuranceFundOperation;
19148
- exports.JITOSOL = JITOSOL;
19149
19683
  exports.JITO_STAKE_POOL = JITO_STAKE_POOL;
19150
19684
  exports.JITO_TIP_DEFAULT = JITO_TIP_DEFAULT;
19151
19685
  exports.JUP = JUP;
@@ -19161,6 +19695,7 @@ exports.KAMINO_OBTRIGATION_SIZE = KAMINO_OBTRIGATION_SIZE;
19161
19695
  exports.KAMINO_SCOPE_PRICES = KAMINO_SCOPE_PRICES;
19162
19696
  exports.LPAction = LPAction;
19163
19697
  exports.LiquidationType = LiquidationType;
19698
+ exports.MARINADE_NATIVE_STAKE_AUTHORITY = MARINADE_NATIVE_STAKE_AUTHORITY;
19164
19699
  exports.MARINADE_PROGRAM_ID = MARINADE_PROGRAM_ID;
19165
19700
  exports.MARINADE_TICKET_SIZE = MARINADE_TICKET_SIZE;
19166
19701
  exports.MEMO_PROGRAM = MEMO_PROGRAM;
@@ -19198,6 +19733,8 @@ exports.SEED_STATE = SEED_STATE;
19198
19733
  exports.SEED_VAULT = SEED_VAULT;
19199
19734
  exports.SOL_ORACLE = SOL_ORACLE;
19200
19735
  exports.STAKE_ACCOUNT_SIZE = STAKE_ACCOUNT_SIZE;
19736
+ exports.STAKE_POOLS = STAKE_POOLS;
19737
+ exports.STAKE_POOLS_MAP = STAKE_POOLS_MAP;
19201
19738
  exports.SettlePnlExplanation = SettlePnlExplanation;
19202
19739
  exports.SettlePnlMode = SettlePnlMode;
19203
19740
  exports.SpotBalanceType = SpotBalanceType;
@@ -19215,8 +19752,6 @@ exports.TimeUnit = TimeUnit;
19215
19752
  exports.TradeSide = TradeSide;
19216
19753
  exports.USDC = USDC;
19217
19754
  exports.UserStatus = UserStatus;
19218
- exports.WBTC = WBTC;
19219
- exports.WETH = WETH;
19220
19755
  exports.WSOL = WSOL;
19221
19756
  exports.ZERO = ZERO;
19222
19757
  exports.decodeUser = decodeUser;
@@ -19237,6 +19772,7 @@ exports.getOpenfundsPda = getOpenfundsPda;
19237
19772
  exports.getOrderParams = getOrderParams;
19238
19773
  exports.getPriorityFeeEstimate = getPriorityFeeEstimate;
19239
19774
  exports.getSimulationComputeUnits = getSimulationComputeUnits;
19775
+ exports.getStakeAccountsWithStates = getStakeAccountsWithStates;
19240
19776
  exports.getStatePda = getStatePda;
19241
19777
  exports.getTriggerLimitOrderParams = getTriggerLimitOrderParams;
19242
19778
  exports.getTriggerMarketOrderParams = getTriggerMarketOrderParams;