@drift-labs/sdk 2.21.0-beta.1 → 2.21.0

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.
@@ -14,9 +14,8 @@ export declare class PollingUserAccountSubscriber implements UserAccountSubscrib
14
14
  accountLoader: BulkAccountLoader;
15
15
  accountsToPoll: Map<string, AccountToPoll>;
16
16
  errorCallbackId?: string;
17
- lazyDecode: boolean;
18
17
  user?: DataAndSlot<UserAccount>;
19
- constructor(program: Program, userAccountPublicKey: PublicKey, accountLoader: BulkAccountLoader, lazyDecode?: boolean);
18
+ constructor(program: Program, userAccountPublicKey: PublicKey, accountLoader: BulkAccountLoader);
20
19
  subscribe(): Promise<boolean>;
21
20
  addToAccountLoader(): Promise<void>;
22
21
  fetchIfUnloaded(): Promise<void>;
@@ -5,14 +5,13 @@ const types_1 = require("./types");
5
5
  const events_1 = require("events");
6
6
  const utils_1 = require("./utils");
7
7
  class PollingUserAccountSubscriber {
8
- constructor(program, userAccountPublicKey, accountLoader, lazyDecode = false) {
8
+ constructor(program, userAccountPublicKey, accountLoader) {
9
9
  this.accountsToPoll = new Map();
10
10
  this.isSubscribed = false;
11
11
  this.program = program;
12
12
  this.accountLoader = accountLoader;
13
13
  this.eventEmitter = new events_1.EventEmitter();
14
14
  this.userAccountPublicKey = userAccountPublicKey;
15
- this.lazyDecode = lazyDecode;
16
15
  }
17
16
  async subscribe() {
18
17
  if (this.isSubscribed) {
@@ -41,9 +40,7 @@ class PollingUserAccountSubscriber {
41
40
  return;
42
41
  }
43
42
  const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
44
- if (!this.lazyDecode) {
45
- this[accountToPoll.key] = { data: account, slot };
46
- }
43
+ this[accountToPoll.key] = { data: account, slot };
47
44
  // @ts-ignore
48
45
  this.eventEmitter.emit(accountToPoll.eventType, account);
49
46
  this.eventEmitter.emit('update');
@@ -56,12 +53,7 @@ class PollingUserAccountSubscriber {
56
53
  async fetchIfUnloaded() {
57
54
  let shouldFetch = false;
58
55
  for (const [_, accountToPoll] of this.accountsToPoll) {
59
- if (!this.lazyDecode && this[accountToPoll.key] === undefined) {
60
- shouldFetch = true;
61
- break;
62
- }
63
- else if (this.lazyDecode &&
64
- this.accountLoader.bufferAndSlotMap.has(accountToPoll.publicKey.toString())) {
56
+ if (this[accountToPoll.key] === undefined) {
65
57
  shouldFetch = true;
66
58
  break;
67
59
  }
@@ -74,7 +66,7 @@ class PollingUserAccountSubscriber {
74
66
  await this.accountLoader.load();
75
67
  for (const [_, accountToPoll] of this.accountsToPoll) {
76
68
  const { buffer, slot } = this.accountLoader.getBufferAndSlot(accountToPoll.publicKey);
77
- if (buffer && !this.lazyDecode) {
69
+ if (buffer) {
78
70
  const account = this.program.account[accountToPoll.key].coder.accounts.decode((0, utils_1.capitalize)(accountToPoll.key), buffer);
79
71
  this[accountToPoll.key] = { data: account, slot };
80
72
  }
@@ -83,7 +75,7 @@ class PollingUserAccountSubscriber {
83
75
  doAccountsExist() {
84
76
  let success = true;
85
77
  for (const [_, accountToPoll] of this.accountsToPoll) {
86
- if (!this.accountLoader.bufferAndSlotMap.has(accountToPoll.publicKey.toString())) {
78
+ if (!this[accountToPoll.key]) {
87
79
  success = false;
88
80
  break;
89
81
  }
@@ -109,14 +101,7 @@ class PollingUserAccountSubscriber {
109
101
  }
110
102
  getUserAccountAndSlot() {
111
103
  this.assertIsSubscribed();
112
- if (!this.lazyDecode) {
113
- return this.user;
114
- }
115
- else {
116
- const { buffer, slot } = this.accountLoader.getBufferAndSlot(this.userAccountPublicKey);
117
- const account = this.program.account.user.coder.accounts.decode('User', buffer);
118
- return { data: account, slot };
119
- }
104
+ return this.user;
120
105
  }
121
106
  }
122
107
  exports.PollingUserAccountSubscriber = PollingUserAccountSubscriber;
package/lib/dlob/DLOB.js CHANGED
@@ -633,8 +633,10 @@ class DLOB {
633
633
  * @returns
634
634
  */
635
635
  *getMakerLimitAsks(marketIndex, slot, marketType, oraclePriceData, fallbackBid) {
636
+ const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
636
637
  for (const node of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
637
- if (fallbackBid &&
638
+ if (isPerpMarket &&
639
+ fallbackBid &&
638
640
  node.getPrice(oraclePriceData, slot).lte(fallbackBid)) {
639
641
  continue;
640
642
  }
@@ -668,8 +670,10 @@ class DLOB {
668
670
  * @returns
669
671
  */
670
672
  *getMakerLimitBids(marketIndex, slot, marketType, oraclePriceData, fallbackAsk) {
673
+ const isPerpMarket = (0, __1.isVariant)(marketType, 'perp');
671
674
  for (const node of this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData)) {
672
- if (fallbackAsk &&
675
+ if (isPerpMarket &&
676
+ fallbackAsk &&
673
677
  node.getPrice(oraclePriceData, slot).gte(fallbackAsk)) {
674
678
  continue;
675
679
  }
@@ -104,6 +104,7 @@ export declare class DriftClient {
104
104
  fetchAllUserAccounts(includeIdle?: boolean): Promise<ProgramAccount<UserAccount>[]>;
105
105
  getUserAccountsForDelegate(delegate: PublicKey): Promise<UserAccount[]>;
106
106
  getUserAccountsForAuthority(authority: PublicKey): Promise<UserAccount[]>;
107
+ getReferrerNameAccountsForAuthority(authority: PublicKey): Promise<ReferrerNameAccount[]>;
107
108
  deleteUser(subAccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
108
109
  getUser(subAccountId?: number): User;
109
110
  getUsers(): User[];
@@ -145,7 +146,7 @@ export declare class DriftClient {
145
146
  * @param fromSubAccountId
146
147
  * @returns
147
148
  */
148
- initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
149
+ initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, marketIndex?: number, subAccountId?: number, name?: string, fromSubAccountId?: number, referrerInfo?: ReferrerInfo, txParams?: TxParams): Promise<[TransactionSignature, PublicKey]>;
149
150
  initializeUserAccountForDevnet(subAccountId: number, name: string, marketIndex: number, tokenFaucet: TokenFaucet, amount: BN, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
150
151
  withdraw(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionSignature>;
151
152
  getWithdrawIx(amount: BN, marketIndex: number, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionInstruction>;
@@ -79,7 +79,6 @@ class DriftClient {
79
79
  ? {
80
80
  type: 'polling',
81
81
  accountLoader: config.accountSubscription.accountLoader,
82
- lazyDecode: config.accountSubscription.lazyDecode,
83
82
  }
84
83
  : {
85
84
  type: 'websocket',
@@ -362,7 +361,7 @@ class DriftClient {
362
361
  async initializeReferrerName(name) {
363
362
  const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, 0);
364
363
  const nameBuffer = (0, userName_1.encodeName)(name);
365
- const referrerNameAccountPublicKey = await (0, pda_1.getReferrerNamePublicKeySync)(this.program.programId, nameBuffer);
364
+ const referrerNameAccountPublicKey = (0, pda_1.getReferrerNamePublicKeySync)(this.program.programId, nameBuffer);
366
365
  const tx = await this.program.transaction.initializeReferrerName(nameBuffer, {
367
366
  accounts: {
368
367
  referrerName: referrerNameAccountPublicKey,
@@ -463,6 +462,18 @@ class DriftClient {
463
462
  ]);
464
463
  return programAccounts.map((programAccount) => programAccount.account);
465
464
  }
465
+ async getReferrerNameAccountsForAuthority(authority) {
466
+ const programAccounts = await this.program.account.referrerName.all([
467
+ {
468
+ memcmp: {
469
+ offset: 8,
470
+ /** data to match, as base-58 encoded string and limited to less than 129 bytes */
471
+ bytes: bs58_1.default.encode(authority.toBuffer()),
472
+ },
473
+ },
474
+ ]);
475
+ return programAccounts.map((programAccount) => programAccount.account);
476
+ }
466
477
  async deleteUser(subAccountId = 0, txParams) {
467
478
  var _a;
468
479
  const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
@@ -821,12 +832,21 @@ class DriftClient {
821
832
  * @param fromSubAccountId
822
833
  * @returns
823
834
  */
824
- async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo) {
835
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, marketIndex = 0, subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, fromSubAccountId, referrerInfo, txParams) {
836
+ var _a;
825
837
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(subAccountId, name, referrerInfo);
826
838
  const additionalSigners = [];
827
839
  const spotMarket = this.getSpotMarketAccount(marketIndex);
828
840
  const isSolMarket = spotMarket.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
829
841
  const tx = new web3_js_1.Transaction();
842
+ tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
843
+ units: (_a = txParams === null || txParams === void 0 ? void 0 : txParams.computeUnits) !== null && _a !== void 0 ? _a : 600000,
844
+ }));
845
+ if (txParams === null || txParams === void 0 ? void 0 : txParams.computeUnitsPrice) {
846
+ tx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
847
+ microLamports: txParams.computeUnitsPrice,
848
+ }));
849
+ }
830
850
  const authority = this.wallet.publicKey;
831
851
  const createWSOLTokenAccount = isSolMarket && userTokenAccount.equals(authority);
832
852
  if (createWSOLTokenAccount) {
@@ -25,7 +25,6 @@ export type DriftClientSubscriptionConfig = {
25
25
  } | {
26
26
  type: 'polling';
27
27
  accountLoader: BulkAccountLoader;
28
- lazyDecode?: boolean;
29
28
  };
30
29
  type TxSenderConfig = {
31
30
  type: 'retry';
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.21.0-beta.1",
2
+ "version": "2.21.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
package/lib/user.js CHANGED
@@ -25,7 +25,7 @@ class User {
25
25
  this.driftClient = config.driftClient;
26
26
  this.userAccountPublicKey = config.userAccountPublicKey;
27
27
  if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) === 'polling') {
28
- this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, config.accountSubscription.accountLoader, config.accountSubscription.lazyDecode);
28
+ this.accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey, config.accountSubscription.accountLoader);
29
29
  }
30
30
  else {
31
31
  this.accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.driftClient.program, config.userAccountPublicKey);
@@ -11,5 +11,4 @@ export type UserSubscriptionConfig = {
11
11
  } | {
12
12
  type: 'polling';
13
13
  accountLoader: BulkAccountLoader;
14
- lazyDecode?: boolean;
15
14
  };
@@ -40,4 +40,5 @@ export declare class UserMap implements UserMapInterface {
40
40
  updateWithEventRecord(record: WrappedEvent<any>): Promise<void>;
41
41
  values(): IterableIterator<User>;
42
42
  size(): number;
43
+ sync(includeIdle?: boolean): Promise<void>;
43
44
  }
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.UserMap = void 0;
4
7
  const __1 = require("..");
5
8
  const web3_js_1 = require("@solana/web3.js");
9
+ const bs58_1 = __importDefault(require("bs58"));
6
10
  class UserMap {
7
11
  constructor(driftClient, accountSubscription) {
8
12
  this.userMap = new Map();
@@ -131,5 +135,42 @@ class UserMap {
131
135
  size() {
132
136
  return this.userMap.size;
133
137
  }
138
+ async sync(includeIdle = true) {
139
+ let filters = undefined;
140
+ if (!includeIdle) {
141
+ filters = [
142
+ {
143
+ memcmp: {
144
+ offset: 4350,
145
+ bytes: bs58_1.default.encode(Uint8Array.from([0])),
146
+ },
147
+ },
148
+ ];
149
+ }
150
+ const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
151
+ commitment: this.driftClient.connection.commitment,
152
+ filters: [
153
+ {
154
+ memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
155
+ },
156
+ ...(Array.isArray(filters) ? filters : []),
157
+ ],
158
+ });
159
+ const programAccountMap = new Map();
160
+ for (const programAccount of programAccounts) {
161
+ programAccountMap.set(programAccount.pubkey.toString(), programAccount.account);
162
+ }
163
+ for (const key of programAccountMap.keys()) {
164
+ if (!this.has(key)) {
165
+ await this.addPubkey(new web3_js_1.PublicKey(key));
166
+ }
167
+ }
168
+ for (const [key, user] of this.userMap.entries()) {
169
+ if (!programAccountMap.has(key)) {
170
+ await user.unsubscribe();
171
+ this.userMap.delete(key);
172
+ }
173
+ }
174
+ }
134
175
  }
135
176
  exports.UserMap = UserMap;
@@ -18,4 +18,5 @@ export declare class UserStatsMap {
18
18
  mustGet(authorityPublicKey: string): Promise<UserStats>;
19
19
  values(): IterableIterator<UserStats>;
20
20
  size(): number;
21
+ sync(): Promise<void>;
21
22
  }
@@ -137,5 +137,24 @@ class UserStatsMap {
137
137
  size() {
138
138
  return this.userStatsMap.size;
139
139
  }
140
+ async sync() {
141
+ const programAccounts = await this.driftClient.connection.getProgramAccounts(this.driftClient.program.programId, {
142
+ commitment: this.driftClient.connection.commitment,
143
+ filters: [
144
+ {
145
+ memcmp: this.driftClient.program.coder.accounts.memcmp('UserStats'),
146
+ },
147
+ ],
148
+ });
149
+ const programAccountMap = new Map();
150
+ for (const programAccount of programAccounts) {
151
+ programAccountMap.set(new web3_js_1.PublicKey(programAccount.account.data.slice(8, 40)).toString(), programAccount.account);
152
+ }
153
+ for (const key of programAccountMap.keys()) {
154
+ if (!this.has(key)) {
155
+ await this.addUserStat(new web3_js_1.PublicKey(key));
156
+ }
157
+ }
158
+ }
140
159
  }
141
160
  exports.UserStatsMap = UserStatsMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.21.0-beta.1",
3
+ "version": "2.21.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -23,22 +23,18 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
23
23
  accountsToPoll = new Map<string, AccountToPoll>();
24
24
  errorCallbackId?: string;
25
25
 
26
- lazyDecode: boolean;
27
-
28
26
  user?: DataAndSlot<UserAccount>;
29
27
 
30
28
  public constructor(
31
29
  program: Program,
32
30
  userAccountPublicKey: PublicKey,
33
- accountLoader: BulkAccountLoader,
34
- lazyDecode = false
31
+ accountLoader: BulkAccountLoader
35
32
  ) {
36
33
  this.isSubscribed = false;
37
34
  this.program = program;
38
35
  this.accountLoader = accountLoader;
39
36
  this.eventEmitter = new EventEmitter();
40
37
  this.userAccountPublicKey = userAccountPublicKey;
41
- this.lazyDecode = lazyDecode;
42
38
  }
43
39
 
44
40
  async subscribe(): Promise<boolean> {
@@ -79,9 +75,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
79
75
  const account = this.program.account[
80
76
  accountToPoll.key
81
77
  ].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
82
- if (!this.lazyDecode) {
83
- this[accountToPoll.key] = { data: account, slot };
84
- }
78
+ this[accountToPoll.key] = { data: account, slot };
85
79
  // @ts-ignore
86
80
  this.eventEmitter.emit(accountToPoll.eventType, account);
87
81
  this.eventEmitter.emit('update');
@@ -97,15 +91,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
97
91
  async fetchIfUnloaded(): Promise<void> {
98
92
  let shouldFetch = false;
99
93
  for (const [_, accountToPoll] of this.accountsToPoll) {
100
- if (!this.lazyDecode && this[accountToPoll.key] === undefined) {
101
- shouldFetch = true;
102
- break;
103
- } else if (
104
- this.lazyDecode &&
105
- this.accountLoader.bufferAndSlotMap.has(
106
- accountToPoll.publicKey.toString()
107
- )
108
- ) {
94
+ if (this[accountToPoll.key] === undefined) {
109
95
  shouldFetch = true;
110
96
  break;
111
97
  }
@@ -122,7 +108,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
122
108
  const { buffer, slot } = this.accountLoader.getBufferAndSlot(
123
109
  accountToPoll.publicKey
124
110
  );
125
- if (buffer && !this.lazyDecode) {
111
+ if (buffer) {
126
112
  const account = this.program.account[
127
113
  accountToPoll.key
128
114
  ].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
@@ -134,11 +120,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
134
120
  doAccountsExist(): boolean {
135
121
  let success = true;
136
122
  for (const [_, accountToPoll] of this.accountsToPoll) {
137
- if (
138
- !this.accountLoader.bufferAndSlotMap.has(
139
- accountToPoll.publicKey.toString()
140
- )
141
- ) {
123
+ if (!this[accountToPoll.key]) {
142
124
  success = false;
143
125
  break;
144
126
  }
@@ -176,17 +158,6 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
176
158
 
177
159
  public getUserAccountAndSlot(): DataAndSlot<UserAccount> {
178
160
  this.assertIsSubscribed();
179
- if (!this.lazyDecode) {
180
- return this.user;
181
- } else {
182
- const { buffer, slot } = this.accountLoader.getBufferAndSlot(
183
- this.userAccountPublicKey
184
- );
185
- const account = this.program.account.user.coder.accounts.decode(
186
- 'User',
187
- buffer
188
- );
189
- return { data: account, slot };
190
- }
161
+ return this.user;
191
162
  }
192
163
  }
package/src/dlob/DLOB.ts CHANGED
@@ -1148,6 +1148,7 @@ export class DLOB {
1148
1148
  oraclePriceData: OraclePriceData,
1149
1149
  fallbackBid?: BN
1150
1150
  ): Generator<DLOBNode> {
1151
+ const isPerpMarket = isVariant(marketType, 'perp');
1151
1152
  for (const node of this.getRestingLimitAsks(
1152
1153
  marketIndex,
1153
1154
  slot,
@@ -1155,6 +1156,7 @@ export class DLOB {
1155
1156
  oraclePriceData
1156
1157
  )) {
1157
1158
  if (
1159
+ isPerpMarket &&
1158
1160
  fallbackBid &&
1159
1161
  node.getPrice(oraclePriceData, slot).lte(fallbackBid)
1160
1162
  ) {
@@ -1213,6 +1215,7 @@ export class DLOB {
1213
1215
  oraclePriceData: OraclePriceData,
1214
1216
  fallbackAsk?: BN
1215
1217
  ): Generator<DLOBNode> {
1218
+ const isPerpMarket = isVariant(marketType, 'perp');
1216
1219
  for (const node of this.getRestingLimitBids(
1217
1220
  marketIndex,
1218
1221
  slot,
@@ -1220,6 +1223,7 @@ export class DLOB {
1220
1223
  oraclePriceData
1221
1224
  )) {
1222
1225
  if (
1226
+ isPerpMarket &&
1223
1227
  fallbackAsk &&
1224
1228
  node.getPrice(oraclePriceData, slot).gte(fallbackAsk)
1225
1229
  ) {
@@ -160,7 +160,6 @@ export class DriftClient {
160
160
  ? {
161
161
  type: 'polling',
162
162
  accountLoader: config.accountSubscription.accountLoader,
163
- lazyDecode: config.accountSubscription.lazyDecode,
164
163
  }
165
164
  : {
166
165
  type: 'websocket',
@@ -604,7 +603,7 @@ export class DriftClient {
604
603
 
605
604
  const nameBuffer = encodeName(name);
606
605
 
607
- const referrerNameAccountPublicKey = await getReferrerNamePublicKeySync(
606
+ const referrerNameAccountPublicKey = getReferrerNamePublicKeySync(
608
607
  this.program.programId,
609
608
  nameBuffer
610
609
  );
@@ -775,6 +774,24 @@ export class DriftClient {
775
774
  );
776
775
  }
777
776
 
777
+ public async getReferrerNameAccountsForAuthority(
778
+ authority: PublicKey
779
+ ): Promise<ReferrerNameAccount[]> {
780
+ const programAccounts = await this.program.account.referrerName.all([
781
+ {
782
+ memcmp: {
783
+ offset: 8,
784
+ /** data to match, as base-58 encoded string and limited to less than 129 bytes */
785
+ bytes: bs58.encode(authority.toBuffer()),
786
+ },
787
+ },
788
+ ]);
789
+
790
+ return programAccounts.map(
791
+ (programAccount) => programAccount.account as ReferrerNameAccount
792
+ );
793
+ }
794
+
778
795
  public async deleteUser(
779
796
  subAccountId = 0,
780
797
  txParams?: TxParams
@@ -1330,7 +1347,8 @@ export class DriftClient {
1330
1347
  subAccountId = 0,
1331
1348
  name = DEFAULT_USER_NAME,
1332
1349
  fromSubAccountId?: number,
1333
- referrerInfo?: ReferrerInfo
1350
+ referrerInfo?: ReferrerInfo,
1351
+ txParams?: TxParams
1334
1352
  ): Promise<[TransactionSignature, PublicKey]> {
1335
1353
  const [userAccountPublicKey, initializeUserAccountIx] =
1336
1354
  await this.getInitializeUserInstructions(
@@ -1347,6 +1365,20 @@ export class DriftClient {
1347
1365
 
1348
1366
  const tx = new Transaction();
1349
1367
 
1368
+ tx.add(
1369
+ ComputeBudgetProgram.setComputeUnitLimit({
1370
+ units: txParams?.computeUnits ?? 600_000,
1371
+ })
1372
+ );
1373
+
1374
+ if (txParams?.computeUnitsPrice) {
1375
+ tx.add(
1376
+ ComputeBudgetProgram.setComputeUnitPrice({
1377
+ microLamports: txParams.computeUnitsPrice,
1378
+ })
1379
+ );
1380
+ }
1381
+
1350
1382
  const authority = this.wallet.publicKey;
1351
1383
 
1352
1384
  const createWSOLTokenAccount =
@@ -29,7 +29,6 @@ export type DriftClientSubscriptionConfig =
29
29
  | {
30
30
  type: 'polling';
31
31
  accountLoader: BulkAccountLoader;
32
- lazyDecode?: boolean;
33
32
  };
34
33
 
35
34
  type TxSenderConfig = {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.21.0-beta.1",
2
+ "version": "2.21.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
package/src/user.ts CHANGED
@@ -95,8 +95,7 @@ export class User {
95
95
  this.accountSubscriber = new PollingUserAccountSubscriber(
96
96
  config.driftClient.program,
97
97
  config.userAccountPublicKey,
98
- config.accountSubscription.accountLoader,
99
- config.accountSubscription.lazyDecode
98
+ config.accountSubscription.accountLoader
100
99
  );
101
100
  } else {
102
101
  this.accountSubscriber = new WebSocketUserAccountSubscriber(
package/src/userConfig.ts CHANGED
@@ -15,5 +15,4 @@ export type UserSubscriptionConfig =
15
15
  | {
16
16
  type: 'polling';
17
17
  accountLoader: BulkAccountLoader;
18
- lazyDecode?: boolean;
19
18
  };
@@ -15,7 +15,9 @@ import {
15
15
  LPRecord,
16
16
  } from '..';
17
17
 
18
- import { PublicKey } from '@solana/web3.js';
18
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
19
+ import { Buffer } from 'buffer';
20
+ import bs58 from 'bs58';
19
21
 
20
22
  export interface UserMapInterface {
21
23
  fetchAllUsers(): Promise<void>;
@@ -177,4 +179,53 @@ export class UserMap implements UserMapInterface {
177
179
  public size(): number {
178
180
  return this.userMap.size;
179
181
  }
182
+
183
+ public async sync(includeIdle = true) {
184
+ let filters = undefined;
185
+ if (!includeIdle) {
186
+ filters = [
187
+ {
188
+ memcmp: {
189
+ offset: 4350,
190
+ bytes: bs58.encode(Uint8Array.from([0])),
191
+ },
192
+ },
193
+ ];
194
+ }
195
+
196
+ const programAccounts =
197
+ await this.driftClient.connection.getProgramAccounts(
198
+ this.driftClient.program.programId,
199
+ {
200
+ commitment: this.driftClient.connection.commitment,
201
+ filters: [
202
+ {
203
+ memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
204
+ },
205
+ ...(Array.isArray(filters) ? filters : []),
206
+ ],
207
+ }
208
+ );
209
+
210
+ const programAccountMap = new Map<string, AccountInfo<Buffer>>();
211
+ for (const programAccount of programAccounts) {
212
+ programAccountMap.set(
213
+ programAccount.pubkey.toString(),
214
+ programAccount.account
215
+ );
216
+ }
217
+
218
+ for (const key of programAccountMap.keys()) {
219
+ if (!this.has(key)) {
220
+ await this.addPubkey(new PublicKey(key));
221
+ }
222
+ }
223
+
224
+ for (const [key, user] of this.userMap.entries()) {
225
+ if (!programAccountMap.has(key)) {
226
+ await user.unsubscribe();
227
+ this.userMap.delete(key);
228
+ }
229
+ }
230
+ }
180
231
  }
@@ -17,9 +17,10 @@ import {
17
17
  InsuranceFundStakeRecord,
18
18
  } from '..';
19
19
  import { ProgramAccount } from '@project-serum/anchor';
20
- import { PublicKey } from '@solana/web3.js';
20
+ import { AccountInfo, PublicKey } from '@solana/web3.js';
21
21
 
22
22
  import { UserMap } from './userMap';
23
+ import { Buffer } from 'buffer';
23
24
 
24
25
  export class UserStatsMap {
25
26
  /**
@@ -190,4 +191,34 @@ export class UserStatsMap {
190
191
  public size(): number {
191
192
  return this.userStatsMap.size;
192
193
  }
194
+
195
+ public async sync() {
196
+ const programAccounts =
197
+ await this.driftClient.connection.getProgramAccounts(
198
+ this.driftClient.program.programId,
199
+ {
200
+ commitment: this.driftClient.connection.commitment,
201
+ filters: [
202
+ {
203
+ memcmp:
204
+ this.driftClient.program.coder.accounts.memcmp('UserStats'),
205
+ },
206
+ ],
207
+ }
208
+ );
209
+
210
+ const programAccountMap = new Map<string, AccountInfo<Buffer>>();
211
+ for (const programAccount of programAccounts) {
212
+ programAccountMap.set(
213
+ new PublicKey(programAccount.account.data.slice(8, 40)).toString(),
214
+ programAccount.account
215
+ );
216
+ }
217
+
218
+ for (const key of programAccountMap.keys()) {
219
+ if (!this.has(key)) {
220
+ await this.addUserStat(new PublicKey(key));
221
+ }
222
+ }
223
+ }
193
224
  }