@drift-labs/sdk 2.31.1-beta.2 → 2.31.1-beta.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/mockUserAccountSubscriber.d.ts +23 -0
  3. package/lib/accounts/mockUserAccountSubscriber.js +31 -0
  4. package/lib/constants/perpMarkets.js +20 -0
  5. package/lib/dlob/orderBookLevels.js +2 -2
  6. package/lib/driftClient.d.ts +57 -4
  7. package/lib/driftClient.js +244 -205
  8. package/lib/driftClientConfig.d.ts +2 -1
  9. package/lib/idl/drift.json +31 -1
  10. package/lib/index.d.ts +2 -0
  11. package/lib/index.js +2 -0
  12. package/lib/marinade/index.d.ts +11 -0
  13. package/lib/marinade/index.js +36 -0
  14. package/lib/marinade/types.d.ts +1963 -0
  15. package/lib/marinade/types.js +1965 -0
  16. package/lib/math/spotBalance.d.ts +9 -2
  17. package/lib/math/spotBalance.js +54 -6
  18. package/lib/math/superStake.d.ts +21 -0
  19. package/lib/math/superStake.js +100 -0
  20. package/lib/math/tiers.d.ts +4 -0
  21. package/lib/math/tiers.js +52 -0
  22. package/lib/tx/retryTxSender.d.ts +12 -3
  23. package/lib/tx/retryTxSender.js +22 -22
  24. package/lib/tx/types.d.ts +2 -2
  25. package/lib/user.d.ts +10 -1
  26. package/lib/user.js +39 -8
  27. package/lib/userConfig.d.ts +4 -0
  28. package/lib/userStats.js +4 -1
  29. package/lib/userStatsConfig.d.ts +2 -0
  30. package/package.json +1 -1
  31. package/src/accounts/mockUserAccountSubscriber.ts +53 -0
  32. package/src/config.ts +2 -2
  33. package/src/constants/perpMarkets.ts +20 -0
  34. package/src/dlob/orderBookLevels.ts +3 -2
  35. package/src/driftClient.ts +440 -224
  36. package/src/driftClientConfig.ts +2 -1
  37. package/src/idl/drift.json +31 -1
  38. package/src/index.ts +2 -0
  39. package/src/marinade/idl/idl.json +1962 -0
  40. package/src/marinade/index.ts +64 -0
  41. package/src/marinade/types.ts +3925 -0
  42. package/src/math/spotBalance.ts +83 -5
  43. package/src/math/superStake.ts +133 -0
  44. package/src/math/tiers.ts +44 -0
  45. package/src/tx/retryTxSender.ts +39 -35
  46. package/src/tx/types.ts +2 -2
  47. package/src/user.ts +63 -12
  48. package/src/userConfig.ts +5 -0
  49. package/src/userStats.ts +4 -0
  50. package/src/userStatsConfig.ts +3 -0
  51. package/tests/spot/test.ts +156 -0
@@ -52,6 +52,7 @@ const market_1 = require("./math/market");
52
52
  const fetch_1 = require("./accounts/fetch");
53
53
  const spotMarket_1 = require("./math/spotMarket");
54
54
  const memcmp_1 = require("./memcmp");
