@drift-labs/sdk 2.98.0-beta.9 → 2.99.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.
Files changed (69) hide show
  1. package/VERSION +1 -1
  2. package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
  3. package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
  4. package/lib/browser/accounts/types.d.ts +14 -1
  5. package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
  6. package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
  7. package/lib/browser/addresses/pda.d.ts +1 -0
  8. package/lib/browser/addresses/pda.js +8 -1
  9. package/lib/browser/constants/perpMarkets.js +11 -0
  10. package/lib/browser/constants/spotMarkets.js +2 -2
  11. package/lib/browser/driftClient.d.ts +14 -4
  12. package/lib/browser/driftClient.js +64 -19
  13. package/lib/browser/idl/drift.json +199 -8
  14. package/lib/browser/index.d.ts +4 -0
  15. package/lib/browser/index.js +4 -0
  16. package/lib/browser/jupiter/jupiterClient.d.ts +6 -0
  17. package/lib/browser/memcmp.d.ts +3 -0
  18. package/lib/browser/memcmp.js +28 -1
  19. package/lib/browser/slot/SlothashSubscriber.d.ts +26 -0
  20. package/lib/browser/slot/SlothashSubscriber.js +85 -0
  21. package/lib/browser/types.d.ts +4 -3
  22. package/lib/browser/user.js +3 -0
  23. package/lib/browser/userMap/referrerMap.d.ts +45 -0
  24. package/lib/browser/userMap/referrerMap.js +180 -0
  25. package/lib/browser/util/digest.d.ts +1 -0
  26. package/lib/browser/util/digest.js +5 -1
  27. package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
  28. package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
  29. package/lib/node/accounts/types.d.ts +14 -1
  30. package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
  31. package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
  32. package/lib/node/addresses/pda.d.ts +1 -0
  33. package/lib/node/addresses/pda.js +8 -1
  34. package/lib/node/constants/perpMarkets.js +11 -0
  35. package/lib/node/constants/spotMarkets.js +2 -2
  36. package/lib/node/driftClient.d.ts +14 -4
  37. package/lib/node/driftClient.js +64 -19
  38. package/lib/node/idl/drift.json +199 -8
  39. package/lib/node/index.d.ts +4 -0
  40. package/lib/node/index.js +4 -0
  41. package/lib/node/jupiter/jupiterClient.d.ts +6 -0
  42. package/lib/node/memcmp.d.ts +3 -0
  43. package/lib/node/memcmp.js +28 -1
  44. package/lib/node/slot/SlothashSubscriber.d.ts +26 -0
  45. package/lib/node/slot/SlothashSubscriber.js +85 -0
  46. package/lib/node/types.d.ts +4 -3
  47. package/lib/node/user.js +3 -0
  48. package/lib/node/userMap/referrerMap.d.ts +45 -0
  49. package/lib/node/userMap/referrerMap.js +180 -0
  50. package/lib/node/util/digest.d.ts +1 -0
  51. package/lib/node/util/digest.js +5 -1
  52. package/package.json +1 -1
  53. package/src/accounts/pollingHighLeverageModeConfigAccountSubscriber.ts +189 -0
  54. package/src/accounts/types.ts +25 -1
  55. package/src/accounts/webSocketHighLeverageModeConfigAccountSubscriber.ts +131 -0
  56. package/src/addresses/pda.ts +13 -0
  57. package/src/constants/perpMarkets.ts +12 -0
  58. package/src/constants/spotMarkets.ts +2 -2
  59. package/src/driftClient.ts +129 -36
  60. package/src/idl/drift.json +226 -9
  61. package/src/index.ts +4 -0
  62. package/src/jupiter/jupiterClient.ts +6 -0
  63. package/src/memcmp.ts +27 -0
  64. package/src/slot/SlothashSubscriber.ts +126 -0
  65. package/src/types.ts +4 -3
  66. package/src/user.ts +4 -0
  67. package/src/userMap/referrerMap.ts +283 -0
  68. package/src/util/digest.ts +4 -0
  69. package/tests/ci/verifyConstants.ts +16 -2
