@glamsystems/glam-sdk 0.1.16 → 0.1.18

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.esm.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import * as anchor from '@coral-xyz/anchor';
2
2
  import { Program, BN } from '@coral-xyz/anchor';
3
- import { PublicKey, StakeProgram, ComputeBudgetProgram, VersionedTransaction, TransactionMessage, SystemProgram, Connection, Transaction, sendAndConfirmTransaction, AddressLookupTableAccount, LAMPORTS_PER_SOL, TransactionInstruction, SYSVAR_CLOCK_PUBKEY, STAKE_CONFIG_ID, SYSVAR_RENT_PUBKEY, SYSVAR_INSTRUCTIONS_PUBKEY, Keypair } from '@solana/web3.js';
4
- import { getExtensionData, ExtensionType, TOKEN_2022_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_PROGRAM_ID, getMint, getAccount, TokenAccountNotFoundError, unpackMint, createAssociatedTokenAccountIdempotentInstruction, createSyncNativeInstruction, createTransferCheckedInstruction, unpackAccount, createCloseAccountInstruction } from '@solana/spl-token';
3
+ import { PublicKey, StakeProgram, ComputeBudgetProgram, VersionedTransaction, TransactionMessage, SystemProgram, Connection, Transaction, sendAndConfirmTransaction, AddressLookupTableAccount, LAMPORTS_PER_SOL, TransactionInstruction, SYSVAR_CLOCK_PUBKEY, STAKE_CONFIG_ID, SYSVAR_INSTRUCTIONS_PUBKEY, SYSVAR_RENT_PUBKEY, Keypair } from '@solana/web3.js';
4
+ import { getExtensionData, ExtensionType, TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID, getMint, getAccount, TokenAccountNotFoundError, unpackMint, createAssociatedTokenAccountIdempotentInstruction, createSyncNativeInstruction, createTransferCheckedInstruction, unpackAccount, createCloseAccountInstruction } from '@solana/spl-token';
5
5
  import { unpack } from '@solana/spl-token-metadata';
6
+ import DLMM, { binIdToBinArrayIndex, deriveBinArray, Strategy } from '@meteora-ag/dlmm';
6
7
  import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
7
8
  import { getUserAccountPublicKeySync, getUserStatsAccountPublicKey, decodeUser, MarketType, getDriftStateAccountPublicKey } from '@drift-labs/sdk';
8
9
  import { Marinade } from '@marinade.finance/marinade-ts-sdk';
9
10
  import { getStakePoolAccount } from '@solana/spl-stake-pool';
10
11
  import * as borsh from '@coral-xyz/borsh';
11
- import DLMM, { Strategy, binIdToBinArrayIndex, deriveBinArray } from '@meteora-ag/dlmm';
12
12
 
13
13
  var address = "GLAMbTqav9N9witRjswJ8enwp9vv5G8bsSJ2kPJ4rcyc";
14
14
  var metadata = {
15
15
  name: "glam_protocol",
16
- version: "0.4.13",
16
+ version: "0.4.16",
17
17
  spec: "0.1.0",
18
18
  description: "Glam Protocol"
19
19
  };
@@ -1259,6 +1259,144 @@ var instructions = [
1259
1259
  }
1260
1260
  ]
1261
1261
  },