55
+ const marinade_1 = require("./marinade");
55
56
  /**
56
57
  * # DriftClient
57
58
  * This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
@@ -64,11 +65,13 @@ class DriftClient {
64
65
  this._isSubscribed = val;
65
66
  }
66
67
  constructor(config) {
67
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
68
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
68
69
  this.users = new Map();
69
70
  this._isSubscribed = false;
70
71
  this.perpMarketLastSlotCache = new Map();
71
72
  this.spotMarketLastSlotCache = new Map();
73
+ this.mustIncludePerpMarketIndexes = new Set();
74
+ this.mustIncludeSpotMarketIndexes = new Set();
72
75
  this.connection = config.connection;
73
76
  this.wallet = config.wallet;
74
77
  this.opts = config.opts || anchor_1.AnchorProvider.defaultOptions();
@@ -78,6 +81,10 @@ class DriftClient {
78
81
  this.activeSubAccountId = (_c = config.activeSubAccountId) !== null && _c !== void 0 ? _c : 0;
79
82
  this.skipLoadUsers = (_d = config.skipLoadUsers) !== null && _d !== void 0 ? _d : false;
80
83
  this.txVersion = (_e = config.txVersion) !== null && _e !== void 0 ? _e : 'legacy';
84
+ this.txParams = {
85
+ computeUnits: (_g = (_f = config.txParams) === null || _f === void 0 ? void 0 : _f.computeUnits) !== null && _g !== void 0 ? _g : 600000,
86
+ computeUnitsPrice: (_j = (_h = config.txParams) === null || _h === void 0 ? void 0 : _h.computeUnitsPrice) !== null && _j !== void 0 ? _j : 0,
87
+ };
81
88
  if (config.includeDelegates && config.subAccountIds) {
82
89
  throw new Error('Can only pass one of includeDelegates or subAccountIds. If you want to specify subaccount ids for multiple authorities, pass authoritySubaccountMap instead');
83
90
  }
@@ -92,16 +99,25 @@ class DriftClient {
92
99
  : config.subAccountIds
93
100
  ? new Map([[this.authority.toString(), config.subAccountIds]])
94
101
  : new Map();
95
- this.includeDelegates = (_f = config.includeDelegates) !== null && _f !== void 0 ? _f : false;
96
- this.userAccountSubscriptionConfig =
97
- ((_g = config.accountSubscription) === null || _g === void 0 ? void 0 : _g.type) === 'polling'
98
- ? {
99
- type: 'polling',
100
- accountLoader: config.accountSubscription.accountLoader,
101
- }
102
- : {
103
- type: 'websocket',
104
- };
102
+ this.includeDelegates = (_k = config.includeDelegates) !== null && _k !== void 0 ? _k : false;
103
+ if (((_l = config.accountSubscription) === null || _l === void 0 ? void 0 : _l.type) === 'polling') {
104
+ this.userAccountSubscriptionConfig = {
105
+ type: 'polling',
106
+ accountLoader: config.accountSubscription.accountLoader,
107
+ };
108
+ this.userStatsAccountSubscriptionConfig = {
109
+ type: 'polling',
110
+ accountLoader: config.accountSubscription.accountLoader,
111
+ };
112
+ }
113
+ else {
114
+ this.userAccountSubscriptionConfig = {
115
+ type: 'websocket',
116
+ };
117
+ this.userStatsAccountSubscriptionConfig = {
118
+ type: 'websocket',
119
+ };
120
+ }
105
121
  if (config.userStats) {
106
122
  this.userStats = new userStats_1.UserStats({
107
123
  driftClient: this,
@@ -116,14 +132,19 @@ class DriftClient {
116
132
  const noMarketsAndOraclesSpecified = config.perpMarketIndexes === undefined &&
117
133
  config.spotMarketIndexes === undefined &&
118
134
  config.oracleInfos === undefined;
119
- if (((_h = config.accountSubscription) === null || _h === void 0 ? void 0 : _h.type) === 'polling') {
120
- this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_j = config.perpMarketIndexes) !== null && _j !== void 0 ? _j : [], (_k = config.spotMarketIndexes) !== null && _k !== void 0 ? _k : [], (_l = config.oracleInfos) !== null && _l !== void 0 ? _l : [], noMarketsAndOraclesSpecified);
135
+ if (((_m = config.accountSubscription) === null || _m === void 0 ? void 0 : _m.type) === 'polling') {
136
+ this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_o = config.perpMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.spotMarketIndexes) !== null && _p !== void 0 ? _p : [], (_q = config.oracleInfos) !== null && _q !== void 0 ? _q : [], noMarketsAndOraclesSpecified);
121
137
  }
122
138
  else {
123
- this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_m = config.perpMarketIndexes) !== null && _m !== void 0 ? _m : [], (_o = config.spotMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.oracleInfos) !== null && _p !== void 0 ? _p : [], noMarketsAndOraclesSpecified);
139
+ this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_r = config.perpMarketIndexes) !== null && _r !== void 0 ? _r : [], (_s = config.spotMarketIndexes) !== null && _s !== void 0 ? _s : [], (_t = config.oracleInfos) !== null && _t !== void 0 ? _t : [], noMarketsAndOraclesSpecified);
124
140
  }
125
141
  this.eventEmitter = this.accountSubscriber.eventEmitter;
126
- this.txSender = (_q = config.txSender) !== null && _q !== void 0 ? _q : new retryTxSender_1.RetryTxSender(this.provider);
142
+ this.txSender =
143
+ (_u = config.txSender) !== null && _u !== void 0 ? _u : new retryTxSender_1.RetryTxSender({
144
+ connection: this.connection,
145
+ wallet: this.wallet,
146
+ opts: this.opts,
147
+ });
127
148
  }
128
149
  getUserMapKey(subAccountId, authority) {
129
150
  return `${subAccountId}_${authority.toString()}`;
@@ -274,7 +295,7 @@ class DriftClient {
274
295
  const newProgram = new anchor_1.Program(drift_json_1.default, this.program.programId, newProvider);
275
296
  this.skipLoadUsers = false;
276
297
  // Update provider for txSender with new wallet details
277
- this.txSender.provider = newProvider;
298
+ this.txSender.wallet = newWallet;
278
299
  this.wallet = newWallet;
279
300
  this.provider = newProvider;
280
301
  this.program = newProgram;
@@ -304,7 +325,7 @@ class DriftClient {
304
325
  this.userStats = new userStats_1.UserStats({
305
326
  driftClient: this,
306
327
  userStatsAccountPublicKey: this.getUserStatsAccountPublicKey(),
307
- accountSubscription: this.userAccountSubscriptionConfig,
328
+ accountSubscription: this.userStatsAccountSubscriptionConfig,
308
329
  });
309
330
  await this.userStats.subscribe();
310
331
  }
@@ -487,6 +508,27 @@ class DriftClient {
487
508
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
488
509
  return txSig;
489
510
  }
511
+ async getUpdateUserMarginTradingEnabledIx(marginTradingEnabled, subAccountId = 0, userAccountPublicKey) {
512
+ const userAccountPublicKeyToUse = userAccountPublicKey ||
513
+ (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
514
+ await this.addUser(subAccountId, this.wallet.publicKey);
515
+ let remainingAccounts;
516
+ try {
517
+ remainingAccounts = this.getRemainingAccounts({
518
+ userAccounts: [this.getUserAccount(subAccountId)],
519
+ });
520
+ }
521
+ catch (err) {
522
+ remainingAccounts = [];
523
+ }
524
+ return await this.program.instruction.updateUserMarginTradingEnabled(subAccountId, marginTradingEnabled, {
525
+ accounts: {
526
+ user: userAccountPublicKeyToUse,
527
+ authority: this.wallet.publicKey,
528
+ },
529
+ remainingAccounts,
530
+ });
531
+ }
490
532
  async updateUserMarginTradingEnabled(marginTradingEnabled, subAccountId = 0) {
491
533
  const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
492
534
  await this.addUser(subAccountId, this.wallet.publicKey);
@@ -606,10 +648,16 @@ class DriftClient {
606
648
  authority = authority !== null && authority !== void 0 ? authority : this.authority;
607
649
  const userMapKey = this.getUserMapKey(subAccountId, authority);
608
650
  if (!this.users.has(userMapKey)) {
609
- throw new Error(`Clearing House has no user for user id ${userMapKey}`);
651
+ throw new Error(`DriftClient has no user for user id ${userMapKey}`);
610
652
  }
611
653
  return this.users.get(userMapKey);
612
654
  }
655
+ hasUser(subAccountId, authority) {
656
+ subAccountId = subAccountId !== null && subAccountId !== void 0 ? subAccountId : this.activeSubAccountId;
657
+ authority = authority !== null && authority !== void 0 ? authority : this.authority;
658
+ const userMapKey = this.getUserMapKey(subAccountId, authority);
659
+ return this.users.has(userMapKey);
660
+ }
613
661
  getUsers() {
614
662
  // delegate users get added to the end
615
663
  return [...this.users.values()]
@@ -692,6 +740,21 @@ class DriftClient {
692
740
  amount = typeof amount === 'number' ? new anchor_1.BN(amount) : amount;
693
741
  return amount.mul(numericConstants_1.PRICE_PRECISION);
694
742
  }
743
+ /**
744
+ * Each drift instruction must include perp and sport market accounts in the ix remaining accounts.
745
+ * Use this function to force a subset of markets to be included in the remaining accounts for every ix
746
+ *
747
+ * @param perpMarketIndexes
748
+ * @param spotMarketIndexes
749
+ */
750
+ mustIncludeMarketsInIx({ perpMarketIndexes, spotMarketIndexes, }) {
751
+ perpMarketIndexes.forEach((perpMarketIndex) => {
752
+ this.mustIncludePerpMarketIndexes.add(perpMarketIndex);
753
+ });
754
+ spotMarketIndexes.forEach((spotMarketIndex) => {
755
+ this.mustIncludeSpotMarketIndexes.add(spotMarketIndex);
756
+ });
757
+ }
695
758
  getRemainingAccounts(params) {
696
759
  var _a;
697
760
  const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } = this.getRemainingAccountMapsForUsers(params.userAccounts);
