@drift-labs/sdk 2.31.0-beta.2 → 2.31.0-beta.5

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 (65) hide show
  1. package/get_events.ts +47 -0
  2. package/lib/auctionSubscriber/auctionSubscriber.d.ts +13 -0
  3. package/lib/auctionSubscriber/auctionSubscriber.js +22 -0
  4. package/lib/auctionSubscriber/index.d.ts +2 -0
  5. package/lib/auctionSubscriber/index.js +18 -0
  6. package/lib/auctionSubscriber/types.d.ts +10 -0
  7. package/lib/auctionSubscriber/types.js +2 -0
  8. package/lib/config.js +2 -2
  9. package/lib/dlob/orderBookLevels.d.ts +1 -1
  10. package/lib/dlob/orderBookLevels.js +7 -4
  11. package/lib/driftClient.d.ts +2 -0
  12. package/lib/driftClient.js +22 -9
  13. package/lib/events/eventSubscriber.d.ts +1 -0
  14. package/lib/events/eventSubscriber.js +5 -3
  15. package/lib/events/fetchLogs.d.ts +1 -1
  16. package/lib/events/fetchLogs.js +2 -2
  17. package/lib/events/pollingLogProvider.d.ts +2 -2
  18. package/lib/events/pollingLogProvider.js +3 -3
  19. package/lib/events/types.d.ts +2 -1
  20. package/lib/events/webSocketLogProvider.d.ts +2 -2
  21. package/lib/events/webSocketLogProvider.js +3 -3
  22. package/lib/idl/drift.json +61 -2
  23. package/lib/index.d.ts +1 -0
  24. package/lib/index.js +1 -0
  25. package/lib/math/spotBalance.js +1 -1
  26. package/lib/memcmp.d.ts +6 -0
  27. package/lib/memcmp.js +53 -0
  28. package/lib/orderSubscriber/OrderSubscriber.d.ts +24 -0
  29. package/lib/orderSubscriber/OrderSubscriber.js +100 -0
  30. package/lib/orderSubscriber/PollingSubscription.d.ts +13 -0
  31. package/lib/orderSubscriber/PollingSubscription.js +23 -0
  32. package/lib/orderSubscriber/WebsocketSubscription.d.ts +12 -0
  33. package/lib/orderSubscriber/WebsocketSubscription.js +30 -0
  34. package/lib/orderSubscriber/index.d.ts +2 -0
  35. package/lib/orderSubscriber/index.js +18 -0
  36. package/lib/orderSubscriber/types.d.ts +11 -0
  37. package/lib/orderSubscriber/types.js +2 -0
  38. package/lib/tx/retryTxSender.js +5 -2
  39. package/lib/types.d.ts +5 -1
  40. package/lib/types.js +1 -1
  41. package/lib/userMap/userMap.js +4 -19
  42. package/package.json +1 -1
  43. package/src/auctionSubscriber/auctionSubscriber.ts +50 -0
  44. package/src/auctionSubscriber/index.ts +2 -0
  45. package/src/auctionSubscriber/types.ts +16 -0
  46. package/src/config.ts +6 -3
  47. package/src/dlob/orderBookLevels.ts +13 -4
  48. package/src/driftClient.ts +41 -10
  49. package/src/events/eventSubscriber.ts +6 -4
  50. package/src/events/fetchLogs.ts +2 -2
  51. package/src/events/pollingLogProvider.ts +2 -2
  52. package/src/events/types.ts +2 -1
  53. package/src/events/webSocketLogProvider.ts +2 -2
  54. package/src/idl/drift.json +61 -2
  55. package/src/index.ts +1 -0
  56. package/src/math/spotBalance.ts +1 -3
  57. package/src/memcmp.ts +48 -0
  58. package/src/orderSubscriber/OrderSubscriber.ts +132 -0
  59. package/src/orderSubscriber/PollingSubscription.ts +39 -0
  60. package/src/orderSubscriber/WebsocketSubscription.ts +54 -0
  61. package/src/orderSubscriber/index.ts +2 -0
  62. package/src/orderSubscriber/types.ts +14 -0
  63. package/src/tx/retryTxSender.ts +8 -2
  64. package/src/types.ts +5 -1
  65. package/src/userMap/userMap.ts +4 -16
