@drift-labs/sdk 2.98.0-beta.10 → 2.98.0-beta.12
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/driftClient.js +3 -0
- package/lib/browser/index.d.ts +2 -0
- package/lib/browser/index.js +2 -0
- 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/driftClient.js +3 -0
- package/lib/node/index.d.ts +2 -0
- package/lib/node/index.js +2 -0
- 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/driftClient.ts +18 -0
- package/src/index.ts +2 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.98.0-beta.
|
|
1
|
+
2.98.0-beta.12
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataAndSlot, HighLeverageModeConfigAccountEvents, HighLeverageModeConfigAccountSubscriber } from './types';
|
|
3
|
+
import { Program } from '@coral-xyz/anchor';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { PublicKey } from '@solana/web3.js';
|
|
7
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
8
|
+
import { HighLeverageModeConfig } from '../types';
|
|
9
|
+
export declare class PollingHighLeverageModeConfigAccountSubscriber implements HighLeverageModeConfigAccountSubscriber {
|
|
10
|
+
isSubscribed: boolean;
|
|
11
|
+
program: Program;
|
|
12
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
13
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
14
|
+
accountLoader: BulkAccountLoader;
|
|
15
|
+
callbackId?: string;
|
|
16
|
+
errorCallbackId?: string;
|
|
17
|
+
highLeverageModeConfigAccountAndSlot?: DataAndSlot<HighLeverageModeConfig>;
|
|
18
|
+
constructor(program: Program, publicKey: PublicKey, accountLoader: BulkAccountLoader);
|
|
19
|
+
subscribe(highLeverageModeConfig?: HighLeverageModeConfig): Promise<boolean>;
|
|
20
|
+
addToAccountLoader(): Promise<void>;
|
|
21
|
+
fetchIfUnloaded(): Promise<void>;
|
|
22
|
+
fetch(): Promise<void>;
|
|
23
|
+
doesAccountExist(): boolean;
|
|
24
|
+
unsubscribe(): Promise<void>;
|
|
25
|
+
assertIsSubscribed(): void;
|
|
26
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
27
|
+
didSubscriptionSucceed(): boolean;
|
|
28
|
+
updateData(highLeverageModeConfig: HighLeverageModeConfig, slot: number): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PollingHighLeverageModeConfigAccountSubscriber = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
class PollingHighLeverageModeConfigAccountSubscriber {
|
|
7
|
+
constructor(program, publicKey, accountLoader) {
|
|
8
|
+
this.isSubscribed = false;
|
|
9
|
+
this.program = program;
|
|
10
|
+
this.highLeverageModeConfigAccountPublicKey = publicKey;
|
|
11
|
+
this.accountLoader = accountLoader;
|
|
12
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
13
|
+
}
|
|
14
|
+
async subscribe(highLeverageModeConfig) {
|
|
15
|
+
if (this.isSubscribed) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (highLeverageModeConfig) {
|
|
19
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
20
|
+
data: highLeverageModeConfig,
|
|
21
|
+
slot: undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
await this.addToAccountLoader();
|
|
25
|
+
await this.fetchIfUnloaded();
|
|
26
|
+
if (this.doesAccountExist()) {
|
|
27
|
+
this.eventEmitter.emit('update');
|
|
28
|
+
}
|
|
29
|
+
this.isSubscribed = true;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
async addToAccountLoader() {
|
|
33
|
+
if (this.callbackId) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.callbackId = await this.accountLoader.addAccount(this.highLeverageModeConfigAccountPublicKey, (buffer, slot) => {
|
|
37
|
+
if (!buffer) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.highLeverageModeConfigAccountAndSlot &&
|
|
41
|
+
this.highLeverageModeConfigAccountAndSlot.slot > slot) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const account = this.program.account.user.coder.accounts.decode('HighLeverageModeConfig', buffer);
|
|
45
|
+
this.highLeverageModeConfigAccountAndSlot = { data: account, slot };
|
|
46
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', account);
|
|
47
|
+
this.eventEmitter.emit('update');
|
|
48
|
+
});
|
|
49
|
+
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
50
|
+
this.eventEmitter.emit('error', error);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async fetchIfUnloaded() {
|
|
54
|
+
if (this.highLeverageModeConfigAccountAndSlot === undefined) {
|
|
55
|
+
await this.fetch();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async fetch() {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
try {
|
|
61
|
+
const dataAndContext = await this.program.account.highLeverageModeConfig.fetchAndContext(this.highLeverageModeConfigAccountPublicKey, this.accountLoader.commitment);
|
|
62
|
+
if (dataAndContext.context.slot >
|
|
63
|
+
((_b = (_a = this.highLeverageModeConfigAccountAndSlot) === null || _a === void 0 ? void 0 : _a.slot) !== null && _b !== void 0 ? _b : 0)) {
|
|
64
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
65
|
+
data: dataAndContext.data,
|
|
66
|
+
slot: dataAndContext.context.slot,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
console.log(`PollingHighLeverageModeConfigAccountSubscriber.fetch() HighLeverageModeConfig does not exist: ${e.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
doesAccountExist() {
|
|
75
|
+
return this.highLeverageModeConfigAccountAndSlot !== undefined;
|
|
76
|
+
}
|
|
77
|
+
async unsubscribe() {
|
|
78
|
+
if (!this.isSubscribed) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.accountLoader.removeAccount(this.highLeverageModeConfigAccountPublicKey, this.callbackId);
|
|
82
|
+
this.callbackId = undefined;
|
|
83
|
+
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
84
|
+
this.errorCallbackId = undefined;
|
|
85
|
+
this.isSubscribed = false;
|
|
86
|
+
}
|
|
87
|
+
assertIsSubscribed() {
|
|
88
|
+
if (!this.isSubscribed) {
|
|
89
|
+
throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
getHighLeverageModeConfigAccountAndSlot() {
|
|
93
|
+
this.assertIsSubscribed();
|
|
94
|
+
return this.highLeverageModeConfigAccountAndSlot;
|
|
95
|
+
}
|
|
96
|
+
didSubscriptionSucceed() {
|
|
97
|
+
return !!this.highLeverageModeConfigAccountAndSlot;
|
|
98
|
+
}
|
|
99
|
+
updateData(highLeverageModeConfig, slot) {
|
|
100
|
+
if (!this.highLeverageModeConfigAccountAndSlot ||
|
|
101
|
+
this.highLeverageModeConfigAccountAndSlot.slot < slot) {
|
|
102
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
103
|
+
data: highLeverageModeConfig,
|
|
104
|
+
slot,
|
|
105
|
+
};
|
|
106
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', highLeverageModeConfig);
|
|
107
|
+
this.eventEmitter.emit('update');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.PollingHighLeverageModeConfigAccountSubscriber = PollingHighLeverageModeConfigAccountSubscriber;
|
|
@@ -6,7 +6,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
6
6
|
import { EventEmitter } from 'events';
|
|
7
7
|
import { Context, PublicKey } from '@solana/web3.js';
|
|
8
8
|
import { Account } from '@solana/spl-token';
|
|
9
|
-
import { OracleInfo, OraclePriceData } from '..';
|
|
9
|
+
import { HighLeverageModeConfig, OracleInfo, OraclePriceData } from '..';
|
|
10
10
|
import { ChannelOptions, CommitmentLevel } from '../isomorphic/grpc';
|
|
11
11
|
export interface AccountSubscriber<T> {
|
|
12
12
|
dataAndSlot?: DataAndSlot<T>;
|
|
@@ -153,3 +153,16 @@ export type GrpcConfigs = {
|
|
|
153
153
|
commitmentLevel?: CommitmentLevel;
|
|
154
154
|
channelOptions?: ChannelOptions;
|
|
155
155
|
};
|
|
156
|
+
export interface HighLeverageModeConfigAccountSubscriber {
|
|
157
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
158
|
+
isSubscribed: boolean;
|
|
159
|
+
subscribe(highLeverageModeConfigAccount?: HighLeverageModeConfig): Promise<boolean>;
|
|
160
|
+
fetch(): Promise<void>;
|
|
161
|
+
unsubscribe(): Promise<void>;
|
|
162
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
163
|
+
}
|
|
164
|
+
export interface HighLeverageModeConfigAccountEvents {
|
|
165
|
+
highLeverageModeConfigAccountUpdate: (payload: HighLeverageModeConfig) => void;
|
|
166
|
+
update: void;
|
|
167
|
+
error: (e: Error) => void;
|
|
168
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataAndSlot, AccountSubscriber, HighLeverageModeConfigAccountEvents, HighLeverageModeConfigAccountSubscriber } from './types';
|
|
3
|
+
import { Program } from '@coral-xyz/anchor';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
7
|
+
import { HighLeverageModeConfig } from '../types';
|
|
8
|
+
export declare class WebSocketHighLeverageModeConfigAccountSubscriber implements HighLeverageModeConfigAccountSubscriber {
|
|
9
|
+
isSubscribed: boolean;
|
|
10
|
+
resubTimeoutMs?: number;
|
|
11
|
+
commitment?: Commitment;
|
|
12
|
+
program: Program;
|
|
13
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
14
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
15
|
+
highLeverageModeConfigDataAccountSubscriber: AccountSubscriber<HighLeverageModeConfig>;
|
|
16
|
+
constructor(program: Program, highLeverageModeConfigAccountPublicKey: PublicKey, resubTimeoutMs?: number, commitment?: Commitment);
|
|
17
|
+
subscribe(highLeverageModeConfigAccount?: HighLeverageModeConfig): Promise<boolean>;
|
|
18
|
+
fetch(): Promise<void>;
|
|
19
|
+
unsubscribe(): Promise<void>;
|
|
20
|
+
assertIsSubscribed(): void;
|
|
21
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
22
|
+
updateData(highLeverageModeConfig: HighLeverageModeConfig, slot: number): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketHighLeverageModeConfigAccountSubscriber = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
|
|
7
|
+
class WebSocketHighLeverageModeConfigAccountSubscriber {
|
|
8
|
+
constructor(program, highLeverageModeConfigAccountPublicKey, resubTimeoutMs, commitment) {
|
|
9
|
+
this.isSubscribed = false;
|
|
10
|
+
this.program = program;
|
|
11
|
+
this.highLeverageModeConfigAccountPublicKey =
|
|
12
|
+
highLeverageModeConfigAccountPublicKey;
|
|
13
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
14
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
15
|
+
this.commitment = commitment;
|
|
16
|
+
}
|
|
17
|
+
async subscribe(highLeverageModeConfigAccount) {
|
|
18
|
+
if (this.isSubscribed) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
this.highLeverageModeConfigDataAccountSubscriber =
|
|
22
|
+
new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('highLeverageModeConfig', this.program, this.highLeverageModeConfigAccountPublicKey, undefined, {
|
|
23
|
+
resubTimeoutMs: this.resubTimeoutMs,
|
|
24
|
+
}, this.commitment);
|
|
25
|
+
if (highLeverageModeConfigAccount) {
|
|
26
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(highLeverageModeConfigAccount);
|
|
27
|
+
}
|
|
28
|
+
await this.highLeverageModeConfigDataAccountSubscriber.subscribe((data) => {
|
|
29
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', data);
|
|
30
|
+
this.eventEmitter.emit('update');
|
|
31
|
+
});
|
|
32
|
+
this.eventEmitter.emit('update');
|
|
33
|
+
this.isSubscribed = true;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
async fetch() {
|
|
37
|
+
await Promise.all([
|
|
38
|
+
this.highLeverageModeConfigDataAccountSubscriber.fetch(),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
async unsubscribe() {
|
|
42
|
+
if (!this.isSubscribed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await Promise.all([
|
|
46
|
+
this.highLeverageModeConfigDataAccountSubscriber.unsubscribe(),
|
|
47
|
+
]);
|
|
48
|
+
this.isSubscribed = false;
|
|
49
|
+
}
|
|
50
|
+
assertIsSubscribed() {
|
|
51
|
+
if (!this.isSubscribed) {
|
|
52
|
+
throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
getHighLeverageModeConfigAccountAndSlot() {
|
|
56
|
+
this.assertIsSubscribed();
|
|
57
|
+
return this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot;
|
|
58
|
+
}
|
|
59
|
+
updateData(highLeverageModeConfig, slot) {
|
|
60
|
+
var _a;
|
|
61
|
+
const currentDataSlot = ((_a = this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot) === null || _a === void 0 ? void 0 : _a.slot) || 0;
|
|
62
|
+
if (currentDataSlot <= slot) {
|
|
63
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(highLeverageModeConfig, slot);
|
|
64
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', highLeverageModeConfig);
|
|
65
|
+
this.eventEmitter.emit('update');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.WebSocketHighLeverageModeConfigAccountSubscriber = WebSocketHighLeverageModeConfigAccountSubscriber;
|
|
@@ -3880,6 +3880,9 @@ class DriftClient {
|
|
|
3880
3880
|
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
3881
3881
|
const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
3882
3882
|
const createWSOLTokenAccount = isSolMarket && collateralAccountPublicKey.equals(this.wallet.publicKey);
|
|
3883
|
+
// create associated token account because it may not exist
|
|
3884
|
+
const associatedTokenAccountPublicKey = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarketAccount.mint, this.wallet.publicKey, true);
|
|
3885
|
+
addIfStakeIxs.push(await (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(this.wallet.publicKey, associatedTokenAccountPublicKey, this.wallet.publicKey, spotMarketAccount.mint));
|
|
3883
3886
|
let tokenAccount;
|
|
3884
3887
|
if (!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))) {
|
|
3885
3888
|
addIfStakeIxs.push(await this.getInitializeUserStatsIx());
|
package/lib/browser/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './constants/perpMarkets';
|
|
|
10
10
|
export * from './accounts/fetch';
|
|
11
11
|
export * from './accounts/webSocketDriftClientAccountSubscriber';
|
|
12
12
|
export * from './accounts/webSocketInsuranceFundStakeAccountSubscriber';
|
|
13
|
+
export * from './accounts/webSocketHighLeverageModeConfigAccountSubscriber';
|
|
13
14
|
export * from './accounts/bulkAccountLoader';
|
|
14
15
|
export * from './accounts/bulkUserSubscription';
|
|
15
16
|
export * from './accounts/bulkUserStatsSubscription';
|
|
@@ -19,6 +20,7 @@ export * from './accounts/pollingTokenAccountSubscriber';
|
|
|
19
20
|
export * from './accounts/pollingUserAccountSubscriber';
|
|
20
21
|
export * from './accounts/pollingUserStatsAccountSubscriber';
|
|
21
22
|
export * from './accounts/pollingInsuranceFundStakeAccountSubscriber';
|
|
23
|
+
export * from './accounts/pollingHighLeverageModeConfigAccountSubscriber';
|
|
22
24
|
export * from './accounts/basicUserAccountSubscriber';
|
|
23
25
|
export * from './accounts/oneShotUserAccountSubscriber';
|
|
24
26
|
export * from './accounts/types';
|
package/lib/browser/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __exportStar(require("./constants/perpMarkets"), exports);
|
|
|
33
33
|
__exportStar(require("./accounts/fetch"), exports);
|
|
34
34
|
__exportStar(require("./accounts/webSocketDriftClientAccountSubscriber"), exports);
|
|
35
35
|
__exportStar(require("./accounts/webSocketInsuranceFundStakeAccountSubscriber"), exports);
|
|
36
|
+
__exportStar(require("./accounts/webSocketHighLeverageModeConfigAccountSubscriber"), exports);
|
|
36
37
|
__exportStar(require("./accounts/bulkAccountLoader"), exports);
|
|
37
38
|
__exportStar(require("./accounts/bulkUserSubscription"), exports);
|
|
38
39
|
__exportStar(require("./accounts/bulkUserStatsSubscription"), exports);
|
|
@@ -42,6 +43,7 @@ __exportStar(require("./accounts/pollingTokenAccountSubscriber"), exports);
|
|
|
42
43
|
__exportStar(require("./accounts/pollingUserAccountSubscriber"), exports);
|
|
43
44
|
__exportStar(require("./accounts/pollingUserStatsAccountSubscriber"), exports);
|
|
44
45
|
__exportStar(require("./accounts/pollingInsuranceFundStakeAccountSubscriber"), exports);
|
|
46
|
+
__exportStar(require("./accounts/pollingHighLeverageModeConfigAccountSubscriber"), exports);
|
|
45
47
|
__exportStar(require("./accounts/basicUserAccountSubscriber"), exports);
|
|
46
48
|
__exportStar(require("./accounts/oneShotUserAccountSubscriber"), exports);
|
|
47
49
|
__exportStar(require("./accounts/types"), exports);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataAndSlot, HighLeverageModeConfigAccountEvents, HighLeverageModeConfigAccountSubscriber } from './types';
|
|
3
|
+
import { Program } from '@coral-xyz/anchor';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { PublicKey } from '@solana/web3.js';
|
|
7
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
8
|
+
import { HighLeverageModeConfig } from '../types';
|
|
9
|
+
export declare class PollingHighLeverageModeConfigAccountSubscriber implements HighLeverageModeConfigAccountSubscriber {
|
|
10
|
+
isSubscribed: boolean;
|
|
11
|
+
program: Program;
|
|
12
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
13
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
14
|
+
accountLoader: BulkAccountLoader;
|
|
15
|
+
callbackId?: string;
|
|
16
|
+
errorCallbackId?: string;
|
|
17
|
+
highLeverageModeConfigAccountAndSlot?: DataAndSlot<HighLeverageModeConfig>;
|
|
18
|
+
constructor(program: Program, publicKey: PublicKey, accountLoader: BulkAccountLoader);
|
|
19
|
+
subscribe(highLeverageModeConfig?: HighLeverageModeConfig): Promise<boolean>;
|
|
20
|
+
addToAccountLoader(): Promise<void>;
|
|
21
|
+
fetchIfUnloaded(): Promise<void>;
|
|
22
|
+
fetch(): Promise<void>;
|
|
23
|
+
doesAccountExist(): boolean;
|
|
24
|
+
unsubscribe(): Promise<void>;
|
|
25
|
+
assertIsSubscribed(): void;
|
|
26
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
27
|
+
didSubscriptionSucceed(): boolean;
|
|
28
|
+
updateData(highLeverageModeConfig: HighLeverageModeConfig, slot: number): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PollingHighLeverageModeConfigAccountSubscriber = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
class PollingHighLeverageModeConfigAccountSubscriber {
|
|
7
|
+
constructor(program, publicKey, accountLoader) {
|
|
8
|
+
this.isSubscribed = false;
|
|
9
|
+
this.program = program;
|
|
10
|
+
this.highLeverageModeConfigAccountPublicKey = publicKey;
|
|
11
|
+
this.accountLoader = accountLoader;
|
|
12
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
13
|
+
}
|
|
14
|
+
async subscribe(highLeverageModeConfig) {
|
|
15
|
+
if (this.isSubscribed) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (highLeverageModeConfig) {
|
|
19
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
20
|
+
data: highLeverageModeConfig,
|
|
21
|
+
slot: undefined,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
await this.addToAccountLoader();
|
|
25
|
+
await this.fetchIfUnloaded();
|
|
26
|
+
if (this.doesAccountExist()) {
|
|
27
|
+
this.eventEmitter.emit('update');
|
|
28
|
+
}
|
|
29
|
+
this.isSubscribed = true;
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
async addToAccountLoader() {
|
|
33
|
+
if (this.callbackId) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
this.callbackId = await this.accountLoader.addAccount(this.highLeverageModeConfigAccountPublicKey, (buffer, slot) => {
|
|
37
|
+
if (!buffer) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.highLeverageModeConfigAccountAndSlot &&
|
|
41
|
+
this.highLeverageModeConfigAccountAndSlot.slot > slot) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const account = this.program.account.user.coder.accounts.decode('HighLeverageModeConfig', buffer);
|
|
45
|
+
this.highLeverageModeConfigAccountAndSlot = { data: account, slot };
|
|
46
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', account);
|
|
47
|
+
this.eventEmitter.emit('update');
|
|
48
|
+
});
|
|
49
|
+
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
50
|
+
this.eventEmitter.emit('error', error);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
async fetchIfUnloaded() {
|
|
54
|
+
if (this.highLeverageModeConfigAccountAndSlot === undefined) {
|
|
55
|
+
await this.fetch();
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async fetch() {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
try {
|
|
61
|
+
const dataAndContext = await this.program.account.highLeverageModeConfig.fetchAndContext(this.highLeverageModeConfigAccountPublicKey, this.accountLoader.commitment);
|
|
62
|
+
if (dataAndContext.context.slot >
|
|
63
|
+
((_b = (_a = this.highLeverageModeConfigAccountAndSlot) === null || _a === void 0 ? void 0 : _a.slot) !== null && _b !== void 0 ? _b : 0)) {
|
|
64
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
65
|
+
data: dataAndContext.data,
|
|
66
|
+
slot: dataAndContext.context.slot,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
console.log(`PollingHighLeverageModeConfigAccountSubscriber.fetch() HighLeverageModeConfig does not exist: ${e.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
doesAccountExist() {
|
|
75
|
+
return this.highLeverageModeConfigAccountAndSlot !== undefined;
|
|
76
|
+
}
|
|
77
|
+
async unsubscribe() {
|
|
78
|
+
if (!this.isSubscribed) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.accountLoader.removeAccount(this.highLeverageModeConfigAccountPublicKey, this.callbackId);
|
|
82
|
+
this.callbackId = undefined;
|
|
83
|
+
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
84
|
+
this.errorCallbackId = undefined;
|
|
85
|
+
this.isSubscribed = false;
|
|
86
|
+
}
|
|
87
|
+
assertIsSubscribed() {
|
|
88
|
+
if (!this.isSubscribed) {
|
|
89
|
+
throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
getHighLeverageModeConfigAccountAndSlot() {
|
|
93
|
+
this.assertIsSubscribed();
|
|
94
|
+
return this.highLeverageModeConfigAccountAndSlot;
|
|
95
|
+
}
|
|
96
|
+
didSubscriptionSucceed() {
|
|
97
|
+
return !!this.highLeverageModeConfigAccountAndSlot;
|
|
98
|
+
}
|
|
99
|
+
updateData(highLeverageModeConfig, slot) {
|
|
100
|
+
if (!this.highLeverageModeConfigAccountAndSlot ||
|
|
101
|
+
this.highLeverageModeConfigAccountAndSlot.slot < slot) {
|
|
102
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
103
|
+
data: highLeverageModeConfig,
|
|
104
|
+
slot,
|
|
105
|
+
};
|
|
106
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', highLeverageModeConfig);
|
|
107
|
+
this.eventEmitter.emit('update');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.PollingHighLeverageModeConfigAccountSubscriber = PollingHighLeverageModeConfigAccountSubscriber;
|
|
@@ -6,7 +6,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
6
6
|
import { EventEmitter } from 'events';
|
|
7
7
|
import { Context, PublicKey } from '@solana/web3.js';
|
|
8
8
|
import { Account } from '@solana/spl-token';
|
|
9
|
-
import { OracleInfo, OraclePriceData } from '..';
|
|
9
|
+
import { HighLeverageModeConfig, OracleInfo, OraclePriceData } from '..';
|
|
10
10
|
import { ChannelOptions, CommitmentLevel } from '../isomorphic/grpc';
|
|
11
11
|
export interface AccountSubscriber<T> {
|
|
12
12
|
dataAndSlot?: DataAndSlot<T>;
|
|
@@ -153,3 +153,16 @@ export type GrpcConfigs = {
|
|
|
153
153
|
commitmentLevel?: CommitmentLevel;
|
|
154
154
|
channelOptions?: ChannelOptions;
|
|
155
155
|
};
|
|
156
|
+
export interface HighLeverageModeConfigAccountSubscriber {
|
|
157
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
158
|
+
isSubscribed: boolean;
|
|
159
|
+
subscribe(highLeverageModeConfigAccount?: HighLeverageModeConfig): Promise<boolean>;
|
|
160
|
+
fetch(): Promise<void>;
|
|
161
|
+
unsubscribe(): Promise<void>;
|
|
162
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
163
|
+
}
|
|
164
|
+
export interface HighLeverageModeConfigAccountEvents {
|
|
165
|
+
highLeverageModeConfigAccountUpdate: (payload: HighLeverageModeConfig) => void;
|
|
166
|
+
update: void;
|
|
167
|
+
error: (e: Error) => void;
|
|
168
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { DataAndSlot, AccountSubscriber, HighLeverageModeConfigAccountEvents, HighLeverageModeConfigAccountSubscriber } from './types';
|
|
3
|
+
import { Program } from '@coral-xyz/anchor';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
7
|
+
import { HighLeverageModeConfig } from '../types';
|
|
8
|
+
export declare class WebSocketHighLeverageModeConfigAccountSubscriber implements HighLeverageModeConfigAccountSubscriber {
|
|
9
|
+
isSubscribed: boolean;
|
|
10
|
+
resubTimeoutMs?: number;
|
|
11
|
+
commitment?: Commitment;
|
|
12
|
+
program: Program;
|
|
13
|
+
eventEmitter: StrictEventEmitter<EventEmitter, HighLeverageModeConfigAccountEvents>;
|
|
14
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
15
|
+
highLeverageModeConfigDataAccountSubscriber: AccountSubscriber<HighLeverageModeConfig>;
|
|
16
|
+
constructor(program: Program, highLeverageModeConfigAccountPublicKey: PublicKey, resubTimeoutMs?: number, commitment?: Commitment);
|
|
17
|
+
subscribe(highLeverageModeConfigAccount?: HighLeverageModeConfig): Promise<boolean>;
|
|
18
|
+
fetch(): Promise<void>;
|
|
19
|
+
unsubscribe(): Promise<void>;
|
|
20
|
+
assertIsSubscribed(): void;
|
|
21
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
22
|
+
updateData(highLeverageModeConfig: HighLeverageModeConfig, slot: number): void;
|
|
23
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketHighLeverageModeConfigAccountSubscriber = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
const events_1 = require("events");
|
|
6
|
+
const webSocketAccountSubscriber_1 = require("./webSocketAccountSubscriber");
|
|
7
|
+
class WebSocketHighLeverageModeConfigAccountSubscriber {
|
|
8
|
+
constructor(program, highLeverageModeConfigAccountPublicKey, resubTimeoutMs, commitment) {
|
|
9
|
+
this.isSubscribed = false;
|
|
10
|
+
this.program = program;
|
|
11
|
+
this.highLeverageModeConfigAccountPublicKey =
|
|
12
|
+
highLeverageModeConfigAccountPublicKey;
|
|
13
|
+
this.eventEmitter = new events_1.EventEmitter();
|
|
14
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
15
|
+
this.commitment = commitment;
|
|
16
|
+
}
|
|
17
|
+
async subscribe(highLeverageModeConfigAccount) {
|
|
18
|
+
if (this.isSubscribed) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
this.highLeverageModeConfigDataAccountSubscriber =
|
|
22
|
+
new webSocketAccountSubscriber_1.WebSocketAccountSubscriber('highLeverageModeConfig', this.program, this.highLeverageModeConfigAccountPublicKey, undefined, {
|
|
23
|
+
resubTimeoutMs: this.resubTimeoutMs,
|
|
24
|
+
}, this.commitment);
|
|
25
|
+
if (highLeverageModeConfigAccount) {
|
|
26
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(highLeverageModeConfigAccount);
|
|
27
|
+
}
|
|
28
|
+
await this.highLeverageModeConfigDataAccountSubscriber.subscribe((data) => {
|
|
29
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', data);
|
|
30
|
+
this.eventEmitter.emit('update');
|
|
31
|
+
});
|
|
32
|
+
this.eventEmitter.emit('update');
|
|
33
|
+
this.isSubscribed = true;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
async fetch() {
|
|
37
|
+
await Promise.all([
|
|
38
|
+
this.highLeverageModeConfigDataAccountSubscriber.fetch(),
|
|
39
|
+
]);
|
|
40
|
+
}
|
|
41
|
+
async unsubscribe() {
|
|
42
|
+
if (!this.isSubscribed) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await Promise.all([
|
|
46
|
+
this.highLeverageModeConfigDataAccountSubscriber.unsubscribe(),
|
|
47
|
+
]);
|
|
48
|
+
this.isSubscribed = false;
|
|
49
|
+
}
|
|
50
|
+
assertIsSubscribed() {
|
|
51
|
+
if (!this.isSubscribed) {
|
|
52
|
+
throw new types_1.NotSubscribedError('You must call `subscribe` before using this function');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
getHighLeverageModeConfigAccountAndSlot() {
|
|
56
|
+
this.assertIsSubscribed();
|
|
57
|
+
return this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot;
|
|
58
|
+
}
|
|
59
|
+
updateData(highLeverageModeConfig, slot) {
|
|
60
|
+
var _a;
|
|
61
|
+
const currentDataSlot = ((_a = this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot) === null || _a === void 0 ? void 0 : _a.slot) || 0;
|
|
62
|
+
if (currentDataSlot <= slot) {
|
|
63
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(highLeverageModeConfig, slot);
|
|
64
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', highLeverageModeConfig);
|
|
65
|
+
this.eventEmitter.emit('update');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.WebSocketHighLeverageModeConfigAccountSubscriber = WebSocketHighLeverageModeConfigAccountSubscriber;
|
package/lib/node/driftClient.js
CHANGED
|
@@ -3880,6 +3880,9 @@ class DriftClient {
|
|
|
3880
3880
|
const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
|
|
3881
3881
|
const isSolMarket = spotMarketAccount.mint.equals(spotMarkets_1.WRAPPED_SOL_MINT);
|
|
3882
3882
|
const createWSOLTokenAccount = isSolMarket && collateralAccountPublicKey.equals(this.wallet.publicKey);
|
|
3883
|
+
// create associated token account because it may not exist
|
|
3884
|
+
const associatedTokenAccountPublicKey = (0, spl_token_1.getAssociatedTokenAddressSync)(spotMarketAccount.mint, this.wallet.publicKey, true);
|
|
3885
|
+
addIfStakeIxs.push(await (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(this.wallet.publicKey, associatedTokenAccountPublicKey, this.wallet.publicKey, spotMarketAccount.mint));
|
|
3883
3886
|
let tokenAccount;
|
|
3884
3887
|
if (!(await this.checkIfAccountExists(this.getUserStatsAccountPublicKey()))) {
|
|
3885
3888
|
addIfStakeIxs.push(await this.getInitializeUserStatsIx());
|
package/lib/node/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './constants/perpMarkets';
|
|
|
10
10
|
export * from './accounts/fetch';
|
|
11
11
|
export * from './accounts/webSocketDriftClientAccountSubscriber';
|
|
12
12
|
export * from './accounts/webSocketInsuranceFundStakeAccountSubscriber';
|
|
13
|
+
export * from './accounts/webSocketHighLeverageModeConfigAccountSubscriber';
|
|
13
14
|
export * from './accounts/bulkAccountLoader';
|
|
14
15
|
export * from './accounts/bulkUserSubscription';
|
|
15
16
|
export * from './accounts/bulkUserStatsSubscription';
|
|
@@ -19,6 +20,7 @@ export * from './accounts/pollingTokenAccountSubscriber';
|
|
|
19
20
|
export * from './accounts/pollingUserAccountSubscriber';
|
|
20
21
|
export * from './accounts/pollingUserStatsAccountSubscriber';
|
|
21
22
|
export * from './accounts/pollingInsuranceFundStakeAccountSubscriber';
|
|
23
|
+
export * from './accounts/pollingHighLeverageModeConfigAccountSubscriber';
|
|
22
24
|
export * from './accounts/basicUserAccountSubscriber';
|
|
23
25
|
export * from './accounts/oneShotUserAccountSubscriber';
|
|
24
26
|
export * from './accounts/types';
|
package/lib/node/index.js
CHANGED
|
@@ -33,6 +33,7 @@ __exportStar(require("./constants/perpMarkets"), exports);
|
|
|
33
33
|
__exportStar(require("./accounts/fetch"), exports);
|
|
34
34
|
__exportStar(require("./accounts/webSocketDriftClientAccountSubscriber"), exports);
|
|
35
35
|
__exportStar(require("./accounts/webSocketInsuranceFundStakeAccountSubscriber"), exports);
|
|
36
|
+
__exportStar(require("./accounts/webSocketHighLeverageModeConfigAccountSubscriber"), exports);
|
|
36
37
|
__exportStar(require("./accounts/bulkAccountLoader"), exports);
|
|
37
38
|
__exportStar(require("./accounts/bulkUserSubscription"), exports);
|
|
38
39
|
__exportStar(require("./accounts/bulkUserStatsSubscription"), exports);
|
|
@@ -42,6 +43,7 @@ __exportStar(require("./accounts/pollingTokenAccountSubscriber"), exports);
|
|
|
42
43
|
__exportStar(require("./accounts/pollingUserAccountSubscriber"), exports);
|
|
43
44
|
__exportStar(require("./accounts/pollingUserStatsAccountSubscriber"), exports);
|
|
44
45
|
__exportStar(require("./accounts/pollingInsuranceFundStakeAccountSubscriber"), exports);
|
|
46
|
+
__exportStar(require("./accounts/pollingHighLeverageModeConfigAccountSubscriber"), exports);
|
|
45
47
|
__exportStar(require("./accounts/basicUserAccountSubscriber"), exports);
|
|
46
48
|
__exportStar(require("./accounts/oneShotUserAccountSubscriber"), exports);
|
|
47
49
|
__exportStar(require("./accounts/types"), exports);
|
package/package.json
CHANGED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataAndSlot,
|
|
3
|
+
NotSubscribedError,
|
|
4
|
+
HighLeverageModeConfigAccountEvents,
|
|
5
|
+
HighLeverageModeConfigAccountSubscriber,
|
|
6
|
+
} from './types';
|
|
7
|
+
import { Program } from '@coral-xyz/anchor';
|
|
8
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
9
|
+
import { EventEmitter } from 'events';
|
|
10
|
+
import { PublicKey } from '@solana/web3.js';
|
|
11
|
+
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
12
|
+
import { HighLeverageModeConfig } from '../types';
|
|
13
|
+
|
|
14
|
+
export class PollingHighLeverageModeConfigAccountSubscriber
|
|
15
|
+
implements HighLeverageModeConfigAccountSubscriber
|
|
16
|
+
{
|
|
17
|
+
isSubscribed: boolean;
|
|
18
|
+
program: Program;
|
|
19
|
+
eventEmitter: StrictEventEmitter<
|
|
20
|
+
EventEmitter,
|
|
21
|
+
HighLeverageModeConfigAccountEvents
|
|
22
|
+
>;
|
|
23
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
24
|
+
|
|
25
|
+
accountLoader: BulkAccountLoader;
|
|
26
|
+
callbackId?: string;
|
|
27
|
+
errorCallbackId?: string;
|
|
28
|
+
|
|
29
|
+
highLeverageModeConfigAccountAndSlot?: DataAndSlot<HighLeverageModeConfig>;
|
|
30
|
+
|
|
31
|
+
public constructor(
|
|
32
|
+
program: Program,
|
|
33
|
+
publicKey: PublicKey,
|
|
34
|
+
accountLoader: BulkAccountLoader
|
|
35
|
+
) {
|
|
36
|
+
this.isSubscribed = false;
|
|
37
|
+
this.program = program;
|
|
38
|
+
this.highLeverageModeConfigAccountPublicKey = publicKey;
|
|
39
|
+
this.accountLoader = accountLoader;
|
|
40
|
+
this.eventEmitter = new EventEmitter();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async subscribe(
|
|
44
|
+
highLeverageModeConfig?: HighLeverageModeConfig
|
|
45
|
+
): Promise<boolean> {
|
|
46
|
+
if (this.isSubscribed) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (highLeverageModeConfig) {
|
|
51
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
52
|
+
data: highLeverageModeConfig,
|
|
53
|
+
slot: undefined,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
await this.addToAccountLoader();
|
|
58
|
+
|
|
59
|
+
await this.fetchIfUnloaded();
|
|
60
|
+
|
|
61
|
+
if (this.doesAccountExist()) {
|
|
62
|
+
this.eventEmitter.emit('update');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
this.isSubscribed = true;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async addToAccountLoader(): Promise<void> {
|
|
70
|
+
if (this.callbackId) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
this.callbackId = await this.accountLoader.addAccount(
|
|
75
|
+
this.highLeverageModeConfigAccountPublicKey,
|
|
76
|
+
(buffer, slot: number) => {
|
|
77
|
+
if (!buffer) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (
|
|
82
|
+
this.highLeverageModeConfigAccountAndSlot &&
|
|
83
|
+
this.highLeverageModeConfigAccountAndSlot.slot > slot
|
|
84
|
+
) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const account = this.program.account.user.coder.accounts.decode(
|
|
89
|
+
'HighLeverageModeConfig',
|
|
90
|
+
buffer
|
|
91
|
+
);
|
|
92
|
+
this.highLeverageModeConfigAccountAndSlot = { data: account, slot };
|
|
93
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', account);
|
|
94
|
+
this.eventEmitter.emit('update');
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
99
|
+
this.eventEmitter.emit('error', error);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async fetchIfUnloaded(): Promise<void> {
|
|
104
|
+
if (this.highLeverageModeConfigAccountAndSlot === undefined) {
|
|
105
|
+
await this.fetch();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async fetch(): Promise<void> {
|
|
110
|
+
try {
|
|
111
|
+
const dataAndContext =
|
|
112
|
+
await this.program.account.highLeverageModeConfig.fetchAndContext(
|
|
113
|
+
this.highLeverageModeConfigAccountPublicKey,
|
|
114
|
+
this.accountLoader.commitment
|
|
115
|
+
);
|
|
116
|
+
if (
|
|
117
|
+
dataAndContext.context.slot >
|
|
118
|
+
(this.highLeverageModeConfigAccountAndSlot?.slot ?? 0)
|
|
119
|
+
) {
|
|
120
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
121
|
+
data: dataAndContext.data as HighLeverageModeConfig,
|
|
122
|
+
slot: dataAndContext.context.slot,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
} catch (e) {
|
|
126
|
+
console.log(
|
|
127
|
+
`PollingHighLeverageModeConfigAccountSubscriber.fetch() HighLeverageModeConfig does not exist: ${e.message}`
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
doesAccountExist(): boolean {
|
|
133
|
+
return this.highLeverageModeConfigAccountAndSlot !== undefined;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async unsubscribe(): Promise<void> {
|
|
137
|
+
if (!this.isSubscribed) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
this.accountLoader.removeAccount(
|
|
142
|
+
this.highLeverageModeConfigAccountPublicKey,
|
|
143
|
+
this.callbackId
|
|
144
|
+
);
|
|
145
|
+
this.callbackId = undefined;
|
|
146
|
+
|
|
147
|
+
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
148
|
+
this.errorCallbackId = undefined;
|
|
149
|
+
|
|
150
|
+
this.isSubscribed = false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
assertIsSubscribed(): void {
|
|
154
|
+
if (!this.isSubscribed) {
|
|
155
|
+
throw new NotSubscribedError(
|
|
156
|
+
'You must call `subscribe` before using this function'
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
public getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig> {
|
|
162
|
+
this.assertIsSubscribed();
|
|
163
|
+
return this.highLeverageModeConfigAccountAndSlot;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
didSubscriptionSucceed(): boolean {
|
|
167
|
+
return !!this.highLeverageModeConfigAccountAndSlot;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
public updateData(
|
|
171
|
+
highLeverageModeConfig: HighLeverageModeConfig,
|
|
172
|
+
slot: number
|
|
173
|
+
): void {
|
|
174
|
+
if (
|
|
175
|
+
!this.highLeverageModeConfigAccountAndSlot ||
|
|
176
|
+
this.highLeverageModeConfigAccountAndSlot.slot < slot
|
|
177
|
+
) {
|
|
178
|
+
this.highLeverageModeConfigAccountAndSlot = {
|
|
179
|
+
data: highLeverageModeConfig,
|
|
180
|
+
slot,
|
|
181
|
+
};
|
|
182
|
+
this.eventEmitter.emit(
|
|
183
|
+
'highLeverageModeConfigAccountUpdate',
|
|
184
|
+
highLeverageModeConfig
|
|
185
|
+
);
|
|
186
|
+
this.eventEmitter.emit('update');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
package/src/accounts/types.ts
CHANGED
|
@@ -11,7 +11,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
12
|
import { Context, PublicKey } from '@solana/web3.js';
|
|
13
13
|
import { Account } from '@solana/spl-token';
|
|
14
|
-
import { OracleInfo, OraclePriceData } from '..';
|
|
14
|
+
import { HighLeverageModeConfig, OracleInfo, OraclePriceData } from '..';
|
|
15
15
|
import { ChannelOptions, CommitmentLevel } from '../isomorphic/grpc';
|
|
16
16
|
|
|
17
17
|
export interface AccountSubscriber<T> {
|
|
@@ -215,3 +215,27 @@ export type GrpcConfigs = {
|
|
|
215
215
|
commitmentLevel?: CommitmentLevel;
|
|
216
216
|
channelOptions?: ChannelOptions;
|
|
217
217
|
};
|
|
218
|
+
|
|
219
|
+
export interface HighLeverageModeConfigAccountSubscriber {
|
|
220
|
+
eventEmitter: StrictEventEmitter<
|
|
221
|
+
EventEmitter,
|
|
222
|
+
HighLeverageModeConfigAccountEvents
|
|
223
|
+
>;
|
|
224
|
+
isSubscribed: boolean;
|
|
225
|
+
|
|
226
|
+
subscribe(
|
|
227
|
+
highLeverageModeConfigAccount?: HighLeverageModeConfig
|
|
228
|
+
): Promise<boolean>;
|
|
229
|
+
fetch(): Promise<void>;
|
|
230
|
+
unsubscribe(): Promise<void>;
|
|
231
|
+
|
|
232
|
+
getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig>;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export interface HighLeverageModeConfigAccountEvents {
|
|
236
|
+
highLeverageModeConfigAccountUpdate: (
|
|
237
|
+
payload: HighLeverageModeConfig
|
|
238
|
+
) => void;
|
|
239
|
+
update: void;
|
|
240
|
+
error: (e: Error) => void;
|
|
241
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataAndSlot,
|
|
3
|
+
AccountSubscriber,
|
|
4
|
+
NotSubscribedError,
|
|
5
|
+
HighLeverageModeConfigAccountEvents,
|
|
6
|
+
HighLeverageModeConfigAccountSubscriber,
|
|
7
|
+
} from './types';
|
|
8
|
+
import { Program } from '@coral-xyz/anchor';
|
|
9
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
import { Commitment, PublicKey } from '@solana/web3.js';
|
|
12
|
+
import { WebSocketAccountSubscriber } from './webSocketAccountSubscriber';
|
|
13
|
+
import { HighLeverageModeConfig } from '../types';
|
|
14
|
+
|
|
15
|
+
export class WebSocketHighLeverageModeConfigAccountSubscriber
|
|
16
|
+
implements HighLeverageModeConfigAccountSubscriber
|
|
17
|
+
{
|
|
18
|
+
isSubscribed: boolean;
|
|
19
|
+
resubTimeoutMs?: number;
|
|
20
|
+
commitment?: Commitment;
|
|
21
|
+
program: Program;
|
|
22
|
+
eventEmitter: StrictEventEmitter<
|
|
23
|
+
EventEmitter,
|
|
24
|
+
HighLeverageModeConfigAccountEvents
|
|
25
|
+
>;
|
|
26
|
+
highLeverageModeConfigAccountPublicKey: PublicKey;
|
|
27
|
+
|
|
28
|
+
highLeverageModeConfigDataAccountSubscriber: AccountSubscriber<HighLeverageModeConfig>;
|
|
29
|
+
|
|
30
|
+
public constructor(
|
|
31
|
+
program: Program,
|
|
32
|
+
highLeverageModeConfigAccountPublicKey: PublicKey,
|
|
33
|
+
resubTimeoutMs?: number,
|
|
34
|
+
commitment?: Commitment
|
|
35
|
+
) {
|
|
36
|
+
this.isSubscribed = false;
|
|
37
|
+
this.program = program;
|
|
38
|
+
this.highLeverageModeConfigAccountPublicKey =
|
|
39
|
+
highLeverageModeConfigAccountPublicKey;
|
|
40
|
+
this.eventEmitter = new EventEmitter();
|
|
41
|
+
this.resubTimeoutMs = resubTimeoutMs;
|
|
42
|
+
this.commitment = commitment;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async subscribe(
|
|
46
|
+
highLeverageModeConfigAccount?: HighLeverageModeConfig
|
|
47
|
+
): Promise<boolean> {
|
|
48
|
+
if (this.isSubscribed) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.highLeverageModeConfigDataAccountSubscriber =
|
|
53
|
+
new WebSocketAccountSubscriber(
|
|
54
|
+
'highLeverageModeConfig',
|
|
55
|
+
this.program,
|
|
56
|
+
this.highLeverageModeConfigAccountPublicKey,
|
|
57
|
+
undefined,
|
|
58
|
+
{
|
|
59
|
+
resubTimeoutMs: this.resubTimeoutMs,
|
|
60
|
+
},
|
|
61
|
+
this.commitment
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
if (highLeverageModeConfigAccount) {
|
|
65
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(
|
|
66
|
+
highLeverageModeConfigAccount
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await this.highLeverageModeConfigDataAccountSubscriber.subscribe(
|
|
71
|
+
(data: HighLeverageModeConfig) => {
|
|
72
|
+
this.eventEmitter.emit('highLeverageModeConfigAccountUpdate', data);
|
|
73
|
+
this.eventEmitter.emit('update');
|
|
74
|
+
}
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
this.eventEmitter.emit('update');
|
|
78
|
+
this.isSubscribed = true;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async fetch(): Promise<void> {
|
|
83
|
+
await Promise.all([
|
|
84
|
+
this.highLeverageModeConfigDataAccountSubscriber.fetch(),
|
|
85
|
+
]);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async unsubscribe(): Promise<void> {
|
|
89
|
+
if (!this.isSubscribed) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
await Promise.all([
|
|
94
|
+
this.highLeverageModeConfigDataAccountSubscriber.unsubscribe(),
|
|
95
|
+
]);
|
|
96
|
+
|
|
97
|
+
this.isSubscribed = false;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
assertIsSubscribed(): void {
|
|
101
|
+
if (!this.isSubscribed) {
|
|
102
|
+
throw new NotSubscribedError(
|
|
103
|
+
'You must call `subscribe` before using this function'
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public getHighLeverageModeConfigAccountAndSlot(): DataAndSlot<HighLeverageModeConfig> {
|
|
109
|
+
this.assertIsSubscribed();
|
|
110
|
+
return this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public updateData(
|
|
114
|
+
highLeverageModeConfig: HighLeverageModeConfig,
|
|
115
|
+
slot: number
|
|
116
|
+
): void {
|
|
117
|
+
const currentDataSlot =
|
|
118
|
+
this.highLeverageModeConfigDataAccountSubscriber.dataAndSlot?.slot || 0;
|
|
119
|
+
if (currentDataSlot <= slot) {
|
|
120
|
+
this.highLeverageModeConfigDataAccountSubscriber.setData(
|
|
121
|
+
highLeverageModeConfig,
|
|
122
|
+
slot
|
|
123
|
+
);
|
|
124
|
+
this.eventEmitter.emit(
|
|
125
|
+
'highLeverageModeConfigAccountUpdate',
|
|
126
|
+
highLeverageModeConfig
|
|
127
|
+
);
|
|
128
|
+
this.eventEmitter.emit('update');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
package/src/driftClient.ts
CHANGED
|
@@ -11,11 +11,13 @@ import bs58 from 'bs58';
|
|
|
11
11
|
import {
|
|
12
12
|
ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
13
13
|
createAssociatedTokenAccountInstruction,
|
|
14
|
+
createAssociatedTokenAccountIdempotentInstruction,
|
|
14
15
|
createCloseAccountInstruction,
|
|
15
16
|
createInitializeAccountInstruction,
|
|
16
17
|
getAssociatedTokenAddress,
|
|
17
18
|
TOKEN_2022_PROGRAM_ID,
|
|
18
19
|
TOKEN_PROGRAM_ID,
|
|
20
|
+
getAssociatedTokenAddressSync,
|
|
19
21
|
} from '@solana/spl-token';
|
|
20
22
|
import {
|
|
21
23
|
DriftClientMetricsEvents,
|
|
@@ -7407,6 +7409,22 @@ export class DriftClient {
|
|
|
7407
7409
|
const createWSOLTokenAccount =
|
|
7408
7410
|
isSolMarket && collateralAccountPublicKey.equals(this.wallet.publicKey);
|
|
7409
7411
|
|
|
7412
|
+
// create associated token account because it may not exist
|
|
7413
|
+
const associatedTokenAccountPublicKey = getAssociatedTokenAddressSync(
|
|
7414
|
+
spotMarketAccount.mint,
|
|
7415
|
+
this.wallet.publicKey,
|
|
7416
|
+
true
|
|
7417
|
+
);
|
|
7418
|
+
|
|
7419
|
+
addIfStakeIxs.push(
|
|
7420
|
+
await createAssociatedTokenAccountIdempotentInstruction(
|
|
7421
|
+
this.wallet.publicKey,
|
|
7422
|
+
associatedTokenAccountPublicKey,
|
|
7423
|
+
this.wallet.publicKey,
|
|
7424
|
+
spotMarketAccount.mint
|
|
7425
|
+
)
|
|
7426
|
+
);
|
|
7427
|
+
|
|
7410
7428
|
let tokenAccount;
|
|
7411
7429
|
|
|
7412
7430
|
if (
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './constants/perpMarkets';
|
|
|
11
11
|
export * from './accounts/fetch';
|
|
12
12
|
export * from './accounts/webSocketDriftClientAccountSubscriber';
|
|
13
13
|
export * from './accounts/webSocketInsuranceFundStakeAccountSubscriber';
|
|
14
|
+
export * from './accounts/webSocketHighLeverageModeConfigAccountSubscriber';
|
|
14
15
|
export * from './accounts/bulkAccountLoader';
|
|
15
16
|
export * from './accounts/bulkUserSubscription';
|
|
16
17
|
export * from './accounts/bulkUserStatsSubscription';
|
|
@@ -20,6 +21,7 @@ export * from './accounts/pollingTokenAccountSubscriber';
|
|
|
20
21
|
export * from './accounts/pollingUserAccountSubscriber';
|
|
21
22
|
export * from './accounts/pollingUserStatsAccountSubscriber';
|
|
22
23
|
export * from './accounts/pollingInsuranceFundStakeAccountSubscriber';
|
|
24
|
+
export * from './accounts/pollingHighLeverageModeConfigAccountSubscriber';
|
|
23
25
|
export * from './accounts/basicUserAccountSubscriber';
|
|
24
26
|
export * from './accounts/oneShotUserAccountSubscriber';
|
|
25
27
|
export * from './accounts/types';
|