@@ -701,30 +764,7 @@ class DriftClient {
701
764
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
702
765
  // otherwise remove from slot
703
766
  if (slot > lastUserSlot) {
704
- const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
705
- perpMarketAccountMap.set(marketIndex, {
706
- pubkey: perpMarketAccount.pubkey,
707
- isSigner: false,
708
- isWritable: false,
709
- });
710
- oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
711
- pubkey: perpMarketAccount.amm.oracle,
712
- isSigner: false,
713
- isWritable: false,
714
- });
715
- const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
716
- spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
717
- pubkey: spotMarketAccount.pubkey,
718
- isSigner: false,
719
- isWritable: false,
720
- });
721
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
722
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
723
- pubkey: spotMarketAccount.oracle,
724
- isSigner: false,
725
- isWritable: false,
726
- });
727
- }
767
+ this.addPerpMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
728
768
  }
729
769
  else {
730
770
  this.perpMarketLastSlotCache.delete(marketIndex);
@@ -734,19 +774,7 @@ class DriftClient {
734
774
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
735
775
  // otherwise remove from slot
736
776
  if (slot > lastUserSlot) {
737
- const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
738
- spotMarketAccountMap.set(marketIndex, {
739
- pubkey: spotMarketAccount.pubkey,
740
- isSigner: false,
741
- isWritable: false,
742
- });
743
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
744
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
745
- pubkey: spotMarketAccount.oracle,
746
- isSigner: false,
747
- isWritable: false,
748
- });
749
- }
777
+ this.addSpotMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap);
750
778
  }