@@ -0,0 +1,100 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OrderSubscriber = void 0;
4
+ const memcmp_1 = require("../memcmp");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const buffer_1 = require("buffer");
7
+ const DLOB_1 = require("../dlob/DLOB");
8
+ const PollingSubscription_1 = require("./PollingSubscription");
9
+ const WebsocketSubscription_1 = require("./WebsocketSubscription");
10
+ class OrderSubscriber {
11
+ constructor(config) {
12
+ this.usersAccounts = new Map();
13
+ this.driftClient = config.driftClient;
14
+ if (config.subscriptionConfig.type === 'polling') {
15
+ this.subscription = new PollingSubscription_1.PollingSubscription({
16
+ orderSubscriber: this,
17
+ frequency: config.subscriptionConfig.frequency,
18
+ });
19
+ }
20
+ else {
21
+ this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
22
+ orderSubscriber: this,
23
+ skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
24
+ });
25
+ }
26
+ }
27
+ async subscribe() {
28
+ await this.subscription.subscribe();
29
+ }
30
+ async fetch() {
31
+ if (this.fetchPromise) {
32
+ return this.fetchPromise;
33
+ }
34
+ this.fetchPromise = new Promise((resolver) => {
35
+ this.fetchPromiseResolver = resolver;
36
+ });
37
+ try {
38
+ const rpcRequestArgs = [
39
+ this.driftClient.program.programId.toBase58(),
40
+ {
41
+ commitment: this.driftClient.opts.commitment,
42
+ filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getUserWithOrderFilter)()],
43
+ encoding: 'base64',
44
+ withContext: true,
45
+ },
46
+ ];
47
+ const rpcJSONResponse =
48
+ // @ts-ignore
49
+ await this.driftClient.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
50
+ const rpcResponseAndContext = rpcJSONResponse.result;
51
+ const slot = rpcResponseAndContext.context.slot;
52
+ const programAccountSet = new Set();
53
+ for (const programAccount of rpcResponseAndContext.value) {
54
+ const key = programAccount.pubkey.toString();
55
+ // @ts-ignore
56
+ const buffer = buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
57
+ programAccountSet.add(key);
58
+ this.tryUpdateUserAccount(key, buffer, slot);
59
+ }
60
+ for (const key of this.usersAccounts.keys()) {
61
+ if (!programAccountSet.has(key)) {
62
+ this.usersAccounts.delete(key);
63
+ }
64
+ }
65
+ }
66
+ catch (e) {
67
+ console.error(e);
68
+ }
69
+ finally {
70
+ this.fetchPromiseResolver();
71
+ this.fetchPromise = undefined;
72
+ }
73
+ }
74
+ tryUpdateUserAccount(key, buffer, slot) {
75
+ const slotAndUserAccount = this.usersAccounts.get(key);
76
+ if (!slotAndUserAccount || slotAndUserAccount.slot < slot) {
77
+ const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
78
+ if (userAccount.hasOpenOrder) {
79
+ this.usersAccounts.set(key, { slot, userAccount });
80
+ }
81
+ else {
82
+ this.usersAccounts.delete(key);
83
+ }
84
+ }
85
+ }
86
+ async getDLOB(slot) {
87
+ const dlob = new DLOB_1.DLOB();
88
+ for (const [key, { userAccount }] of this.usersAccounts.entries()) {
89
+ const userAccountPubkey = new web3_js_1.PublicKey(key);
90
+ for (const order of userAccount.orders) {
91
+ dlob.insertOrder(order, userAccountPubkey, slot);
92
+ }
93
+ }
94
+ return dlob;
95
+ }
96
+ async unsubscribe() {
97
+ await this.subscription.unsubscribe();
98
+ }
99
+ }
100
+ exports.OrderSubscriber = OrderSubscriber;
@@ -0,0 +1,13 @@
1
+ /// <reference types="node" />
2
+ import { OrderSubscriber } from './OrderSubscriber';
3
+ export declare class PollingSubscription {
4
+ private orderSubscriber;
5
+ private frequency;
6
+ intervalId?: NodeJS.Timer;
7
+ constructor({ orderSubscriber, frequency, }: {
8
+ orderSubscriber: OrderSubscriber;
9
+ frequency: number;
10
+ });
11
+ subscribe(): Promise<void>;
12
+ unsubscribe(): Promise<void>;
13
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PollingSubscription = void 0;
4
+ class PollingSubscription {
5
+ constructor({ orderSubscriber, frequency, }) {
6
+ this.orderSubscriber = orderSubscriber;
7
+ this.frequency = frequency;
8
+ }
9
+ async subscribe() {
10
+ if (this.intervalId) {
11
+ return;
12
+ }
13
+ this.intervalId = setInterval(this.orderSubscriber.fetch.bind(this.orderSubscriber), this.frequency);
14
+ await this.orderSubscriber.fetch();
15
+ }
16
+ async unsubscribe() {
17
+ if (this.intervalId) {
18
+ clearInterval(this.intervalId);
19
+ this.intervalId = undefined;
20
+ }
21
+ }
22
+ }
23
+ exports.PollingSubscription = PollingSubscription;
@@ -0,0 +1,12 @@
1
+ import { OrderSubscriber } from './OrderSubscriber';
2
+ export declare class WebsocketSubscription {
3
+ private orderSubscriber;
4
+ private skipInitialLoad;
5
+ private websocketId;
6
+ constructor({ orderSubscriber, skipInitialLoad, }: {
7
+ orderSubscriber: OrderSubscriber;
8
+ skipInitialLoad?: boolean;
9
+ });
10
+ subscribe(): Promise<void>;
11
+ unsubscribe(): Promise<void>;
12
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebsocketSubscription = void 0;
4
+ const memcmp_1 = require("../memcmp");
5
+ class WebsocketSubscription {
6
+ constructor({ orderSubscriber, skipInitialLoad = false, }) {
7
+ this.orderSubscriber = orderSubscriber;
8
+ this.skipInitialLoad = skipInitialLoad;
9
+ }
10
+ async subscribe() {
11
+ if (this.websocketId) {
12
+ return;
13
+ }
14
+ this.websocketId =
15
+ this.orderSubscriber.driftClient.connection.onProgramAccountChange(this.orderSubscriber.driftClient.program.programId, (keyAccountInfo, context) => {
16
+ const userKey = keyAccountInfo.accountId.toBase58();
17
+ this.orderSubscriber.tryUpdateUserAccount(userKey, keyAccountInfo.accountInfo.data, context.slot);
18
+ }, this.orderSubscriber.driftClient.opts.commitment, [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()]);
19
+ if (!this.skipInitialLoad) {
20
+ await this.orderSubscriber.fetch();
21
+ }
22
+ }
23
+ async unsubscribe() {
24
+ if (this.websocketId) {
25
+ await this.orderSubscriber.driftClient.connection.removeProgramAccountChangeListener(this.websocketId);
26
+ this.websocketId = undefined;
27
+ }
28
+ }
29
+ }
30
+ exports.WebsocketSubscription = WebsocketSubscription;
@@ -0,0 +1,2 @@
1
+ export * from './OrderSubscriber';
2
+ export * from './types';
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./OrderSubscriber"), exports);
18
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,11 @@
1
+ import { DriftClient } from '../driftClient';
2
+ export type OrderSubscriberConfig = {
3
+ driftClient: DriftClient;
4
+ subscriptionConfig: {
5
+ type: 'polling';
6
+ frequency: number;
7
+ } | {
8
+ type: 'websocket';
9
+ skipInitialLoad?: boolean;
10
+ };
11
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -55,12 +55,15 @@ class RetryTxSender {
55
55
  return tx;
56
56
  }
57
57
  async sendVersionedTransaction(tx, additionalSigners, opts) {
58
+ additionalSigners === null || additionalSigners === void 0 ? void 0 : additionalSigners.filter((s) => s !== undefined).forEach((kp) => {
59
+ tx.sign([kp]);
60
+ });
58
61
  // @ts-ignore
59
- tx.sign((additionalSigners !== null && additionalSigners !== void 0 ? additionalSigners : []).concat(this.provider.wallet.payer));
62
+ const signedTx = await this.provider.wallet.signTransaction(tx);
60
63
  if (opts === undefined) {
61
64
  opts = this.provider.opts;
62
65
  }
63
- return this.sendRawTransaction(tx.serialize(), opts);
66
+ return this.sendRawTransaction(signedTx.serialize(), opts);
64
67
  }
65
68
  async sendRawTransaction(rawTransaction, opts) {
66
69
  const startTime = this.getTimestamp();
package/lib/types.d.ts CHANGED
@@ -222,7 +222,7 @@ export declare class OrderActionExplanation {
222
222
  orderFilledWithAmmJitLpSplit: {};
223
223
  };
224
224
  static readonly ORDER_FILLED_WITH_LP_JIT: {
225
- orderFilledWithAmmJitLpSplit: {};
225
+ orderFilledWithLpJit: {};
226
226
  };
227
227
  static readonly ORDER_FILLED_WITH_MATCH: {
228
228
  orderFilledWithMatch: {};
@@ -877,6 +877,10 @@ export type UserAccount = {
877
877
  lastActiveSlot: BN;
878
878
  isMarginTradingEnabled: boolean;
879
879
  idle: boolean;
880
+ openOrders: number;
881
+ hasOpenOrder: boolean;
882
+ openAuctions: number;
883
+ hasOpenAuction: boolean;
880
884
  };
881
885
  export type SpotPosition = {
882
886
  marketIndex: number;
package/lib/types.js CHANGED
@@ -138,7 +138,7 @@ OrderActionExplanation.ORDER_FILLED_WITH_AMM_JIT_LP_SPLIT = {
138
138
  orderFilledWithAmmJitLpSplit: {},
139
139
  };
140
140
  OrderActionExplanation.ORDER_FILLED_WITH_LP_JIT = {
141
- orderFilledWithAmmJitLpSplit: {},
141
+ orderFilledWithLpJit: {},
142
142
  };
143
143
  OrderActionExplanation.ORDER_FILLED_WITH_MATCH = {
144
144
  orderFilledWithMatch: {},
@@ -1,13 +1,10 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.UserMap = void 0;
7
4
  const __1 = require("..");
8
5
  const web3_js_1 = require("@solana/web3.js");
9
6
  const buffer_1 = require("buffer");
10
- const bs58_1 = __importDefault(require("bs58"));
7
+ const memcmp_1 = require("../memcmp");
11
8
  class UserMap {
12
9
  /**
13
10
  *
@@ -143,27 +140,15 @@ class UserMap {
143
140
  return this.userMap.size;
144
141
  }
145
142
  async sync() {
146
- let filters = undefined;
143
+ const filters = [(0, memcmp_1.getUserFilter)()];
147
144
  if (!this.includeIdle) {
148
- filters = [
149
- {
150
- memcmp: {
151
- offset: 4350,
152
- bytes: bs58_1.default.encode(Uint8Array.from([0])),
153
- },
154
- },
155
- ];
145
+ filters.push((0, memcmp_1.getNonIdleUserFilter)());
156
146
  }
157
147
  const rpcRequestArgs = [
158
148
  this.driftClient.program.programId.toBase58(),
159
149
  {
160
150
  commitment: this.driftClient.connection.commitment,
161
- filters: [
162
- {
163
- memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
164
- },
165
- ...(Array.isArray(filters) ? filters : []),
166
- ],
151
+ filters,
167
152
  encoding: 'base64',
168
153
  withContext: true,
169
154
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.31.0-beta.2",
3
+ "version": "2.31.0-beta.5",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -0,0 +1,50 @@
1
+ import { AuctionSubscriberConfig, AuctionSubscriberEvents } from './types';
2
+ import { DriftClient } from '../driftClient';
3
+ import { getUserFilter, getUserWithAuctionFilter } from '../memcmp';
4
+ import StrictEventEmitter from 'strict-event-emitter-types';
5
+ import { EventEmitter } from 'events';
6
+ import { UserAccount } from '../types';
7
+ import { ConfirmOptions } from '@solana/web3.js';
8
+
9
+ export class AuctionSubscriber {
10
+ private driftClient: DriftClient;
11
+ private opts: ConfirmOptions;
12
+
13
+ eventEmitter: StrictEventEmitter<EventEmitter, AuctionSubscriberEvents>;
14
+
15
+ private websocketId: number;
16
+
17
+ constructor({ driftClient, opts }: AuctionSubscriberConfig) {
18
+ this.driftClient = driftClient;
19
+ this.opts = opts || this.driftClient.opts;
20
+ }
21
+
22
+ public async subscribe() {
23
+ this.websocketId = this.driftClient.connection.onProgramAccountChange(
24
+ this.driftClient.program.programId,
25
+ (keyAccountInfo, context) => {
26
+ const userAccount =
27
+ this.driftClient.program.account.user.coder.accounts.decode(
28
+ 'User',
29
+ keyAccountInfo.accountInfo.data
30
+ ) as UserAccount;
31
+ this.eventEmitter.emit(
32
+ 'onAccountUpdate',
33
+ userAccount,
34
+ keyAccountInfo.accountId,
35
+ context.slot
36
+ );
37
+ },
38
+ this.driftClient.opts.commitment,
39
+ [getUserFilter(), getUserWithAuctionFilter()]
40
+ );
41
+ }
42
+
43
+ public async unsubscribe() {
44
+ if (this.websocketId) {
45
+ await this.driftClient.connection.removeProgramAccountChangeListener(
46
+ this.websocketId
47
+ );
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,2 @@
1
+ export * from './types';
2
+ export * from './auctionSubscriber';
@@ -0,0 +1,16 @@
1
+ import { DriftClient } from '../driftClient';
2
+ import { UserAccount } from '../types';
3
+ import { ConfirmOptions, PublicKey } from '@solana/web3.js';
4
+
5
+ export type AuctionSubscriberConfig = {
6
+ driftClient: DriftClient;
7
+ opts?: ConfirmOptions;
8
+ };
9
+
10
+ export interface AuctionSubscriberEvents {
11
+ onAccountUpdate: (
12
+ account: UserAccount,
13
+ pubkey: PublicKey,
14
+ slot: number
15
+ ) => void;
16
+ }
package/src/config.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { PerpMarketAccount, SpotMarketAccount } from '.';
1
2
  import {
2
3
  DevnetPerpMarkets,
3
4
  MainnetPerpMarkets,
@@ -11,7 +12,7 @@ import {
11
12
  MainnetSpotMarkets,
12
13
  } from './constants/spotMarkets';
13
14
  import { OracleInfo } from './oracles/types';
14
- import { Program } from '@coral-xyz/anchor';
15
+ import { Program, ProgramAccount } from '@coral-xyz/anchor';
15
16
 
16
17
  type DriftConfig = {
17
18
  ENV: DriftEnv;
@@ -124,8 +125,10 @@ export async function findAllMarketAndOracles(program: Program): Promise<{
124
125
  const spotMarketIndexes = [];
125
126
  const oracleInfos = new Map<string, OracleInfo>();
126
127
 
127
- const perpMarketProgramAccounts = await program.account.perpMarket.all();
128
- const spotMarketProgramAccounts = await program.account.spotMarket.all();
128
+ const perpMarketProgramAccounts =
129
+ (await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
130
+ const spotMarketProgramAccounts =
131
+ (await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
129
132
 
130
133
  for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
131
134
  const perpMarket = perpMarketProgramAccount.account;
@@ -244,17 +244,22 @@ export function getVammL2Generator({
244
244
  };
245
245
  }
246
246
 
247
- export function groupL2(l2: L2OrderBook, grouping: BN): L2OrderBook {
247
+ export function groupL2(
248
+ l2: L2OrderBook,
249
+ grouping: BN,
250
+ depth: number
251
+ ): L2OrderBook {
248
252
  return {
249
- bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG),
250
- asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT),
253
+ bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG, depth),
254
+ asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT, depth),
251
255
  };
252
256
  }
253
257
 
254
258
  function groupL2Levels(
255
259
  levels: L2Level[],
256
260
  grouping: BN,
257
- direction: PositionDirection
261
+ direction: PositionDirection,
262
+ depth: number
258
263
  ): L2Level[] {
259
264
  const groupedLevels = [];
260
265
  for (const level of levels) {
@@ -281,6 +286,10 @@ function groupL2Levels(
281
286
  };
282
287
  groupedLevels.push(groupedLevel);
283
288
  }
289
+
290
+ if (groupedLevels.length === depth) {
291
+ break;
292
+ }
284
293
  }
285
294
  return groupedLevels;
286
295
  }
@@ -114,6 +114,7 @@ import { calculateMarketMaxAvailableInsurance } from './math/market';
114
114
  import { fetchUserStatsAccount } from './accounts/fetch';
115
115
  import { castNumberToSpotPrecision } from './math/spotMarket';
116
116
  import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
117
+ import { getNonIdleUserFilter } from './memcmp';
117
118
 
118
119
  type RemainingAccountParams = {
119
120
  userAccounts: UserAccount[];
@@ -897,14 +898,7 @@ export class DriftClient {
897
898
  ): Promise<ProgramAccount<UserAccount>[]> {
898
899
  let filters = undefined;
899
900
  if (!includeIdle) {
900
- filters = [
901
- {
902
- memcmp: {
903
- offset: 4350,
904
- bytes: bs58.encode(Uint8Array.from([0])),
905
- },
906
- },
907
- ];
901
+ filters = [getNonIdleUserFilter()];
908
902
  }
909
903
  return (await this.program.account.user.all(
910
904
  filters
@@ -3395,12 +3389,12 @@ export class DriftClient {
3395
3389
  endSwapIx,
3396
3390
  ];
3397
3391
 
3398
- const tx = await this.buildTransaction(
3392
+ const tx = (await this.buildTransaction(
3399
3393
  instructions,
3400
3394
  txParams,
3401
3395
  0,
3402
3396
  lookupTables
3403
- );
3397
+ )) as VersionedTransaction;
3404
3398
 
3405
3399
  const { txSig, slot } = await this.sendTransaction(tx);
3406
3400
  this.spotMarketLastSlotCache.set(outMarketIndex, slot);
@@ -3625,6 +3619,43 @@ export class DriftClient {
3625
3619
  });
3626
3620
  }
3627
3621
 
3622
+ public async updateUserOpenOrdersCount(
3623
+ userAccountPublicKey: PublicKey,
3624
+ user: UserAccount,
3625
+ txParams?: TxParams
3626
+ ): Promise<TransactionSignature> {
3627
+ const { txSig } = await this.sendTransaction(
3628
+ await this.buildTransaction(
3629
+ await this.getUpdateUserOpenOrdersCountIx(userAccountPublicKey, user),
3630
+ txParams
3631
+ ),
3632
+ [],
3633
+ this.opts
3634
+ );
3635
+ return txSig;
3636
+ }
3637
+
3638
+ public async getUpdateUserOpenOrdersCountIx(
3639
+ userAccountPublicKey: PublicKey,
3640
+ userAccount: UserAccount
3641
+ ): Promise<TransactionInstruction> {
3642
+ const fillerPublicKey = await this.getUserAccountPublicKey();
3643
+
3644
+ const remainingAccounts = this.getRemainingAccounts({
3645
+ userAccounts: [userAccount],
3646
+ });
3647
+
3648
+ return await this.program.instruction.updateUserOpenOrdersCount({
3649
+ accounts: {
3650
+ state: await this.getStatePublicKey(),
3651
+ filler: fillerPublicKey,
3652
+ user: userAccountPublicKey,
3653
+ authority: this.wallet.publicKey,
3654
+ },
3655
+ remainingAccounts,
3656
+ });
3657
+ }
3658
+
3628
3659
  public async placeAndTakePerpOrder(
3629
3660
  orderParams: OptionalOrderParams,
3630
3661
  makerInfo?: MakerInfo | MakerInfo[],
@@ -1,4 +1,4 @@
1
- import { Connection, TransactionSignature } from '@solana/web3.js';
1
+ import { Connection, PublicKey, TransactionSignature } from '@solana/web3.js';
2
2
  import { Program } from '@coral-xyz/anchor';
3
3
  import {
4
4
  DefaultEventSubscriptionOptions,
@@ -19,6 +19,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
19
19
  import { getSortFn } from './sort';
20
20
 
21
21
  export class EventSubscriber {
22
+ private address: PublicKey;
22
23
  private eventListMap: Map<EventType, EventList<EventType>>;
23
24
  private txEventCache: TxEventCache;
24
25
  private awaitTxPromises = new Map<string, Promise<void>>();
@@ -35,6 +36,7 @@ export class EventSubscriber {
35
36
  private options: EventSubscriptionOptions = DefaultEventSubscriptionOptions
36
37
  ) {
37
38
  this.options = Object.assign({}, DefaultEventSubscriptionOptions, options);
39
+ this.address = this.options.address ?? program.programId;
38
40
  this.txEventCache = new TxEventCache(this.options.maxTx);
39
41
  this.eventListMap = new Map<EventType, EventList<EventType>>();
40
42
  for (const eventType of this.options.eventTypes) {
@@ -52,13 +54,13 @@ export class EventSubscriber {
52
54
  if (this.options.logProviderConfig.type === 'websocket') {
53
55
  this.logProvider = new WebSocketLogProvider(
54
56
  this.connection,
55
- this.program.programId,
57
+ this.address,
56
58
  this.options.commitment
57
59
  );
58
60
  } else {
59
61
  this.logProvider = new PollingLogProvider(
60
62
  this.connection,
61
- this.program.programId,
63
+ this.address,
62
64
  options.commitment,
63
65
  this.options.logProviderConfig.frequency
64
66
  );
@@ -134,7 +136,7 @@ export class EventSubscriber {
134
136
  while (txFetched < this.options.maxTx) {
135
137
  const response = await fetchLogs(
136
138
  this.connection,
137
- this.program.programId,
139
+ this.address,
138
140
  this.options.commitment === 'finalized' ? 'finalized' : 'confirmed',
139
141
  beforeTx,
140
142
  untilTx
@@ -31,14 +31,14 @@ function mapTransactionResponseToLog(
31
31
 
32
32
  export async function fetchLogs(
33
33
  connection: Connection,
34
- programId: PublicKey,
34
+ address: PublicKey,
35
35
  finality: Finality,
36
36
  beforeTx?: TransactionSignature,
37
37
  untilTx?: TransactionSignature,
38
38
  limit?: number
39
39
  ): Promise<FetchLogsResponse> {
40
40
  const signatures = await connection.getSignaturesForAddress(
41
- programId,
41
+ address,
42
42
  {
43
43
  before: beforeTx,
44
44
  until: untilTx,
@@ -17,7 +17,7 @@ export class PollingLogProvider implements LogProvider {
17
17
 
18
18
  public constructor(
19
19
  private connection: Connection,
20
- private programId: PublicKey,
20
+ private address: PublicKey,
21
21
  commitment: Commitment,
22
22
  private frequency = 15 * 1000
23
23
  ) {
@@ -41,7 +41,7 @@ export class PollingLogProvider implements LogProvider {
41
41
  try {
42
42
  const response = await fetchLogs(
43
43
  this.connection,
44
- this.programId,
44
+ this.address,
45
45
  this.finality,
46
46
  undefined,
47
47
  this.mostRecentSeenTx,
@@ -1,4 +1,4 @@
1
- import { Commitment, TransactionSignature } from '@solana/web3.js';
1
+ import { Commitment, PublicKey, TransactionSignature } from '@solana/web3.js';
2
2
  import {
3
3
  DepositRecord,
4
4
  FundingPaymentRecord,
@@ -17,6 +17,7 @@ import {
17
17
  } from '../index';
18
18
 
19
19
  export type EventSubscriptionOptions = {
20
+ address?: PublicKey;
20
21
  eventTypes?: EventType[];
21
22
  maxEventsPerType?: number;
22
23
  orderBy?: EventSubscriptionOrderBy;
@@ -5,7 +5,7 @@ export class WebSocketLogProvider implements LogProvider {
5
5
  private subscriptionId: number;
6
6
  public constructor(
7
7
  private connection: Connection,
8
- private programId: PublicKey,
8
+ private address: PublicKey,
9
9
  private commitment: Commitment
10
10
  ) {}
11
11
 
@@ -15,7 +15,7 @@ export class WebSocketLogProvider implements LogProvider {
15
15
  }
16
16
 
17
17
  this.subscriptionId = this.connection.onLogs(
18
- this.programId,
18
+ this.address,
19
19
  (logs, ctx) => {
20
20
  callback(logs.signature, ctx.slot, logs.logs, undefined);
21
21
  },