@drift-labs/sdk 2.48.0-beta.2 → 2.48.0-beta.21
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/bulkAccountLoader.js +1 -1
- package/lib/accounts/pollingUserAccountSubscriber.js +14 -7
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +14 -7
- package/lib/accounts/webSocketAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +3 -2
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
- package/lib/accounts/webSocketProgramAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +1 -1
- package/lib/constants/spotMarkets.js +10 -0
- package/lib/dlob/orderBookLevels.js +1 -1
- package/lib/driftClient.js +4 -4
- package/lib/events/eventSubscriber.js +23 -2
- package/lib/events/pollingLogProvider.d.ts +1 -1
- package/lib/events/pollingLogProvider.js +1 -1
- package/lib/events/types.d.ts +9 -2
- package/lib/events/webSocketLogProvider.d.ts +15 -3
- package/lib/events/webSocketLogProvider.js +66 -7
- package/lib/orderSubscriber/OrderSubscriber.d.ts +5 -1
- package/lib/orderSubscriber/OrderSubscriber.js +24 -7
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -1
- package/lib/orderSubscriber/WebsocketSubscription.js +4 -3
- package/lib/orderSubscriber/types.d.ts +3 -1
- package/lib/slot/SlotSubscriber.js +4 -2
- package/lib/user.js +3 -3
- package/lib/userMap/userMap.d.ts +16 -4
- package/lib/userMap/userMap.js +83 -41
- package/lib/userMap/userStatsMap.d.ts +29 -8
- package/lib/userMap/userStatsMap.js +46 -41
- package/package.json +1 -1
- package/src/accounts/bulkAccountLoader.ts +1 -1
- package/src/accounts/pollingUserAccountSubscriber.ts +19 -11
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +20 -12
- package/src/accounts/webSocketAccountSubscriber.ts +1 -1
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +13 -6
- package/src/accounts/webSocketProgramAccountSubscriber.ts +1 -1
- package/src/accounts/webSocketUserAccountSubscriber.ts +1 -1
- package/src/constants/spotMarkets.ts +10 -0
- package/src/dlob/orderBookLevels.ts +1 -1
- package/src/driftClient.ts +3 -2
- package/src/events/eventSubscriber.ts +46 -2
- package/src/events/pollingLogProvider.ts +2 -2
- package/src/events/types.ts +11 -2
- package/src/events/webSocketLogProvider.ts +78 -8
- package/src/orderSubscriber/OrderSubscriber.ts +39 -15
- package/src/orderSubscriber/WebsocketSubscription.ts +7 -2
- package/src/orderSubscriber/types.ts +3 -1
- package/src/slot/SlotSubscriber.ts +4 -2
- package/src/user.ts +3 -3
- package/src/userMap/userMap.ts +139 -66
- package/src/userMap/userStatsMap.ts +64 -69
- package/tests/amm/test.ts +3 -2
- package/tests/dlob/test.ts +8 -5
|
@@ -150,6 +150,16 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
150
150
|
'2sTMN9A1D1qeZLF95XQgJCUPiKe5DiV52jLfZGqMP46m'
|
|
151
151
|
),
|
|
152
152
|
},
|
|
153
|
+
{
|
|
154
|
+
symbol: 'bSOL',
|
|
155
|
+
marketIndex: 8,
|
|
156
|
+
oracle: new PublicKey('AFrYBhb5wKQtxRS9UA9YRS4V3dwFm7SqmS6DHKq6YVgo'),
|
|
157
|
+
oracleSource: OracleSource.PYTH,
|
|
158
|
+
mint: new PublicKey('bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1'),
|
|
159
|
+
precision: new BN(10).pow(NINE),
|
|
160
|
+
precisionExp: NINE,
|
|
161
|
+
serumMarket: new PublicKey('ARjaHVxGCQfTvvKjLd7U7srvk6orthZSE6uqWchCczZc'),
|
|
162
|
+
},
|
|
153
163
|
];
|
|
154
164
|
|
|
155
165
|
export const SpotMarkets: { [key in DriftEnv]: SpotMarketConfig[] } = {
|
|
@@ -173,7 +173,7 @@ export function getVammL2Generator({
|
|
|
173
173
|
updatedAmm.orderStepSize
|
|
174
174
|
);
|
|
175
175
|
|
|
176
|
-
const minOrderSize = marketAccount.amm.
|
|
176
|
+
const minOrderSize = marketAccount.amm.minOrderSize;
|
|
177
177
|
if (openBids.lt(minOrderSize.muln(2))) {
|
|
178
178
|
openBids = ZERO;
|
|
179
179
|
}
|
package/src/driftClient.ts
CHANGED
|
@@ -283,7 +283,8 @@ export class DriftClient {
|
|
|
283
283
|
config.spotMarketIndexes ?? [],
|
|
284
284
|
config.oracleInfos ?? [],
|
|
285
285
|
noMarketsAndOraclesSpecified,
|
|
286
|
-
config.accountSubscription?.resubTimeoutMs
|
|
286
|
+
config.accountSubscription?.resubTimeoutMs,
|
|
287
|
+
config.accountSubscription?.commitment
|
|
287
288
|
);
|
|
288
289
|
}
|
|
289
290
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
@@ -2028,7 +2029,7 @@ export class DriftClient {
|
|
|
2028
2029
|
}
|
|
2029
2030
|
|
|
2030
2031
|
const tx = await this.buildTransaction(withdrawIxs, {
|
|
2031
|
-
computeUnits:
|
|
2032
|
+
computeUnits: 1_400_000,
|
|
2032
2033
|
});
|
|
2033
2034
|
const { txSig, slot } = await this.sendTransaction(
|
|
2034
2035
|
tx,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
EventMap,
|
|
9
9
|
LogProvider,
|
|
10
10
|
EventSubscriberEvents,
|
|
11
|
+
WebSocketLogProviderConfig,
|
|
11
12
|
} from './types';
|
|
12
13
|
import { TxEventCache } from './txEventCache';
|
|
13
14
|
import { EventList } from './eventList';
|
|
@@ -56,7 +57,8 @@ export class EventSubscriber {
|
|
|
56
57
|
this.logProvider = new WebSocketLogProvider(
|
|
57
58
|
this.connection,
|
|
58
59
|
this.address,
|
|
59
|
-
this.options.commitment
|
|
60
|
+
this.options.commitment,
|
|
61
|
+
this.options.logProviderConfig.resubTimeoutMs
|
|
60
62
|
);
|
|
61
63
|
} else {
|
|
62
64
|
this.logProvider = new PollingLogProvider(
|
|
@@ -75,6 +77,48 @@ export class EventSubscriber {
|
|
|
75
77
|
return true;
|
|
76
78
|
}
|
|
77
79
|
|
|
80
|
+
if (this.options.logProviderConfig.type === 'websocket') {
|
|
81
|
+
if (this.options.logProviderConfig.resubTimeoutMs) {
|
|
82
|
+
if (
|
|
83
|
+
this.options.logProviderConfig.maxReconnectAttempts &&
|
|
84
|
+
this.options.logProviderConfig.maxReconnectAttempts > 0
|
|
85
|
+
) {
|
|
86
|
+
const logProviderConfig = this.options
|
|
87
|
+
.logProviderConfig as WebSocketLogProviderConfig;
|
|
88
|
+
this.logProvider.eventEmitter.on(
|
|
89
|
+
'reconnect',
|
|
90
|
+
(reconnectAttempts) => {
|
|
91
|
+
if (
|
|
92
|
+
reconnectAttempts > logProviderConfig.maxReconnectAttempts
|
|
93
|
+
) {
|
|
94
|
+
console.log('Failing over to polling');
|
|
95
|
+
this.logProvider.eventEmitter.removeAllListeners('reconnect');
|
|
96
|
+
this.unsubscribe().then(() => {
|
|
97
|
+
this.logProvider = new PollingLogProvider(
|
|
98
|
+
this.connection,
|
|
99
|
+
this.address,
|
|
100
|
+
this.options.commitment,
|
|
101
|
+
logProviderConfig.fallbackFrequency,
|
|
102
|
+
logProviderConfig.fallbackBatchSize
|
|
103
|
+
);
|
|
104
|
+
this.logProvider.subscribe(
|
|
105
|
+
(txSig, slot, logs, mostRecentBlockTime) => {
|
|
106
|
+
this.handleTxLogs(
|
|
107
|
+
txSig,
|
|
108
|
+
slot,
|
|
109
|
+
logs,
|
|
110
|
+
mostRecentBlockTime
|
|
111
|
+
);
|
|
112
|
+
},
|
|
113
|
+
true
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
78
122
|
this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
|
|
79
123
|
this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
|
|
80
124
|
}, true);
|
|
@@ -158,7 +202,7 @@ export class EventSubscriber {
|
|
|
158
202
|
}
|
|
159
203
|
|
|
160
204
|
public async unsubscribe(): Promise<boolean> {
|
|
161
|
-
return await this.logProvider.unsubscribe();
|
|
205
|
+
return await this.logProvider.unsubscribe(true);
|
|
162
206
|
}
|
|
163
207
|
|
|
164
208
|
private parseEventsFromLogs(
|
|
@@ -25,10 +25,10 @@ export class PollingLogProvider implements LogProvider {
|
|
|
25
25
|
this.finality = commitment === 'finalized' ? 'finalized' : 'confirmed';
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
public subscribe(
|
|
28
|
+
public async subscribe(
|
|
29
29
|
callback: logProviderCallback,
|
|
30
30
|
skipHistory?: boolean
|
|
31
|
-
): boolean {
|
|
31
|
+
): Promise<boolean> {
|
|
32
32
|
if (this.intervalId) {
|
|
33
33
|
return true;
|
|
34
34
|
}
|
package/src/events/types.ts
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
CurveRecord,
|
|
16
16
|
SwapRecord,
|
|
17
17
|
} from '../index';
|
|
18
|
+
import { EventEmitter } from 'events';
|
|
18
19
|
|
|
19
20
|
export type EventSubscriptionOptions = {
|
|
20
21
|
address?: PublicKey;
|
|
@@ -126,12 +127,20 @@ export type logProviderCallback = (
|
|
|
126
127
|
|
|
127
128
|
export interface LogProvider {
|
|
128
129
|
isSubscribed(): boolean;
|
|
129
|
-
subscribe(
|
|
130
|
-
|
|
130
|
+
subscribe(
|
|
131
|
+
callback: logProviderCallback,
|
|
132
|
+
skipHistory?: boolean
|
|
133
|
+
): Promise<boolean>;
|
|
134
|
+
unsubscribe(external: boolean): Promise<boolean>;
|
|
135
|
+
eventEmitter?: EventEmitter;
|
|
131
136
|
}
|
|
132
137
|
|
|
133
138
|
export type WebSocketLogProviderConfig = {
|
|
134
139
|
type: 'websocket';
|
|
140
|
+
resubTimeoutMs?: number;
|
|
141
|
+
maxReconnectAttempts?: number;
|
|
142
|
+
fallbackFrequency?: number;
|
|
143
|
+
fallbackBatchSize?: number;
|
|
135
144
|
};
|
|
136
145
|
|
|
137
146
|
export type PollingLogProviderConfig = {
|
|
@@ -1,38 +1,108 @@
|
|
|
1
1
|
import { LogProvider, logProviderCallback } from './types';
|
|
2
2
|
import { Commitment, Connection, PublicKey } from '@solana/web3.js';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
3
4
|
|
|
4
5
|
export class WebSocketLogProvider implements LogProvider {
|
|
5
6
|
private subscriptionId: number;
|
|
7
|
+
private isUnsubscribing = false;
|
|
8
|
+
private externalUnsubscribe = false;
|
|
9
|
+
private receivingData = false;
|
|
10
|
+
private timeoutId?: NodeJS.Timeout;
|
|
11
|
+
private reconnectAttempts = 0;
|
|
12
|
+
eventEmitter?: EventEmitter;
|
|
13
|
+
private callback?: logProviderCallback;
|
|
6
14
|
public constructor(
|
|
7
15
|
private connection: Connection,
|
|
8
16
|
private address: PublicKey,
|
|
9
|
-
private commitment: Commitment
|
|
10
|
-
|
|
17
|
+
private commitment: Commitment,
|
|
18
|
+
private resubTimeoutMs?: number
|
|
19
|
+
) {
|
|
20
|
+
if (this.resubTimeoutMs) {
|
|
21
|
+
this.eventEmitter = new EventEmitter();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
11
24
|
|
|
12
|
-
public subscribe(callback: logProviderCallback): boolean {
|
|
25
|
+
public async subscribe(callback: logProviderCallback): Promise<boolean> {
|
|
13
26
|
if (this.subscriptionId) {
|
|
14
27
|
return true;
|
|
15
28
|
}
|
|
16
29
|
|
|
30
|
+
this.callback = callback;
|
|
31
|
+
try {
|
|
32
|
+
this.setSubscription(callback);
|
|
33
|
+
} catch (error) {
|
|
34
|
+
// Sometimes ws connection isn't ready, give it a few secs
|
|
35
|
+
setTimeout(() => this.setSubscription(callback), 2000);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (this.resubTimeoutMs) {
|
|
39
|
+
this.setTimeout();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public setSubscription(callback: logProviderCallback): void {
|
|
17
46
|
this.subscriptionId = this.connection.onLogs(
|
|
18
47
|
this.address,
|
|
19
48
|
(logs, ctx) => {
|
|
49
|
+
if (this.resubTimeoutMs && !this.isUnsubscribing) {
|
|
50
|
+
this.receivingData = true;
|
|
51
|
+
clearTimeout(this.timeoutId);
|
|
52
|
+
this.setTimeout();
|
|
53
|
+
}
|
|
20
54
|
callback(logs.signature, ctx.slot, logs.logs, undefined);
|
|
21
55
|
},
|
|
22
56
|
this.commitment
|
|
23
57
|
);
|
|
24
|
-
return true;
|
|
25
58
|
}
|
|
26
59
|
|
|
27
60
|
public isSubscribed(): boolean {
|
|
28
61
|
return this.subscriptionId !== undefined;
|
|
29
62
|
}
|
|
30
63
|
|
|
31
|
-
public async unsubscribe(): Promise<boolean> {
|
|
64
|
+
public async unsubscribe(external = false): Promise<boolean> {
|
|
65
|
+
this.isUnsubscribing = true;
|
|
66
|
+
this.externalUnsubscribe = external;
|
|
67
|
+
clearTimeout(this.timeoutId);
|
|
68
|
+
this.timeoutId = undefined;
|
|
69
|
+
|
|
32
70
|
if (this.subscriptionId !== undefined) {
|
|
33
|
-
|
|
34
|
-
|
|
71
|
+
try {
|
|
72
|
+
await this.connection.removeOnLogsListener(this.subscriptionId);
|
|
73
|
+
this.subscriptionId = undefined;
|
|
74
|
+
this.isUnsubscribing = false;
|
|
75
|
+
return true;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.log('Error unsubscribing from logs: ', err);
|
|
78
|
+
this.isUnsubscribing = false;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
this.isUnsubscribing = false;
|
|
83
|
+
return true;
|
|
35
84
|
}
|
|
36
|
-
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private setTimeout(): void {
|
|
88
|
+
this.timeoutId = setTimeout(async () => {
|
|
89
|
+
if (this.isUnsubscribing || this.externalUnsubscribe) {
|
|
90
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (this.receivingData) {
|
|
95
|
+
console.log(
|
|
96
|
+
`No log data in ${this.resubTimeoutMs}ms, resubscribing on attempt ${
|
|
97
|
+
this.reconnectAttempts + 1
|
|
98
|
+
}`
|
|
99
|
+
);
|
|
100
|
+
await this.unsubscribe();
|
|
101
|
+
this.receivingData = false;
|
|
102
|
+
this.reconnectAttempts++;
|
|
103
|
+
this.eventEmitter.emit('reconnect', this.reconnectAttempts);
|
|
104
|
+
this.subscribe(this.callback);
|
|
105
|
+
}
|
|
106
|
+
}, this.resubTimeoutMs);
|
|
37
107
|
}
|
|
38
108
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DriftClient } from '../driftClient';
|
|
2
2
|
import { UserAccount } from '../types';
|
|
3
3
|
import { getUserFilter, getUserWithOrderFilter } from '../memcmp';
|
|
4
|
-
import { PublicKey, RpcResponseAndContext } from '@solana/web3.js';
|
|
4
|
+
import { Commitment, PublicKey, RpcResponseAndContext } from '@solana/web3.js';
|
|
5
5
|
import { Buffer } from 'buffer';
|
|
6
6
|
import { DLOB } from '../dlob/DLOB';
|
|
7
7
|
import { OrderSubscriberConfig, OrderSubscriberEvents } from './types';
|
|
@@ -14,13 +14,17 @@ export class OrderSubscriber {
|
|
|
14
14
|
driftClient: DriftClient;
|
|
15
15
|
usersAccounts = new Map<string, { slot: number; userAccount: UserAccount }>();
|
|
16
16
|
subscription: PollingSubscription | WebsocketSubscription;
|
|
17
|
+
commitment: Commitment;
|
|
17
18
|
eventEmitter: StrictEventEmitter<EventEmitter, OrderSubscriberEvents>;
|
|
18
19
|
|
|
19
20
|
fetchPromise?: Promise<void>;
|
|
20
21
|
fetchPromiseResolver: () => void;
|
|
21
22
|
|
|
23
|
+
mostRecentSlot: number;
|
|
24
|
+
|
|
22
25
|
constructor(config: OrderSubscriberConfig) {
|
|
23
26
|
this.driftClient = config.driftClient;
|
|
27
|
+
this.commitment = config.subscriptionConfig.commitment || 'processed';
|
|
24
28
|
if (config.subscriptionConfig.type === 'polling') {
|
|
25
29
|
this.subscription = new PollingSubscription({
|
|
26
30
|
orderSubscriber: this,
|
|
@@ -29,6 +33,7 @@ export class OrderSubscriber {
|
|
|
29
33
|
} else {
|
|
30
34
|
this.subscription = new WebsocketSubscription({
|
|
31
35
|
orderSubscriber: this,
|
|
36
|
+
commitment: this.commitment,
|
|
32
37
|
skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
|
|
33
38
|
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
34
39
|
});
|
|
@@ -53,7 +58,7 @@ export class OrderSubscriber {
|
|
|
53
58
|
const rpcRequestArgs = [
|
|
54
59
|
this.driftClient.program.programId.toBase58(),
|
|
55
60
|
{
|
|
56
|
-
commitment: this.
|
|
61
|
+
commitment: this.commitment,
|
|
57
62
|
filters: [getUserFilter(), getUserWithOrderFilter()],
|
|
58
63
|
encoding: 'base64',
|
|
59
64
|
withContext: true,
|
|
@@ -81,18 +86,13 @@ export class OrderSubscriber {
|
|
|
81
86
|
const programAccountSet = new Set<string>();
|
|
82
87
|
for (const programAccount of rpcResponseAndContext.value) {
|
|
83
88
|
const key = programAccount.pubkey.toString();
|
|
84
|
-
// @ts-ignore
|
|
85
|
-
const buffer = Buffer.from(
|
|
86
|
-
programAccount.account.data[0],
|
|
87
|
-
programAccount.account.data[1]
|
|
88
|
-
);
|
|
89
89
|
programAccountSet.add(key);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
90
|
+
this.tryUpdateUserAccount(
|
|
91
|
+
key,
|
|
92
|
+
'raw',
|
|
93
|
+
programAccount.account.data,
|
|
94
|
+
slot
|
|
95
|
+
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
for (const key of this.usersAccounts.keys()) {
|
|
@@ -110,11 +110,31 @@ export class OrderSubscriber {
|
|
|
110
110
|
|
|
111
111
|
tryUpdateUserAccount(
|
|
112
112
|
key: string,
|
|
113
|
-
|
|
113
|
+
dataType: 'raw' | 'decoded',
|
|
114
|
+
data: string[] | UserAccount,
|
|
114
115
|
slot: number
|
|
115
116
|
): void {
|
|
117
|
+
if (!this.mostRecentSlot || slot > this.mostRecentSlot) {
|
|
118
|
+
this.mostRecentSlot = slot;
|
|
119
|
+
}
|
|
120
|
+
|
|
116
121
|
const slotAndUserAccount = this.usersAccounts.get(key);
|
|
117
|
-
if (!slotAndUserAccount || slotAndUserAccount.slot
|
|
122
|
+
if (!slotAndUserAccount || slotAndUserAccount.slot <= slot) {
|
|
123
|
+
let userAccount: UserAccount;
|
|
124
|
+
// Polling leads to a lot of redundant decoding, so we only decode if data is from a fresh slot
|
|
125
|
+
if (dataType === 'raw') {
|
|
126
|
+
// @ts-ignore
|
|
127
|
+
const buffer = Buffer.from(data[0], data[1]);
|
|
128
|
+
|
|
129
|
+
userAccount =
|
|
130
|
+
this.driftClient.program.account.user.coder.accounts.decodeUnchecked(
|
|
131
|
+
'User',
|
|
132
|
+
buffer
|
|
133
|
+
) as UserAccount;
|
|
134
|
+
} else {
|
|
135
|
+
userAccount = data as UserAccount;
|
|
136
|
+
}
|
|
137
|
+
|
|
118
138
|
const newOrders = userAccount.orders.filter(
|
|
119
139
|
(order) =>
|
|
120
140
|
order.slot.toNumber() > (slotAndUserAccount?.slot ?? 0) &&
|
|
@@ -148,6 +168,10 @@ export class OrderSubscriber {
|
|
|
148
168
|
return dlob;
|
|
149
169
|
}
|
|
150
170
|
|
|
171
|
+
public getSlot(): number {
|
|
172
|
+
return this.mostRecentSlot ?? 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
151
175
|
public async unsubscribe(): Promise<void> {
|
|
152
176
|
await this.subscription.unsubscribe();
|
|
153
177
|
}
|
|
@@ -2,10 +2,11 @@ import { OrderSubscriber } from './OrderSubscriber';
|
|
|
2
2
|
import { getNonIdleUserFilter, getUserFilter } from '../memcmp';
|
|
3
3
|
import { WebSocketProgramAccountSubscriber } from '../accounts/webSocketProgramAccountSubscriber';
|
|
4
4
|
import { UserAccount } from '../types';
|
|
5
|
-
import { Context, PublicKey } from '@solana/web3.js';
|
|
5
|
+
import { Commitment, Context, PublicKey } from '@solana/web3.js';
|
|
6
6
|
|
|
7
7
|
export class WebsocketSubscription {
|
|
8
8
|
private orderSubscriber: OrderSubscriber;
|
|
9
|
+
private commitment: Commitment;
|
|
9
10
|
private skipInitialLoad: boolean;
|
|
10
11
|
private resubTimeoutMs?: number;
|
|
11
12
|
|
|
@@ -13,14 +14,17 @@ export class WebsocketSubscription {
|
|
|
13
14
|
|
|
14
15
|
constructor({
|
|
15
16
|
orderSubscriber,
|
|
17
|
+
commitment,
|
|
16
18
|
skipInitialLoad = false,
|
|
17
19
|
resubTimeoutMs,
|
|
18
20
|
}: {
|
|
19
21
|
orderSubscriber: OrderSubscriber;
|
|
22
|
+
commitment: Commitment;
|
|
20
23
|
skipInitialLoad?: boolean;
|
|
21
24
|
resubTimeoutMs?: number;
|
|
22
25
|
}) {
|
|
23
26
|
this.orderSubscriber = orderSubscriber;
|
|
27
|
+
this.commitment = commitment;
|
|
24
28
|
this.skipInitialLoad = skipInitialLoad;
|
|
25
29
|
this.resubTimeoutMs = resubTimeoutMs;
|
|
26
30
|
}
|
|
@@ -36,7 +40,7 @@ export class WebsocketSubscription {
|
|
|
36
40
|
),
|
|
37
41
|
{
|
|
38
42
|
filters: [getUserFilter(), getNonIdleUserFilter()],
|
|
39
|
-
commitment: this.
|
|
43
|
+
commitment: this.commitment,
|
|
40
44
|
},
|
|
41
45
|
this.resubTimeoutMs
|
|
42
46
|
);
|
|
@@ -47,6 +51,7 @@ export class WebsocketSubscription {
|
|
|
47
51
|
const userKey = accountId.toBase58();
|
|
48
52
|
this.orderSubscriber.tryUpdateUserAccount(
|
|
49
53
|
userKey,
|
|
54
|
+
'decoded',
|
|
50
55
|
account,
|
|
51
56
|
context.slot
|
|
52
57
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PublicKey } from '@solana/web3.js';
|
|
1
|
+
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { Order, UserAccount } from '../types';
|
|
3
3
|
import { DriftClient } from '../driftClient';
|
|
4
4
|
|
|
@@ -8,11 +8,13 @@ export type OrderSubscriberConfig = {
|
|
|
8
8
|
| {
|
|
9
9
|
type: 'polling';
|
|
10
10
|
frequency: number;
|
|
11
|
+
commitment?: Commitment;
|
|
11
12
|
}
|
|
12
13
|
| {
|
|
13
14
|
type: 'websocket';
|
|
14
15
|
skipInitialLoad?: boolean;
|
|
15
16
|
resubTimeoutMs?: number;
|
|
17
|
+
commitment?: Commitment;
|
|
16
18
|
};
|
|
17
19
|
};
|
|
18
20
|
|
|
@@ -29,8 +29,10 @@ export class SlotSubscriber {
|
|
|
29
29
|
this.currentSlot = await this.connection.getSlot('confirmed');
|
|
30
30
|
|
|
31
31
|
this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
|
|
32
|
-
this.currentSlot
|
|
33
|
-
|
|
32
|
+
if (!this.currentSlot || this.currentSlot < slotInfo.slot) {
|
|
33
|
+
this.currentSlot = slotInfo.slot;
|
|
34
|
+
this.eventEmitter.emit('newSlot', slotInfo.slot);
|
|
35
|
+
}
|
|
34
36
|
});
|
|
35
37
|
}
|
|
36
38
|
|
package/src/user.ts
CHANGED
|
@@ -109,12 +109,12 @@ export class User {
|
|
|
109
109
|
);
|
|
110
110
|
} else if (config.accountSubscription?.type === 'custom') {
|
|
111
111
|
this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
|
|
112
|
-
} else
|
|
112
|
+
} else {
|
|
113
113
|
this.accountSubscriber = new WebSocketUserAccountSubscriber(
|
|
114
114
|
config.driftClient.program,
|
|
115
115
|
config.userAccountPublicKey,
|
|
116
|
-
config.accountSubscription
|
|
117
|
-
config.accountSubscription
|
|
116
|
+
config.accountSubscription?.resubTimeoutMs,
|
|
117
|
+
config.accountSubscription?.commitment
|
|
118
118
|
);
|
|
119
119
|
}
|
|
120
120
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|