751
779
  else {
752
780
  this.spotMarketLastSlotCache.delete(marketIndex);
@@ -754,91 +782,32 @@ class DriftClient {
754
782
  }
755
783
  }
756
784
  if (params.readablePerpMarketIndex !== undefined) {
757
- const perpMarketAccount = this.getPerpMarketAccount(params.readablePerpMarketIndex);
758
- perpMarketAccountMap.set(params.readablePerpMarketIndex, {
759
- pubkey: perpMarketAccount.pubkey,
760
- isSigner: false,
761
- isWritable: false,
762
- });
763
- oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
764
- pubkey: perpMarketAccount.amm.oracle,
765
- isSigner: false,
766
- isWritable: false,
767
- });
768
- const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
769
- spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
770
- pubkey: spotMarketAccount.pubkey,
771
- isSigner: false,
772
- isWritable: false,
773
- });
774
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
775
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
776
- pubkey: spotMarketAccount.oracle,
777
- isSigner: false,
778
- isWritable: false,
779
- });
785
+ const readablePerpMarketIndexes = Array.isArray(params.readablePerpMarketIndex)
786
+ ? params.readablePerpMarketIndex
787
+ : [params.readablePerpMarketIndex];
788
+ for (const marketIndex of readablePerpMarketIndexes) {
789
+ this.addPerpMarketToRemainingAccountMaps(marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
780
790
  }
781
791
  }
792
+ for (const perpMarketIndex of this.mustIncludePerpMarketIndexes.values()) {
793
+ this.addPerpMarketToRemainingAccountMaps(perpMarketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
794
+ }
782
795
  if (params.readableSpotMarketIndexes !== undefined) {
783
796
  for (const readableSpotMarketIndex of params.readableSpotMarketIndexes) {
784
- const spotMarketAccount = this.getSpotMarketAccount(readableSpotMarketIndex);
785
- spotMarketAccountMap.set(readableSpotMarketIndex, {
786
- pubkey: spotMarketAccount.pubkey,
787
- isSigner: false,
788
- isWritable: false,
789
- });
790
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
791
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
792
- pubkey: spotMarketAccount.oracle,
793
- isSigner: false,
794
- isWritable: false,
795
- });
796
- }
797
+ this.addSpotMarketToRemainingAccountMaps(readableSpotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
797
798
  }
798
799
  }
800
+ for (const spotMarketIndex of this.mustIncludeSpotMarketIndexes.values()) {
801
+ this.addSpotMarketToRemainingAccountMaps(spotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
802
+ }
799
803
  if (params.writablePerpMarketIndexes !== undefined) {
800
804
  for (const writablePerpMarketIndex of params.writablePerpMarketIndexes) {
801
- const perpMarketAccount = this.getPerpMarketAccount(writablePerpMarketIndex);
802
- perpMarketAccountMap.set(writablePerpMarketIndex, {
803
- pubkey: perpMarketAccount.pubkey,
804
- isSigner: false,
805
- isWritable: true,
806
- });
807
- oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
808
- pubkey: perpMarketAccount.amm.oracle,
809
- isSigner: false,
810
- isWritable: false,
811
- });
812
- const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
813
- spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
814
- pubkey: spotMarketAccount.pubkey,
815
- isSigner: false,
816
- isWritable: false,
817
- });
818
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
819
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
820
- pubkey: spotMarketAccount.oracle,
821
- isSigner: false,
822
- isWritable: false,
823
- });
824
- }
805
+ this.addPerpMarketToRemainingAccountMaps(writablePerpMarketIndex, true, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
825
806
  }
