@drift-labs/sdk 2.31.0-beta.2 → 2.31.0-beta.5
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/get_events.ts +47 -0
- package/lib/auctionSubscriber/auctionSubscriber.d.ts +13 -0
- package/lib/auctionSubscriber/auctionSubscriber.js +22 -0
- package/lib/auctionSubscriber/index.d.ts +2 -0
- package/lib/auctionSubscriber/index.js +18 -0
- package/lib/auctionSubscriber/types.d.ts +10 -0
- package/lib/auctionSubscriber/types.js +2 -0
- package/lib/config.js +2 -2
- package/lib/dlob/orderBookLevels.d.ts +1 -1
- package/lib/dlob/orderBookLevels.js +7 -4
- package/lib/driftClient.d.ts +2 -0
- package/lib/driftClient.js +22 -9
- package/lib/events/eventSubscriber.d.ts +1 -0
- package/lib/events/eventSubscriber.js +5 -3
- package/lib/events/fetchLogs.d.ts +1 -1
- package/lib/events/fetchLogs.js +2 -2
- package/lib/events/pollingLogProvider.d.ts +2 -2
- package/lib/events/pollingLogProvider.js +3 -3
- package/lib/events/types.d.ts +2 -1
- package/lib/events/webSocketLogProvider.d.ts +2 -2
- package/lib/events/webSocketLogProvider.js +3 -3
- package/lib/idl/drift.json +61 -2
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/spotBalance.js +1 -1
- package/lib/memcmp.d.ts +6 -0
- package/lib/memcmp.js +53 -0
- package/lib/orderSubscriber/OrderSubscriber.d.ts +24 -0
- package/lib/orderSubscriber/OrderSubscriber.js +100 -0
- package/lib/orderSubscriber/PollingSubscription.d.ts +13 -0
- package/lib/orderSubscriber/PollingSubscription.js +23 -0
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +12 -0
- package/lib/orderSubscriber/WebsocketSubscription.js +30 -0
- package/lib/orderSubscriber/index.d.ts +2 -0
- package/lib/orderSubscriber/index.js +18 -0
- package/lib/orderSubscriber/types.d.ts +11 -0
- package/lib/orderSubscriber/types.js +2 -0
- package/lib/tx/retryTxSender.js +5 -2
- package/lib/types.d.ts +5 -1
- package/lib/types.js +1 -1
- package/lib/userMap/userMap.js +4 -19
- package/package.json +1 -1
- package/src/auctionSubscriber/auctionSubscriber.ts +50 -0
- package/src/auctionSubscriber/index.ts +2 -0
- package/src/auctionSubscriber/types.ts +16 -0
- package/src/config.ts +6 -3
- package/src/dlob/orderBookLevels.ts +13 -4
- package/src/driftClient.ts +41 -10
- package/src/events/eventSubscriber.ts +6 -4
- package/src/events/fetchLogs.ts +2 -2
- package/src/events/pollingLogProvider.ts +2 -2
- package/src/events/types.ts +2 -1
- package/src/events/webSocketLogProvider.ts +2 -2
- package/src/idl/drift.json +61 -2
- package/src/index.ts +1 -0
- package/src/math/spotBalance.ts +1 -3
- package/src/memcmp.ts +48 -0
- package/src/orderSubscriber/OrderSubscriber.ts +132 -0
- package/src/orderSubscriber/PollingSubscription.ts +39 -0
- package/src/orderSubscriber/WebsocketSubscription.ts +54 -0
- package/src/orderSubscriber/index.ts +2 -0
- package/src/orderSubscriber/types.ts +14 -0
- package/src/tx/retryTxSender.ts +8 -2
- package/src/types.ts +5 -1
- package/src/userMap/userMap.ts +4 -16
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OrderSubscriber = void 0;
|
|
4
|
+
const memcmp_1 = require("../memcmp");
|
|
5
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
6
|
+
const buffer_1 = require("buffer");
|
|
7
|
+
const DLOB_1 = require("../dlob/DLOB");
|
|
8
|
+
const PollingSubscription_1 = require("./PollingSubscription");
|
|
9
|
+
const WebsocketSubscription_1 = require("./WebsocketSubscription");
|
|
10
|
+
class OrderSubscriber {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.usersAccounts = new Map();
|
|
13
|
+
this.driftClient = config.driftClient;
|
|
14
|
+
if (config.subscriptionConfig.type === 'polling') {
|
|
15
|
+
this.subscription = new PollingSubscription_1.PollingSubscription({
|
|
16
|
+
orderSubscriber: this,
|
|
17
|
+
frequency: config.subscriptionConfig.frequency,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.subscription = new WebsocketSubscription_1.WebsocketSubscription({
|
|
22
|
+
orderSubscriber: this,
|
|
23
|
+
skipInitialLoad: config.subscriptionConfig.skipInitialLoad,
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async subscribe() {
|
|
28
|
+
await this.subscription.subscribe();
|
|
29
|
+
}
|
|
30
|
+
async fetch() {
|
|
31
|
+
if (this.fetchPromise) {
|
|
32
|
+
return this.fetchPromise;
|
|
33
|
+
}
|
|
34
|
+
this.fetchPromise = new Promise((resolver) => {
|
|
35
|
+
this.fetchPromiseResolver = resolver;
|
|
36
|
+
});
|
|
37
|
+
try {
|
|
38
|
+
const rpcRequestArgs = [
|
|
39
|
+
this.driftClient.program.programId.toBase58(),
|
|
40
|
+
{
|
|
41
|
+
commitment: this.driftClient.opts.commitment,
|
|
42
|
+
filters: [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getUserWithOrderFilter)()],
|
|
43
|
+
encoding: 'base64',
|
|
44
|
+
withContext: true,
|
|
45
|
+
},
|
|
46
|
+
];
|
|
47
|
+
const rpcJSONResponse =
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
await this.driftClient.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
|
|
50
|
+
const rpcResponseAndContext = rpcJSONResponse.result;
|
|
51
|
+
const slot = rpcResponseAndContext.context.slot;
|
|
52
|
+
const programAccountSet = new Set();
|
|
53
|
+
for (const programAccount of rpcResponseAndContext.value) {
|
|
54
|
+
const key = programAccount.pubkey.toString();
|
|
55
|
+
// @ts-ignore
|
|
56
|
+
const buffer = buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]);
|
|
57
|
+
programAccountSet.add(key);
|
|
58
|
+
this.tryUpdateUserAccount(key, buffer, slot);
|
|
59
|
+
}
|
|
60
|
+
for (const key of this.usersAccounts.keys()) {
|
|
61
|
+
if (!programAccountSet.has(key)) {
|
|
62
|
+
this.usersAccounts.delete(key);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
console.error(e);
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
this.fetchPromiseResolver();
|
|
71
|
+
this.fetchPromise = undefined;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
tryUpdateUserAccount(key, buffer, slot) {
|
|
75
|
+
const slotAndUserAccount = this.usersAccounts.get(key);
|
|
76
|
+
if (!slotAndUserAccount || slotAndUserAccount.slot < slot) {
|
|
77
|
+
const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
|
|
78
|
+
if (userAccount.hasOpenOrder) {
|
|
79
|
+
this.usersAccounts.set(key, { slot, userAccount });
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
this.usersAccounts.delete(key);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async getDLOB(slot) {
|
|
87
|
+
const dlob = new DLOB_1.DLOB();
|
|
88
|
+
for (const [key, { userAccount }] of this.usersAccounts.entries()) {
|
|
89
|
+
const userAccountPubkey = new web3_js_1.PublicKey(key);
|
|
90
|
+
for (const order of userAccount.orders) {
|
|
91
|
+
dlob.insertOrder(order, userAccountPubkey, slot);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return dlob;
|
|
95
|
+
}
|
|
96
|
+
async unsubscribe() {
|
|
97
|
+
await this.subscription.unsubscribe();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.OrderSubscriber = OrderSubscriber;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { OrderSubscriber } from './OrderSubscriber';
|
|
3
|
+
export declare class PollingSubscription {
|
|
4
|
+
private orderSubscriber;
|
|
5
|
+
private frequency;
|
|
6
|
+
intervalId?: NodeJS.Timer;
|
|
7
|
+
constructor({ orderSubscriber, frequency, }: {
|
|
8
|
+
orderSubscriber: OrderSubscriber;
|
|
9
|
+
frequency: number;
|
|
10
|
+
});
|
|
11
|
+
subscribe(): Promise<void>;
|
|
12
|
+
unsubscribe(): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PollingSubscription = void 0;
|
|
4
|
+
class PollingSubscription {
|
|
5
|
+
constructor({ orderSubscriber, frequency, }) {
|
|
6
|
+
this.orderSubscriber = orderSubscriber;
|
|
7
|
+
this.frequency = frequency;
|
|
8
|
+
}
|
|
9
|
+
async subscribe() {
|
|
10
|
+
if (this.intervalId) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
this.intervalId = setInterval(this.orderSubscriber.fetch.bind(this.orderSubscriber), this.frequency);
|
|
14
|
+
await this.orderSubscriber.fetch();
|
|
15
|
+
}
|
|
16
|
+
async unsubscribe() {
|
|
17
|
+
if (this.intervalId) {
|
|
18
|
+
clearInterval(this.intervalId);
|
|
19
|
+
this.intervalId = undefined;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.PollingSubscription = PollingSubscription;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { OrderSubscriber } from './OrderSubscriber';
|
|
2
|
+
export declare class WebsocketSubscription {
|
|
3
|
+
private orderSubscriber;
|
|
4
|
+
private skipInitialLoad;
|
|
5
|
+
private websocketId;
|
|
6
|
+
constructor({ orderSubscriber, skipInitialLoad, }: {
|
|
7
|
+
orderSubscriber: OrderSubscriber;
|
|
8
|
+
skipInitialLoad?: boolean;
|
|
9
|
+
});
|
|
10
|
+
subscribe(): Promise<void>;
|
|
11
|
+
unsubscribe(): Promise<void>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebsocketSubscription = void 0;
|
|
4
|
+
const memcmp_1 = require("../memcmp");
|
|
5
|
+
class WebsocketSubscription {
|
|
6
|
+
constructor({ orderSubscriber, skipInitialLoad = false, }) {
|
|
7
|
+
this.orderSubscriber = orderSubscriber;
|
|
8
|
+
this.skipInitialLoad = skipInitialLoad;
|
|
9
|
+
}
|
|
10
|
+
async subscribe() {
|
|
11
|
+
if (this.websocketId) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
this.websocketId =
|
|
15
|
+
this.orderSubscriber.driftClient.connection.onProgramAccountChange(this.orderSubscriber.driftClient.program.programId, (keyAccountInfo, context) => {
|
|
16
|
+
const userKey = keyAccountInfo.accountId.toBase58();
|
|
17
|
+
this.orderSubscriber.tryUpdateUserAccount(userKey, keyAccountInfo.accountInfo.data, context.slot);
|
|
18
|
+
}, this.orderSubscriber.driftClient.opts.commitment, [(0, memcmp_1.getUserFilter)(), (0, memcmp_1.getNonIdleUserFilter)()]);
|
|
19
|
+
if (!this.skipInitialLoad) {
|
|
20
|
+
await this.orderSubscriber.fetch();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async unsubscribe() {
|
|
24
|
+
if (this.websocketId) {
|
|
25
|
+
await this.orderSubscriber.driftClient.connection.removeProgramAccountChangeListener(this.websocketId);
|
|
26
|
+
this.websocketId = undefined;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.WebsocketSubscription = WebsocketSubscription;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./OrderSubscriber"), exports);
|
|
18
|
+
__exportStar(require("./types"), exports);
|
package/lib/tx/retryTxSender.js
CHANGED
|
@@ -55,12 +55,15 @@ class RetryTxSender {
|
|
|
55
55
|
return tx;
|
|
56
56
|
}
|
|
57
57
|
async sendVersionedTransaction(tx, additionalSigners, opts) {
|
|
58
|
+
additionalSigners === null || additionalSigners === void 0 ? void 0 : additionalSigners.filter((s) => s !== undefined).forEach((kp) => {
|
|
59
|
+
tx.sign([kp]);
|
|
60
|
+
});
|
|
58
61
|
// @ts-ignore
|
|
59
|
-
|
|
62
|
+
const signedTx = await this.provider.wallet.signTransaction(tx);
|
|
60
63
|
if (opts === undefined) {
|
|
61
64
|
opts = this.provider.opts;
|
|
62
65
|
}
|
|
63
|
-
return this.sendRawTransaction(
|
|
66
|
+
return this.sendRawTransaction(signedTx.serialize(), opts);
|
|
64
67
|
}
|
|
65
68
|
async sendRawTransaction(rawTransaction, opts) {
|
|
66
69
|
const startTime = this.getTimestamp();
|
package/lib/types.d.ts
CHANGED
|
@@ -222,7 +222,7 @@ export declare class OrderActionExplanation {
|
|
|
222
222
|
orderFilledWithAmmJitLpSplit: {};
|
|
223
223
|
};
|
|
224
224
|
static readonly ORDER_FILLED_WITH_LP_JIT: {
|
|
225
|
-
|
|
225
|
+
orderFilledWithLpJit: {};
|
|
226
226
|
};
|
|
227
227
|
static readonly ORDER_FILLED_WITH_MATCH: {
|
|
228
228
|
orderFilledWithMatch: {};
|
|
@@ -877,6 +877,10 @@ export type UserAccount = {
|
|
|
877
877
|
lastActiveSlot: BN;
|
|
878
878
|
isMarginTradingEnabled: boolean;
|
|
879
879
|
idle: boolean;
|
|
880
|
+
openOrders: number;
|
|
881
|
+
hasOpenOrder: boolean;
|
|
882
|
+
openAuctions: number;
|
|
883
|
+
hasOpenAuction: boolean;
|
|
880
884
|
};
|
|
881
885
|
export type SpotPosition = {
|
|
882
886
|
marketIndex: number;
|
package/lib/types.js
CHANGED
|
@@ -138,7 +138,7 @@ OrderActionExplanation.ORDER_FILLED_WITH_AMM_JIT_LP_SPLIT = {
|
|
|
138
138
|
orderFilledWithAmmJitLpSplit: {},
|
|
139
139
|
};
|
|
140
140
|
OrderActionExplanation.ORDER_FILLED_WITH_LP_JIT = {
|
|
141
|
-
|
|
141
|
+
orderFilledWithLpJit: {},
|
|
142
142
|
};
|
|
143
143
|
OrderActionExplanation.ORDER_FILLED_WITH_MATCH = {
|
|
144
144
|
orderFilledWithMatch: {},
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.UserMap = void 0;
|
|
7
4
|
const __1 = require("..");
|
|
8
5
|
const web3_js_1 = require("@solana/web3.js");
|
|
9
6
|
const buffer_1 = require("buffer");
|
|
10
|
-
const
|
|
7
|
+
const memcmp_1 = require("../memcmp");
|
|
11
8
|
class UserMap {
|
|
12
9
|
/**
|
|
13
10
|
*
|
|
@@ -143,27 +140,15 @@ class UserMap {
|
|
|
143
140
|
return this.userMap.size;
|
|
144
141
|
}
|
|
145
142
|
async sync() {
|
|
146
|
-
|
|
143
|
+
const filters = [(0, memcmp_1.getUserFilter)()];
|
|
147
144
|
if (!this.includeIdle) {
|
|
148
|
-
filters
|
|
149
|
-
{
|
|
150
|
-
memcmp: {
|
|
151
|
-
offset: 4350,
|
|
152
|
-
bytes: bs58_1.default.encode(Uint8Array.from([0])),
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
];
|
|
145
|
+
filters.push((0, memcmp_1.getNonIdleUserFilter)());
|
|
156
146
|
}
|
|
157
147
|
const rpcRequestArgs = [
|
|
158
148
|
this.driftClient.program.programId.toBase58(),
|
|
159
149
|
{
|
|
160
150
|
commitment: this.driftClient.connection.commitment,
|
|
161
|
-
filters
|
|
162
|
-
{
|
|
163
|
-
memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
|
|
164
|
-
},
|
|
165
|
-
...(Array.isArray(filters) ? filters : []),
|
|
166
|
-
],
|
|
151
|
+
filters,
|
|
167
152
|
encoding: 'base64',
|
|
168
153
|
withContext: true,
|
|
169
154
|
},
|
package/package.json
CHANGED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AuctionSubscriberConfig, AuctionSubscriberEvents } from './types';
|
|
2
|
+
import { DriftClient } from '../driftClient';
|
|
3
|
+
import { getUserFilter, getUserWithAuctionFilter } from '../memcmp';
|
|
4
|
+
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
5
|
+
import { EventEmitter } from 'events';
|
|
6
|
+
import { UserAccount } from '../types';
|
|
7
|
+
import { ConfirmOptions } from '@solana/web3.js';
|
|
8
|
+
|
|
9
|
+
export class AuctionSubscriber {
|
|
10
|
+
private driftClient: DriftClient;
|
|
11
|
+
private opts: ConfirmOptions;
|
|
12
|
+
|
|
13
|
+
eventEmitter: StrictEventEmitter<EventEmitter, AuctionSubscriberEvents>;
|
|
14
|
+
|
|
15
|
+
private websocketId: number;
|
|
16
|
+
|
|
17
|
+
constructor({ driftClient, opts }: AuctionSubscriberConfig) {
|
|
18
|
+
this.driftClient = driftClient;
|
|
19
|
+
this.opts = opts || this.driftClient.opts;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
public async subscribe() {
|
|
23
|
+
this.websocketId = this.driftClient.connection.onProgramAccountChange(
|
|
24
|
+
this.driftClient.program.programId,
|
|
25
|
+
(keyAccountInfo, context) => {
|
|
26
|
+
const userAccount =
|
|
27
|
+
this.driftClient.program.account.user.coder.accounts.decode(
|
|
28
|
+
'User',
|
|
29
|
+
keyAccountInfo.accountInfo.data
|
|
30
|
+
) as UserAccount;
|
|
31
|
+
this.eventEmitter.emit(
|
|
32
|
+
'onAccountUpdate',
|
|
33
|
+
userAccount,
|
|
34
|
+
keyAccountInfo.accountId,
|
|
35
|
+
context.slot
|
|
36
|
+
);
|
|
37
|
+
},
|
|
38
|
+
this.driftClient.opts.commitment,
|
|
39
|
+
[getUserFilter(), getUserWithAuctionFilter()]
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public async unsubscribe() {
|
|
44
|
+
if (this.websocketId) {
|
|
45
|
+
await this.driftClient.connection.removeProgramAccountChangeListener(
|
|
46
|
+
this.websocketId
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { DriftClient } from '../driftClient';
|
|
2
|
+
import { UserAccount } from '../types';
|
|
3
|
+
import { ConfirmOptions, PublicKey } from '@solana/web3.js';
|
|
4
|
+
|
|
5
|
+
export type AuctionSubscriberConfig = {
|
|
6
|
+
driftClient: DriftClient;
|
|
7
|
+
opts?: ConfirmOptions;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export interface AuctionSubscriberEvents {
|
|
11
|
+
onAccountUpdate: (
|
|
12
|
+
account: UserAccount,
|
|
13
|
+
pubkey: PublicKey,
|
|
14
|
+
slot: number
|
|
15
|
+
) => void;
|
|
16
|
+
}
|
package/src/config.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PerpMarketAccount, SpotMarketAccount } from '.';
|
|
1
2
|
import {
|
|
2
3
|
DevnetPerpMarkets,
|
|
3
4
|
MainnetPerpMarkets,
|
|
@@ -11,7 +12,7 @@ import {
|
|
|
11
12
|
MainnetSpotMarkets,
|
|
12
13
|
} from './constants/spotMarkets';
|
|
13
14
|
import { OracleInfo } from './oracles/types';
|
|
14
|
-
import { Program } from '@coral-xyz/anchor';
|
|
15
|
+
import { Program, ProgramAccount } from '@coral-xyz/anchor';
|
|
15
16
|
|
|
16
17
|
type DriftConfig = {
|
|
17
18
|
ENV: DriftEnv;
|
|
@@ -124,8 +125,10 @@ export async function findAllMarketAndOracles(program: Program): Promise<{
|
|
|
124
125
|
const spotMarketIndexes = [];
|
|
125
126
|
const oracleInfos = new Map<string, OracleInfo>();
|
|
126
127
|
|
|
127
|
-
const perpMarketProgramAccounts =
|
|
128
|
-
|
|
128
|
+
const perpMarketProgramAccounts =
|
|
129
|
+
(await program.account.perpMarket.all()) as ProgramAccount<PerpMarketAccount>[];
|
|
130
|
+
const spotMarketProgramAccounts =
|
|
131
|
+
(await program.account.spotMarket.all()) as ProgramAccount<SpotMarketAccount>[];
|
|
129
132
|
|
|
130
133
|
for (const perpMarketProgramAccount of perpMarketProgramAccounts) {
|
|
131
134
|
const perpMarket = perpMarketProgramAccount.account;
|
|
@@ -244,17 +244,22 @@ export function getVammL2Generator({
|
|
|
244
244
|
};
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
export function groupL2(
|
|
247
|
+
export function groupL2(
|
|
248
|
+
l2: L2OrderBook,
|
|
249
|
+
grouping: BN,
|
|
250
|
+
depth: number
|
|
251
|
+
): L2OrderBook {
|
|
248
252
|
return {
|
|
249
|
-
bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG),
|
|
250
|
-
asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT),
|
|
253
|
+
bids: groupL2Levels(l2.bids, grouping, PositionDirection.LONG, depth),
|
|
254
|
+
asks: groupL2Levels(l2.asks, grouping, PositionDirection.SHORT, depth),
|
|
251
255
|
};
|
|
252
256
|
}
|
|
253
257
|
|
|
254
258
|
function groupL2Levels(
|
|
255
259
|
levels: L2Level[],
|
|
256
260
|
grouping: BN,
|
|
257
|
-
direction: PositionDirection
|
|
261
|
+
direction: PositionDirection,
|
|
262
|
+
depth: number
|
|
258
263
|
): L2Level[] {
|
|
259
264
|
const groupedLevels = [];
|
|
260
265
|
for (const level of levels) {
|
|
@@ -281,6 +286,10 @@ function groupL2Levels(
|
|
|
281
286
|
};
|
|
282
287
|
groupedLevels.push(groupedLevel);
|
|
283
288
|
}
|
|
289
|
+
|
|
290
|
+
if (groupedLevels.length === depth) {
|
|
291
|
+
break;
|
|
292
|
+
}
|
|
284
293
|
}
|
|
285
294
|
return groupedLevels;
|
|
286
295
|
}
|
package/src/driftClient.ts
CHANGED
|
@@ -114,6 +114,7 @@ import { calculateMarketMaxAvailableInsurance } from './math/market';
|
|
|
114
114
|
import { fetchUserStatsAccount } from './accounts/fetch';
|
|
115
115
|
import { castNumberToSpotPrecision } from './math/spotMarket';
|
|
116
116
|
import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
|
|
117
|
+
import { getNonIdleUserFilter } from './memcmp';
|
|
117
118
|
|
|
118
119
|
type RemainingAccountParams = {
|
|
119
120
|
userAccounts: UserAccount[];
|
|
@@ -897,14 +898,7 @@ export class DriftClient {
|
|
|
897
898
|
): Promise<ProgramAccount<UserAccount>[]> {
|
|
898
899
|
let filters = undefined;
|
|
899
900
|
if (!includeIdle) {
|
|
900
|
-
filters = [
|
|
901
|
-
{
|
|
902
|
-
memcmp: {
|
|
903
|
-
offset: 4350,
|
|
904
|
-
bytes: bs58.encode(Uint8Array.from([0])),
|
|
905
|
-
},
|
|
906
|
-
},
|
|
907
|
-
];
|
|
901
|
+
filters = [getNonIdleUserFilter()];
|
|
908
902
|
}
|
|
909
903
|
return (await this.program.account.user.all(
|
|
910
904
|
filters
|
|
@@ -3395,12 +3389,12 @@ export class DriftClient {
|
|
|
3395
3389
|
endSwapIx,
|
|
3396
3390
|
];
|
|
3397
3391
|
|
|
3398
|
-
const tx = await this.buildTransaction(
|
|
3392
|
+
const tx = (await this.buildTransaction(
|
|
3399
3393
|
instructions,
|
|
3400
3394
|
txParams,
|
|
3401
3395
|
0,
|
|
3402
3396
|
lookupTables
|
|
3403
|
-
);
|
|
3397
|
+
)) as VersionedTransaction;
|
|
3404
3398
|
|
|
3405
3399
|
const { txSig, slot } = await this.sendTransaction(tx);
|
|
3406
3400
|
this.spotMarketLastSlotCache.set(outMarketIndex, slot);
|
|
@@ -3625,6 +3619,43 @@ export class DriftClient {
|
|
|
3625
3619
|
});
|
|
3626
3620
|
}
|
|
3627
3621
|
|
|
3622
|
+
public async updateUserOpenOrdersCount(
|
|
3623
|
+
userAccountPublicKey: PublicKey,
|
|
3624
|
+
user: UserAccount,
|
|
3625
|
+
txParams?: TxParams
|
|
3626
|
+
): Promise<TransactionSignature> {
|
|
3627
|
+
const { txSig } = await this.sendTransaction(
|
|
3628
|
+
await this.buildTransaction(
|
|
3629
|
+
await this.getUpdateUserOpenOrdersCountIx(userAccountPublicKey, user),
|
|
3630
|
+
txParams
|
|
3631
|
+
),
|
|
3632
|
+
[],
|
|
3633
|
+
this.opts
|
|
3634
|
+
);
|
|
3635
|
+
return txSig;
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
public async getUpdateUserOpenOrdersCountIx(
|
|
3639
|
+
userAccountPublicKey: PublicKey,
|
|
3640
|
+
userAccount: UserAccount
|
|
3641
|
+
): Promise<TransactionInstruction> {
|
|
3642
|
+
const fillerPublicKey = await this.getUserAccountPublicKey();
|
|
3643
|
+
|
|
3644
|
+
const remainingAccounts = this.getRemainingAccounts({
|
|
3645
|
+
userAccounts: [userAccount],
|
|
3646
|
+
});
|
|
3647
|
+
|
|
3648
|
+
return await this.program.instruction.updateUserOpenOrdersCount({
|
|
3649
|
+
accounts: {
|
|
3650
|
+
state: await this.getStatePublicKey(),
|
|
3651
|
+
filler: fillerPublicKey,
|
|
3652
|
+
user: userAccountPublicKey,
|
|
3653
|
+
authority: this.wallet.publicKey,
|
|
3654
|
+
},
|
|
3655
|
+
remainingAccounts,
|
|
3656
|
+
});
|
|
3657
|
+
}
|
|
3658
|
+
|
|
3628
3659
|
public async placeAndTakePerpOrder(
|
|
3629
3660
|
orderParams: OptionalOrderParams,
|
|
3630
3661
|
makerInfo?: MakerInfo | MakerInfo[],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Connection, TransactionSignature } from '@solana/web3.js';
|
|
1
|
+
import { Connection, PublicKey, TransactionSignature } from '@solana/web3.js';
|
|
2
2
|
import { Program } from '@coral-xyz/anchor';
|
|
3
3
|
import {
|
|
4
4
|
DefaultEventSubscriptionOptions,
|
|
@@ -19,6 +19,7 @@ import StrictEventEmitter from 'strict-event-emitter-types';
|
|
|
19
19
|
import { getSortFn } from './sort';
|
|
20
20
|
|
|
21
21
|
export class EventSubscriber {
|
|
22
|
+
private address: PublicKey;
|
|
22
23
|
private eventListMap: Map<EventType, EventList<EventType>>;
|
|
23
24
|
private txEventCache: TxEventCache;
|
|
24
25
|
private awaitTxPromises = new Map<string, Promise<void>>();
|
|
@@ -35,6 +36,7 @@ export class EventSubscriber {
|
|
|
35
36
|
private options: EventSubscriptionOptions = DefaultEventSubscriptionOptions
|
|
36
37
|
) {
|
|
37
38
|
this.options = Object.assign({}, DefaultEventSubscriptionOptions, options);
|
|
39
|
+
this.address = this.options.address ?? program.programId;
|
|
38
40
|
this.txEventCache = new TxEventCache(this.options.maxTx);
|
|
39
41
|
this.eventListMap = new Map<EventType, EventList<EventType>>();
|
|
40
42
|
for (const eventType of this.options.eventTypes) {
|
|
@@ -52,13 +54,13 @@ export class EventSubscriber {
|
|
|
52
54
|
if (this.options.logProviderConfig.type === 'websocket') {
|
|
53
55
|
this.logProvider = new WebSocketLogProvider(
|
|
54
56
|
this.connection,
|
|
55
|
-
this.
|
|
57
|
+
this.address,
|
|
56
58
|
this.options.commitment
|
|
57
59
|
);
|
|
58
60
|
} else {
|
|
59
61
|
this.logProvider = new PollingLogProvider(
|
|
60
62
|
this.connection,
|
|
61
|
-
this.
|
|
63
|
+
this.address,
|
|
62
64
|
options.commitment,
|
|
63
65
|
this.options.logProviderConfig.frequency
|
|
64
66
|
);
|
|
@@ -134,7 +136,7 @@ export class EventSubscriber {
|
|
|
134
136
|
while (txFetched < this.options.maxTx) {
|
|
135
137
|
const response = await fetchLogs(
|
|
136
138
|
this.connection,
|
|
137
|
-
this.
|
|
139
|
+
this.address,
|
|
138
140
|
this.options.commitment === 'finalized' ? 'finalized' : 'confirmed',
|
|
139
141
|
beforeTx,
|
|
140
142
|
untilTx
|
package/src/events/fetchLogs.ts
CHANGED
|
@@ -31,14 +31,14 @@ function mapTransactionResponseToLog(
|
|
|
31
31
|
|
|
32
32
|
export async function fetchLogs(
|
|
33
33
|
connection: Connection,
|
|
34
|
-
|
|
34
|
+
address: PublicKey,
|
|
35
35
|
finality: Finality,
|
|
36
36
|
beforeTx?: TransactionSignature,
|
|
37
37
|
untilTx?: TransactionSignature,
|
|
38
38
|
limit?: number
|
|
39
39
|
): Promise<FetchLogsResponse> {
|
|
40
40
|
const signatures = await connection.getSignaturesForAddress(
|
|
41
|
-
|
|
41
|
+
address,
|
|
42
42
|
{
|
|
43
43
|
before: beforeTx,
|
|
44
44
|
until: untilTx,
|
|
@@ -17,7 +17,7 @@ export class PollingLogProvider implements LogProvider {
|
|
|
17
17
|
|
|
18
18
|
public constructor(
|
|
19
19
|
private connection: Connection,
|
|
20
|
-
private
|
|
20
|
+
private address: PublicKey,
|
|
21
21
|
commitment: Commitment,
|
|
22
22
|
private frequency = 15 * 1000
|
|
23
23
|
) {
|
|
@@ -41,7 +41,7 @@ export class PollingLogProvider implements LogProvider {
|
|
|
41
41
|
try {
|
|
42
42
|
const response = await fetchLogs(
|
|
43
43
|
this.connection,
|
|
44
|
-
this.
|
|
44
|
+
this.address,
|
|
45
45
|
this.finality,
|
|
46
46
|
undefined,
|
|
47
47
|
this.mostRecentSeenTx,
|
package/src/events/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Commitment, TransactionSignature } from '@solana/web3.js';
|
|
1
|
+
import { Commitment, PublicKey, TransactionSignature } from '@solana/web3.js';
|
|
2
2
|
import {
|
|
3
3
|
DepositRecord,
|
|
4
4
|
FundingPaymentRecord,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
} from '../index';
|
|
18
18
|
|
|
19
19
|
export type EventSubscriptionOptions = {
|
|
20
|
+
address?: PublicKey;
|
|
20
21
|
eventTypes?: EventType[];
|
|
21
22
|
maxEventsPerType?: number;
|
|
22
23
|
orderBy?: EventSubscriptionOrderBy;
|
|
@@ -5,7 +5,7 @@ export class WebSocketLogProvider implements LogProvider {
|
|
|
5
5
|
private subscriptionId: number;
|
|
6
6
|
public constructor(
|
|
7
7
|
private connection: Connection,
|
|
8
|
-
private
|
|
8
|
+
private address: PublicKey,
|
|
9
9
|
private commitment: Commitment
|
|
10
10
|
) {}
|
|
11
11
|
|
|
@@ -15,7 +15,7 @@ export class WebSocketLogProvider implements LogProvider {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
this.subscriptionId = this.connection.onLogs(
|
|
18
|
-
this.
|
|
18
|
+
this.address,
|
|
19
19
|
(logs, ctx) => {
|
|
20
20
|
callback(logs.signature, ctx.slot, logs.logs, undefined);
|
|
21
21
|
},
|