@drift-labs/sdk 2.82.0-beta.16 → 2.82.0-beta.18
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/clock/clockSubscriber.d.ts +29 -0
- package/lib/clock/clockSubscriber.js +74 -0
- package/lib/constants/spotMarkets.js +10 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +1 -1
- package/src/clock/clockSubscriber.ts +113 -0
- package/src/constants/spotMarkets.ts +10 -0
- package/src/index.ts +1 -0
- package/tests/dlob/helpers.ts +3 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.82.0-beta.
|
|
1
|
+
2.82.0-beta.18
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { Commitment, Connection } from '@solana/web3.js';
|
|
3
|
+
import { EventEmitter } from 'events';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types/types/src';
|
|
5
|
+
type ClockSubscriberConfig = {
|
|
6
|
+
commitment: Commitment;
|
|
7
|
+
resubTimeoutMs?: number;
|
|
8
|
+
};
|
|
9
|
+
export interface ClockSubscriberEvent {
|
|
10
|
+
clockUpdate: (ts: number) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare class ClockSubscriber {
|
|
13
|
+
private connection;
|
|
14
|
+
private latestSlot;
|
|
15
|
+
currentTs: number;
|
|
16
|
+
private subscriptionId;
|
|
17
|
+
commitment: Commitment;
|
|
18
|
+
eventEmitter: StrictEventEmitter<EventEmitter, ClockSubscriberEvent>;
|
|
19
|
+
private timeoutId?;
|
|
20
|
+
private resubTimeoutMs?;
|
|
21
|
+
private isUnsubscribing;
|
|
22
|
+
private receivingData;
|
|
23
|
+
constructor(connection: Connection, config?: ClockSubscriberConfig);
|
|
24
|
+
subscribe(): Promise<void>;
|
|
25
|
+
private setTimeout;
|
|
26
|
+
getUnixTs(): number;
|
|
27
|
+
unsubscribe(onResub?: boolean): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ClockSubscriber = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
const __1 = require("..");
|
|
7
|
+
class ClockSubscriber {
|
|
8
|
+
constructor(connection, config) {
|
|
9
|
+
this.connection = connection;
|
|
10
|
+
this.isUnsubscribing = false;
|
|
11
|
+
this.receivingData = false;
|
|
12
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
13
|
+
this.resubTimeoutMs = config === null || config === void 0 ? void 0 : config.resubTimeoutMs;
|
|
14
|
+
this.commitment = (config === null || config === void 0 ? void 0 : config.commitment) || 'confirmed';
|
|
15
|
+
if (this.resubTimeoutMs < 1000) {
|
|
16
|
+
console.log('resubTimeoutMs should be at least 1000ms to avoid spamming resub');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async subscribe() {
|
|
20
|
+
if (this.subscriptionId != null) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
this.subscriptionId = this.connection.onAccountChange(web3_js_1.SYSVAR_CLOCK_PUBKEY, (acctInfo, context) => {
|
|
24
|
+
if (!this.latestSlot || this.latestSlot < context.slot) {
|
|
25
|
+
if (this.resubTimeoutMs && !this.isUnsubscribing) {
|
|
26
|
+
this.receivingData = true;
|
|
27
|
+
clearTimeout(this.timeoutId);
|
|
28
|
+
this.setTimeout();
|
|
29
|
+
}
|
|
30
|
+
this.latestSlot = context.slot;
|
|
31
|
+
this.currentTs = new __1.BN(acctInfo.data.subarray(32, 39), undefined, 'le').toNumber();
|
|
32
|
+
this.eventEmitter.emit('clockUpdate', this.currentTs);
|
|
33
|
+
}
|
|
34
|
+
}, this.commitment);
|
|
35
|
+
if (this.resubTimeoutMs) {
|
|
36
|
+
this.receivingData = true;
|
|
37
|
+
this.setTimeout();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
setTimeout() {
|
|
41
|
+
this.timeoutId = setTimeout(async () => {
|
|
42
|
+
if (this.isUnsubscribing) {
|
|
43
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (this.receivingData) {
|
|
47
|
+
console.log(`No new slot in ${this.resubTimeoutMs}ms, slot subscriber resubscribing`);
|
|
48
|
+
await this.unsubscribe(true);
|
|
49
|
+
this.receivingData = false;
|
|
50
|
+
await this.subscribe();
|
|
51
|
+
}
|
|
52
|
+
}, this.resubTimeoutMs);
|
|
53
|
+
}
|
|
54
|
+
getUnixTs() {
|
|
55
|
+
return this.currentTs;
|
|
56
|
+
}
|
|
57
|
+
async unsubscribe(onResub = false) {
|
|
58
|
+
if (!onResub) {
|
|
59
|
+
this.resubTimeoutMs = undefined;
|
|
60
|
+
}
|
|
61
|
+
this.isUnsubscribing = true;
|
|
62
|
+
clearTimeout(this.timeoutId);
|
|
63
|
+
this.timeoutId = undefined;
|
|
64
|
+
if (this.subscriptionId != null) {
|
|
65
|
+
await this.connection.removeAccountChangeListener(this.subscriptionId);
|
|
66
|
+
this.subscriptionId = undefined;
|
|
67
|
+
this.isUnsubscribing = false;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
this.isUnsubscribing = false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.ClockSubscriber = ClockSubscriber;
|
|
@@ -197,6 +197,16 @@ exports.MainnetSpotMarkets = [
|
|
|
197
197
|
phoenixMarket: new web3_js_1.PublicKey('AbJCZ9TAJiby5AY3cHcXS2gUdENC6mtsm6m7XpC2ZMvE'),
|
|
198
198
|
launchTs: 1712593532000,
|
|
199
199
|
},
|
|
200
|
+
{
|
|
201
|
+
symbol: 'DRIFT',
|
|
202
|
+
marketIndex: 15,
|
|
203
|
+
oracle: new web3_js_1.PublicKey('PeNpQeGEm9UEFJ6MBCMauY4WW4h3YxoESPWbsqVKucE'),
|
|
204
|
+
oracleSource: __1.OracleSource.SWITCHBOARD,
|
|
205
|
+
mint: new web3_js_1.PublicKey('DriFtupJYLTosbwoN8koMbEYSx54aFAVLddWsbksjwg7'),
|
|
206
|
+
precision: new __1.BN(10).pow(numericConstants_1.SIX),
|
|
207
|
+
precisionExp: numericConstants_1.SIX,
|
|
208
|
+
launchTs: 1715860800000,
|
|
209
|
+
},
|
|
200
210
|
];
|
|
201
211
|
exports.SpotMarkets = {
|
|
202
212
|
devnet: exports.DevnetSpotMarkets,
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -124,3 +124,4 @@ __exportStar(require("./auctionSubscriber/types"), exports);
|
|
|
124
124
|
__exportStar(require("./memcmp"), exports);
|
|
125
125
|
__exportStar(require("./decode/user"), exports);
|
|
126
126
|
__exportStar(require("./blockhashSubscriber"), exports);
|
|
127
|
+
__exportStar(require("./clock/clockSubscriber"), exports);
|
package/package.json
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Commitment, Connection, SYSVAR_CLOCK_PUBKEY } from '@solana/web3.js';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import StrictEventEmitter from 'strict-event-emitter-types/types/src';
|
|
4
|
+
import { BN } from '..';
|
|
5
|
+
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
7
|
+
type ClockSubscriberConfig = {
|
|
8
|
+
commitment: Commitment;
|
|
9
|
+
resubTimeoutMs?: number;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export interface ClockSubscriberEvent {
|
|
13
|
+
clockUpdate: (ts: number) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ClockSubscriber {
|
|
17
|
+
private latestSlot: number;
|
|
18
|
+
currentTs: number;
|
|
19
|
+
private subscriptionId: number;
|
|
20
|
+
commitment: Commitment;
|
|
21
|
+
eventEmitter: StrictEventEmitter<EventEmitter, ClockSubscriberEvent>;
|
|
22
|
+
|
|
23
|
+
// Reconnection
|
|
24
|
+
private timeoutId?: NodeJS.Timeout;
|
|
25
|
+
private resubTimeoutMs?: number;
|
|
26
|
+
private isUnsubscribing = false;
|
|
27
|
+
private receivingData = false;
|
|
28
|
+
|
|
29
|
+
public constructor(
|
|
30
|
+
private connection: Connection,
|
|
31
|
+
config?: ClockSubscriberConfig
|
|
32
|
+
) {
|
|
33
|
+
this.eventEmitter = new EventEmitter();
|
|
34
|
+
this.resubTimeoutMs = config?.resubTimeoutMs;
|
|
35
|
+
this.commitment = config?.commitment || 'confirmed';
|
|
36
|
+
if (this.resubTimeoutMs < 1000) {
|
|
37
|
+
console.log(
|
|
38
|
+
'resubTimeoutMs should be at least 1000ms to avoid spamming resub'
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async subscribe(): Promise<void> {
|
|
44
|
+
if (this.subscriptionId != null) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.subscriptionId = this.connection.onAccountChange(
|
|
49
|
+
SYSVAR_CLOCK_PUBKEY,
|
|
50
|
+
(acctInfo, context) => {
|
|
51
|
+
if (!this.latestSlot || this.latestSlot < context.slot) {
|
|
52
|
+
if (this.resubTimeoutMs && !this.isUnsubscribing) {
|
|
53
|
+
this.receivingData = true;
|
|
54
|
+
clearTimeout(this.timeoutId);
|
|
55
|
+
this.setTimeout();
|
|
56
|
+
}
|
|
57
|
+
this.latestSlot = context.slot;
|
|
58
|
+
this.currentTs = new BN(
|
|
59
|
+
acctInfo.data.subarray(32, 39),
|
|
60
|
+
undefined,
|
|
61
|
+
'le'
|
|
62
|
+
).toNumber();
|
|
63
|
+
this.eventEmitter.emit('clockUpdate', this.currentTs);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
this.commitment
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (this.resubTimeoutMs) {
|
|
70
|
+
this.receivingData = true;
|
|
71
|
+
this.setTimeout();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private setTimeout(): void {
|
|
76
|
+
this.timeoutId = setTimeout(async () => {
|
|
77
|
+
if (this.isUnsubscribing) {
|
|
78
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (this.receivingData) {
|
|
83
|
+
console.log(
|
|
84
|
+
`No new slot in ${this.resubTimeoutMs}ms, slot subscriber resubscribing`
|
|
85
|
+
);
|
|
86
|
+
await this.unsubscribe(true);
|
|
87
|
+
this.receivingData = false;
|
|
88
|
+
await this.subscribe();
|
|
89
|
+
}
|
|
90
|
+
}, this.resubTimeoutMs);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
public getUnixTs(): number {
|
|
94
|
+
return this.currentTs;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
public async unsubscribe(onResub = false): Promise<void> {
|
|
98
|
+
if (!onResub) {
|
|
99
|
+
this.resubTimeoutMs = undefined;
|
|
100
|
+
}
|
|
101
|
+
this.isUnsubscribing = true;
|
|
102
|
+
clearTimeout(this.timeoutId);
|
|
103
|
+
this.timeoutId = undefined;
|
|
104
|
+
|
|
105
|
+
if (this.subscriptionId != null) {
|
|
106
|
+
await this.connection.removeAccountChangeListener(this.subscriptionId);
|
|
107
|
+
this.subscriptionId = undefined;
|
|
108
|
+
this.isUnsubscribing = false;
|
|
109
|
+
} else {
|
|
110
|
+
this.isUnsubscribing = false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -240,6 +240,16 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
|
|
|
240
240
|
),
|
|
241
241
|
launchTs: 1712593532000,
|
|
242
242
|
},
|
|
243
|
+
{
|
|
244
|
+
symbol: 'DRIFT',
|
|
245
|
+
marketIndex: 15,
|
|
246
|
+
oracle: new PublicKey('PeNpQeGEm9UEFJ6MBCMauY4WW4h3YxoESPWbsqVKucE'),
|
|
247
|
+
oracleSource: OracleSource.SWITCHBOARD,
|
|
248
|
+
mint: new PublicKey('DriFtupJYLTosbwoN8koMbEYSx54aFAVLddWsbksjwg7'),
|
|
249
|
+
precision: new BN(10).pow(SIX),
|
|
250
|
+
precisionExp: SIX,
|
|
251
|
+
launchTs: 1715860800000,
|
|
252
|
+
},
|
|
243
253
|
];
|
|
244
254
|
|
|
245
255
|
export const SpotMarkets: { [key in DriftEnv]: SpotMarketConfig[] } = {
|
package/src/index.ts
CHANGED
package/tests/dlob/helpers.ts
CHANGED
|
@@ -350,6 +350,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
|
|
|
350
350
|
lastIndexPriceTwapTs: new BN(0),
|
|
351
351
|
},
|
|
352
352
|
pausedOperations: 0,
|
|
353
|
+
ifPausedOperations: 0,
|
|
353
354
|
},
|
|
354
355
|
{
|
|
355
356
|
status: MarketStatus.ACTIVE,
|
|
@@ -432,6 +433,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
|
|
|
432
433
|
lastIndexPriceTwapTs: new BN(0),
|
|
433
434
|
},
|
|
434
435
|
pausedOperations: 0,
|
|
436
|
+
ifPausedOperations: 0,
|
|
435
437
|
},
|
|
436
438
|
{
|
|
437
439
|
status: MarketStatus.ACTIVE,
|
|
@@ -514,6 +516,7 @@ export const mockSpotMarkets: Array<SpotMarketAccount> = [
|
|
|
514
516
|
lastIndexPriceTwapTs: new BN(0),
|
|
515
517
|
},
|
|
516
518
|
pausedOperations: 0,
|
|
519
|
+
ifPausedOperations: 0,
|
|
517
520
|
},
|
|
518
521
|
];
|
|
519
522
|
|