826
807
  }
827
808
  if (params.writableSpotMarketIndexes !== undefined) {
828
809
  for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
829
- const spotMarketAccount = this.getSpotMarketAccount(writableSpotMarketIndex);
830
- spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
831
- pubkey: spotMarketAccount.pubkey,
832
- isSigner: false,
833
- isWritable: true,
834
- });
835
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
836
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
837
- pubkey: spotMarketAccount.oracle,
838
- isSigner: false,
839
- isWritable: false,
840
- });
841
- }
810
+ this.addSpotMarketToRemainingAccountMaps(writableSpotMarketIndex, true, oracleAccountMap, spotMarketAccountMap);
842
811
  }
843
812
  }
844
813
  return [
@@ -847,6 +816,35 @@ class DriftClient {
847
816
  ...perpMarketAccountMap.values(),
848
817
  ];
849
818
  }
819
+ addPerpMarketToRemainingAccountMaps(marketIndex, writable, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap) {
820
+ const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
821
+ perpMarketAccountMap.set(marketIndex, {
822
+ pubkey: perpMarketAccount.pubkey,
823
+ isSigner: false,
824
+ isWritable: writable,
825
+ });
826
+ oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
827
+ pubkey: perpMarketAccount.amm.oracle,
828
+ isSigner: false,
829
+ isWritable: false,
830
+ });
831
+ this.addSpotMarketToRemainingAccountMaps(perpMarketAccount.quoteSpotMarketIndex, false, oracleAccountMap, spotMarketAccountMap);
832
+ }
833
+ addSpotMarketToRemainingAccountMaps(marketIndex, writable, oracleAccountMap, spotMarketAccountMap) {
834
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
835
+ spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
836
+ pubkey: spotMarketAccount.pubkey,
837
+ isSigner: false,
838
+ isWritable: writable,
839
+ });
840
+ if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
841
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
842
+ pubkey: spotMarketAccount.oracle,
843
+ isSigner: false,
844
+ isWritable: false,
845
+ });
846
+ }
847
+ }
850
848
  getRemainingAccountMapsForUsers(userAccounts) {
851
849
  const oracleAccountMap = new Map();
852
850
  const spotMarketAccountMap = new Map();
@@ -854,63 +852,16 @@ class DriftClient {
854
852
  for (const userAccount of userAccounts) {
855
853
  for (const spotPosition of userAccount.spotPositions) {
856
854
  if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
857
- const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
858
- spotMarketAccountMap.set(spotPosition.marketIndex, {
859
- pubkey: spotMarket.pubkey,
860
- isSigner: false,
861
- isWritable: false,
862
- });
863
- if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
864
- oracleAccountMap.set(spotMarket.oracle.toString(), {
865
- pubkey: spotMarket.oracle,
866
- isSigner: false,
867
- isWritable: false,
868
- });
869
- }
855
+ this.addSpotMarketToRemainingAccountMaps(spotPosition.marketIndex, false, oracleAccountMap, spotMarketAccountMap);
870
856
  if (!spotPosition.openAsks.eq(numericConstants_1.ZERO) ||
871
857
  !spotPosition.openBids.eq(numericConstants_1.ZERO)) {
872
- const quoteSpotMarket = this.getQuoteSpotMarketAccount();
873
- spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
874
- pubkey: quoteSpotMarket.pubkey,
875
- isSigner: false,
876
- isWritable: false,
877
- });
878
- if (!quoteSpotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
879
- oracleAccountMap.set(quoteSpotMarket.oracle.toString(), {
880
- pubkey: quoteSpotMarket.oracle,
881
- isSigner: false,
882
- isWritable: false,
883
- });
884
- }
858
+ this.addSpotMarketToRemainingAccountMaps(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, false, oracleAccountMap, spotMarketAccountMap);
885
859
  }
886
860
  }
887
861
  }
888
862
  for (const position of userAccount.perpPositions) {
889
863
  if (!(0, position_1.positionIsAvailable)(position)) {
890
- const perpMarketAccount = this.getPerpMarketAccount(position.marketIndex);
891
- perpMarketAccountMap.set(position.marketIndex, {
892
- pubkey: perpMarketAccount.pubkey,
893
- isWritable: false,
894
- isSigner: false,
895
- });
896
- oracleAccountMap.set(perpMarketAccount.amm.oracle.toString(), {
897
- pubkey: perpMarketAccount.amm.oracle,
898
- isWritable: false,
899
- isSigner: false,
900
- });
901
- const spotMarketAccount = this.getSpotMarketAccount(perpMarketAccount.quoteSpotMarketIndex);
902
- spotMarketAccountMap.set(perpMarketAccount.quoteSpotMarketIndex, {
903
- pubkey: spotMarketAccount.pubkey,
904
- isSigner: false,
905
- isWritable: false,
906
- });
907
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
908
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
909
- pubkey: spotMarketAccount.oracle,
910
- isSigner: false,
911
- isWritable: false,
912
- });
913
- }
864
+ this.addPerpMarketToRemainingAccountMaps(position.marketIndex, false, oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap);
914
865
  }
