@drift-labs/sdk 2.40.0-beta.0 → 2.40.0-beta.10

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 (57) 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/auctionSubscriber/auctionSubscriber.d.ts +3 -2
  16. package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
  17. package/lib/auctionSubscriber/types.d.ts +1 -0
  18. package/lib/constants/spotMarkets.js +1 -0
  19. package/lib/driftClient.d.ts +2 -1
  20. package/lib/driftClient.js +5 -4
  21. package/lib/driftClientConfig.d.ts +1 -0
  22. package/lib/idl/drift.json +51 -0
  23. package/lib/jupiter/jupiterClient.d.ts +3 -1
  24. package/lib/jupiter/jupiterClient.js +3 -1
  25. package/lib/math/amm.js +7 -2
  26. package/lib/math/superStake.d.ts +51 -4
  27. package/lib/math/superStake.js +173 -21
  28. package/lib/math/utils.d.ts +1 -0
  29. package/lib/math/utils.js +10 -1
  30. package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
  31. package/lib/orderSubscriber/OrderSubscriber.js +4 -3
  32. package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
  33. package/lib/orderSubscriber/WebsocketSubscription.js +13 -12
  34. package/lib/orderSubscriber/types.d.ts +1 -0
  35. package/lib/user.d.ts +2 -2
  36. package/lib/user.js +5 -5
  37. package/package.json +1 -1
  38. package/src/accounts/types.ts +8 -1
  39. package/src/accounts/webSocketAccountSubscriber.ts +36 -2
  40. package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
  41. package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
  42. package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
  43. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
  44. package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
  45. package/src/auctionSubscriber/types.ts +1 -0
  46. package/src/constants/spotMarkets.ts +3 -0
  47. package/src/driftClient.ts +5 -1
  48. package/src/driftClientConfig.ts +1 -0
  49. package/src/idl/drift.json +51 -0
  50. package/src/jupiter/jupiterClient.ts +3 -0
  51. package/src/math/amm.ts +9 -2
  52. package/src/math/superStake.ts +248 -24
  53. package/src/math/utils.ts +12 -0
  54. package/src/orderSubscriber/OrderSubscriber.ts +12 -7
  55. package/src/orderSubscriber/WebsocketSubscription.ts +33 -23
  56. package/src/orderSubscriber/types.ts +1 -0
  57. package/src/user.ts +7 -5
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.40.0-beta.0
1
+ 2.40.0-beta.10
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
  }
@@ -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;
@@ -87,6 +87,7 @@ exports.MainnetSpotMarkets = [
87
87
  precision: new __1.BN(10).pow(numericConstants_1.EIGHT),
88
88
  precisionExp: numericConstants_1.EIGHT,
89
89
  serumMarket: new web3_js_1.PublicKey('BbJgE7HZMaDp5NTYvRh5jZSkQPVDTU8ubPFtpogUkEj4'),
90
+ phoenixMarket: new web3_js_1.PublicKey('Ew3vFDdtdGrknJAVVfraxCA37uNJtimXYPY4QjnfhFHH'),
90
91
  },
91
92
  {
92
93
  symbol: 'USDT',
@@ -319,7 +319,7 @@ export declare class DriftClient {
319
319
  * @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
320
320
  * @param txParams
321
321
  */
322
- swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }: {
322
+ swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, onlyDirectRoutes, }: {
323
323
  jupiterClient: JupiterClient;
324
324
  outMarketIndex: number;
325
325
  inMarketIndex: number;
@@ -331,6 +331,7 @@ export declare class DriftClient {
331
331
  route?: Route;
332
332
  reduceOnly?: SwapReduceOnly;
333
333
  txParams?: TxParams;
334
+ onlyDirectRoutes?: boolean;
334
335
  v6?: {
335
336
  quote?: QuoteResponse;
336
337
  };
@@ -66,7 +66,7 @@ class DriftClient {
66
66
  this._isSubscribed = val;
67
67
  }
68
68
  constructor(config) {
69
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
69
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
70
70
  this.users = new Map();
71
71
  this._isSubscribed = false;
72
72
  this.perpMarketLastSlotCache = new Map();
@@ -139,11 +139,11 @@ class DriftClient {
139
139
  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);
140
140
  }
141
141
  else {
142
- 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);
142
+ 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, (_u = config.accountSubscription) === null || _u === void 0 ? void 0 : _u.resubTimeoutMs);
143
143
  }
144
144
  this.eventEmitter = this.accountSubscriber.eventEmitter;
145
145
  this.txSender =
146
- (_u = config.txSender) !== null && _u !== void 0 ? _u : new retryTxSender_1.RetryTxSender({
146
+ (_v = config.txSender) !== null && _v !== void 0 ? _v : new retryTxSender_1.RetryTxSender({
147
147
  connection: this.connection,
148
148
  wallet: this.wallet,
149
149
  opts: this.opts,
@@ -1975,7 +1975,7 @@ class DriftClient {
1975
1975
  * @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
1976
1976
  * @param txParams
1977
1977
  */
1978
- async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }) {
1978
+ async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, onlyDirectRoutes = false, }) {
1979
1979
  let ixs;
1980
1980
  let lookupTables;
1981
1981
  if (v6) {
@@ -1990,6 +1990,7 @@ class DriftClient {
1990
1990
  swapMode,
1991
1991
  quote: v6.quote,
1992
1992
  reduceOnly,
1993
+ onlyDirectRoutes,
1993
1994
  });
1994
1995
  ixs = res.ixs;
1995
1996
  lookupTables = res.lookupTables;
@@ -28,6 +28,7 @@ export type DriftClientConfig = {
28
28
  };
29
29
  export type DriftClientSubscriptionConfig = {
30
30
  type: 'websocket';
31
+ resubTimeoutMs?: number;
31
32
  } | {
32
33
  type: 'polling';
33
34
  accountLoader: BulkAccountLoader;
@@ -6314,6 +6314,24 @@
6314
6314
  ]
6315
6315
  }
6316
6316
  },
6317
+ {
6318
+ "name": "MarketIdentifier",
6319
+ "type": {
6320
+ "kind": "struct",
6321
+ "fields": [
6322
+ {
6323
+ "name": "marketType",
6324
+ "type": {
6325
+ "defined": "MarketType"
6326
+ }
6327
+ },
6328
+ {
6329
+ "name": "marketIndex",
6330
+ "type": "u16"
6331
+ }
6332
+ ]
6333
+ }
6334
+ },
6317
6335
  {
6318
6336
  "name": "HistoricalOracleData",
6319
6337
  "type": {
@@ -8198,6 +8216,34 @@
8198
8216
  ]
8199
8217
  }
8200
8218
  },
8219
+ {
8220
+ "name": "MarginCalculationMode",
8221
+ "type": {
8222
+ "kind": "enum",
8223
+ "variants": [
8224
+ {
8225
+ "name": "Standard"
8226
+ },
8227
+ {
8228
+ "name": "Liquidation",
8229
+ "fields": [
8230
+ {
8231
+ "name": "margin_buffer",
8232
+ "type": "u128"
8233
+ },
8234
+ {
8235
+ "name": "market_to_track_margin_requirement",
8236
+ "type": {
8237
+ "option": {
8238
+ "defined": "MarketIdentifier"
8239
+ }
8240
+ }
8241
+ }
8242
+ ]
8243
+ }
8244
+ ]
8245
+ }
8246
+ },
8201
8247
  {
8202
8248
  "name": "OracleSource",
8203
8249
  "type": {
@@ -10781,6 +10827,11 @@
10781
10827
  "code": 6254,
10782
10828
  "name": "UserReduceOnly",
10783
10829
  "msg": "UserReduceOnly"
10830
+ },
10831
+ {
10832
+ "code": 6255,
10833
+ "name": "InvalidMarginCalculation",
10834
+ "msg": "InvalidMarginCalculation"
10784
10835
  }
10785
10836
  ]
10786
10837
  }
