@drift-labs/sdk 2.40.0-beta.1 → 2.40.0-beta.10
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/README.md +0 -1
- package/VERSION +1 -1
- package/bun.lockb +0 -0
- package/lib/accounts/types.d.ts +5 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -1
- package/lib/accounts/webSocketAccountSubscriber.js +28 -2
- package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +6 -5
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +32 -0
- package/lib/accounts/webSocketProgramAccountSubscriber.js +99 -0
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +2 -1
- package/lib/accounts/webSocketUserAccountSubscriber.js +3 -2
- package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +2 -1
- package/lib/accounts/webSocketUserStatsAccountSubsriber.js +3 -2
- package/lib/auctionSubscriber/auctionSubscriber.d.ts +3 -2
- package/lib/auctionSubscriber/auctionSubscriber.js +15 -7
- package/lib/auctionSubscriber/types.d.ts +1 -0
- package/lib/driftClient.d.ts +2 -1
- package/lib/driftClient.js +5 -4
- package/lib/driftClientConfig.d.ts +1 -0
- package/lib/idl/drift.json +51 -0
- package/lib/jupiter/jupiterClient.d.ts +3 -1
- package/lib/jupiter/jupiterClient.js +3 -1
- package/lib/math/amm.js +7 -2
- package/lib/math/superStake.d.ts +51 -4
- package/lib/math/superStake.js +173 -21
- package/lib/math/utils.d.ts +1 -0
- package/lib/math/utils.js +10 -1
- package/lib/orderSubscriber/OrderSubscriber.d.ts +1 -3
- package/lib/orderSubscriber/OrderSubscriber.js +4 -3
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -2
- package/lib/orderSubscriber/WebsocketSubscription.js +13 -12
- package/lib/orderSubscriber/types.d.ts +1 -0
- package/lib/user.d.ts +2 -2
- package/lib/user.js +5 -5
- package/package.json +1 -1
- package/src/accounts/types.ts +8 -1
- package/src/accounts/webSocketAccountSubscriber.ts +36 -2
- package/src/accounts/webSocketDriftClientAccountSubscriber.ts +15 -5
- package/src/accounts/webSocketProgramAccountSubscriber.ts +152 -0
- package/src/accounts/webSocketUserAccountSubscriber.ts +10 -2
- package/src/accounts/webSocketUserStatsAccountSubsriber.ts +10 -2
- package/src/auctionSubscriber/auctionSubscriber.ts +30 -21
- package/src/auctionSubscriber/types.ts +1 -0
- package/src/driftClient.ts +5 -1
- package/src/driftClientConfig.ts +1 -0
- package/src/idl/drift.json +51 -0
- package/src/jupiter/jupiterClient.ts +3 -0
- package/src/math/amm.ts +9 -2
- package/src/math/superStake.ts +248 -24
- package/src/math/utils.ts +12 -0
- package/src/orderSubscriber/OrderSubscriber.ts +12 -7
- package/src/orderSubscriber/WebsocketSubscription.ts +33 -23
- package/src/orderSubscriber/types.ts +1 -0
- package/src/user.ts +7 -5
package/README.md
CHANGED
|
@@ -244,4 +244,3 @@ Drift Protocol v2 is licensed under [Apache 2.0](./LICENSE).
|
|
|
244
244
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
|
245
245
|
for inclusion in Drift SDK by you, as defined in the Apache-2.0 license, shall be
|
|
246
246
|
licensed as above, without any additional terms or conditions.
|
|
247
|
-
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.40.0-beta.
|
|
1
|
+
2.40.0-beta.10
|
package/bun.lockb
ADDED
|
Binary file
|
package/lib/accounts/types.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { SpotMarketAccount, PerpMarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
|
|
4
4
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
5
|
import { EventEmitter } from 'events';
|
|
6
|
-
import { PublicKey } from '@solana/web3.js';
|
|
6
|
+
import { Context, PublicKey } from '@solana/web3.js';
|
|
7
7
|
import { Account } from '@solana/spl-token';
|
|
8
8
|
import { OracleInfo, OraclePriceData } from '..';
|
|
9
9
|
export interface AccountSubscriber<T> {
|
|
@@ -13,6 +13,10 @@ export interface AccountSubscriber<T> {
|
|
|
13
13
|
unsubscribe(): Promise<void>;
|
|
14
14
|
setData(userAccount: T, slot?: number): void;
|
|
15
15
|
}
|
|
16
|
+
export interface ProgramAccountSubscriber<T> {
|
|
17
|
+
subscribe(onChange: (accountId: PublicKey, data: T, context: Context) => void): Promise<void>;
|
|
18
|
+
unsubscribe(): Promise<void>;
|
|
19
|
+
}
|
|
16
20
|
export declare class NotSubscribedError extends Error {
|
|
17
21
|
name: string;
|
|
18
22
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { DataAndSlot, BufferAndSlot, AccountSubscriber } from './types';
|
|
3
4
|
import { Program } from '@coral-xyz/anchor';
|
|
4
5
|
import { AccountInfo, Context, PublicKey } from '@solana/web3.js';
|
|
@@ -11,9 +12,13 @@ export declare class WebSocketAccountSubscriber<T> implements AccountSubscriber<
|
|
|
11
12
|
decodeBufferFn: (buffer: Buffer) => T;
|
|
12
13
|
onChange: (data: T) => void;
|
|
13
14
|
listenerId?: number;
|
|
14
|
-
|
|
15
|
+
resubTimeoutMs?: number;
|
|
16
|
+
timeoutId?: NodeJS.Timeout;
|
|
17
|
+
receivingData: boolean;
|
|
18
|
+
constructor(accountName: string, program: Program, accountPublicKey: PublicKey, decodeBuffer?: (buffer: Buffer) => T, resubTimeoutMs?: number);
|
|
15
19
|
subscribe(onChange: (data: T) => void): Promise<void>;
|
|
16
20
|
setData(data: T, slot?: number): void;
|
|
21
|
+
private setTimeout;
|
|
17
22
|
fetch(): Promise<void>;
|
|
18
23
|
handleRpcResponse(context: Context, accountInfo?: AccountInfo<Buffer>): void;
|
|
19
24
|
decodeBuffer(buffer: Buffer): T;
|
|
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.WebSocketAccountSubscriber = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
class WebSocketAccountSubscriber {
|
|
6
|
-
constructor(accountName, program, accountPublicKey, decodeBuffer) {
|
|
6
|
+
constructor(accountName, program, accountPublicKey, decodeBuffer, resubTimeoutMs) {
|
|
7
7
|
this.accountName = accountName;
|
|
8
8
|
this.program = program;
|
|
9
9
|
this.accountPublicKey = accountPublicKey;
|
|
10
10
|
this.decodeBufferFn = decodeBuffer;
|
|
11
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
12
|
+
this.receivingData = false;
|
|
11
13
|
}
|
|
12
14
|
async subscribe(onChange) {
|
|
13
15
|
if (this.listenerId) {
|
|
@@ -18,8 +20,19 @@ class WebSocketAccountSubscriber {
|
|
|
18
20
|
await this.fetch();
|
|
19
21
|
}
|
|
20
22
|
this.listenerId = this.program.provider.connection.onAccountChange(this.accountPublicKey, (accountInfo, context) => {
|
|
21
|
-
this.
|
|
23
|
+
if (this.resubTimeoutMs) {
|
|
24
|
+
this.receivingData = true;
|
|
25
|
+
clearTimeout(this.timeoutId);
|
|
26
|
+
this.handleRpcResponse(context, accountInfo);
|
|
27
|
+
this.setTimeout();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
this.handleRpcResponse(context, accountInfo);
|
|
31
|
+
}
|
|
22
32
|
}, this.program.provider.opts.commitment);
|
|
33
|
+
if (this.resubTimeoutMs) {
|
|
34
|
+
this.setTimeout();
|
|
35
|
+
}
|
|
23
36
|
}
|
|
24
37
|
setData(data, slot) {
|
|
25
38
|
const newSlot = slot || 0;
|
|
@@ -31,6 +44,19 @@ class WebSocketAccountSubscriber {
|
|
|
31
44
|
slot,
|
|
32
45
|
};
|
|
33
46
|
}
|
|
47
|
+
setTimeout() {
|
|
48
|
+
if (!this.onChange) {
|
|
49
|
+
throw new Error('onChange callback function must be set');
|
|
50
|
+
}
|
|
51
|
+
this.timeoutId = setTimeout(async () => {
|
|
52
|
+
if (this.receivingData) {
|
|
53
|
+
console.log(`No ws data from ${this.accountName} in ${this.resubTimeoutMs}ms, resubscribing`);
|
|
54
|
+
await this.unsubscribe();
|
|
55
|
+
this.receivingData = false;
|
|
56
|
+
await this.subscribe(this.onChange);
|
|
57
|
+
}
|
|
58
|
+
}, this.resubTimeoutMs);
|
|
59
|
+
}
|
|
34
60
|
async fetch() {
|
|
35
61
|
const rpcResponse = await this.program.provider.connection.getAccountInfoAndContext(this.accountPublicKey, this.program.provider.opts.commitment);
|
|
36
62
|
this.handleRpcResponse(rpcResponse.context, rpcResponse === null || rpcResponse === void 0 ? void 0 : rpcResponse.value);
|
|
@@ -15,6 +15,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
|
|
|
15
15
|
spotMarketIndexes: number[];
|
|
16
16
|
oracleInfos: OracleInfo[];
|
|
17
17
|
oracleClientCache: OracleClientCache;
|
|
18
|
+
resubTimeoutMs?: number;
|
|
18
19
|
shouldFindAllMarketsAndOracles: boolean;
|
|
19
20
|
eventEmitter: StrictEventEmitter<EventEmitter, DriftClientAccountEvents>;
|
|
20
21
|
stateAccountSubscriber?: AccountSubscriber<StateAccount>;
|
|
@@ -24,7 +25,7 @@ export declare class WebSocketDriftClientAccountSubscriber implements DriftClien
|
|
|
24
25
|
private isSubscribing;
|
|
25
26
|
private subscriptionPromise;
|
|
26
27
|
private subscriptionPromiseResolver;
|
|
27
|
-
constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean);
|
|
28
|
+
constructor(program: Program, perpMarketIndexes: number[], spotMarketIndexes: number[], oracleInfos: OracleInfo[], shouldFindAllMarketsAndOracles: boolean, resubTimeoutMs?: number);
|
|
28
29
|
subscribe(): Promise<boolean>;
|
|
29
30
|
subscribeToPerpMarketAccounts(): Promise<boolean>;
|
|
30
31
|
subscribeToPerpMarketAccount(marketIndex: number): Promise<boolean>;
|
|
@@ -10,7 +10,7 @@ const oracleClientCache_1 = require("../oracles/oracleClientCache");
|
|
|
10
10
|
const quoteAssetOracleClient_1 = require("../oracles/quoteAssetOracleClient");
|
|
11
11
|
const config_1 = require("../config");
|
|
12
12
|
class WebSocketDriftClientAccountSubscriber {
|
|
13
|
-
constructor(program, perpMarketIndexes, spotMarketIndexes, oracleInfos, shouldFindAllMarketsAndOracles) {
|
|
13
|
+
constructor(program, perpMarketIndexes, spotMarketIndexes, oracleInfos, shouldFindAllMarketsAndOracles, resubTimeoutMs) {
|
|
14
14
|
this.oracleClientCache = new oracleClientCache_1.OracleClientCache();
|
|
15
15
|
this.perpMarketAccountSubscribers = new Map();
|
|
16
16
|
this.spotMarketAccountSubscribers = new Map();
|
|
@@ -23,6 +23,7 @@ class WebSocketDriftClientAccountSubscriber {
|
|
|
23
23
|
this.spotMarketIndexes = spotMarketIndexes;
|
|
24
24
|
this.oracleInfos = oracleInfos;
|
|
25
25
|
this.shouldFindAllMarketsAndOracles = shouldFindAllMarketsAndOracles;
|
|
26
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
26
27
|
}
|
|
27
28
|
async subscribe() {
|
|
28
29
|
if (this.isSubscribed) {
|
|
@@ -43,7 +44,7 @@ class WebSocketDriftClientAccountSubscriber {
|
|
|
43
44
|
}
|
|
44
45
|
const statePublicKey = await (0, pda_1.getDriftStateAccountPublicKey)(this.program.programId);
|
|
45
46
|
// create and activate main state account subscription
|
|
46
|
-
this.stateAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('state', this.program, statePublicKey);
|
|
47
|
+
this.stateAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('state', this.program, statePublicKey, undefined, this.resubTimeoutMs);
|
|
47
48
|
await this.stateAccountSubscriber.subscribe((data) => {
|
|
48
49
|
this.eventEmitter.emit('stateAccountUpdate', data);
|
|
49
50
|
this.eventEmitter.emit('update');
|
|
@@ -68,7 +69,7 @@ class WebSocketDriftClientAccountSubscriber {
|
|
|
68
69
|
}
|
|
69
70
|
async subscribeToPerpMarketAccount(marketIndex) {
|
|
70
71
|
const perpMarketPublicKey = await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, marketIndex);
|
|
71
|
-
const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('perpMarket', this.program, perpMarketPublicKey);
|
|
72
|
+
const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('perpMarket', this.program, perpMarketPublicKey, undefined, this.resubTimeoutMs);
|
|
72
73
|
await accountSubscriber.subscribe((data) => {
|
|
73
74
|
this.eventEmitter.emit('perpMarketAccountUpdate', data);
|
|
74
75
|
this.eventEmitter.emit('update');
|
|
@@ -84,7 +85,7 @@ class WebSocketDriftClientAccountSubscriber {
|
|
|
84
85
|
}
|
|
85
86
|
async subscribeToSpotMarketAccount(marketIndex) {
|
|
86
87
|
const marketPublicKey = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, marketIndex);
|
|
87
|
-
const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('spotMarket', this.program, marketPublicKey);
|
|
88
|
+
const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('spotMarket', this.program, marketPublicKey, undefined, this.resubTimeoutMs);
|
|
88
89
|
await accountSubscriber.subscribe((data) => {
|
|
89
90
|
this.eventEmitter.emit('spotMarketAccountUpdate', data);
|
|
90
91
|
this.eventEmitter.emit('update');
|
|
@@ -104,7 +105,7 @@ class WebSocketDriftClientAccountSubscriber {
|
|
|
104
105
|
const client = this.oracleClientCache.get(oracleInfo.source, this.program.provider.connection);
|
|
105
106
|
const accountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('oracle', this.program, oracleInfo.publicKey, (buffer) => {
|
|
106
107
|
return client.getOraclePriceDataFromBuffer(buffer);
|
|
107
|
-
});
|
|
108
|
+
}, this.resubTimeoutMs);
|
|
108
109
|
await accountSubscriber.subscribe((data) => {
|
|
109
110
|
this.eventEmitter.emit('oraclePriceUpdate', oracleInfo.publicKey, data);
|
|
110
111
|
this.eventEmitter.emit('update');
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
3
|
+
import { DataAndSlot, BufferAndSlot, ProgramAccountSubscriber } from './types';
|
|
4
|
+
import { Program } from '@coral-xyz/anchor';
|
|
5
|
+
import { Commitment, Context, KeyedAccountInfo, MemcmpFilter, PublicKey } from '@solana/web3.js';
|
|
6
|
+
export declare class WebSocketProgramAccountSubscriber<T> implements ProgramAccountSubscriber<T> {
|
|
7
|
+
subscriptionName: string;
|
|
8
|
+
accountDiscriminator: string;
|
|
9
|
+
dataAndSlot?: DataAndSlot<T> & {
|
|
10
|
+
accountId: PublicKey;
|
|
11
|
+
};
|
|
12
|
+
bufferAndSlot?: BufferAndSlot;
|
|
13
|
+
program: Program;
|
|
14
|
+
decodeBuffer: (accountName: string, ix: Buffer) => T;
|
|
15
|
+
onChange: (accountId: PublicKey, data: T, context: Context) => void;
|
|
16
|
+
listenerId?: number;
|
|
17
|
+
resubTimeoutMs?: number;
|
|
18
|
+
timeoutId?: NodeJS.Timeout;
|
|
19
|
+
options: {
|
|
20
|
+
filters: MemcmpFilter[];
|
|
21
|
+
commitment?: Commitment;
|
|
22
|
+
};
|
|
23
|
+
receivingData: boolean;
|
|
24
|
+
constructor(subscriptionName: string, accountDiscriminator: string, program: Program, decodeBufferFn: (accountName: string, ix: Buffer) => T, options?: {
|
|
25
|
+
filters: MemcmpFilter[];
|
|
26
|
+
commitment?: Commitment;
|
|
27
|
+
}, resubTimeoutMs?: number);
|
|
28
|
+
subscribe(onChange: (accountId: PublicKey, data: T, context: Context) => void): Promise<void>;
|
|
29
|
+
private setTimeout;
|
|
30
|
+
handleRpcResponse(context: Context, keyedAccountInfo: KeyedAccountInfo): void;
|
|
31
|
+
unsubscribe(): Promise<void>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketProgramAccountSubscriber = void 0;
|
|
4
|
+
class WebSocketProgramAccountSubscriber {
|
|
5
|
+
constructor(subscriptionName, accountDiscriminator, program, decodeBufferFn, options = {
|
|
6
|
+
filters: [],
|
|
7
|
+
}, resubTimeoutMs) {
|
|
8
|
+
this.receivingData = false;
|
|
9
|
+
this.subscriptionName = subscriptionName;
|
|
10
|
+
this.accountDiscriminator = accountDiscriminator;
|
|
11
|
+
this.program = program;
|
|
12
|
+
this.decodeBuffer = decodeBufferFn;
|
|
13
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
14
|
+
this.options = options;
|
|
15
|
+
this.receivingData = false;
|
|
16
|
+
}
|
|
17
|
+
async subscribe(onChange) {
|
|
18
|
+
var _a;
|
|
19
|
+
if (this.listenerId) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
this.onChange = onChange;
|
|
23
|
+
this.listenerId = this.program.provider.connection.onProgramAccountChange(this.program.programId, (keyedAccountInfo, context) => {
|
|
24
|
+
if (this.resubTimeoutMs) {
|
|
25
|
+
this.receivingData = true;
|
|
26
|
+
clearTimeout(this.timeoutId);
|
|
27
|
+
this.handleRpcResponse(context, keyedAccountInfo);
|
|
28
|
+
this.setTimeout();
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
this.handleRpcResponse(context, keyedAccountInfo);
|
|
32
|
+
}
|
|
33
|
+
}, (_a = this.options.commitment) !== null && _a !== void 0 ? _a : this.program.provider.opts.commitment, this.options.filters);
|
|
34
|
+
if (this.resubTimeoutMs) {
|
|
35
|
+
this.setTimeout();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
setTimeout() {
|
|
39
|
+
if (!this.onChange) {
|
|
40
|
+
throw new Error('onChange callback function must be set');
|
|
41
|
+
}
|
|
42
|
+
this.timeoutId = setTimeout(async () => {
|
|
43
|
+
if (this.receivingData) {
|
|
44
|
+
console.log(`No ws data from ${this.subscriptionName} in ${this.resubTimeoutMs}ms, resubscribing`);
|
|
45
|
+
await this.unsubscribe();
|
|
46
|
+
this.receivingData = false;
|
|
47
|
+
await this.subscribe(this.onChange);
|
|
48
|
+
}
|
|
49
|
+
}, this.resubTimeoutMs);
|
|
50
|
+
}
|
|
51
|
+
handleRpcResponse(context, keyedAccountInfo) {
|
|
52
|
+
const newSlot = context.slot;
|
|
53
|
+
let newBuffer = undefined;
|
|
54
|
+
if (keyedAccountInfo) {
|
|
55
|
+
newBuffer = keyedAccountInfo.accountInfo.data;
|
|
56
|
+
}
|
|
57
|
+
if (!this.bufferAndSlot) {
|
|
58
|
+
this.bufferAndSlot = {
|
|
59
|
+
buffer: newBuffer,
|
|
60
|
+
slot: newSlot,
|
|
61
|
+
};
|
|
62
|
+
if (newBuffer) {
|
|
63
|
+
const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
|
|
64
|
+
this.dataAndSlot = {
|
|
65
|
+
data: account,
|
|
66
|
+
slot: newSlot,
|
|
67
|
+
accountId: keyedAccountInfo.accountId,
|
|
68
|
+
};
|
|
69
|
+
this.onChange(keyedAccountInfo.accountId, account, context);
|
|
70
|
+
}
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (newSlot <= this.bufferAndSlot.slot) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const oldBuffer = this.bufferAndSlot.buffer;
|
|
77
|
+
if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
|
|
78
|
+
this.bufferAndSlot = {
|
|
79
|
+
buffer: newBuffer,
|
|
80
|
+
slot: newSlot,
|
|
81
|
+
};
|
|
82
|
+
const account = this.decodeBuffer(this.accountDiscriminator, newBuffer);
|
|
83
|
+
this.dataAndSlot = {
|
|
84
|
+
data: account,
|
|
85
|
+
slot: newSlot,
|
|
86
|
+
accountId: keyedAccountInfo.accountId,
|
|
87
|
+
};
|
|
88
|
+
this.onChange(keyedAccountInfo.accountId, account, context);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
unsubscribe() {
|
|
92
|
+
if (this.listenerId) {
|
|
93
|
+
const promise = this.program.provider.connection.removeAccountChangeListener(this.listenerId);
|
|
94
|
+
this.listenerId = undefined;
|
|
95
|
+
return promise;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.WebSocketProgramAccountSubscriber = WebSocketProgramAccountSubscriber;
|
|
@@ -7,11 +7,12 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
7
7
|
import { UserAccount } from '../types';
|
|
8
8
|
export declare class WebSocketUserAccountSubscriber implements UserAccountSubscriber {
|
|
9
9
|
isSubscribed: boolean;
|
|
10
|
+
reconnectTimeoutMs?: number;
|
|
10
11
|
program: Program;
|
|
11
12
|
eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
|
|
12
13
|
userAccountPublicKey: PublicKey;
|
|
13
14
|
userDataAccountSubscriber: AccountSubscriber<UserAccount>;
|
|
14
|
-
constructor(program: Program, userAccountPublicKey: PublicKey);
|
|
15
|
+
constructor(program: Program, userAccountPublicKey: PublicKey, reconnectTimeoutMs?: number);
|
|
15
16
|
subscribe(userAccount?: UserAccount): Promise<boolean>;
|
|
16
17
|
fetch(): Promise<void>;
|
|
17
18
|
unsubscribe(): Promise<void>;
|
|
@@ -5,17 +5,18 @@ const types_1 = require("./types");
|
|
|
5
5
|
const events_1 = require("events");
|
|
6
6
|
const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
|
|
7
7
|
class WebSocketUserAccountSubscriber {
|
|
8
|
-
constructor(program, userAccountPublicKey) {
|
|
8
|
+
constructor(program, userAccountPublicKey, reconnectTimeoutMs) {
|
|
9
9
|
this.isSubscribed = false;
|
|
10
10
|
this.program = program;
|
|
11
11
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
12
12
|
this.eventEmitter = new events_1.EventEmitter();
|
|
13
|
+
this.reconnectTimeoutMs = reconnectTimeoutMs;
|
|
13
14
|
}
|
|
14
15
|
async subscribe(userAccount) {
|
|
15
16
|
if (this.isSubscribed) {
|
|
16
17
|
return true;
|
|
17
18
|
}
|
|
18
|
-
this.userDataAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('user', this.program, this.userAccountPublicKey);
|
|
19
|
+
this.userDataAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('user', this.program, this.userAccountPublicKey, undefined, this.reconnectTimeoutMs);
|
|
19
20
|
if (userAccount) {
|
|
20
21
|
this.userDataAccountSubscriber.setData(userAccount);
|
|
21
22
|
}
|
|
@@ -7,11 +7,12 @@ import { PublicKey } from '@solana/web3.js';
|
|
|
7
7
|
import { UserStatsAccount } from '../types';
|
|
8
8
|
export declare class WebSocketUserStatsAccountSubscriber implements UserStatsAccountSubscriber {
|
|
9
9
|
isSubscribed: boolean;
|
|
10
|
+
reconnectTimeoutMs?: number;
|
|
10
11
|
program: Program;
|
|
11
12
|
eventEmitter: StrictEventEmitter<EventEmitter, UserStatsAccountEvents>;
|
|
12
13
|
userStatsAccountPublicKey: PublicKey;
|
|
13
14
|
userStatsAccountSubscriber: AccountSubscriber<UserStatsAccount>;
|
|
14
|
-
constructor(program: Program, userStatsAccountPublicKey: PublicKey);
|
|
15
|
+
constructor(program: Program, userStatsAccountPublicKey: PublicKey, reconnectTimeoutMs?: number);
|
|
15
16
|
subscribe(userStatsAccount?: UserStatsAccount): Promise<boolean>;
|
|
16
17
|
fetch(): Promise<void>;
|
|
17
18
|
unsubscribe(): Promise<void>;
|
|
@@ -5,17 +5,18 @@ const types_1 = require("./types");
|
|
|
5
5
|
const events_1 = require("events");
|
|
6
6
|
const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
|
|
7
7
|
class WebSocketUserStatsAccountSubscriber {
|
|
8
|
-
constructor(program, userStatsAccountPublicKey) {
|
|
8
|
+
constructor(program, userStatsAccountPublicKey, reconnectTimeoutMs) {
|
|
9
9
|
this.isSubscribed = false;
|
|
10
10
|
this.program = program;
|
|
11
11
|
this.userStatsAccountPublicKey = userStatsAccountPublicKey;
|
|
12
12
|
this.eventEmitter = new events_1.EventEmitter();
|
|
13
|
+
this.reconnectTimeoutMs = reconnectTimeoutMs;
|
|
13
14
|
}
|
|
14
15
|
async subscribe(userStatsAccount) {
|
|
15
16
|
if (this.isSubscribed) {
|
|
16
17
|
return true;
|
|
17
18
|
}
|
|
18
|
-
this.userStatsAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('userStats', this.program, this.userStatsAccountPublicKey);
|
|
19
|
+
this.userStatsAccountSubscriber = new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('userStats', this.program, this.userStatsAccountPublicKey, undefined, this.reconnectTimeoutMs);
|
|
19
20
|
if (userStatsAccount) {
|
|
20
21
|
this.userStatsAccountSubscriber.setData(userStatsAccount);
|
|
21
22
|
}
|
|
@@ -5,9 +5,10 @@ import { EventEmitter } from 'events';
|
|
|
5
5
|
export declare class AuctionSubscriber {
|
|
6
6
|
private driftClient;
|
|
7
7
|
private opts;
|
|
8
|
+
private resubTimeoutMs?;
|
|
8
9
|
eventEmitter: StrictEventEmitter<EventEmitter, AuctionSubscriberEvents>;
|
|
9
|
-
private
|
|
10
|
-
constructor({ driftClient, opts }: AuctionSubscriberConfig);
|
|
10
|
+
private subscriber;
|
|
11
|
+
constructor({ driftClient, opts, resubTimeoutMs }: AuctionSubscriberConfig);
|
|
11
12
|
subscribe(): Promise<void>;
|
|
12
13
|
unsubscribe(): Promise<void>;
|
|
13
14
|
}
|
|
@@ -3,22 +3,30 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.AuctionSubscriber = void 0;
|
|
4
4
|
const memcmp_1 = require("../memcmp");
|
|
5
5
|
const events_1 = require("events");
|
|
6
|
+
const webSocketProgramAccountSubscriber_1 = require("../accounts/webSocketProgramAccountSubscriber");
|
|
6
7
|
class AuctionSubscriber {
|
|
7
|
-
constructor({ driftClient, opts }) {
|
|
8
|
+
constructor({ driftClient, opts, resubTimeoutMs }) {
|
|
8
9
|
this.driftClient = driftClient;
|
|
9
10
|
this.opts = opts || this.driftClient.opts;
|
|
10
11
|
this.eventEmitter = new events_1.EventEmitter();
|
|
12
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
11
13
|
}
|
|
12
14
|
async subscribe() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
if (!this.subscriber) {
|
|
16
|
+
this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('AuctionSubscriber', 'User', this.driftClient.program, this.driftClient.program.account.user.coder.accounts.decode.bind(this.driftClient.program.account.user.coder.accounts), {
|
|
17
|
+
filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getUserWithAuctionFilter)()],
|
|
18
|
+
commitment: this.driftClient.opts.commitment,
|
|
19
|
+
}, this.resubTimeoutMs);
|
|
20
|
+
}
|
|
21
|
+
await this.subscriber.subscribe((accountId, data, context) => {
|
|
22
|
+
this.eventEmitter.emit('onAccountUpdate', data, accountId, context.slot);
|
|
23
|
+
});
|
|
17
24
|
}
|
|
18
25
|
async unsubscribe() {
|
|
19
|
-
if (this.
|
|
20
|
-
|
|
26
|
+
if (!this.subscriber) {
|
|
27
|
+
return;
|
|
21
28
|
}
|
|
29
|
+
this.subscriber.unsubscribe();
|
|
22
30
|
}
|
|
23
31
|
}
|
|
24
32
|
exports.AuctionSubscriber = AuctionSubscriber;
|
|
@@ -4,6 +4,7 @@ import { ConfirmOptions, PublicKey } from '@solana/web3.js';
|
|
|
4
4
|
export type AuctionSubscriberConfig = {
|
|
5
5
|
driftClient: DriftClient;
|
|
6
6
|
opts?: ConfirmOptions;
|
|
7
|
+
resubTimeoutMs?: number;
|
|
7
8
|
};
|
|
8
9
|
export interface AuctionSubscriberEvents {
|
|
9
10
|
onAccountUpdate: (account: UserAccount, pubkey: PublicKey, slot: number) => void;
|
package/lib/driftClient.d.ts
CHANGED
|
@@ -319,7 +319,7 @@ export declare class DriftClient {
|
|
|
319
319
|
* @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
|
|
320
320
|
* @param txParams
|
|
321
321
|
*/
|
|
322
|
-
swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }: {
|
|
322
|
+
swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, onlyDirectRoutes, }: {
|
|
323
323
|
jupiterClient: JupiterClient;
|
|
324
324
|
outMarketIndex: number;
|
|
325
325
|
inMarketIndex: number;
|
|
@@ -331,6 +331,7 @@ export declare class DriftClient {
|
|
|
331
331
|
route?: Route;
|
|
332
332
|
reduceOnly?: SwapReduceOnly;
|
|
333
333
|
txParams?: TxParams;
|
|
334
|
+
onlyDirectRoutes?: boolean;
|
|
334
335
|
v6?: {
|
|
335
336
|
quote?: QuoteResponse;
|
|
336
337
|
};
|
package/lib/driftClient.js
CHANGED
|
@@ -66,7 +66,7 @@ class DriftClient {
|
|
|
66
66
|
this._isSubscribed = val;
|
|
67
67
|
}
|
|
68
68
|
constructor(config) {
|
|
69
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
|
|
69
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
70
70
|
this.users = new Map();
|
|
71
71
|
this._isSubscribed = false;
|
|
72
72
|
this.perpMarketLastSlotCache = new Map();
|
|
@@ -139,11 +139,11 @@ class DriftClient {
|
|
|
139
139
|
this.accountSubscriber = new pollingDriftClientAccountSubscriber_1.PollingDriftClientAccountSubscriber(this.program, config.accountSubscription.accountLoader, (_o = config.perpMarketIndexes) !== null && _o !== void 0 ? _o : [], (_p = config.spotMarketIndexes) !== null && _p !== void 0 ? _p : [], (_q = config.oracleInfos) !== null && _q !== void 0 ? _q : [], noMarketsAndOraclesSpecified);
|
|
140
140
|
}
|
|
141
141
|
else {
|
|
142
|
-
this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_r = config.perpMarketIndexes) !== null && _r !== void 0 ? _r : [], (_s = config.spotMarketIndexes) !== null && _s !== void 0 ? _s : [], (_t = config.oracleInfos) !== null && _t !== void 0 ? _t : [], noMarketsAndOraclesSpecified);
|
|
142
|
+
this.accountSubscriber = new webSocketDriftClientAccountSubscriber_1.WebSocketDriftClientAccountSubscriber(this.program, (_r = config.perpMarketIndexes) !== null && _r !== void 0 ? _r : [], (_s = config.spotMarketIndexes) !== null && _s !== void 0 ? _s : [], (_t = config.oracleInfos) !== null && _t !== void 0 ? _t : [], noMarketsAndOraclesSpecified, (_u = config.accountSubscription) === null || _u === void 0 ? void 0 : _u.resubTimeoutMs);
|
|
143
143
|
}
|
|
144
144
|
this.eventEmitter = this.accountSubscriber.eventEmitter;
|
|
145
145
|
this.txSender =
|
|
146
|
-
(
|
|
146
|
+
(_v = config.txSender) !== null && _v !== void 0 ? _v : new retryTxSender_1.RetryTxSender({
|
|
147
147
|
connection: this.connection,
|
|
148
148
|
wallet: this.wallet,
|
|
149
149
|
opts: this.opts,
|
|
@@ -1975,7 +1975,7 @@ class DriftClient {
|
|
|
1975
1975
|
* @param reduceOnly specify if In or Out token on the drift account must reduceOnly, checked at end of swap
|
|
1976
1976
|
* @param txParams
|
|
1977
1977
|
*/
|
|
1978
|
-
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, }) {
|
|
1978
|
+
async swap({ jupiterClient, outMarketIndex, inMarketIndex, outAssociatedTokenAccount, inAssociatedTokenAccount, amount, slippageBps, swapMode, route, reduceOnly, txParams, v6, onlyDirectRoutes = false, }) {
|
|
1979
1979
|
let ixs;
|
|
1980
1980
|
let lookupTables;
|
|
1981
1981
|
if (v6) {
|
|
@@ -1990,6 +1990,7 @@ class DriftClient {
|
|
|
1990
1990
|
swapMode,
|
|
1991
1991
|
quote: v6.quote,
|
|
1992
1992
|
reduceOnly,
|
|
1993
|
+
onlyDirectRoutes,
|
|
1993
1994
|
});
|
|
1994
1995
|
ixs = res.ixs;
|
|
1995
1996
|
lookupTables = res.lookupTables;
|
package/lib/idl/drift.json
CHANGED
|
@@ -6314,6 +6314,24 @@
|
|
|
6314
6314
|
]
|
|
6315
6315
|
}
|
|
6316
6316
|
},
|
|
6317
|
+
{
|
|
6318
|
+
"name": "MarketIdentifier",
|
|
6319
|
+
"type": {
|
|
6320
|
+
"kind": "struct",
|
|
6321
|
+
"fields": [
|
|
6322
|
+
{
|
|
6323
|
+
"name": "marketType",
|
|
6324
|
+
"type": {
|
|
6325
|
+
"defined": "MarketType"
|
|
6326
|
+
}
|
|
6327
|
+
},
|
|
6328
|
+
{
|
|
6329
|
+
"name": "marketIndex",
|
|
6330
|
+
"type": "u16"
|
|
6331
|
+
}
|
|
6332
|
+
]
|
|
6333
|
+
}
|
|
6334
|
+
},
|
|
6317
6335
|
{
|
|
6318
6336
|
"name": "HistoricalOracleData",
|
|
6319
6337
|
"type": {
|
|
@@ -8198,6 +8216,34 @@
|
|
|
8198
8216
|
]
|
|
8199
8217
|
}
|
|
8200
8218
|
},
|
|
8219
|
+
{
|
|
8220
|
+
"name": "MarginCalculationMode",
|
|
8221
|
+
"type": {
|
|
8222
|
+
"kind": "enum",
|
|
8223
|
+
"variants": [
|
|
8224
|
+
{
|
|
8225
|
+
"name": "Standard"
|
|
8226
|
+
},
|
|
8227
|
+
{
|
|
8228
|
+
"name": "Liquidation",
|
|
8229
|
+
"fields": [
|
|
8230
|
+
{
|
|
8231
|
+
"name": "margin_buffer",
|
|
8232
|
+
"type": "u128"
|
|
8233
|
+
},
|
|
8234
|
+
{
|
|
8235
|
+
"name": "market_to_track_margin_requirement",
|
|
8236
|
+
"type": {
|
|
8237
|
+
"option": {
|
|
8238
|
+
"defined": "MarketIdentifier"
|
|
8239
|
+
}
|
|
8240
|
+
}
|
|
8241
|
+
}
|
|
8242
|
+
]
|
|
8243
|
+
}
|
|
8244
|
+
]
|
|
8245
|
+
}
|
|
8246
|
+
},
|
|
8201
8247
|
{
|
|
8202
8248
|
"name": "OracleSource",
|
|
8203
8249
|
"type": {
|
|
@@ -10781,6 +10827,11 @@
|
|
|
10781
10827
|
"code": 6254,
|
|
10782
10828
|
"name": "UserReduceOnly",
|
|
10783
10829
|
"msg": "UserReduceOnly"
|
|
10830
|
+
},
|
|
10831
|
+
{
|
|
10832
|
+
"code": 6255,
|
|
10833
|
+
"name": "InvalidMarginCalculation",
|
|
10834
|
+
"msg": "InvalidMarginCalculation"
|
|
10784
10835
|
}
|
|
10785
10836
|
]
|
|
10786
10837
|
}
|
|
@@ -229,10 +229,12 @@ export declare class JupiterClient {
|
|
|
229
229
|
* @param swapMode the swap mode (ExactIn or ExactOut)
|
|
230
230
|
* @param onlyDirectRoutes whether to only return direct routes
|
|
231
231
|
*/
|
|
232
|
-
getQuote({ inputMint, outputMint, amount,
|
|
232
|
+
getQuote({ inputMint, outputMint, amount, maxAccounts, // 52 is an estimated amount with buffer
|
|
233
|
+
slippageBps, swapMode, onlyDirectRoutes, }: {
|
|
233
234
|
inputMint: PublicKey;
|
|
234
235
|
outputMint: PublicKey;
|
|
235
236
|
amount: BN;
|
|
237
|
+
maxAccounts?: number;
|
|
236
238
|
slippageBps?: number;
|
|
237
239
|
swapMode?: SwapMode;
|
|
238
240
|
onlyDirectRoutes?: boolean;
|
|
@@ -43,7 +43,8 @@ class JupiterClient {
|
|
|
43
43
|
* @param swapMode the swap mode (ExactIn or ExactOut)
|
|
44
44
|
* @param onlyDirectRoutes whether to only return direct routes
|
|
45
45
|
*/
|
|
46
|
-
async getQuote({ inputMint, outputMint, amount,
|
|
46
|
+
async getQuote({ inputMint, outputMint, amount, maxAccounts = 52, // 52 is an estimated amount with buffer
|
|
47
|
+
slippageBps = 50, swapMode = 'ExactIn', onlyDirectRoutes = false, }) {
|
|
47
48
|
const params = new URLSearchParams({
|
|
48
49
|
inputMint: inputMint.toString(),
|
|
49
50
|
outputMint: outputMint.toString(),
|
|
@@ -51,6 +52,7 @@ class JupiterClient {
|
|
|
51
52
|
slippageBps: slippageBps.toString(),
|
|
52
53
|
swapMode,
|
|
53
54
|
onlyDirectRoutes: onlyDirectRoutes.toString(),
|
|
55
|
+
maxAccounts: maxAccounts.toString(),
|
|
54
56
|
}).toString();
|
|
55
57
|
const quote = await (await (0, node_fetch_1.default)(`${this.url}/v6/quote?${params}`)).json();
|
|
56
58
|
return quote;
|
package/lib/math/amm.js
CHANGED
|
@@ -253,8 +253,13 @@ function calculateVolSpreadBN(lastOracleConfPct, reservePrice, markStd, oracleSt
|
|
|
253
253
|
const clampMax = numericConstants_1.PERCENTAGE_PRECISION.mul(new anchor_1.BN(16)).div(new anchor_1.BN(10));
|
|
254
254
|
const longVolSpreadFactor = (0, __1.clampBN)(longIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
|
|
255
255
|
const shortVolSpreadFactor = (0, __1.clampBN)(shortIntensity.mul(numericConstants_1.PERCENTAGE_PRECISION).div(anchor_1.BN.max(numericConstants_1.ONE, volume24H)), clampMin, clampMax);
|
|
256
|
-
|
|
257
|
-
|
|
256
|
+
// only consider confidence interval at full value when above 25 bps
|
|
257
|
+
let confComponent = lastOracleConfPct;
|
|
258
|
+
if (lastOracleConfPct.lte(numericConstants_1.PRICE_PRECISION.div(new anchor_1.BN(400)))) {
|
|
259
|
+
confComponent = lastOracleConfPct.div(new anchor_1.BN(10));
|
|
260
|
+
}
|
|
261
|
+
const longVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(longVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
|
|
262
|
+
const shortVolSpread = anchor_1.BN.max(confComponent, volSpread.mul(shortVolSpreadFactor).div(numericConstants_1.PERCENTAGE_PRECISION));
|
|
258
263
|
return [longVolSpread, shortVolSpread];
|
|
259
264
|
}
|
|
260
265
|
exports.calculateVolSpreadBN = calculateVolSpreadBN;
|