@glamsystems/glam-sdk 0.1.19 → 0.1.21

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
@@ -5,7 +5,6 @@ import { getExtensionData, ExtensionType, TOKEN_PROGRAM_ID, getAssociatedTokenAd
5
5
  import { unpack } from '@solana/spl-token-metadata';
6
6
  import DLMM, { binIdToBinArrayIndex, deriveBinArray, Strategy } from '@meteora-ag/dlmm';
7
7
  import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
8
- import { getUserAccountPublicKeySync, getUserStatsAccountPublicKey, decodeUser, MarketType, getDriftStateAccountPublicKey } from '@drift-labs/sdk';
9
8
  import { Marinade } from '@marinade.finance/marinade-ts-sdk';
10
9
  import { getStakePoolAccount } from '@solana/spl-stake-pool';
11
10
  import * as borsh from '@coral-xyz/borsh';
@@ -3230,6 +3229,7 @@ var instructions = [
3230
3229
  },
3231
3230
  {
3232
3231
  name: "glam_vault",
3232
+ writable: true,
3233
3233
  pda: {
3234
3234
  seeds: [
3235
3235
  {
@@ -9194,16 +9194,21 @@ var errors = [
9194
9194
  },
9195
9195
  {
9196
9196
  code: 50004,
9197
+ name: "InvalidPlatformFeeForSwap",
9198
+ msg: "Invalid platform fee"
9199
+ },
9200
+ {
9201
+ code: 50005,
9197
9202
  name: "InvalidTokenAccount",
9198
9203
  msg: "Invalid token account"
9199
9204
  },
9200
9205
  {
9201
- code: 50005,
9206
+ code: 50006,
9202
9207
  name: "InvalidVoteSide",
9203
9208
  msg: "Invalid vote side"
9204
9209
  },
9205
9210
  {
9206
- code: 50006,
9211
+ code: 50007,
9207
9212
  name: "MultipleStakeAccountsDisallowed",
9208
9213
  msg: "Multiple stake accounts disallowed"
9209
9214
  },
@@ -12427,9 +12432,12 @@ const MEMO_PROGRAM = new PublicKey("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
12427
12432
  * Stake pools
12428
12433
  */ const JITO_STAKE_POOL = new PublicKey("Jito4APyf642JPZPx3hGc6WWJ8zPKtRbRs4P815Awbb");
12429
12434
  const JUPSOL_STAKE_POOL = new PublicKey("8VpRhuxa7sUUepdY3kQiTmX9rS5vx4WgaXiAnXq4KCtr");
12435
+ /**
12436
+ * Referrers
12437
+ */ const GLAM_REFERRER = new PublicKey("GLAMrG37ZqioqvzBNQGCfCUueDz3tsr7MwMFyRk9PS89");
12430
12438
 
12431
12439
  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) ?? [];
12440
+ const GlamPermissions = GlamProtocolIdlJson?.types?.find((t)=>t.name === "Permission")?.type?.variants?.map((v)=>v.name).filter((v)=>!v.startsWith("__")) ?? [];
12433
12441
  const GLAM_PROGRAM_ID_DEFAULT = new PublicKey(GlamProtocolIdlJson.address);
12434
12442
  class StateIdlModel {
12435
12443
  constructor(data){
@@ -12904,6 +12912,13 @@ const getErrorFromRPCResponse = (rpcResponse)=>{
12904
12912
  throw Error(error.toString());
12905
12913
  }
12906
12914
  };
12915
+ const setsAreEqual = (a, b)=>{
12916
+ if (a.size !== b.size) return false;
12917
+ for (let item of a){
12918
+ if (!b.has(item)) return false;
12919
+ }
12920
+ return true;
12921
+ };
12907
12922
 
12908
12923
  const ASSETS_MAINNET = new Map([
12909
12924
  [
@@ -13573,7 +13588,901 @@ class BaseClient {
13573
13588
  }
13574
13589
  }
13575
13590
 
13576
- const DRIFT_VAULT = new PublicKey("JCNCMFXo5M5qwUPg2Utu1u6YWp3MbygxqBsBeXXJfrw");
13591
+ const ZERO = new BN(0);
13592
+ // # Utility Types / Enums / Constants
13593
+ var ExchangeStatus = /*#__PURE__*/ function(ExchangeStatus) {
13594
+ ExchangeStatus[ExchangeStatus["ACTIVE"] = 0] = "ACTIVE";
13595
+ ExchangeStatus[ExchangeStatus["DEPOSIT_PAUSED"] = 1] = "DEPOSIT_PAUSED";
13596
+ ExchangeStatus[ExchangeStatus["WITHDRAW_PAUSED"] = 2] = "WITHDRAW_PAUSED";
13597
+ ExchangeStatus[ExchangeStatus["AMM_PAUSED"] = 4] = "AMM_PAUSED";
13598
+ ExchangeStatus[ExchangeStatus["FILL_PAUSED"] = 8] = "FILL_PAUSED";
13599
+ ExchangeStatus[ExchangeStatus["LIQ_PAUSED"] = 16] = "LIQ_PAUSED";
13600
+ ExchangeStatus[ExchangeStatus["FUNDING_PAUSED"] = 32] = "FUNDING_PAUSED";
13601
+ ExchangeStatus[ExchangeStatus["SETTLE_PNL_PAUSED"] = 64] = "SETTLE_PNL_PAUSED";
13602
+ ExchangeStatus[ExchangeStatus["AMM_IMMEDIATE_FILL_PAUSED"] = 128] = "AMM_IMMEDIATE_FILL_PAUSED";
13603
+ ExchangeStatus[ExchangeStatus["PAUSED"] = 255] = "PAUSED";
13604
+ return ExchangeStatus;
13605
+ }({});
13606
+ class MarketStatus {
13607
+ }
13608
+ MarketStatus.INITIALIZED = {
13609
+ initialized: {}
13610
+ };
13611
+ MarketStatus.ACTIVE = {
13612
+ active: {}
13613
+ };
13614
+ MarketStatus.FUNDING_PAUSED = {
13615
+ fundingPaused: {}
13616
+ };
13617
+ MarketStatus.AMM_PAUSED = {
13618
+ ammPaused: {}
13619
+ };
13620
+ MarketStatus.FILL_PAUSED = {
13621
+ fillPaused: {}
13622
+ };
13623
+ MarketStatus.WITHDRAW_PAUSED = {
13624
+ withdrawPaused: {}
13625
+ };
13626
+ MarketStatus.REDUCE_ONLY = {
13627
+ reduceOnly: {}
13628
+ };
13629
+ MarketStatus.SETTLEMENT = {
13630
+ settlement: {}
13631
+ };
13632
+ MarketStatus.DELISTED = {
13633
+ delisted: {}
13634
+ };
13635
+ var PerpOperation = /*#__PURE__*/ function(PerpOperation) {
13636
+ PerpOperation[PerpOperation["UPDATE_FUNDING"] = 1] = "UPDATE_FUNDING";
13637
+ PerpOperation[PerpOperation["AMM_FILL"] = 2] = "AMM_FILL";
13638
+ PerpOperation[PerpOperation["FILL"] = 4] = "FILL";
13639
+ PerpOperation[PerpOperation["SETTLE_PNL"] = 8] = "SETTLE_PNL";
13640
+ PerpOperation[PerpOperation["SETTLE_PNL_WITH_POSITION"] = 16] = "SETTLE_PNL_WITH_POSITION";
13641
+ PerpOperation[PerpOperation["LIQUIDATION"] = 32] = "LIQUIDATION";
13642
+ return PerpOperation;
13643
+ }({});
13644
+ var SpotOperation = /*#__PURE__*/ function(SpotOperation) {
13645
+ SpotOperation[SpotOperation["UPDATE_CUMULATIVE_INTEREST"] = 1] = "UPDATE_CUMULATIVE_INTEREST";
13646
+ SpotOperation[SpotOperation["FILL"] = 2] = "FILL";
13647
+ SpotOperation[SpotOperation["DEPOSIT"] = 4] = "DEPOSIT";
13648
+ SpotOperation[SpotOperation["WITHDRAW"] = 8] = "WITHDRAW";
13649
+ SpotOperation[SpotOperation["LIQUIDATION"] = 16] = "LIQUIDATION";
13650
+ return SpotOperation;
13651
+ }({});
13652
+ var InsuranceFundOperation = /*#__PURE__*/ function(InsuranceFundOperation) {
13653
+ InsuranceFundOperation[InsuranceFundOperation["INIT"] = 1] = "INIT";
13654
+ InsuranceFundOperation[InsuranceFundOperation["ADD"] = 2] = "ADD";
13655
+ InsuranceFundOperation[InsuranceFundOperation["REQUEST_REMOVE"] = 4] = "REQUEST_REMOVE";
13656
+ InsuranceFundOperation[InsuranceFundOperation["REMOVE"] = 8] = "REMOVE";
13657
+ return InsuranceFundOperation;
13658
+ }({});
13659
+ var UserStatus = /*#__PURE__*/ function(UserStatus) {
13660
+ UserStatus[UserStatus["BEING_LIQUIDATED"] = 1] = "BEING_LIQUIDATED";
13661
+ UserStatus[UserStatus["BANKRUPT"] = 2] = "BANKRUPT";
13662
+ UserStatus[UserStatus["REDUCE_ONLY"] = 4] = "REDUCE_ONLY";
13663
+ UserStatus[UserStatus["ADVANCED_LP"] = 8] = "ADVANCED_LP";
13664
+ UserStatus[UserStatus["PROTECTED_MAKER"] = 16] = "PROTECTED_MAKER";
13665
+ return UserStatus;
13666
+ }({});
13667
+ class MarginMode {
13668
+ }
13669
+ MarginMode.DEFAULT = {
13670
+ default: {}
13671
+ };
13672
+ MarginMode.HIGH_LEVERAGE = {
13673
+ highLeverage: {}
13674
+ };
13675
+ class ContractType {
13676
+ }
13677
+ ContractType.PERPETUAL = {
13678
+ perpetual: {}
13679
+ };
13680
+ ContractType.FUTURE = {
13681
+ future: {}
13682
+ };
13683
+ ContractType.PREDICTION = {
13684
+ prediction: {}
13685
+ };
13686
+ class ContractTier {
13687
+ }
13688
+ ContractTier.A = {
13689
+ a: {}
13690
+ };
13691
+ ContractTier.B = {
13692
+ b: {}
13693
+ };
13694
+ ContractTier.C = {
13695
+ c: {}
13696
+ };
13697
+ ContractTier.SPECULATIVE = {
13698
+ speculative: {}
13699
+ };
13700
+ ContractTier.HIGHLY_SPECULATIVE = {
13701
+ highlySpeculative: {}
13702
+ };
13703
+ ContractTier.ISOLATED = {
13704
+ isolated: {}
13705
+ };
13706
+ class AssetTier {
13707
+ }
13708
+ AssetTier.COLLATERAL = {
13709
+ collateral: {}
13710
+ };
13711
+ AssetTier.PROTECTED = {
13712
+ protected: {}
13713
+ };
13714
+ AssetTier.CROSS = {
13715
+ cross: {}
13716
+ };
13717
+ AssetTier.ISOLATED = {
13718
+ isolated: {}
13719
+ };
13720
+ AssetTier.UNLISTED = {
13721
+ unlisted: {}
13722
+ };
13723
+ class SwapDirection {
13724
+ }
13725
+ SwapDirection.ADD = {
13726
+ add: {}
13727
+ };
13728
+ SwapDirection.REMOVE = {
13729
+ remove: {}
13730
+ };
13731
+ class SpotBalanceType {
13732
+ }
13733
+ SpotBalanceType.DEPOSIT = {
13734
+ deposit: {}
13735
+ };
13736
+ SpotBalanceType.BORROW = {
13737
+ borrow: {}
13738
+ };
13739
+ class PositionDirection {
13740
+ }
13741
+ PositionDirection.LONG = {
13742
+ long: {}
13743
+ };
13744
+ PositionDirection.SHORT = {
13745
+ short: {}
13746
+ };
13747
+ class DepositDirection {
13748
+ }
13749
+ DepositDirection.DEPOSIT = {
13750
+ deposit: {}
13751
+ };
13752
+ DepositDirection.WITHDRAW = {
13753
+ withdraw: {}
13754
+ };
13755
+ class OracleSource {
13756
+ static get(n) {
13757
+ const name = Object.entries(OracleSourceNum).find(([, v])=>v === n)?.[0];
13758
+ const source = Object.entries(OracleSource).find(([key, _])=>key.toLocaleLowerCase() === name?.toLocaleLowerCase())?.[1];
13759
+ if (!source) {
13760
+ throw new Error(`Invalid oracle source enum value: ${n}`);
13761
+ }
13762
+ return source;
13763
+ }
13764
+ }
13765
+ OracleSource.PYTH = {
13766
+ pyth: {}
13767
+ };
13768
+ OracleSource.PYTH_1K = {
13769
+ pyth1K: {}
13770
+ };
13771
+ OracleSource.PYTH_1M = {
13772
+ pyth1M: {}
13773
+ };
13774
+ OracleSource.PYTH_PULL = {
13775
+ pythPull: {}
13776
+ };
13777
+ OracleSource.PYTH_1K_PULL = {
13778
+ pyth1KPull: {}
13779
+ };
13780
+ OracleSource.PYTH_1M_PULL = {
13781
+ pyth1MPull: {}
13782
+ };
13783
+ OracleSource.SWITCHBOARD = {
13784
+ switchboard: {}
13785
+ };
13786
+ OracleSource.QUOTE_ASSET = {
13787
+ quoteAsset: {}
13788
+ };
13789
+ OracleSource.PYTH_STABLE_COIN = {
13790
+ pythStableCoin: {}
13791
+ };
13792
+ OracleSource.PYTH_STABLE_COIN_PULL = {
13793
+ pythStableCoinPull: {}
13794
+ };
13795
+ OracleSource.Prelaunch = {
13796
+ prelaunch: {}
13797
+ };
13798
+ OracleSource.SWITCHBOARD_ON_DEMAND = {
13799
+ switchboardOnDemand: {}
13800
+ };
13801
+ OracleSource.PYTH_LAZER = {
13802
+ pythLazer: {}
13803
+ };
13804
+ OracleSource.PYTH_LAZER_1K = {
13805
+ pythLazer1K: {}
13806
+ };
13807
+ OracleSource.PYTH_LAZER_1M = {
13808
+ pythLazer1M: {}
13809
+ };
13810
+ OracleSource.PYTH_LAZER_STABLE_COIN = {
13811
+ pythLazerStableCoin: {}
13812
+ };
13813
+ class OracleSourceNum {
13814
+ }
13815
+ OracleSourceNum.PYTH = 0;
13816
+ OracleSourceNum.PYTH_1K = 1;
13817
+ OracleSourceNum.PYTH_1M = 2;
13818
+ OracleSourceNum.PYTH_PULL = 3;
13819
+ OracleSourceNum.PYTH_1K_PULL = 4;
13820
+ OracleSourceNum.PYTH_1M_PULL = 5;
13821
+ OracleSourceNum.SWITCHBOARD = 6;
13822
+ OracleSourceNum.QUOTE_ASSET = 7;
13823
+ OracleSourceNum.PYTH_STABLE_COIN = 8;
13824
+ OracleSourceNum.PYTH_STABLE_COIN_PULL = 9;
13825
+ OracleSourceNum.PRELAUNCH = 10;
13826
+ OracleSourceNum.SWITCHBOARD_ON_DEMAND = 11;
13827
+ OracleSourceNum.PYTH_LAZER = 12;
13828
+ OracleSourceNum.PYTH_LAZER_1K = 13;
13829
+ OracleSourceNum.PYTH_LAZER_1M = 14;
13830
+ OracleSourceNum.PYTH_LAZER_STABLE_COIN = 15;
13831
+ class OrderType {
13832
+ }
13833
+ OrderType.LIMIT = {
13834
+ limit: {}
13835
+ };
13836
+ OrderType.TRIGGER_MARKET = {
13837
+ triggerMarket: {}
13838
+ };
13839
+ OrderType.TRIGGER_LIMIT = {
13840
+ triggerLimit: {}
13841
+ };
13842
+ OrderType.MARKET = {
13843
+ market: {}
13844
+ };
13845
+ OrderType.ORACLE = {
13846
+ oracle: {}
13847
+ };
13848
+ class MarketType {
13849
+ }
13850
+ MarketType.SPOT = {
13851
+ spot: {}
13852
+ };
13853
+ MarketType.PERP = {
13854
+ perp: {}
13855
+ };
13856
+ class OrderStatus {
13857
+ }
13858
+ OrderStatus.INIT = {
13859
+ init: {}
13860
+ };
13861
+ OrderStatus.OPEN = {
13862
+ open: {}
13863
+ };
13864
+ OrderStatus.FILLED = {
13865
+ filled: {}
13866
+ };
13867
+ OrderStatus.CANCELED = {
13868
+ canceled: {}
13869
+ };
13870
+ class OrderAction {
13871
+ }
13872
+ OrderAction.PLACE = {
13873
+ place: {}
13874
+ };
13875
+ OrderAction.CANCEL = {
13876
+ cancel: {}
13877
+ };
13878
+ OrderAction.EXPIRE = {
13879
+ expire: {}
13880
+ };
13881
+ OrderAction.FILL = {
13882
+ fill: {}
13883
+ };
13884
+ OrderAction.TRIGGER = {
13885
+ trigger: {}
13886
+ };
13887
+ class OrderActionExplanation {
13888
+ }
13889
+ OrderActionExplanation.NONE = {
13890
+ none: {}
13891
+ };
13892
+ OrderActionExplanation.INSUFFICIENT_FREE_COLLATERAL = {
13893
+ insufficientFreeCollateral: {}
13894
+ };
13895
+ OrderActionExplanation.ORACLE_PRICE_BREACHED_LIMIT_PRICE = {
13896
+ oraclePriceBreachedLimitPrice: {}
13897
+ };
13898
+ OrderActionExplanation.MARKET_ORDER_FILLED_TO_LIMIT_PRICE = {
13899
+ marketOrderFilledToLimitPrice: {}
13900
+ };
13901
+ OrderActionExplanation.ORDER_EXPIRED = {
13902
+ orderExpired: {}
13903
+ };
13904
+ OrderActionExplanation.LIQUIDATION = {
13905
+ liquidation: {}
13906
+ };
13907
+ OrderActionExplanation.ORDER_FILLED_WITH_AMM = {
13908
+ orderFilledWithAmm: {}
13909
+ };
13910
+ OrderActionExplanation.ORDER_FILLED_WITH_AMM_JIT = {
13911
+ orderFilledWithAmmJit: {}
13912
+ };
13913
+ OrderActionExplanation.ORDER_FILLED_WITH_AMM_JIT_LP_SPLIT = {
13914
+ orderFilledWithAmmJitLpSplit: {}
13915
+ };
13916
+ OrderActionExplanation.ORDER_FILLED_WITH_LP_JIT = {
13917
+ orderFilledWithLpJit: {}
13918
+ };
13919
+ OrderActionExplanation.ORDER_FILLED_WITH_MATCH = {
13920
+ orderFilledWithMatch: {}
13921
+ };
13922
+ OrderActionExplanation.ORDER_FILLED_WITH_MATCH_JIT = {
13923
+ orderFilledWithMatchJit: {}
13924
+ };
13925
+ OrderActionExplanation.MARKET_EXPIRED = {
13926
+ marketExpired: {}
13927
+ };
13928
+ OrderActionExplanation.RISK_INCREASING_ORDER = {
13929
+ riskingIncreasingOrder: {}
13930
+ };
13931
+ OrderActionExplanation.ORDER_FILLED_WITH_SERUM = {
13932
+ orderFillWithSerum: {}
13933
+ };
13934
+ OrderActionExplanation.ORDER_FILLED_WITH_OPENBOOK_V2 = {
13935
+ orderFilledWithOpenbookV2: {}
13936
+ };
13937
+ OrderActionExplanation.ORDER_FILLED_WITH_PHOENIX = {
13938
+ orderFillWithPhoenix: {}
13939
+ };
13940
+ OrderActionExplanation.REDUCE_ONLY_ORDER_INCREASED_POSITION = {
13941
+ reduceOnlyOrderIncreasedPosition: {}
13942
+ };
13943
+ OrderActionExplanation.DERISK_LP = {
13944
+ deriskLp: {}
13945
+ };
13946
+ OrderActionExplanation.TRANSFER_PERP_POSITION = {
13947
+ transferPerpPosition: {}
13948
+ };
13949
+ class OrderTriggerCondition {
13950
+ }
13951
+ OrderTriggerCondition.ABOVE = {
13952
+ above: {}
13953
+ };
13954
+ OrderTriggerCondition.BELOW = {
13955
+ below: {}
13956
+ };
13957
+ OrderTriggerCondition.TRIGGERED_ABOVE = {
13958
+ triggeredAbove: {}
13959
+ } // above condition has been triggered
13960
+ ;
13961
+ OrderTriggerCondition.TRIGGERED_BELOW = {
13962
+ triggeredBelow: {}
13963
+ } // below condition has been triggered
13964
+ ;
13965
+ class SpotFulfillmentType {
13966
+ }
13967
+ SpotFulfillmentType.EXTERNAL = {
13968
+ external: {}
13969
+ };
13970
+ SpotFulfillmentType.MATCH = {
13971
+ match: {}
13972
+ };
13973
+ class SpotFulfillmentStatus {
13974
+ }
13975
+ SpotFulfillmentStatus.ENABLED = {
13976
+ enabled: {}
13977
+ };
13978
+ SpotFulfillmentStatus.DISABLED = {
13979
+ disabled: {}
13980
+ };
13981
+ class DepositExplanation {
13982
+ }
13983
+ DepositExplanation.NONE = {
13984
+ none: {}
13985
+ };
13986
+ DepositExplanation.TRANSFER = {
13987
+ transfer: {}
13988
+ };
13989
+ DepositExplanation.BORROW = {
13990
+ borrow: {}
13991
+ };
13992
+ DepositExplanation.REPAY_BORROW = {
13993
+ repayBorrow: {}
13994
+ };
13995
+ class SettlePnlExplanation {
13996
+ }
13997
+ SettlePnlExplanation.NONE = {
13998
+ none: {}
13999
+ };
14000
+ SettlePnlExplanation.EXPIRED_POSITION = {
14001
+ expiredPosition: {}
14002
+ };
14003
+ class SpotFulfillmentConfigStatus {
14004
+ }
14005
+ SpotFulfillmentConfigStatus.ENABLED = {
14006
+ enabled: {}
14007
+ };
14008
+ SpotFulfillmentConfigStatus.DISABLED = {
14009
+ disabled: {}
14010
+ };
14011
+ class StakeAction {
14012
+ }
14013
+ StakeAction.STAKE = {
14014
+ stake: {}
14015
+ };
14016
+ StakeAction.UNSTAKE_REQUEST = {
14017
+ unstakeRequest: {}
14018
+ };
14019
+ StakeAction.UNSTAKE_CANCEL_REQUEST = {
14020
+ unstakeCancelRequest: {}
14021
+ };
14022
+ StakeAction.UNSTAKE = {
14023
+ unstake: {}
14024
+ };
14025
+ StakeAction.UNSTAKE_TRANSFER = {
14026
+ unstakeTransfer: {}
14027
+ };
14028
+ StakeAction.STAKE_TRANSFER = {
14029
+ stakeTransfer: {}
14030
+ };
14031
+ class SettlePnlMode {
14032
+ }
14033
+ SettlePnlMode.TRY_SETTLE = {
14034
+ trySettle: {}
14035
+ };
14036
+ SettlePnlMode.MUST_SETTLE = {
14037
+ mustSettle: {}
14038
+ };
14039
+ function isVariant(object, type) {
14040
+ return object.hasOwnProperty(type);
14041
+ }
14042
+ function isOneOfVariant(object, types) {
14043
+ return types.reduce((result, type)=>{
14044
+ return result || object.hasOwnProperty(type);
14045
+ }, false);
14046
+ }
14047
+ function getVariant(object) {
14048
+ return Object.keys(object)[0];
14049
+ }
14050
+ var TradeSide = /*#__PURE__*/ function(TradeSide) {
14051
+ TradeSide[TradeSide["None"] = 0] = "None";
14052
+ TradeSide[TradeSide["Buy"] = 1] = "Buy";
14053
+ TradeSide[TradeSide["Sell"] = 2] = "Sell";
14054
+ return TradeSide;
14055
+ }({});
14056
+ class LPAction {
14057
+ }
14058
+ LPAction.ADD_LIQUIDITY = {
14059
+ addLiquidity: {}
14060
+ };
14061
+ LPAction.REMOVE_LIQUIDITY = {
14062
+ removeLiquidity: {}
14063
+ };
14064
+ LPAction.SETTLE_LIQUIDITY = {
14065
+ settleLiquidity: {}
14066
+ };
14067
+ LPAction.REMOVE_LIQUIDITY_DERISK = {
14068
+ removeLiquidityDerisk: {}
14069
+ };
14070
+ class LiquidationType {
14071
+ }
14072
+ LiquidationType.LIQUIDATE_PERP = {
14073
+ liquidatePerp: {}
14074
+ };
14075
+ LiquidationType.LIQUIDATE_BORROW_FOR_PERP_PNL = {
14076
+ liquidateBorrowForPerpPnl: {}
14077
+ };
14078
+ LiquidationType.LIQUIDATE_PERP_PNL_FOR_DEPOSIT = {
14079
+ liquidatePerpPnlForDeposit: {}
14080
+ };
14081
+ LiquidationType.PERP_BANKRUPTCY = {
14082
+ perpBankruptcy: {}
14083
+ };
14084
+ LiquidationType.SPOT_BANKRUPTCY = {
14085
+ spotBankruptcy: {}
14086
+ };
14087
+ LiquidationType.LIQUIDATE_SPOT = {
14088
+ liquidateSpot: {}
14089
+ };
14090
+ class PostOnlyParams {
14091
+ }
14092
+ PostOnlyParams.NONE = {
14093
+ none: {}
14094
+ };
14095
+ PostOnlyParams.MUST_POST_ONLY = {
14096
+ mustPostOnly: {}
14097
+ } // Tx fails if order can't be post only
14098
+ ;
14099
+ PostOnlyParams.TRY_POST_ONLY = {
14100
+ tryPostOnly: {}
14101
+ } // Tx succeeds and order not placed if can't be post only
14102
+ ;
14103
+ PostOnlyParams.SLIDE = {
14104
+ slide: {}
14105
+ } // Modify price to be post only if can't be post only
14106
+ ;
14107
+ var ModifyOrderPolicy = /*#__PURE__*/ function(ModifyOrderPolicy) {
14108
+ ModifyOrderPolicy[ModifyOrderPolicy["MustModify"] = 1] = "MustModify";
14109
+ ModifyOrderPolicy[ModifyOrderPolicy["ExcludePreviousFill"] = 2] = "ExcludePreviousFill";
14110
+ return ModifyOrderPolicy;
14111
+ }({});
14112
+ const DefaultOrderParams = {
14113
+ orderType: OrderType.MARKET,
14114
+ marketType: MarketType.PERP,
14115
+ userOrderId: 0,
14116
+ direction: PositionDirection.LONG,
14117
+ baseAssetAmount: ZERO,
14118
+ price: ZERO,
14119
+ marketIndex: 0,
14120
+ reduceOnly: false,
14121
+ postOnly: PostOnlyParams.NONE,
14122
+ immediateOrCancel: false,
14123
+ triggerPrice: null,
14124
+ triggerCondition: OrderTriggerCondition.ABOVE,
14125
+ oraclePriceOffset: null,
14126
+ auctionDuration: null,
14127
+ maxTs: null,
14128
+ auctionStartPrice: null,
14129
+ auctionEndPrice: null
14130
+ };
14131
+ var ReferrerStatus = /*#__PURE__*/ function(ReferrerStatus) {
14132
+ ReferrerStatus[ReferrerStatus["IsReferrer"] = 1] = "IsReferrer";
14133
+ ReferrerStatus[ReferrerStatus["IsReferred"] = 2] = "IsReferred";
14134
+ return ReferrerStatus;
14135
+ }({});
14136
+ var FuelOverflowStatus = /*#__PURE__*/ function(FuelOverflowStatus) {
14137
+ FuelOverflowStatus[FuelOverflowStatus["Exists"] = 1] = "Exists";
14138
+ return FuelOverflowStatus;
14139
+ }({});
14140
+ var PlaceAndTakeOrderSuccessCondition = /*#__PURE__*/ function(PlaceAndTakeOrderSuccessCondition) {
14141
+ PlaceAndTakeOrderSuccessCondition[PlaceAndTakeOrderSuccessCondition["PartialFill"] = 1] = "PartialFill";
14142
+ PlaceAndTakeOrderSuccessCondition[PlaceAndTakeOrderSuccessCondition["FullFill"] = 2] = "FullFill";
14143
+ return PlaceAndTakeOrderSuccessCondition;
14144
+ }({});
14145
+ class SwapReduceOnly {
14146
+ }
14147
+ SwapReduceOnly.In = {
14148
+ in: {}
14149
+ };
14150
+ SwapReduceOnly.Out = {
14151
+ out: {}
14152
+ };
14153
+
14154
+ function readUnsignedBigInt64LE(buffer, offset) {
14155
+ return new BN(buffer.subarray(offset, offset + 8), 10, "le");
14156
+ }
14157
+ function readSignedBigInt64LE(buffer, offset) {
14158
+ const unsignedValue = new BN(buffer.subarray(offset, offset + 8), 10, "le");
14159
+ if (unsignedValue.testn(63)) {
14160
+ const inverted = unsignedValue.notn(64).addn(1);
14161
+ return inverted.neg();
14162
+ } else {
14163
+ return unsignedValue;
14164
+ }
14165
+ }
14166
+ function decodeUser(buffer) {
14167
+ let offset = 8;
14168
+ const authority = new PublicKey(buffer.slice(offset, offset + 32));
14169
+ offset += 32;
14170
+ const delegate = new PublicKey(buffer.slice(offset, offset + 32));
14171
+ offset += 32;
14172
+ const name = [];
14173
+ for(let i = 0; i < 32; i++){
14174
+ name.push(buffer.readUint8(offset + i));
14175
+ }
14176
+ offset += 32;
14177
+ const spotPositions = [];
14178
+ for(let i = 0; i < 8; i++){
14179
+ const scaledBalance = readUnsignedBigInt64LE(buffer, offset);
14180
+ const openOrders = buffer.readUInt8(offset + 35);
14181
+ if (scaledBalance.eq(ZERO) && openOrders === 0) {
14182
+ offset += 40;
14183
+ continue;
14184
+ }
14185
+ offset += 8;
14186
+ const openBids = readSignedBigInt64LE(buffer, offset);
14187
+ offset += 8;
14188
+ const openAsks = readSignedBigInt64LE(buffer, offset);
14189
+ offset += 8;
14190
+ const cumulativeDeposits = readSignedBigInt64LE(buffer, offset);
14191
+ offset += 8;
14192
+ const marketIndex = buffer.readUInt16LE(offset);
14193
+ offset += 2;
14194
+ const balanceTypeNum = buffer.readUInt8(offset);
14195
+ let balanceType;
14196
+ if (balanceTypeNum === 0) {
14197
+ balanceType = SpotBalanceType.DEPOSIT;
14198
+ } else {
14199
+ balanceType = SpotBalanceType.BORROW;
14200
+ }
14201
+ offset += 6;
14202
+ spotPositions.push({
14203
+ scaledBalance,
14204
+ openBids,
14205
+ openAsks,
14206
+ cumulativeDeposits,
14207
+ marketIndex,
14208
+ balanceType,
14209
+ openOrders
14210
+ });
14211
+ }
14212
+ const perpPositions = [];
14213
+ for(let i = 0; i < 8; i++){
14214
+ const baseAssetAmount = readSignedBigInt64LE(buffer, offset + 8);
14215
+ const quoteAssetAmount = readSignedBigInt64LE(buffer, offset + 16);
14216
+ const lpShares = readUnsignedBigInt64LE(buffer, offset + 64);
14217
+ const openOrders = buffer.readUInt8(offset + 94);
14218
+ if (baseAssetAmount.eq(ZERO) && openOrders === 0 && quoteAssetAmount.eq(ZERO) && lpShares.eq(ZERO)) {
14219
+ offset += 96;
14220
+ continue;
14221
+ }
14222
+ const lastCumulativeFundingRate = readSignedBigInt64LE(buffer, offset);
14223
+ offset += 24;
14224
+ const quoteBreakEvenAmount = readSignedBigInt64LE(buffer, offset);
14225
+ offset += 8;
14226
+ const quoteEntryAmount = readSignedBigInt64LE(buffer, offset);
14227
+ offset += 8;
14228
+ const openBids = readSignedBigInt64LE(buffer, offset);
14229
+ offset += 8;
14230
+ const openAsks = readSignedBigInt64LE(buffer, offset);
14231
+ offset += 8;
14232
+ const settledPnl = readSignedBigInt64LE(buffer, offset);
14233
+ offset += 16;
14234
+ const lastBaseAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
14235
+ offset += 8;
14236
+ const lastQuoteAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
14237
+ offset += 8;
14238
+ const remainderBaseAssetAmount = buffer.readInt32LE(offset);
14239
+ offset += 4;
14240
+ const marketIndex = buffer.readUInt16LE(offset);
14241
+ offset += 3;
14242
+ const perLpBase = buffer.readUInt8(offset);
14243
+ offset += 1;
14244
+ perpPositions.push({
14245
+ lastCumulativeFundingRate,
14246
+ baseAssetAmount,
14247
+ quoteAssetAmount,
14248
+ quoteBreakEvenAmount,
14249
+ quoteEntryAmount,
14250
+ openBids,
14251
+ openAsks,
14252
+ settledPnl,
14253
+ lpShares,
14254
+ lastBaseAssetAmountPerLp,
14255
+ lastQuoteAssetAmountPerLp,
14256
+ remainderBaseAssetAmount,
14257
+ marketIndex,
14258
+ openOrders,
14259
+ perLpBase
14260
+ });
14261
+ }
14262
+ const orders = [];
14263
+ for(let i = 0; i < 32; i++){
14264
+ // skip order if it's not open
14265
+ if (buffer.readUint8(offset + 82) !== 1) {
14266
+ offset += 96;
14267
+ continue;
14268
+ }
14269
+ const slot = readUnsignedBigInt64LE(buffer, offset);
14270
+ offset += 8;
14271
+ const price = readUnsignedBigInt64LE(buffer, offset);
14272
+ offset += 8;
14273
+ const baseAssetAmount = readUnsignedBigInt64LE(buffer, offset);
14274
+ offset += 8;
14275
+ const baseAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
14276
+ offset += 8;
14277
+ const quoteAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
14278
+ offset += 8;
14279
+ const triggerPrice = readUnsignedBigInt64LE(buffer, offset);
14280
+ offset += 8;
14281
+ const auctionStartPrice = readSignedBigInt64LE(buffer, offset);
14282
+ offset += 8;
14283
+ const auctionEndPrice = readSignedBigInt64LE(buffer, offset);
14284
+ offset += 8;
14285
+ const maxTs = readSignedBigInt64LE(buffer, offset);
14286
+ offset += 8;
14287
+ const oraclePriceOffset = buffer.readInt32LE(offset);
14288
+ offset += 4;
14289
+ const orderId = buffer.readUInt32LE(offset);
14290
+ offset += 4;
14291
+ const marketIndex = buffer.readUInt16LE(offset);
14292
+ offset += 2;
14293
+ const orderStatusNum = buffer.readUInt8(offset);
14294
+ let status = OrderStatus.INIT;
14295
+ if (orderStatusNum === 0) {
14296
+ status = OrderStatus.INIT;
14297
+ } else if (orderStatusNum === 1) {
14298
+ status = OrderStatus.OPEN;
14299
+ } else if (orderStatusNum === 2) {
14300
+ status = OrderStatus.FILLED;
14301
+ } else if (orderStatusNum === 3) {
14302
+ status = OrderStatus.CANCELED;
14303
+ }
14304
+ offset += 1;
14305
+ const orderTypeNum = buffer.readUInt8(offset);
14306
+ let orderType = OrderType.MARKET;
14307
+ if (orderTypeNum === 0) {
14308
+ orderType = OrderType.MARKET;
14309
+ } else if (orderTypeNum === 1) {
14310
+ orderType = OrderType.LIMIT;
14311
+ } else if (orderTypeNum === 2) {
14312
+ orderType = OrderType.TRIGGER_MARKET;
14313
+ } else if (orderTypeNum === 3) {
14314
+ orderType = OrderType.TRIGGER_LIMIT;
14315
+ } else if (orderTypeNum === 4) {
14316
+ orderType = OrderType.ORACLE;
14317
+ }
14318
+ offset += 1;
14319
+ const marketTypeNum = buffer.readUInt8(offset);
14320
+ let marketType;
14321
+ if (marketTypeNum === 0) {
14322
+ marketType = MarketType.SPOT;
14323
+ } else {
14324
+ marketType = MarketType.PERP;
14325
+ }
14326
+ offset += 1;
14327
+ const userOrderId = buffer.readUint8(offset);
14328
+ offset += 1;
14329
+ const existingPositionDirectionNum = buffer.readUInt8(offset);
14330
+ let existingPositionDirection;
14331
+ if (existingPositionDirectionNum === 0) {
14332
+ existingPositionDirection = PositionDirection.LONG;
14333
+ } else {
14334
+ existingPositionDirection = PositionDirection.SHORT;
14335
+ }
14336
+ offset += 1;
14337
+ const positionDirectionNum = buffer.readUInt8(offset);
14338
+ let direction;
14339
+ if (positionDirectionNum === 0) {
14340
+ direction = PositionDirection.LONG;
14341
+ } else {
14342
+ direction = PositionDirection.SHORT;
14343
+ }
14344
+ offset += 1;
14345
+ const reduceOnly = buffer.readUInt8(offset) === 1;
14346
+ offset += 1;
14347
+ const postOnly = buffer.readUInt8(offset) === 1;
14348
+ offset += 1;
14349
+ const immediateOrCancel = buffer.readUInt8(offset) === 1;
14350
+ offset += 1;
14351
+ const triggerConditionNum = buffer.readUInt8(offset);
14352
+ let triggerCondition = OrderTriggerCondition.ABOVE;
14353
+ if (triggerConditionNum === 0) {
14354
+ triggerCondition = OrderTriggerCondition.ABOVE;
14355
+ } else if (triggerConditionNum === 1) {
14356
+ triggerCondition = OrderTriggerCondition.BELOW;
14357
+ } else if (triggerConditionNum === 2) {
14358
+ triggerCondition = OrderTriggerCondition.TRIGGERED_ABOVE;
14359
+ } else if (triggerConditionNum === 3) {
14360
+ triggerCondition = OrderTriggerCondition.TRIGGERED_BELOW;
14361
+ }
14362
+ offset += 1;
14363
+ const auctionDuration = buffer.readUInt8(offset);
14364
+ offset += 1;
14365
+ const postedSlotTail = buffer.readUint8(offset);
14366
+ offset += 1;
14367
+ const bitFlags = buffer.readUint8(offset);
14368
+ offset += 1;
14369
+ offset += 1; // padding
14370
+ orders.push({
14371
+ slot,
14372
+ price,
14373
+ baseAssetAmount,
14374
+ quoteAssetAmount: undefined,
14375
+ baseAssetAmountFilled,
14376
+ quoteAssetAmountFilled,
14377
+ triggerPrice,
14378
+ auctionStartPrice,
14379
+ auctionEndPrice,
14380
+ maxTs,
14381
+ oraclePriceOffset,
14382
+ orderId,
14383
+ marketIndex,
14384
+ status,
14385
+ orderType,
14386
+ marketType,
14387
+ userOrderId,
14388
+ existingPositionDirection,
14389
+ direction,
14390
+ reduceOnly,
14391
+ postOnly,
14392
+ immediateOrCancel,
14393
+ triggerCondition,
14394
+ auctionDuration,
14395
+ bitFlags,
14396
+ postedSlotTail
14397
+ });
14398
+ }
14399
+ const lastAddPerpLpSharesTs = readSignedBigInt64LE(buffer, offset);
14400
+ offset += 8;
14401
+ const totalDeposits = readUnsignedBigInt64LE(buffer, offset);
14402
+ offset += 8;
14403
+ const totalWithdraws = readUnsignedBigInt64LE(buffer, offset);
14404
+ offset += 8;
14405
+ const totalSocialLoss = readUnsignedBigInt64LE(buffer, offset);
14406
+ offset += 8;
14407
+ const settledPerpPnl = readSignedBigInt64LE(buffer, offset);
14408
+ offset += 8;
14409
+ const cumulativeSpotFees = readSignedBigInt64LE(buffer, offset);
14410
+ offset += 8;
14411
+ const cumulativePerpFunding = readSignedBigInt64LE(buffer, offset);
14412
+ offset += 8;
14413
+ const liquidationMarginFreed = readUnsignedBigInt64LE(buffer, offset);
14414
+ offset += 8;
14415
+ const lastActiveSlot = readUnsignedBigInt64LE(buffer, offset);
14416
+ offset += 8;
14417
+ const nextOrderId = buffer.readUInt32LE(offset);
14418
+ offset += 4;
14419
+ const maxMarginRatio = buffer.readUInt32LE(offset);
14420
+ offset += 4;
14421
+ const nextLiquidationId = buffer.readUInt16LE(offset);
14422
+ offset += 2;
14423
+ const subAccountId = buffer.readUInt16LE(offset);
14424
+ offset += 2;
14425
+ const status = buffer.readUInt8(offset);
14426
+ offset += 1;
14427
+ const isMarginTradingEnabled = buffer.readUInt8(offset) === 1;
14428
+ offset += 1;
14429
+ const idle = buffer.readUInt8(offset) === 1;
14430
+ offset += 1;
14431
+ const openOrders = buffer.readUInt8(offset);
14432
+ offset += 1;
14433
+ const hasOpenOrder = buffer.readUInt8(offset) === 1;
14434
+ offset += 1;
14435
+ const openAuctions = buffer.readUInt8(offset);
14436
+ offset += 1;
14437
+ const hasOpenAuction = buffer.readUInt8(offset) === 1;
14438
+ offset += 1;
14439
+ let marginMode;
14440
+ const marginModeNum = buffer.readUInt8(offset);
14441
+ if (marginModeNum === 0) {
14442
+ marginMode = MarginMode.DEFAULT;
14443
+ } else {
14444
+ marginMode = MarginMode.HIGH_LEVERAGE;
14445
+ }
14446
+ offset += 1;
14447
+ const poolId = buffer.readUint8(offset);
14448
+ offset += 1;
14449
+ offset += 3; // padding
14450
+ const lastFuelBonusUpdateTs = buffer.readUint32LE(offset);
14451
+ offset += 4;
14452
+ return {
14453
+ authority,
14454
+ delegate,
14455
+ name,
14456
+ spotPositions,
14457
+ perpPositions,
14458
+ orders,
14459
+ lastAddPerpLpSharesTs,
14460
+ totalDeposits,
14461
+ totalWithdraws,
14462
+ totalSocialLoss,
14463
+ settledPerpPnl,
14464
+ cumulativeSpotFees,
14465
+ cumulativePerpFunding,
14466
+ liquidationMarginFreed,
14467
+ lastActiveSlot,
14468
+ nextOrderId,
14469
+ maxMarginRatio,
14470
+ nextLiquidationId,
14471
+ subAccountId,
14472
+ status,
14473
+ isMarginTradingEnabled,
14474
+ idle,
14475
+ openOrders,
14476
+ hasOpenOrder,
14477
+ openAuctions,
14478
+ hasOpenAuction,
14479
+ marginMode,
14480
+ poolId,
14481
+ lastFuelBonusUpdateTs
14482
+ };
14483
+ }
14484
+
14485
+ const DRIFT_SIGNER = new PublicKey("JCNCMFXo5M5qwUPg2Utu1u6YWp3MbygxqBsBeXXJfrw");
13577
14486
  const DRIFT_MARGIN_PRECISION = 10000;
13578
14487
  class DriftClient {
13579
14488
  /*
@@ -13598,83 +14507,268 @@ class DriftClient {
13598
14507
  const tx = await this.deleteUserTx(new PublicKey(statePda), subAccountId, txOptions);
13599
14508
  return await this.base.sendAndConfirm(tx);
13600
14509
  }
13601
- async deposit(statePda, amount, marketIndex = 1, subAccountId = 0, marketConfigs, txOptions = {}) {
13602
- const tx = await this.depositTx(new PublicKey(statePda), amount, marketIndex, subAccountId, marketConfigs, txOptions);
14510
+ async deposit(statePda, amount, marketIndex = 1, subAccountId = 0, txOptions = {}) {
14511
+ const tx = await this.depositTx(new PublicKey(statePda), amount, marketIndex, subAccountId, txOptions);
13603
14512
  return await this.base.sendAndConfirm(tx);
13604
14513
  }
13605
- async withdraw(statePda, amount, marketIndex = 1, subAccountId = 0, marketConfigs, txOptions = {}) {
13606
- const tx = await this.withdrawTx(new PublicKey(statePda), amount, marketIndex, subAccountId, marketConfigs, txOptions);
14514
+ async withdraw(statePda, amount, marketIndex = 1, subAccountId = 0, txOptions = {}) {
14515
+ const tx = await this.withdrawTx(new PublicKey(statePda), amount, marketIndex, subAccountId, txOptions);
13607
14516
  return await this.base.sendAndConfirm(tx);
13608
14517
  }
13609
- async placeOrder(statePda, orderParams, subAccountId = 0, marketConfigs, txOptions = {}) {
13610
- const tx = await this.placeOrderTx(new PublicKey(statePda), orderParams, subAccountId, marketConfigs, txOptions);
14518
+ async placeOrder(statePda, orderParams, subAccountId = 0, txOptions = {}) {
14519
+ const tx = await this.placeOrderTx(new PublicKey(statePda), orderParams, subAccountId, txOptions);
13611
14520
  return await this.base.sendAndConfirm(tx);
13612
14521
  }
13613
- async modifyOrder(statePda, modifyOrderParams, subAccountId = 0, marketConfigs, txOptions = {}) {
13614
- const tx = await this.modifyOrderTx(new PublicKey(statePda), modifyOrderParams, subAccountId, marketConfigs, txOptions);
14522
+ async modifyOrder(statePda, modifyOrderParams, subAccountId = 0, txOptions = {}) {
14523
+ const tx = await this.modifyOrderTx(new PublicKey(statePda), modifyOrderParams, subAccountId, txOptions);
13615
14524
  return await this.base.sendAndConfirm(tx);
13616
14525
  }
13617
- async cancelOrders(statePda, marketType, marketIndex, direction, subAccountId = 0, marketConfigs, txOptions = {}) {
13618
- const tx = await this.cancelOrdersTx(new PublicKey(statePda), marketType, marketIndex, direction, subAccountId, marketConfigs, txOptions);
14526
+ async cancelOrders(statePda, marketType, marketIndex, direction, subAccountId = 0, txOptions = {}) {
14527
+ const tx = await this.cancelOrdersTx(new PublicKey(statePda), marketType, marketIndex, direction, subAccountId, txOptions);
13619
14528
  return await this.base.sendAndConfirm(tx);
13620
14529
  }
13621
- async cancelOrdersByIds(statePda, orderIds, subAccountId = 0, marketConfigs, txOptions = {}) {
13622
- const tx = await this.cancelOrdersByIdsTx(new PublicKey(statePda), orderIds, subAccountId, marketConfigs, txOptions);
14530
+ async cancelOrdersByIds(statePda, orderIds, subAccountId = 0, txOptions = {}) {
14531
+ const tx = await this.cancelOrdersByIdsTx(new PublicKey(statePda), orderIds, subAccountId, txOptions);
13623
14532
  return await this.base.sendAndConfirm(tx);
13624
14533
  }
13625
- async settlePnl(statePda, marketIndex, subAccountId = 0, marketConfigs, txOptions = {}) {
13626
- const tx = await this.settlePnlTx(new PublicKey(statePda), marketIndex, subAccountId, marketConfigs, txOptions);
14534
+ async settlePnl(statePda, marketIndex, subAccountId = 0, txOptions = {}) {
14535
+ const tx = await this.settlePnlTx(new PublicKey(statePda), marketIndex, subAccountId, txOptions);
13627
14536
  return await this.base.sendAndConfirm(tx);
13628
14537
  }
13629
- async priceDrift(statePda, marketConfigs, priceDenom, txOptions = {}) {
13630
- const tx = await this.priceDriftTx(new PublicKey(statePda), marketConfigs, priceDenom, txOptions);
14538
+ async priceDrift(statePda, priceDenom, txOptions = {}) {
14539
+ const tx = await this.priceDriftTx(new PublicKey(statePda), priceDenom, txOptions);
13631
14540
  return await this.base.sendAndConfirm(tx);
13632
14541
  }
13633
- /*
13634
- * Utils
13635
- */ getUser(statePda, subAccountId = 0) {
14542
+ getGlamReferrerPdas() {
14543
+ return {
14544
+ user: this.getUserPda(GLAM_REFERRER, 0),
14545
+ userStats: this.getUserStatsPda(GLAM_REFERRER)
14546
+ };
14547
+ }
14548
+ parsePerpMarket(data) {
14549
+ const marketPda = new PublicKey(data.subarray(8, 40));
14550
+ const oracle = new PublicKey(data.subarray(40, 72));
14551
+ const name = this.charsToName(data.subarray(1000, 1032));
14552
+ const oralceEnum = data.subarray(926, 927).readUint8();
14553
+ const oracleSource = OracleSource.get(oralceEnum);
14554
+ const marketIndex = data.subarray(1160, 1162).readUint16LE();
14555
+ return {
14556
+ name,
14557
+ marketPda,
14558
+ marketIndex,
14559
+ oracle,
14560
+ oracleSource
14561
+ };
14562
+ }
14563
+ parseSpotMarket(data) {
14564
+ const marketPda = new PublicKey(data.subarray(8, 40));
14565
+ const oracle = new PublicKey(data.subarray(40, 72));
14566
+ const mint = new PublicKey(data.subarray(72, 104));
14567
+ const vault = new PublicKey(data.subarray(104, 136));
14568
+ const name = this.charsToName(data.subarray(136, 168));
14569
+ const cumulativeDepositInterest = new BN(data.subarray(464, 480), "le");
14570
+ const cumulativeBorrowInterest = new BN(data.subarray(480, 496), "le");
14571
+ const decimals = data.subarray(680, 684).readUint32LE();
14572
+ const marketIndex = data.subarray(684, 686).readUint16LE();
14573
+ const oralceEnum = data.subarray(687, 688).readUint8();
14574
+ const oracleSource = OracleSource.get(oralceEnum);
14575
+ const tokenProgram = data.subarray(734, 735).readUint8() == 0 ? TOKEN_PROGRAM_ID : TOKEN_2022_PROGRAM_ID;
14576
+ return {
14577
+ name,
14578
+ marketIndex,
14579
+ marketPda,
14580
+ oracle,
14581
+ oracleSource,
14582
+ vault,
14583
+ mint,
14584
+ decimals,
14585
+ tokenProgram,
14586
+ cumulativeDepositInterest,
14587
+ cumulativeBorrowInterest
14588
+ };
14589
+ }
14590
+ async calcSpotBalance(marketIndex, scaledBalance, scaledBalanceType) {
14591
+ const { decimals, cumulativeDepositInterest, cumulativeBorrowInterest } = await this.fetchAndParseSpotMarket(marketIndex);
14592
+ const precisionAdjustment = new BN(10 ** (19 - decimals));
14593
+ let interest = cumulativeDepositInterest;
14594
+ if (scaledBalanceType === SpotBalanceType.BORROW) {
14595
+ interest = cumulativeBorrowInterest;
14596
+ }
14597
+ const balance = scaledBalance.mul(interest).div(precisionAdjustment);
14598
+ const amount = scaledBalanceType === SpotBalanceType.BORROW ? balance.neg().toNumber() : balance.toNumber();
14599
+ const uiAmount = amount / 10 ** decimals;
14600
+ return {
14601
+ amount,
14602
+ uiAmount
14603
+ };
14604
+ }
14605
+ getDriftUserPdas(statePda, subAccountId = 0) {
13636
14606
  const vault = this.base.getVaultPda(new PublicKey(statePda));
13637
- return [
13638
- getUserAccountPublicKeySync(DRIFT_PROGRAM_ID, vault, subAccountId),
13639
- getUserStatsAccountPublicKey(DRIFT_PROGRAM_ID, vault)
13640
- ];
14607
+ return {
14608
+ user: this.getUserPda(vault, subAccountId),
14609
+ userStats: this.getUserStatsPda(vault)
14610
+ };
13641
14611
  }
13642
- async fetchMarketConfigs() {
13643
- const response = await fetch("https://api.glam.systems/v0/drift/market_configs/");
13644
- if (!response.ok) {
13645
- throw new Error(`Failed to fetch market configs: ${response.status}`);
14612
+ get driftStatePda() {
14613
+ return PublicKey.findProgramAddressSync([
14614
+ Buffer.from("drift_state")
14615
+ ], DRIFT_PROGRAM_ID)[0];
14616
+ }
14617
+ async fetchAndParseSpotMarket(marketIndex) {
14618
+ const markets = await this.fetchAndParseSpotMarkets([
14619
+ marketIndex
14620
+ ]);
14621
+ if (!markets || markets.length === 0) {
14622
+ throw new Error(`Spot market not found at index ${marketIndex}`);
13646
14623
  }
13647
- const data = await response.json();
13648
- return data;
14624
+ return markets[0];
14625
+ }
14626
+ async fetchAndParseSpotMarkets(marketIndexes) {
14627
+ const indexesToFetch = marketIndexes.filter((marketIndex)=>!this.spotMarkets.has(marketIndex));
14628
+ if (indexesToFetch.length > 0) {
14629
+ console.log("Fetching spot markets:", indexesToFetch);
14630
+ const marketPdas = indexesToFetch.map((marketIndex)=>this.getMarketPda(MarketType.SPOT, marketIndex));
14631
+ const accounts = await this.base.provider.connection.getMultipleAccountsInfo(marketPdas);
14632
+ accounts.forEach((account)=>{
14633
+ if (account) {
14634
+ const spotMarket = this.parseSpotMarket(account.data);
14635
+ this.spotMarkets.set(spotMarket.marketIndex, spotMarket);
14636
+ }
14637
+ });
14638
+ }
14639
+ // At this point this.spotMarkets has all the requested markets
14640
+ return marketIndexes.map((marketIndex)=>this.spotMarkets.get(marketIndex)).filter((m)=>m);
13649
14641
  }
13650
- async fetchGlamDriftUser(glamState, subAccountId = 0) {
13651
- const vault = this.base.getVaultPda(new PublicKey(glamState));
13652
- const response = await fetch(`https://api.glam.systems/v0/drift/user?authority=${vault.toBase58()}&accountId=${subAccountId}`);
13653
- const data = await response.json();
13654
- if (!data) {
13655
- throw new Error("Failed to fetch drift user.");
14642
+ async fetchAndParsePerpMarket(marketIndex) {
14643
+ const markets = await this.fetchAndParsePerpMarkets([
14644
+ marketIndex
14645
+ ]);
14646
+ if (!markets || markets.length === 0) {
14647
+ throw new Error(`Perp market not found at index ${marketIndex}`);
13656
14648
  }
13657
- return data;
14649
+ return markets[0];
14650
+ }
14651
+ async fetchAndParsePerpMarkets(marketIndexes) {
14652
+ const indexesToFetch = marketIndexes.filter((marketIndex)=>!this.perpMarkets.has(marketIndex));
14653
+ if (indexesToFetch.length > 0) {
14654
+ console.log("Fetching perp markets:", indexesToFetch);
14655
+ const marketPdas = marketIndexes.map((marketIndex)=>this.getMarketPda(MarketType.PERP, marketIndex));
14656
+ const accounts = await this.base.provider.connection.getMultipleAccountsInfo(marketPdas);
14657
+ accounts.forEach((account)=>{
14658
+ if (account) {
14659
+ const perpMarket = this.parsePerpMarket(account.data);
14660
+ this.perpMarkets.set(perpMarket.marketIndex, perpMarket);
14661
+ }
14662
+ });
14663
+ } else {
14664
+ console.log("Requested perp markets already cached:", marketIndexes);
14665
+ }
14666
+ return marketIndexes.map((marketIndex)=>this.perpMarkets.get(marketIndex)).filter((m)=>m);
13658
14667
  }
13659
- async getPositions(statePda, subAccountId = 0) {
13660
- const { spotPositions, perpPositions } = await this.fetchGlamDriftUser(new PublicKey(statePda), subAccountId);
14668
+ async fetchMarketConfigs() {
14669
+ // const response = await fetch(
14670
+ // "https://api.glam.systems/v0/drift/market_configs/",
14671
+ // );
14672
+ // if (!response.ok) {
14673
+ // throw new Error(`Failed to fetch market configs: ${response.status}`);
14674
+ // }
14675
+ // const data = await response.json();
14676
+ // const { orderConstants, perp, spot } = data;
14677
+ // // Transform perp market from API to `PerpMarket` type
14678
+ // const perpMarkets = perp.map((m: any) => ({
14679
+ // marketIndex: m.marketIndex,
14680
+ // marketPda: m.marketPDA,
14681
+ // oracle: new PublicKey(m.oracle),
14682
+ // }));
14683
+ // // Transform spot market from API to `SpotMarket` type
14684
+ // const spotMarkets = spot.map((m: any) => ({
14685
+ // marketIndex: m.marketIndex,
14686
+ // marketPda: m.marketPDA,
14687
+ // oracle: new PublicKey(m.oracle),
14688
+ // mint: new PublicKey(m.mint),
14689
+ // vault: new PublicKey(m.vaultPDA),
14690
+ // decimals: m.decimals,
14691
+ // }));
14692
+ if (!this.marketConfigs) {
14693
+ const perpMarkets = await this.fetchAndParsePerpMarkets(Array.from(Array(100).keys()));
14694
+ const spotMarkets = await this.fetchAndParseSpotMarkets(Array.from(Array(100).keys()));
14695
+ this.marketConfigs = {
14696
+ orderConstants: {
14697
+ perpBaseScale: 9,
14698
+ quoteScale: 6
14699
+ },
14700
+ perpMarkets,
14701
+ spotMarkets
14702
+ };
14703
+ }
14704
+ return this.marketConfigs;
14705
+ }
14706
+ // public async fetchGlamDriftUser(
14707
+ // glamState: PublicKey | string,
14708
+ // subAccountId: number = 0,
14709
+ // ): Promise<GlamDriftUser> {
14710
+ // const vault = this.base.getVaultPda(new PublicKey(glamState));
14711
+ // const response = await fetch(
14712
+ // `https://api.glam.systems/v0/drift/user?authority=${vault.toBase58()}&accountId=${subAccountId}`,
14713
+ // );
14714
+ // const data = await response.json();
14715
+ // if (!data) {
14716
+ // throw new Error("Failed to fetch drift user.");
14717
+ // }
14718
+ // return data as GlamDriftUser;
14719
+ // }
14720
+ charsToName(chars) {
14721
+ return String.fromCharCode(...chars).replace(/\0/g, "").trim();
14722
+ }
14723
+ async fetchDriftUser(statePda, subAccountId = 0) {
14724
+ const { user } = this.getDriftUserPdas(new PublicKey(statePda), subAccountId);
14725
+ const accountInfo = await this.base.provider.connection.getAccountInfo(user);
14726
+ if (!accountInfo) {
14727
+ return null;
14728
+ }
14729
+ const { delegate, name, spotPositions, marginMode, perpPositions, isMarginTradingEnabled, maxMarginRatio, orders } = decodeUser(accountInfo.data);
14730
+ // Prefetch market configs
14731
+ const marketConfigs = await this.fetchMarketConfigs();
14732
+ const spotPositionsExt = await Promise.all(spotPositions.map(async (p)=>{
14733
+ const { amount, uiAmount } = await this.calcSpotBalance(p.marketIndex, p.scaledBalance, p.balanceType);
14734
+ const spotMarket = marketConfigs.spotMarkets.find((m)=>m.marketIndex === p.marketIndex);
14735
+ return {
14736
+ ...p,
14737
+ amount,
14738
+ uiAmount,
14739
+ mint: spotMarket.mint,
14740
+ decimals: spotMarket.decimals,
14741
+ marketName: spotMarket.name
14742
+ };
14743
+ }));
13661
14744
  return {
13662
- spotPositions,
13663
- perpPositions
14745
+ delegate,
14746
+ name: this.charsToName(name),
14747
+ spotPositions: spotPositionsExt,
14748
+ perpPositions,
14749
+ orders,
14750
+ marginMode,
14751
+ subAccountId,
14752
+ isMarginTradingEnabled,
14753
+ maxMarginRatio
13664
14754
  };
13665
14755
  }
14756
+ // async getPositions(statePda: PublicKey | string, subAccountId: number = 0) {
14757
+ // const driftUser = await this.fetchDriftUser(
14758
+ // new PublicKey(statePda),
14759
+ // subAccountId,
14760
+ // );
14761
+ // if (!driftUser) {
14762
+ // return { spotPositions: [], perpPositions: [] };
14763
+ // }
14764
+ // const marketConfigs = await this.fetchMarketConfigs();
14765
+ // const { spotPositions, perpPositions } = driftUser;
14766
+ // return { spotPositions, perpPositions };
14767
+ // }
13666
14768
  async fetchPolicyConfig(glamState) {
13667
- let driftUserAccount;
13668
- if (glamState && glamState.id) {
13669
- const [driftUserAddress] = this.getUser(glamState.id);
13670
- const connection = this.base.provider.connection;
13671
- const info = await connection.getAccountInfo(driftUserAddress, connection.commitment);
13672
- if (info) {
13673
- driftUserAccount = decodeUser(info.data);
13674
- }
13675
- }
14769
+ const driftUserAccount = glamState && glamState.id && await this.fetchDriftUser(glamState.id);
13676
14770
  let delegate = driftUserAccount?.delegate;
13677
- if (delegate && delegate.equals(new PublicKey(0))) {
14771
+ if (delegate && delegate.equals(PublicKey.default)) {
13678
14772
  delegate = undefined;
13679
14773
  }
13680
14774
  return {
@@ -13687,8 +14781,12 @@ class DriftClient {
13687
14781
  driftMarketIndexesSpot: glamState?.driftMarketIndexesSpot || []
13688
14782
  };
13689
14783
  }
13690
- async composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex) {
13691
- const { spotPositions, perpPositions } = await this.getPositions(glamState, subAccountId);
14784
+ async composeRemainingAccounts(glamState, subAccountId, marketType, marketIndex) {
14785
+ const driftUser = await this.fetchDriftUser(glamState, subAccountId);
14786
+ if (!driftUser) {
14787
+ throw new Error("Drift user not found");
14788
+ }
14789
+ const { spotPositions, perpPositions } = driftUser;
13692
14790
  const spotMarketIndexes = spotPositions.map((p)=>p.marketIndex);
13693
14791
  const perpMarketIndexes = perpPositions.map((p)=>p.marketIndex);
13694
14792
  // Note that marketIndex is could be 0, need to explicitly check undefined
@@ -13703,10 +14801,13 @@ class DriftClient {
13703
14801
  spotMarketIndexes.push(0);
13704
14802
  }
13705
14803
  }
13706
- const oracles = spotMarketIndexes.map((i)=>marketConfigs.spot[i].oracle).concat(perpMarketIndexes.map((i)=>marketConfigs.perp[i].oracle));
13707
- const markets = spotMarketIndexes.map((i)=>marketConfigs.spot[i].marketPDA).concat(perpMarketIndexes.map((i)=>marketConfigs.perp[i].marketPDA));
13708
- console.log("[composeRemainingAccounts] markets:", markets);
13709
- console.log("[composeRemainingAccounts] oracles:", oracles);
14804
+ const spotMarkets = await this.fetchAndParseSpotMarkets(spotMarketIndexes);
14805
+ const perpMarkets = await this.fetchAndParsePerpMarkets(perpMarketIndexes);
14806
+ console.log("[composeRemainingAccounts] perpMarkets:", perpMarkets);
14807
+ const oracles = spotMarkets.map((m)=>m.oracle).concat(perpMarkets.map((m)=>m.oracle));
14808
+ const markets = spotMarkets.map((m)=>m.marketPda).concat(perpMarkets.map((m)=>m.marketPda));
14809
+ console.log("[composeRemainingAccounts] markets:", markets.map((m)=>m.toBase58()));
14810
+ console.log("[composeRemainingAccounts] oracles:", oracles.map((o)=>o.toBase58()));
13710
14811
  return oracles.map((o)=>({
13711
14812
  pubkey: new PublicKey(o),
13712
14813
  isWritable: false,
@@ -13718,35 +14819,44 @@ class DriftClient {
13718
14819
  })));
13719
14820
  }
13720
14821
  async initializeUserStatsIx(glamState, glamSigner) {
13721
- const [_, userStats] = this.getUser(glamState);
13722
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
14822
+ const { userStats } = this.getDriftUserPdas(glamState);
13723
14823
  // @ts-ignore
13724
14824
  return await this.base.program.methods.driftInitializeUserStats().accounts({
13725
14825
  glamState,
13726
14826
  glamSigner,
13727
- state,
14827
+ state: this.driftStatePda,
13728
14828
  userStats
13729
14829
  }).instruction();
13730
14830
  }
13731
14831
  async initializeUserIx(glamState, glamSigner, subAccountId) {
13732
14832
  const name = `GLAM *.+ ${subAccountId}`.split("").map((char)=>char.charCodeAt(0)).concat(Array(24).fill(0));
13733
- const [user, userStats] = this.getUser(glamState, subAccountId);
13734
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
14833
+ const { user, userStats } = this.getDriftUserPdas(glamState, subAccountId);
14834
+ const { user: referrer, userStats: referrerStats } = this.getGlamReferrerPdas();
14835
+ const remainingAccounts = [
14836
+ {
14837
+ pubkey: referrer,
14838
+ isWritable: true,
14839
+ isSigner: false
14840
+ },
14841
+ {
14842
+ pubkey: referrerStats,
14843
+ isWritable: true,
14844
+ isSigner: false
14845
+ }
14846
+ ];
13735
14847
  return await this.base.program.methods.driftInitializeUser(subAccountId, name).accounts({
13736
14848
  glamState,
13737
14849
  user,
13738
14850
  userStats,
13739
- state,
14851
+ state: this.driftStatePda,
13740
14852
  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();
14853
+ }).remainingAccounts(remainingAccounts).instruction();
13744
14854
  }
13745
14855
  async initializeTx(glamState, subAccountId = 0, txOptions = {}) {
13746
14856
  const glamSigner = txOptions.signer || this.base.getSigner();
13747
14857
  const tx = new Transaction();
13748
14858
  // Create userStats account if it doesn't exist
13749
- const [_, userStats] = this.getUser(glamState);
14859
+ const { userStats } = this.getDriftUserPdas(glamState);
13750
14860
  const userStatsInfo = await this.base.provider.connection.getAccountInfo(userStats);
13751
14861
  if (!userStatsInfo) {
13752
14862
  tx.add(await this.initializeUserStatsIx(glamState, glamSigner));
@@ -13757,7 +14867,7 @@ class DriftClient {
13757
14867
  }
13758
14868
  async updateUserCustomMarginRatioIx(glamState, maxLeverage, subAccountId = 0, txOptions = {}) {
13759
14869
  const glamSigner = txOptions.signer || this.base.getSigner();
13760
- const [user] = this.getUser(glamState, subAccountId);
14870
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
13761
14871
  // https://github.com/drift-labs/protocol-v2/blob/babed162b08b1fe34e49a81c5aa3e4ec0a88ecdf/programs/drift/src/math/constants.rs#L183-L184
13762
14872
  const marginRatio = DRIFT_MARGIN_PRECISION / maxLeverage;
13763
14873
  return await this.base.program.methods.driftUpdateUserCustomMarginRatio(subAccountId, marginRatio).accounts({
@@ -13772,7 +14882,7 @@ class DriftClient {
13772
14882
  }
13773
14883
  async updateUserMarginTradingEnabledIx(glamState, marginTradingEnabled, subAccountId = 0, txOptions = {}) {
13774
14884
  const glamSigner = txOptions.signer || this.base.getSigner();
13775
- const [user] = this.getUser(glamState, subAccountId);
14885
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
13776
14886
  return await this.base.program.methods.driftUpdateUserMarginTradingEnabled(subAccountId, marginTradingEnabled).accounts({
13777
14887
  glamState,
13778
14888
  glamSigner,
@@ -13785,7 +14895,7 @@ class DriftClient {
13785
14895
  }
13786
14896
  async updateUserDelegateIx(glamState, delegate, subAccountId = 0, txOptions = {}) {
13787
14897
  const glamSigner = txOptions.signer || this.base.getSigner();
13788
- const [user] = this.getUser(glamState, subAccountId);
14898
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
13789
14899
  return await this.base.program.methods.driftUpdateUserDelegate(subAccountId, new PublicKey(delegate)).accounts({
13790
14900
  glamState,
13791
14901
  glamSigner,
@@ -13798,32 +14908,28 @@ class DriftClient {
13798
14908
  }
13799
14909
  async deleteUserTx(glamState, subAccountId = 0, txOptions = {}) {
13800
14910
  const glamSigner = txOptions.signer || this.base.getSigner();
13801
- const [user, userStats] = this.getUser(glamState, subAccountId);
13802
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
14911
+ const { user, userStats } = this.getDriftUserPdas(glamState, subAccountId);
13803
14912
  const tx = await this.base.program.methods.driftDeleteUser().accounts({
13804
14913
  glamState,
13805
- state,
14914
+ state: this.driftStatePda,
13806
14915
  user,
13807
14916
  userStats,
13808
14917
  glamSigner
13809
14918
  }).transaction();
13810
14919
  return await this.base.intoVersionedTransaction(tx, txOptions);
13811
14920
  }
13812
- async depositTx(glamState, amount, marketIndex = 1, subAccountId = 0, marketConfigs, txOptions = {}) {
14921
+ async depositTx(glamState, amount, marketIndex = 1, subAccountId = 0, txOptions = {}) {
13813
14922
  const glamSigner = txOptions.signer || this.base.getSigner();
13814
- const [user, userStats] = this.getUser(glamState, subAccountId);
13815
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13816
- const { mint, oracle, marketPDA, vaultPDA } = marketConfigs.spot[marketIndex];
13817
- console.log("mint, oracle, marketPDA, vaultPDA", mint, oracle, marketPDA, vaultPDA);
14923
+ const { user, userStats } = this.getDriftUserPdas(glamState, subAccountId);
14924
+ const { mint, oracle, tokenProgram, marketPda, vault: driftVault } = await this.fetchAndParseSpotMarket(marketIndex);
14925
+ console.log(`Spot market ${marketIndex} mint ${mint}, oracle: ${oracle}, marketPda: ${marketPda}, vault: ${driftVault}`);
13818
14926
  const preInstructions = [];
13819
14927
  const postInstructions = [];
13820
14928
  // If drift user doesn't exist, prepend initializeUserStats and initializeUser instructions
13821
- try {
13822
- await this.fetchGlamDriftUser(glamState, subAccountId);
13823
- } catch (_) {
14929
+ if (!await this.fetchDriftUser(glamState, subAccountId)) {
13824
14930
  preInstructions.push(await this.initializeUserStatsIx(glamState, glamSigner), await this.initializeUserIx(glamState, glamSigner, subAccountId));
13825
14931
  }
13826
- if (mint === WSOL.toBase58()) {
14932
+ if (mint.equals(WSOL)) {
13827
14933
  const wrapSolIxs = await this.base.maybeWrapSol(glamState, amount, glamSigner);
13828
14934
  preInstructions.push(...wrapSolIxs);
13829
14935
  // If we need to wrap SOL, it means the wSOL balance will be drained,
@@ -13837,75 +14943,97 @@ class DriftClient {
13837
14943
  }).instruction();
13838
14944
  postInstructions.push(closeTokenAccountIx);
13839
14945
  }
13840
- const tx = await this.base.program.methods.driftDeposit(marketIndex, amount, false).accounts({
13841
- glamState,
13842
- state,
13843
- user,
13844
- userStats,
13845
- spotMarketVault: new PublicKey(vaultPDA),
13846
- userTokenAccount: this.base.getVaultAta(glamState, new PublicKey(mint)),
13847
- glamSigner,
13848
- tokenProgram: TOKEN_PROGRAM_ID
13849
- }).remainingAccounts([
14946
+ const remainingAccounts = [
13850
14947
  {
13851
14948
  pubkey: new PublicKey(oracle),
13852
14949
  isSigner: false,
13853
14950
  isWritable: false
13854
14951
  },
13855
14952
  {
13856
- pubkey: new PublicKey(marketPDA),
14953
+ pubkey: new PublicKey(marketPda),
13857
14954
  isSigner: false,
13858
14955
  isWritable: true
13859
14956
  }
13860
- ]).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
14957
+ ];
14958
+ if (tokenProgram.equals(TOKEN_2022_PROGRAM_ID)) {
14959
+ remainingAccounts.push({
14960
+ pubkey: mint,
14961
+ isSigner: false,
14962
+ isWritable: false
14963
+ });
14964
+ }
14965
+ const tx = await this.base.program.methods.driftDeposit(marketIndex, amount, false).accounts({
14966
+ glamState,
14967
+ state: this.driftStatePda,
14968
+ user,
14969
+ userStats,
14970
+ spotMarketVault: driftVault,
14971
+ userTokenAccount: this.base.getVaultAta(glamState, mint, tokenProgram),
14972
+ glamSigner,
14973
+ tokenProgram
14974
+ }).remainingAccounts(remainingAccounts).preInstructions(preInstructions).postInstructions(postInstructions).transaction();
13861
14975
  return await this.base.intoVersionedTransaction(tx, txOptions);
13862
14976
  }
13863
- async withdrawTx(statePda, amount, marketIndex = 1, subAccountId = 0, marketConfigs, txOptions = {}) {
14977
+ async withdrawTx(statePda, amount, marketIndex = 1, subAccountId = 0, txOptions = {}) {
13864
14978
  const glamSigner = txOptions.signer || this.base.getSigner();
13865
- const [user, userStats] = this.getUser(statePda, subAccountId);
13866
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13867
- const { mint: m, vaultPDA: d } = marketConfigs.spot[marketIndex];
13868
- const mint = new PublicKey(m);
13869
- const driftAta = new PublicKey(d); // drift vault ata
13870
- const vault = this.base.getVaultPda(statePda);
13871
- const vaultAta = this.base.getVaultAta(statePda, mint); // glam vault ata
13872
- const remainingAccounts = await this.composeRemainingAccounts(statePda, subAccountId, marketConfigs, MarketType.SPOT, marketIndex);
13873
- const { tokenProgram } = await this.base.fetchMintWithOwner(mint);
14979
+ const { user, userStats } = this.getDriftUserPdas(statePda, subAccountId);
14980
+ const { mint, tokenProgram, vault: driftVault } = await this.fetchAndParseSpotMarket(marketIndex);
14981
+ const glamVault = this.base.getVaultPda(statePda);
14982
+ const glamVaultAta = this.base.getVaultAta(statePda, mint, tokenProgram);
14983
+ const remainingAccounts = await this.composeRemainingAccounts(statePda, subAccountId, MarketType.SPOT, marketIndex);
14984
+ if (tokenProgram.equals(TOKEN_2022_PROGRAM_ID)) {
14985
+ remainingAccounts.push({
14986
+ pubkey: mint,
14987
+ isSigner: false,
14988
+ isWritable: false
14989
+ });
14990
+ }
13874
14991
  // Create vault ata in case it doesn't exist
13875
14992
  const preInstructions = [
13876
- createAssociatedTokenAccountIdempotentInstruction(glamSigner, vaultAta, vault, mint, tokenProgram)
14993
+ createAssociatedTokenAccountIdempotentInstruction(glamSigner, glamVaultAta, glamVault, mint, tokenProgram)
13877
14994
  ];
13878
14995
  const tx = await this.base.program.methods.driftWithdraw(marketIndex, amount, false).accounts({
13879
14996
  glamState: statePda,
13880
- state,
14997
+ state: this.driftStatePda,
13881
14998
  user,
13882
14999
  userStats,
13883
15000
  glamSigner,
13884
- spotMarketVault: driftAta,
13885
- userTokenAccount: vaultAta,
13886
- driftSigner: DRIFT_VAULT,
13887
- tokenProgram: TOKEN_PROGRAM_ID
15001
+ spotMarketVault: driftVault,
15002
+ userTokenAccount: glamVaultAta,
15003
+ driftSigner: DRIFT_SIGNER,
15004
+ tokenProgram
13888
15005
  }).remainingAccounts(remainingAccounts).preInstructions(preInstructions).transaction();
13889
15006
  return await this.base.intoVersionedTransaction(tx, txOptions);
13890
15007
  }
13891
- async placeOrderTx(glamState, orderParams, subAccountId = 0, marketConfigs, txOptions = {}) {
15008
+ async placeOrderTx(glamState, orderParams, subAccountId = 0, txOptions = {}) {
13892
15009
  const { marketIndex, marketType } = orderParams;
13893
- const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex);
15010
+ const { user: referrer, userStats: referrerStats } = this.getGlamReferrerPdas();
15011
+ const remainingAccounts = (await this.composeRemainingAccounts(glamState, subAccountId, marketType, marketIndex)).concat([
15012
+ {
15013
+ pubkey: referrer,
15014
+ isWritable: true,
15015
+ isSigner: false
15016
+ },
15017
+ {
15018
+ pubkey: referrerStats,
15019
+ isWritable: true,
15020
+ isSigner: false
15021
+ }
15022
+ ]);
13894
15023
  const glamSigner = txOptions.signer || this.base.getSigner();
13895
- const [user] = this.getUser(glamState, subAccountId);
13896
- const state = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13897
- const tx = await this.base.program.methods// @ts-ignore
13898
- .driftPlaceOrders([
15024
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
15025
+ // @ts-ignore
15026
+ const tx = await this.base.program.methods.driftPlaceOrders([
13899
15027
  orderParams
13900
15028
  ]).accounts({
13901
15029
  glamState,
13902
15030
  user,
13903
- state,
15031
+ state: this.driftStatePda,
13904
15032
  glamSigner
13905
15033
  }).remainingAccounts(remainingAccounts).transaction();
13906
15034
  return await this.base.intoVersionedTransaction(tx, txOptions);
13907
15035
  }
13908
- async modifyOrderTx(statePda, modifyOrderParams, subAccountId = 0, marketConfigs, txOptions = {}) {
15036
+ async modifyOrderTx(statePda, modifyOrderParams, subAccountId = 0, txOptions = {}) {
13909
15037
  // const { marketIndex, marketType } = orderParams;
13910
15038
  // const remainingAccounts = await this.composeRemainingAccounts(
13911
15039
  // statePda,
@@ -13915,65 +15043,62 @@ class DriftClient {
13915
15043
  // marketIndex,
13916
15044
  // );
13917
15045
  const signer = txOptions.signer || this.base.getSigner();
13918
- const [user] = this.getUser(statePda, subAccountId);
13919
- const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
15046
+ const { user } = this.getDriftUserPdas(statePda, subAccountId);
13920
15047
  const tx = await this.base.program.methods// @ts-ignore
13921
15048
  .driftModifyOrder(1, modifyOrderParams).accounts({
13922
15049
  glamState: statePda,
13923
15050
  glamSigner: signer,
13924
15051
  user,
13925
- state: driftState
15052
+ state: this.driftStatePda
13926
15053
  })// .remainingAccounts(remainingAccounts)
13927
15054
  .transaction();
13928
15055
  return await this.base.intoVersionedTransaction(tx, txOptions);
13929
15056
  }
13930
- async cancelOrdersTx(glamState, marketType, marketIndex, direction, subAccountId = 0, marketConfigs, txOptions = {}) {
15057
+ async cancelOrdersTx(glamState, marketType, marketIndex, direction, subAccountId = 0, txOptions = {}) {
13931
15058
  const glamSigner = txOptions.signer || this.base.getSigner();
13932
- const [user] = this.getUser(glamState, subAccountId);
13933
- const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13934
- const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs, marketType, marketIndex);
15059
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
15060
+ const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketType, marketIndex);
13935
15061
  // @ts-ignore
13936
15062
  const tx = await this.base.program.methods.driftCancelOrders(marketType, marketIndex, direction).accounts({
13937
15063
  glamState,
13938
15064
  glamSigner,
13939
15065
  user,
13940
- state: driftState
15066
+ state: this.driftStatePda
13941
15067
  }).remainingAccounts(remainingAccounts).transaction();
13942
15068
  return await this.base.intoVersionedTransaction(tx, txOptions);
13943
15069
  }
13944
- async cancelOrdersByIdsTx(glamState, orderIds, subAccountId = 0, marketConfigs, txOptions = {}) {
15070
+ async cancelOrdersByIdsTx(glamState, orderIds, subAccountId = 0, txOptions = {}) {
13945
15071
  const glamSigner = txOptions.signer || this.base.getSigner();
13946
- const [user] = this.getUser(glamState, subAccountId);
13947
- const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13948
- const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId, marketConfigs);
15072
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
15073
+ const remainingAccounts = await this.composeRemainingAccounts(glamState, subAccountId);
15074
+ // @ts-ignore
13949
15075
  const tx = await this.base.program.methods.driftCancelOrdersByIds(orderIds).accounts({
13950
15076
  glamState,
13951
15077
  glamSigner,
13952
15078
  user,
13953
- state: driftState
15079
+ state: this.driftStatePda
13954
15080
  }).remainingAccounts(remainingAccounts).transaction();
13955
15081
  return await this.base.intoVersionedTransaction(tx, txOptions);
13956
15082
  }
13957
- async settlePnlTx(glamState, marketIndex, subAccountId = 0, marketConfigs, txOptions = {}) {
15083
+ async settlePnlTx(glamState, marketIndex, subAccountId = 0, txOptions = {}) {
13958
15084
  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];
15085
+ const { user } = this.getDriftUserPdas(glamState, subAccountId);
15086
+ const { vault: driftVault } = await this.fetchAndParseSpotMarket(marketIndex);
15087
+ // @ts-ignore
13962
15088
  const tx = await this.base.program.methods.driftSettlePnl(marketIndex).accounts({
13963
15089
  glamState,
13964
15090
  glamSigner,
13965
15091
  user,
13966
- state: driftState,
13967
- spotMarketVault: new PublicKey(vaultPDA)
15092
+ state: this.driftStatePda,
15093
+ spotMarketVault: driftVault
13968
15094
  }).transaction();
13969
15095
  return await this.base.intoVersionedTransaction(tx, txOptions);
13970
15096
  }
13971
- async priceDriftTx(glamState, marketConfigs, priceDenom, txOptions = {}) {
15097
+ async priceDriftTx(glamState, priceDenom, txOptions = {}) {
13972
15098
  const signer = txOptions.signer || this.base.getSigner();
13973
15099
  const glamVault = this.base.getVaultPda(glamState);
13974
- const [user, userStats] = this.getUser(glamState);
13975
- const driftState = await getDriftStateAccountPublicKey(DRIFT_PROGRAM_ID);
13976
- const remainingAccounts = await this.composeRemainingAccounts(glamState, 0, marketConfigs);
15100
+ const { user, userStats } = this.getDriftUserPdas(glamState);
15101
+ const remainingAccounts = await this.composeRemainingAccounts(glamState, 0);
13977
15102
  const tx = await this.base.program.methods.priceDrift(priceDenom).accounts({
13978
15103
  glamState,
13979
15104
  signer,
@@ -13981,12 +15106,30 @@ class DriftClient {
13981
15106
  user,
13982
15107
  userStats,
13983
15108
  solOracle: SOL_ORACLE,
13984
- state: driftState
15109
+ state: this.driftStatePda
13985
15110
  }).remainingAccounts(remainingAccounts).transaction();
13986
15111
  return await this.base.intoVersionedTransaction(tx, txOptions);
13987
15112
  }
13988
15113
  constructor(base){
13989
15114
  this.base = base;
15115
+ this.spotMarkets = new Map();
15116
+ this.perpMarkets = new Map();
15117
+ this.marketConfigs = null;
15118
+ this./*
15119
+ * Utils
15120
+ */ getMarketPda = (marketType, marketIndex)=>PublicKey.findProgramAddressSync([
15121
+ Buffer.from(`${marketType === MarketType.PERP ? "perp" : "spot"}_market`),
15122
+ new anchor.BN(marketIndex).toArrayLike(Buffer, "le", 2)
15123
+ ], DRIFT_PROGRAM_ID)[0];
15124
+ this.getUserPda = (authority, subAccountId = 0)=>PublicKey.findProgramAddressSync([
15125
+ Buffer.from("user"),
15126
+ authority.toBuffer(),
15127
+ new anchor.BN(subAccountId).toArrayLike(Buffer, "le", 2)
15128
+ ], DRIFT_PROGRAM_ID)[0];
15129
+ this.getUserStatsPda = (authority)=>PublicKey.findProgramAddressSync([
15130
+ Buffer.from("user_stats"),
15131
+ authority.toBuffer()
15132
+ ], DRIFT_PROGRAM_ID)[0];
13990
15133
  this.marketTypeEquals = (a, b)=>a && Object.keys(a)[0] === Object.keys(b)[0];
13991
15134
  }
13992
15135
  }
@@ -15653,7 +16796,7 @@ const DEFAULT_OBLIGATION_ARGS = {
15653
16796
  id: 0
15654
16797
  };
15655
16798
  const SCOPE_PRICES = new PublicKey("3NJYftD5sjVfxSnUdZ1wVML8f3aC6mp1CXCL6L7TnU8C");
15656
- function refreshObligation(accounts, programId) {
16799
+ function refreshObligation(accounts, programId = KAMINO_LENDING_PROGRAM) {
15657
16800
  const keys = [
15658
16801
  {
15659
16802
  pubkey: accounts.lendingMarket,
@@ -15691,7 +16834,7 @@ function refreshObligation(accounts, programId) {
15691
16834
  });
15692
16835
  return ix;
15693
16836
  }
15694
- function refreshReserve(accounts, programId) {
16837
+ function refreshReserve(accounts, programId = KAMINO_LENDING_PROGRAM) {
15695
16838
  const keys = [
15696
16839
  {
15697
16840
  pubkey: accounts.reserve,
@@ -15742,7 +16885,7 @@ function refreshReserve(accounts, programId) {
15742
16885
  });
15743
16886
  return ix;
15744
16887
  }
15745
- function refreshObligationFarmsForReserve(args, accounts, programId) {
16888
+ function refreshObligationFarmsForReserve(args, accounts, programId = KAMINO_LENDING_PROGRAM) {
15746
16889
  const keys = [
15747
16890
  {
15748
16891
  pubkey: accounts.crank,
@@ -15833,7 +16976,7 @@ class KaminoLendingClient {
15833
16976
  * @param txOptions
15834
16977
  * @returns
15835
16978
  */ async initUserMetadata(statePda, referrer, txOptions = {}) {
15836
- const tx = await this.initUserMetadataTx(new PublicKey(statePda), referrer ? new PublicKey(referrer) : PublicKey.default, txOptions);
16979
+ const tx = await this.initUserMetadataTx(new PublicKey(statePda), referrer ? new PublicKey(referrer) : null, txOptions);
15837
16980
  return await this.base.sendAndConfirm(tx);
15838
16981
  }
15839
16982
  /**
@@ -15919,18 +17062,17 @@ class KaminoLendingClient {
15919
17062
  ], KAMINO_FARM_PROGRAM);
15920
17063
  return obligationFarm;
15921
17064
  }
15922
- async initUserMetadataTx(glamState, referrer, txOptions) {
17065
+ async initUserMetadataTx(glamState, referrer, txOptions = {}) {
15923
17066
  const glamSigner = txOptions.signer || this.base.getSigner();
15924
17067
  const vault = this.base.getVaultPda(glamState);
15925
17068
  const userMetadata = this.getUserMetadataPda(vault);
15926
17069
  const lookupTable = new PublicKey(0); // FIXME: create lookup table
15927
- const referrerUserMetadata = referrer.equals(PublicKey.default) ? KAMINO_LENDING_PROGRAM : referrer;
15928
17070
  // @ts-ignore
15929
17071
  const tx = await this.base.program.methods.kaminoLendingInitUserMetadata(lookupTable).accounts({
15930
17072
  glamState,
15931
17073
  glamSigner,
15932
17074
  userMetadata,
15933
- referrerUserMetadata
17075
+ referrerUserMetadata: referrer
15934
17076
  }).transaction();
15935
17077
  const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
15936
17078
  return vTx;
@@ -15943,7 +17085,7 @@ class KaminoLendingClient {
15943
17085
  switchboardPriceOracle: KAMINO_LENDING_PROGRAM,
15944
17086
  switchboardTwapOracle: KAMINO_LENDING_PROGRAM,
15945
17087
  scopePrices: SCOPE_PRICES
15946
- }, KAMINO_LENDING_PROGRAM));
17088
+ }));
15947
17089
  }
15948
17090
  refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) {
15949
17091
  return parsedReserves.map((parsedReserve)=>{
@@ -15968,18 +17110,21 @@ class KaminoLendingClient {
15968
17110
  farmsProgram: KAMINO_FARM_PROGRAM,
15969
17111
  rent: SYSVAR_RENT_PUBKEY,
15970
17112
  systemProgram: SystemProgram.programId
15971
- }, KAMINO_LENDING_PROGRAM);
17113
+ });
15972
17114
  });
15973
17115
  }).flat();
15974
17116
  }
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);
17117
+ // If obligation has deposits or borrows, we need the following refresh ixs:
17118
+ // - refreshReserve x N_reserves
17119
+ // - refreshObligation
17120
+ // - refreshObligationFarmsForReserve x M_farms
17121
+ //
17122
+ // For pricing purpose, we don't need to refresh farm states
17123
+ async getRefreshIxs(obligation, refreshFarms = true) {
17124
+ const { lendingMarket, deposits, borrows } = await this.fetchAndParseObligation(obligation);
17125
+ if (!lendingMarket) {
17126
+ throw new Error("Lending market not found");
17127
+ }
15983
17128
  const reserves = deposits.concat(borrows).map((d)=>d.reserve);
15984
17129
  const parsedReserves = await this.fetchAndParseReserves(reserves);
15985
17130
  return [
@@ -15988,8 +17133,8 @@ class KaminoLendingClient {
15988
17133
  lendingMarket,
15989
17134
  obligation,
15990
17135
  reserves
15991
- }, KAMINO_LENDING_PROGRAM),
15992
- ...this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves)
17136
+ }),
17137
+ ...refreshFarms ? this.refreshObligationFarmsForReserveIxs(obligation, lendingMarket, parsedReserves) : []
15993
17138
  ];
15994
17139
  }
15995
17140
  getMarketAuthority(market) {
@@ -16040,11 +17185,14 @@ class KaminoLendingClient {
16040
17185
  const obligationAccount = await this.base.provider.connection.getAccountInfo(obligation);
16041
17186
  if (!obligationAccount) {
16042
17187
  return {
17188
+ address: obligation,
17189
+ lendingMarket: null,
16043
17190
  deposits: [],
16044
17191
  borrows: []
16045
17192
  };
16046
17193
  }
16047
17194
  const data = obligationAccount.data;
17195
+ const lendingMarket = new PublicKey(data.subarray(32, 64));
16048
17196
  // read deposits
16049
17197
  let depositsOffset = 96;
16050
17198
  let depositSize = 136;
@@ -16054,8 +17202,9 @@ class KaminoLendingClient {
16054
17202
  length: numDeposits
16055
17203
  }, (_, i)=>{
16056
17204
  const depositData = depositsData.subarray(i * depositSize, (i + 1) * depositSize);
17205
+ const reserve = new PublicKey(depositData.subarray(0, 32));
16057
17206
  return {
16058
- reserve: new PublicKey(depositData.subarray(0, 32))
17207
+ reserve
16059
17208
  };
16060
17209
  }).filter((d)=>!d.reserve.equals(PublicKey.default));
16061
17210
  // read borrows
@@ -16067,24 +17216,33 @@ class KaminoLendingClient {
16067
17216
  length: numBorrows
16068
17217
  }, (_, i)=>{
16069
17218
  const borrowData = borrowsData.subarray(i * borrowSize, (i + 1) * borrowSize);
17219
+ const reserve = new PublicKey(borrowData.subarray(0, 32));
16070
17220
  return {
16071
- reserve: new PublicKey(borrowData.subarray(0, 32))
17221
+ reserve
16072
17222
  };
16073
17223
  }).filter((d)=>!d.reserve.equals(PublicKey.default));
16074
17224
  const parsedObligation = {
17225
+ address: obligation,
17226
+ lendingMarket,
16075
17227
  deposits,
16076
17228
  borrows
16077
17229
  };
16078
17230
  this.obligations.set(obligation, parsedObligation);
16079
17231
  return parsedObligation;
16080
17232
  }
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) {
17233
+ _parseReserveAccount(data) {
17234
+ const market = new PublicKey(data.subarray(32, 64));
17235
+ const farmCollateral = new PublicKey(data.subarray(64, 96));
17236
+ const farmDebt = new PublicKey(data.subarray(96, 128));
17237
+ const liquidityMint = new PublicKey(data.subarray(128, 160));
17238
+ return {
17239
+ farmCollateral: farmCollateral.equals(PublicKey.default) ? null : farmCollateral,
17240
+ farmDebt: farmDebt.equals(PublicKey.default) ? null : farmDebt,
17241
+ liquidityMint,
17242
+ ...this.reservePdas(market, liquidityMint)
17243
+ };
17244
+ }
17245
+ async fetchAndParseReserves(reserves) {
16088
17246
  if (this.pubkeyArraysEqual(reserves, Array.from(this.reserves.keys()))) {
16089
17247
  return Array.from(this.reserves.values());
16090
17248
  }
@@ -16093,20 +17251,12 @@ class KaminoLendingClient {
16093
17251
  throw new Error("Not all reserves can be found");
16094
17252
  }
16095
17253
  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 = {
17254
+ const parsedReserve = {
16102
17255
  address: reserves[i],
16103
- farmCollateral: farmCollateral.equals(PublicKey.default) ? null : farmCollateral,
16104
- farmDebt: farmDebt.equals(PublicKey.default) ? null : farmDebt,
16105
- liquidityMint,
16106
- ...this.reservePdas(market, liquidityMint)
17256
+ ...this._parseReserveAccount(account.data)
16107
17257
  };
16108
- this.reserves.set(reserves[i], parsed);
16109
- return parsed;
17258
+ this.reserves.set(reserves[i], parsedReserve);
17259
+ return parsedReserve;
16110
17260
  });
16111
17261
  }
16112
17262
  async findAndParseReserve(market, asset) {
@@ -16133,18 +17283,12 @@ class KaminoLendingClient {
16133
17283
  throw new Error("Reserve not found");
16134
17284
  }
16135
17285
  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 = {
17286
+ const parsedReserve = {
16140
17287
  address: account.pubkey,
16141
- farmCollateral: farmCollateral.equals(PublicKey.default) ? null : farmCollateral,
16142
- farmDebt: farmDebt.equals(PublicKey.default) ? null : farmDebt,
16143
- liquidityMint: asset,
16144
- ...this.reservePdas(market, asset)
17288
+ ...this._parseReserveAccount(account.account.data)
16145
17289
  };
16146
- this.reserves.set(account.pubkey, parsed);
16147
- return parsed;
17290
+ this.reserves.set(account.pubkey, parsedReserve);
17291
+ return parsedReserve;
16148
17292
  }
16149
17293
  async depositTx(glamState, market, asset, amount, txOptions) {
16150
17294
  const glamSigner = txOptions.signer || this.base.getSigner();
@@ -16202,7 +17346,7 @@ class KaminoLendingClient {
16202
17346
  lendingMarket: market,
16203
17347
  obligation,
16204
17348
  reserves: reservesInUse
16205
- }, KAMINO_LENDING_PROGRAM));
17349
+ }));
16206
17350
  if (depositReserve.farmCollateral) {
16207
17351
  const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16208
17352
  depositReserve
@@ -16298,7 +17442,7 @@ class KaminoLendingClient {
16298
17442
  lendingMarket: market,
16299
17443
  obligation,
16300
17444
  reserves: reservesInUse
16301
- }, KAMINO_LENDING_PROGRAM));
17445
+ }));
16302
17446
  if (withdrawReserve.farmCollateral) {
16303
17447
  const ixs = this.refreshObligationFarmsForReserveIxs(obligation, market, [
16304
17448
  withdrawReserve
@@ -16388,7 +17532,7 @@ class KaminoLendingClient {
16388
17532
  lendingMarket: market,
16389
17533
  obligation,
16390
17534
  reserves: reservesInUse
16391
- }, KAMINO_LENDING_PROGRAM));
17535
+ }));
16392
17536
  // Don't need to refresh debt farm for borrow
16393
17537
  /*
16394
17538
  if (borrowReserve.farmDebt) {
@@ -16476,7 +17620,7 @@ class KaminoLendingClient {
16476
17620
  lendingMarket: market,
16477
17621
  obligation,
16478
17622
  reserves: reservesInUse
16479
- }, KAMINO_LENDING_PROGRAM));
17623
+ }));
16480
17624
  const repayIx = await this.base.program.methods.kaminoLendingRepayObligationLiquidityV2(amount).accounts({
16481
17625
  glamState,
16482
17626
  glamSigner,
@@ -16520,6 +17664,135 @@ class KaminoLendingClient {
16520
17664
  };
16521
17665
  }
16522
17666
  }
17667
+ class KaminoFarmClient {
17668
+ async findAndParseFarmStates(owner) {
17669
+ const accounts = await this.base.provider.connection.getProgramAccounts(KAMINO_FARM_PROGRAM, {
17670
+ filters: [
17671
+ {
17672
+ dataSize: 920
17673
+ },
17674
+ {
17675
+ memcmp: {
17676
+ offset: 48,
17677
+ bytes: owner.toBase58()
17678
+ }
17679
+ }
17680
+ ]
17681
+ });
17682
+ return accounts.map((account)=>{
17683
+ const data = account.account.data;
17684
+ const farmState = new PublicKey(data.subarray(16, 48));
17685
+ return {
17686
+ userFarmState: account.pubkey,
17687
+ farmState
17688
+ };
17689
+ });
17690
+ }
17691
+ async parseFarm(data) {
17692
+ const globalConfig = new PublicKey(data.subarray(40, 72));
17693
+ const rewardsOffset = 192;
17694
+ const numRewards = 10;
17695
+ const rewardSize = 704;
17696
+ const rewardsData = data.subarray(rewardsOffset, rewardsOffset + numRewards * rewardSize);
17697
+ const rewards = Array.from({
17698
+ length: numRewards
17699
+ }, (_, i)=>{
17700
+ const rewardData = rewardsData.subarray(i * rewardSize, (i + 1) * rewardSize);
17701
+ const mint = new PublicKey(rewardData.subarray(0, 32));
17702
+ const tokenProgram = new PublicKey(rewardData.subarray(40, 72));
17703
+ const rewardsVault = new PublicKey(rewardData.subarray(120, 152));
17704
+ const minClaimDurationSeconds = new BN(rewardData.subarray(480, 488), "le");
17705
+ return {
17706
+ index: i,
17707
+ mint,
17708
+ minClaimDurationSeconds,
17709
+ tokenProgram,
17710
+ rewardsVault
17711
+ };
17712
+ }).filter((r)=>{
17713
+ if (r.mint.equals(PublicKey.default)) {
17714
+ return false;
17715
+ }
17716
+ // Filter out rewards with minClaimDurationSeconds > 1 year, they are considered disabled
17717
+ if (r.minClaimDurationSeconds.div(new BN(365 * 24 * 60 * 60)).gt(new BN(1))) {
17718
+ return false;
17719
+ }
17720
+ return true;
17721
+ });
17722
+ return {
17723
+ globalConfig,
17724
+ rewards
17725
+ };
17726
+ }
17727
+ async fetchAndParseFarms(farms) {
17728
+ const farmAccounts = await this.base.provider.connection.getMultipleAccountsInfo(farms);
17729
+ const map = new Map();
17730
+ for(let i = 0; i < farmAccounts.length; i++){
17731
+ const account = farmAccounts[i];
17732
+ if (!account) {
17733
+ continue;
17734
+ }
17735
+ const data = account.data;
17736
+ const parsedFarm = await this.parseFarm(data);
17737
+ map.set(farms[i].toBase58(), parsedFarm);
17738
+ }
17739
+ return map;
17740
+ }
17741
+ async harvest(statePda, txOptions = {}) {
17742
+ const tx = await this.harvestTx(new PublicKey(statePda), txOptions);
17743
+ return await this.base.sendAndConfirm(tx);
17744
+ }
17745
+ async harvestTx(glamState, txOptions = {}) {
17746
+ const glamSigner = txOptions.signer || this.base.getSigner();
17747
+ const vault = this.base.getVaultPda(glamState);
17748
+ const farmStates = await this.findAndParseFarmStates(vault);
17749
+ const parsedFarms = await this.fetchAndParseFarms(farmStates.map((f)=>f.farmState));
17750
+ const tx = new Transaction();
17751
+ for (const { userFarmState, farmState } of farmStates){
17752
+ const { globalConfig, rewards } = parsedFarms.get(farmState.toBase58());
17753
+ for (const { index, mint, tokenProgram, rewardsVault } of rewards){
17754
+ console.log("Reward token:", mint.toBase58());
17755
+ const vaultAta = this.base.getVaultAta(glamState, mint, tokenProgram);
17756
+ const createAtaIx = createAssociatedTokenAccountIdempotentInstruction(glamSigner, vaultAta, vault, mint, tokenProgram);
17757
+ const harvestIx = await this.base.program.methods.kaminoFarmHarvestReward(new BN(index)).accounts({
17758
+ glamState,
17759
+ glamSigner,
17760
+ userState: userFarmState,
17761
+ farmState,
17762
+ globalConfig,
17763
+ rewardMint: mint,
17764
+ userRewardAta: vaultAta,
17765
+ rewardsVault,
17766
+ rewardsTreasuryVault: this.rewardsTreasuryVault(globalConfig, mint),
17767
+ farmVaultsAuthority: this.farmVaultsAuthority(farmState),
17768
+ scopePrices: null,
17769
+ tokenProgram
17770
+ }).instruction();
17771
+ tx.add(createAtaIx, harvestIx);
17772
+ }
17773
+ }
17774
+ const lookupTables = txOptions.lookupTables || await this.base.getAdressLookupTableAccounts([
17775
+ LOOKUP_TABLE
17776
+ ]);
17777
+ const vTx = await this.base.intoVersionedTransaction(tx, {
17778
+ ...txOptions,
17779
+ lookupTables
17780
+ });
17781
+ return vTx;
17782
+ }
17783
+ constructor(base){
17784
+ this.base = base;
17785
+ this.farmVaultsAuthority = (farm)=>PublicKey.findProgramAddressSync([
17786
+ Buffer.from("authority"),
17787
+ farm.toBuffer()
17788
+ ], KAMINO_FARM_PROGRAM)[0];
17789
+ this.rewardsTreasuryVault = (globalConfig, mint)=>PublicKey.findProgramAddressSync([
17790
+ Buffer.from("tvault"),
17791
+ globalConfig.toBuffer(),
17792
+ mint.toBuffer()
17793
+ ], KAMINO_FARM_PROGRAM)[0];
17794
+ }
17795
+ }
16523
17796
 
16524
17797
  // Pubkey::find_program_address(&[b"__event_authority"], &dlmm_interface::ID)
16525
17798
  const EVENT_AUTHORITY = new PublicKey("D1ZN9Wj1fRSUQfCjhvnu1hqDMT7hzjzBBpi12nVniYD6");
@@ -16996,6 +18269,28 @@ class PriceClient {
16996
18269
  });
16997
18270
  return pricedAssets.reduce((sum, p)=>new BN(p.amount).add(sum), new BN(0));
16998
18271
  }
18272
+ async priceKaminoIxs(glamState, priceDenom) {
18273
+ const glamVault = this.base.getVaultPda(glamState);
18274
+ const obligations = await fetchKaminoObligations(this.base.provider.connection, glamVault);
18275
+ const refreshIxs = [];
18276
+ for (const obligation of obligations){
18277
+ const ixs = await this.klend.getRefreshIxs(obligation, false); // skip farms
18278
+ refreshIxs.push(...ixs);
18279
+ }
18280
+ // @ts-ignore
18281
+ const priceIx = await this.base.program.methods.priceKaminoObligations(priceDenom).accounts({
18282
+ glamState,
18283
+ solOracle: SOL_ORACLE
18284
+ }).remainingAccounts(obligations.map((o)=>({
18285
+ pubkey: o,
18286
+ isSigner: false,
18287
+ isWritable: false
18288
+ }))).instruction();
18289
+ return [
18290
+ ...refreshIxs,
18291
+ priceIx
18292
+ ];
18293
+ }
16999
18294
  async priceVaultIxs(glamState, priceDenom) {
17000
18295
  const vault = this.base.getVaultPda(glamState);
17001
18296
  const tickets = await fetchMarinadeTicketAccounts(this.base.provider.connection, vault);
@@ -17025,29 +18320,18 @@ class PriceClient {
17025
18320
  glamState,
17026
18321
  solOracle: SOL_ORACLE
17027
18322
  }).remainingAccounts(await this.remainingAccountsForPricingMeteora(glamState)).instruction();
17028
- const priceKaminoIx = await this.base.program.methods.priceKaminoObligations(priceDenom).accounts({
17029
- glamState,
17030
- solOracle: SOL_ORACLE
17031
- }).remainingAccounts(await this.remainingAccountsForPricingKamino(glamState)).instruction();
18323
+ const priceKaminoIxs = await this.priceKaminoIxs(glamState, priceDenom);
17032
18324
  return [
17033
18325
  priceTicketsIx,
17034
18326
  priceStakesIx,
17035
18327
  priceVaultIx,
17036
18328
  priceMeteoraIx,
17037
- priceKaminoIx
18329
+ ...priceKaminoIxs
17038
18330
  ];
17039
18331
  }
17040
- constructor(base){
18332
+ constructor(base, klend){
17041
18333
  this.base = base;
17042
- this.remainingAccountsForPricingKamino = async (glamState)=>{
17043
- const glamVault = this.base.getVaultPda(glamState);
17044
- const obligationAccounts = await fetchKaminoObligations(this.base.provider.connection, glamVault);
17045
- return obligationAccounts.map((a)=>({
17046
- pubkey: a,
17047
- isSigner: false,
17048
- isWritable: false
17049
- }));
17050
- };
18334
+ this.klend = klend;
17051
18335
  this.remainingAccountsForPricingMeteora = async (glamState)=>{
17052
18336
  const glamVault = this.base.getVaultPda(glamState);
17053
18337
  const positions = await fetchMeteoraPositions(this.base.provider.connection, glamVault);
@@ -17133,7 +18417,7 @@ class PriceClient {
17133
18417
  }
17134
18418
  get price() {
17135
18419
  if (!this._price) {
17136
- this._price = new PriceClient(this);
18420
+ this._price = new PriceClient(this, this.kaminoLending);
17137
18421
  }
17138
18422
  return this._price;
17139
18423
  }
@@ -17155,6 +18439,12 @@ class PriceClient {
17155
18439
  }
17156
18440
  return this._kaminoLending;
17157
18441
  }
18442
+ get kaminoFarm() {
18443
+ if (!this._kaminoFarm) {
18444
+ this._kaminoFarm = new KaminoFarmClient(this);
18445
+ }
18446
+ return this._kaminoFarm;
18447
+ }
17158
18448
  get meteoraDlmm() {
17159
18449
  if (!this._meteoraDlmm) {
17160
18450
  this._meteoraDlmm = new MeteoraDlmmClient(this);
@@ -17170,7 +18460,7 @@ const getPriorityFeeEstimate = async (heliusApiKey, tx, accountKeys, priorityLev
17170
18460
  if (!tx && !accountKeys) {
17171
18461
  throw new Error("Either tx or accountKeys must be provided");
17172
18462
  }
17173
- const options = priorityLevel ? {
18463
+ const options = priorityLevel && priorityLevel !== "Recommended" ? {
17174
18464
  priorityLevel
17175
18465
  } : {
17176
18466
  recommended: true
@@ -17202,4 +18492,39 @@ const getPriorityFeeEstimate = async (heliusApiKey, tx, accountKeys, priorityLev
17202
18492
  return data.result.priorityFeeEstimate;
17203
18493
  };
17204
18494
 
17205
- 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 };
18495
+ function getLimitOrderParams(params) {
18496
+ return getOrderParams(Object.assign({}, params, {
18497
+ orderType: OrderType.LIMIT
18498
+ }));
18499
+ }
18500
+ function getTriggerMarketOrderParams(params) {
18501
+ return getOrderParams(Object.assign({}, params, {
18502
+ orderType: OrderType.TRIGGER_MARKET
18503
+ }));
18504
+ }
18505
+ function getTriggerLimitOrderParams(params) {
18506
+ return getOrderParams(Object.assign({}, params, {
18507
+ orderType: OrderType.TRIGGER_LIMIT
18508
+ }));
18509
+ }
18510
+ function getMarketOrderParams(params) {
18511
+ return getOrderParams(Object.assign({}, params, {
18512
+ orderType: OrderType.MARKET
18513
+ }));
18514
+ }
18515
+ /**
18516
+ * Creates an OrderParams object with the given OptionalOrderParams and any params to override.
18517
+ *
18518
+ * example:
18519
+ * ```
18520
+ * const orderParams = getOrderParams(optionalOrderParams, { marketType: MarketType.PERP });
18521
+ * ```
18522
+ *
18523
+ * @param optionalOrderParams
18524
+ * @param overridingParams
18525
+ * @returns
18526
+ */ function getOrderParams(optionalOrderParams, overridingParams = {}) {
18527
+ return Object.assign({}, DefaultOrderParams, optionalOrderParams, overridingParams);
18528
+ }
18529
+
18530
+ export { ASSETS_MAINNET, ASSETS_TESTS, AssetTier, BaseClient, ClusterNetwork, CompanyModel, ContractTier, ContractType, CreatedModel, DRIFT_PROGRAM_ID, DefaultOrderParams, DelegateAcl, DepositDirection, DepositExplanation, DriftClient, ExchangeStatus, FuelOverflowStatus, FundOpenfundsModel, GLAM_REFERRER, GOVERNANCE_PROGRAM_ID, GlamClient, GlamError, GlamIdl, GlamIntegrations, GlamPermissions, GlamProtocolIdlJson, InsuranceFundOperation, 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, LPAction, LiquidationType, MARINADE_PROGRAM_ID, MARINADE_TICKET_SIZE, MEMO_PROGRAM, MERKLE_DISTRIBUTOR_PROGRAM, METEORA_DLMM_PROGRAM, METEORA_POSITION_SIZE, MSOL, ManagerModel, MarginMode, MarketStatus, MarketType, Metadata, MintIdlModel, MintModel, MintOpenfundsModel, ModifyOrderPolicy, OracleSource, OracleSourceNum, OrderAction, OrderActionExplanation, OrderStatus, OrderTriggerCondition, OrderType, PerpOperation, PlaceAndTakeOrderSuccessCondition, PositionDirection, PostOnlyParams, PriceDenom, ReferrerStatus, SANCTUM_STAKE_POOL_PROGRAM_ID, SEED_ESCROW, SEED_METADATA, SEED_MINT, SEED_STATE, SEED_VAULT, SOL_ORACLE, STAKE_ACCOUNT_SIZE, SettlePnlExplanation, SettlePnlMode, SpotBalanceType, SpotFulfillmentConfigStatus, SpotFulfillmentStatus, SpotFulfillmentType, SpotOperation, StakeAction, StateIdlModel, StateModel, SwapDirection, SwapReduceOnly, TRANSFER_HOOK_PROGRAM, TradeSide, USDC, UserStatus, WBTC, WETH, WSOL, ZERO, decodeUser, fetchKaminoObligations, fetchMarinadeTicketAccounts, fetchMeteoraPositions, fetchStakeAccounts, getGlamProgram, getGlamProgramId, getLimitOrderParams, getMarketOrderParams, getOrderParams, getPriorityFeeEstimate, getSimulationComputeUnits, getTriggerLimitOrderParams, getTriggerMarketOrderParams, getVariant, isBrowser, isOneOfVariant, isVariant, parseMeteoraPosition, setsAreEqual };