@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.
- package/VERSION +1 -1
- package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
- package/lib/browser/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
- package/lib/browser/accounts/types.d.ts +14 -1
- package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
- package/lib/browser/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
- package/lib/browser/addresses/pda.d.ts +1 -0
- package/lib/browser/addresses/pda.js +8 -1
- package/lib/browser/constants/perpMarkets.js +11 -0
- package/lib/browser/constants/spotMarkets.js +2 -2
- package/lib/browser/driftClient.d.ts +14 -4
- package/lib/browser/driftClient.js +64 -19
- package/lib/browser/idl/drift.json +199 -8
- package/lib/browser/index.d.ts +4 -0
- package/lib/browser/index.js +4 -0
- package/lib/browser/jupiter/jupiterClient.d.ts +6 -0
- package/lib/browser/memcmp.d.ts +3 -0
- package/lib/browser/memcmp.js +28 -1
- package/lib/browser/slot/SlothashSubscriber.d.ts +26 -0
- package/lib/browser/slot/SlothashSubscriber.js +85 -0
- package/lib/browser/types.d.ts +4 -3
- package/lib/browser/user.js +3 -0
- package/lib/browser/userMap/referrerMap.d.ts +45 -0
- package/lib/browser/userMap/referrerMap.js +180 -0
- package/lib/browser/util/digest.d.ts +1 -0
- package/lib/browser/util/digest.js +5 -1
- package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.d.ts +29 -0
- package/lib/node/accounts/pollingHighLeverageModeConfigAccountSubscriber.js +111 -0
- package/lib/node/accounts/types.d.ts +14 -1
- package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.d.ts +23 -0
- package/lib/node/accounts/webSocketHighLeverageModeConfigAccountSubscriber.js +69 -0
- package/lib/node/addresses/pda.d.ts +1 -0
- package/lib/node/addresses/pda.js +8 -1
- package/lib/node/constants/perpMarkets.js +11 -0
- package/lib/node/constants/spotMarkets.js +2 -2
- package/lib/node/driftClient.d.ts +14 -4
- package/lib/node/driftClient.js +64 -19
- package/lib/node/idl/drift.json +199 -8
- package/lib/node/index.d.ts +4 -0
- package/lib/node/index.js +4 -0
- package/lib/node/jupiter/jupiterClient.d.ts +6 -0
- package/lib/node/memcmp.d.ts +3 -0
- package/lib/node/memcmp.js +28 -1
- package/lib/node/slot/SlothashSubscriber.d.ts +26 -0
- package/lib/node/slot/SlothashSubscriber.js +85 -0
- package/lib/node/types.d.ts +4 -3
- package/lib/node/user.js +3 -0
- package/lib/node/userMap/referrerMap.d.ts +45 -0
- package/lib/node/userMap/referrerMap.js +180 -0
- package/lib/node/util/digest.d.ts +1 -0
- package/lib/node/util/digest.js +5 -1
- package/package.json +1 -1
- package/src/accounts/pollingHighLeverageModeConfigAccountSubscriber.ts +189 -0
- package/src/accounts/types.ts +25 -1
- package/src/accounts/webSocketHighLeverageModeConfigAccountSubscriber.ts +131 -0
- package/src/addresses/pda.ts +13 -0
- package/src/constants/perpMarkets.ts +12 -0
- package/src/constants/spotMarkets.ts +2 -2
- package/src/driftClient.ts +129 -36
- package/src/idl/drift.json +226 -9
- package/src/index.ts +4 -0
- package/src/jupiter/jupiterClient.ts +6 -0
- package/src/memcmp.ts +27 -0
- package/src/slot/SlothashSubscriber.ts +126 -0
- package/src/types.ts +4 -3
- package/src/user.ts +4 -0
- package/src/userMap/referrerMap.ts +283 -0
- package/src/util/digest.ts +4 -0
- 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
|
+
}
|
package/src/util/digest.ts
CHANGED
|
@@ -130,7 +130,14 @@ describe('Verify Constants', function () {
|
|
|
130
130
|
} oracle ${market.oracle.toBase58()}`
|
|
131
131
|
);
|
|
132
132
|
|
|
133
|
-
if (
|
|
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 (
|
|
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
|
}
|