@@ -229,10 +229,12 @@ export declare class JupiterClient {
229
229
  * @param swapMode the swap mode (ExactIn or ExactOut)
230
230
  * @param onlyDirectRoutes whether to only return direct routes
231
231
  */
232
- getQuote({ inputMint, outputMint, amount, slippageBps, swapMode, onlyDirectRoutes, }: {
232
+ getQuote({ inputMint, outputMint, amount, maxAccounts, // 52 is an estimated amount with buffer
233
+ slippageBps, swapMode, onlyDirectRoutes, }: {
233
234
  inputMint: PublicKey;
234
235
  outputMint: PublicKey;
235
236
  amount: BN;
237
+ maxAccounts?: number;
236
238
  slippageBps?: number;
237
239
  swapMode?: SwapMode;
238
240
  onlyDirectRoutes?: boolean;
@@ -43,7 +43,8 @@ class JupiterClient {
43
43
  * @param swapMode the swap mode (ExactIn or ExactOut)
44
44
  * @param onlyDirectRoutes whether to only return direct routes
45
45
  */
46
- async getQuote({ inputMint, outputMint, amount, slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, }) {
46
+ async getQuote({ inputMint, outputMint, amount, maxAccounts = 52, // 52 is an estimated amount with buffer
47
+ slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, }) {
47
48
  const params = new URLSearchParams({
48
49
  inputMint: inputMint.toString(),
49
50
  outputMint: outputMint.toString(),
@@ -51,6 +52,7 @@ class JupiterClient {
51
52
  slippageBps: slippageBps.toString(),
52
53
  swapMode,
53
54
  onlyDirectRoutes: onlyDirectRoutes.toString(),
55
+ maxAccounts: maxAccounts.toString(),
54
56
  }).toString();
55
57
  const quote = await (await (0, node_fetch_1.default)(`${this.url}/v6/quote?${params}`)).json();
56
58
  return quote;
package/lib/math/amm.js CHANGED
@@ -253,8 +253,13 @@ function calculateVolSpreadBN(lastOracleConfPct, reservePrice, markStd, oracleSt
253
253
  const clampMax = numericConstants_1.PERCENTAGE_PRECISION.mul(new anchor_1.BN(16)).div(new anchor_1.BN(10));
254
254
  const longVolSpreadFactor = (0, __1.clampBN)(longIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
255
255
  const shortVolSpreadFactor = (0, __1.clampBN)(shortIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
256
- const longVolSpread = anchor_1.BN.max(lastOracleConfPct, volSpread.mul(longVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
257
- const shortVolSpread = anchor_1.BN.max(lastOracleConfPct, volSpread.mul(shortVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
256
+ // only consider confidence interval at full value when above 25 bps
257
+ let confComponent = lastOracleConfPct;
258
+ if (lastOracleConfPct.lte(numericConstants_1.PRICE_PRECISION.div(new anchor_1.BN(400)))) {
259
+ confComponent = lastOracleConfPct.div(new anchor_1.BN(10));
260
+ }
261
+ const longVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(longVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
262
+ const shortVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(shortVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
258
263
  return [longVolSpread, shortVolSpread];
259
264
  }
260
265
  exports.calculateVolSpreadBN = calculateVolSpreadBN;