@drift-labs/sdk 2.41.0-beta.0 → 2.41.0-beta.1

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 (81) hide show
  1. package/README.md +0 -1
  2. package/VERSION +1 -1
  3. package/bun.lockb +0 -0
  4. package/lib/accounts/types.d.ts +5 -1
  5. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -1
  6. package/lib/accounts/webSocketAccountSubscriber.js +28 -2
  7. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +2 -1
  8. package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
  9. package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
  10. package/lib/accounts/webSocketProgramAccountSubscriber.js +99 -0
  11. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +2 -1
  12. package/lib/accounts/webSocketUserAccountSubscriber.js +3 -2
  13. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +2 -1
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -2
  15. package/lib/addresses/pda.d.ts +1 -0
  16. package/lib/addresses/pda.js +5 -1
  17. package/lib/adminClient.d.ts +2 -0
  18. package/lib/adminClient.js +20 -0
  19. package/lib/auctionSubscriber/auctionSubscriber.d.ts +3 -2
  20. package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
  21. package/lib/auctionSubscriber/types.d.ts +1 -0
  22. package/lib/dlob/DLOB.d.ts +2 -6
  23. package/lib/dlob/DLOB.js +9 -11
  24. package/lib/dlob/DLOBSubscriber.js +4 -7
  25. package/lib/dlob/orderBookLevels.d.ts +4 -2
  26. package/lib/dlob/orderBookLevels.js +79 -16
  27. package/lib/driftClient.d.ts +2 -1
  28. package/lib/driftClient.js +5 -4
  29. package/lib/driftClientConfig.d.ts +1 -0
  30. package/lib/factory/bigNum.js +4 -2
  31. package/lib/idl/drift.json +222 -2
  32. package/lib/jupiter/jupiterClient.d.ts +4 -1
  33. package/lib/jupiter/jupiterClient.js +4 -1
  34. package/lib/math/amm.js +7 -2
  35. package/lib/math/auction.d.ts +12 -1
  36. package/lib/math/auction.js +22 -1
  37. package/lib/math/market.js +2 -4
  38. package/lib/math/superStake.d.ts +51 -4
  39. package/lib/math/superStake.js +173 -21
  40. package/lib/math/trade.js +2 -4
  41. package/lib/math/utils.d.ts +1 -0
  42. package/lib/math/utils.js +10 -1
  43. package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
  44. package/lib/orderSubscriber/OrderSubscriber.js +4 -3
  45. package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
  46. package/lib/orderSubscriber/WebsocketSubscription.js +15 -12
  47. package/lib/orderSubscriber/types.d.ts +1 -0
  48. package/lib/user.d.ts +2 -2
  49. package/lib/user.js +5 -5
  50. package/package.json +2 -1
  51. package/src/accounts/types.ts +8 -1
  52. package/src/accounts/webSocketAccountSubscriber.ts +36 -2
  53. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
  54. package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
  55. package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
  56. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
  57. package/src/addresses/pda.ts +9 -0
  58. package/src/adminClient.ts +32 -0
  59. package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
  60. package/src/auctionSubscriber/types.ts +1 -0
  61. package/src/dlob/DLOB.ts +9 -32
  62. package/src/dlob/DLOBSubscriber.ts +8 -7
  63. package/src/dlob/orderBookLevels.ts +133 -32
  64. package/src/driftClient.ts +5 -1
  65. package/src/driftClientConfig.ts +1 -0
  66. package/src/factory/bigNum.ts +2 -0
  67. package/src/idl/drift.json +222 -2
  68. package/src/jupiter/jupiterClient.ts +6 -0
  69. package/src/math/amm.ts +9 -2
  70. package/src/math/auction.ts +36 -2
  71. package/src/math/market.ts +4 -9
  72. package/src/math/superStake.ts +247 -23
  73. package/src/math/trade.ts +3 -11
  74. package/src/math/utils.ts +12 -0
  75. package/src/orderSubscriber/OrderSubscriber.ts +12 -7
  76. package/src/orderSubscriber/WebsocketSubscription.ts +34 -23
  77. package/src/orderSubscriber/types.ts +1 -0
  78. package/src/user.ts +7 -5
  79. package/tests/amm/test.ts +402 -0
  80. package/tests/auctions/test.ts +66 -0
  81. package/tests/dlob/test.ts +1 -73
package/README.md CHANGED
@@ -244,4 +244,3 @@ Drift Protocol v2 is licensed under [Apache 2.0](./LICENSE).
244
244
  Unless you explicitly state otherwise, any contribution intentionally submitted
245
245
  for inclusion in Drift SDK by you, as defined in the Apache-2.0 license, shall be
246
246
  licensed as above, without any additional terms or conditions.
247
-
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.41.0-beta.0
1
+ 2.41.0-beta.1
package/bun.lockb ADDED
Binary file
@@ -3,7 +3,7 @@
3
3
  import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
4
4
  import StrictEventEmitter from 'strict-event-emitter-types';
5
5
  import { EventEmitter } from 'events';
6
- import { PublicKey } from '@solana/web3.js';
6
+ import { Context, PublicKey } from '@solana/web3.js';
7
7
  import { Account } from '@solana/spl-token';