@@ -0,0 +1,283 @@
1
+ import {
2
+ MemcmpFilter,
3
+ PublicKey,
4
+ RpcResponseAndContext,
5
+ } from '@solana/web3.js';
6
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
7
+ import { DriftClient } from '../driftClient';
8
+ import { ReferrerInfo } from '../types';
9
+ import {
10
+ getUserAccountPublicKeySync,
11
+ getUserStatsAccountPublicKey,
12
+ } from '../addresses/pda';
13
+ import {
14
+ getUserStatsFilter,
15
+ getUserStatsIsReferredFilter,
16
+ getUserStatsIsReferredOrReferrerFilter,
17
+ } from '../memcmp';
18
+ import { bs58 } from '@coral-xyz/anchor/dist/cjs/utils/bytes';
19
+
20
+ const DEFAULT_PUBLIC_KEY = PublicKey.default.toBase58();
21
+
22
+ export class ReferrerMap {
23
+ /**
24
+ * map from authority pubkey to ReferrerInfo.
25
+ * - if a user has not been entered into the map, the value is undefined
26
+ * - if a user has no referrer, the value is null
27
+ * - if a user has a referrer, the value is a ReferrerInfo object
28
+ */
29
+ private referrerMap = new Map<string, ReferrerInfo | null>();
30
+ private driftClient: DriftClient;
31
+ private bulkAccountLoader: BulkAccountLoader;
32
+ private parallelSync: boolean;
33
+
34
+ private fetchPromise?: Promise<void>;
35
+ private fetchPromiseResolver: () => void;
36
+
37
+ /**
38
+ * Creates a new UserStatsMap instance.
39
+ *
40
+ * @param {DriftClient} driftClient - The DriftClient instance.
41
+ * @param {BulkAccountLoader} [bulkAccountLoader] - If not provided, a new BulkAccountLoader with polling disabled will be created.
42
+ */
43
+ constructor(
44
+ driftClient: DriftClient,
45
+ bulkAccountLoader?: BulkAccountLoader,
46
+ parallelSync?: boolean
47
+ ) {
48
+ this.driftClient = driftClient;
49
+ if (!bulkAccountLoader) {
50
+ bulkAccountLoader = new BulkAccountLoader(
51
+ driftClient.connection,
52
+ driftClient.opts.commitment,
53
+ 0
54
+ );
55
+ }
56
+ this.bulkAccountLoader = bulkAccountLoader;
57
+ this.parallelSync = parallelSync !== undefined ? parallelSync : true;
58
+ }
59
+
60
+ /**
61
+ * Subscribe to all UserStats accounts.
62
+ */
63
+ public async subscribe() {
64
+ if (this.size() > 0) {
65
+ return;
66
+ }
67
+
68
+ await this.driftClient.subscribe();
69
+ await this.sync();
70
+ }
71
+
72
+ public has(authorityPublicKey: string): boolean {
73
+ return this.referrerMap.has(authorityPublicKey);
74
+ }
75
+
76
+ public get(authorityPublicKey: string): ReferrerInfo | undefined {
77
+ const info = this.referrerMap.get(authorityPublicKey);
78
+ return info === null ? undefined : info;
79
+ }
80
+
81
+ public async addReferrerInfo(
82
+ authority: string,
83
+ referrerInfo?: ReferrerInfo | null
84
+ ) {
85
+ if (referrerInfo || referrerInfo === null) {
86
+ this.referrerMap.set(authority, referrerInfo);
87
+ } else if (referrerInfo === undefined) {
88
+ const userStatsAccountPublicKey = getUserStatsAccountPublicKey(
89
+ this.driftClient.program.programId,
90
+ new PublicKey(authority)
91
+ );
92
+ const buffer = (
93
+ await this.driftClient.connection.getAccountInfo(
94
+ userStatsAccountPublicKey,
95
+ 'processed'
96
+ )
97
+ ).data;
98
+
99
+ const referrer = bs58.encode(buffer.subarray(40, 72));
100
+
101
+ const referrerKey = new PublicKey(referrer);
102
+ this.addReferrerInfo(
103
+ authority,
104
+ referrer === DEFAULT_PUBLIC_KEY
105
+ ? null
106
+ : {
107
+ referrer: getUserAccountPublicKeySync(
108
+ this.driftClient.program.programId,
109
+ referrerKey,
110
+ 0
111
+ ),
112
+ referrerStats: getUserStatsAccountPublicKey(
113
+ this.driftClient.program.programId,
114
+ referrerKey
115
+ ),
116
+ }
117
+ );
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Enforce that a UserStats will exist for the given authorityPublicKey,
123
+ * reading one from the blockchain if necessary.
124
+ * @param authorityPublicKey
125
+ * @returns
126
+ */
127
+ public async mustGet(
128
+ authorityPublicKey: string
129
+ ): Promise<ReferrerInfo | undefined> {
130
+ if (!this.has(authorityPublicKey)) {
131
+ await this.addReferrerInfo(authorityPublicKey);
132
+ }
133
+ return this.get(authorityPublicKey);
134
+ }
135
+
136
+ public values(): IterableIterator<ReferrerInfo | null> {
137
+ return this.referrerMap.values();
138
+ }
139
+
140
+ public size(): number {
141
+ return this.referrerMap.size;
142
+ }
143
+
144
+ public async sync(): Promise<void> {
145
+ if (this.fetchPromise) {
146
+ return this.fetchPromise;
147
+ }
148
+
149
+ this.fetchPromise = new Promise((resolver) => {
150
+ this.fetchPromiseResolver = resolver;
151
+ });
152
+
153
+ try {
154
+ if (this.parallelSync) {
155
+ await Promise.all([
156
+ this.syncAll(),
157
+ this.syncReferrer(getUserStatsIsReferredFilter()),
158
+ this.syncReferrer(getUserStatsIsReferredOrReferrerFilter()),
159
+ ]);
160
+ } else {
161
+ await this.syncAll();
162
+ await this.syncReferrer(getUserStatsIsReferredFilter());
163
+ await this.syncReferrer(getUserStatsIsReferredOrReferrerFilter());
164
+ }
165
+ } catch (e) {
166
+ console.error('error in referrerMap.sync', e);
167
+ } finally {
168
+ this.fetchPromiseResolver();
169
+ this.fetchPromise = undefined;
170
+ }
171
+ }
172
+
173
+ public async syncAll(): Promise<void> {
174
+ const rpcRequestArgs = [
175
+ this.driftClient.program.programId.toBase58(),
176
+ {
177
+ commitment: this.driftClient.opts.commitment,
178
+ filters: [getUserStatsFilter()],
179
+ encoding: 'base64',
180
+ dataSlice: {
181
+ offset: 0,
182
+ length: 0,
183
+ },
184
+ withContext: true,
185
+ },
186
+ ];
187
+
188
+ const rpcJSONResponse: any =
189
+ // @ts-ignore
190
+ await this.driftClient.connection._rpcRequest(
191
+ 'getProgramAccounts',
192
+ rpcRequestArgs
193
+ );
194
+
195
+ const rpcResponseAndContext: RpcResponseAndContext<
196
+ Array<{
197
+ pubkey: string;
198
+ account: {
199
+ data: [string, string];
200
+ };
201
+ }>
202
+ > = rpcJSONResponse.result;
203
+
204
+ for (const account of rpcResponseAndContext.value) {
205
+ // only add if it isn't already in the map
206
+ // so that if syncReferrer already set it, we dont overwrite
207
+ if (!this.has(account.pubkey)) {
208
+ this.addReferrerInfo(account.pubkey, null);
209
+ }
210
+ }
211
+ }
212
+
213
+ async syncReferrer(referrerFilter: MemcmpFilter): Promise<void> {
214
+ const rpcRequestArgs = [
215
+ this.driftClient.program.programId.toBase58(),
216
+ {
217
+ commitment: this.driftClient.opts.commitment,
218
+ filters: [getUserStatsFilter(), referrerFilter],
219
+ encoding: 'base64',
220
+ dataSlice: {
221
+ offset: 0,
222
+ length: 72,
223
+ },
224
+ withContext: true,
225
+ },
226
+ ];
227
+
228
+ const rpcJSONResponse: any =
229
+ // @ts-ignore
230
+ await this.driftClient.connection._rpcRequest(
231
+ 'getProgramAccounts',
232
+ rpcRequestArgs
233
+ );
234
+
235
+ const rpcResponseAndContext: RpcResponseAndContext<
236
+ Array<{
237
+ pubkey: string;
238
+ account: {
239
+ data: [string, string];
240
+ };
241
+ }>
242
+ > = rpcJSONResponse.result;
243
+
244
+ const batchSize = 1000;
245
+ for (let i = 0; i < rpcResponseAndContext.value.length; i += batchSize) {
246
+ const batch = rpcResponseAndContext.value.slice(i, i + batchSize);
247
+ await Promise.all(
248
+ batch.map(async (programAccount) => {
249
+ // @ts-ignore
250
+ const buffer = Buffer.from(
251
+ programAccount.account.data[0],
252
+ programAccount.account.data[1]
253
+ );
254
+ const authority = bs58.encode(buffer.subarray(8, 40));
255
+ const referrer = bs58.encode(buffer.subarray(40, 72));
256
+
257
+ const referrerKey = new PublicKey(referrer);
258
+ this.addReferrerInfo(
259
+ authority,
260
+ referrer === DEFAULT_PUBLIC_KEY
261
+ ? null
262
+ : {
263
+ referrer: getUserAccountPublicKeySync(
264
+ this.driftClient.program.programId,
265
+ referrerKey,
266
+ 0
267
+ ),
268
+ referrerStats: getUserStatsAccountPublicKey(
269
+ this.driftClient.program.programId,
270
+ referrerKey
271
+ ),
272
+ }
273
+ );
274
+ })
275
+ );
276
+ await new Promise((resolve) => setTimeout(resolve, 0));
277
+ }
278
+ }
279
+
280
+ public async unsubscribe() {
281
+ this.referrerMap.clear();
282
+ }
283
+ }
@@ -5,3 +5,7 @@ export function digest(data: Buffer): Buffer {
5
5
  hash.update(data);
6
6
  return hash.digest();
7
7
  }
8
+
9
+ export function digestSignature(signature: Uint8Array): string {
10
+ return createHash('sha256').update(signature).digest('base64');
11
+ }
@@ -130,7 +130,14 @@ describe('Verify Constants', function () {
130
130
  } oracle ${market.oracle.toBase58()}`
131
131
  );
132
132
 
133
- if (isOneOfVariant(market.oracleSource, ['pythPull', 'pyth1KPull', 'pyth1MPull', 'pythStableCoinPull'])) {
133
+ if (
134
+ isOneOfVariant(market.oracleSource, [
135
+ 'pythPull',
136
+ 'pyth1KPull',
137
+ 'pyth1MPull',
138
+ 'pythStableCoinPull',
139
+ ])
140
+ ) {
134
141
  if (!correspondingConfigMarket.pythFeedId) {
135
142
  assert(false, `spot market ${market.marketIndex} missing feed id`);
136
143
  }
@@ -185,7 +192,14 @@ describe('Verify Constants', function () {
185
192
  } oracle ${market.amm.oracle.toBase58()}`
186
193
  );
187
194
 
188
- if (isOneOfVariant(market.amm.oracleSource, ['pythPull', 'pyth1KPull', 'pyth1MPull', 'pythStableCoinPull'])) {
195
+ if (
196
+ isOneOfVariant(market.amm.oracleSource, [
197
+ 'pythPull',
198
+ 'pyth1KPull',
199
+ 'pyth1MPull',
200
+ 'pythStableCoinPull',
201
+ ])
202
+ ) {
189
203
  if (!correspondingConfigMarket.pythFeedId) {
190
204
  assert(false, `perp market ${market.marketIndex} missing feed id`);
191
205
  }