@drift-labs/sdk 2.142.0-beta.13 → 2.142.0-beta.15
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/browser/accounts/grpcDriftClientAccountSubscriberV2.d.ts +46 -5
- package/lib/browser/accounts/grpcDriftClientAccountSubscriberV2.js +223 -49
- package/lib/browser/accounts/grpcMultiAccountSubscriber.d.ts +5 -3
- package/lib/browser/accounts/grpcMultiAccountSubscriber.js +77 -17
- package/lib/node/accounts/grpcDriftClientAccountSubscriberV2.d.ts +46 -5
- package/lib/node/accounts/grpcDriftClientAccountSubscriberV2.d.ts.map +1 -1
- package/lib/node/accounts/grpcDriftClientAccountSubscriberV2.js +223 -49
- package/lib/node/accounts/grpcMultiAccountSubscriber.d.ts +5 -3
- package/lib/node/accounts/grpcMultiAccountSubscriber.d.ts.map +1 -1
- package/lib/node/accounts/grpcMultiAccountSubscriber.js +77 -17
- package/package.json +1 -1
- package/scripts/client-test.ts +123 -162
- package/src/accounts/grpcDriftClientAccountSubscriberV2.ts +376 -81
- package/src/accounts/grpcMultiAccountSubscriber.ts +119 -29
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Program } from '@coral-xyz/anchor';
|
|
2
|
-
import { Context, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { Commitment, Context, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import * as Buffer from 'buffer';
|
|
4
4
|
import bs58 from 'bs58';
|
|
5
5
|
|
|
@@ -21,13 +21,32 @@ interface AccountInfoLike {
|
|
|
21
21
|
rentEpoch: number;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
function commitmentLevelToCommitment(
|
|
25
|
+
commitmentLevel: CommitmentLevel
|
|
26
|
+
): Commitment {
|
|
27
|
+
switch (commitmentLevel) {
|
|
28
|
+
case CommitmentLevel.PROCESSED:
|
|
29
|
+
return 'processed';
|
|
30
|
+
case CommitmentLevel.CONFIRMED:
|
|
31
|
+
return 'confirmed';
|
|
32
|
+
case CommitmentLevel.FINALIZED:
|
|
33
|
+
return 'finalized';
|
|
34
|
+
default:
|
|
35
|
+
return 'confirmed';
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class grpcMultiAccountSubscriber<T, U = undefined> {
|
|
25
40
|
private client: Client;
|
|
26
41
|
private stream: ClientDuplexStream<SubscribeRequest, SubscribeUpdate>;
|
|
27
42
|
private commitmentLevel: CommitmentLevel;
|
|
28
43
|
private program: Program;
|
|
29
44
|
private accountName: string;
|
|
30
|
-
private decodeBufferFn?: (
|
|
45
|
+
private decodeBufferFn?: (
|
|
46
|
+
buffer: Buffer,
|
|
47
|
+
pubkey?: string,
|
|
48
|
+
accountProps?: U
|
|
49
|
+
) => T;
|
|
31
50
|
private resubOpts?: ResubOpts;
|
|
32
51
|
private onUnsubscribe?: () => Promise<void>;
|
|
33
52
|
|
|
@@ -39,10 +58,11 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
39
58
|
private subscribedAccounts = new Set<string>();
|
|
40
59
|
private onChangeMap = new Map<
|
|
41
60
|
string,
|
|
42
|
-
(data: T, context: Context, buffer: Buffer) => void
|
|
61
|
+
(data: T, context: Context, buffer: Buffer, accountProps: U) => void
|
|
43
62
|
>();
|
|
44
63
|
|
|
45
64
|
private dataMap = new Map<string, DataAndSlot<T>>();
|
|
65
|
+
private accountPropsMap = new Map<string, U | Array<U>>();
|
|
46
66
|
|
|
47
67
|
private constructor(
|
|
48
68
|
client: Client,
|
|
@@ -51,7 +71,8 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
51
71
|
program: Program,
|
|
52
72
|
decodeBuffer?: (buffer: Buffer, pubkey?: string) => T,
|
|
53
73
|
resubOpts?: ResubOpts,
|
|
54
|
-
onUnsubscribe?: () => Promise<void
|
|
74
|
+
onUnsubscribe?: () => Promise<void>,
|
|
75
|
+
accountPropsMap?: Map<string, U | Array<U>>
|
|
55
76
|
) {
|
|
56
77
|
this.client = client;
|
|
57
78
|
this.commitmentLevel = commitmentLevel;
|
|
@@ -60,17 +81,19 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
60
81
|
this.decodeBufferFn = decodeBuffer;
|
|
61
82
|
this.resubOpts = resubOpts;
|
|
62
83
|
this.onUnsubscribe = onUnsubscribe;
|
|
84
|
+
this.accountPropsMap = accountPropsMap;
|
|
63
85
|
}
|
|
64
86
|
|
|
65
|
-
public static async create<U>(
|
|
87
|
+
public static async create<T, U = undefined>(
|
|
66
88
|
grpcConfigs: GrpcConfigs,
|
|
67
89
|
accountName: string,
|
|
68
90
|
program: Program,
|
|
69
|
-
decodeBuffer?: (buffer: Buffer, pubkey?: string) =>
|
|
91
|
+
decodeBuffer?: (buffer: Buffer, pubkey?: string, accountProps?: U) => T,
|
|
70
92
|
resubOpts?: ResubOpts,
|
|
71
93
|
clientProp?: Client,
|
|
72
|
-
onUnsubscribe?: () => Promise<void
|
|
73
|
-
|
|
94
|
+
onUnsubscribe?: () => Promise<void>,
|
|
95
|
+
accountPropsMap?: Map<string, U | Array<U>>
|
|
96
|
+
): Promise<grpcMultiAccountSubscriber<T, U>> {
|
|
74
97
|
const client = clientProp
|
|
75
98
|
? clientProp
|
|
76
99
|
: await createClient(
|
|
@@ -89,7 +112,8 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
89
112
|
program,
|
|
90
113
|
decodeBuffer,
|
|
91
114
|
resubOpts,
|
|
92
|
-
onUnsubscribe
|
|
115
|
+
onUnsubscribe,
|
|
116
|
+
accountPropsMap
|
|
93
117
|
);
|
|
94
118
|
}
|
|
95
119
|
|
|
@@ -105,13 +129,64 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
105
129
|
return this.dataMap;
|
|
106
130
|
}
|
|
107
131
|
|
|
132
|
+
async fetch(): Promise<void> {
|
|
133
|
+
try {
|
|
134
|
+
// Chunk account IDs into groups of 100 (getMultipleAccounts limit)
|
|
135
|
+
const chunkSize = 100;
|
|
136
|
+
const chunks: string[][] = [];
|
|
137
|
+
const accountIds = Array.from(this.subscribedAccounts.values());
|
|
138
|
+
for (let i = 0; i < accountIds.length; i += chunkSize) {
|
|
139
|
+
chunks.push(accountIds.slice(i, i + chunkSize));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Process all chunks concurrently
|
|
143
|
+
await Promise.all(
|
|
144
|
+
chunks.map(async (chunk) => {
|
|
145
|
+
const accountAddresses = chunk.map(
|
|
146
|
+
(accountId) => new PublicKey(accountId)
|
|
147
|
+
);
|
|
148
|
+
const rpcResponseAndContext =
|
|
149
|
+
await this.program.provider.connection.getMultipleAccountsInfoAndContext(
|
|
150
|
+
accountAddresses,
|
|
151
|
+
{
|
|
152
|
+
commitment: commitmentLevelToCommitment(this.commitmentLevel),
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const rpcResponse = rpcResponseAndContext.value;
|
|
157
|
+
const currentSlot = rpcResponseAndContext.context.slot;
|
|
158
|
+
|
|
159
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
160
|
+
const accountId = chunk[i];
|
|
161
|
+
const accountInfo = rpcResponse[i];
|
|
162
|
+
if (accountInfo) {
|
|
163
|
+
const perpMarket = this.program.coder.accounts.decode(
|
|
164
|
+
'PerpMarket',
|
|
165
|
+
accountInfo.data
|
|
166
|
+
);
|
|
167
|
+
this.setAccountData(accountId, perpMarket, currentSlot);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
})
|
|
171
|
+
);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
if (this.resubOpts?.logResubMessages) {
|
|
174
|
+
console.log(
|
|
175
|
+
`[${this.accountName}] grpcMultiAccountSubscriber error fetching accounts:`,
|
|
176
|
+
error
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
108
182
|
async subscribe(
|
|
109
183
|
accounts: PublicKey[],
|
|
110
184
|
onChange: (
|
|
111
185
|
accountId: PublicKey,
|
|
112
186
|
data: T,
|
|
113
187
|
context: Context,
|
|
114
|
-
buffer: Buffer
|
|
188
|
+
buffer: Buffer,
|
|
189
|
+
accountProps: U
|
|
115
190
|
) => void
|
|
116
191
|
): Promise<void> {
|
|
117
192
|
if (this.listenerId != null || this.isUnsubscribing) {
|
|
@@ -122,9 +197,9 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
122
197
|
for (const pk of accounts) {
|
|
123
198
|
const key = pk.toBase58();
|
|
124
199
|
this.subscribedAccounts.add(key);
|
|
125
|
-
this.onChangeMap.set(key, (data, ctx, buffer) => {
|
|
200
|
+
this.onChangeMap.set(key, (data, ctx, buffer, accountProps) => {
|
|
126
201
|
this.setAccountData(key, data, ctx.slot);
|
|
127
|
-
onChange(new PublicKey(key), data, ctx, buffer);
|
|
202
|
+
onChange(new PublicKey(key), data, ctx, buffer, accountProps);
|
|
128
203
|
});
|
|
129
204
|
}
|
|
130
205
|
|
|
@@ -170,23 +245,38 @@ export class grpcMultiAccountSubscriber<T> {
|
|
|
170
245
|
|
|
171
246
|
const context = { slot } as Context;
|
|
172
247
|
const buffer = accountInfo.data;
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
248
|
+
const accountProps = this.accountPropsMap?.get(accountPubkey);
|
|
249
|
+
|
|
250
|
+
const handleDataBuffer = (
|
|
251
|
+
context: Context,
|
|
252
|
+
buffer: Buffer,
|
|
253
|
+
accountProps: U
|
|
254
|
+
) => {
|
|
255
|
+
const data = this.decodeBufferFn
|
|
256
|
+
? this.decodeBufferFn(buffer, accountPubkey, accountProps)
|
|
257
|
+
: this.program.account[this.accountName].coder.accounts.decode(
|
|
258
|
+
this.capitalize(this.accountName),
|
|
259
|
+
buffer
|
|
260
|
+
);
|
|
261
|
+
const handler = this.onChangeMap.get(accountPubkey);
|
|
262
|
+
if (handler) {
|
|
263
|
+
if (this.resubOpts?.resubTimeoutMs) {
|
|
264
|
+
this.receivingData = true;
|
|
265
|
+
clearTimeout(this.timeoutId);
|
|
266
|
+
handler(data, context, buffer, accountProps);
|
|
267
|
+
this.setTimeout();
|
|
268
|
+
} else {
|
|
269
|
+
handler(data, context, buffer, accountProps);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
if (Array.isArray(accountProps)) {
|
|
275
|
+
for (const props of accountProps) {
|
|
276
|
+
handleDataBuffer(context, buffer, props);
|
|
189
277
|
}
|
|
278
|
+
} else {
|
|
279
|
+
handleDataBuffer(context, buffer, accountProps);
|
|
190
280
|
}
|
|
191
281
|
});
|
|
192
282
|
|