915
866
  }
916
867
  }
@@ -1064,7 +1015,7 @@ class DriftClient {
1064
1015
  return (0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, associatedTokenAddress, this.wallet.publicKey, tokenMintAddress);
1065
1016
  }
1066
1017
  /**
1067
- * Creates the Clearing House User account for a user, and deposits some initial collateral
1018
+ * Creates the User account for a user, and deposits some initial collateral
1068
1019
  * @param amount
1069
1020
  * @param userTokenAccount
1070
1021
  * @param marketIndex
@@ -1349,6 +1300,19 @@ class DriftClient {
1349
1300
  remainingAccounts: remainingAccounts,
1350
1301
  });
1351
1302
  }
1303
+ getQuoteValuePerLpShare(marketIndex) {
1304
+ const perpMarketAccount = this.getPerpMarketAccount(marketIndex);
1305
+ const openBids = anchor_1.BN.max(perpMarketAccount.amm.baseAssetReserve.sub(perpMarketAccount.amm.minBaseAssetReserve), numericConstants_1.ZERO);
1306
+ const openAsks = anchor_1.BN.max(perpMarketAccount.amm.maxBaseAssetReserve.sub(perpMarketAccount.amm.baseAssetReserve), numericConstants_1.ZERO);
1307
+ const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex);
1308
+ const maxOpenBidsAsks = anchor_1.BN.max(openBids, openAsks);
1309
+ const quoteValuePerLpShare = maxOpenBidsAsks
1310
+ .mul(oraclePriceData.price)
1311
+ .mul(numericConstants_1.QUOTE_PRECISION)
1312
+ .div(numericConstants_1.PRICE_PRECISION)
1313
+ .div(perpMarketAccount.amm.sqrtK);
1314
+ return quoteValuePerLpShare;
1315
+ }
1352
1316
  /**
1353
1317
  * @deprecated use {@link placePerpOrder} or {@link placeAndTakePerpOrder} instead
1354
1318
  */
@@ -1608,23 +1572,45 @@ class DriftClient {
1608
1572
  });
1609
1573
  }
1610
1574
  async cancelAndPlaceOrders(cancelOrderParams, placeOrderParams, txParams) {
1611
- const tx = (0, utils_1.wrapInTx)(await this.getCancelOrdersIx(cancelOrderParams.marketType, cancelOrderParams.marketIndex, cancelOrderParams.direction), txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits, txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice);
1612
- for (const placeOrderParam of placeOrderParams) {
1613
- const marketType = placeOrderParam.marketType;
1614
- if (!marketType) {
1615
- throw new Error('marketType must be set on placeOrderParams');
1616
- }
1617
- let ix;
1618
- if ((0, types_1.isVariant)(marketType, 'perp')) {
1619
- ix = this.getPlacePerpOrderIx(placeOrderParam);
1575
+ const ixs = [
1576
+ await this.getCancelOrdersIx(cancelOrderParams.marketType, cancelOrderParams.marketIndex, cancelOrderParams.direction),
1577
+ await this.getPlaceOrdersIx(placeOrderParams),
1578
+ ];
1579
+ const tx = await this.buildTransaction(ixs, txParams);
1580
+ const { txSig } = await this.sendTransaction(tx, [], this.opts);
1581
+ return txSig;
1582
+ }
1583
+ async placeOrders(params, txParams) {
1584
+ const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getPlaceOrdersIx(params), txParams), [], this.opts);
1585
+ return txSig;
1586
+ }
1587
+ async getPlaceOrdersIx(params) {
1588
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1589
+ const readablePerpMarketIndex = [];
1590
+ const readableSpotMarketIndexes = [];
1591
+ for (const param of params) {
1592
+ if ((0, types_1.isVariant)(param.marketType, 'perp')) {
1593
+ readablePerpMarketIndex.push(param.marketIndex);
1620
1594
  }
1621
1595
  else {
1622
- ix = this.getPlaceSpotOrderIx(placeOrderParam);
1596
+ readableSpotMarketIndexes.push(param.marketIndex);
1623
1597
  }
1624
- tx.add(ix);
1625
1598
  }
1626
- const { txSig } = await this.sendTransaction(tx, [], this.opts);
1627
- return txSig;
1599
+ const remainingAccounts = this.getRemainingAccounts({
1600
+ userAccounts: [this.getUserAccount()],
1601
+ readablePerpMarketIndex,
1602
+ readableSpotMarketIndexes,
1603
+ useMarketLastSlotCache: true,
1604
+ });
1605
+ return await this.program.instruction.placeOrders(params, {
1606
+ accounts: {
1607
+ state: await this.getStatePublicKey(),
1608
+ user: userAccountPublicKey,
1609
+ userStats: this.getUserStatsAccountPublicKey(),
1610
+ authority: this.wallet.publicKey,
1611
+ },
1612
+ remainingAccounts,
1613
+ });
1628
1614
  }
