@glamsystems/glam-sdk 0.1.18 → 0.1.20

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
@@ -3230,6 +3230,7 @@ var instructions = [
3230
3230
  },
3231
3231
  {
3232
3232
  name: "glam_vault",
3233
+ writable: true,
3233
3234
  pda: {
3234
3235
  seeds: [
3235
3236
  {
@@ -12427,9 +12428,12 @@ const MEMO_PROGRAM = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
12427
12428
  * Stake pools
12428
12429
  */ const JITO_STAKE_POOL = new PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb");
12429
12430
  const JUPSOL_STAKE_POOL = new PublicKey("8VpRhuxa7sUUepdY3kQiTmX9rS5vx4WgaXiAnXq4KCtr");
12431
+ /**
12432
+ * Referrers
12433
+ */ const GLAM_REFERRER = new PublicKey("GLAMrG37ZqioqvzBNQGCfCUueDz3tsr7MwMFyRk9PS89");
12430
12434
 
12431
12435
  const GlamIntegrations = GlamProtocolIdlJson?.types?.find((t)=>t.name === "Integration")?.type?.variants?.map((v)=>v.name) ?? [];
12432
- const GlamPermissions = GlamProtocolIdlJson?.types?.find((t)=>t.name === "Permission")?.type?.variants?.map((v)=>v.name) ?? [];
12436
+ const GlamPermissions = GlamProtocolIdlJson?.types?.find((t)=>t.name === "Permission")?.type?.variants?.map((v)=>v.name).filter((v)=>!v.startsWith("__")) ?? [];
12433
12437
  const GLAM_PROGRAM_ID_DEFAULT = new PublicKey(GlamProtocolIdlJson.address);
12434
12438
  class StateIdlModel {
12435
12439
  constructor(data){
@@ -13639,6 +13643,12 @@ class DriftClient {
13639
13643
  getUserStatsAccountPublicKey(DRIFT_PROGRAM_ID, vault)
13640
13644
  ];
13641
13645
  }
13646
+ getGlamReferrer() {
13647
+ return [
13648
+ getUserAccountPublicKeySync(DRIFT_PROGRAM_ID, GLAM_REFERRER, 0),
13649
+ getUserStatsAccountPublicKey(DRIFT_PROGRAM_ID, GLAM_REFERRER)
13650
+ ];
13651
+ }
13642
13652
  async fetchMarketConfigs() {
13643
13653
  const response = await fetch("https://api.glam.systems/v0/drift/market_configs/");
13644
13654
  if (!response.ok) {
@@ -13732,15 +13742,18 @@ class DriftClient {
13732
13742
  const name = `GLAM *.+ ${subAccountId}`.split("").map((char)=>char.charCodeAt(0)).concat(Array(24).fill(0));
13733
13743
  const [user, userStats] = this.getUser(glamState, subAccountId);
13734
13744
  const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13745
+ const remainingAccounts = this.getGlamReferrer().map((p)=>({
13746
+ pubkey: p,
13747
+ isWritable: true,
13748
+ isSigner: false
13749
+ }));
13735
13750
  return await this.base.program.methods.driftInitializeUser(subAccountId, name).accounts({
13736
13751
  glamState,
13737
13752
  user,
13738
13753
  userStats,
13739
13754
  state,
13740
13755
  glamSigner
13741
- })// We should only try to add referrer if it is the first user (subAccountId == 0)
13742
- // .remainingAccounts([]) TODO: set glam referral account
13743
- .instruction();
13756
+ }).remainingAccounts(remainingAccounts).instruction();
13744
13757
  }
13745
13758
  async initializeTx(glamState, subAccountId = 0, txOptions = {}) {
13746
13759
  const glamSigner = txOptions.signer || this.base.getSigner();
@@ -13890,7 +13903,11 @@ class DriftClient {
13890
13903
  }
13891
13904
  async placeOrderTx(glamState, orderParams, subAccountId = 0, marketConfigs, txOptions = {}) {
13892
13905
  const { marketIndex, marketType } = orderParams;
13893
- const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex);
13906
+ const remainingAccounts = (await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex)).concat(this.getGlamReferrer().map((p)=>({
13907
+ pubkey: p,
13908
+ isWritable: true,
13909
+ isSigner: false
13910
+ })));
13894
13911
  const glamSigner = txOptions.signer || this.base.getSigner();
13895
13912
  const [user] = this.getUser(glamState, subAccountId);
13896
13913
  const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
@@ -15653,7 +15670,7 @@ const DEFAULT_OBLIGATION_ARGS = {
15653
15670
  id: 0
15654
15671
  };
15655
15672
  const SCOPE_PRICES = new PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C");
15656
- function refreshObligation(accounts, programId) {
15673
+ function refreshObligation(accounts, programId = KAMINO_LENDING_PROGRAM) {
15657
15674
  const keys = [
15658
15675
  {
15659
15676
  pubkey: accounts.lendingMarket,
@@ -15691,7 +15708,7 @@ function refreshObligation(accounts, programId) {
15691
15708
  });
15692
15709
  return ix;
15693
15710
  }
15694
- function refreshReserve(accounts, programId) {
15711
+ function refreshReserve(accounts, programId = KAMINO_LENDING_PROGRAM) {
15695
15712
  const keys = [
15696
15713
  {
15697
15714
  pubkey: accounts.reserve,
@@ -15742,7 +15759,7 @@ function refreshReserve(accounts, programId) {
15742
15759
  });
15743
15760
  return ix;
15744
15761
  }
15745
- function refreshObligationFarmsForReserve(args, accounts, programId) {
15762
+ function refreshObligationFarmsForReserve(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
15746
15763
  const keys = [
15747
15764
  {
15748
15765
  pubkey: accounts.crank,
@@ -15833,7 +15850,7 @@ class KaminoLendingClient {
15833
15850
  * @param txOptions
15834
15851
  * @returns
15835
15852
  */ async initUserMetadata(statePda, referrer, txOptions = {}) {
15836
- const tx = await this.initUserMetadataTx(new PublicKey(statePda), referrer ? new PublicKey(referrer) : PublicKey.default, txOptions);
15853
+ const tx = await this.initUserMetadataTx(new PublicKey(statePda), referrer ? new PublicKey(referrer) : null, txOptions);
15837
15854
  return await this.base.sendAndConfirm(tx);
15838
15855
  }
15839
15856
  /**
@@ -15919,18 +15936,17 @@ class KaminoLendingClient {
15919
15936
  ], KAMINO_FARM_PROGRAM);
15920
15937
  return obligationFarm;
15921
15938
  }
15922
- async initUserMetadataTx(glamState, referrer, txOptions) {
15939
+ async initUserMetadataTx(glamState, referrer, txOptions = {}) {
15923
15940
  const glamSigner = txOptions.signer || this.base.getSigner();
15924
15941
  const vault = this.base.getVaultPda(glamState);
15925
15942
  const userMetadata = this.getUserMetadataPda(vault);
15926
15943
  const lookupTable = new PublicKey(0); // FIXME: create lookup table
15927
- const referrerUserMetadata = referrer.equals(PublicKey.default) ? KAMINO_LENDING_PROGRAM : referrer;
15928
15944
  // @ts-ignore
15929
15945
  const tx = await this.base.program.methods.kaminoLendingInitUserMetadata(lookupTable).accounts({
15930
15946
  glamState,
15931
15947
  glamSigner,
15932
15948
  userMetadata,
15933
- referrerUserMetadata
15949
+ referrerUserMetadata: referrer
15934
15950
  }).transaction();
15935
15951
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
15936
15952
  return vTx;
@@ -15943,7 +15959,7 @@ class KaminoLendingClient {
15943
15959
  switchboardPriceOracle: KAMINO_LENDING_PROGRAM,
15944
15960
  switchboardTwapOracle: KAMINO_LENDING_PROGRAM,
15945
15961
  scopePrices: SCOPE_PRICES
15946
- }, KAMINO_LENDING_PROGRAM));
15962
+ }));
15947
15963
  }
15948
15964
  refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) {
15949
15965
  return parsedReserves.map((parsedReserve)=>{
@@ -15968,18 +15984,21 @@ class KaminoLendingClient {
15968
15984
  farmsProgram: KAMINO_FARM_PROGRAM,
15969
15985
  rent: SYSVAR_RENT_PUBKEY,
15970
15986
  systemProgram: SystemProgram.programId
15971
- }, KAMINO_LENDING_PROGRAM);
15987
+ });
15972
15988
  });
15973
15989
  }).flat();
15974
15990
  }
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);
15991
+ // If obligation has deposits or borrows, we need the following refresh ixs:
15992
+ // - refreshReserve x N_reserves
15993
+ // - refreshObligation
15994
+ // - refreshObligationFarmsForReserve x M_farms
15995
+ //
15996
+ // For pricing purpose, we don't need to refresh farm states
15997
+ async getRefreshIxs(obligation, refreshFarms = true) {
15998
+ const { lendingMarket, deposits, borrows } = await this.fetchAndParseObligation(obligation);
15999
+ if (!lendingMarket) {
16000
+ throw new Error("Lending market not found");
16001
+ }
15983
16002
  const reserves = deposits.concat(borrows).map((d)=>d.reserve);
15984
16003
  const parsedReserves = await this.fetchAndParseReserves(reserves);
15985
16004
  return [
@@ -15988,8 +16007,8 @@ class KaminoLendingClient {
15988
16007
  lendingMarket,
15989
16008
  obligation,
15990
16009
  reserves
15991
- }, KAMINO_LENDING_PROGRAM),
15992
- ...this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves)
16010
+ }),
16011
+ ...refreshFarms ? this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) : []
15993
16012
  ];
15994
16013
  }
15995
16014
  getMarketAuthority(market) {
@@ -16040,11 +16059,14 @@ class KaminoLendingClient {
16040
16059
  const obligationAccount = await this.base.provider.connection.getAccountInfo(obligation);
16041
16060
  if (!obligationAccount) {
16042
16061
  return {
16062
+ address: obligation,
16063
+ lendingMarket: null,
16043
16064
  deposits: [],
16044
16065
  borrows: []
16045
16066
  };
16046
16067
  }
16047
16068
  const data = obligationAccount.data;
16069
+ const lendingMarket = new PublicKey(data.subarray(32, 64));
16048
16070
  // read deposits
16049
16071
  let depositsOffset = 96;
16050
16072
  let depositSize = 136;
@@ -16054,8 +16076,9 @@ class KaminoLendingClient {
16054
16076
  length: numDeposits
16055
16077
  }, (_, i)=>{
16056
16078
  const depositData = depositsData.subarray(i * depositSize, (i + 1) * depositSize);
16079
+ const reserve = new PublicKey(depositData.subarray(0, 32));
16057
16080
  return {
16058
- reserve: new PublicKey(depositData.subarray(0, 32))
16081
+ reserve
16059
16082
  };
16060
16083
  }).filter((d)=>!d.reserve.equals(PublicKey.default));
16061
16084
  // read borrows
@@ -16067,24 +16090,33 @@ class KaminoLendingClient {
16067
16090
  length: numBorrows
16068
16091
  }, (_, i)=>{
16069
16092
  const borrowData = borrowsData.subarray(i * borrowSize, (i + 1) * borrowSize);
16093
+ const reserve = new PublicKey(borrowData.subarray(0, 32));
16070
16094
  return {
16071
- reserve: new PublicKey(borrowData.subarray(0, 32))
16095
+ reserve
16072
16096
  };
16073
16097
  }).filter((d)=>!d.reserve.equals(PublicKey.default));
16074
16098
  const parsedObligation = {
16099
+ address: obligation,
16100
+ lendingMarket,
16075
16101
  deposits,
16076
16102
  borrows
16077
16103
  };
16078
16104
  this.obligations.set(obligation, parsedObligation);
16079
16105
  return parsedObligation;
16080
16106
  }
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) {
16107
+ _parseReserveAccount(data) {
16108
+ const market = new PublicKey(data.subarray(32, 64));
16109
+ const farmCollateral = new PublicKey(data.subarray(64, 96));
16110
+ const farmDebt = new PublicKey(data.subarray(96, 128));
16111
+ const liquidityMint = new PublicKey(data.subarray(128, 160));
16112
+ return {
16113
+ farmCollateral: farmCollateral.equals(PublicKey.default) ? null : farmCollateral,
16114
+ farmDebt: farmDebt.equals(PublicKey.default) ? null : farmDebt,
16115
+ liquidityMint,
16116
+ ...this.reservePdas(market, liquidityMint)
16117
+ };
16118
+ }
16119
+ async fetchAndParseReserves(reserves) {
16088
16120
  if (this.pubkeyArraysEqual(reserves, Array.from(this.reserves.keys()))) {
16089
16121
  return Array.from(this.reserves.values());
16090
16122
  }
@@ -16093,20 +16125,12 @@ class KaminoLendingClient {
16093
16125
  throw new Error("Not all reserves can be found");
16094
16126
  }
16095
16127
  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 = {
16128
+ const parsedReserve = {
16102
16129
  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)
16130
+ ...this._parseReserveAccount(account.data)
16107
16131
  };
16108
- this.reserves.set(reserves[i], parsed);
16109
- return parsed;
16132
+ this.reserves.set(reserves[i], parsedReserve);
16133
+ return parsedReserve;
16110
16134
  });
16111
16135
  }
16112
16136
  async findAndParseReserve(market, asset) {
@@ -16133,18 +16157,12 @@ class KaminoLendingClient {
16133
16157
  throw new Error("Reserve not found");
16134
16158
  }
16135
16159
  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 = {
16160
+ const parsedReserve = {
16140
16161
  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)
16162
+ ...this._parseReserveAccount(account.account.data)
16145
16163
  };
16146
- this.reserves.set(account.pubkey, parsed);
16147
- return parsed;
16164
+ this.reserves.set(account.pubkey, parsedReserve);
16165
+ return parsedReserve;
16148
16166
  }
16149
16167
  async depositTx(glamState, market, asset, amount, txOptions) {
16150
16168
  const glamSigner = txOptions.signer || this.base.getSigner();
@@ -16202,7 +16220,7 @@ class KaminoLendingClient {
16202
16220
  lendingMarket: market,
16203
16221
  obligation,
16204
16222
  reserves: reservesInUse
16205
- }, KAMINO_LENDING_PROGRAM));
16223
+ }));
16206
16224
  if (depositReserve.farmCollateral) {
16207
16225
  const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16208
16226
  depositReserve
@@ -16244,7 +16262,6 @@ class KaminoLendingClient {
16244
16262
  liquidityTokenProgram: TOKEN_PROGRAM_ID,
16245
16263
  instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16246
16264
  obligationFarmUserState: obligationFarm,
16247
- // @ts-ignore
16248
16265
  reserveFarmState: depositReserve.farmCollateral,
16249
16266
  farmsProgram: KAMINO_FARM_PROGRAM
16250
16267
  }).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
@@ -16299,7 +16316,7 @@ class KaminoLendingClient {
16299
16316
  lendingMarket: market,
16300
16317
  obligation,
16301
16318
  reserves: reservesInUse
16302
- }, KAMINO_LENDING_PROGRAM));
16319
+ }));
16303
16320
  if (withdrawReserve.farmCollateral) {
16304
16321
  const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16305
16322
  withdrawReserve
@@ -16328,7 +16345,6 @@ class KaminoLendingClient {
16328
16345
  liquidityTokenProgram: TOKEN_PROGRAM_ID,
16329
16346
  instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16330
16347
  obligationFarmUserState: obligationFarm,
16331
- // @ts-ignore
16332
16348
  reserveFarmState: withdrawReserve.farmCollateral,
16333
16349
  farmsProgram: KAMINO_FARM_PROGRAM
16334
16350
  }).instruction();
@@ -16390,7 +16406,7 @@ class KaminoLendingClient {
16390
16406
  lendingMarket: market,
16391
16407
  obligation,
16392
16408
  reserves: reservesInUse
16393
- }, KAMINO_LENDING_PROGRAM));
16409
+ }));
16394
16410
  // Don't need to refresh debt farm for borrow
16395
16411
  /*
16396
16412
  if (borrowReserve.farmDebt) {
@@ -16419,7 +16435,6 @@ class KaminoLendingClient {
16419
16435
  instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16420
16436
  tokenProgram: TOKEN_PROGRAM_ID,
16421
16437
  obligationFarmUserState: obligationFarm,
16422
- // @ts-ignore
16423
16438
  reserveFarmState: borrowReserve.farmDebt,
16424
16439
  farmsProgram: KAMINO_FARM_PROGRAM
16425
16440
  }).instruction();
@@ -16479,7 +16494,7 @@ class KaminoLendingClient {
16479
16494
  lendingMarket: market,
16480
16495
  obligation,
16481
16496
  reserves: reservesInUse
16482
- }, KAMINO_LENDING_PROGRAM));
16497
+ }));
16483
16498
  const repayIx = await this.base.program.methods.kaminoLendingRepayObligationLiquidityV2(amount).accounts({
16484
16499
  glamState,
16485
16500
  glamSigner,
@@ -16493,7 +16508,6 @@ class KaminoLendingClient {
16493
16508
  instructionSysvarAccount: SYSVAR_INSTRUCTIONS_PUBKEY,
16494
16509
  tokenProgram: TOKEN_PROGRAM_ID,
16495
16510
  obligationFarmUserState: obligationFarm,
16496
- // @ts-ignore
16497
16511
  reserveFarmState: repayReserve.farmDebt,
16498
16512
  farmsProgram: KAMINO_FARM_PROGRAM
16499
16513
  }).instruction();
@@ -16524,6 +16538,135 @@ class KaminoLendingClient {
16524
16538
  };
16525
16539
  }
16526
16540
  }
16541
+ class KaminoFarmClient {
16542
+ async findAndParseFarmStates(owner) {
16543
+ const accounts = await this.base.provider.connection.getProgramAccounts(KAMINO_FARM_PROGRAM, {
16544
+ filters: [
16545
+ {
16546
+ dataSize: 920
16547
+ },
16548
+ {
16549
+ memcmp: {
16550
+ offset: 48,
16551
+ bytes: owner.toBase58()
16552
+ }
16553
+ }
16554
+ ]
16555
+ });
16556
+ return accounts.map((account)=>{
16557
+ const data = account.account.data;
16558
+ const farmState = new PublicKey(data.subarray(16, 48));
16559
+ return {
16560
+ userFarmState: account.pubkey,
16561
+ farmState
16562
+ };
16563
+ });
16564
+ }
16565
+ async parseFarm(data) {
16566
+ const globalConfig = new PublicKey(data.subarray(40, 72));
16567
+ const rewardsOffset = 192;
16568
+ const numRewards = 10;
16569
+ const rewardSize = 704;
16570
+ const rewardsData = data.subarray(rewardsOffset, rewardsOffset + numRewards * rewardSize);
16571
+ const rewards = Array.from({
16572
+ length: numRewards
16573
+ }, (_, i)=>{
16574
+ const rewardData = rewardsData.subarray(i * rewardSize, (i + 1) * rewardSize);
16575
+ const mint = new PublicKey(rewardData.subarray(0, 32));
16576
+ const tokenProgram = new PublicKey(rewardData.subarray(40, 72));
16577
+ const rewardsVault = new PublicKey(rewardData.subarray(120, 152));
16578
+ const minClaimDurationSeconds = new BN(rewardData.subarray(480, 488), "le");
16579
+ return {
16580
+ index: i,
16581
+ mint,
16582
+ minClaimDurationSeconds,
16583
+ tokenProgram,
16584
+ rewardsVault
16585
+ };
16586
+ }).filter((r)=>{
16587
+ if (r.mint.equals(PublicKey.default)) {
16588
+ return false;
16589
+ }
16590
+ // Filter out rewards with minClaimDurationSeconds > 1 year, they are considered disabled
16591
+ if (r.minClaimDurationSeconds.div(new BN(365 * 24 * 60 * 60)).gt(new BN(1))) {
16592
+ return false;
16593
+ }
16594
+ return true;
16595
+ });
16596
+ return {
16597
+ globalConfig,
16598
+ rewards
16599
+ };
16600
+ }
16601
+ async fetchAndParseFarms(farms) {
16602
+ const farmAccounts = await this.base.provider.connection.getMultipleAccountsInfo(farms);
16603
+ const map = new Map();
16604
+ for(let i = 0; i < farmAccounts.length; i++){
16605
+ const account = farmAccounts[i];
16606
+ if (!account) {
16607
+ continue;
16608
+ }
16609
+ const data = account.data;
16610
+ const parsedFarm = await this.parseFarm(data);
16611
+ map.set(farms[i].toBase58(), parsedFarm);
16612
+ }
16613
+ return map;
16614
+ }
16615
+ async harvest(statePda, txOptions = {}) {
16616
+ const tx = await this.harvestTx(new PublicKey(statePda), txOptions);
16617
+ return await this.base.sendAndConfirm(tx);
16618
+ }
16619
+ async harvestTx(glamState, txOptions = {}) {
16620
+ const glamSigner = txOptions.signer || this.base.getSigner();
16621
+ const vault = this.base.getVaultPda(glamState);
16622
+ const farmStates = await this.findAndParseFarmStates(vault);
16623
+ const parsedFarms = await this.fetchAndParseFarms(farmStates.map((f)=>f.farmState));
16624
+ const tx = new Transaction();
16625
+ for (const { userFarmState, farmState } of farmStates){
16626
+ const { globalConfig, rewards } = parsedFarms.get(farmState.toBase58());
16627
+ for (const { index, mint, tokenProgram, rewardsVault } of rewards){
16628
+ console.log("Reward token:", mint.toBase58());
16629
+ const vaultAta = this.base.getVaultAta(glamState, mint, tokenProgram);
16630
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(glamSigner, vaultAta, vault, mint, tokenProgram);
16631
+ const harvestIx = await this.base.program.methods.kaminoFarmHarvestReward(new BN(index)).accounts({
16632
+ glamState,
16633
+ glamSigner,
16634
+ userState: userFarmState,
16635
+ farmState,
16636
+ globalConfig,
16637
+ rewardMint: mint,
16638
+ userRewardAta: vaultAta,
16639
+ rewardsVault,
16640
+ rewardsTreasuryVault: this.rewardsTreasuryVault(globalConfig, mint),
16641
+ farmVaultsAuthority: this.farmVaultsAuthority(farmState),
16642
+ scopePrices: null,
16643
+ tokenProgram
16644
+ }).instruction();
16645
+ tx.add(createAtaIx, harvestIx);
16646
+ }
16647
+ }
16648
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
16649
+ LOOKUP_TABLE
16650
+ ]);
16651
+ const vTx = await this.base.intoVersionedTransaction(tx, {
16652
+ ...txOptions,
16653
+ lookupTables
16654
+ });
16655
+ return vTx;
16656
+ }
16657
+ constructor(base){
16658
+ this.base = base;
16659
+ this.farmVaultsAuthority = (farm)=>PublicKey.findProgramAddressSync([
16660
+ Buffer.from("authority"),
16661
+ farm.toBuffer()
16662
+ ], KAMINO_FARM_PROGRAM)[0];
16663
+ this.rewardsTreasuryVault = (globalConfig, mint)=>PublicKey.findProgramAddressSync([
16664
+ Buffer.from("tvault"),
16665
+ globalConfig.toBuffer(),
16666
+ mint.toBuffer()
16667
+ ], KAMINO_FARM_PROGRAM)[0];
16668
+ }
16669
+ }
16527
16670
 
16528
16671
  // Pubkey::find_program_address(&[b"__event_authority"], &dlmm_interface::ID)
16529
16672
  const EVENT_AUTHORITY = new PublicKey("D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6");
@@ -17000,6 +17143,28 @@ class PriceClient {
17000
17143
  });
17001
17144
  return pricedAssets.reduce((sum, p)=>new BN(p.amount).add(sum), new BN(0));
17002
17145
  }
17146
+ async priceKaminoIxs(glamState, priceDenom) {
17147
+ const glamVault = this.base.getVaultPda(glamState);
17148
+ const obligations = await fetchKaminoObligations(this.base.provider.connection, glamVault);
17149
+ const refreshIxs = [];
17150
+ for (const obligation of obligations){
17151
+ const ixs = await this.klend.getRefreshIxs(obligation, false); // skip farms
17152
+ refreshIxs.push(...ixs);
17153
+ }
17154
+ // @ts-ignore
17155
+ const priceIx = await this.base.program.methods.priceKaminoObligations(priceDenom).accounts({
17156
+ glamState,
17157
+ solOracle: SOL_ORACLE
17158
+ }).remainingAccounts(obligations.map((o)=>({
17159
+ pubkey: o,
17160
+ isSigner: false,
17161
+ isWritable: false
17162
+ }))).instruction();
17163
+ return [
17164
+ ...refreshIxs,
17165
+ priceIx
17166
+ ];
17167
+ }
17003
17168
  async priceVaultIxs(glamState, priceDenom) {
17004
17169
  const vault = this.base.getVaultPda(glamState);
17005
17170
  const tickets = await fetchMarinadeTicketAccounts(this.base.provider.connection, vault);
@@ -17029,29 +17194,18 @@ class PriceClient {
17029
17194
  glamState,
17030
17195
  solOracle: SOL_ORACLE
17031
17196
  }).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();
17197
+ const priceKaminoIxs = await this.priceKaminoIxs(glamState, priceDenom);
17036
17198
  return [
17037
17199
  priceTicketsIx,
17038
17200
  priceStakesIx,
17039
17201
  priceVaultIx,
17040
17202
  priceMeteoraIx,
17041
- priceKaminoIx
17203
+ ...priceKaminoIxs
17042
17204
  ];
17043
17205
  }
17044
- constructor(base){
17206
+ constructor(base, klend){
17045
17207
  this.base = base;
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
- };
17208
+ this.klend = klend;
17055
17209
  this.remainingAccountsForPricingMeteora = async (glamState)=>{
17056
17210
  const glamVault = this.base.getVaultPda(glamState);
17057
17211
  const positions = await fetchMeteoraPositions(this.base.provider.connection, glamVault);
@@ -17137,7 +17291,7 @@ class PriceClient {
17137
17291
  }
17138
17292
  get price() {
17139
17293
  if (!this._price) {
17140
- this._price = new PriceClient(this);
17294
+ this._price = new PriceClient(this, this.kaminoLending);
17141
17295
  }
17142
17296
  return this._price;
17143
17297
  }
@@ -17159,6 +17313,12 @@ class PriceClient {
17159
17313
  }
17160
17314
  return this._kaminoLending;
17161
17315
  }
17316
+ get kaminoFarm() {
17317
+ if (!this._kaminoFarm) {
17318
+ this._kaminoFarm = new KaminoFarmClient(this);
17319
+ }
17320
+ return this._kaminoFarm;
17321
+ }
17162
17322
  get meteoraDlmm() {
17163
17323
  if (!this._meteoraDlmm) {
17164
17324
  this._meteoraDlmm = new MeteoraDlmmClient(this);
@@ -17174,7 +17334,7 @@ const getPriorityFeeEstimate = async (heliusApiKey, tx, accountKeys, priorityLev
17174
17334
  if (!tx && !accountKeys) {
17175
17335
  throw new Error("Either tx or accountKeys must be provided");
17176
17336
  }
17177
- const options = priorityLevel ? {
17337
+ const options = priorityLevel && priorityLevel !== "Recommended" ? {
17178
17338
  priorityLevel
17179
17339
  } : {
17180
17340
  recommended: true
@@ -17206,4 +17366,4 @@ const getPriorityFeeEstimate = async (heliusApiKey, tx, accountKeys, priorityLev
17206
17366
  return data.result.priorityFeeEstimate;
17207
17367
  };
17208
17368
 
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 };
17369
+ export { ASSETS_MAINNET, ASSETS_TESTS, BaseClient, ClusterNetwork, CompanyModel, CreatedModel, DRIFT_PROGRAM_ID, DelegateAcl, DriftClient, FundOpenfundsModel, GLAM_REFERRER, 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 };
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@glamsystems/glam-sdk",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "TypeScript SDK for the GLAM Protocol",
5
5
  "main": "./index.cjs.js",
6
6
  "module": "./index.esm.js",
7
7
  "homepage": "https://www.glam.systems",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git@github.com:glamsystems/glam.git"
10
+ "url": "git@github.com:glamsystems/glam-sdk.git"
11
11
  },
12
12
  "keywords": [
13
13
  "glam",
@@ -72,6 +72,7 @@ export declare class DriftClient {
72
72
  settlePnl(statePda: PublicKey | string, marketIndex: number, subAccountId: number, marketConfigs: DriftMarketConfigs, txOptions?: TxOptions): Promise<TransactionSignature>;
73
73
  priceDrift(statePda: PublicKey | string, marketConfigs: DriftMarketConfigs, priceDenom: PriceDenom, txOptions?: TxOptions): Promise<TransactionSignature>;
74
74
  getUser(statePda: PublicKey | string, subAccountId?: number): PublicKey[];
75
+ getGlamReferrer(): PublicKey[];
75
76
  fetchMarketConfigs(): Promise<DriftMarketConfigs>;
76
77
  fetchGlamDriftUser(glamState: PublicKey | string, subAccountId?: number): Promise<GlamDriftUser>;
77
78
  getPositions(statePda: PublicKey | string, subAccountId?: number): Promise<{