8
8
  import { OracleInfo, OraclePriceData } from '..';
9
9
  export interface AccountSubscriber<T> {
@@ -13,6 +13,10 @@ export interface AccountSubscriber<T> {
13
13
  unsubscribe(): Promise<void>;
14
14
  setData(userAccount: T, slot?: number): void;
15
15
  }
16
+ export interface ProgramAccountSubscriber<T> {
17
+ subscribe(onChange: (accountId: PublicKey, data: T, context: Context) => void): Promise<void>;
18
+ unsubscribe(): Promise<void>;
19
+ }
16
20
  export declare class NotSubscribedError extends Error {
17
21
  name: string;
18
22
  }
@@ -1,4 +1,5 @@
1
1
  /// <reference types="node" />
2
+ /// <reference types="node" />
2
3
  import { DataAndSlot, BufferAndSlot, AccountSubscriber } from './types';
3
4
  import { Program } from '@coral-xyz/anchor';
4
5
  import { AccountInfo, Context, PublicKey } from '@solana/web3.js';
@@ -11,9 +12,13 @@ export declare class WebSocketAccountSubscriber<T> implements AccountSubscriber<
11
12
  decodeBufferFn: (buffer: Buffer) => T;
12
13
  onChange: (data: T) => void;
13
14
  listenerId?: number;
14
- constructor(accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => T);
15
+ resubTimeoutMs?: number;
16
+ timeoutId?: NodeJS.Timeout;
17
+ receivingData: boolean;
18
+ constructor(accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => T, resubTimeoutMs?: number);
15
19
  subscribe(onChange: (data: T) => void): Promise<void>;
16
20
  setData(data: T, slot?: number): void;
21
+ private setTimeout;
17
22
  fetch(): Promise<void>;
18
23
  handleRpcResponse(context: Context, accountInfo?: AccountInfo<Buffer>): void;
19
24
  decodeBuffer(buffer: Buffer): T;
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WebSocketAccountSubscriber = void 0;
4
4
  const utils_1 = require("./utils");
5
5
  class WebSocketAccountSubscriber {
6
- constructor(accountName, program, accountPublicKey, decodeBuffer) {
6
+ constructor(accountName, program, accountPublicKey, decodeBuffer, resubTimeoutMs) {
7
7
  this.accountName = accountName;
8
8
  this.program = program;
9
9
  this.accountPublicKey = accountPublicKey;
10
10
  this.decodeBufferFn = decodeBuffer;
11
+ this.resubTimeoutMs = resubTimeoutMs;
12
+ this.receivingData = false;
11
13
  }
12
14
  async subscribe(onChange) {
13
15
  if (this.listenerId) {
@@ -18,8 +20,19 @@ class WebSocketAccountSubscriber {
18
20
  await this.fetch();
19
21
  }
20
22
  this.listenerId = this.program.provider.connection.onAccountChange(this.accountPublicKey, (accountInfo, context) => {
21
- this.handleRpcResponse(context, accountInfo);
23
+ if (this.resubTimeoutMs) {
24
+ this.receivingData = true;
25
+ clearTimeout(this.timeoutId);
26
+ this.handleRpcResponse(context, accountInfo);
27
+ this.setTimeout();
28
+ }
29
+ else {
30
+ this.handleRpcResponse(context, accountInfo);
31
+ }
22
32
  }, this.program.provider.opts.commitment);
33
+ if (this.resubTimeoutMs) {
34
+ this.setTimeout();
35
+ }
23
36
  }
24
37
  setData(data, slot) {
25
38
  const newSlot = slot || 0;
@@ -31,6 +44,19 @@ class WebSocketAccountSubscriber {
31
44
  slot,
32
45
  };
33
46
  }
47
+ setTimeout() {
48
+ if (!this.onChange) {
49
+ throw new Error('onChange callback function must be set');
50
+ }
51
+ this.timeoutId = setTimeout(async () => {
52
+ if (this.receivingData) {
53
+ console.log(`No ws data from ${this.accountName} in ${this.resubTimeoutMs}ms, resubscribing`);
54
+ await this.unsubscribe();
55
+ this.receivingData = false;
56
+ await this.subscribe(this.onChange);
57
+ }
58
+ }, this.resubTimeoutMs);
59
+ }
34
60
  async fetch() {
35
61
  const rpcResponse = await this.program.provider.connection.getAccountInfoAndContext(this.accountPublicKey, this.program.provider.opts.commitment);
36
62
  this.handleRpcResponse(rpcResponse.context, rpcResponse === null || rpcResponse === void 0 ? void 0 : rpcResponse.value);
@@ -15,6 +15,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
15
15
  spotMarketIndexes: number[];
16
16
  oracleInfos: OracleInfo[];
17
17
  oracleClientCache: OracleClientCache;
18
+ resubTimeoutMs?: number;
18
19
  shouldFindAllMarketsAndOracles: boolean;
19
20
  eventEmitter: StrictEventEmitter<EventEmitter, DriftClientAccountEvents>;
20
21
  stateAccountSubscriber?: AccountSubscriber<StateAccount>;
@@ -24,7 +25,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
24
25
  private isSubscribing;
25
26
  private subscriptionPromise;
26
27
  private subscriptionPromiseResolver;
27
- constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean);
28
+ constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean, resubTimeoutMs?: number);
28
29
  subscribe(): Promise<boolean>;
29
30
  subscribeToPerpMarketAccounts(): Promise<boolean>;
30
31
  subscribeToPerpMarketAccount(marketIndex: number): Promise<boolean>;
@@ -10,7 +10,7 @@ const oracleClientCache_1 = require("../oracles/oracleClientCache");
10
10
  const quoteAssetOracleClient_1 = require("../oracles/quoteAssetOracleClient");
11
11
  const config_1 = require("../config");
12
12
  class WebSocketDriftClientAccountSubscriber {
13
- constructor(program, perpMarketIndexes, spotMarketIndexes, oracleInfos, shouldFindAllMarketsAndOracles) {
13
+ constructor(program, perpMarketIndexes, spotMarketIndexes, oracleInfos, shouldFindAllMarketsAndOracles, resubTimeoutMs) {
14
14
  this.oracleClientCache = new oracleClientCache_1.OracleClientCache();
15
15
  this.perpMarketAccountSubscribers = new Map();
16
16
  this.spotMarketAccountSubscribers = new Map();
@@ -23,6 +23,7 @@ class WebSocketDriftClientAccountSubscriber {
23
23
  this.spotMarketIndexes = spotMarketIndexes;
24
24
  this.oracleInfos = oracleInfos;
25
25
  this.shouldFindAllMarketsAndOracles = shouldFindAllMarketsAndOracles;
26
+ this.resubTimeoutMs = resubTimeoutMs;
26
27
  }
27
28
  async subscribe() {
28
29
  if (this.isSubscribed) {
@@ -43,7 +44,7 @@ class WebSocketDriftClientAccountSubscriber {
43
44
  }
44
45
  const statePublicKey = await (0, pda_1.getDriftStateAccountPublicKey)(this.program.programId);
45
46
  // create and activate main state account subscription
46
- this.stateAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('state', this.program, statePublicKey);
47
+ this.stateAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('state', this.program, statePublicKey, undefined, this.resubTimeoutMs);
47
48
  await this.stateAccountSubscriber.subscribe((data) => {
48
49
  this.eventEmitter.emit('stateAccountUpdate', data);
49
50
  this.eventEmitter.emit('update');
@@ -68,7 +69,7 @@ class WebSocketDriftClientAccountSubscriber {
68
69
  }
69
70
  async subscribeToPerpMarketAccount(marketIndex) {
70
71
  const perpMarketPublicKey = await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, marketIndex);
71
- const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('perpMarket', this.program, perpMarketPublicKey);
72
+ const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('perpMarket', this.program, perpMarketPublicKey, undefined, this.resubTimeoutMs);
72
73
  await accountSubscriber.subscribe((data) => {
73
74
  this.eventEmitter.emit('perpMarketAccountUpdate', data);
74
75
  this.eventEmitter.emit('update');
@@ -84,7 +85,7 @@ class WebSocketDriftClientAccountSubscriber {
84
85
  }
85
86
  async subscribeToSpotMarketAccount(marketIndex) {
86
87
  const marketPublicKey = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, marketIndex);
87
- const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('spotMarket', this.program, marketPublicKey);
88
+ const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('spotMarket', this.program, marketPublicKey, undefined, this.resubTimeoutMs);
88
89
  await accountSubscriber.subscribe((data) => {
89
90
  this.eventEmitter.emit('spotMarketAccountUpdate', data);
90
91
  this.eventEmitter.emit('update');
@@ -104,7 +105,7 @@ class WebSocketDriftClientAccountSubscriber {
104
105
  const client = this.oracleClientCache.get(oracleInfo.source, this.program.provider.connection);
105
106
  const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('oracle', this.program, oracleInfo.publicKey, (buffer) => {
106
107
  return client.getOraclePriceDataFromBuffer(buffer);
107
- });
108
+ }, this.resubTimeoutMs);
108
109
  await accountSubscriber.subscribe((data) => {
109
110
  this.eventEmitter.emit('oraclePriceUpdate', oracleInfo.publicKey, data);
110
111
  this.eventEmitter.emit('update');
@@ -0,0 +1,32 @@
1
+ /// <reference types="node" />
2
+ /// <reference types="node" />
3
+ import { DataAndSlot, BufferAndSlot, ProgramAccountSubscriber } from './types';
4
+ import { Program } from '@coral-xyz/anchor';
5
+ import { Commitment, Context, KeyedAccountInfo, MemcmpFilter, PublicKey } from '@solana/web3.js';
6
+ export declare class WebSocketProgramAccountSubscriber<T> implements ProgramAccountSubscriber<T> {
7
+ subscriptionName: string;
8
+ accountDiscriminator: string;
9
+ dataAndSlot?: DataAndSlot<T> & {
10
+ accountId: PublicKey;
11
+ };
12
+ bufferAndSlot?: BufferAndSlot;
13
+ program: Program;
14
+ decodeBuffer: (accountName: string, ix: Buffer) => T;
15
+ onChange: (accountId: PublicKey, data: T, context: Context) => void;
16
+ listenerId?: number;
17
+ resubTimeoutMs?: number;
18
+ timeoutId?: NodeJS.Timeout;
19
+ options: {
20
+ filters: MemcmpFilter[];
21
+ commitment?: Commitment;
22
+ };
23
+ receivingData: boolean;
24
+ constructor(subscriptionName: string, accountDiscriminator: string, program: Program, decodeBufferFn: (accountName: string, ix: Buffer) => T, options?: {
25
+ filters: MemcmpFilter[];
26
+ commitment?: Commitment;
27
+ }, resubTimeoutMs?: number);
28
+ subscribe(onChange: (accountId: PublicKey, data: T, context: Context) => void): Promise<void>;
29
+ private setTimeout;
30
+ handleRpcResponse(context: Context, keyedAccountInfo: KeyedAccountInfo): void;
31
+ unsubscribe(): Promise<void>;
32
+ }
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WebSocketProgramAccountSubscriber = void 0;
4
+ class WebSocketProgramAccountSubscriber {
5
+ constructor(subscriptionName, accountDiscriminator, program, decodeBufferFn, options = {
6
+ filters: [],
7
+ }, resubTimeoutMs) {
8
+ this.receivingData = false;
9
+ this.subscriptionName = subscriptionName;
10
+ this.accountDiscriminator = accountDiscriminator;
11
+ this.program = program;
12
+ this.decodeBuffer = decodeBufferFn;
13
+ this.resubTimeoutMs = resubTimeoutMs;
14
+ this.options = options;
15
+ this.receivingData = false;
16
+ }
17
+ async subscribe(onChange) {
18
+ var _a;
19
+ if (this.listenerId) {
20
+ return;
21
+ }
22
+ this.onChange = onChange;
23
+ this.listenerId = this.program.provider.connection.onProgramAccountChange(this.program.programId, (keyedAccountInfo, context) => {
24
+ if (this.resubTimeoutMs) {
25
+ this.receivingData = true;
26
+ clearTimeout(this.timeoutId);
27
+ this.handleRpcResponse(context, keyedAccountInfo);
28
+ this.setTimeout();
29
+ }
30
+ else {
31
+ this.handleRpcResponse(context, keyedAccountInfo);
32
+ }
33
+ }, (_a = this.options.commitment) !== null && _a !== void 0 ? _a : this.program.provider.opts.commitment, this.options.filters);
34
+ if (this.resubTimeoutMs) {
35
+ this.setTimeout();
36
+ }
37
+ }
38
+ setTimeout() {
39
+ if (!this.onChange) {
40
+ throw new Error('onChange callback function must be set');
41
+ }
42
+ this.timeoutId = setTimeout(async () => {
43
+ if (this.receivingData) {
44
+ console.log(`No ws data from ${this.subscriptionName} in ${this.resubTimeoutMs}ms, resubscribing`);
45
+ await this.unsubscribe();
46
+ this.receivingData = false;
47
+ await this.subscribe(this.onChange);
48
+ }
49
+ }, this.resubTimeoutMs);
50
+ }
51
+ handleRpcResponse(context, keyedAccountInfo) {
52
+ const newSlot = context.slot;
53
+ let newBuffer = undefined;
54
+ if (keyedAccountInfo) {
55
+ newBuffer = keyedAccountInfo.accountInfo.data;
56
+ }
57
+ if (!this.bufferAndSlot) {
58
+ this.bufferAndSlot = {
59
+ buffer: newBuffer,
60
+ slot: newSlot,
61
+ };
62
+ if (newBuffer) {
63
+ const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
64
+ this.dataAndSlot = {
65
+ data: account,
66
+ slot: newSlot,
67
+ accountId: keyedAccountInfo.accountId,
68
+ };
69
+ this.onChange(keyedAccountInfo.accountId, account, context);
70
+ }
71
+ return;
72
+ }
73
+ if (newSlot <= this.bufferAndSlot.slot) {
74
+ return;
75
+ }
76
+ const oldBuffer = this.bufferAndSlot.buffer;
77
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
78
+ this.bufferAndSlot = {
79
+ buffer: newBuffer,
80
+ slot: newSlot,
81
+ };
82
+ const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
83
+ this.dataAndSlot = {
84
+ data: account,
85
+ slot: newSlot,
86
+ accountId: keyedAccountInfo.accountId,
87
+ };
88
+ this.onChange(keyedAccountInfo.accountId, account, context);
89
+ }
90
+ }
91
+ unsubscribe() {
92
+ if (this.listenerId) {
93
+ const promise = this.program.provider.connection.removeAccountChangeListener(this.listenerId);
94
+ this.listenerId = undefined;
95
+ return promise;
96
+ }
97
+ }
98
+ }
99
+ exports.WebSocketProgramAccountSubscriber = WebSocketProgramAccountSubscriber;
@@ -7,11 +7,12 @@ import { PublicKey } from '@solana/web3.js';
7
7
  import { UserAccount } from '../types';
8
8
  export declare class WebSocketUserAccountSubscriber implements UserAccountSubscriber {
9
9
  isSubscribed: boolean;
10
+ reconnectTimeoutMs?: number;
10
11
  program: Program;
11
12
  eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
12
13
  userAccountPublicKey: PublicKey;
13
14
  userDataAccountSubscriber: AccountSubscriber<UserAccount>;
14
- constructor(program: Program, userAccountPublicKey: PublicKey);
15
+ constructor(program: Program, userAccountPublicKey: PublicKey, reconnectTimeoutMs?: number);
15
16
  subscribe(userAccount?: UserAccount): Promise<boolean>;
16
17
  fetch(): Promise<void>;
17
18
  unsubscribe(): Promise<void>;
@@ -5,17 +5,18 @@ const types_1 = require("./types");
5
5
  const events_1 = require("events");
6
6
  const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
7
7
  class WebSocketUserAccountSubscriber {
8
- constructor(program, userAccountPublicKey) {
8
+ constructor(program, userAccountPublicKey, reconnectTimeoutMs) {
9
9
  this.isSubscribed = false;
10
10
  this.program = program;
11
11
  this.userAccountPublicKey = userAccountPublicKey;
12
12
  this.eventEmitter = new events_1.EventEmitter();
13
+ this.reconnectTimeoutMs = reconnectTimeoutMs;
13
14
  }
14
15
  async subscribe(userAccount) {
15
16
  if (this.isSubscribed) {
16
17
  return true;
17
18
  }
18
- this.userDataAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('user', this.program, this.userAccountPublicKey);
19
+ this.userDataAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('user', this.program, this.userAccountPublicKey, undefined, this.reconnectTimeoutMs);
19
20
  if (userAccount) {
20
21
  this.userDataAccountSubscriber.setData(userAccount);
21
22
  }
@@ -7,11 +7,12 @@ import { PublicKey } from '@solana/web3.js';
7
7
  import { UserStatsAccount } from '../types';
8
8
  export declare class WebSocketUserStatsAccountSubscriber implements UserStatsAccountSubscriber {
9
9
  isSubscribed: boolean;
10
+ reconnectTimeoutMs?: number;
10
11
  program: Program;
11
12
  eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
12
13
  userStatsAccountPublicKey: PublicKey;
13
14
  userStatsAccountSubscriber: AccountSubscriber<UserStatsAccount>;
14
- constructor(program: Program, userStatsAccountPublicKey: PublicKey);
15
+ constructor(program: Program, userStatsAccountPublicKey: PublicKey, reconnectTimeoutMs?: number);
15
16
  subscribe(userStatsAccount?: UserStatsAccount): Promise<boolean>;
16
17
  fetch(): Promise<void>;
17
18
  unsubscribe(): Promise<void>;
@@ -5,17 +5,18 @@ const types_1 = require("./types");
5
5
  const events_1 = require("events");
6
6
  const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
7
7
  class WebSocketUserStatsAccountSubscriber {
8
- constructor(program, userStatsAccountPublicKey) {
8
+ constructor(program, userStatsAccountPublicKey, reconnectTimeoutMs) {
9
9
  this.isSubscribed = false;
10
10
  this.program = program;
11
11
  this.userStatsAccountPublicKey = userStatsAccountPublicKey;
12
12
  this.eventEmitter = new events_1.EventEmitter();
13
+ this.reconnectTimeoutMs = reconnectTimeoutMs;
13
14
  }
14
15
  async subscribe(userStatsAccount) {
15
16
  if (this.isSubscribed) {
16
17
  return true;
17
18
  }
18
- this.userStatsAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('userStats', this.program, this.userStatsAccountPublicKey);
19
+ this.userStatsAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('userStats', this.program, this.userStatsAccountPublicKey, undefined, this.reconnectTimeoutMs);
19
20
  if (userStatsAccount) {
20
21
  this.userStatsAccountSubscriber.setData(userStatsAccount);
21
22
  }
@@ -17,3 +17,4 @@ export declare function getSerumSignerPublicKey(programId: PublicKey, market: Pu
17
17
  export declare function getSerumFulfillmentConfigPublicKey(programId: PublicKey, market: PublicKey): PublicKey;
18
18
  export declare function getPhoenixFulfillmentConfigPublicKey(programId: PublicKey, market: PublicKey): PublicKey;
19
19
  export declare function getReferrerNamePublicKeySync(programId: PublicKey, nameBuffer: number[]): PublicKey;
20
+ export declare function getProtocolIfSharesTransferConfigPublicKey(programId: PublicKey): PublicKey;
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  return result;
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.getReferrerNamePublicKeySync = exports.getPhoenixFulfillmentConfigPublicKey = exports.getSerumFulfillmentConfigPublicKey = exports.getSerumSignerPublicKey = exports.getSerumOpenOrdersPublicKey = exports.getDriftSignerPublicKey = exports.getInsuranceFundStakeAccountPublicKey = exports.getInsuranceFundVaultPublicKey = exports.getSpotMarketVaultPublicKey = exports.getSpotMarketPublicKey = exports.getPerpMarketPublicKey = exports.getUserStatsAccountPublicKey = exports.getUserAccountPublicKeySync = exports.getUserAccountPublicKey = exports.getUserAccountPublicKeyAndNonce = exports.getDriftStateAccountPublicKey = exports.getDriftStateAccountPublicKeyAndNonce = void 0;
26
+ exports.getProtocolIfSharesTransferConfigPublicKey = exports.getReferrerNamePublicKeySync = exports.getPhoenixFulfillmentConfigPublicKey = exports.getSerumFulfillmentConfigPublicKey = exports.getSerumSignerPublicKey = exports.getSerumOpenOrdersPublicKey = exports.getDriftSignerPublicKey = exports.getInsuranceFundStakeAccountPublicKey = exports.getInsuranceFundVaultPublicKey = exports.getSpotMarketVaultPublicKey = exports.getSpotMarketPublicKey = exports.getPerpMarketPublicKey = exports.getUserStatsAccountPublicKey = exports.getUserAccountPublicKeySync = exports.getUserAccountPublicKey = exports.getUserAccountPublicKeyAndNonce = exports.getDriftStateAccountPublicKey = exports.getDriftStateAccountPublicKeyAndNonce = void 0;
27
27
  const web3_js_1 = require("@solana/web3.js");
28
28
  const anchor = __importStar(require("@coral-xyz/anchor"));
29
29
  async function getDriftStateAccountPublicKeyAndNonce(programId) {
@@ -133,3 +133,7 @@ function getReferrerNamePublicKeySync(programId, nameBuffer) {
133
133
  ], programId)[0];
134
134
  }
135
135
  exports.getReferrerNamePublicKeySync = getReferrerNamePublicKeySync;
136
+ function getProtocolIfSharesTransferConfigPublicKey(programId) {
137
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(anchor.utils.bytes.utf8.encode('if_shares_transfer_config'))], programId)[0];
138
+ }
139
+ exports.getProtocolIfSharesTransferConfigPublicKey = getProtocolIfSharesTransferConfigPublicKey;
@@ -70,4 +70,6 @@ export declare class AdminClient extends DriftClient {
70
70
  updateSerumVault(srmVault: PublicKey): Promise<TransactionSignature>;
71
71
  updatePerpMarketLiquidationFee(perpMarketIndex: number, liquidatorFee: number, ifLiquidationFee: number): Promise<TransactionSignature>;
72
72
  updateSpotMarketLiquidationFee(spotMarketIndex: number, liquidatorFee: number, ifLiquidationFee: number): Promise<TransactionSignature>;
73
+ initializeProtocolIfSharesTransferConfig(): Promise<TransactionSignature>;
74
+ updateProtocolIfSharesTransferConfig(whitelistedSigners?: PublicKey[], maxTransferPerEpoch?: BN): Promise<TransactionSignature>;
73
75
  }
@@ -791,5 +791,25 @@ class AdminClient extends driftClient_1.DriftClient {
791
791
  },
792
792
  });
793
793
  }
794
+ async initializeProtocolIfSharesTransferConfig() {
795
+ return await this.program.rpc.initializeProtocolIfSharesTransferConfig({
796
+ accounts: {
797
+ admin: this.wallet.publicKey,
798
+ state: await this.getStatePublicKey(),
799
+ rent: web3_js_1.SYSVAR_RENT_PUBKEY,
800
+ systemProgram: anchor.web3.SystemProgram.programId,
801
+ protocolIfSharesTransferConfig: (0, pda_1.getProtocolIfSharesTransferConfigPublicKey)(this.program.programId),
802
+ },
803
+ });
804
+ }
805
+ async updateProtocolIfSharesTransferConfig(whitelistedSigners, maxTransferPerEpoch) {
806
+ return await this.program.rpc.updateProtocolIfSharesTransferConfig(whitelistedSigners || null, maxTransferPerEpoch, {
807
+ accounts: {
808
+ admin: this.wallet.publicKey,
809
+ state: await this.getStatePublicKey(),
810
+ protocolIfSharesTransferConfig: (0, pda_1.getProtocolIfSharesTransferConfigPublicKey)(this.program.programId),
811
+ },
812
+ });
813
+ }
794
814
  }
795
815
  exports.AdminClient = AdminClient;
@@ -5,9 +5,10 @@ import { EventEmitter } from 'events';
5
5
  export declare class AuctionSubscriber {
6
6
  private driftClient;
7
7
  private opts;
8
+ private resubTimeoutMs?;
8
9
  eventEmitter: StrictEventEmitter<EventEmitter, AuctionSubscriberEvents>;
9
- private websocketId;
10
- constructor({ driftClient, opts }: AuctionSubscriberConfig);
10
+ private subscriber;
11
+ constructor({ driftClient, opts, resubTimeoutMs }: AuctionSubscriberConfig);
11
12
  subscribe(): Promise<void>;
12
13
  unsubscribe(): Promise<void>;
13
14
  }
@@ -3,22 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AuctionSubscriber = void 0;
4
4
  const memcmp_1 = require("../memcmp");
5
5
  const events_1 = require("events");
6
+ const webSocketProgramAccountSubscriber_1 = require("../accounts/webSocketProgramAccountSubscriber");
6
7
  class AuctionSubscriber {
7
- constructor({ driftClient, opts }) {
8
+ constructor({ driftClient, opts, resubTimeoutMs }) {
8
9
  this.driftClient = driftClient;
9
10
  this.opts = opts || this.driftClient.opts;
10
11
  this.eventEmitter = new events_1.EventEmitter();
12
+ this.resubTimeoutMs = resubTimeoutMs;
11
13
  }
12
14
  async subscribe() {
13
- this.websocketId = this.driftClient.connection.onProgramAccountChange(this.driftClient.program.programId, (keyAccountInfo, context) => {
14
- const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', keyAccountInfo.accountInfo.data);
15
- this.eventEmitter.emit('onAccountUpdate', userAccount, keyAccountInfo.accountId, context.slot);
16
- }, this.driftClient.opts.commitment, [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getUserWithAuctionFilter)()]);
15
+ if (!this.subscriber) {
16
+ this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('AuctionSubscriber', 'User', this.driftClient.program, this.driftClient.program.account.user.coder.accounts.decode.bind(this.driftClient.program.account.user.coder.accounts), {
17
+ filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getUserWithAuctionFilter)()],
18
+ commitment: this.driftClient.opts.commitment,
19
+ }, this.resubTimeoutMs);
20
+ }
21
+ await this.subscriber.subscribe((accountId, data, context) => {
22
+ this.eventEmitter.emit('onAccountUpdate', data, accountId, context.slot);
23
+ });
17
24
  }
18
25
  async unsubscribe() {
19
- if (this.websocketId) {
20
- await this.driftClient.connection.removeProgramAccountChangeListener(this.websocketId);
26
+ if (!this.subscriber) {
27
+ return;
21
28
  }
29
+ this.subscriber.unsubscribe();
22
30
  }
23
31
  }
24
32
  exports.AuctionSubscriber = AuctionSubscriber;
@@ -4,6 +4,7 @@ import { ConfirmOptions, PublicKey } from '@solana/web3.js';
4
4
  export type AuctionSubscriberConfig = {
5
5
  driftClient: DriftClient;
6
6
  opts?: ConfirmOptions;
7
+ resubTimeoutMs?: number;
7
8
  };
8
9
  export interface AuctionSubscriberEvents {
9
10
  onAccountUpdate: (account: UserAccount, pubkey: PublicKey, slot: number) => void;
@@ -63,7 +63,7 @@ export declare class DLOB {
63
63
  mergeNodesToFill(restingLimitOrderNodesToFill: NodeToFill[], takingOrderNodesToFill: NodeToFill[]): NodeToFill[];
64
64
  findRestingLimitOrderNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
65
65
  findTakingNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid?: BN | undefined): NodeToFill[];
66
- findTakingNodesCrossingMakerNodes(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, takerNodeGenerator: Generator<DLOBNode>, makerNodeGeneratorFn: (marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, fallbackPrice?: BN) => Generator<DLOBNode>, doesCross: (takerPrice: BN | undefined, makerPrice: BN) => boolean, fallbackPrice?: BN): NodeToFill[];
66
+ findTakingNodesCrossingMakerNodes(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, takerNodeGenerator: Generator<DLOBNode>, makerNodeGeneratorFn: (marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData) => Generator<DLOBNode>, doesCross: (takerPrice: BN | undefined, makerPrice: BN) => boolean): NodeToFill[];
67
67
  findNodesCrossingFallbackLiquidity(marketType: MarketType, slot: number, oraclePriceData: OraclePriceData, nodeGenerator: Generator<DLOBNode>, fallbackPrice: BN, doesCross: (nodePrice: BN | undefined, fallbackPrice: BN) => boolean, minAuctionDuration: number): NodeToFill[];
68
68
  findExpiredNodesToFill(marketIndex: number, ts: number, marketType: MarketType): NodeToFill[];
69
69
  findJitAuctionNodesToFill(marketIndex: number, slot: number, oraclePriceData: OraclePriceData, marketType: MarketType): NodeToFill[];
@@ -107,18 +107,14 @@ export declare class DLOB {
107
107
  * @param slot
108
108
  * @param oraclePriceData
109
109
  * @param depth how many levels of the order book to return
110
- * @param fallbackAsk best ask for fallback liquidity, only relevant for perps
111
- * @param fallbackBid best bid for fallback liquidity, only relevant for perps
112
110
  * @param fallbackL2Generators L2 generators for fallback liquidity e.g. vAMM {@link getVammL2Generator}, openbook {@link SerumSubscriber}
113
111
  */
114
- getL2({ marketIndex, marketType, slot, oraclePriceData, depth, fallbackAsk, fallbackBid, fallbackL2Generators, }: {
112
+ getL2({ marketIndex, marketType, slot, oraclePriceData, depth, fallbackL2Generators, }: {
115
113
  marketIndex: number;
116
114
  marketType: MarketType;
117
115
  slot: number;
118
116
  oraclePriceData: OraclePriceData;
119
117
  depth: number;
120
- fallbackAsk?: BN;
121
- fallbackBid?: BN;
122
118
  fallbackL2Generators?: L2OrderBookGenerator[];
123
119
  }): L2OrderBook;
124
120
  /**
package/lib/dlob/DLOB.js CHANGED
@@ -365,7 +365,7 @@ class DLOB {
365
365
  findTakingNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid) {
366
366
  const nodesToFill = new Array();
367
367
  let takingOrderGenerator = this.getTakingAsks(marketIndex, marketType, slot, oraclePriceData);
368
- const takingAsksCrossingBids = this.findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takingOrderGenerator, this.getMakerLimitBids.bind(this), (takerPrice, makerPrice) => {
368
+ const takingAsksCrossingBids = this.findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takingOrderGenerator, this.getRestingLimitBids.bind(this), (takerPrice, makerPrice) => {
369
369
  if ((0, __1.isVariant)(marketType, 'spot')) {
370
370
  if (takerPrice === undefined) {
371
371
  return false;
@@ -375,7 +375,7 @@ class DLOB {
375
375
  }
376
376
  }
377
377
  return takerPrice === undefined || takerPrice.lte(makerPrice);
378
- }, fallbackAsk);
378
+ });
379
379
  for (const takingAskCrossingBid of takingAsksCrossingBids) {
380
380
  nodesToFill.push(takingAskCrossingBid);
381
381
  }
@@ -389,7 +389,7 @@ class DLOB {
389
389
  }
390
390
  }
391
391
  takingOrderGenerator = this.getTakingBids(marketIndex, marketType, slot, oraclePriceData);
392
- const takingBidsToFill = this.findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takingOrderGenerator, this.getMakerLimitAsks.bind(this), (takerPrice, makerPrice) => {
392
+ const takingBidsToFill = this.findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takingOrderGenerator, this.getRestingLimitAsks.bind(this), (takerPrice, makerPrice) => {
393
393
  if ((0, __1.isVariant)(marketType, 'spot')) {
394
394
  if (takerPrice === undefined) {
395
395
  return false;
@@ -399,7 +399,7 @@ class DLOB {
399
399
  }
400
400
  }
401
401
  return takerPrice === undefined || takerPrice.gte(makerPrice);
402
- }, fallbackBid);
402
+ });
403
403
  for (const takingBidToFill of takingBidsToFill) {
404
404
  nodesToFill.push(takingBidToFill);
405
405
  }
@@ -414,10 +414,10 @@ class DLOB {
414
414
  }
415
415
  return nodesToFill;
416
416
  }
417
- findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takerNodeGenerator, makerNodeGeneratorFn, doesCross, fallbackPrice) {
417
+ findTakingNodesCrossingMakerNodes(marketIndex, slot, marketType, oraclePriceData, takerNodeGenerator, makerNodeGeneratorFn, doesCross) {
418
418
  const nodesToFill = new Array();
419
419
  for (const takerNode of takerNodeGenerator) {
420
- const makerNodeGenerator = makerNodeGeneratorFn(marketIndex, slot, marketType, oraclePriceData, fallbackPrice);
420
+ const makerNodeGenerator = makerNodeGeneratorFn(marketIndex, slot, marketType, oraclePriceData);
421
421
  for (const makerNode of makerNodeGenerator) {
422
422
  // Can't match orders from the same user
423
423
  const sameUser = takerNode.userAccount.equals(makerNode.userAccount);
@@ -964,12 +964,10 @@ class DLOB {
964
964
  * @param slot
965
965
  * @param oraclePriceData
966
966
  * @param depth how many levels of the order book to return
967
- * @param fallbackAsk best ask for fallback liquidity, only relevant for perps
968
- * @param fallbackBid best bid for fallback liquidity, only relevant for perps
969
967
  * @param fallbackL2Generators L2 generators for fallback liquidity e.g. vAMM {@link getVammL2Generator}, openbook {@link SerumSubscriber}
970
968
  */
971
- getL2({ marketIndex, marketType, slot, oraclePriceData, depth, fallbackAsk, fallbackBid, fallbackL2Generators = [], }) {
972
- const makerAskL2LevelGenerator = (0, orderBookLevels_1.getL2GeneratorFromDLOBNodes)(this.getMakerLimitAsks(marketIndex, slot, marketType, oraclePriceData, fallbackBid), oraclePriceData, slot);
969
+ getL2({ marketIndex, marketType, slot, oraclePriceData, depth, fallbackL2Generators = [], }) {
970
+ const makerAskL2LevelGenerator = (0, orderBookLevels_1.getL2GeneratorFromDLOBNodes)(this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData), oraclePriceData, slot);
973
971
  const fallbackAskGenerators = fallbackL2Generators.map((fallbackL2Generator) => {
974
972
  return fallbackL2Generator.getL2Asks();
975
973
  });
@@ -977,7 +975,7 @@ class DLOB {
977
975
  return a.price.lt(b.price);
978
976
  });
979
977
  const asks = (0, orderBookLevels_1.createL2Levels)(askL2LevelGenerator, depth);
980
- const makerBidGenerator = (0, orderBookLevels_1.getL2GeneratorFromDLOBNodes)(this.getMakerLimitBids(marketIndex, slot, marketType, oraclePriceData, fallbackAsk), oraclePriceData, slot);
978
+ const makerBidGenerator = (0, orderBookLevels_1.getL2GeneratorFromDLOBNodes)(this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData), oraclePriceData, slot);
981
979
  const fallbackBidGenerators = fallbackL2Generators.map((fallbackOrders) => {
982
980
  return fallbackOrders.getL2Bids();
983
981
  });