@drift-labs/sdk 2.66.0-beta.1 → 2.66.0-beta.3
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/oneShotUserAccountSubscriber.d.ts +2 -1
- package/lib/userMap/PollingSubscription.d.ts +2 -1
- package/lib/userMap/PollingSubscription.js +6 -4
- package/lib/userMap/userMap.js +33 -29
- package/package.json +1 -1
- package/src/accounts/oneShotUserAccountSubscriber.ts +5 -1
- package/src/userMap/PollingSubscription.ts +7 -8
- package/src/userMap/userMap.ts +44 -41
- package/tests/amm/test.ts +22 -3
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.66.0-beta.
|
|
1
|
+
2.66.0-beta.3
|
|
@@ -2,12 +2,13 @@ import { Commitment, PublicKey } from '@solana/web3.js';
|
|
|
2
2
|
import { UserAccount } from '../types';
|
|
3
3
|
import { BasicUserAccountSubscriber } from './basicUserAccountSubscriber';
|
|
4
4
|
import { Program } from '@coral-xyz/anchor';
|
|
5
|
+
import { UserAccountSubscriber } from './types';
|
|
5
6
|
/**
|
|
6
7
|
* Simple implementation of UserAccountSubscriber. It will fetch the UserAccount
|
|
7
8
|
* date on subscribe (or call to fetch) if no account data is provided on init.
|
|
8
9
|
* Expect to use only 1 RPC call unless you call fetch repeatedly.
|
|
9
10
|
*/
|
|
10
|
-
export declare class OneShotUserAccountSubscriber extends BasicUserAccountSubscriber {
|
|
11
|
+
export declare class OneShotUserAccountSubscriber extends BasicUserAccountSubscriber implements UserAccountSubscriber {
|
|
11
12
|
program: Program;
|
|
12
13
|
commitment: Commitment;
|
|
13
14
|
constructor(program: Program, userAccountPublicKey: PublicKey, data?: UserAccount, slot?: number, commitment?: Commitment);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
1
2
|
import { UserMap } from './userMap';
|
|
2
3
|
export declare class PollingSubscription {
|
|
3
4
|
private userMap;
|
|
4
5
|
private frequency;
|
|
5
6
|
private skipInitialLoad;
|
|
6
|
-
intervalId?:
|
|
7
|
+
intervalId?: NodeJS.Timeout;
|
|
7
8
|
constructor({ userMap, frequency, skipInitialLoad, }: {
|
|
8
9
|
userMap: UserMap;
|
|
9
10
|
frequency: number;
|
|
@@ -8,15 +8,17 @@ class PollingSubscription {
|
|
|
8
8
|
this.skipInitialLoad = skipInitialLoad;
|
|
9
9
|
}
|
|
10
10
|
async subscribe() {
|
|
11
|
-
if (this.intervalId) {
|
|
11
|
+
if (this.intervalId || this.frequency <= 0) {
|
|
12
12
|
return;
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
const executeSync = async () => {
|
|
15
|
+
await this.userMap.sync();
|
|
16
|
+
this.intervalId = setTimeout(executeSync, this.frequency);
|
|
17
|
+
};
|
|
17
18
|
if (!this.skipInitialLoad) {
|
|
18
19
|
await this.userMap.sync();
|
|
19
20
|
}
|
|
21
|
+
executeSync();
|
|
20
22
|
}
|
|
21
23
|
async unsubscribe() {
|
|
22
24
|
if (this.intervalId) {
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -225,6 +225,7 @@ class UserMap {
|
|
|
225
225
|
return userAuthKeys;
|
|
226
226
|
}
|
|
227
227
|
async sync() {
|
|
228
|
+
var _a;
|
|
228
229
|
if (this.syncPromise) {
|
|
229
230
|
return this.syncPromise;
|
|
230
231
|
}
|
|
@@ -245,43 +246,44 @@ class UserMap {
|
|
|
245
246
|
withContext: true,
|
|
246
247
|
},
|
|
247
248
|
];
|
|
248
|
-
const rpcJSONResponse =
|
|
249
249
|
// @ts-ignore
|
|
250
|
-
await this.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
|
|
250
|
+
const rpcJSONResponse = await this.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
|
|
251
251
|
const rpcResponseAndContext = rpcJSONResponse.result;
|
|
252
252
|
const slot = rpcResponseAndContext.context.slot;
|
|
253
253
|
this.updateLatestSlot(slot);
|
|
254
254
|
const programAccountBufferMap = new Map();
|
|
255
|
-
|
|
255
|
+
rpcResponseAndContext.value.forEach((programAccount) => {
|
|
256
256
|
programAccountBufferMap.set(programAccount.pubkey.toString(),
|
|
257
257
|
// @ts-ignore
|
|
258
258
|
buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]));
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
259
|
+
});
|
|
260
|
+
const promises = Array.from(programAccountBufferMap.entries()).map(([key, buffer]) => (async () => {
|
|
261
|
+
const currAccountWithSlot = this.getWithSlot(key);
|
|
262
|
+
if (currAccountWithSlot) {
|
|
263
|
+
if (slot >= currAccountWithSlot.slot) {
|
|
264
|
+
const userAccount = this.decode('User', buffer);
|
|
265
|
+
this.updateUserAccount(key, userAccount, slot);
|
|
266
|
+
}
|
|
265
267
|
}
|
|
266
268
|
else {
|
|
267
269
|
const userAccount = this.decode('User', buffer);
|
|
268
|
-
this.
|
|
270
|
+
await this.addPubkey(new web3_js_1.PublicKey(key), userAccount, slot);
|
|
269
271
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
for (const [key, user] of this.entries()) {
|
|
272
|
+
})());
|
|
273
|
+
await Promise.all(promises);
|
|
274
|
+
for (const [key] of this.entries()) {
|
|
274
275
|
if (!programAccountBufferMap.has(key)) {
|
|
275
|
-
|
|
276
|
-
|
|
276
|
+
const user = this.get(key);
|
|
277
|
+
if (user) {
|
|
278
|
+
await user.unsubscribe();
|
|
279
|
+
this.userMap.delete(key);
|
|
280
|
+
}
|
|
277
281
|
}
|
|
278
|
-
// give event loop a chance to breathe
|
|
279
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
280
282
|
}
|
|
281
283
|
}
|
|
282
|
-
catch (
|
|
283
|
-
|
|
284
|
-
console.error(e);
|
|
284
|
+
catch (err) {
|
|
285
|
+
const e = err;
|
|
286
|
+
console.error(`Error in UserMap.sync(): ${e.message} ${(_a = e.stack) !== null && _a !== void 0 ? _a : ''}`);
|
|
285
287
|
}
|
|
286
288
|
finally {
|
|
287
289
|
this.syncPromiseResolver();
|
|
@@ -302,17 +304,19 @@ class UserMap {
|
|
|
302
304
|
}
|
|
303
305
|
}
|
|
304
306
|
async updateUserAccount(key, userAccount, slot) {
|
|
307
|
+
const userWithSlot = this.getWithSlot(key);
|
|
305
308
|
this.updateLatestSlot(slot);
|
|
306
|
-
if (
|
|
307
|
-
|
|
309
|
+
if (userWithSlot) {
|
|
310
|
+
if (slot >= userWithSlot.slot) {
|
|
311
|
+
userWithSlot.data.accountSubscriber.updateData(userAccount, slot);
|
|
312
|
+
this.userMap.set(key, {
|
|
313
|
+
data: userWithSlot.data,
|
|
314
|
+
slot,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
308
317
|
}
|
|
309
318
|
else {
|
|
310
|
-
|
|
311
|
-
user.accountSubscriber.updateData(userAccount, slot);
|
|
312
|
-
this.userMap.set(key, {
|
|
313
|
-
data: user,
|
|
314
|
-
slot,
|
|
315
|
-
});
|
|
319
|
+
this.addPubkey(new web3_js_1.PublicKey(key), userAccount, slot);
|
|
316
320
|
}
|
|
317
321
|
}
|
|
318
322
|
updateLatestSlot(slot) {
|
package/package.json
CHANGED
|
@@ -2,13 +2,17 @@ import { Commitment, PublicKey } from '@solana/web3.js';
|
|
|
2
2
|
import { UserAccount } from '../types';
|
|
3
3
|
import { BasicUserAccountSubscriber } from './basicUserAccountSubscriber';
|
|
4
4
|
import { Program } from '@coral-xyz/anchor';
|
|
5
|
+
import { UserAccountSubscriber } from './types';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Simple implementation of UserAccountSubscriber. It will fetch the UserAccount
|
|
8
9
|
* date on subscribe (or call to fetch) if no account data is provided on init.
|
|
9
10
|
* Expect to use only 1 RPC call unless you call fetch repeatedly.
|
|
10
11
|
*/
|
|
11
|
-
export class OneShotUserAccountSubscriber
|
|
12
|
+
export class OneShotUserAccountSubscriber
|
|
13
|
+
extends BasicUserAccountSubscriber
|
|
14
|
+
implements UserAccountSubscriber
|
|
15
|
+
{
|
|
12
16
|
program: Program;
|
|
13
17
|
commitment: Commitment;
|
|
14
18
|
|
|
@@ -5,7 +5,7 @@ export class PollingSubscription {
|
|
|
5
5
|
private frequency: number;
|
|
6
6
|
private skipInitialLoad: boolean;
|
|
7
7
|
|
|
8
|
-
intervalId?:
|
|
8
|
+
intervalId?: NodeJS.Timeout;
|
|
9
9
|
|
|
10
10
|
constructor({
|
|
11
11
|
userMap,
|
|
@@ -23,20 +23,19 @@ export class PollingSubscription {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async subscribe(): Promise<void> {
|
|
26
|
-
if (this.intervalId) {
|
|
26
|
+
if (this.intervalId || this.frequency <= 0) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
this.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
35
|
-
}
|
|
30
|
+
const executeSync = async () => {
|
|
31
|
+
await this.userMap.sync();
|
|
32
|
+
this.intervalId = setTimeout(executeSync, this.frequency);
|
|
33
|
+
};
|
|
36
34
|
|
|
37
35
|
if (!this.skipInitialLoad) {
|
|
38
36
|
await this.userMap.sync();
|
|
39
37
|
}
|
|
38
|
+
executeSync();
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
public async unsubscribe(): Promise<void> {
|
package/src/userMap/userMap.ts
CHANGED
|
@@ -362,25 +362,20 @@ export class UserMap implements UserMapInterface {
|
|
|
362
362
|
},
|
|
363
363
|
];
|
|
364
364
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
365
|
+
// @ts-ignore
|
|
366
|
+
const rpcJSONResponse: any = await this.connection._rpcRequest(
|
|
367
|
+
'getProgramAccounts',
|
|
368
|
+
rpcRequestArgs
|
|
369
|
+
);
|
|
369
370
|
const rpcResponseAndContext: RpcResponseAndContext<
|
|
370
|
-
Array<{
|
|
371
|
-
pubkey: PublicKey;
|
|
372
|
-
account: {
|
|
373
|
-
data: [string, string];
|
|
374
|
-
};
|
|
375
|
-
}>
|
|
371
|
+
Array<{ pubkey: PublicKey; account: { data: [string, string] } }>
|
|
376
372
|
> = rpcJSONResponse.result;
|
|
377
|
-
|
|
378
373
|
const slot = rpcResponseAndContext.context.slot;
|
|
379
374
|
|
|
380
375
|
this.updateLatestSlot(slot);
|
|
381
376
|
|
|
382
377
|
const programAccountBufferMap = new Map<string, Buffer>();
|
|
383
|
-
|
|
378
|
+
rpcResponseAndContext.value.forEach((programAccount) => {
|
|
384
379
|
programAccountBufferMap.set(
|
|
385
380
|
programAccount.pubkey.toString(),
|
|
386
381
|
// @ts-ignore
|
|
@@ -389,32 +384,38 @@ export class UserMap implements UserMapInterface {
|
|
|
389
384
|
programAccount.account.data[1]
|
|
390
385
|
)
|
|
391
386
|
);
|
|
392
|
-
}
|
|
387
|
+
});
|
|
393
388
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
389
|
+
const promises = Array.from(programAccountBufferMap.entries()).map(
|
|
390
|
+
([key, buffer]) =>
|
|
391
|
+
(async () => {
|
|
392
|
+
const currAccountWithSlot = this.getWithSlot(key);
|
|
393
|
+
if (currAccountWithSlot) {
|
|
394
|
+
if (slot >= currAccountWithSlot.slot) {
|
|
395
|
+
const userAccount = this.decode('User', buffer);
|
|
396
|
+
this.updateUserAccount(key, userAccount, slot);
|
|
397
|
+
}
|
|
398
|
+
} else {
|
|
399
|
+
const userAccount = this.decode('User', buffer);
|
|
400
|
+
await this.addPubkey(new PublicKey(key), userAccount, slot);
|
|
401
|
+
}
|
|
402
|
+
})()
|
|
403
|
+
);
|
|
406
404
|
|
|
407
|
-
|
|
405
|
+
await Promise.all(promises);
|
|
406
|
+
|
|
407
|
+
for (const [key] of this.entries()) {
|
|
408
408
|
if (!programAccountBufferMap.has(key)) {
|
|
409
|
-
|
|
410
|
-
|
|
409
|
+
const user = this.get(key);
|
|
410
|
+
if (user) {
|
|
411
|
+
await user.unsubscribe();
|
|
412
|
+
this.userMap.delete(key);
|
|
413
|
+
}
|
|
411
414
|
}
|
|
412
|
-
// give event loop a chance to breathe
|
|
413
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
414
415
|
}
|
|
415
|
-
} catch (
|
|
416
|
-
|
|
417
|
-
console.error(e);
|
|
416
|
+
} catch (err) {
|
|
417
|
+
const e = err as Error;
|
|
418
|
+
console.error(`Error in UserMap.sync(): ${e.message} ${e.stack ?? ''}`);
|
|
418
419
|
} finally {
|
|
419
420
|
this.syncPromiseResolver();
|
|
420
421
|
this.syncPromise = undefined;
|
|
@@ -446,16 +447,18 @@ export class UserMap implements UserMapInterface {
|
|
|
446
447
|
userAccount: UserAccount,
|
|
447
448
|
slot: number
|
|
448
449
|
) {
|
|
450
|
+
const userWithSlot = this.getWithSlot(key);
|
|
449
451
|
this.updateLatestSlot(slot);
|
|
450
|
-
if (
|
|
451
|
-
|
|
452
|
+
if (userWithSlot) {
|
|
453
|
+
if (slot >= userWithSlot.slot) {
|
|
454
|
+
userWithSlot.data.accountSubscriber.updateData(userAccount, slot);
|
|
455
|
+
this.userMap.set(key, {
|
|
456
|
+
data: userWithSlot.data,
|
|
457
|
+
slot,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
452
460
|
} else {
|
|
453
|
-
|
|
454
|
-
user.accountSubscriber.updateData(userAccount, slot);
|
|
455
|
-
this.userMap.set(key, {
|
|
456
|
-
data: user,
|
|
457
|
-
slot,
|
|
458
|
-
});
|
|
461
|
+
this.addPubkey(new PublicKey(key), userAccount, slot);
|
|
459
462
|
}
|
|
460
463
|
}
|
|
461
464
|
|
package/tests/amm/test.ts
CHANGED
|
@@ -615,11 +615,11 @@ describe('AMM Tests', () => {
|
|
|
615
615
|
assert(termsSuiExample.effectiveLeverageCapped <= 1.000001);
|
|
616
616
|
assert(termsSuiExample.inventorySpreadScale == 1.00007);
|
|
617
617
|
assert(
|
|
618
|
-
termsSuiExample.longSpread ==
|
|
618
|
+
termsSuiExample.longSpread == 269818,
|
|
619
619
|
`SUI long spread got ${termsSuiExample.longSpread}`
|
|
620
620
|
);
|
|
621
621
|
assert(
|
|
622
|
-
termsSuiExample.shortSpread ==
|
|
622
|
+
termsSuiExample.shortSpread == 3920,
|
|
623
623
|
`SUI short spread got ${termsSuiExample.shortSpread}`
|
|
624
624
|
);
|
|
625
625
|
|
|
@@ -680,7 +680,26 @@ describe('AMM Tests', () => {
|
|
|
680
680
|
);
|
|
681
681
|
|
|
682
682
|
console.log(termsSuiExampleMod2);
|
|
683
|
-
|
|
683
|
+
assert(
|
|
684
|
+
_.isEqual(
|
|
685
|
+
termsSuiExampleMod2.maxTargetSpread,
|
|
686
|
+
termsSuiExampleMod1.maxTargetSpread
|
|
687
|
+
)
|
|
688
|
+
);
|
|
689
|
+
assert(
|
|
690
|
+
_.isEqual(
|
|
691
|
+
termsSuiExampleMod2.shortSpreadwPS,
|
|
692
|
+
termsSuiExampleMod1.shortSpreadwPS
|
|
693
|
+
)
|
|
694
|
+
);
|
|
695
|
+
assert(
|
|
696
|
+
_.isEqual(
|
|
697
|
+
termsSuiExampleMod2.longSpreadwPS,
|
|
698
|
+
termsSuiExampleMod1.longSpreadwPS
|
|
699
|
+
)
|
|
700
|
+
);
|
|
701
|
+
|
|
702
|
+
// note: effectiveLeverage as currently implemented is sensitive to peg change
|
|
684
703
|
});
|
|
685
704
|
|
|
686
705
|
it('Spread Reserves (with offset)', () => {
|