1262
+ {
1263
+ name: "drift_settle_multiple_pnls",
1264
+ discriminator: [
1265
+ 100,
1266
+ 72,
1267
+ 3,
1268
+ 45,
1269
+ 69,
1270
+ 37,
1271
+ 10,
1272
+ 144
1273
+ ],
1274
+ accounts: [
1275
+ {
1276
+ name: "glam_state"
1277
+ },
1278
+ {
1279
+ name: "glam_vault",
1280
+ pda: {
1281
+ seeds: [
1282
+ {
1283
+ kind: "const",
1284
+ value: [
1285
+ 118,
1286
+ 97,
1287
+ 117,
1288
+ 108,
1289
+ 116
1290
+ ]
1291
+ },
1292
+ {
1293
+ kind: "account",
1294
+ path: "glam_state"
1295
+ }
1296
+ ]
1297
+ }
1298
+ },
1299
+ {
1300
+ name: "glam_signer",
1301
+ writable: true,
1302
+ signer: true
1303
+ },
1304
+ {
1305
+ name: "cpi_program",
1306
+ address: "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH"
1307
+ },
1308
+ {
1309
+ name: "state"
1310
+ },
1311
+ {
1312
+ name: "user",
1313
+ writable: true
1314
+ },
1315
+ {
1316
+ name: "spot_market_vault"
1317
+ }
1318
+ ],
1319
+ args: [
1320
+ {
1321
+ name: "market_indexes",
1322
+ type: {
1323
+ vec: "u16"
1324
+ }
1325
+ },
1326
+ {
1327
+ name: "mode",
1328
+ type: {
1329
+ defined: {
1330
+ name: "SettlePnlMode"
1331
+ }
1332
+ }
1333
+ }
1334
+ ]
1335
+ },
1336
+ {
1337
+ name: "drift_settle_pnl",
1338
+ discriminator: [
1339
+ 161,
1340
+ 254,
1341
+ 255,
1342
+ 100,
1343
+ 140,
1344
+ 113,
1345
+ 169,
1346
+ 175
1347
+ ],
1348
+ accounts: [
1349
+ {
1350
+ name: "glam_state"
1351
+ },
1352
+ {
1353
+ name: "glam_vault",
1354
+ pda: {
1355
+ seeds: [
1356
+ {
1357
+ kind: "const",
1358
+ value: [
1359
+ 118,
1360
+ 97,
1361
+ 117,
1362
+ 108,
1363
+ 116
1364
+ ]
1365
+ },
1366
+ {
1367
+ kind: "account",
1368
+ path: "glam_state"
1369
+ }
1370
+ ]
1371
+ }
1372
+ },
1373
+ {
1374
+ name: "glam_signer",
1375
+ writable: true,
1376
+ signer: true
1377
+ },
1378
+ {
1379
+ name: "cpi_program",
1380
+ address: "dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH"
1381
+ },
1382
+ {
1383
+ name: "state"
1384
+ },
1385
+ {
1386
+ name: "user",
1387
+ writable: true
1388
+ },
1389
+ {
1390
+ name: "spot_market_vault"
1391
+ }
1392
+ ],
1393
+ args: [
1394
+ {
1395
+ name: "market_index",
1396
+ type: "u16"
1397
+ }
1398
+ ]
1399
+ },
1262
1400
  {
1263
1401
  name: "drift_update_user_custom_margin_ratio",
1264
1402
  discriminator: [
@@ -3074,6 +3212,96 @@ var instructions = [
3074
3212
  ],
3075
3213
  args: []
3076
3214
  },
3215
+ {
3216
+ name: "kamino_farm_harvest_reward",
3217
+ discriminator: [
3218
+ 64,
3219
+ 132,
3220
+ 133,
3221
+ 175,
3222
+ 224,
3223
+ 147,
3224
+ 145,
3225
+ 119
3226
+ ],
3227
+ accounts: [
3228
+ {
3229
+ name: "glam_state"
3230
+ },
3231
+ {
3232
+ name: "glam_vault",
3233
+ pda: {
3234
+ seeds: [
3235
+ {
3236
+ kind: "const",
3237
+ value: [
3238
+ 118,
3239
+ 97,
3240
+ 117,
3241
+ 108,
3242
+ 116
3243
+ ]
3244
+ },
3245
+ {
3246
+ kind: "account",
3247
+ path: "glam_state"
3248
+ }
3249
+ ]
3250
+ }
3251
+ },
3252
+ {
3253
+ name: "glam_signer",
3254
+ writable: true,
3255
+ signer: true
3256
+ },
3257
+ {
3258
+ name: "cpi_program",
3259
+ address: "FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr"
3260
+ },
3261
+ {
3262
+ name: "user_state",
3263
+ writable: true
3264
+ },
3265
+ {
3266
+ name: "farm_state",
3267
+ writable: true
3268
+ },
3269
+ {
3270
+ name: "global_config"
3271
+ },
3272
+ {
3273
+ name: "reward_mint"
3274
+ },
3275
+ {
3276
+ name: "user_reward_ata",
3277
+ writable: true
3278
+ },
3279
+ {
3280
+ name: "rewards_vault",
3281
+ writable: true
3282
+ },
3283
+ {
3284
+ name: "rewards_treasury_vault",
3285
+ writable: true
3286
+ },
3287
+ {
3288
+ name: "farm_vaults_authority"
3289
+ },
3290
+ {
3291
+ name: "scope_prices",
3292
+ optional: true
3293
+ },
3294
+ {
3295
+ name: "token_program"
3296
+ }
3297
+ ],
3298
+ args: [
3299
+ {
3300
+ name: "reward_index",
3301
+ type: "u64"
3302
+ }
3303
+ ]
3304
+ },
3077
3305
  {
3078
3306
  name: "kamino_lending_borrow_obligation_liquidity_v2",
3079
3307
  discriminator: [
@@ -3152,7 +3380,8 @@ var instructions = [
3152
3380
  },
3153
3381
  {
3154
3382
  name: "referrer_token_state",
3155
- writable: true
3383
+ writable: true,
3384
+ optional: true
3156
3385
  },
3157
3386
  {
3158
3387
  name: "token_program"
@@ -3162,11 +3391,13 @@ var instructions = [
3162
3391
  },
3163
3392
  {
3164
3393
  name: "obligation_farm_user_state",
3165
- writable: true
3394
+ writable: true,
3395
+ optional: true
3166
3396
  },
3167
3397
  {
3168
3398
  name: "reserve_farm_state",
3169
- writable: true
3399
+ writable: true,
3400
+ optional: true
3170
3401
  },
3171
3402
  {
3172
3403
  name: "farms_program"
@@ -3260,7 +3491,8 @@ var instructions = [
3260
3491
  writable: true
3261
3492
  },
3262
3493
  {
3263
- name: "placeholder_user_destination_collateral"
3494
+ name: "placeholder_user_destination_collateral",
3495
+ optional: true
3264
3496
  },
3265
3497
  {
3266
3498
  name: "collateral_token_program"
@@ -3273,11 +3505,13 @@ var instructions = [
3273
3505
  },
3274
3506
  {
3275
3507
  name: "obligation_farm_user_state",
3276
- writable: true
3508
+ writable: true,
3509
+ optional: true
3277
3510
  },
3278
3511
  {
3279
3512
  name: "reserve_farm_state",
3280
- writable: true
3513
+ writable: true,
3514
+ optional: true
3281
3515
  },
3282
3516
  {
3283
3517
  name: "farms_program"
@@ -3304,7 +3538,8 @@ var instructions = [
3304
3538
  ],
3305
3539
  accounts: [
3306
3540
  {
3307
- name: "glam_state"
3541
+ name: "glam_state",
3542
+ writable: true
3308
3543
  },
3309
3544
  {
3310
3545
  name: "glam_vault",
@@ -3525,7 +3760,8 @@ var instructions = [
3525
3760
  writable: true
3526
3761
  },
3527
3762
  {
3528
- name: "referrer_user_metadata"
3763
+ name: "referrer_user_metadata",
3764
+ optional: true
3529
3765
  },
3530
3766
  {
3531
3767
  name: "rent",
@@ -3620,11 +3856,13 @@ var instructions = [
3620
3856
  },
3621
3857
  {
3622
3858
  name: "obligation_farm_user_state",
3623
- writable: true
3859
+ writable: true,
3860
+ optional: true
3624
3861
  },
3625
3862
  {
3626
3863
  name: "reserve_farm_state",
3627
- writable: true
3864
+ writable: true,
3865
+ optional: true
3628
3866
  },
3629
3867
  {
3630
3868
  name: "lending_market_authority"
@@ -3721,7 +3959,8 @@ var instructions = [
3721
3959
  writable: true
3722
3960
  },
3723
3961
  {
3724
- name: "placeholder_user_destination_collateral"
3962
+ name: "placeholder_user_destination_collateral",
3963
+ optional: true
3725
3964
  },
3726
3965
  {
3727
3966
  name: "collateral_token_program"
@@ -3734,11 +3973,13 @@ var instructions = [
3734
3973
  },
3735
3974
  {
3736
3975
  name: "obligation_farm_user_state",
3737
- writable: true
3976
+ writable: true,
3977
+ optional: true
3738
3978
  },
3739
3979
  {
3740
3980
  name: "reserve_farm_state",
3741
- writable: true
3981
+ writable: true,
3982
+ optional: true
3742
3983
  },
3743
3984
  {
3744
3985
  name: "farms_program"
@@ -4259,7 +4500,8 @@ var instructions = [
4259
4500
  },
4260
4501
  {
4261
4502
  name: "bin_array_bitmap_extension",
4262
- writable: true
4503
+ writable: true,
4504
+ optional: true
4263
4505
  },
4264
4506
  {
4265
4507
  name: "user_token_x",
@@ -4371,7 +4613,8 @@ var instructions = [
4371
4613
  },
4372
4614
  {
4373
4615
  name: "bin_array_bitmap_extension",
4374
- writable: true
4616
+ writable: true,
4617
+ optional: true
4375
4618
  },
4376
4619
  {
4377
4620
  name: "user_token_x",
@@ -4483,7 +4726,8 @@ var instructions = [
4483
4726
  },
4484
4727
  {
4485
4728
  name: "bin_array_bitmap_extension",
4486
- writable: true
4729
+ writable: true,
4730
+ optional: true
4487
4731
  },
4488
4732
  {
4489
4733
  name: "user_token",
@@ -5040,7 +5284,8 @@ var instructions = [
5040
5284
  },
5041
5285
  {
5042
5286
  name: "bin_array_bitmap_extension",
5043
- writable: true
5287
+ writable: true,
5288
+ optional: true
5044
5289
  },
5045
5290
  {
5046
5291
  name: "user_token_x",
@@ -5157,8 +5402,9 @@ var instructions = [
5157
5402
  },
5158
5403
  {
5159
5404
  name: "bin_array_bitmap_extension",
5160
- writable: true
5161
- },
5405
+ writable: true,
5406
+ optional: true
5407
+ },
5162
5408
  {
5163
5409
  name: "user_token_x",
5164
5410
  writable: true
@@ -5271,7 +5517,8 @@ var instructions = [
5271
5517
  writable: true
5272
5518
  },
5273
5519
  {
5274
- name: "bin_array_bitmap_extension"
5520
+ name: "bin_array_bitmap_extension",
5521
+ optional: true
5275
5522
  },
5276
5523
  {
5277
5524
  name: "reserve_x",
@@ -5301,7 +5548,8 @@ var instructions = [
5301
5548
  },
5302
5549
  {
5303
5550
  name: "host_fee_in",
5304
- writable: true
5551
+ writable: true,
5552
+ optional: true
5305
5553
  },
5306
5554
  {
5307
5555
  name: "token_x_program"
@@ -5389,7 +5637,8 @@ var instructions = [
5389
5637
  writable: true
5390
5638
  },
5391
5639
  {
5392
- name: "bin_array_bitmap_extension"
5640
+ name: "bin_array_bitmap_extension",
5641
+ optional: true
5393
5642
  },
5394
5643
  {
5395
5644
  name: "reserve_x",
@@ -5419,7 +5668,8 @@ var instructions = [
5419
5668
  },
5420
5669
  {
5421
5670
  name: "host_fee_in",
5422
- writable: true
5671
+ writable: true,
5672
+ optional: true
5423
5673
  },
5424
5674
  {
5425
5675
  name: "token_x_program"
@@ -5592,7 +5842,8 @@ var instructions = [
5592
5842
  ],
5593
5843
  accounts: [
5594
5844
  {
5595
- name: "glam_state"
5845
+ name: "glam_state",
5846
+ writable: true
5596
5847
  },
5597
5848
  {
5598
5849
  name: "glam_vault"
@@ -5602,6 +5853,9 @@ var instructions = [
5602
5853
  writable: true,
5603
5854
  signer: true
5604
5855
  },
5856
+ {
5857
+ name: "sol_oracle"
5858
+ },
5605
5859
  {
5606
5860
  name: "state"
5607
5861
  },
@@ -5612,19 +5866,28 @@ var instructions = [
5612
5866
  name: "user_stats"
5613
5867
  }
5614
5868
  ],
5615
- args: []
5869
+ args: [
5870
+ {
5871
+ name: "denom",
5872
+ type: {
5873
+ defined: {
5874
+ name: "PriceDenom"
5875
+ }
5876
+ }
5877
+ }
5878
+ ]
5616
5879
  },
5617
5880
  {
5618
- name: "price_meteora",
5881
+ name: "price_kamino_obligations",
5619
5882
  discriminator: [
5620
5883
  166,
5621
- 250,
5622
- 203,
5623
- 148,
5624
- 67,
5625
- 60,
5626
- 207,
5627
- 51
5884
+ 110,
5885
+ 234,
5886
+ 179,
5887
+ 240,
5888
+ 179,
5889
+ 69,
5890
+ 246
5628
5891
  ],
5629
5892
  accounts: [
5630
5893
  {
@@ -5656,9 +5919,79 @@ var instructions = [
5656
5919
  name: "glam_signer",
5657
5920
  writable: true,
5658
5921
  signer: true
5922
+ },
5923
+ {
5924
+ name: "sol_oracle"
5659
5925
  }
5660
5926
  ],
5661
- args: []
5927
+ args: [
5928
+ {
5929
+ name: "denom",
5930
+ type: {
5931
+ defined: {
5932
+ name: "PriceDenom"
5933
+ }
5934
+ }
5935
+ }
5936
+ ]
5937
+ },
5938
+ {
5939
+ name: "price_meteora_positions",
5940
+ discriminator: [
5941
+ 186,
5942
+ 22,
5943
+ 157,
5944
+ 249,
5945
+ 185,
5946
+ 176,
5947
+ 253,
5948
+ 133
5949
+ ],
5950
+ accounts: [
5951
+ {
5952
+ name: "glam_state",
5953
+ writable: true
5954
+ },
5955
+ {
5956
+ name: "glam_vault",
5957
+ pda: {
5958
+ seeds: [
5959
+ {
5960
+ kind: "const",
5961
+ value: [
5962
+ 118,
5963
+ 97,
5964
+ 117,
5965
+ 108,
5966
+ 116
5967
+ ]
5968
+ },
5969
+ {
5970
+ kind: "account",
5971
+ path: "glam_state"
5972
+ }
5973
+ ]
5974
+ }
5975
+ },
5976
+ {
5977
+ name: "glam_signer",
5978
+ writable: true,
5979
+ signer: true
5980
+ },
5981
+ {
5982
+ name: "sol_oracle"
5983
+ }
5984
+ ],
5985
+ args: [
5986
+ {
5987
+ name: "denom",
5988
+ type: {
5989
+ defined: {
5990
+ name: "PriceDenom"
5991
+ }
5992
+ }
5993
+ }
5994
+ ]
5662
5995
  },
5663
5996
  {
5664
5997
  name: "price_stakes",
@@ -5702,9 +6035,21 @@ var instructions = [
5702
6035
  name: "glam_signer",
5703
6036
  writable: true,
5704
6037
  signer: true
6038
+ },
6039
+ {
6040
+ name: "sol_oracle"
5705
6041
  }
5706
6042
  ],
5707
- args: []
6043
+ args: [
6044
+ {
6045
+ name: "denom",
6046
+ type: {
6047
+ defined: {
6048
+ name: "PriceDenom"
6049
+ }
6050
+ }
6051
+ }
6052
+ ]
5708
6053
  },
5709
6054
  {
5710
6055
  name: "price_tickets",
@@ -5748,9 +6093,21 @@ var instructions = [
5748
6093
  name: "glam_signer",
5749
6094
  writable: true,
5750
6095
  signer: true
6096
+ },
6097
+ {
6098
+ name: "sol_oracle"
5751
6099
  }
5752
6100
  ],
5753
- args: []
6101
+ args: [
6102
+ {
6103
+ name: "denom",
6104
+ type: {
6105
+ defined: {
6106
+ name: "PriceDenom"
6107
+ }
6108
+ }
6109
+ }
6110
+ ]
5754
6111
  },
5755
6112
  {
5756
6113
  name: "price_vault",
@@ -5794,9 +6151,21 @@ var instructions = [
5794
6151
  name: "glam_signer",
5795
6152
  writable: true,
5796
6153
  signer: true
6154
+ },
6155
+ {
6156
+ name: "sol_oracle"
5797
6157
  }
5798
6158
  ],
5799
- args: []
6159
+ args: [
6160
+ {
6161
+ name: "denom",
6162
+ type: {
6163
+ defined: {
6164
+ name: "PriceDenom"
6165
+ }
6166
+ }
6167
+ }
6168
+ ]
5800
6169
  },
5801
6170
  {
5802
6171
  name: "queued_redeem",
@@ -8890,21 +9259,26 @@ var errors = [
8890
9259
  },
8891
9260
  {
8892
9261
  code: 51103,
8893
- name: "UnpricedExternalAccounts",
9262
+ name: "ExternalAccountsNotPriced",
8894
9263
  msg: "Not all external vault accounts are priced"
8895
9264
  },
8896
9265
  {
8897
9266
  code: 51104,
9267
+ name: "VaultAssetsNotPriced",
9268
+ msg: "Not all vault assets are priced"
9269
+ },
9270
+ {
9271
+ code: 51105,
8898
9272
  name: "VaultNotPriced",
8899
9273
  msg: "No priced assets found"
8900
9274
  },
8901
9275
  {
8902
- code: 51105,
9276
+ code: 51106,
8903
9277
  name: "PositiveAumRequired",
8904
9278
  msg: "AUM must be positive"
8905
9279
  },
8906
9280
  {
8907
- code: 51106,
9281
+ code: 51107,
8908
9282
  name: "MathError",
8909
9283
  msg: "Math error"
8910
9284
  },
@@ -11049,6 +11423,9 @@ var types = [
11049
11423
  {
11050
11424
  name: "KaminoWithdraw"
11051
11425
  },
11426
+ {
11427
+ name: "KaminoClaim"
11428
+ },
11052
11429
  {
11053
11430
  name: "MeteoraDlmmPosition"
11054
11431
  },
@@ -11117,6 +11494,9 @@ var types = [
11117
11494
  },
11118
11495
  {
11119
11496
  name: "USD"
11497
+ },
11498
+ {
11499
+ name: "ASSET6"
11120
11500
  }
11121
11501
  ]
11122
11502
  }
@@ -11243,6 +11623,20 @@ var types = [
11243
11623
  ]
11244
11624
  }
11245
11625
  },
11626
+ {
11627
+ name: "SettlePnlMode",
11628
+ type: {
11629
+ kind: "enum",
11630
+ variants: [
11631
+ {
11632
+ name: "MustSettle"
11633
+ },
11634
+ {
11635
+ name: "TrySettle"
11636
+ }
11637
+ ]
11638
+ }
11639
+ },
11246
11640
  {
11247
11641
  name: "ShareClassField",
11248
11642
  type: {
@@ -11997,6 +12391,8 @@ const SEED_VAULT = (GlamProtocolIdlJson.constants.find((x)=>x.name === "SEED_VAU
11997
12391
  const SEED_ESCROW = (GlamProtocolIdlJson.constants.find((x)=>x.name === "SEED_ESCROW")?.value || "").replace(/"/g, "");
11998
12392
  const MARINADE_TICKET_SIZE = 88;
11999
12393
  const STAKE_ACCOUNT_SIZE = 200;
12394
+ const METEORA_POSITION_SIZE = 8120;
12395
+ const KAMINO_OBTRIGATION_SIZE = 3344;
12000
12396
  const JITO_TIP_DEFAULT = new PublicKey("96gYZGLnJYVFmbjzopPSU6QiEV5fGqZNyN9nmNhvrZU5");
12001
12397
  /**
12002
12398
  * Token mints. If no devnet version is defined, assume mainnet and devnet addresses are the same.
@@ -12023,6 +12419,10 @@ const GOVERNANCE_PROGRAM_ID = new PublicKey("GovaE4iu227srtG2s3tZzB4RmWBzw8sTwrC
12023
12419
  const JUP_VOTE_PROGRAM = new PublicKey("voTpe3tHQ7AjQHMapgSue2HJFAh2cGsdokqN3XqmVSj");
12024
12420
  const MERKLE_DISTRIBUTOR_PROGRAM = new PublicKey("DiS3nNjFVMieMgmiQFm6wgJL7nevk4NrhXKLbtEH1Z2R");
12025
12421
  const TRANSFER_HOOK_PROGRAM = new PublicKey("po1iCYakK3gHCLbuju4wGzFowTMpAJxkqK1iwUqMonY");
12422
+ const METEORA_DLMM_PROGRAM = new PublicKey("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo");
12423
+ const KAMINO_LENDING_PROGRAM = new PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD");
12424
+ const KAMINO_FARM_PROGRAM = new PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr");
12425
+ const MEMO_PROGRAM = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
12026
12426
  /**
12027
12427
  * Stake pools
12028
12428
  */ const JITO_STAKE_POOL = new PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb");
@@ -12111,6 +12511,7 @@ class StateModel extends StateIdlModel {
12111
12511
  let stateModel = {
12112
12512
  id: statePda,
12113
12513
  name: stateAccount.name,
12514
+ enabled: stateAccount.enabled,
12114
12515
  uri: stateAccount.uri,
12115
12516
  accountType: stateAccount.accountType,
12116
12517
  metadata: stateAccount.metadata,
@@ -12132,7 +12533,7 @@ class StateModel extends StateIdlModel {
12132
12533
  if (new StateIdlModel({}).hasOwnProperty(name)) {
12133
12534
  // @ts-ignore
12134
12535
  stateModel[name] = value;
12135
- } else {
12536
+ } else if (process.env.NODE_ENV === "development") {
12136
12537
  console.warn(`State param ${name} not found in StateIdlModel`);
12137
12538
  }
12138
12539
  });
@@ -12340,14 +12741,22 @@ class DelegateAcl {
12340
12741
  this.expiresAt = obj.expiresAt ?? new BN(0);
12341
12742
  }
12342
12743
  }
12744
+ class PriceDenom {
12745
+ }
12746
+ PriceDenom.SOL = {
12747
+ sol: {}
12748
+ };
12749
+ PriceDenom.USD = {
12750
+ usd: {}
12751
+ };
12343
12752
 
12344
- var ClusterNetwork;
12345
- (function(ClusterNetwork) {
12753
+ var ClusterNetwork = /*#__PURE__*/ function(ClusterNetwork) {
12346
12754
  ClusterNetwork["Mainnet"] = "mainnet-beta";
12347
12755
  ClusterNetwork["Testnet"] = "testnet";
12348
12756
  ClusterNetwork["Devnet"] = "devnet";
12349
12757
  ClusterNetwork["Custom"] = "custom";
12350
- })(ClusterNetwork || (ClusterNetwork = {}));
12758
+ return ClusterNetwork;
12759
+ }({});
12351
12760
 
12352
12761
  const fetchStakeAccounts = async (connection, withdrawAuthority)=>{
12353
12762
  const accounts = await connection.getParsedProgramAccounts(StakeProgram.programId, {
@@ -12379,6 +12788,67 @@ const fetchMarinadeTicketAccounts = async (connection, beneficiary)=>await conne
12379
12788
  }
12380
12789
  ]
12381
12790
  });
12791
+ const fetchKaminoObligations = async (connection, owner, market)=>{
12792
+ const accounts = await connection.getParsedProgramAccounts(KAMINO_LENDING_PROGRAM, {
12793
+ filters: [
12794
+ {
12795
+ dataSize: KAMINO_OBTRIGATION_SIZE
12796
+ },
12797
+ {
12798
+ memcmp: {
12799
+ offset: 64,
12800
+ bytes: owner.toBase58()
12801
+ }
12802
+ },
12803
+ ...market ? [
12804
+ {
12805
+ memcmp: {
12806
+ offset: 32,
12807
+ bytes: market.toBase58()
12808
+ }
12809
+ }
12810
+ ] : []
12811
+ ]
12812
+ });
12813
+ return accounts.map((a)=>a.pubkey);
12814
+ };
12815
+ const fetchMeteoraPositions = async (connection, owner)=>{
12816
+ const accounts = await connection.getParsedProgramAccounts(METEORA_DLMM_PROGRAM, {
12817
+ filters: [
12818
+ {
12819
+ dataSize: METEORA_POSITION_SIZE
12820
+ },
12821
+ {
12822
+ memcmp: {
12823
+ offset: 40,
12824
+ bytes: owner.toBase58()
12825
+ }
12826
+ }
12827
+ ]
12828
+ });
12829
+ return accounts.map((a)=>a.pubkey);
12830
+ };
12831
+ const parseMeteoraPosition = async (connection, position)=>{
12832
+ const positionAccountInfo = await connection.getAccountInfo(position);
12833
+ if (!positionAccountInfo) {
12834
+ throw new Error("Position not found");
12835
+ }
12836
+ const positionData = positionAccountInfo.data;
12837
+ const lbPair = new PublicKey(positionData.subarray(8, 40));
12838
+ const lowerBinId = positionData.subarray(7912, 7916).readInt32LE();
12839
+ const upperBinId = positionData.subarray(7916, 7920).readInt32LE();
12840
+ const lowerBinArrayIndex = binIdToBinArrayIndex(new BN(lowerBinId));
12841
+ const [binArrayLower] = deriveBinArray(lbPair, lowerBinArrayIndex, METEORA_DLMM_PROGRAM);
12842
+ const upperBinArrayIndex = BN.max(lowerBinArrayIndex.add(new BN(1)), binIdToBinArrayIndex(new BN(upperBinId)));
12843
+ const [binArrayUpper] = deriveBinArray(lbPair, upperBinArrayIndex, METEORA_DLMM_PROGRAM);
12844
+ return {
12845
+ lbPair,
12846
+ lowerBinId,
12847
+ upperBinId,
12848
+ binArrayLower,
12849
+ binArrayUpper
12850
+ };
12851
+ };
12382
12852
  const getSimulationComputeUnits = async (connection, instructions, payer, lookupTables)=>{
12383
12853
  const testInstructions = [
12384
12854
  // Set an arbitrarily high number in simulation
@@ -12435,556 +12905,132 @@ const getErrorFromRPCResponse = (rpcResponse)=>{
12435
12905
  }
12436
12906
  };
12437
12907
 
12438
- /**
12439
- * Metadata for an asset for pricing
12440
- */ class AssetMeta {
12441
- }
12442
- /**
12443
- * We use sponsored feed listed on https://docs.pyth.network/price-feeds/sponsored-feeds/solana for popular tokens.
12444
- *
12445
- * For PYUSD, we use the price feed from Drift.
12446
- * For LSTs, we use the state account to calculate the price based on the number of SOLs locked.
12447
- */ const ASSETS_MAINNET = new Map([
12908
+ const ASSETS_MAINNET = new Map([
12448
12909
  [
12449
- // wSOL
12910
+ // SOL
12450
12911
  "So11111111111111111111111111111111111111112",
12451
12912
  {
12452
- pricingAccount: new PublicKey("7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE"),
12453
- priceFeed: "ef0d8b6fda2ceba41da15d4095d1da392a0d2f8ed0c6c7bc0f4cfac8c280b56d"
12454
- }
12455
- ],
12456
- [
12457
- // USDC
12458
- "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
12459
- {
12460
- pricingAccount: new PublicKey("Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX"),
12461
- priceFeed: "eaa020c61cc479712813461ce153894a96a6c00b21ed0cfc2798d1f9a9e9c94a"
12913
+ decimals: 9,
12914
+ oracle: new PublicKey("3m6i4RFWEDw2Ft4tFHPJtYgmpPe21k56M3FHeWYrgGBz")
12462
12915
  }
12463
12916
  ],
12464
12917
  [
12465
- // USDT
12466
- "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
12467
- {
12468
- pricingAccount: new PublicKey("HT2PLQBcG5EiCcNSaMHAjSgd9F98ecpATbk4Sk5oYuM"),
12469
- priceFeed: "2b89b9dc8fdf9f34709a5b106b472f0f39bb6ca9ce04b0fd7f2e971688e2e53b"
12470
- }
12471
- ],
12472
- [
12473
- // wBTC (Wormhole)
12918
+ // wBTC
12474
12919
  "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
12475
12920
  {
12476
- pricingAccount: new PublicKey("9gNX5vguzarZZPjTnE1hWze3s6UsZ7dsU3UnAmKPnMHG"),
12477
- priceFeed: "c9d8b075a5c69303365ae23633d4e085199bf5c520a3b90fed1322a0342ffc33"
12478
- }
12479
- ],
12480
- [
12481
- // ETH
12482
- "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
12483
- {
12484
- pricingAccount: new PublicKey("42amVS4KgzR9rA28tkVYqVXjq9Qa8dcZQMbH5EYFX6XC"),
12485
- priceFeed: "ff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace"
12921
+ decimals: 8,
12922
+ oracle: new PublicKey("fqPfDa6uQr9ndMvwaFp4mUBeUrHmLop8Jxfb1XJNmVm")
12486
12923
  }
12487
12924
  ],
12488
12925
  [
12489
- // PYTH
12490
- "HZ1JovNiVvGrGNiiYvEozEVgZ58xaU3RKwX8eACQBCt3",
12926
+ // cbBTC
12927
+ "cbbtcf3aa214zXHbiAZQwf4122FBYbraNdFqgw4iMij",
12491
12928
  {
12492
- pricingAccount: new PublicKey("8vjchtMuJNY4oFQdTi8yCe6mhCaNBFaUbktT482TpLPS"),
12493
- priceFeed: "0bbf28e9a841a1cc788f6a361b17ca072d0ea3098a1e5df1c3922d06719579ff"
12929
+ decimals: 8,
12930
+ oracle: new PublicKey("9jPy6EHpLkXaMdvfkoVnRnSdJoQysQDKKj3bW5Amz4Ci")
12494
12931
  }
12495
12932
  ],
12496
12933
  [
12497
- // BONK
12498
- "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
12934
+ // wETH
12935
+ "7vfCXTUXx5WJV5JADk17DUJ4ksgau7utNKj4b963voxs",
12499
12936
  {
12500
- pricingAccount: new PublicKey("DBE3N8uNjhKPRHfANdwGvCZghWXyLPdqdSbEW2XFwBiX"),
12501
- priceFeed: "72b021217ca3fe68922a19aaf990109cb9d84e9ad004b4d2025ad6f529314419"
12937
+ decimals: 8,
12938
+ oracle: new PublicKey("6bEp2MiyoiiiDxcVqE8rUHQWwHirXUXtKfAEATTVqNzT")
12502
12939
  }
12503
12940
  ],
12504
12941
  [
12505
- // mSOL
12506
- "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
12942
+ // JUP
12943
+ "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN",
12507
12944
  {
12508
- stateAccount: new PublicKey("8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC"),
12509
- priceFeed: "c2289a6a43d2ce91c6f55caec370f4acc38a2ed477f58813334c6d03749ff2a4"
12945
+ decimals: 6,
12946
+ oracle: new PublicKey("DXqKSHyhTBKEW4qgnL7ycbf3Jca5hCvUgWHFYWsh4KJa")
12510
12947
  }
12511
12948
  ],
12512
- //
12513
- // Price feed from Drift
12514
- //
12515
12949
  [
12516
- // PYUSD
12517
- "2b1kV6DkPAnxd5ixfnxCpjxmKwqjjaYmCZfHsFu24GXo",
12950
+ // JLP
12951
+ "27G8MtK7VtTcCHkpASjSDdkWWYfoqT6ggEuKidVJidD4",
12518
12952
  {
12519
- pricingAccount: new PublicKey("HpMoKp3TCd3QT4MWYUKk2zCBwmhr5Df45fB6wdxYqEeh"),
12520
- priceFeed: "c1da1b73d7f01e7ddd54b3766cf7fcd644395ad14f70aa706ec5384c59e76692"
12953
+ decimals: 6,
12954
+ oracle: new PublicKey("5Mb11e5rt1Sp6A286B145E4TmgMzsM2UX9nCF2vas5bs")
12521
12955
  }
12522
12956
  ],
12523
- //
12524
- // LST - autogen
12525
- //
12526
12957
  [
12527
- // fpSOL - FP SOL
12528
- "fpSoL8EJ7UA5yJxFKWk1MFiWi35w8CbH36G5B9d7DsV",
12958
+ // USDC
12959
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
12529
12960
  {
12530
- stateAccount: new PublicKey("GutG5bcmEZw15WmPHNVMWHU77c6t8CEinUEdPLYz3doa")
12961
+ decimals: 6,
12962
+ oracle: new PublicKey("9VCioxmni2gDLv11qufWzT3RDERhQE4iY5Gf7NTfYyAV")
12531
12963
  }
12532
12964
  ],
12533
12965
  [
12534
- // wifSOL - dogwifSOL
12535
- "Fi5GayacZzUrfaCRCJtBz2vSYkGF56xjgCceZx5SbXwq",
12966
+ // USDT
12967
+ "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
12536
12968
  {
12537
- stateAccount: new PublicKey("9Z8yimuc3bQCWLDyMhe6jfWqNk9EggyJZUo8TLnYsqhN")
12969
+ decimals: 6,
12970
+ oracle: new PublicKey("JDKJSkxjasBGL3ce1pkrN6tqDzuVUZPWzzkGuyX8m9yN")
12538
12971
  }
12539
12972
  ],
12540
12973
  [
12541
- // pathSOL - Pathfinders SOL
12542
- "pathdXw4He1Xk3eX84pDdDZnGKEme3GivBamGCVPZ5a",
12974
+ // mSOL
12975
+ "mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So",
12543
12976
  {
12544
- stateAccount: new PublicKey("GM7TwD34n8HmDP9XcT6bD3JJuNniKJkrKQinHqmqHarz")
12977
+ decimals: 9,
12978
+ // oracle: new PublicKey("FAq7hqjn7FWGXKDwJHzsXGgBcydGTcK4kziJpAGWXjDb"), // drift pyth
12979
+ oracle: new PublicKey("8szGkuLTAux9XMgZ2vtY39jVSowEcpBfFfD8hXSEqdGC")
12545
12980
  }
12546
12981
  ],
12547
12982
  [
12548
- // JupSOL - Jupiter Staked SOL
12549
- "jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v",
12983
+ // jitoSOL
12984
+ "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
12550
12985
  {
12551
- stateAccount: new PublicKey("8VpRhuxa7sUUepdY3kQiTmX9rS5vx4WgaXiAnXq4KCtr")
12986
+ decimals: 9,
12987
+ // oracle: new PublicKey("9QE1P5EfzthYDgoQ9oPeTByCEKaRJeZbVVqKJfgU9iau"), // drift pyth
12988
+ oracle: new PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb")
12552
12989
  }
12553
12990
  ],
12554
- // jjupSOL - Juicing Jupiter SOL
12555
- // [
12556
- // "BgYgFYq4A9a2o5S1QbWkmYVFBh7LBQL8YvugdhieFg38",
12557
- // {
12558
- // stateAccount: new PublicKey(
12559
- // "4mBwcXKJN2vz6MJikNTgVBSY5vYnyjZk7txd8j3K46Ei", // state
12560
- // ),
12561
- // },
12562
- // ],
12563
12991
  [
12564
- // phaseSOL - Phase Labs SOL
12565
- "phaseZSfPxTDBpiVb96H4XFSD8xHeHxZre5HerehBJG",
12992
+ // bonkSOL
12993
+ "BonK1YhkXEGLZzwtcvRTip3gAL9nCeQD7ppZBLXhtTs",
12566
12994
  {
12567
- stateAccount: new PublicKey("phasejkG1akKgqkLvfWzWY17evnH6mSWznnUspmpyeG")
12995
+ decimals: 9,
12996
+ oracle: new PublicKey("ArAQfbzsdotoKB5jJcZa3ajQrrPcWr2YQoDAEAiFxJAC")
12568
12997
  }
12569
12998
  ],
12570
12999
  [
12571
- // banxSOL - banxSOL
12572
- "BANXyWgPpa519e2MtQF1ecRbKYKKDMXPF1dyBxUq9NQG",
13000
+ // dSOL
13001
+ "Dso1bDeDjCQxTrWHqUUi63oBvV7Mdm6WaobLbQ7gnPQ",
12573
13002
  {
12574
- stateAccount: new PublicKey("4fdMvFuyNboQ5Kr93X16f1tFcTeEkvfNwNAeSrzY3afb")
13003
+ decimals: 9,
13004
+ oracle: new PublicKey("9mhGNSPArRMHpLDMSmxAvuoizBqtBGqYdT8WGuqgxNdn")
12575
13005
  }
12576
- ],
12577
- [
12578
- // iceSOL - iceSOL
12579
- "iceSdwqztAQFuH6En49HWwMxwthKMnGzLFQcMN3Bqhj",
12580
- {
12581
- stateAccount: new PublicKey("EVXQHaLSJyUNrnBGfXUnvEi4DvVz4UJ3GnoKGVQVxrjr")
13006
+ ]
13007
+ ]);
13008
+ const ASSETS_TESTS = new Map([]);
13009
+ const SOL_ORACLE = ASSETS_MAINNET.get("So11111111111111111111111111111111111111112").oracle;
13010
+
13011
+ class GlamError extends Error {
13012
+ constructor(message, rawError, programLogs){
13013
+ super(message);
13014
+ this.message = message;
13015
+ this.rawError = rawError;
13016
+ this.programLogs = programLogs;
13017
+ }
13018
+ }
13019
+
13020
+ const BROWSER_CACHE_NAME = "glam-gui";
13021
+ class BlockhashWithCache {
13022
+ async get() {
13023
+ let data;
13024
+ if (this.isBrowser) {
13025
+ data = await this._getFromBrowserCache();
13026
+ } else {
13027
+ data = this._getFromNodeCache();
12582
13028
  }
12583
- ],
12584
- [
12585
- // fmSOL - SolanaFM Staked SOL
12586
- "fmSoLKzBY6h9b5RQ67UVs7xE3Ym6mx2ChpPxHdoaVho",
12587
- {
12588
- stateAccount: new PublicKey("5FYTvZgc7QEGZSDmbJn5hrtjtRtyFZo5vR7gL1jJYanE")
12589
- }
12590
- ],
12591
- [
12592
- // BurnSOL - BurnDAO
12593
- "AxM7a5HNmRNHbND6h5ZMSsU8n3NLa1tskoN6m5mAgVvL",
12594
- {
12595
- stateAccount: new PublicKey("CAEsfzw43mvaVauCxXCSJh8DvnFsTMiTyeL1kjs6UwaT")
12596
- }
12597
- ],
12598
- [
12599
- // BNSOL - Binance Staked SOL
12600
- "BNso1VUJnh4zcfpZa6986Ea66P6TCp59hvtNJ8b1X85",
12601
- {
12602
- stateAccount: new PublicKey("Hr9pzexrBge3vgmBNRR8u42CNQgBXdHm4UkUN2DH4a7r")
12603
- }
12604
- ],
12605
- [
12606
- // pwrSOL - Power Staked SOL
12607
- "pWrSoLAhue6jUxUkbWgmEy5rD9VJzkFmvfTDV5KgNuu",
12608
- {
12609
- stateAccount: new PublicKey("DfiQgSvpW3Dy4gKfhtdHnWGHwFUrE8exvaxqjtMtAVxk")
12610
- }
12611
- ],
12612
- [
12613
- // superSOL - Superfast Staked SOL
12614
- "suPer8CPwxoJPQ7zksGMwFvjBQhjAHwUMmPV4FVatBw",
12615
- {
12616
- stateAccount: new PublicKey("4dZDUL3BFJUFeqS3Y3cwkc84Rs6mgVHRYGt1LJvhooW4")
12617
- }
12618
- ],
12619
- [
12620
- // jucySOL - Juicy SOL
12621
- "jucy5XJ76pHVvtPZb5TKRcGQExkwit2P5s4vY8UzmpC",
12622
- {
12623
- stateAccount: new PublicKey("AZGSr2fUyKkPLMhAW6WUEKEsQiRMAFKf8Fjnt4MFFaGv")
12624
- }
12625
- ],
12626
- [
12627
- // bonkSOL - bonkSOL
12628
- "BonK1YhkXEGLZzwtcvRTip3gAL9nCeQD7ppZBLXhtTs",
12629
- {
12630
- stateAccount: new PublicKey("ArAQfbzsdotoKB5jJcZa3ajQrrPcWr2YQoDAEAiFxJAC")
12631
- }
12632
- ],
12633
- [
12634
- // dSOL - Drift Staked SOL
12635
- "Dso1bDeDjCQxTrWHqUUi63oBvV7Mdm6WaobLbQ7gnPQ",
12636
- {
12637
- stateAccount: new PublicKey("9mhGNSPArRMHpLDMSmxAvuoizBqtBGqYdT8WGuqgxNdn")
12638
- }
12639
- ],
12640
- [
12641
- // compassSOL - Compass SOL
12642
- "Comp4ssDzXcLeu2MnLuGNNFC4cmLPMng8qWHPvzAMU1h",
12643
- {
12644
- stateAccount: new PublicKey("AwDeTcW6BovNYR34Df1TPm4bFwswa4CJY4YPye2LXtPS")
12645
- }
12646
- ],
12647
- [
12648
- // picoSOL - picoSOL
12649
- "picobAEvs6w7QEknPce34wAE4gknZA9v5tTonnmHYdX",
12650
- {
12651
- stateAccount: new PublicKey("8Dv3hNYcEWEaa4qVx9BTN1Wfvtha1z8cWDUXb7KVACVe")
12652
- }
12653
- ],
12654
- [
12655
- // clockSOL - Overclock SOL
12656
- "GRJQtWwdJmp5LLpy8JWjPgn5FnLyqSJGNhn5ZnCTFUwM",
12657
- {
12658
- stateAccount: new PublicKey("6e2LpgytfG3RqMdYuPr3dnedv6bmHQUk9hH9h2fzVk9o")
12659
- }
12660
- ],
12661
- [
12662
- // hubSOL - SolanaHub staked SOL
12663
- "HUBsveNpjo5pWqNkH57QzxjQASdTVXcSK7bVKTSZtcSX",
12664
- {
12665
- stateAccount: new PublicKey("ECRqn7gaNASuvTyC5xfCUjehWZCSowMXstZiM5DNweyB")
12666
- }
12667
- ],
12668
- [
12669
- // strongSOL - Stronghold LST
12670
- "strng7mqqc1MBJJV6vMzYbEqnwVGvKKGKedeCvtktWA",
12671
- {
12672
- stateAccount: new PublicKey("GZDX5JYXDzCEDL3kybhjN7PSixL4ams3M2G4CvWmMmm5")
12673
- }
12674
- ],
12675
- [
12676
- // lanternSOL - Lantern Staked SOL
12677
- "LnTRntk2kTfWEY6cVB8K9649pgJbt6dJLS1Ns1GZCWg",
12678
- {
12679
- stateAccount: new PublicKey("LW3qEdGWdVrxNgxSXW8vZri7Jifg4HuKEQ1UABLxs3C")
12680
- }
12681
- ],
12682
- [
12683
- // stakeSOL - Stake City SOL
12684
- "st8QujHLPsX3d6HG9uQg9kJ91jFxUgruwsb1hyYXSNd",
12685
- {
12686
- stateAccount: new PublicKey("2jjK1MsLgsPgVjnp97HUJeovNj3jp4XgyQ3nuiWMwiS8")
12687
- }
12688
- ],
12689
- [
12690
- // pumpkinSOL - Pumpkin's Staked SOL
12691
- "pumpkinsEq8xENVZE6QgTS93EN4r9iKvNxNALS1ooyp",
12692
- {
12693
- stateAccount: new PublicKey("8WHCJsUduwDBhPL9uVADQSdWkUi2LPZNFAMyX1n2HGMD")
12694
- }
12695
- ],
12696
- [
12697
- // hSOL - Helius Staked SOL
12698
- "he1iusmfkpAdwvxLNGV8Y1iSbj4rUy6yMhEA3fotn9A",
12699
- {
12700
- stateAccount: new PublicKey("3wK2g8ZdzAH8FJ7PKr2RcvGh7V9VYson5hrVsJM5Lmws")
12701
- }
12702
- ],
12703
- [
12704
- // lifSOL - Lifinity Staked SOL
12705
- "LSoLi4A4Pk4i8DPFYcfHziRdEbH9otvSJcSrkMVq99c",
12706
- {
12707
- stateAccount: new PublicKey("HSDnqBq7EnfcKpnw52DTAZrP38tf8rdWLiRhQo4qGTUa")
12708
- }
12709
- ],
12710
- [
12711
- // cgntSOL - Cogent SOL
12712
- "CgnTSoL3DgY9SFHxcLj6CgCgKKoTBr6tp4CPAEWy25DE",
12713
- {
12714
- stateAccount: new PublicKey("CgntPoLka5pD5fesJYhGmUCF8KU1QS1ZmZiuAuMZr2az")
12715
- }
12716
- ],
12717
- [
12718
- // laineSOL - Laine Stake Token
12719
- "LAinEtNLgpmCP9Rvsf5Hn8W6EhNiKLZQti1xfWMLy6X",
12720
- {
12721
- stateAccount: new PublicKey("2qyEeSAWKfU18AFthrF7JA8z8ZCi1yt76Tqs917vwQTV")
12722
- }
12723
- ],
12724
- [
12725
- // vSOL - The Vault
12726
- "vSoLxydx6akxyMD9XEcPvGYNGq6Nn66oqVb3UkGkei7",
12727
- {
12728
- stateAccount: new PublicKey("Fu9BYC6tWBo1KMKaP3CFoKfRhqv9akmy3DuYwnCyWiyC")
12729
- }
12730
- ],
12731
- [
12732
- // bSOL - BlazeStake Staked SOL
12733
- "bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1",
12734
- {
12735
- stateAccount: new PublicKey("stk9ApL5HeVAwPLr3TLhDXdZS8ptVu7zp6ov8HFDuMi")
12736
- }
12737
- ],
12738
- [
12739
- // daoSOL - daoSOL
12740
- "GEJpt3Wjmr628FqXxTgxMce1pLntcPV4uFi8ksxMyPQh",
12741
- {
12742
- stateAccount: new PublicKey("7ge2xKsZXmqPxa3YmXxXmzCp9Hc2ezrTxh6PECaxCwrL")
12743
- }
12744
- ],
12745
- [
12746
- // JitoSOL - Jito Staked SOL
12747
- "J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn",
12748
- {
12749
- stateAccount: new PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb"),
12750
- pricingAccount: new PublicKey("7yyaeuJ1GGtVBLT2z2xub5ZWYKaNhF28mj1RdV4VDFVk"),
12751
- priceFeed: "67be9f519b95cf24338801051f9a808eff0a578ccb388db73b7f6fe1de019ffb"
12752
- }
12753
- ],
12754
- [
12755
- // JSOL - JPOOL Solana Token
12756
- "7Q2afV64in6N6SeZsAAB81TJzwDoD6zpqmHkzi9Dcavn",
12757
- {
12758
- stateAccount: new PublicKey("CtMyWsrUtAwXWiGr9WjHT5fC3p3fgV8cyGpLTo2LJzG1")
12759
- }
12760
- ],
12761
- [
12762
- // LST - Liquid Staking Token
12763
- "LSTxxxnJzKDFSLr4dUkPcmCf5VyryEqzPLz5j4bpxFp",
12764
- {
12765
- stateAccount: new PublicKey("DqhH94PjkZsjAqEze2BEkWhFQJ6EyU6MdtMphMgnXqeK")
12766
- }
12767
- ],
12768
- [
12769
- // zippySOL - Zippy Staked SOL
12770
- "Zippybh3S5xYYam2nvL6hVJKz1got6ShgV4DyD1XQYF",
12771
- {
12772
- stateAccount: new PublicKey("DxRFpqBQBC2nKcvh14gD1eizCj9Xi7ruMR3nCR3Hvw8f")
12773
- }
12774
- ],
12775
- [
12776
- // edgeSOL - Edgevana Staked SOL
12777
- "edge86g9cVz87xcpKpy3J77vbp4wYd9idEV562CCntt",
12778
- {
12779
- stateAccount: new PublicKey("edgejNWAqkePLpi5sHRxT9vHi7u3kSHP9cocABPKiWZ")
12780
- }
12781
- ],
12782
- [
12783
- // thugSOL - Thugbirdz Staked SOL
12784
- "ThUGsoLWtoTCfb24AmQTKDVjTTUBbNrUrozupJeyPsy",
12785
- {
12786
- stateAccount: new PublicKey("G9WdMBxWSo1X3fKxbuyGrv1nGXrVqGg5zBKAkBFkb37g")
12787
- }
12788
- ],
12789
- [
12790
- // wenSOL - Wen Staked SOL
12791
- "WensoLXxZJnev2YvihHFchn1dVVFnFLYvgomXWvvwRu",
12792
- {
12793
- stateAccount: new PublicKey("CWM1VcNPd2A5WF2x2mmEUCgA1PGSKNZCGAH5GsoQw7h8")
12794
- }
12795
- ],
12796
- [
12797
- // camaoSOL - camaoSOL
12798
- "camaK1kryp4KJ2jS1HDiZuxmK7S6dyEtr9DA7NsuAAB",
12799
- {
12800
- stateAccount: new PublicKey("2RUTyfN8iq7Hsd2s9rLgrRT9VhHLuqkx2mGNgbuzbhTc")
12801
- }
12802
- ],
12803
- [
12804
- // dainSOL - dainSOL
12805
- "2LuXDpkn7ZWMqufwgUv7ZisggGkSE5FpeHCHBsRgLg3m",
12806
- {
12807
- stateAccount: new PublicKey("7qJ34Vq7nGZvk5YExkJsDZB6to6vz9RpcPmNEK84HjrV")
12808
- }
12809
- ],
12810
- [
12811
- // digitSOL - digitSOL
12812
- "D1gittVxgtszzY4fMwiTfM4Hp7uL5Tdi1S9LYaepAUUm",
12813
- {
12814
- stateAccount: new PublicKey("4qYufFsPQETukkXd5z9fxDsdwm8AEaSqzYpuzmZzCJxR")
12815
- }
12816
- ],
12817
- [
12818
- // digitalSOL - digitalSOL
12819
- "3bfv2scCdbvumVBc3Sar5QhYXx7Ecsi8EFF2akjxe329",
12820
- {
12821
- stateAccount: new PublicKey("Fwy2jGmRCDjKpWTacMVvnLp66Fg4L5yhVCfahHsbjMGf")
12822
- }
12823
- ],
12824
- [
12825
- // dlgtSOL - Delegate Liquid Staking SOL
12826
- "DLGToUUnqy9hXxpJTm5VaiBKqnw9Zt1qzvrpwKwUmuuZ",
12827
- {
12828
- stateAccount: new PublicKey("9pffpv2w65TSeZpD988hAjvvzUiF1KZN1Swx5j2zPCdy")
12829
- }
12830
- ],
12831
- [
12832
- // dualSOL - Dual SOL
12833
- "DUAL6T9pATmQUFPYmrWq2BkkGdRxLtERySGScYmbHMER",
12834
- {
12835
- stateAccount: new PublicKey("BmEgS5XpWJJDqT3FVfB6ZmoELQrWkJxDXo3cNoJVsNFK")
12836
- }
12837
- ],
12838
- [
12839
- // haSOL - Hanabi Staked SOL
12840
- "haSo1Vz5aTsqEnz8nisfnEsipvbAAWpgzRDh2WhhMEh",
12841
- {
12842
- stateAccount: new PublicKey("9ovWYMZp18Qn7UVbyUvwqLSBBSEPDDA5q9pUgDFy6R23")
12843
- }
12844
- ],
12845
- [
12846
- // hausSOL - StakeHaus Staked SOL
12847
- "HausGKcq9G9zM3azwNmgZyzUvYeeqR8h8663PmZpxuDj",
12848
- {
12849
- stateAccount: new PublicKey("5bzgfi7nidWWrp3DCwPwLzepw7PGgawRmMH9tqqXMZRj")
12850
- }
12851
- ],
12852
- [
12853
- // kumaSOL - kumaSOL
12854
- "KUMAgSzADhUmwXwNiUbNHYnMBnd89u4t9obZThJ4dqg",
12855
- {
12856
- stateAccount: new PublicKey("Fvy5L7f3rduuYfRf9GR9fDqEgmJkYagDPh3Ddkp5jcoP")
12857
- }
12858
- ],
12859
- [
12860
- // nordSOL - Nordic Staked SOL
12861
- "nordEhq2BnR6weCyrdezNVk7TwC3Ej94znPZxdBnfLM",
12862
- {
12863
- stateAccount: new PublicKey("GrrASJmjz19gHDsUUGv9y3gtRAwYJcdrtFESCRAosd44")
12864
- }
12865
- ],
12866
- [
12867
- // polarSOL - polarSOL
12868
- "PoLaRbHgtHnmeSohWQN83LkwA4xnQt91VUqL5hx5VTc",
12869
- {
12870
- stateAccount: new PublicKey("EYwMHf8Ajnpvy3PqMMkq1MPkTyhCsBEesXFgnK9BZfmu")
12871
- }
12872
- ],
12873
- [
12874
- // rkSOL - StaRKe SOL
12875
- "EPCz5LK372vmvCkZH3HgSuGNKACJJwwxsofW6fypCPZL",
12876
- {
12877
- stateAccount: new PublicKey("6LXCxeyQZqdAL4yLCtgATFYF6dcayWvsiwjtBFYVfb1N")
12878
- }
12879
- ],
12880
- [
12881
- // rSOL - reflectSOL
12882
- "RSoLp7kddnNwvvvaz4b1isQy8vcqdSwXjgm1wXaMhD8",
12883
- {
12884
- stateAccount: new PublicKey("4gT1GaFtJK5pnX3CnjnSYwy8VUV9UdmozoQV9GCNk9RQ")
12885
- }
12886
- ],
12887
- [
12888
- // spikySOL - Hedgehog Spiky SOL
12889
- "spkyB5SzVaz2x3nNzSBuhpLSEF8otbRDbufc73fuLXg",
12890
- {
12891
- stateAccount: new PublicKey("GEGRQNw17Y5s44dRH69sk8bvhyj3i6VwgqGmN1MBHKHp")
12892
- }
12893
- ],
12894
- [
12895
- // stakrSOL - STAKR.space SOL
12896
- "stkrHcjQGytQggswj3tCF77yriaJYYhrRxisRqe9AiZ",
12897
- {
12898
- stateAccount: new PublicKey("9j2mFdABTCCnWnzLtpMjp86AEcm4e3XistVeuujds7Au")
12899
- }
12900
- ],
12901
- [
12902
- // xSOL - ElagabalX Staked SOL
12903
- "B5GgNAZQDN8vPrQ15jPrXmJxVtManHLqHogj9B9i4zSs",
12904
- {
12905
- stateAccount: new PublicKey("DYuSikgwzHidFo2b8jqrViW1psAb7hpawJnszBothRzp")
12906
- }
12907
- ],
12908
- [
12909
- // fuseSOL - Fuse Staked SOL
12910
- "fuseYvhNJbSzdDByyTCrLcogsoNwAviB1WeewhbqgFc",
12911
- {
12912
- stateAccount: new PublicKey("pjwKqvtt4ij6VJW4HxNxSaufSrkWHRc6iCTHoC4gFs4")
12913
- }
12914
- ],
12915
- [
12916
- // mangoSOL - Mango SOL
12917
- "MangmsBgFqJhW4cLUR9LxfVgMboY1xAoP8UUBiWwwuY",
12918
- {
12919
- stateAccount: new PublicKey("9jWbABPXfc75wseAbLEkBCb1NRaX9EbJZJTDQnbtpzc1")
12920
- }
12921
- ],
12922
- [
12923
- // apySOL - apySOL
12924
- "apySoLhdVa6QbvNyEjXCbET3FdUm9cCdEvYyjCU7icM",
12925
- {
12926
- stateAccount: new PublicKey("FxhzbU8rn4MhZxmeH2u7M18qkvFH3LjkWk8z9686TE45")
12927
- }
12928
- ],
12929
- [
12930
- // bbSOL
12931
- "Bybit2vBJGhPF52GBdNaQfUJ6ZpThSgHBobjWZpLPb4B",
12932
- {
12933
- stateAccount: new PublicKey("2aMLkB5p5gVvCwKkdSo5eZAL1WwhZbxezQr1wxiynRhq")
12934
- }
12935
- ]
12936
- ]);
12937
- const ASSETS_TESTS = new Map([
12938
- //
12939
- // LOCALNET
12940
- //
12941
- [
12942
- // USDC
12943
- "AwRP1kuJbykXeF4hcLzfMDMY2ZTGN3cx8ErCWxVYekef",
12944
- {
12945
- pricingAccount: new PublicKey("Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX")
12946
- }
12947
- ],
12948
- [
12949
- // BTC
12950
- "7Pz5yQdyQm64WtzxvpQZi3nD1q5mbxj4Hhcjy2kmZ7Zd",
12951
- {
12952
- pricingAccount: new PublicKey("4cSM2e6rvbGQUFiJbqytoVMi5GgghSMr8LwVrT9VPSPo"),
12953
- programId: TOKEN_2022_PROGRAM_ID
12954
- }
12955
- ],
12956
- [
12957
- // ETH
12958
- "GRxagtBNxzjwxkKdEgW7P1oqU57Amai6ha5F3UBJzU1m",
12959
- {
12960
- pricingAccount: new PublicKey("42amVS4KgzR9rA28tkVYqVXjq9Qa8dcZQMbH5EYFX6XC")
12961
- }
12962
- ]
12963
- ]);
12964
-
12965
- class GlamError extends Error {
12966
- constructor(message, rawError, programLogs){
12967
- super(message);
12968
- this.message = message;
12969
- this.rawError = rawError;
12970
- this.programLogs = programLogs;
12971
- }
12972
- }
12973
-
12974
- const BROWSER_CACHE_NAME = "glam-gui";
12975
- class BlockhashWithCache {
12976
- async get() {
12977
- let data;
12978
- if (this.isBrowser) {
12979
- data = await this._getFromBrowserCache();
12980
- } else {
12981
- data = this._getFromNodeCache();
12982
- }
12983
- if (data) {
12984
- const { blockhash, expiresAt } = data;
12985
- if (expiresAt > Date.now()) {
12986
- return blockhash;
12987
- }
13029
+ if (data) {
13030
+ const { blockhash, expiresAt } = data;
13031
+ if (expiresAt > Date.now()) {
13032
+ return blockhash;
13033
+ }
12988
13034
  }
12989
13035
  const latestBlockhash = await this.provider.connection.getLatestBlockhash();
12990
13036
  await this.set({
@@ -13066,7 +13112,14 @@ class BaseClient {
13066
13112
  * @param assetMint Token mint of the asset
13067
13113
  * @returns Metadata of the asset
13068
13114
  */ getAssetMeta(assetMint) {
13069
- return (this.isMainnet() ? ASSETS_MAINNET.get(assetMint) : ASSETS_MAINNET.get(assetMint) || ASSETS_TESTS.get(assetMint)) || new AssetMeta();
13115
+ let assetMeta = ASSETS_MAINNET.get(assetMint);
13116
+ if (!assetMeta && !this.isMainnet()) {
13117
+ assetMeta = ASSETS_TESTS.get(assetMint);
13118
+ }
13119
+ if (!assetMeta) {
13120
+ throw new Error("Invalid asset: " + assetMint);
13121
+ }
13122
+ return assetMeta;
13070
13123
  }
13071
13124
  async getComputeBudgetIxs(vTx, computeUnitLimit, getPriorityFeeMicroLamports, maxFeeLamports, useMaxFee) {
13072
13125
  if (this.isPhantom()) {
@@ -13407,7 +13460,7 @@ class BaseClient {
13407
13460
  const solBalance = new BN(await this.provider.connection.getBalance(glamVault));
13408
13461
  const delta = new BN(lamports).sub(wsolBalance); // wSOL amount needed
13409
13462
  if (solBalance.lt(delta)) {
13410
- throw new Error("Insufficient funds in vault to complete the transaction");
13463
+ throw new Error(`Insufficient funds in vault to complete the transaction. SOL balance (lamports): ${solBalance}, lamports needed: ${lamports}`);
13411
13464
  }
13412
13465
  if (delta.gt(new BN(0)) && solBalance.gte(delta)) {
13413
13466
  return [
@@ -13526,7 +13579,7 @@ class DriftClient {
13526
13579
  /*
13527
13580
  * Client methods
13528
13581
  */ async initialize(statePda, subAccountId = 0, txOptions = {}) {
13529
- const tx = await this.initializeTx(statePda, subAccountId, txOptions);
13582
+ const tx = await this.initializeTx(new PublicKey(statePda), subAccountId, txOptions);
13530
13583
  return await this.base.sendAndConfirm(tx);
13531
13584
  }
13532
13585
  async updateUserCustomMarginRatio(statePda, maxLeverage, subAccountId = 0) {
@@ -13569,8 +13622,12 @@ class DriftClient {
13569
13622
  const tx = await this.cancelOrdersByIdsTx(new PublicKey(statePda), orderIds, subAccountId, marketConfigs, txOptions);
13570
13623
  return await this.base.sendAndConfirm(tx);
13571
13624
  }
13572
- async priceDrift(statePda, marketConfigs, txOptions = {}) {
13573
- const tx = await this.priceDriftTx(new PublicKey(statePda), marketConfigs, txOptions);
13625
+ async settlePnl(statePda, marketIndex, subAccountId = 0, marketConfigs, txOptions = {}) {
13626
+ const tx = await this.settlePnlTx(new PublicKey(statePda), marketIndex, subAccountId, marketConfigs, txOptions);
13627
+ return await this.base.sendAndConfirm(tx);
13628
+ }
13629
+ async priceDrift(statePda, marketConfigs, priceDenom, txOptions = {}) {
13630
+ const tx = await this.priceDriftTx(new PublicKey(statePda), marketConfigs, priceDenom, txOptions);
13574
13631
  return await this.base.sendAndConfirm(tx);
13575
13632
  }
13576
13633
  /*
@@ -13681,17 +13738,20 @@ class DriftClient {
13681
13738
  userStats,
13682
13739
  state,
13683
13740
  glamSigner
13684
- })// .remainingAccounts([]) TODO: set glam referral account
13741
+ })// We should only try to add referrer if it is the first user (subAccountId == 0)
13742
+ // .remainingAccounts([]) TODO: set glam referral account
13685
13743
  .instruction();
13686
13744
  }
13687
13745
  async initializeTx(glamState, subAccountId = 0, txOptions = {}) {
13688
13746
  const glamSigner = txOptions.signer || this.base.getSigner();
13689
13747
  const tx = new Transaction();
13690
- // Create userStats account first if subAccountId is 0
13691
- // If subAccountId > 0, we assume userStats account is already created
13692
- if (subAccountId === 0) {
13748
+ // Create userStats account if it doesn't exist
13749
+ const [_, userStats] = this.getUser(glamState);
13750
+ const userStatsInfo = await this.base.provider.connection.getAccountInfo(userStats);
13751
+ if (!userStatsInfo) {
13693
13752
  tx.add(await this.initializeUserStatsIx(glamState, glamSigner));
13694
13753
  }
13754
+ // Initialize user (aka sub-account)
13695
13755
  tx.add(await this.initializeUserIx(glamState, glamSigner, subAccountId));
13696
13756
  return await this.base.intoVersionedTransaction(tx, txOptions);
13697
13757
  }
@@ -13872,8 +13932,8 @@ class DriftClient {
13872
13932
  const [user] = this.getUser(glamState, subAccountId);
13873
13933
  const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13874
13934
  const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex);
13875
- const tx = await this.base.program.methods// @ts-ignore
13876
- .driftCancelOrders(marketType, marketIndex, direction).accounts({
13935
+ // @ts-ignore
13936
+ const tx = await this.base.program.methods.driftCancelOrders(marketType, marketIndex, direction).accounts({
13877
13937
  glamState,
13878
13938
  glamSigner,
13879
13939
  user,
@@ -13894,18 +13954,33 @@ class DriftClient {
13894
13954
  }).remainingAccounts(remainingAccounts).transaction();
13895
13955
  return await this.base.intoVersionedTransaction(tx, txOptions);
13896
13956
  }
13897
- async priceDriftTx(glamState, marketConfigs, txOptions = {}) {
13957
+ async settlePnlTx(glamState, marketIndex, subAccountId = 0, marketConfigs, txOptions = {}) {
13958
+ const glamSigner = txOptions.signer || this.base.getSigner();
13959
+ const [user] = this.getUser(glamState, subAccountId);
13960
+ const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13961
+ const { vaultPDA } = marketConfigs.spot[marketIndex];
13962
+ const tx = await this.base.program.methods.driftSettlePnl(marketIndex).accounts({
13963
+ glamState,
13964
+ glamSigner,
13965
+ user,
13966
+ state: driftState,
13967
+ spotMarketVault: new PublicKey(vaultPDA)
13968
+ }).transaction();
13969
+ return await this.base.intoVersionedTransaction(tx, txOptions);
13970
+ }
13971
+ async priceDriftTx(glamState, marketConfigs, priceDenom, txOptions = {}) {
13898
13972
  const signer = txOptions.signer || this.base.getSigner();
13899
13973
  const glamVault = this.base.getVaultPda(glamState);
13900
13974
  const [user, userStats] = this.getUser(glamState);
13901
13975
  const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13902
13976
  const remainingAccounts = await this.composeRemainingAccounts(glamState, 0, marketConfigs);
13903
- const tx = await this.base.program.methods.priceDrift().accounts({
13977
+ const tx = await this.base.program.methods.priceDrift(priceDenom).accounts({
13904
13978
  glamState,
13905
13979
  signer,
13906
13980
  glamVault,
13907
13981
  user,
13908
13982
  userStats,
13983
+ solOracle: SOL_ORACLE,
13909
13984
  state: driftState
13910
13985
  }).remainingAccounts(remainingAccounts).transaction();
13911
13986
  return await this.base.intoVersionedTransaction(tx, txOptions);
@@ -13986,8 +14061,8 @@ class JupiterSwapClient {
13986
14061
  this.getTokenProgram(inputMint),
13987
14062
  this.getTokenProgram(outputMint)
13988
14063
  ]);
13989
- const inputStakePool = ASSETS_MAINNET.get(inputMint.toBase58())?.stateAccount || null;
13990
- const outputStakePool = ASSETS_MAINNET.get(outputMint.toBase58())?.stateAccount || null;
14064
+ const inputStakePool = ASSETS_MAINNET.get(inputMint.toBase58())?.oracle || null;
14065
+ const outputStakePool = ASSETS_MAINNET.get(outputMint.toBase58())?.oracle || null;
13991
14066
  const preInstructions = await this.getPreInstructions(glamState, glamSigner, inputMint, outputMint, amount, inputTokenProgram, outputTokenProgram);
13992
14067
  // @ts-ignore
13993
14068
  const tx = await this.base.program.methods.jupiterSwap(swapIx.data).accounts({
@@ -14554,10 +14629,10 @@ class StakingClient {
14554
14629
  }
14555
14630
  // Other LSTs
14556
14631
  const assetMeta = this.base.getAssetMeta(assetStr);
14557
- if (!assetMeta || !assetMeta.stateAccount) {
14632
+ if (!assetMeta || !assetMeta.oracle) {
14558
14633
  throw new Error("Invalid LST: " + asset);
14559
14634
  }
14560
- const tx = await this.stakePoolWithdrawStakeTx(glamState, assetMeta.stateAccount, new BN(amount), true, txOptions);
14635
+ const tx = await this.stakePoolWithdrawStakeTx(glamState, assetMeta.oracle, new BN(amount), true, txOptions);
14561
14636
  return await this.base.sendAndConfirm(tx);
14562
14637
  }
14563
14638
  async stakePoolDepositSol(glamState, stakePool, amount, txOptions = {}) {
@@ -15572,45 +15647,13 @@ class MintClient {
15572
15647
  }
15573
15648
  }
15574
15649
 
15575
- // Kamino prod and staging use the same Farms program
15576
- const KaminoFarmsProgramId = new PublicKey("FarmsPZpWu9i7Kky8tPN37rs2TpmMrAZrC7S7vJa91Hr");
15577
- const kLendProgramId = {
15578
- prod: new PublicKey("KLend2g3cP87fffoy8q1mQqGKjrxjC8boSyAYavgmjD"),
15579
- staging: new PublicKey("SLendK7ySfcEzyaFqy93gDnD3RtrpXJcnRwb6zFHJSh")
15580
- };
15581
- // Kamino has multiple lending markets, use the main market for tests
15582
- const lendingMarketMain = {
15583
- prod: new PublicKey("H6rHXmXoCQvq8Ue81MqNh7ow5ysPa1dSozwW3PU1dDH6"),
15584
- staging: new PublicKey("6WVSwDQXrBZeQVnu6hpnsRZhodaJTZBUaC334SiiBKdb")
15585
- };
15586
- const solReserve = {
15587
- prod: new PublicKey("6gTJfuPHEg6uRAijRkMqNc9kan4sVZejKMxmvx2grT1p"),
15588
- staging: new PublicKey("EaAuYkMrA9rmnU9eVvHi63yqZzKzmnVj3PWFnmW9RD4W")
15650
+ const LOOKUP_TABLE = new PublicKey("284iwGtA9X9aLy3KsyV8uT2pXLARhYbiSi5SiM2g47M2");
15651
+ const DEFAULT_OBLIGATION_ARGS = {
15652
+ tag: 0,
15653
+ id: 0
15589
15654
  };
15590
- const lendingMarketAuthority = {
15591
- prod: new PublicKey("Dx8iy2o46sK1DzWbEcznqSKeLbLVeu7otkibA3WohGAj"),
15592
- staging: new PublicKey("4zzBjUgjuNUrGqt8Xrig7SDLqBPgZo3v3R7YEuBQoiC4")
15593
- };
15594
- const reserveFarmState = {
15595
- prod: new PublicKey("BgMEUzcjkJxEH1PdPkZyv3NbUynwbkPiNJ7X2x7G1JmH"),
15596
- staging: new PublicKey("CtGYmztwXGrDtUrRCEydrwkwpJ7ptAY5BkfzThkVPPK9")
15597
- };
15598
- const reserveLiquiditySupply = {
15599
- prod: new PublicKey("ywaaLvG7t1vXJo8sT3UzE8yzzZtxLM7Fmev64Jbooye"),
15600
- staging: new PublicKey("GaTJgVfgUTTYyZYTQB36rXTQEbv1i1LUvfGSBDAr2An1")
15601
- };
15602
- const reserveCollateralMint = {
15603
- prod: new PublicKey("DxzDt5kPdFkMy9AANiZh4zuoitobqsn1G6bdoNyjePC2"),
15604
- staging: new PublicKey("966sqybMQJfwYgiEDQqiFsSK5o9tFPyBptZ3GFXbF7vR")
15605
- };
15606
- const reserveDestinationDepositCollateral = {
15607
- prod: new PublicKey("8qnXfbaLbY6Y4xiCP6SZ3RK8ccjVa8DhALzDGifBPeNx"),
15608
- staging: new PublicKey("DZpgVJq3WpwRpPXNwzvLwVMerJodqCiitxAeU5QgkJe3")
15609
- };
15610
- const scopePrices = new PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C");
15655
+ const SCOPE_PRICES = new PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C");
15611
15656
  function refreshObligation(accounts, programId) {
15612
- // First time deposit we don't need additional accounts
15613
- // FIXME: but we need to append Kamino reserve accounts if the obligation uses them
15614
15657
  const keys = [
15615
15658
  {
15616
15659
  pubkey: accounts.lendingMarket,
@@ -15623,6 +15666,13 @@ function refreshObligation(accounts, programId) {
15623
15666
  isWritable: true
15624
15667
  }
15625
15668
  ];
15669
+ accounts.reserves.forEach((reserve)=>{
15670
+ keys.push({
15671
+ pubkey: reserve,
15672
+ isSigner: false,
15673
+ isWritable: false
15674
+ });
15675
+ });
15626
15676
  const identifier = Buffer.from([
15627
15677
  33,
15628
15678
  132,
@@ -15774,22 +15824,78 @@ function refreshObligationFarmsForReserve(args, accounts, programId) {
15774
15824
  return ix;
15775
15825
  }
15776
15826
  class KaminoLendingClient {
15777
- async initialize(statePda, txOptions = {}) {
15778
- const tx = await this.initializeTx(statePda, txOptions);
15827
+ /**
15828
+ * Initializes Kamino user metadata
15829
+ *
15830
+ * @param statePda
15831
+ * @param market Lending market
15832
+ * @param referrer Referrer user metadata
15833
+ * @param txOptions
15834
+ * @returns
15835
+ */ async initUserMetadata(statePda, referrer, txOptions = {}) {
15836
+ const tx = await this.initUserMetadataTx(new PublicKey(statePda), referrer ? new PublicKey(referrer) : PublicKey.default, txOptions);
15837
+ return await this.base.sendAndConfirm(tx);
15838
+ }
15839
+ /**
15840
+ * Deposits asset to the lending market.
15841
+ *
15842
+ * @param statePda
15843
+ * @param market Lending market
15844
+ * @param asset Asset mint
15845
+ * @param amount Amount to deposit
15846
+ * @param txOptions
15847
+ * @returns
15848
+ */ async deposit(statePda, market, asset, amount, txOptions = {}) {
15849
+ const tx = await this.depositTx(new PublicKey(statePda), new PublicKey(market), new PublicKey(asset), new BN(amount), txOptions);
15779
15850
  return await this.base.sendAndConfirm(tx);
15780
15851
  }
15781
- async deposit(statePda, amount, txOptions = {}) {
15782
- const tx = await this.depositTx(statePda, WSOL, amount, txOptions);
15852
+ /**
15853
+ * Withdraws asset from the lending market.
15854
+ *
15855
+ * @param statePda
15856
+ * @param market Lending market
15857
+ * @param asset Asset mint
15858
+ * @param amount Amount to deposit
15859
+ * @param txOptions
15860
+ * @returns
15861
+ */ async withdraw(statePda, market, asset, amount, txOptions = {}) {
15862
+ const tx = await this.withdrawTx(new PublicKey(statePda), new PublicKey(market), new PublicKey(asset), new BN(amount), txOptions);
15863
+ return await this.base.sendAndConfirm(tx);
15864
+ }
15865
+ /**
15866
+ * Borrows asset from the lending market.
15867
+ *
15868
+ * @param statePda GLAM state
15869
+ * @param market Lending market
15870
+ * @param asset Asset mint
15871
+ * @param amount Amount to borrow
15872
+ * @param txOptions
15873
+ * @returns
15874
+ */ async borrow(statePda, market, asset, amount, txOptions = {}) {
15875
+ const tx = await this.borrowTx(new PublicKey(statePda), new PublicKey(market), new PublicKey(asset), new BN(amount), txOptions);
15876
+ return await this.base.sendAndConfirm(tx);
15877
+ }
15878
+ /**
15879
+ * Repays asset to the lending market.
15880
+ *
15881
+ * @param statePda
15882
+ * @param market
15883
+ * @param asset
15884
+ * @param amount
15885
+ * @param txOptions
15886
+ * @returns
15887
+ */ async repay(statePda, market, asset, amount, txOptions = {}) {
15888
+ const tx = await this.repayTx(new PublicKey(statePda), new PublicKey(market), new PublicKey(asset), new BN(amount), txOptions);
15783
15889
  return await this.base.sendAndConfirm(tx);
15784
15890
  }
15785
15891
  getUserMetadataPda(owner) {
15786
15892
  const [userMetadataPda] = PublicKey.findProgramAddressSync([
15787
15893
  Buffer.from("user_meta"),
15788
15894
  owner.toBuffer()
15789
- ], kLendProgramId.prod);
15895
+ ], KAMINO_LENDING_PROGRAM);
15790
15896
  return userMetadataPda;
15791
15897
  }
15792
- getObligationPda(owner, args) {
15898
+ getObligationPda(owner, market, args = DEFAULT_OBLIGATION_ARGS) {
15793
15899
  const seed = [
15794
15900
  Buffer.from([
15795
15901
  args.tag
@@ -15798,141 +15904,627 @@ class KaminoLendingClient {
15798
15904
  args.id
15799
15905
  ]),
15800
15906
  owner.toBuffer(),
15801
- lendingMarketMain.prod.toBuffer(),
15907
+ market.toBuffer(),
15802
15908
  PublicKey.default.toBuffer(),
15803
15909
  PublicKey.default.toBuffer()
15804
15910
  ];
15805
- const [obligation, _] = PublicKey.findProgramAddressSync(seed, kLendProgramId.prod);
15911
+ const [obligation, _] = PublicKey.findProgramAddressSync(seed, KAMINO_LENDING_PROGRAM);
15806
15912
  return obligation;
15807
15913
  }
15808
- getObligationFarm(obligation) {
15914
+ getObligationFarmState(obligation, farm) {
15809
15915
  const [obligationFarm] = PublicKey.findProgramAddressSync([
15810
15916
  Buffer.from("user"),
15811
- reserveFarmState.prod.toBuffer(),
15917
+ farm.toBuffer(),
15812
15918
  obligation.toBuffer()
15813
- ], KaminoFarmsProgramId);
15919
+ ], KAMINO_FARM_PROGRAM);
15814
15920
  return obligationFarm;
15815
15921
  }
15816
- async initializeTx(statePda, txOptions) {
15817
- const signer = txOptions.signer || this.base.getSigner();
15818
- const vault = await this.base.getVaultPda(statePda);
15922
+ async initUserMetadataTx(glamState, referrer, txOptions) {
15923
+ const glamSigner = txOptions.signer || this.base.getSigner();
15924
+ const vault = this.base.getVaultPda(glamState);
15819
15925
  const userMetadata = this.getUserMetadataPda(vault);
15820
- const args = {
15821
- tag: 0,
15822
- id: 0
15823
- };
15824
- const obligation = this.getObligationPda(vault, args);
15825
- const obligationFarm = this.getObligationFarm(obligation);
15926
+ const lookupTable = new PublicKey(0); // FIXME: create lookup table
15927
+ const referrerUserMetadata = referrer.equals(PublicKey.default) ? KAMINO_LENDING_PROGRAM : referrer;
15826
15928
  // @ts-ignore
15827
- const initObligationIx = await this.base.program.methods.kaminoLendingInitObligation(args).accounts({
15828
- glamState: statePda,
15829
- glamSigner: signer,
15830
- obligation,
15831
- lendingMarket: lendingMarketMain.prod,
15832
- seed1Account: new PublicKey(0),
15833
- seed2Account: new PublicKey(0),
15834
- ownerUserMetadata: userMetadata
15835
- }).instruction();
15836
- const initObligationFarmIx = await this.base.program.methods.kaminoLendingInitObligationFarmsForReserve(0).accounts({
15837
- glamState: statePda,
15838
- glamSigner: signer,
15839
- obligation,
15840
- lendingMarketAuthority: lendingMarketAuthority.prod,
15841
- reserve: solReserve.prod,
15842
- reserveFarmState: reserveFarmState.prod,
15843
- obligationFarm,
15844
- lendingMarket: lendingMarketMain.prod,
15845
- farmsProgram: KaminoFarmsProgramId
15846
- }).instruction();
15847
- const tx = await this.base.program.methods.kaminoLendingInitUserMetadata(new PublicKey(0)).accounts({
15848
- glamState: statePda,
15849
- glamSigner: signer,
15929
+ const tx = await this.base.program.methods.kaminoLendingInitUserMetadata(lookupTable).accounts({
15930
+ glamState,
15931
+ glamSigner,
15850
15932
  userMetadata,
15851
- referrerUserMetadata: kLendProgramId.prod
15852
- }).postInstructions([
15853
- initObligationIx,
15854
- initObligationFarmIx
15855
- ]).transaction();
15933
+ referrerUserMetadata
15934
+ }).transaction();
15856
15935
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
15857
15936
  return vTx;
15858
15937
  }
15859
- async depositTx(statePda, asset, amount, txOptions) {
15860
- if (!asset.equals(WSOL)) {
15861
- throw new Error("Only WSOL is supported");
15938
+ refreshReserveIxs(lendingMarket, reserves) {
15939
+ return reserves.map((reserve)=>refreshReserve({
15940
+ reserve,
15941
+ lendingMarket,
15942
+ pythOracle: KAMINO_LENDING_PROGRAM,
15943
+ switchboardPriceOracle: KAMINO_LENDING_PROGRAM,
15944
+ switchboardTwapOracle: KAMINO_LENDING_PROGRAM,
15945
+ scopePrices: SCOPE_PRICES
15946
+ }, KAMINO_LENDING_PROGRAM));
15947
+ }
15948
+ refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) {
15949
+ return parsedReserves.map((parsedReserve)=>{
15950
+ const { farmCollateral, farmDebt } = parsedReserve;
15951
+ return [
15952
+ farmCollateral,
15953
+ farmDebt
15954
+ ].filter((farm)=>!!farm).map((farm)=>{
15955
+ const obligationFarmUserState = this.getObligationFarmState(obligation, farm);
15956
+ return refreshObligationFarmsForReserve({
15957
+ mode: 0
15958
+ }, {
15959
+ crank: this.base.getSigner(),
15960
+ baseAccounts: {
15961
+ obligation,
15962
+ lendingMarketAuthority: this.getMarketAuthority(lendingMarket),
15963
+ reserve: parsedReserve.address,
15964
+ reserveFarmState: farm,
15965
+ obligationFarmUserState,
15966
+ lendingMarket
15967
+ },
15968
+ farmsProgram: KAMINO_FARM_PROGRAM,
15969
+ rent: SYSVAR_RENT_PUBKEY,
15970
+ systemProgram: SystemProgram.programId
15971
+ }, KAMINO_LENDING_PROGRAM);
15972
+ });
15973
+ }).flat();
15974
+ }
15975
+ /**
15976
+ * Returns an array of instructions for refreshing an existing obligation and reserves it depends on.
15977
+ */ async getRefreshIxs(obligation, lendingMarket) {
15978
+ // If obligation has deposits or borrows, we need the following refresh ixs:
15979
+ // - refreshReserve x N_reserves
15980
+ // - refreshObligation
15981
+ // - refreshObligationFarmsForReserve x M_farms
15982
+ const { deposits, borrows } = await this.fetchAndParseObligation(obligation);
15983
+ const reserves = deposits.concat(borrows).map((d)=>d.reserve);
15984
+ const parsedReserves = await this.fetchAndParseReserves(reserves);
15985
+ return [
15986
+ ...this.refreshReserveIxs(lendingMarket, reserves),
15987
+ refreshObligation({
15988
+ lendingMarket,
15989
+ obligation,
15990
+ reserves
15991
+ }, KAMINO_LENDING_PROGRAM),
15992
+ ...this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves)
15993
+ ];
15994
+ }
15995
+ getMarketAuthority(market) {
15996
+ const [authority, _] = PublicKey.findProgramAddressSync([
15997
+ Buffer.from("lma"),
15998
+ market.toBuffer()
15999
+ ], KAMINO_LENDING_PROGRAM);
16000
+ return authority;
16001
+ }
16002
+ reservePdas(market, mint) {
16003
+ const [liquiditySupplyVault] = PublicKey.findProgramAddressSync([
16004
+ Buffer.from("reserve_liq_supply"),
16005
+ market.toBuffer(),
16006
+ mint.toBuffer()
16007
+ ], KAMINO_LENDING_PROGRAM);
16008
+ const [collateralMint] = PublicKey.findProgramAddressSync([
16009
+ Buffer.from("reserve_coll_mint"),
16010
+ market.toBuffer(),
16011
+ mint.toBuffer()
16012
+ ], KAMINO_LENDING_PROGRAM);
16013
+ const [collateralSupplyVault] = PublicKey.findProgramAddressSync([
16014
+ Buffer.from("reserve_coll_supply"),
16015
+ market.toBuffer(),
16016
+ mint.toBuffer()
16017
+ ], KAMINO_LENDING_PROGRAM);
16018
+ const [feeVault] = PublicKey.findProgramAddressSync([
16019
+ Buffer.from("fee_receiver"),
16020
+ market.toBuffer(),
16021
+ mint.toBuffer()
16022
+ ], KAMINO_LENDING_PROGRAM);
16023
+ return {
16024
+ liquiditySupplyVault,
16025
+ collateralMint,
16026
+ collateralSupplyVault,
16027
+ feeVault
16028
+ };
16029
+ }
16030
+ /**
16031
+ * Fetches and parses obligation account
16032
+ *
16033
+ * @param obligation User obligation pubkey
16034
+ * @returns Pubkeys of reserves for deposits and borrows
16035
+ */ async fetchAndParseObligation(obligation) {
16036
+ const cached = this.obligations.get(obligation);
16037
+ if (cached) {
16038
+ return cached;
15862
16039
  }
15863
- const signer = txOptions.signer || this.base.getSigner();
15864
- const vault = this.base.getVaultPda(statePda);
15865
- const args = {
15866
- tag: 0,
15867
- id: 0
16040
+ const obligationAccount = await this.base.provider.connection.getAccountInfo(obligation);
16041
+ if (!obligationAccount) {
16042
+ return {
16043
+ deposits: [],
16044
+ borrows: []
16045
+ };
16046
+ }
16047
+ const data = obligationAccount.data;
16048
+ // read deposits
16049
+ let depositsOffset = 96;
16050
+ let depositSize = 136;
16051
+ let numDeposits = 8;
16052
+ const depositsData = data.subarray(depositsOffset, depositsOffset + numDeposits * depositSize);
16053
+ const deposits = Array.from({
16054
+ length: numDeposits
16055
+ }, (_, i)=>{
16056
+ const depositData = depositsData.subarray(i * depositSize, (i + 1) * depositSize);
16057
+ return {
16058
+ reserve: new PublicKey(depositData.subarray(0, 32))
16059
+ };
16060
+ }).filter((d)=>!d.reserve.equals(PublicKey.default));
16061
+ // read borrows
16062
+ let borrowsOffset = 1208;
16063
+ let borrowSize = 200;
16064
+ let numBorrows = 5;
16065
+ const borrowsData = data.subarray(borrowsOffset, borrowsOffset + numBorrows * borrowSize);
16066
+ const borrows = Array.from({
16067
+ length: numBorrows
16068
+ }, (_, i)=>{
16069
+ const borrowData = borrowsData.subarray(i * borrowSize, (i + 1) * borrowSize);
16070
+ return {
16071
+ reserve: new PublicKey(borrowData.subarray(0, 32))
16072
+ };
16073
+ }).filter((d)=>!d.reserve.equals(PublicKey.default));
16074
+ const parsedObligation = {
16075
+ deposits,
16076
+ borrows
15868
16077
  };
15869
- const obligation = this.getObligationPda(vault, args);
15870
- const obligationFarm = this.getObligationFarm(obligation);
15871
- const refreshIxs = [
15872
- refreshReserve({
15873
- reserve: solReserve.prod,
15874
- lendingMarket: lendingMarketMain.prod,
15875
- pythOracle: kLendProgramId.prod,
15876
- switchboardPriceOracle: kLendProgramId.prod,
15877
- switchboardTwapOracle: kLendProgramId.prod,
15878
- scopePrices
15879
- }, kLendProgramId.prod),
15880
- refreshObligation({
15881
- lendingMarket: lendingMarketMain.prod,
15882
- obligation
15883
- }, kLendProgramId.prod),
15884
- refreshObligationFarmsForReserve({
15885
- mode: 0
15886
- }, {
15887
- crank: this.base.getSigner(),
15888
- baseAccounts: {
16078
+ this.obligations.set(obligation, parsedObligation);
16079
+ return parsedObligation;
16080
+ }
16081
+ /**
16082
+ * We only need pubkeys that don't change over time. No need to fetch them every time.
16083
+ *
16084
+ * @param market
16085
+ * @param asset
16086
+ * @returns
16087
+ */ async fetchAndParseReserves(reserves) {
16088
+ if (this.pubkeyArraysEqual(reserves, Array.from(this.reserves.keys()))) {
16089
+ return Array.from(this.reserves.values());
16090
+ }
16091
+ const reserveAccounts = await this.base.provider.connection.getMultipleAccountsInfo(reserves);
16092
+ if (reserveAccounts.find((a)=>!a)) {
16093
+ throw new Error("Not all reserves can be found");
16094
+ }
16095
+ return reserveAccounts.filter((a)=>!!a).map((account, i)=>{
16096
+ const data = account.data;
16097
+ const market = new PublicKey(data.subarray(32, 64));
16098
+ const farmCollateral = new PublicKey(data.subarray(64, 96));
16099
+ const farmDebt = new PublicKey(data.subarray(96, 128));
16100
+ const liquidityMint = new PublicKey(data.subarray(128, 160));
16101
+ const parsed = {
16102
+ address: reserves[i],
16103
+ farmCollateral: farmCollateral.equals(PublicKey.default) ? undefined : farmCollateral,
16104
+ farmDebt: farmDebt.equals(PublicKey.default) ? undefined : farmDebt,
16105
+ liquidityMint,
16106
+ ...this.reservePdas(market, liquidityMint)
16107
+ };
16108
+ this.reserves.set(reserves[i], parsed);
16109
+ return parsed;
16110
+ });
16111
+ }
16112
+ async findAndParseReserve(market, asset) {
16113
+ const accounts = await this.base.provider.connection.getProgramAccounts(KAMINO_LENDING_PROGRAM, {
16114
+ filters: [
16115
+ {
16116
+ dataSize: 8624
16117
+ },
16118
+ {
16119
+ memcmp: {
16120
+ offset: 32,
16121
+ bytes: market.toBase58()
16122
+ }
16123
+ },
16124
+ {
16125
+ memcmp: {
16126
+ offset: 128,
16127
+ bytes: asset.toBase58()
16128
+ }
16129
+ }
16130
+ ]
16131
+ });
16132
+ if (accounts.length === 0) {
16133
+ throw new Error("Reserve not found");
16134
+ }
16135
+ const account = accounts[0];
16136
+ const data = account.account.data;
16137
+ const farmCollateral = new PublicKey(data.subarray(64, 96));
16138
+ const farmDebt = new PublicKey(data.subarray(96, 128));
16139
+ const parsed = {
16140
+ address: account.pubkey,
16141
+ farmCollateral: farmCollateral.equals(PublicKey.default) ? undefined : farmCollateral,
16142
+ farmDebt: farmDebt.equals(PublicKey.default) ? undefined : farmDebt,
16143
+ liquidityMint: asset,
16144
+ ...this.reservePdas(market, asset)
16145
+ };
16146
+ this.reserves.set(account.pubkey, parsed);
16147
+ return parsed;
16148
+ }
16149
+ async depositTx(glamState, market, asset, amount, txOptions) {
16150
+ const glamSigner = txOptions.signer || this.base.getSigner();
16151
+ const vault = this.base.getVaultPda(glamState);
16152
+ const userMetadata = this.getUserMetadataPda(vault);
16153
+ const preInstructions = [];
16154
+ const postInstructions = [];
16155
+ const depositReserve = await this.findAndParseReserve(market, asset);
16156
+ const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
16157
+ // If obligation doesn't exist, initialize & refresh obligation and collateral farm state first
16158
+ const obligationAccount = await this.base.provider.connection.getAccountInfo(obligation);
16159
+ if (!obligationAccount) {
16160
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitObligation(DEFAULT_OBLIGATION_ARGS).accounts({
16161
+ glamState,
16162
+ glamSigner,
16163
+ obligation,
16164
+ lendingMarket: market,
16165
+ seed1Account: new PublicKey(0),
16166
+ seed2Account: new PublicKey(0),
16167
+ ownerUserMetadata: userMetadata
16168
+ }).instruction());
16169
+ }
16170
+ // If reserve has collateral farm but obligation farm state doesn't exist, initialize it
16171
+ let obligationFarm = null;
16172
+ if (depositReserve.farmCollateral) {
16173
+ obligationFarm = this.getObligationFarmState(obligation, depositReserve.farmCollateral);
16174
+ const obligationFarmAccount = await this.base.provider.connection.getAccountInfo(obligationFarm);
16175
+ if (!obligationFarmAccount) {
16176
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitObligationFarmsForReserve(0) // TODO: What does mode do?
16177
+ .accounts({
16178
+ glamState,
16179
+ glamSigner,
15889
16180
  obligation,
15890
- lendingMarketAuthority: lendingMarketAuthority.prod,
15891
- reserve: solReserve.prod,
15892
- reserveFarmState: reserveFarmState.prod,
15893
- obligationFarmUserState: obligationFarm,
15894
- lendingMarket: lendingMarketMain.prod
15895
- },
15896
- farmsProgram: KaminoFarmsProgramId,
15897
- rent: SYSVAR_RENT_PUBKEY,
15898
- systemProgram: SystemProgram.programId
15899
- }, kLendProgramId.prod)
15900
- ];
15901
- const tx = await this.base.program.methods.kaminoLendingDepositReserveLiquidityAndObligationCollateralV2(new BN(amount)).accounts({
15902
- glamState: statePda,
15903
- glamSigner: signer,
16181
+ lendingMarketAuthority: this.getMarketAuthority(market),
16182
+ reserve: depositReserve.address,
16183
+ reserveFarmState: depositReserve.farmCollateral,
16184
+ obligationFarm,
16185
+ lendingMarket: market,
16186
+ farmsProgram: KAMINO_FARM_PROGRAM
16187
+ }).instruction());
16188
+ }
16189
+ }
16190
+ const reservesToRefresh = [];
16191
+ const { deposits, borrows } = await this.fetchAndParseObligation(obligation);
16192
+ const reservesInUse = deposits.concat(borrows).map((d)=>d.reserve);
16193
+ if (reservesInUse.find((r)=>r.equals(depositReserve.address))) {
16194
+ reservesToRefresh.push(...reservesInUse);
16195
+ } else {
16196
+ reservesToRefresh.push(depositReserve.address, ...reservesInUse);
16197
+ }
16198
+ // Refresh reserves, including deposit reserve and reserves in use
16199
+ preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
16200
+ // Refresh obligation with reserves in use
16201
+ preInstructions.push(refreshObligation({
16202
+ lendingMarket: market,
15904
16203
  obligation,
15905
- lendingMarket: lendingMarketMain.prod,
15906
- lendingMarketAuthority: lendingMarketAuthority.prod,
15907
- reserve: solReserve.prod,
16204
+ reserves: reservesInUse
16205
+ }, KAMINO_LENDING_PROGRAM));
16206
+ if (depositReserve.farmCollateral) {
16207
+ const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16208
+ depositReserve
16209
+ ]);
16210
+ preInstructions.push(...ixs);
16211
+ postInstructions.push(...ixs); // farms must be refreshed after deposit
16212
+ }
16213
+ // If deposit asset is WSOL, wrap SOL first in case vault doesn't have enough wSOL
16214
+ const userSourceLiquidity = this.base.getVaultAta(glamState, asset);
16215
+ if (asset.equals(WSOL)) {
16216
+ const wrapSolIxs = await this.base.maybeWrapSol(glamState, amount);
16217
+ preInstructions.unshift(...wrapSolIxs);
16218
+ // Close wSOL ata automatically after deposit
16219
+ if (wrapSolIxs.length > 0) {
16220
+ const closeIx = await this.base.program.methods.tokenCloseAccount().accounts({
16221
+ glamState,
16222
+ glamSigner,
16223
+ tokenAccount: userSourceLiquidity,
16224
+ cpiProgram: TOKEN_PROGRAM_ID
16225
+ }).instruction();
16226
+ postInstructions.push(closeIx);
16227
+ }
16228
+ }
16229
+ // @ts-ignore
16230
+ const tx = await this.base.program.methods.kaminoLendingDepositReserveLiquidityAndObligationCollateralV2(amount).accounts({
16231
+ glamState,
16232
+ glamSigner,
16233
+ obligation,
16234
+ lendingMarket: market,
16235
+ lendingMarketAuthority: this.getMarketAuthority(market),
16236
+ reserve: depositReserve.address,
15908
16237
  reserveLiquidityMint: asset,
15909
- reserveLiquiditySupply: reserveLiquiditySupply.prod,
15910
- reserveCollateralMint: reserveCollateralMint.prod,
15911
- reserveDestinationDepositCollateral: reserveDestinationDepositCollateral.prod,
15912
- userSourceLiquidity: this.base.getVaultAta(statePda, asset),
15913
- placeholderUserDestinationCollateral: kLendProgramId.prod,
16238
+ reserveLiquiditySupply: depositReserve.liquiditySupplyVault,
16239
+ reserveCollateralMint: depositReserve.collateralMint,
16240
+ reserveDestinationDepositCollateral: depositReserve.collateralSupplyVault,
16241
+ userSourceLiquidity,
16242
+ placeholderUserDestinationCollateral: KAMINO_LENDING_PROGRAM,
15914
16243
  collateralTokenProgram: TOKEN_PROGRAM_ID,
15915
16244
  liquidityTokenProgram: TOKEN_PROGRAM_ID,
15916
16245
  instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
15917
16246
  obligationFarmUserState: obligationFarm,
15918
- reserveFarmState: reserveFarmState.prod,
15919
- farmsProgram: KaminoFarmsProgramId
15920
- }).preInstructions(refreshIxs) // 3 refresh ixs
15921
- .postInstructions([
15922
- refreshIxs[2]
15923
- ]) // 1 refresh ix
15924
- .transaction();
15925
- const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16247
+ // @ts-ignore
16248
+ reserveFarmState: depositReserve.farmCollateral,
16249
+ farmsProgram: KAMINO_FARM_PROGRAM
16250
+ }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
16251
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
16252
+ LOOKUP_TABLE
16253
+ ]);
16254
+ const vTx = await this.base.intoVersionedTransaction(tx, {
16255
+ ...txOptions,
16256
+ lookupTables
16257
+ });
16258
+ return vTx;
16259
+ }
16260
+ async withdrawTx(glamState, market, asset, amount, txOptions) {
16261
+ const glamSigner = txOptions.signer || this.base.getSigner();
16262
+ const vault = this.base.getVaultPda(glamState);
16263
+ const preInstructions = [];
16264
+ const postInstructions = [];
16265
+ const withdrawReserve = await this.findAndParseReserve(market, asset);
16266
+ const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
16267
+ let obligationFarm = null;
16268
+ // If reserve has debt farm but obligation farm state doesn't exist, initialize it
16269
+ if (withdrawReserve.farmCollateral) {
16270
+ obligationFarm = this.getObligationFarmState(obligation, withdrawReserve.farmCollateral);
16271
+ const obligationFarmAccount = await this.base.provider.connection.getAccountInfo(obligationFarm);
16272
+ if (!obligationFarmAccount) {
16273
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitObligationFarmsForReserve(0) // TODO: What does mode do?
16274
+ .accounts({
16275
+ glamState,
16276
+ glamSigner,
16277
+ obligation,
16278
+ lendingMarketAuthority: this.getMarketAuthority(market),
16279
+ reserve: withdrawReserve.address,
16280
+ reserveFarmState: withdrawReserve.farmCollateral,
16281
+ obligationFarm,
16282
+ lendingMarket: market,
16283
+ farmsProgram: KAMINO_FARM_PROGRAM
16284
+ }).instruction());
16285
+ }
16286
+ }
16287
+ const reservesToRefresh = [];
16288
+ const { deposits, borrows } = await this.fetchAndParseObligation(obligation);
16289
+ const reservesInUse = deposits.concat(borrows).map((d)=>d.reserve);
16290
+ if (reservesInUse.find((r)=>r.equals(withdrawReserve.address))) {
16291
+ reservesToRefresh.push(...reservesInUse);
16292
+ } else {
16293
+ reservesToRefresh.push(withdrawReserve.address, ...reservesInUse);
16294
+ }
16295
+ // Refresh reserves, including deposit reserve and reserves in use
16296
+ preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
16297
+ // Refresh obligation with reserves in use
16298
+ preInstructions.push(refreshObligation({
16299
+ lendingMarket: market,
16300
+ obligation,
16301
+ reserves: reservesInUse
16302
+ }, KAMINO_LENDING_PROGRAM));
16303
+ if (withdrawReserve.farmCollateral) {
16304
+ const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16305
+ withdrawReserve
16306
+ ]);
16307
+ preInstructions.push(...ixs);
16308
+ postInstructions.push(...ixs); // farms must be refreshed after withdraw
16309
+ }
16310
+ // Create asset ATA in case it doesn't exist. Add it to the beginning of preInstructions
16311
+ const userDestinationLiquidity = this.base.getVaultAta(glamState, asset);
16312
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(glamSigner, userDestinationLiquidity, vault, asset);
16313
+ preInstructions.unshift(createAtaIx);
16314
+ const withdrawIx = await this.base.program.methods.kaminoLendingWithdrawObligationCollateralAndRedeemReserveCollateralV2(amount).accounts({
16315
+ glamState,
16316
+ glamSigner,
16317
+ obligation,
16318
+ lendingMarket: market,
16319
+ lendingMarketAuthority: this.getMarketAuthority(market),
16320
+ withdrawReserve: withdrawReserve.address,
16321
+ reserveLiquidityMint: asset,
16322
+ reserveSourceCollateral: withdrawReserve.collateralSupplyVault,
16323
+ reserveCollateralMint: withdrawReserve.collateralMint,
16324
+ reserveLiquiditySupply: withdrawReserve.liquiditySupplyVault,
16325
+ userDestinationLiquidity: this.base.getVaultAta(glamState, asset),
16326
+ placeholderUserDestinationCollateral: null,
16327
+ collateralTokenProgram: TOKEN_PROGRAM_ID,
16328
+ liquidityTokenProgram: TOKEN_PROGRAM_ID,
16329
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16330
+ obligationFarmUserState: obligationFarm,
16331
+ // @ts-ignore
16332
+ reserveFarmState: withdrawReserve.farmCollateral,
16333
+ farmsProgram: KAMINO_FARM_PROGRAM
16334
+ }).instruction();
16335
+ // The final instructions in the tx:
16336
+ // - refreshReserve * N
16337
+ // - refreshObligation
16338
+ // - refreshObligationFarmsForReserve (if farm exists)
16339
+ // - withdrawIx
16340
+ // - refreshObligationFarmsForReserve (if farm exists)
16341
+ const tx = new Transaction();
16342
+ tx.add(...preInstructions, withdrawIx, ...postInstructions);
16343
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
16344
+ LOOKUP_TABLE
16345
+ ]);
16346
+ const vTx = await this.base.intoVersionedTransaction(tx, {
16347
+ ...txOptions,
16348
+ lookupTables
16349
+ });
16350
+ return vTx;
16351
+ }
16352
+ async borrowTx(glamState, market, asset, amount, txOptions) {
16353
+ const glamSigner = txOptions.signer || this.base.getSigner();
16354
+ const vault = this.base.getVaultPda(glamState);
16355
+ const preInstructions = [];
16356
+ const borrowReserve = await this.findAndParseReserve(market, asset);
16357
+ const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
16358
+ let obligationFarm = null;
16359
+ // If reserve has debt farm but obligation farm state doesn't exist, initialize it
16360
+ if (borrowReserve.farmDebt) {
16361
+ obligationFarm = this.getObligationFarmState(obligation, borrowReserve.farmDebt);
16362
+ const obligationFarmAccount = await this.base.provider.connection.getAccountInfo(obligationFarm);
16363
+ if (!obligationFarmAccount) {
16364
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitObligationFarmsForReserve(0) // TODO: What does mode do?
16365
+ .accounts({
16366
+ glamState,
16367
+ glamSigner,
16368
+ obligation,
16369
+ lendingMarketAuthority: this.getMarketAuthority(market),
16370
+ reserve: borrowReserve.address,
16371
+ reserveFarmState: borrowReserve.farmDebt,
16372
+ obligationFarm,
16373
+ lendingMarket: market,
16374
+ farmsProgram: KAMINO_FARM_PROGRAM
16375
+ }).instruction());
16376
+ }
16377
+ }
16378
+ const reservesToRefresh = [];
16379
+ const { deposits, borrows } = await this.fetchAndParseObligation(obligation);
16380
+ const reservesInUse = deposits.concat(borrows).map((d)=>d.reserve);
16381
+ if (reservesInUse.find((r)=>r.equals(borrowReserve.address))) {
16382
+ reservesToRefresh.push(...reservesInUse);
16383
+ } else {
16384
+ reservesToRefresh.push(borrowReserve.address, ...reservesInUse);
16385
+ }
16386
+ // Refresh reserves, including deposit reserve and reserves in use
16387
+ preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
16388
+ // Refresh obligation with reserves in use
16389
+ preInstructions.push(refreshObligation({
16390
+ lendingMarket: market,
16391
+ obligation,
16392
+ reserves: reservesInUse
16393
+ }, KAMINO_LENDING_PROGRAM));
16394
+ // Don't need to refresh debt farm for borrow
16395
+ /*
16396
+ if (borrowReserve.farmDebt) {
16397
+ const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16398
+ borrowReserve,
16399
+ ]);
16400
+ preInstructions.push(...ixs);
16401
+ postInstructions.push(...ixs); // farms must be refreshed after deposit
16402
+ }
16403
+ */ // Create asset ATA in case it doesn't exist. Add it to the beginning of preInstructions
16404
+ const userDestinationLiquidity = this.base.getVaultAta(glamState, asset);
16405
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(glamSigner, userDestinationLiquidity, vault, asset);
16406
+ preInstructions.unshift(createAtaIx);
16407
+ const borrowIx = await this.base.program.methods.kaminoLendingBorrowObligationLiquidityV2(amount).accounts({
16408
+ glamState,
16409
+ glamSigner,
16410
+ obligation,
16411
+ lendingMarket: market,
16412
+ lendingMarketAuthority: this.getMarketAuthority(market),
16413
+ borrowReserve: borrowReserve.address,
16414
+ borrowReserveLiquidityMint: asset,
16415
+ reserveSourceLiquidity: borrowReserve.liquiditySupplyVault,
16416
+ borrowReserveLiquidityFeeReceiver: borrowReserve.feeVault,
16417
+ userDestinationLiquidity: this.base.getVaultAta(glamState, asset),
16418
+ referrerTokenState: null,
16419
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16420
+ tokenProgram: TOKEN_PROGRAM_ID,
16421
+ obligationFarmUserState: obligationFarm,
16422
+ // @ts-ignore
16423
+ reserveFarmState: borrowReserve.farmDebt,
16424
+ farmsProgram: KAMINO_FARM_PROGRAM
16425
+ }).instruction();
16426
+ // The final instructions in the tx:
16427
+ // - refreshReserve * N
16428
+ // - refreshObligation
16429
+ // - borrowObligationLiquidityV2
16430
+ const tx = new Transaction();
16431
+ tx.add(...preInstructions, borrowIx);
16432
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
16433
+ LOOKUP_TABLE
16434
+ ]);
16435
+ const vTx = await this.base.intoVersionedTransaction(tx, {
16436
+ ...txOptions,
16437
+ lookupTables
16438
+ });
16439
+ return vTx;
16440
+ }
16441
+ async repayTx(glamState, market, asset, amount, txOptions = {}) {
16442
+ const glamSigner = txOptions.signer || this.base.getSigner();
16443
+ const vault = this.base.getVaultPda(glamState);
16444
+ const preInstructions = [];
16445
+ const repayReserve = await this.findAndParseReserve(market, asset);
16446
+ const obligation = this.getObligationPda(vault, market, DEFAULT_OBLIGATION_ARGS);
16447
+ let obligationFarm = null;
16448
+ // If reserve has debt farm but obligation farm state doesn't exist, initialize it
16449
+ if (repayReserve.farmDebt) {
16450
+ obligationFarm = this.getObligationFarmState(obligation, repayReserve.farmDebt);
16451
+ const obligationFarmAccount = await this.base.provider.connection.getAccountInfo(obligationFarm);
16452
+ if (!obligationFarmAccount) {
16453
+ preInstructions.push(await this.base.program.methods.kaminoLendingInitObligationFarmsForReserve(0) // TODO: What does mode do?
16454
+ .accounts({
16455
+ glamState,
16456
+ glamSigner,
16457
+ obligation,
16458
+ lendingMarketAuthority: this.getMarketAuthority(market),
16459
+ reserve: repayReserve.address,
16460
+ reserveFarmState: repayReserve.farmDebt,
16461
+ obligationFarm,
16462
+ lendingMarket: market,
16463
+ farmsProgram: KAMINO_FARM_PROGRAM
16464
+ }).instruction());
16465
+ }
16466
+ }
16467
+ const reservesToRefresh = [];
16468
+ const { deposits, borrows } = await this.fetchAndParseObligation(obligation);
16469
+ const reservesInUse = deposits.concat(borrows).map((d)=>d.reserve);
16470
+ if (reservesInUse.find((r)=>r.equals(repayReserve.address))) {
16471
+ reservesToRefresh.push(...reservesInUse);
16472
+ } else {
16473
+ reservesToRefresh.push(repayReserve.address, ...reservesInUse);
16474
+ }
16475
+ // Refresh reserves, including deposit reserve and reserves in use
16476
+ preInstructions.push(...this.refreshReserveIxs(market, reservesToRefresh));
16477
+ // Refresh obligation with reserves in use
16478
+ preInstructions.push(refreshObligation({
16479
+ lendingMarket: market,
16480
+ obligation,
16481
+ reserves: reservesInUse
16482
+ }, KAMINO_LENDING_PROGRAM));
16483
+ const repayIx = await this.base.program.methods.kaminoLendingRepayObligationLiquidityV2(amount).accounts({
16484
+ glamState,
16485
+ glamSigner,
16486
+ obligation,
16487
+ lendingMarket: market,
16488
+ lendingMarketAuthority: this.getMarketAuthority(market),
16489
+ repayReserve: repayReserve.address,
16490
+ reserveLiquidityMint: asset,
16491
+ reserveDestinationLiquidity: repayReserve.liquiditySupplyVault,
16492
+ userSourceLiquidity: this.base.getVaultAta(glamState, asset),
16493
+ instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16494
+ tokenProgram: TOKEN_PROGRAM_ID,
16495
+ obligationFarmUserState: obligationFarm,
16496
+ // @ts-ignore
16497
+ reserveFarmState: repayReserve.farmDebt,
16498
+ farmsProgram: KAMINO_FARM_PROGRAM
16499
+ }).instruction();
16500
+ // The final instructions in the tx:
16501
+ // - refreshReserve * N
16502
+ // - refreshObligation
16503
+ // - repayObligationLiquidityV2
16504
+ const tx = new Transaction();
16505
+ tx.add(...preInstructions, repayIx);
16506
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
16507
+ LOOKUP_TABLE
16508
+ ]);
16509
+ const vTx = await this.base.intoVersionedTransaction(tx, {
16510
+ ...txOptions,
16511
+ lookupTables
16512
+ });
15926
16513
  return vTx;
15927
16514
  }
15928
16515
  constructor(base){
15929
16516
  this.base = base;
16517
+ this.reserves = new Map();
16518
+ this.obligations = new Map();
16519
+ this.pubkeyArraysEqual = (a, b)=>{
16520
+ if (a.length !== b.length) return false;
16521
+ a.sort();
16522
+ b.sort();
16523
+ return a.every((p, i)=>p.equals(b[i]));
16524
+ };
15930
16525
  }
15931
16526
  }
15932
16527
 
15933
- const METEORA_DLMM = new PublicKey("LBUZKhRxPF3XUpBCjp4YzTKgLccjZhTSDM9YuVaPwxo");
15934
- const MEMO_PROGRAM_ID = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
15935
- new PublicKey("5rCf1DM8LjKTw4YqhnoLcngyZYeNnQqztScTogYHAS6");
15936
16528
  // Pubkey::find_program_address(&[b"__event_authority"], &dlmm_interface::ID)
15937
16529
  const EVENT_AUTHORITY = new PublicKey("D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6");
15938
16530
  const DEFAULT_RANGE_INTERVAL = 34; // 34 bins on each side of the active bin, 69 bins in total
@@ -15961,7 +16553,7 @@ class MeteoraDlmmClient {
15961
16553
  lbPair: new PublicKey(pool),
15962
16554
  position: position.publicKey,
15963
16555
  eventAuthority: EVENT_AUTHORITY,
15964
- program: METEORA_DLMM
16556
+ program: METEORA_DLMM_PROGRAM
15965
16557
  }).transaction();
15966
16558
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
15967
16559
  return await this.base.sendAndConfirm(vTx, [
@@ -15982,14 +16574,14 @@ class MeteoraDlmmClient {
15982
16574
  lbPair: new PublicKey(pool),
15983
16575
  position,
15984
16576
  eventAuthority: EVENT_AUTHORITY,
15985
- program: METEORA_DLMM
16577
+ program: METEORA_DLMM_PROGRAM
15986
16578
  }).transaction();
15987
16579
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
15988
16580
  return await this.base.sendAndConfirm(vTx);
15989
16581
  }
15990
16582
  async addLiquidityByStrategy(statePda, position, amountX, amountY, strategyType, txOptions = {}) {
15991
16583
  const glamSigner = txOptions.signer || this.base.getSigner();
15992
- const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await this.parsePosition(new PublicKey(position));
16584
+ const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new PublicKey(position));
15993
16585
  const dlmmPool = await this.getDlmmPool(lbPair);
15994
16586
  const activeBinId = (await dlmmPool.getActiveBin()).binId;
15995
16587
  const glamState = new PublicKey(statePda);
@@ -16027,7 +16619,7 @@ class MeteoraDlmmClient {
16027
16619
  glamState,
16028
16620
  position: new PublicKey(position),
16029
16621
  lbPair,
16030
- binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM,
16622
+ binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM_PROGRAM,
16031
16623
  userTokenX: vaultTokenXAta,
16032
16624
  userTokenY: vaultTokenYAta,
16033
16625
  reserveX: dlmmPool.tokenX.reserve,
@@ -16037,13 +16629,13 @@ class MeteoraDlmmClient {
16037
16629
  tokenXProgram: TOKEN_PROGRAM_ID,
16038
16630
  tokenYProgram: TOKEN_PROGRAM_ID,
16039
16631
  eventAuthority: EVENT_AUTHORITY,
16040
- program: METEORA_DLMM
16632
+ program: METEORA_DLMM_PROGRAM
16041
16633
  }).preInstructions(preInstructions).remainingAccounts(remainingAccounts).transaction();
16042
16634
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16043
16635
  return this.base.sendAndConfirm(vTx);
16044
16636
  }
16045
16637
  async removeLiquidityByRange(statePda, position, bpsToRemove, txOptions = {}) {
16046
- const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await this.parsePosition(new PublicKey(position));
16638
+ const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new PublicKey(position));
16047
16639
  const dlmmPool = await this.getDlmmPool(lbPair);
16048
16640
  const glamState = new PublicKey(statePda);
16049
16641
  const vaultTokenXAta = this.base.getVaultAta(glamState, dlmmPool.tokenX.publicKey);
@@ -16056,13 +16648,14 @@ class MeteoraDlmmClient {
16056
16648
  isSigner: false,
16057
16649
  isWritable: true
16058
16650
  }));
16651
+ // @ts-ignore
16059
16652
  const tx = await this.base.program.methods.meteoraDlmmRemoveLiquidityByRange2(lowerBinId, upperBinId, bpsToRemove, {
16060
16653
  slices: []
16061
16654
  }).accounts({
16062
16655
  glamState,
16063
16656
  position: new PublicKey(position),
16064
16657
  lbPair,
16065
- binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM,
16658
+ binArrayBitmapExtension: dlmmPool.binArrayBitmapExtension ? dlmmPool.binArrayBitmapExtension.publicKey : METEORA_DLMM_PROGRAM,
16066
16659
  userTokenX: vaultTokenXAta,
16067
16660
  userTokenY: vaultTokenYAta,
16068
16661
  reserveX: dlmmPool.tokenX.reserve,
@@ -16072,14 +16665,14 @@ class MeteoraDlmmClient {
16072
16665
  tokenXProgram: TOKEN_PROGRAM_ID,
16073
16666
  tokenYProgram: TOKEN_PROGRAM_ID,
16074
16667
  eventAuthority: EVENT_AUTHORITY,
16075
- memoProgram: MEMO_PROGRAM_ID,
16076
- program: METEORA_DLMM
16668
+ memoProgram: MEMO_PROGRAM,
16669
+ program: METEORA_DLMM_PROGRAM
16077
16670
  }).remainingAccounts(remainingAccounts).transaction();
16078
16671
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16079
16672
  return this.base.sendAndConfirm(vTx);
16080
16673
  }
16081
16674
  async claimFee(statePda, position, txOptions = {}) {
16082
- const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await this.parsePosition(new PublicKey(position));
16675
+ const { lbPair, lowerBinId, upperBinId, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new PublicKey(position));
16083
16676
  const dlmmPool = await this.getDlmmPool(lbPair);
16084
16677
  const glamState = new PublicKey(statePda);
16085
16678
  const vaultTokenXAta = this.base.getVaultAta(glamState, dlmmPool.tokenX.publicKey);
@@ -16092,6 +16685,7 @@ class MeteoraDlmmClient {
16092
16685
  isSigner: false,
16093
16686
  isWritable: true
16094
16687
  }));
16688
+ // @ts-ignore
16095
16689
  const tx = await this.base.program.methods.meteoraDlmmClaimFee2(lowerBinId, upperBinId, {
16096
16690
  slices: []
16097
16691
  }).accounts({
@@ -16106,17 +16700,18 @@ class MeteoraDlmmClient {
16106
16700
  tokenYMint: dlmmPool.tokenY.publicKey,
16107
16701
  tokenProgramX: TOKEN_PROGRAM_ID,
16108
16702
  tokenProgramY: TOKEN_PROGRAM_ID,
16109
- memoProgram: MEMO_PROGRAM_ID,
16703
+ memoProgram: MEMO_PROGRAM,
16110
16704
  eventAuthority: EVENT_AUTHORITY,
16111
- program: METEORA_DLMM
16705
+ program: METEORA_DLMM_PROGRAM
16112
16706
  }).remainingAccounts(remainingAccounts).transaction();
16113
16707
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16114
16708
  return await this.base.sendAndConfirm(vTx);
16115
16709
  }
16116
16710
  async closePosition(statePda, position, txOptions = {}) {
16117
- const { lbPair, binArrayLower, binArrayUpper } = await this.parsePosition(new PublicKey(position));
16711
+ const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, new PublicKey(position));
16118
16712
  const glamState = new PublicKey(statePda);
16119
16713
  console.log(`close position: ${position}, binArrayLower: ${binArrayLower}, binArrayUpper: ${binArrayUpper}`);
16714
+ // @ts-ignore
16120
16715
  const tx = await this.base.program.methods.meteoraDlmmClosePosition().accounts({
16121
16716
  glamState,
16122
16717
  position: new PublicKey(position),
@@ -16125,7 +16720,7 @@ class MeteoraDlmmClient {
16125
16720
  binArrayUpper,
16126
16721
  rentReceiver: this.base.getSigner(),
16127
16722
  eventAuthority: EVENT_AUTHORITY,
16128
- program: METEORA_DLMM
16723
+ program: METEORA_DLMM_PROGRAM
16129
16724
  }).transaction();
16130
16725
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
16131
16726
  return await this.base.sendAndConfirm(vTx);
@@ -16143,46 +16738,9 @@ class MeteoraDlmmClient {
16143
16738
  base.toBuffer(),
16144
16739
  lowerBinIdBuffer,
16145
16740
  widthBuffer
16146
- ], METEORA_DLMM);
16741
+ ], METEORA_DLMM_PROGRAM);
16147
16742
  return pda;
16148
16743
  }
16149
- async fetchPositions(owner) {
16150
- const accounts = await this.base.provider.connection.getParsedProgramAccounts(METEORA_DLMM, {
16151
- filters: [
16152
- {
16153
- dataSize: 8120
16154
- },
16155
- {
16156
- memcmp: {
16157
- offset: 40,
16158
- bytes: owner.toBase58()
16159
- }
16160
- }
16161
- ]
16162
- });
16163
- return accounts.map((a)=>a.pubkey);
16164
- }
16165
- async parsePosition(position) {
16166
- const positionAccountInfo = await this.base.provider.connection.getAccountInfo(position);
16167
- if (!positionAccountInfo) {
16168
- throw new Error("Position not found");
16169
- }
16170
- const positionData = positionAccountInfo.data;
16171
- const lbPair = new PublicKey(positionData.subarray(8, 40));
16172
- const lowerBinId = positionData.subarray(7912, 7916).readInt32LE();
16173
- const upperBinId = positionData.subarray(7916, 7920).readInt32LE();
16174
- const lowerBinArrayIndex = binIdToBinArrayIndex(new BN(lowerBinId));
16175
- const [binArrayLower] = deriveBinArray(lbPair, lowerBinArrayIndex, METEORA_DLMM);
16176
- const upperBinArrayIndex = BN.max(lowerBinArrayIndex.add(new BN(1)), binIdToBinArrayIndex(new BN(upperBinId)));
16177
- const [binArrayUpper] = deriveBinArray(lbPair, upperBinArrayIndex, METEORA_DLMM);
16178
- return {
16179
- lowerBinId,
16180
- upperBinId,
16181
- binArrayLower,
16182
- binArrayUpper,
16183
- lbPair
16184
- };
16185
- }
16186
16744
  async autoFillY(dlmmPool, amountX) {
16187
16745
  const activeBin = await dlmmPool.getActiveBin();
16188
16746
  const activeBinPricePerToken = dlmmPool.fromPricePerLamport(Number(activeBin.price));
@@ -16427,7 +16985,8 @@ class InvestorClient {
16427
16985
  class PriceClient {
16428
16986
  /**
16429
16987
  * !! This is a convenience method that calculates the AUM of the vault based on priced assets.
16430
- * !! It doesn't reflect the actual AUM of the vault. If the vault has not been priced or pricing data is outdated, the number is NOT meaningful.
16988
+ * !! It doesn't reflect the actual AUM of the vault.
16989
+ * !! If the vault has not been priced or pricing data is outdated, the number is NOT meaningful.
16431
16990
  */ async getAum(glamState) {
16432
16991
  // @ts-ignore
16433
16992
  const glamStateAccount = await this.base.fetchStateAccount(glamState);
@@ -16441,41 +17000,85 @@ class PriceClient {
16441
17000
  });
16442
17001
  return pricedAssets.reduce((sum, p)=>new BN(p.amount).add(sum), new BN(0));
16443
17002
  }
16444
- async priceVaultIxs(glamState) {
17003
+ async priceVaultIxs(glamState, priceDenom) {
16445
17004
  const vault = this.base.getVaultPda(glamState);
16446
17005
  const tickets = await fetchMarinadeTicketAccounts(this.base.provider.connection, vault);
16447
- const priceTicketsIx = await this.base.program.methods.priceTickets().accounts({
16448
- glamState
17006
+ // @ts-ignore
17007
+ const priceTicketsIx = await this.base.program.methods.priceTickets(priceDenom).accounts({
17008
+ glamState,
17009
+ solOracle: SOL_ORACLE
16449
17010
  }).remainingAccounts(tickets.map((t)=>({
16450
17011
  pubkey: t.pubkey,
16451
17012
  isSigner: false,
16452
17013
  isWritable: false
16453
17014
  }))).instruction();
16454
17015
  const stakes = await fetchStakeAccounts(this.base.provider.connection, vault);
16455
- const priceStakesIx = await this.base.program.methods.priceStakes().accounts({
16456
- glamState
17016
+ const priceStakesIx = await this.base.program.methods.priceStakes(priceDenom).accounts({
17017
+ glamState,
17018
+ solOracle: SOL_ORACLE
16457
17019
  }).remainingAccounts(stakes.map((s)=>({
16458
17020
  pubkey: s,
16459
17021
  isSigner: false,
16460
17022
  isWritable: false
16461
17023
  }))).instruction();
16462
- const priceVaultIx = await this.base.program.methods.priceVault().accounts({
16463
- glamState
16464
- }).remainingAccounts(await this.remainingAccountsForPricing(glamState)).instruction();
17024
+ const priceVaultIx = await this.base.program.methods.priceVault(priceDenom).accounts({
17025
+ glamState,
17026
+ solOracle: SOL_ORACLE
17027
+ }).remainingAccounts(await this.remainingAccountsForPricingVaultAssets(glamState)).instruction();
17028
+ const priceMeteoraIx = await this.base.program.methods.priceMeteoraPositions(priceDenom).accounts({
17029
+ glamState,
17030
+ solOracle: SOL_ORACLE
17031
+ }).remainingAccounts(await this.remainingAccountsForPricingMeteora(glamState)).instruction();
17032
+ const priceKaminoIx = await this.base.program.methods.priceKaminoObligations(priceDenom).accounts({
17033
+ glamState,
17034
+ solOracle: SOL_ORACLE
17035
+ }).remainingAccounts(await this.remainingAccountsForPricingKamino(glamState)).instruction();
16465
17036
  return [
16466
17037
  priceTicketsIx,
16467
17038
  priceStakesIx,
16468
- priceVaultIx
17039
+ priceVaultIx,
17040
+ priceMeteoraIx,
17041
+ priceKaminoIx
16469
17042
  ];
16470
17043
  }
16471
17044
  constructor(base){
16472
17045
  this.base = base;
16473
- this.remainingAccountsForPricing = async (glamState)=>{
17046
+ this.remainingAccountsForPricingKamino = async (glamState)=>{
17047
+ const glamVault = this.base.getVaultPda(glamState);
17048
+ const obligationAccounts = await fetchKaminoObligations(this.base.provider.connection, glamVault);
17049
+ return obligationAccounts.map((a)=>({
17050
+ pubkey: a,
17051
+ isSigner: false,
17052
+ isWritable: false
17053
+ }));
17054
+ };
17055
+ this.remainingAccountsForPricingMeteora = async (glamState)=>{
17056
+ const glamVault = this.base.getVaultPda(glamState);
17057
+ const positions = await fetchMeteoraPositions(this.base.provider.connection, glamVault);
17058
+ let chunks = await Promise.all(positions.map(async (pubkey)=>{
17059
+ const { lbPair, binArrayLower, binArrayUpper } = await parseMeteoraPosition(this.base.provider.connection, pubkey);
17060
+ return [
17061
+ pubkey,
17062
+ lbPair,
17063
+ binArrayLower,
17064
+ binArrayUpper,
17065
+ new PublicKey("3m6i4RFWEDw2Ft4tFHPJtYgmpPe21k56M3FHeWYrgGBz"),
17066
+ new PublicKey("9VCioxmni2gDLv11qufWzT3RDERhQE4iY5Gf7NTfYyAV")
17067
+ ].map((k)=>({
17068
+ pubkey: k,
17069
+ isSigner: false,
17070
+ isWritable: false
17071
+ }));
17072
+ }));
17073
+ return chunks.flat();
17074
+ };
17075
+ this.remainingAccountsForPricingVaultAssets = async (glamState)=>{
16474
17076
  const glamStateAccount = await this.base.fetchStateAccount(glamState);
16475
17077
  return glamStateAccount.assets.map((asset)=>[
16476
17078
  this.base.getVaultAta(glamState, asset),
16477
17079
  asset,
16478
- ASSETS_MAINNET.get(asset.toBase58())?.stateAccount || new PublicKey(0)
17080
+ // FIXME: check oracle vs LST state?
17081
+ ASSETS_MAINNET.get(asset.toBase58())?.oracle || new PublicKey(0)
16479
17082
  ]).flat().map((a)=>({
16480
17083
  pubkey: a,
16481
17084
  isSigner: false,
@@ -16603,4 +17206,4 @@ const getPriorityFeeEstimate = async (heliusApiKey, tx, accountKeys, priorityLev
16603
17206
  return data.result.priorityFeeEstimate;
16604
17207
  };
16605
17208
 
16606
- export { BaseClient, ClusterNetwork, CompanyModel, CreatedModel, DRIFT_PROGRAM_ID, DelegateAcl, DriftClient, FundOpenfundsModel, GOVERNANCE_PROGRAM_ID, GlamClient, GlamError, GlamIdl, GlamIntegrations, GlamPermissions, GlamProtocolIdlJson, JITOSOL, JITO_STAKE_POOL, JITO_TIP_DEFAULT, JUP, JUPITER_API_DEFAULT, JUPITER_PROGRAM_ID, JUPSOL_STAKE_POOL, JUP_VOTE_PROGRAM, JupiterSwapClient, JupiterVoteClient, MARINADE_PROGRAM_ID, MARINADE_TICKET_SIZE, MERKLE_DISTRIBUTOR_PROGRAM, MSOL, ManagerModel, Metadata, MintIdlModel, MintModel, MintOpenfundsModel, SANCTUM_STAKE_POOL_PROGRAM_ID, SEED_ESCROW, SEED_METADATA, SEED_MINT, SEED_STATE, SEED_VAULT, STAKE_ACCOUNT_SIZE, StateIdlModel, StateModel, TRANSFER_HOOK_PROGRAM, USDC, WBTC, WETH, WSOL, fetchMarinadeTicketAccounts, fetchStakeAccounts, getGlamProgram, getGlamProgramId, getPriorityFeeEstimate, getSimulationComputeUnits, isBrowser };
17209
+ export { ASSETS_MAINNET, ASSETS_TESTS, BaseClient, ClusterNetwork, CompanyModel, CreatedModel, DRIFT_PROGRAM_ID, DelegateAcl, DriftClient, FundOpenfundsModel, GOVERNANCE_PROGRAM_ID, GlamClient, GlamError, GlamIdl, GlamIntegrations, GlamPermissions, GlamProtocolIdlJson, JITOSOL, JITO_STAKE_POOL, JITO_TIP_DEFAULT, JUP, JUPITER_API_DEFAULT, JUPITER_PROGRAM_ID, JUPSOL_STAKE_POOL, JUP_VOTE_PROGRAM, JupiterSwapClient, JupiterVoteClient, KAMINO_FARM_PROGRAM, KAMINO_LENDING_PROGRAM, KAMINO_OBTRIGATION_SIZE, MARINADE_PROGRAM_ID, MARINADE_TICKET_SIZE, MEMO_PROGRAM, MERKLE_DISTRIBUTOR_PROGRAM, METEORA_DLMM_PROGRAM, METEORA_POSITION_SIZE, MSOL, ManagerModel, Metadata, MintIdlModel, MintModel, MintOpenfundsModel, PriceDenom, SANCTUM_STAKE_POOL_PROGRAM_ID, SEED_ESCROW, SEED_METADATA, SEED_MINT, SEED_STATE, SEED_VAULT, SOL_ORACLE, STAKE_ACCOUNT_SIZE, StateIdlModel, StateModel, TRANSFER_HOOK_PROGRAM, USDC, WBTC, WETH, WSOL, fetchKaminoObligations, fetchMarinadeTicketAccounts, fetchMeteoraPositions, fetchStakeAccounts, getGlamProgram, getGlamProgramId, getPriorityFeeEstimate, getSimulationComputeUnits, isBrowser, parseMeteoraPosition };