@drift-labs/sdk 2.96.0-beta.0 → 2.96.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.
- package/VERSION +1 -1
- package/lib/accounts/grpcAccountSubscriber.d.ts +16 -0
- package/lib/accounts/grpcAccountSubscriber.js +155 -0
- package/lib/accounts/grpcDriftClientAccountSubscriber.d.ts +13 -0
- package/lib/accounts/grpcDriftClientAccountSubscriber.js +96 -0
- package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.d.ts +10 -0
- package/lib/accounts/grpcInsuranceFundStakeAccountSubscriber.js +30 -0
- package/lib/accounts/grpcProgramAccountSubscriber.d.ts +19 -0
- package/lib/accounts/grpcProgramAccountSubscriber.js +161 -0
- package/lib/accounts/grpcUserAccountSubscriber.d.ts +10 -0
- package/lib/accounts/grpcUserAccountSubscriber.js +28 -0
- package/lib/accounts/grpcUserStatsAccountSubscriber.d.ts +10 -0
- package/lib/accounts/grpcUserStatsAccountSubscriber.js +28 -0
- package/lib/accounts/types.d.ts +8 -0
- package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +3 -3
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +1 -1
- package/lib/driftClient.js +35 -14
- package/lib/driftClientConfig.d.ts +6 -0
- package/lib/orderSubscriber/OrderSubscriber.d.ts +2 -1
- package/lib/orderSubscriber/OrderSubscriber.js +19 -4
- package/lib/orderSubscriber/grpcSubscription.d.ts +25 -0
- package/lib/orderSubscriber/grpcSubscription.js +68 -0
- package/lib/orderSubscriber/types.d.ts +9 -0
- package/lib/user.js +11 -4
- package/lib/userConfig.d.ts +6 -1
- package/lib/userMap/grpcSubscription.d.ts +26 -0
- package/lib/userMap/grpcSubscription.js +42 -0
- package/lib/userMap/userMap.js +14 -0
- package/lib/userMap/userMapConfig.d.ts +7 -0
- package/lib/userStatsConfig.d.ts +6 -0
- package/package.json +3 -1
- package/src/accounts/grpcAccountSubscriber.ts +158 -0
- package/src/accounts/grpcDriftClientAccountSubscriber.ts +196 -0
- package/src/accounts/grpcInsuranceFundStakeAccountSubscriber.ts +62 -0
- package/src/accounts/grpcProgramAccountSubscriber.ts +181 -0
- package/src/accounts/grpcUserAccountSubscriber.ts +48 -0
- package/src/accounts/grpcUserStatsAccountSubscriber.ts +51 -0
- package/src/accounts/types.ts +9 -0
- package/src/accounts/webSocketAccountSubscriber.ts +1 -1
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +3 -3
- package/src/accounts/webSocketProgramAccountSubscriber.ts +1 -1
- package/src/driftClient.ts +28 -0
- package/src/driftClientConfig.ts +7 -0
- package/src/orderSubscriber/OrderSubscriber.ts +15 -1
- package/src/orderSubscriber/grpcSubscription.ts +126 -0
- package/src/orderSubscriber/types.ts +10 -0
- package/src/user.ts +11 -0
- package/src/userConfig.ts +7 -1
- package/src/userMap/grpcSubscription.ts +83 -0
- package/src/userMap/userMap.ts +17 -1
- package/src/userMap/userMapConfig.ts +8 -0
- package/src/userStatsConfig.ts +7 -0
|
@@ -60,9 +60,9 @@ export class WebSocketDriftClientAccountSubscriber
|
|
|
60
60
|
initialSpotMarketAccountData: Map<number, SpotMarketAccount>;
|
|
61
61
|
initialOraclePriceData: Map<string, OraclePriceData>;
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
protected isSubscribing = false;
|
|
64
|
+
protected subscriptionPromise: Promise<boolean>;
|
|
65
|
+
protected subscriptionPromiseResolver: (val: boolean) => void;
|
|
66
66
|
|
|
67
67
|
public constructor(
|
|
68
68
|
program: Program,
|
package/src/driftClient.ts
CHANGED
|
@@ -152,6 +152,7 @@ import { isVersionedTransaction } from './tx/utils';
|
|
|
152
152
|
import pythSolanaReceiverIdl from './idl/pyth_solana_receiver.json';
|
|
153
153
|
import { asV0Tx, PullFeed } from '@switchboard-xyz/on-demand';
|
|
154
154
|
import switchboardOnDemandIdl from './idl/switchboard_on_demand_30.json';
|
|
155
|
+
import { gprcDriftClientAccountSubscriber } from './accounts/grpcDriftClientAccountSubscriber';
|
|
155
156
|
|
|
156
157
|
type RemainingAccountParams = {
|
|
157
158
|
userAccounts: UserAccount[];
|
|
@@ -292,6 +293,19 @@ export class DriftClient {
|
|
|
292
293
|
type: 'polling',
|
|
293
294
|
accountLoader: config.accountSubscription.accountLoader,
|
|
294
295
|
};
|
|
296
|
+
} else if (config.accountSubscription?.type === 'grpc') {
|
|
297
|
+
this.userAccountSubscriptionConfig = {
|
|
298
|
+
type: 'grpc',
|
|
299
|
+
resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
|
|
300
|
+
logResubMessages: config.accountSubscription?.logResubMessages,
|
|
301
|
+
configs: config.accountSubscription?.configs,
|
|
302
|
+
};
|
|
303
|
+
this.userStatsAccountSubscriptionConfig = {
|
|
304
|
+
type: 'grpc',
|
|
305
|
+
resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
|
|
306
|
+
logResubMessages: config.accountSubscription?.logResubMessages,
|
|
307
|
+
configs: config.accountSubscription?.configs,
|
|
308
|
+
};
|
|
295
309
|
} else {
|
|
296
310
|
this.userAccountSubscriptionConfig = {
|
|
297
311
|
type: 'websocket',
|
|
@@ -338,6 +352,19 @@ export class DriftClient {
|
|
|
338
352
|
config.oracleInfos ?? [],
|
|
339
353
|
noMarketsAndOraclesSpecified
|
|
340
354
|
);
|
|
355
|
+
} else if (config.accountSubscription?.type === 'grpc') {
|
|
356
|
+
this.accountSubscriber = new gprcDriftClientAccountSubscriber(
|
|
357
|
+
config.accountSubscription.configs,
|
|
358
|
+
this.program,
|
|
359
|
+
config.perpMarketIndexes ?? [],
|
|
360
|
+
config.spotMarketIndexes ?? [],
|
|
361
|
+
config.oracleInfos ?? [],
|
|
362
|
+
noMarketsAndOraclesSpecified,
|
|
363
|
+
{
|
|
364
|
+
resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
|
|
365
|
+
logResubMessages: config.accountSubscription?.logResubMessages,
|
|
366
|
+
}
|
|
367
|
+
);
|
|
341
368
|
} else {
|
|
342
369
|
this.accountSubscriber = new WebSocketDriftClientAccountSubscriber(
|
|
343
370
|
this.program,
|
|
@@ -352,6 +379,7 @@ export class DriftClient {
|
|
|
352
379
|
config.accountSubscription?.commitment
|
|
353
380
|
);
|
|
354
381
|
}
|
|
382
|
+
|
|
355
383
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
356
384
|
|
|
357
385
|
this.metricsEventEmitter = new EventEmitter();
|
package/src/driftClientConfig.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
|
11
11
|
import { DriftEnv } from './config';
|
|
12
12
|
import { TxSender } from './tx/types';
|
|
13
13
|
import { TxHandler, TxHandlerConfig } from './tx/txHandler';
|
|
14
|
+
import { GrpcConfigs } from './accounts/types';
|
|
14
15
|
|
|
15
16
|
export type DriftClientConfig = {
|
|
16
17
|
connection: Connection;
|
|
@@ -48,4 +49,10 @@ export type DriftClientSubscriptionConfig =
|
|
|
48
49
|
| {
|
|
49
50
|
type: 'polling';
|
|
50
51
|
accountLoader: BulkAccountLoader;
|
|
52
|
+
}
|
|
53
|
+
| {
|
|
54
|
+
type: 'grpc';
|
|
55
|
+
configs: GrpcConfigs;
|
|
56
|
+
resubTimeoutMs?: number;
|
|
57
|
+
logResubMessages?: boolean;
|
|
51
58
|
};
|
|
@@ -11,11 +11,12 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
12
|
import { BN } from '../index';
|
|
13
13
|
import { decodeUser } from '../decode/user';
|
|
14
|
+
import { grpcSubscription } from './grpcSubscription';
|
|
14
15
|
|
|
15
16
|
export class OrderSubscriber {
|
|
16
17
|
driftClient: DriftClient;
|
|
17
18
|
usersAccounts = new Map<string, { slot: number; userAccount: UserAccount }>();
|
|
18
|
-
subscription: PollingSubscription | WebsocketSubscription;
|
|
19
|
+
subscription: PollingSubscription | WebsocketSubscription | grpcSubscription;
|
|
19
20
|
commitment: Commitment;
|
|
20
21
|
eventEmitter: StrictEventEmitter<EventEmitter, OrderSubscriberEvents>;
|
|
21
22
|
|
|
@@ -34,6 +35,19 @@ export class OrderSubscriber {
|
|
|
34
35
|
orderSubscriber: this,
|
|
35
36
|
frequency: config.subscriptionConfig.frequency,
|
|
36
37
|
});
|
|
38
|
+
} else if (config.subscriptionConfig.type === 'grpc') {
|
|
39
|
+
this.subscription = new grpcSubscription({
|
|
40
|
+
grpcConfigs: config.subscriptionConfig.configs,
|
|
41
|
+
orderSubscriber: this,
|
|
42
|
+
commitment: this.commitment,
|
|
43
|
+
skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
|
|
44
|
+
resubOpts: {
|
|
45
|
+
resubTimeoutMs: config.subscriptionConfig?.resubTimeoutMs,
|
|
46
|
+
logResubMessages: config.subscriptionConfig?.logResubMessages,
|
|
47
|
+
},
|
|
48
|
+
resyncIntervalMs: config.subscriptionConfig.resyncIntervalMs,
|
|
49
|
+
decoded: config.decodeData,
|
|
50
|
+
});
|
|
37
51
|
} else {
|
|
38
52
|
this.subscription = new WebsocketSubscription({
|
|
39
53
|
orderSubscriber: this,
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Commitment, Context, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { Buffer } from 'buffer';
|
|
3
|
+
import { grpcProgramAccountSubscriber } from '../accounts/grpcProgramAccountSubscriber';
|
|
4
|
+
import { OrderSubscriber } from './OrderSubscriber';
|
|
5
|
+
import { GrpcConfigs, ResubOpts } from '../accounts/types';
|
|
6
|
+
import { UserAccount } from '../types';
|
|
7
|
+
import { getNonIdleUserFilter, getUserFilter } from '../memcmp';
|
|
8
|
+
|
|
9
|
+
export class grpcSubscription {
|
|
10
|
+
private orderSubscriber: OrderSubscriber;
|
|
11
|
+
private commitment: Commitment;
|
|
12
|
+
private skipInitialLoad: boolean;
|
|
13
|
+
private resubOpts?: ResubOpts;
|
|
14
|
+
private resyncIntervalMs?: number;
|
|
15
|
+
|
|
16
|
+
private subscriber?: grpcProgramAccountSubscriber<UserAccount>;
|
|
17
|
+
private resyncTimeoutId?: NodeJS.Timeout;
|
|
18
|
+
|
|
19
|
+
private decoded?: boolean;
|
|
20
|
+
|
|
21
|
+
private grpcConfigs: GrpcConfigs;
|
|
22
|
+
|
|
23
|
+
constructor({
|
|
24
|
+
grpcConfigs,
|
|
25
|
+
orderSubscriber,
|
|
26
|
+
commitment,
|
|
27
|
+
skipInitialLoad = false,
|
|
28
|
+
resubOpts,
|
|
29
|
+
resyncIntervalMs,
|
|
30
|
+
decoded = true,
|
|
31
|
+
}: {
|
|
32
|
+
grpcConfigs: GrpcConfigs;
|
|
33
|
+
orderSubscriber: OrderSubscriber;
|
|
34
|
+
commitment: Commitment;
|
|
35
|
+
skipInitialLoad?: boolean;
|
|
36
|
+
resubOpts?: ResubOpts;
|
|
37
|
+
resyncIntervalMs?: number;
|
|
38
|
+
decoded?: boolean;
|
|
39
|
+
}) {
|
|
40
|
+
this.orderSubscriber = orderSubscriber;
|
|
41
|
+
this.commitment = commitment;
|
|
42
|
+
this.skipInitialLoad = skipInitialLoad;
|
|
43
|
+
this.resubOpts = resubOpts;
|
|
44
|
+
this.resyncIntervalMs = resyncIntervalMs;
|
|
45
|
+
this.decoded = decoded;
|
|
46
|
+
this.grpcConfigs = grpcConfigs;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public async subscribe(): Promise<void> {
|
|
50
|
+
if (this.subscriber) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.subscriber = new grpcProgramAccountSubscriber<UserAccount>(
|
|
55
|
+
this.grpcConfigs,
|
|
56
|
+
'OrderSubscriber',
|
|
57
|
+
'User',
|
|
58
|
+
this.orderSubscriber.driftClient.program,
|
|
59
|
+
this.orderSubscriber.decodeFn,
|
|
60
|
+
{
|
|
61
|
+
filters: [getUserFilter(), getNonIdleUserFilter()],
|
|
62
|
+
commitment: this.commitment,
|
|
63
|
+
},
|
|
64
|
+
this.resubOpts
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
await this.subscriber.subscribe(
|
|
68
|
+
(
|
|
69
|
+
accountId: PublicKey,
|
|
70
|
+
account: UserAccount,
|
|
71
|
+
context: Context,
|
|
72
|
+
buffer: Buffer
|
|
73
|
+
) => {
|
|
74
|
+
const userKey = accountId.toBase58();
|
|
75
|
+
if (this.decoded ?? true) {
|
|
76
|
+
this.orderSubscriber.tryUpdateUserAccount(
|
|
77
|
+
userKey,
|
|
78
|
+
'decoded',
|
|
79
|
+
account,
|
|
80
|
+
context.slot
|
|
81
|
+
);
|
|
82
|
+
} else {
|
|
83
|
+
this.orderSubscriber.tryUpdateUserAccount(
|
|
84
|
+
userKey,
|
|
85
|
+
'buffer',
|
|
86
|
+
buffer,
|
|
87
|
+
context.slot
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
if (!this.skipInitialLoad) {
|
|
94
|
+
await this.orderSubscriber.fetch();
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (this.resyncIntervalMs) {
|
|
98
|
+
const recursiveResync = () => {
|
|
99
|
+
this.resyncTimeoutId = setTimeout(() => {
|
|
100
|
+
this.orderSubscriber
|
|
101
|
+
.fetch()
|
|
102
|
+
.catch((e) => {
|
|
103
|
+
console.error('Failed to resync in OrderSubscriber');
|
|
104
|
+
console.log(e);
|
|
105
|
+
})
|
|
106
|
+
.finally(() => {
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
108
|
+
if (!this.resyncTimeoutId) return;
|
|
109
|
+
recursiveResync();
|
|
110
|
+
});
|
|
111
|
+
}, this.resyncIntervalMs);
|
|
112
|
+
};
|
|
113
|
+
recursiveResync();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public async unsubscribe(): Promise<void> {
|
|
118
|
+
if (!this.subscriber) return;
|
|
119
|
+
await this.subscriber.unsubscribe();
|
|
120
|
+
this.subscriber = undefined;
|
|
121
|
+
if (this.resyncTimeoutId !== undefined) {
|
|
122
|
+
clearTimeout(this.resyncTimeoutId);
|
|
123
|
+
this.resyncTimeoutId = undefined;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
2
2
|
import { Order, UserAccount } from '../types';
|
|
3
3
|
import { DriftClient } from '../driftClient';
|
|
4
|
+
import { GrpcConfigs } from '../accounts/types';
|
|
4
5
|
|
|
5
6
|
export type OrderSubscriberConfig = {
|
|
6
7
|
driftClient: DriftClient;
|
|
@@ -10,6 +11,15 @@ export type OrderSubscriberConfig = {
|
|
|
10
11
|
frequency: number;
|
|
11
12
|
commitment?: Commitment;
|
|
12
13
|
}
|
|
14
|
+
| {
|
|
15
|
+
type: 'grpc';
|
|
16
|
+
skipInitialLoad?: boolean;
|
|
17
|
+
resubTimeoutMs?: number;
|
|
18
|
+
logResubMessages?: boolean;
|
|
19
|
+
resyncIntervalMs?: number;
|
|
20
|
+
configs: GrpcConfigs;
|
|
21
|
+
commitment?: Commitment;
|
|
22
|
+
}
|
|
13
23
|
| {
|
|
14
24
|
type: 'websocket';
|
|
15
25
|
skipInitialLoad?: boolean;
|
package/src/user.ts
CHANGED
|
@@ -98,6 +98,7 @@ import {
|
|
|
98
98
|
calculatePerpFuelBonus,
|
|
99
99
|
calculateInsuranceFuelBonus,
|
|
100
100
|
} from './math/fuel';
|
|
101
|
+
import { grpcUserAccountSubscriber } from './accounts/grpcUserAccountSubscriber';
|
|
101
102
|
|
|
102
103
|
export class User {
|
|
103
104
|
driftClient: DriftClient;
|
|
@@ -128,6 +129,16 @@ export class User {
|
|
|
128
129
|
);
|
|
129
130
|
} else if (config.accountSubscription?.type === 'custom') {
|
|
130
131
|
this.accountSubscriber = config.accountSubscription.userAccountSubscriber;
|
|
132
|
+
} else if (config.accountSubscription?.type === 'grpc') {
|
|
133
|
+
this.accountSubscriber = new grpcUserAccountSubscriber(
|
|
134
|
+
config.accountSubscription.configs,
|
|
135
|
+
config.driftClient.program,
|
|
136
|
+
config.userAccountPublicKey,
|
|
137
|
+
{
|
|
138
|
+
resubTimeoutMs: config.accountSubscription?.resubTimeoutMs,
|
|
139
|
+
logResubMessages: config.accountSubscription?.logResubMessages,
|
|
140
|
+
}
|
|
141
|
+
);
|
|
131
142
|
} else {
|
|
132
143
|
this.accountSubscriber = new WebSocketUserAccountSubscriber(
|
|
133
144
|
config.driftClient.program,
|
package/src/userConfig.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DriftClient } from './driftClient';
|
|
2
2
|
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
4
|
-
import { UserAccountSubscriber } from './accounts/types';
|
|
4
|
+
import { GrpcConfigs, UserAccountSubscriber } from './accounts/types';
|
|
5
5
|
|
|
6
6
|
export type UserConfig = {
|
|
7
7
|
accountSubscription?: UserSubscriptionConfig;
|
|
@@ -23,4 +23,10 @@ export type UserSubscriptionConfig =
|
|
|
23
23
|
| {
|
|
24
24
|
type: 'custom';
|
|
25
25
|
userAccountSubscriber: UserAccountSubscriber;
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
type: 'grpc';
|
|
29
|
+
resubTimeoutMs?: number;
|
|
30
|
+
logResubMessages?: boolean;
|
|
31
|
+
configs: GrpcConfigs;
|
|
26
32
|
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { UserMap } from './userMap';
|
|
2
|
+
import { getNonIdleUserFilter, getUserFilter } from '../memcmp';
|
|
3
|
+
import { WebSocketProgramAccountSubscriber } from '../accounts/webSocketProgramAccountSubscriber';
|
|
4
|
+
import { UserAccount } from '../types';
|
|
5
|
+
import { Commitment, Context, PublicKey } from '@solana/web3.js';
|
|
6
|
+
import { GrpcConfigs, ResubOpts } from '../accounts/types';
|
|
7
|
+
import { grpcProgramAccountSubscriber } from '../accounts/grpcProgramAccountSubscriber';
|
|
8
|
+
|
|
9
|
+
export class grpcSubscription {
|
|
10
|
+
private configs: GrpcConfigs;
|
|
11
|
+
private userMap: UserMap;
|
|
12
|
+
private commitment: Commitment;
|
|
13
|
+
private skipInitialLoad: boolean;
|
|
14
|
+
private resubOpts?: ResubOpts;
|
|
15
|
+
private includeIdle?: boolean;
|
|
16
|
+
private decodeFn: (name: string, data: Buffer) => UserAccount;
|
|
17
|
+
|
|
18
|
+
private subscriber: WebSocketProgramAccountSubscriber<UserAccount>;
|
|
19
|
+
|
|
20
|
+
constructor({
|
|
21
|
+
configs,
|
|
22
|
+
userMap,
|
|
23
|
+
commitment,
|
|
24
|
+
skipInitialLoad = false,
|
|
25
|
+
resubOpts,
|
|
26
|
+
includeIdle = false,
|
|
27
|
+
decodeFn,
|
|
28
|
+
}: {
|
|
29
|
+
configs: GrpcConfigs;
|
|
30
|
+
userMap: UserMap;
|
|
31
|
+
commitment: Commitment;
|
|
32
|
+
skipInitialLoad?: boolean;
|
|
33
|
+
resubOpts?: ResubOpts;
|
|
34
|
+
includeIdle?: boolean;
|
|
35
|
+
decodeFn: (name: string, data: Buffer) => UserAccount;
|
|
36
|
+
}) {
|
|
37
|
+
this.userMap = userMap;
|
|
38
|
+
this.commitment = commitment;
|
|
39
|
+
this.skipInitialLoad = skipInitialLoad;
|
|
40
|
+
this.resubOpts = resubOpts;
|
|
41
|
+
this.includeIdle = includeIdle || false;
|
|
42
|
+
this.decodeFn = decodeFn;
|
|
43
|
+
this.configs = configs;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public async subscribe(): Promise<void> {
|
|
47
|
+
if (!this.subscriber) {
|
|
48
|
+
const filters = [getUserFilter()];
|
|
49
|
+
if (!this.includeIdle) {
|
|
50
|
+
filters.push(getNonIdleUserFilter());
|
|
51
|
+
}
|
|
52
|
+
this.subscriber = new grpcProgramAccountSubscriber<UserAccount>(
|
|
53
|
+
this.configs,
|
|
54
|
+
'UserMap',
|
|
55
|
+
'User',
|
|
56
|
+
this.userMap.driftClient.program,
|
|
57
|
+
this.decodeFn,
|
|
58
|
+
{
|
|
59
|
+
filters,
|
|
60
|
+
commitment: this.commitment,
|
|
61
|
+
},
|
|
62
|
+
this.resubOpts
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
await this.subscriber.subscribe(
|
|
67
|
+
(accountId: PublicKey, account: UserAccount, context: Context) => {
|
|
68
|
+
const userKey = accountId.toBase58();
|
|
69
|
+
this.userMap.updateUserAccount(userKey, account, context.slot);
|
|
70
|
+
}
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
if (!this.skipInitialLoad) {
|
|
74
|
+
await this.userMap.sync();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async unsubscribe(): Promise<void> {
|
|
79
|
+
if (!this.subscriber) return;
|
|
80
|
+
await this.subscriber.unsubscribe();
|
|
81
|
+
this.subscriber = undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/userMap/userMap.ts
CHANGED
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
import { WebsocketSubscription } from './WebsocketSubscription';
|
|
37
37
|
import { PollingSubscription } from './PollingSubscription';
|
|
38
38
|
import { decodeUser } from '../decode/user';
|
|
39
|
+
import { grpcSubscription } from './grpcSubscription';
|
|
39
40
|
|
|
40
41
|
const MAX_USER_ACCOUNT_SIZE_BYTES = 4376;
|
|
41
42
|
|
|
@@ -75,7 +76,10 @@ export class UserMap implements UserMapInterface {
|
|
|
75
76
|
private includeIdle: boolean;
|
|
76
77
|
private disableSyncOnTotalAccountsChange: boolean;
|
|
77
78
|
private lastNumberOfSubAccounts: BN;
|
|
78
|
-
private subscription:
|
|
79
|
+
private subscription:
|
|
80
|
+
| PollingSubscription
|
|
81
|
+
| WebsocketSubscription
|
|
82
|
+
| grpcSubscription;
|
|
79
83
|
private stateAccountUpdateCallback = async (state: StateAccount) => {
|
|
80
84
|
if (!state.numberOfSubAccounts.eq(this.lastNumberOfSubAccounts)) {
|
|
81
85
|
await this.sync();
|
|
@@ -122,6 +126,18 @@ export class UserMap implements UserMapInterface {
|
|
|
122
126
|
frequency: config.subscriptionConfig.frequency,
|
|
123
127
|
skipInitialLoad: config.skipInitialLoad,
|
|
124
128
|
});
|
|
129
|
+
} else if (config.subscriptionConfig.type === 'grpc') {
|
|
130
|
+
this.subscription = new grpcSubscription({
|
|
131
|
+
configs: config.subscriptionConfig.configs,
|
|
132
|
+
userMap: this,
|
|
133
|
+
commitment: this.commitment,
|
|
134
|
+
resubOpts: {
|
|
135
|
+
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
136
|
+
logResubMessages: config.subscriptionConfig.logResubMessages,
|
|
137
|
+
},
|
|
138
|
+
skipInitialLoad: config.skipInitialLoad,
|
|
139
|
+
decodeFn,
|
|
140
|
+
});
|
|
125
141
|
} else {
|
|
126
142
|
this.subscription = new WebsocketSubscription({
|
|
127
143
|
userMap: this,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Commitment, Connection } from '@solana/web3.js';
|
|
2
2
|
import { DriftClient } from '../driftClient';
|
|
3
|
+
import { GrpcConfigs } from '../accounts/types';
|
|
3
4
|
|
|
4
5
|
// passed into UserMap.getUniqueAuthorities to filter users
|
|
5
6
|
export type UserAccountFilterCriteria = {
|
|
@@ -27,6 +28,13 @@ export type UserMapConfig = {
|
|
|
27
28
|
frequency: number;
|
|
28
29
|
commitment?: Commitment;
|
|
29
30
|
}
|
|
31
|
+
| {
|
|
32
|
+
type: 'grpc';
|
|
33
|
+
configs: GrpcConfigs;
|
|
34
|
+
resubTimeoutMs?: number;
|
|
35
|
+
logResubMessages?: boolean;
|
|
36
|
+
commitment?: Commitment;
|
|
37
|
+
}
|
|
30
38
|
| {
|
|
31
39
|
type: 'websocket';
|
|
32
40
|
resubTimeoutMs?: number;
|
package/src/userStatsConfig.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DriftClient } from './driftClient';
|
|
2
2
|
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { BulkAccountLoader } from './accounts/bulkAccountLoader';
|
|
4
|
+
import { GrpcConfigs } from './accounts/types';
|
|
4
5
|
|
|
5
6
|
export type UserStatsConfig = {
|
|
6
7
|
accountSubscription?: UserStatsSubscriptionConfig;
|
|
@@ -21,4 +22,10 @@ export type UserStatsSubscriptionConfig =
|
|
|
21
22
|
}
|
|
22
23
|
| {
|
|
23
24
|
type: 'custom';
|
|
25
|
+
}
|
|
26
|
+
| {
|
|
27
|
+
type: 'grpc';
|
|
28
|
+
resubTimeoutMs?: number;
|
|
29
|
+
logResubMessages?: boolean;
|
|
30
|
+
configs: GrpcConfigs;
|
|
24
31
|
};
|