@drift-labs/sdk 2.40.0-beta.7 → 2.40.0-beta.9
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.
- package/VERSION +1 -1
- package/lib/accounts/types.d.ts +5 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -1
- package/lib/accounts/webSocketAccountSubscriber.js +28 -2
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
- package/lib/accounts/webSocketProgramAccountSubscriber.js +99 -0
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +3 -2
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +2 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -2
- package/lib/auctionSubscriber/auctionSubscriber.d.ts +3 -2
- package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
- package/lib/auctionSubscriber/types.d.ts +1 -0
- package/lib/constants/spotMarkets.js +1 -1
- package/lib/driftClient.js +3 -3
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/math/superStake.d.ts +51 -4
- package/lib/math/superStake.js +173 -21
- package/lib/math/utils.d.ts +1 -0
- package/lib/math/utils.js +10 -1
- package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
- package/lib/orderSubscriber/OrderSubscriber.js +4 -3
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
- package/lib/orderSubscriber/WebsocketSubscription.js +13 -12
- package/lib/orderSubscriber/types.d.ts +1 -0
- package/package.json +1 -1
- package/src/accounts/types.ts +8 -1
- package/src/accounts/webSocketAccountSubscriber.ts +36 -2
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
- package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
- package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
- package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
- package/src/auctionSubscriber/types.ts +1 -0
- package/src/constants/spotMarkets.ts +1 -1
- package/src/driftClient.ts +2 -1
- package/src/driftClientConfig.ts +1 -0
- package/src/math/superStake.ts +248 -24
- package/src/math/utils.ts +12 -0
- package/src/orderSubscriber/OrderSubscriber.ts +12 -7
- package/src/orderSubscriber/WebsocketSubscription.ts +33 -23
- package/src/orderSubscriber/types.ts +1 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { DataAndSlot, BufferAndSlot, ProgramAccountSubscriber } from './types';
|
|
2
|
+
import { AnchorProvider, Program } from '@coral-xyz/anchor';
|
|
3
|
+
import {
|
|
4
|
+
Commitment,
|
|
5
|
+
Context,
|
|
6
|
+
KeyedAccountInfo,
|
|
7
|
+
MemcmpFilter,
|
|
8
|
+
PublicKey,
|
|
9
|
+
} from '@solana/web3.js';
|
|
10
|
+
import * as Buffer from 'buffer';
|
|
11
|
+
|
|
12
|
+
export class WebSocketProgramAccountSubscriber<T>
|
|
13
|
+
implements ProgramAccountSubscriber<T>
|
|
14
|
+
{
|
|
15
|
+
subscriptionName: string;
|
|
16
|
+
accountDiscriminator: string;
|
|
17
|
+
dataAndSlot?: DataAndSlot<T> & { accountId: PublicKey };
|
|
18
|
+
bufferAndSlot?: BufferAndSlot;
|
|
19
|
+
program: Program;
|
|
20
|
+
decodeBuffer: (accountName: string, ix: Buffer) => T;
|
|
21
|
+
onChange: (accountId: PublicKey, data: T, context: Context) => void;
|
|
22
|
+
listenerId?: number;
|
|
23
|
+
resubTimeoutMs?: number;
|
|
24
|
+
timeoutId?: NodeJS.Timeout;
|
|
25
|
+
options: { filters: MemcmpFilter[]; commitment?: Commitment };
|
|
26
|
+
|
|
27
|
+
receivingData = false;
|
|
28
|
+
|
|
29
|
+
public constructor(
|
|
30
|
+
subscriptionName: string,
|
|
31
|
+
accountDiscriminator: string,
|
|
32
|
+
program: Program,
|
|
33
|
+
decodeBufferFn: (accountName: string, ix: Buffer) => T,
|
|
34
|
+
options: { filters: MemcmpFilter[]; commitment?: Commitment } = {
|
|
35
|
+
filters: [],
|
|
36
|
+
},
|
|
37
|
+
resubTimeoutMs?: number
|
|
38
|
+
) {
|
|
39
|
+
this.subscriptionName = subscriptionName;
|
|
40
|
+
this.accountDiscriminator = accountDiscriminator;
|
|
41
|
+
this.program = program;
|
|
42
|
+
this.decodeBuffer = decodeBufferFn;
|
|
43
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
44
|
+
this.options = options;
|
|
45
|
+
this.receivingData = false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async subscribe(
|
|
49
|
+
onChange: (accountId: PublicKey, data: T, context: Context) => void
|
|
50
|
+
): Promise<void> {
|
|
51
|
+
if (this.listenerId) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
this.onChange = onChange;
|
|
56
|
+
|
|
57
|
+
this.listenerId = this.program.provider.connection.onProgramAccountChange(
|
|
58
|
+
this.program.programId,
|
|
59
|
+
(keyedAccountInfo, context) => {
|
|
60
|
+
if (this.resubTimeoutMs) {
|
|
61
|
+
this.receivingData = true;
|
|
62
|
+
clearTimeout(this.timeoutId);
|
|
63
|
+
this.handleRpcResponse(context, keyedAccountInfo);
|
|
64
|
+
this.setTimeout();
|
|
65
|
+
} else {
|
|
66
|
+
this.handleRpcResponse(context, keyedAccountInfo);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
this.options.commitment ??
|
|
70
|
+
(this.program.provider as AnchorProvider).opts.commitment,
|
|
71
|
+
this.options.filters
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (this.resubTimeoutMs) {
|
|
75
|
+
this.setTimeout();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private setTimeout(): void {
|
|
80
|
+
if (!this.onChange) {
|
|
81
|
+
throw new Error('onChange callback function must be set');
|
|
82
|
+
}
|
|
83
|
+
this.timeoutId = setTimeout(async () => {
|
|
84
|
+
if (this.receivingData) {
|
|
85
|
+
console.log(
|
|
86
|
+
`No ws data from ${this.subscriptionName} in ${this.resubTimeoutMs}ms, resubscribing`
|
|
87
|
+
);
|
|
88
|
+
await this.unsubscribe();
|
|
89
|
+
this.receivingData = false;
|
|
90
|
+
await this.subscribe(this.onChange);
|
|
91
|
+
}
|
|
92
|
+
}, this.resubTimeoutMs);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
handleRpcResponse(
|
|
96
|
+
context: Context,
|
|
97
|
+
keyedAccountInfo: KeyedAccountInfo
|
|
98
|
+
): void {
|
|
99
|
+
const newSlot = context.slot;
|
|
100
|
+
let newBuffer: Buffer | undefined = undefined;
|
|
101
|
+
if (keyedAccountInfo) {
|
|
102
|
+
newBuffer = keyedAccountInfo.accountInfo.data;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!this.bufferAndSlot) {
|
|
106
|
+
this.bufferAndSlot = {
|
|
107
|
+
buffer: newBuffer,
|
|
108
|
+
slot: newSlot,
|
|
109
|
+
};
|
|
110
|
+
if (newBuffer) {
|
|
111
|
+
const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
|
|
112
|
+
this.dataAndSlot = {
|
|
113
|
+
data: account,
|
|
114
|
+
slot: newSlot,
|
|
115
|
+
accountId: keyedAccountInfo.accountId,
|
|
116
|
+
};
|
|
117
|
+
this.onChange(keyedAccountInfo.accountId, account, context);
|
|
118
|
+
}
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (newSlot <= this.bufferAndSlot.slot) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const oldBuffer = this.bufferAndSlot.buffer;
|
|
127
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
128
|
+
this.bufferAndSlot = {
|
|
129
|
+
buffer: newBuffer,
|
|
130
|
+
slot: newSlot,
|
|
131
|
+
};
|
|
132
|
+
const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
|
|
133
|
+
this.dataAndSlot = {
|
|
134
|
+
data: account,
|
|
135
|
+
slot: newSlot,
|
|
136
|
+
accountId: keyedAccountInfo.accountId,
|
|
137
|
+
};
|
|
138
|
+
this.onChange(keyedAccountInfo.accountId, account, context);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
unsubscribe(): Promise<void> {
|
|
143
|
+
if (this.listenerId) {
|
|
144
|
+
const promise =
|
|
145
|
+
this.program.provider.connection.removeAccountChangeListener(
|
|
146
|
+
this.listenerId
|
|
147
|
+
);
|
|
148
|
+
this.listenerId = undefined;
|
|
149
|
+
return promise;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -14,17 +14,23 @@ import { UserAccount } from '../types';
|
|
|
14
14
|
|
|
15
15
|
export class WebSocketUserAccountSubscriber implements UserAccountSubscriber {
|
|
16
16
|
isSubscribed: boolean;
|
|
17
|
+
reconnectTimeoutMs?: number;
|
|
17
18
|
program: Program;
|
|
18
19
|
eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
|
|
19
20
|
userAccountPublicKey: PublicKey;
|
|
20
21
|
|
|
21
22
|
userDataAccountSubscriber: AccountSubscriber<UserAccount>;
|
|
22
23
|
|
|
23
|
-
public constructor(
|
|
24
|
+
public constructor(
|
|
25
|
+
program: Program,
|
|
26
|
+
userAccountPublicKey: PublicKey,
|
|
27
|
+
reconnectTimeoutMs?: number
|
|
28
|
+
) {
|
|
24
29
|
this.isSubscribed = false;
|
|
25
30
|
this.program = program;
|
|
26
31
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
27
32
|
this.eventEmitter = new EventEmitter();
|
|
33
|
+
this.reconnectTimeoutMs = reconnectTimeoutMs;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
async subscribe(userAccount?: UserAccount): Promise<boolean> {
|
|
@@ -35,7 +41,9 @@ export class WebSocketUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
35
41
|
this.userDataAccountSubscriber = new WebSocketAccountSubscriber(
|
|
36
42
|
'user',
|
|
37
43
|
this.program,
|
|
38
|
-
this.userAccountPublicKey
|
|
44
|
+
this.userAccountPublicKey,
|
|
45
|
+
undefined,
|
|
46
|
+
this.reconnectTimeoutMs
|
|
39
47
|
);
|
|
40
48
|
|
|
41
49
|
if (userAccount) {
|
|
@@ -16,17 +16,23 @@ export class WebSocketUserStatsAccountSubscriber
|
|
|
16
16
|
implements UserStatsAccountSubscriber
|
|
17
17
|
{
|
|
18
18
|
isSubscribed: boolean;
|
|
19
|
+
reconnectTimeoutMs?: number;
|
|
19
20
|
program: Program;
|
|
20
21
|
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
21
22
|
userStatsAccountPublicKey: PublicKey;
|
|
22
23
|
|
|
23
24
|
userStatsAccountSubscriber: AccountSubscriber<UserStatsAccount>;
|
|
24
25
|
|
|
25
|
-
public constructor(
|
|
26
|
+
public constructor(
|
|
27
|
+
program: Program,
|
|
28
|
+
userStatsAccountPublicKey: PublicKey,
|
|
29
|
+
reconnectTimeoutMs?: number
|
|
30
|
+
) {
|
|
26
31
|
this.isSubscribed = false;
|
|
27
32
|
this.program = program;
|
|
28
33
|
this.userStatsAccountPublicKey = userStatsAccountPublicKey;
|
|
29
34
|
this.eventEmitter = new EventEmitter();
|
|
35
|
+
this.reconnectTimeoutMs = reconnectTimeoutMs;
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
async subscribe(userStatsAccount?: UserStatsAccount): Promise<boolean> {
|
|
@@ -37,7 +43,9 @@ export class WebSocketUserStatsAccountSubscriber
|
|
|
37
43
|
this.userStatsAccountSubscriber = new WebSocketAccountSubscriber(
|
|
38
44
|
'userStats',
|
|
39
45
|
this.program,
|
|
40
|
-
this.userStatsAccountPublicKey
|
|
46
|
+
this.userStatsAccountPublicKey,
|
|
47
|
+
undefined,
|
|
48
|
+
this.reconnectTimeoutMs
|
|
41
49
|
);
|
|
42
50
|
|
|
43
51
|
if (userStatsAccount) {
|
|
@@ -4,48 +4,57 @@ import { getUserFilter, getUserWithAuctionFilter } from '../memcmp';
|
|
|
4
4
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
6
|
import { UserAccount } from '../types';
|
|
7
|
-
import { ConfirmOptions } from '@solana/web3.js';
|
|
7
|
+
import { ConfirmOptions, Context, PublicKey } from '@solana/web3.js';
|
|
8
|
+
import { WebSocketProgramAccountSubscriber } from '../accounts/webSocketProgramAccountSubscriber';
|
|
8
9
|
|
|
9
10
|
export class AuctionSubscriber {
|
|
10
11
|
private driftClient: DriftClient;
|
|
11
12
|
private opts: ConfirmOptions;
|
|
13
|
+
private resubTimeoutMs?: number;
|
|
12
14
|
|
|
13
15
|
eventEmitter: StrictEventEmitter<EventEmitter, AuctionSubscriberEvents>;
|
|
16
|
+
private subscriber: WebSocketProgramAccountSubscriber<UserAccount>;
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
constructor({ driftClient, opts }: AuctionSubscriberConfig) {
|
|
18
|
+
constructor({ driftClient, opts, resubTimeoutMs }: AuctionSubscriberConfig) {
|
|
18
19
|
this.driftClient = driftClient;
|
|
19
20
|
this.opts = opts || this.driftClient.opts;
|
|
20
21
|
this.eventEmitter = new EventEmitter();
|
|
22
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
public async subscribe() {
|
|
24
|
-
this.
|
|
25
|
-
this.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
if (!this.subscriber) {
|
|
27
|
+
this.subscriber = new WebSocketProgramAccountSubscriber<UserAccount>(
|
|
28
|
+
'AuctionSubscriber',
|
|
29
|
+
'User',
|
|
30
|
+
this.driftClient.program,
|
|
31
|
+
this.driftClient.program.account.user.coder.accounts.decode.bind(
|
|
32
|
+
this.driftClient.program.account.user.coder.accounts
|
|
33
|
+
),
|
|
34
|
+
{
|
|
35
|
+
filters: [getUserFilter(), getUserWithAuctionFilter()],
|
|
36
|
+
commitment: this.driftClient.opts.commitment,
|
|
37
|
+
},
|
|
38
|
+
this.resubTimeoutMs
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
await this.subscriber.subscribe(
|
|
43
|
+
(accountId: PublicKey, data: UserAccount, context: Context) => {
|
|
32
44
|
this.eventEmitter.emit(
|
|
33
45
|
'onAccountUpdate',
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
data,
|
|
47
|
+
accountId,
|
|
36
48
|
context.slot
|
|
37
49
|
);
|
|
38
|
-
}
|
|
39
|
-
this.driftClient.opts.commitment,
|
|
40
|
-
[getUserFilter(), getUserWithAuctionFilter()]
|
|
50
|
+
}
|
|
41
51
|
);
|
|
42
52
|
}
|
|
43
53
|
|
|
44
54
|
public async unsubscribe() {
|
|
45
|
-
if (this.
|
|
46
|
-
|
|
47
|
-
this.websocketId
|
|
48
|
-
);
|
|
55
|
+
if (!this.subscriber) {
|
|
56
|
+
return;
|
|
49
57
|
}
|
|
58
|
+
this.subscriber.unsubscribe();
|
|
50
59
|
}
|
|
51
60
|
}
|
|
@@ -128,7 +128,7 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
128
128
|
serumMarket: new PublicKey('B2na8Awyd7cpC59iEU43FagJAPLigr3AP3s38KM982bu'),
|
|
129
129
|
},
|
|
130
130
|
{
|
|
131
|
-
symbol: '
|
|
131
|
+
symbol: 'JitoSOL',
|
|
132
132
|
marketIndex: 6,
|
|
133
133
|
oracle: new PublicKey('7yyaeuJ1GGtVBLT2z2xub5ZWYKaNhF28mj1RdV4VDFVk'),
|
|
134
134
|
oracleSource: OracleSource.PYTH,
|
package/src/driftClient.ts
CHANGED
|
@@ -278,7 +278,8 @@ export class DriftClient {
|
|
|
278
278
|
config.perpMarketIndexes ?? [],
|
|
279
279
|
config.spotMarketIndexes ?? [],
|
|
280
280
|
config.oracleInfos ?? [],
|
|
281
|
-
noMarketsAndOraclesSpecified
|
|
281
|
+
noMarketsAndOraclesSpecified,
|
|
282
|
+
config.accountSubscription?.resubTimeoutMs
|
|
282
283
|
);
|
|
283
284
|
}
|
|
284
285
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|