1629
1615
  async fillPerpOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo, txParams) {
1630
1616
  const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getFillPerpOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo), txParams), [], this.opts);
@@ -1960,6 +1946,25 @@ class DriftClient {
1960
1946
  * @param txParams
1961
1947
  */
1962
1948
  async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, }) {
1949
+ const { ixs, lookupTables } = await this.getJupiterSwapIx({
1950
+ jupiterClient,
1951
+ outMarketIndex,
1952
+ inMarketIndex,
1953
+ outAssociatedTokenAccount,
1954
+ inAssociatedTokenAccount,
1955
+ amount,
1956
+ slippageBps,
1957
+ swapMode,
1958
+ route,
1959
+ reduceOnly,
1960
+ });
1961
+ const tx = (await this.buildTransaction(ixs, txParams, 0, lookupTables));
1962
+ const { txSig, slot } = await this.sendTransaction(tx);
1963
+ this.spotMarketLastSlotCache.set(outMarketIndex, slot);
1964
+ this.spotMarketLastSlotCache.set(inMarketIndex, slot);
1965
+ return txSig;
1966
+ }
1967
+ async getJupiterSwapIx({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, userAccountPublicKey, }) {
1963
1968
  const outMarket = this.getSpotMarketAccount(outMarketIndex);
1964
1969
  const inMarket = this.getSpotMarketAccount(inMarketIndex);
1965
1970
  if (!route) {
@@ -2010,18 +2015,15 @@ class DriftClient {
2010
2015
  inTokenAccount: inAssociatedTokenAccount,
2011
2016
  outTokenAccount: outAssociatedTokenAccount,
2012
2017
  reduceOnly,
2018
+ userAccountPublicKey,
2013
2019
  });
2014
- const instructions = [
2020
+ const ixs = [
2015
2021
  ...preInstructions,
2016
2022
  beginSwapIx,
2017
2023
  ...jupiterInstructions,
2018
2024
  endSwapIx,
2019
2025
  ];
2020
- const tx = (await this.buildTransaction(instructions, txParams, 0, lookupTables));
2021
- const { txSig, slot } = await this.sendTransaction(tx);
2022
- this.spotMarketLastSlotCache.set(outMarketIndex, slot);
2023
- this.spotMarketLastSlotCache.set(inMarketIndex, slot);
2024
- return txSig;
2026
+ return { ixs, lookupTables };
2025
2027
  }
2026
2028
  /**
2027
2029
  * Get the drift begin_swap and end_swap instructions
@@ -2032,11 +2034,14 @@ class DriftClient {
2032
2034
  * @param inTokenAccount the token account to move the tokens being sold
2033
2035
  * @param outTokenAccount the token account to receive the tokens being bought
2034
2036
  * @param limitPrice the limit price of the swap
2037
+ * @param reduceOnly
2038
+ * @param userAccountPublicKey optional, specify a custom userAccountPublicKey to use instead of getting the current user account; can be helpful if the account is being created within the current tx
2035
2039
  */
2036
- async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, }) {
2037
- const userAccountPublicKey = await this.getUserAccountPublicKey();
2040
+ async getSwapIx({ outMarketIndex, inMarketIndex, amountIn, inTokenAccount, outTokenAccount, limitPrice, reduceOnly, userAccountPublicKey, }) {
2041
+ const userAccountPublicKeyToUse = userAccountPublicKey || (await this.getUserAccountPublicKey());
2042
+ const userAccounts = this.hasUser() ? [this.getUserAccount()] : [];
2038
2043
  const remainingAccounts = this.getRemainingAccounts({
2039
- userAccounts: [this.getUserAccount()],
2044
+ userAccounts,
2040
2045
  writableSpotMarketIndexes: [outMarketIndex, inMarketIndex],
2041
2046
  });
2042
2047
  const outSpotMarket = this.getSpotMarketAccount(outMarketIndex);
@@ -2044,7 +2049,7 @@ class DriftClient {
2044
2049
  const beginSwapIx = await this.program.instruction.beginSwap(inMarketIndex, outMarketIndex, amountIn, {
2045
2050
  accounts: {
2046
2051
  state: await this.getStatePublicKey(),
2047
- user: userAccountPublicKey,
2052
+ user: userAccountPublicKeyToUse,
2048
2053
  userStats: this.getUserStatsAccountPublicKey(),
2049
2054
  authority: this.authority,
2050
2055
  outSpotMarketVault: outSpotMarket.vault,
@@ -2060,7 +2065,7 @@ class DriftClient {
2060
2065
  const endSwapIx = await this.program.instruction.endSwap(inMarketIndex, outMarketIndex, limitPrice !== null && limitPrice !== void 0 ? limitPrice : null, reduceOnly !== null && reduceOnly !== void 0 ? reduceOnly : null, {
2061
2066
  accounts: {
2062
2067
  state: await this.getStatePublicKey(),
2063
- user: userAccountPublicKey,
2068
+ user: userAccountPublicKeyToUse,
2064
2069
  userStats: this.getUserStatsAccountPublicKey(),
2065
2070
  authority: this.authority,
2066
2071
  outSpotMarketVault: outSpotMarket.vault,
@@ -2075,6 +2080,40 @@ class DriftClient {
2075
2080
  });
2076
2081
  return { beginSwapIx, endSwapIx };
2077
2082
  }
2083
+ async stakeForMSOL({ amount }) {
2084
+ const ixs = await this.getStakeForMSOLIx({ amount });
2085
+ const tx = await this.buildTransaction(ixs);
2086
+ return this.sendTransaction(tx);
2087
+ }
2088
+ async getStakeForMSOLIx({ amount, userAccountPublicKey, }) {
2089
+ const wSOLMint = this.getSpotMarketAccount(1).mint;
2090
+ const mSOLAccount = await this.getAssociatedTokenAccount(2);
2091
+ const wSOLAccount = await this.getAssociatedTokenAccount(1, false);
2092
+ const wSOLAccountExists = await this.checkIfAccountExists(wSOLAccount);
2093
+ const closeWSOLIx = (0, spl_token_1.createCloseAccountInstruction)(wSOLAccount, this.wallet.publicKey, this.wallet.publicKey);
2094
+ const createWSOLIx = await this.createAssociatedTokenAccountIdempotentInstruction(wSOLAccount, this.wallet.publicKey, this.wallet.publicKey, wSOLMint);
2095
+ const { beginSwapIx, endSwapIx } = await this.getSwapIx({
2096
+ inMarketIndex: 1,
2097
+ outMarketIndex: 2,
2098
+ amountIn: amount,
2099
+ inTokenAccount: wSOLAccount,
2100
+ outTokenAccount: mSOLAccount,
2101
+ userAccountPublicKey,
2102
+ });
2103
+ const program = (0, marinade_1.getMarinadeFinanceProgram)(this.provider);
2104
+ const depositIx = await (0, marinade_1.getMarinadeDepositIx)({
2105
+ program,
2106
+ mSOLAccount: mSOLAccount,
2107
+ transferFrom: this.wallet.publicKey,
2108
+ amount,
2109
+ });
2110
+ const ixs = [];
2111
+ if (!wSOLAccountExists) {
2112
+ ixs.push(createWSOLIx);
2113
+ }
2114
+ ixs.push(beginSwapIx, closeWSOLIx, depositIx, createWSOLIx, endSwapIx);
2115
+ return ixs;
2116
+ }
2078
2117
  async triggerOrder(userAccountPublicKey, user, order, txParams) {
2079
2118
  const { txSig } = await this.sendTransaction(await this.buildTransaction(await this.getTriggerOrderIx(userAccountPublicKey, user, order), txParams), [], this.opts);
2080
2119
  return txSig;
@@ -3049,13 +3088,13 @@ class DriftClient {
3049
3088
  async buildTransaction(instructions, txParams, txVersion, lookupTables) {
3050
3089
  var _a, _b;
3051
3090
  const allIx = [];
3052
- const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000;
3091
+ const computeUnits = (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : this.txParams.computeUnits;
3053
3092
  if (computeUnits !== 200000) {
3054
3093
  allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
3055
3094
  units: computeUnits,
3056
3095
  }));
3057
3096
  }
3058
- const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : 0;
3097
+ const computeUnitsPrice = (_b = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) !== null && _b !== void 0 ? _b : this.txParams.computeUnitsPrice;
3059
3098
  if (computeUnitsPrice !== 0) {
3060
3099
  allIx.push(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
3061
3100
  microLamports: computeUnitsPrice,