@drift-labs/sdk 2.49.0-beta.15 → 2.49.0-beta.17
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/adminClient.d.ts +1 -0
- package/lib/adminClient.js +8 -0
- package/lib/decode/user.d.ts +3 -0
- package/lib/decode/user.js +328 -0
- package/lib/idl/drift.json +31 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/state.d.ts +5 -0
- package/lib/math/state.js +30 -0
- package/lib/orderSubscriber/OrderSubscriber.d.ts +3 -0
- package/lib/orderSubscriber/OrderSubscriber.js +13 -3
- package/lib/orderSubscriber/WebsocketSubscription.js +1 -1
- package/lib/orderSubscriber/types.d.ts +4 -1
- package/lib/types.d.ts +1 -1
- package/lib/user.d.ts +1 -1
- package/lib/user.js +7 -2
- package/lib/userMap/PollingSubscription.js +3 -1
- package/lib/userMap/WebsocketSubscription.d.ts +5 -1
- package/lib/userMap/WebsocketSubscription.js +3 -2
- package/lib/userMap/userMap.d.ts +1 -0
- package/lib/userMap/userMap.js +14 -6
- package/lib/userMap/userMapConfig.d.ts +1 -0
- package/package.json +2 -1
- package/src/adminClient.ts +14 -0
- package/src/decode/user.ts +357 -0
- package/src/idl/drift.json +32 -2
- package/src/index.ts +1 -0
- package/src/math/state.ts +29 -0
- package/src/orderSubscriber/OrderSubscriber.ts +27 -6
- package/src/orderSubscriber/WebsocketSubscription.ts +1 -3
- package/src/orderSubscriber/types.ts +13 -1
- package/src/types.ts +1 -1
- package/src/user.ts +12 -2
- package/src/userMap/PollingSubscription.ts +6 -4
- package/src/userMap/WebsocketSubscription.ts +5 -3
- package/src/userMap/userMap.ts +17 -12
- package/src/userMap/userMapConfig.ts +3 -0
- package/tests/decode/test.ts +266 -0
- package/tests/decode/userAccountBufferStrings.ts +102 -0
- package/tests/dlob/helpers.ts +1 -0
- package/tests/dlob/test.ts +4 -6
- package/tests/user/helpers.ts +0 -1
|
@@ -4,12 +4,13 @@ exports.WebsocketSubscription = void 0;
|
|
|
4
4
|
const memcmp_1 = require("../memcmp");
|
|
5
5
|
const webSocketProgramAccountSubscriber_1 = require("../accounts/webSocketProgramAccountSubscriber");
|
|
6
6
|
class WebsocketSubscription {
|
|
7
|
-
constructor({ userMap, commitment, skipInitialLoad = false, resubTimeoutMs, includeIdle = false, }) {
|
|
7
|
+
constructor({ userMap, commitment, skipInitialLoad = false, resubTimeoutMs, includeIdle = false, decodeFn, }) {
|
|
8
8
|
this.userMap = userMap;
|
|
9
9
|
this.commitment = commitment;
|
|
10
10
|
this.skipInitialLoad = skipInitialLoad;
|
|
11
11
|
this.resubTimeoutMs = resubTimeoutMs;
|
|
12
12
|
this.includeIdle = includeIdle || false;
|
|
13
|
+
this.decodeFn = decodeFn;
|
|
13
14
|
}
|
|
14
15
|
async subscribe() {
|
|
15
16
|
if (!this.subscriber) {
|
|
@@ -17,7 +18,7 @@ class WebsocketSubscription {
|
|
|
17
18
|
if (!this.includeIdle) {
|
|
18
19
|
filters.push((0, memcmp_1.getNonIdleUserFilter)());
|
|
19
20
|
}
|
|
20
|
-
this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('UserMap', 'User', this.userMap.driftClient.program, this.
|
|
21
|
+
this.subscriber = new webSocketProgramAccountSubscriber_1.WebSocketProgramAccountSubscriber('UserMap', 'User', this.userMap.driftClient.program, this.decodeFn, {
|
|
21
22
|
filters,
|
|
22
23
|
commitment: this.commitment,
|
|
23
24
|
}, this.resubTimeoutMs);
|
package/lib/userMap/userMap.d.ts
CHANGED
package/lib/userMap/userMap.js
CHANGED
|
@@ -7,12 +7,13 @@ const buffer_1 = require("buffer");
|
|
|
7
7
|
const memcmp_1 = require("../memcmp");
|
|
8
8
|
const WebsocketSubscription_1 = require("./WebsocketSubscription");
|
|
9
9
|
const PollingSubscription_1 = require("./PollingSubscription");
|
|
10
|
+
const user_1 = require("../decode/user");
|
|
10
11
|
class UserMap {
|
|
11
12
|
/**
|
|
12
13
|
* Constructs a new UserMap instance.
|
|
13
14
|
*/
|
|
14
15
|
constructor(config) {
|
|
15
|
-
var _a, _b;
|
|
16
|
+
var _a, _b, _c;
|
|
16
17
|
this.userMap = new Map();
|
|
17
18
|
this.stateAccountUpdateCallback = async (state) => {
|
|
18
19
|
if (!state.numberOfSubAccounts.eq(this.lastNumberOfSubAccounts)) {
|
|
@@ -30,6 +31,15 @@ class UserMap {
|
|
|
30
31
|
this.commitment =
|
|
31
32
|
(_a = config.subscriptionConfig.commitment) !== null && _a !== void 0 ? _a : this.driftClient.opts.commitment;
|
|
32
33
|
this.includeIdle = (_b = config.includeIdle) !== null && _b !== void 0 ? _b : false;
|
|
34
|
+
let decodeFn;
|
|
35
|
+
if ((_c = config.fastDecode) !== null && _c !== void 0 ? _c : true) {
|
|
36
|
+
decodeFn = (name, buffer) => (0, user_1.decodeUser)(buffer);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
decodeFn =
|
|
40
|
+
this.driftClient.program.account.user.coder.accounts.decodeUnchecked.bind(this.driftClient.program.account.user.coder.accounts);
|
|
41
|
+
}
|
|
42
|
+
this.decode = decodeFn;
|
|
33
43
|
if (config.subscriptionConfig.type === 'polling') {
|
|
34
44
|
this.subscription = new PollingSubscription_1.PollingSubscription({
|
|
35
45
|
userMap: this,
|
|
@@ -43,6 +53,7 @@ class UserMap {
|
|
|
43
53
|
commitment: this.commitment,
|
|
44
54
|
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
45
55
|
skipInitialLoad: config.skipInitialLoad,
|
|
56
|
+
decodeFn,
|
|
46
57
|
});
|
|
47
58
|
}
|
|
48
59
|
}
|
|
@@ -215,8 +226,9 @@ class UserMap {
|
|
|
215
226
|
}
|
|
216
227
|
for (const [key, buffer] of programAccountBufferMap.entries()) {
|
|
217
228
|
if (!this.has(key)) {
|
|
218
|
-
const userAccount = this.
|
|
229
|
+
const userAccount = this.decode('User', buffer);
|
|
219
230
|
await this.addPubkey(new web3_js_1.PublicKey(key), userAccount);
|
|
231
|
+
this.userMap.get(key).accountSubscriber.updateData(userAccount, slot);
|
|
220
232
|
}
|
|
221
233
|
// give event loop a chance to breathe
|
|
222
234
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -226,10 +238,6 @@ class UserMap {
|
|
|
226
238
|
await user.unsubscribe();
|
|
227
239
|
this.userMap.delete(key);
|
|
228
240
|
}
|
|
229
|
-
else {
|
|
230
|
-
const userAccount = this.driftClient.program.account.user.coder.accounts.decodeUnchecked('User', programAccountBufferMap.get(key));
|
|
231
|
-
user.accountSubscriber.updateData(userAccount, slot);
|
|
232
|
-
}
|
|
233
241
|
// give event loop a chance to breathe
|
|
234
242
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
235
243
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.49.0-beta.
|
|
3
|
+
"version": "2.49.0-beta.17",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"uuid": "^8.3.2"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
|
+
"object-sizeof": "^2.6.3",
|
|
47
48
|
"@types/big.js": "^6.2.0",
|
|
48
49
|
"@types/bn.js": "^5.1.3",
|
|
49
50
|
"@types/chai": "^4.3.1",
|
package/src/adminClient.ts
CHANGED
|
@@ -846,6 +846,20 @@ export class AdminClient extends DriftClient {
|
|
|
846
846
|
);
|
|
847
847
|
}
|
|
848
848
|
|
|
849
|
+
public async updateStateMaxInitializeUserFee(
|
|
850
|
+
maxInitializeUserFee: number
|
|
851
|
+
): Promise<TransactionSignature> {
|
|
852
|
+
return await this.program.rpc.updateStateMaxInitializeUserFee(
|
|
853
|
+
maxInitializeUserFee,
|
|
854
|
+
{
|
|
855
|
+
accounts: {
|
|
856
|
+
admin: this.wallet.publicKey,
|
|
857
|
+
state: await this.getStatePublicKey(),
|
|
858
|
+
},
|
|
859
|
+
}
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
|
|
849
863
|
public async updateWithdrawGuardThreshold(
|
|
850
864
|
spotMarketIndex: number,
|
|
851
865
|
withdrawGuardThreshold: BN
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MarketType,
|
|
3
|
+
Order,
|
|
4
|
+
OrderStatus,
|
|
5
|
+
OrderTriggerCondition,
|
|
6
|
+
OrderType,
|
|
7
|
+
PerpPosition,
|
|
8
|
+
PositionDirection,
|
|
9
|
+
SpotBalanceType,
|
|
10
|
+
SpotPosition,
|
|
11
|
+
UserAccount,
|
|
12
|
+
} from '../types';
|
|
13
|
+
import { PublicKey } from '@solana/web3.js';
|
|
14
|
+
import { BN } from '../';
|
|
15
|
+
import { ZERO } from '../';
|
|
16
|
+
|
|
17
|
+
function readUnsignedBigInt64LE(buffer: Buffer, offset: number): BN {
|
|
18
|
+
return new BN(buffer.subarray(offset, offset + 8), 10, 'le');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function readSignedBigInt64LE(buffer: Buffer, offset: number): BN {
|
|
22
|
+
const unsignedValue = new BN(buffer.subarray(offset, offset + 8), 10, 'le');
|
|
23
|
+
if (unsignedValue.testn(63)) {
|
|
24
|
+
const inverted = unsignedValue.notn(64).addn(1);
|
|
25
|
+
return inverted.neg();
|
|
26
|
+
} else {
|
|
27
|
+
return unsignedValue;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function decodeUser(buffer: Buffer): UserAccount {
|
|
32
|
+
let offset = 8;
|
|
33
|
+
const authority = new PublicKey(buffer.slice(offset, offset + 32));
|
|
34
|
+
offset += 32;
|
|
35
|
+
const delegate = new PublicKey(buffer.slice(offset, offset + 32));
|
|
36
|
+
offset += 32;
|
|
37
|
+
const name = [];
|
|
38
|
+
for (let i = 0; i < 32; i++) {
|
|
39
|
+
name.push(buffer.readUint8(offset + i));
|
|
40
|
+
}
|
|
41
|
+
offset += 32;
|
|
42
|
+
|
|
43
|
+
const spotPositions: SpotPosition[] = [];
|
|
44
|
+
for (let i = 0; i < 8; i++) {
|
|
45
|
+
const scaledBalance = readUnsignedBigInt64LE(buffer, offset);
|
|
46
|
+
const openOrders = buffer.readUInt8(offset + 35);
|
|
47
|
+
if (scaledBalance.eq(ZERO) && openOrders === 0) {
|
|
48
|
+
offset += 40;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
offset += 8;
|
|
53
|
+
const openBids = readSignedBigInt64LE(buffer, offset);
|
|
54
|
+
offset += 8;
|
|
55
|
+
const openAsks = readSignedBigInt64LE(buffer, offset);
|
|
56
|
+
offset += 8;
|
|
57
|
+
const cumulativeDeposits = readSignedBigInt64LE(buffer, offset);
|
|
58
|
+
offset += 8;
|
|
59
|
+
const marketIndex = buffer.readUInt16LE(offset);
|
|
60
|
+
offset += 2;
|
|
61
|
+
const balanceTypeNum = buffer.readUInt8(offset);
|
|
62
|
+
let balanceType: SpotBalanceType;
|
|
63
|
+
if (balanceTypeNum === 0) {
|
|
64
|
+
balanceType = SpotBalanceType.DEPOSIT;
|
|
65
|
+
} else {
|
|
66
|
+
balanceType = SpotBalanceType.BORROW;
|
|
67
|
+
}
|
|
68
|
+
offset += 6;
|
|
69
|
+
spotPositions.push({
|
|
70
|
+
scaledBalance,
|
|
71
|
+
openBids,
|
|
72
|
+
openAsks,
|
|
73
|
+
cumulativeDeposits,
|
|
74
|
+
marketIndex,
|
|
75
|
+
balanceType,
|
|
76
|
+
openOrders,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const perpPositions: PerpPosition[] = [];
|
|
81
|
+
for (let i = 0; i < 8; i++) {
|
|
82
|
+
const baseAssetAmount = readSignedBigInt64LE(buffer, offset + 8);
|
|
83
|
+
const quoteAssetAmount = readSignedBigInt64LE(buffer, offset + 16);
|
|
84
|
+
const lpShares = readUnsignedBigInt64LE(buffer, offset + 64);
|
|
85
|
+
const openOrders = buffer.readUInt8(offset + 94);
|
|
86
|
+
|
|
87
|
+
if (
|
|
88
|
+
baseAssetAmount.eq(ZERO) &&
|
|
89
|
+
openOrders === 0 &&
|
|
90
|
+
quoteAssetAmount.eq(ZERO) &&
|
|
91
|
+
lpShares.eq(ZERO)
|
|
92
|
+
) {
|
|
93
|
+
offset += 96;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const lastCumulativeFundingRate = readSignedBigInt64LE(buffer, offset);
|
|
98
|
+
offset += 24;
|
|
99
|
+
const quoteBreakEvenAmount = readSignedBigInt64LE(buffer, offset);
|
|
100
|
+
offset += 8;
|
|
101
|
+
const quoteEntryAmount = readSignedBigInt64LE(buffer, offset);
|
|
102
|
+
offset += 8;
|
|
103
|
+
const openBids = readSignedBigInt64LE(buffer, offset);
|
|
104
|
+
offset += 8;
|
|
105
|
+
const openAsks = readSignedBigInt64LE(buffer, offset);
|
|
106
|
+
offset += 8;
|
|
107
|
+
const settledPnl = readSignedBigInt64LE(buffer, offset);
|
|
108
|
+
offset += 16;
|
|
109
|
+
const lastBaseAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
|
|
110
|
+
offset += 8;
|
|
111
|
+
const lastQuoteAssetAmountPerLp = readSignedBigInt64LE(buffer, offset);
|
|
112
|
+
offset += 8;
|
|
113
|
+
const remainderBaseAssetAmount = buffer.readUint32LE(offset);
|
|
114
|
+
offset += 4;
|
|
115
|
+
const marketIndex = buffer.readUInt16LE(offset);
|
|
116
|
+
offset += 3;
|
|
117
|
+
const perLpBase = buffer.readUInt8(offset);
|
|
118
|
+
offset += 1;
|
|
119
|
+
|
|
120
|
+
perpPositions.push({
|
|
121
|
+
lastCumulativeFundingRate,
|
|
122
|
+
baseAssetAmount,
|
|
123
|
+
quoteAssetAmount,
|
|
124
|
+
quoteBreakEvenAmount,
|
|
125
|
+
quoteEntryAmount,
|
|
126
|
+
openBids,
|
|
127
|
+
openAsks,
|
|
128
|
+
settledPnl,
|
|
129
|
+
lpShares,
|
|
130
|
+
lastBaseAssetAmountPerLp,
|
|
131
|
+
lastQuoteAssetAmountPerLp,
|
|
132
|
+
remainderBaseAssetAmount,
|
|
133
|
+
marketIndex,
|
|
134
|
+
openOrders,
|
|
135
|
+
perLpBase,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const orders: Order[] = [];
|
|
140
|
+
for (let i = 0; i < 32; i++) {
|
|
141
|
+
// skip order if it's not open
|
|
142
|
+
if (buffer.readUint8(offset + 82) === 0) {
|
|
143
|
+
offset += 96;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const slot = readUnsignedBigInt64LE(buffer, offset);
|
|
148
|
+
offset += 8;
|
|
149
|
+
const price = readUnsignedBigInt64LE(buffer, offset);
|
|
150
|
+
offset += 8;
|
|
151
|
+
const baseAssetAmount = readUnsignedBigInt64LE(buffer, offset);
|
|
152
|
+
offset += 8;
|
|
153
|
+
const baseAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
|
|
154
|
+
offset += 8;
|
|
155
|
+
const quoteAssetAmountFilled = readUnsignedBigInt64LE(buffer, offset);
|
|
156
|
+
offset += 8;
|
|
157
|
+
const triggerPrice = readUnsignedBigInt64LE(buffer, offset);
|
|
158
|
+
offset += 8;
|
|
159
|
+
const auctionStartPrice = readSignedBigInt64LE(buffer, offset);
|
|
160
|
+
offset += 8;
|
|
161
|
+
const auctionEndPrice = readSignedBigInt64LE(buffer, offset);
|
|
162
|
+
offset += 8;
|
|
163
|
+
const maxTs = readSignedBigInt64LE(buffer, offset);
|
|
164
|
+
offset += 8;
|
|
165
|
+
const oraclePriceOffset = buffer.readInt32LE(offset);
|
|
166
|
+
offset += 4;
|
|
167
|
+
const orderId = buffer.readUInt32LE(offset);
|
|
168
|
+
offset += 4;
|
|
169
|
+
const marketIndex = buffer.readUInt16LE(offset);
|
|
170
|
+
offset += 2;
|
|
171
|
+
const orderStatusNum = buffer.readUInt8(offset);
|
|
172
|
+
|
|
173
|
+
let status: OrderStatus;
|
|
174
|
+
if (orderStatusNum === 0) {
|
|
175
|
+
status = OrderStatus.INIT;
|
|
176
|
+
} else if (orderStatusNum === 1) {
|
|
177
|
+
status = OrderStatus.OPEN;
|
|
178
|
+
}
|
|
179
|
+
offset += 1;
|
|
180
|
+
const orderTypeNum = buffer.readUInt8(offset);
|
|
181
|
+
let orderType: OrderType;
|
|
182
|
+
if (orderTypeNum === 0) {
|
|
183
|
+
orderType = OrderType.MARKET;
|
|
184
|
+
} else if (orderTypeNum === 1) {
|
|
185
|
+
orderType = OrderType.LIMIT;
|
|
186
|
+
} else if (orderTypeNum === 2) {
|
|
187
|
+
orderType = OrderType.TRIGGER_MARKET;
|
|
188
|
+
} else if (orderTypeNum === 3) {
|
|
189
|
+
orderType = OrderType.TRIGGER_LIMIT;
|
|
190
|
+
} else if (orderTypeNum === 4) {
|
|
191
|
+
orderType = OrderType.ORACLE;
|
|
192
|
+
}
|
|
193
|
+
offset += 1;
|
|
194
|
+
const marketTypeNum = buffer.readUInt8(offset);
|
|
195
|
+
let marketType: MarketType;
|
|
196
|
+
if (marketTypeNum === 0) {
|
|
197
|
+
marketType = MarketType.SPOT;
|
|
198
|
+
} else {
|
|
199
|
+
marketType = MarketType.PERP;
|
|
200
|
+
}
|
|
201
|
+
offset += 1;
|
|
202
|
+
const userOrderId = buffer.readUint8(offset);
|
|
203
|
+
offset += 1;
|
|
204
|
+
const existingPositionDirectionNum = buffer.readUInt8(offset);
|
|
205
|
+
let existingPositionDirection: PositionDirection;
|
|
206
|
+
if (existingPositionDirectionNum === 0) {
|
|
207
|
+
existingPositionDirection = PositionDirection.LONG;
|
|
208
|
+
} else {
|
|
209
|
+
existingPositionDirection = PositionDirection.SHORT;
|
|
210
|
+
}
|
|
211
|
+
offset += 1;
|
|
212
|
+
const positionDirectionNum = buffer.readUInt8(offset);
|
|
213
|
+
let direction: PositionDirection;
|
|
214
|
+
if (positionDirectionNum === 0) {
|
|
215
|
+
direction = PositionDirection.LONG;
|
|
216
|
+
} else {
|
|
217
|
+
direction = PositionDirection.SHORT;
|
|
218
|
+
}
|
|
219
|
+
offset += 1;
|
|
220
|
+
const reduceOnly = buffer.readUInt8(offset) === 1;
|
|
221
|
+
offset += 1;
|
|
222
|
+
const postOnly = buffer.readUInt8(offset) === 1;
|
|
223
|
+
offset += 1;
|
|
224
|
+
const immediateOrCancel = buffer.readUInt8(offset) === 1;
|
|
225
|
+
offset += 1;
|
|
226
|
+
const triggerConditionNum = buffer.readUInt8(offset);
|
|
227
|
+
let triggerCondition: OrderTriggerCondition;
|
|
228
|
+
if (triggerConditionNum === 0) {
|
|
229
|
+
triggerCondition = OrderTriggerCondition.ABOVE;
|
|
230
|
+
} else if (triggerConditionNum === 1) {
|
|
231
|
+
triggerCondition = OrderTriggerCondition.BELOW;
|
|
232
|
+
} else if (triggerConditionNum === 2) {
|
|
233
|
+
triggerCondition = OrderTriggerCondition.TRIGGERED_ABOVE;
|
|
234
|
+
} else if (triggerConditionNum === 3) {
|
|
235
|
+
triggerCondition = OrderTriggerCondition.TRIGGERED_BELOW;
|
|
236
|
+
}
|
|
237
|
+
offset += 1;
|
|
238
|
+
const auctionDuration = buffer.readUInt8(offset);
|
|
239
|
+
offset += 1;
|
|
240
|
+
offset += 3; // padding
|
|
241
|
+
orders.push({
|
|
242
|
+
slot,
|
|
243
|
+
price,
|
|
244
|
+
baseAssetAmount,
|
|
245
|
+
baseAssetAmountFilled,
|
|
246
|
+
quoteAssetAmountFilled,
|
|
247
|
+
triggerPrice,
|
|
248
|
+
auctionStartPrice,
|
|
249
|
+
auctionEndPrice,
|
|
250
|
+
maxTs,
|
|
251
|
+
oraclePriceOffset,
|
|
252
|
+
orderId,
|
|
253
|
+
marketIndex,
|
|
254
|
+
status,
|
|
255
|
+
orderType,
|
|
256
|
+
marketType,
|
|
257
|
+
userOrderId,
|
|
258
|
+
existingPositionDirection,
|
|
259
|
+
direction,
|
|
260
|
+
reduceOnly,
|
|
261
|
+
postOnly,
|
|
262
|
+
immediateOrCancel,
|
|
263
|
+
triggerCondition,
|
|
264
|
+
auctionDuration,
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const lastAddPerpLpSharesTs = readSignedBigInt64LE(buffer, offset);
|
|
269
|
+
offset += 8;
|
|
270
|
+
|
|
271
|
+
const totalDeposits = readUnsignedBigInt64LE(buffer, offset);
|
|
272
|
+
offset += 8;
|
|
273
|
+
|
|
274
|
+
const totalWithdraws = readUnsignedBigInt64LE(buffer, offset);
|
|
275
|
+
offset += 8;
|
|
276
|
+
|
|
277
|
+
const totalSocialLoss = readUnsignedBigInt64LE(buffer, offset);
|
|
278
|
+
offset += 8;
|
|
279
|
+
|
|
280
|
+
const settledPerpPnl = readSignedBigInt64LE(buffer, offset);
|
|
281
|
+
offset += 8;
|
|
282
|
+
|
|
283
|
+
const cumulativeSpotFees = readSignedBigInt64LE(buffer, offset);
|
|
284
|
+
offset += 8;
|
|
285
|
+
|
|
286
|
+
const cumulativePerpFunding = readSignedBigInt64LE(buffer, offset);
|
|
287
|
+
offset += 8;
|
|
288
|
+
|
|
289
|
+
const liquidationMarginFreed = readUnsignedBigInt64LE(buffer, offset);
|
|
290
|
+
offset += 8;
|
|
291
|
+
|
|
292
|
+
const lastActiveSlot = readUnsignedBigInt64LE(buffer, offset);
|
|
293
|
+
offset += 8;
|
|
294
|
+
|
|
295
|
+
const nextOrderId = buffer.readUInt32LE(offset);
|
|
296
|
+
offset += 4;
|
|
297
|
+
|
|
298
|
+
const maxMarginRatio = buffer.readUInt32LE(offset);
|
|
299
|
+
offset += 4;
|
|
300
|
+
|
|
301
|
+
const nextLiquidationId = buffer.readUInt16LE(offset);
|
|
302
|
+
offset += 2;
|
|
303
|
+
|
|
304
|
+
const subAccountId = buffer.readUInt16LE(offset);
|
|
305
|
+
offset += 2;
|
|
306
|
+
|
|
307
|
+
const status = buffer.readUInt8(offset);
|
|
308
|
+
offset += 1;
|
|
309
|
+
|
|
310
|
+
const isMarginTradingEnabled = buffer.readUInt8(offset) === 1;
|
|
311
|
+
offset += 1;
|
|
312
|
+
|
|
313
|
+
const idle = buffer.readUInt8(offset) === 1;
|
|
314
|
+
offset += 1;
|
|
315
|
+
|
|
316
|
+
const openOrders = buffer.readUInt8(offset);
|
|
317
|
+
offset += 1;
|
|
318
|
+
|
|
319
|
+
const hasOpenOrder = buffer.readUInt8(offset) === 1;
|
|
320
|
+
offset += 1;
|
|
321
|
+
|
|
322
|
+
const openAuctions = buffer.readUInt8(offset);
|
|
323
|
+
offset += 1;
|
|
324
|
+
|
|
325
|
+
const hasOpenAuction = buffer.readUInt8(offset) === 1;
|
|
326
|
+
offset += 1;
|
|
327
|
+
|
|
328
|
+
// @ts-ignore
|
|
329
|
+
return {
|
|
330
|
+
authority,
|
|
331
|
+
delegate,
|
|
332
|
+
name,
|
|
333
|
+
spotPositions,
|
|
334
|
+
perpPositions,
|
|
335
|
+
orders,
|
|
336
|
+
lastAddPerpLpSharesTs,
|
|
337
|
+
totalDeposits,
|
|
338
|
+
totalWithdraws,
|
|
339
|
+
totalSocialLoss,
|
|
340
|
+
settledPerpPnl,
|
|
341
|
+
cumulativeSpotFees,
|
|
342
|
+
cumulativePerpFunding,
|
|
343
|
+
liquidationMarginFreed,
|
|
344
|
+
lastActiveSlot,
|
|
345
|
+
nextOrderId,
|
|
346
|
+
maxMarginRatio,
|
|
347
|
+
nextLiquidationId,
|
|
348
|
+
subAccountId,
|
|
349
|
+
status,
|
|
350
|
+
isMarginTradingEnabled,
|
|
351
|
+
idle,
|
|
352
|
+
openOrders,
|
|
353
|
+
hasOpenOrder,
|
|
354
|
+
openAuctions,
|
|
355
|
+
hasOpenAuction,
|
|
356
|
+
};
|
|
357
|
+
}
|
package/src/idl/drift.json
CHANGED
|
@@ -4184,6 +4184,27 @@
|
|
|
4184
4184
|
}
|
|
4185
4185
|
]
|
|
4186
4186
|
},
|
|
4187
|
+
{
|
|
4188
|
+
"name": "updateStateMaxInitializeUserFee",
|
|
4189
|
+
"accounts": [
|
|
4190
|
+
{
|
|
4191
|
+
"name": "admin",
|
|
4192
|
+
"isMut": false,
|
|
4193
|
+
"isSigner": true
|
|
4194
|
+
},
|
|
4195
|
+
{
|
|
4196
|
+
"name": "state",
|
|
4197
|
+
"isMut": true,
|
|
4198
|
+
"isSigner": false
|
|
4199
|
+
}
|
|
4200
|
+
],
|
|
4201
|
+
"args": [
|
|
4202
|
+
{
|
|
4203
|
+
"name": "maxInitializeUserFee",
|
|
4204
|
+
"type": "u16"
|
|
4205
|
+
}
|
|
4206
|
+
]
|
|
4207
|
+
},
|
|
4187
4208
|
{
|
|
4188
4209
|
"name": "updatePerpMarketOracle",
|
|
4189
4210
|
"accounts": [
|
|
@@ -5747,12 +5768,16 @@
|
|
|
5747
5768
|
"name": "maxNumberOfSubAccounts",
|
|
5748
5769
|
"type": "u16"
|
|
5749
5770
|
},
|
|
5771
|
+
{
|
|
5772
|
+
"name": "maxInitializeUserFee",
|
|
5773
|
+
"type": "u16"
|
|
5774
|
+
},
|
|
5750
5775
|
{
|
|
5751
5776
|
"name": "padding",
|
|
5752
5777
|
"type": {
|
|
5753
5778
|
"array": [
|
|
5754
5779
|
"u8",
|
|
5755
|
-
|
|
5780
|
+
10
|
|
5756
5781
|
]
|
|
5757
5782
|
}
|
|
5758
5783
|
}
|
|
@@ -11094,6 +11119,11 @@
|
|
|
11094
11119
|
"code": 6255,
|
|
11095
11120
|
"name": "InvalidMarginCalculation",
|
|
11096
11121
|
"msg": "InvalidMarginCalculation"
|
|
11122
|
+
},
|
|
11123
|
+
{
|
|
11124
|
+
"code": 6256,
|
|
11125
|
+
"name": "CantPayUserInitFee",
|
|
11126
|
+
"msg": "CantPayUserInitFee"
|
|
11097
11127
|
}
|
|
11098
11128
|
]
|
|
11099
|
-
}
|
|
11129
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -56,6 +56,7 @@ export * from './math/margin';
|
|
|
56
56
|
export * from './math/insurance';
|
|
57
57
|
export * from './math/superStake';
|
|
58
58
|
export * from './math/spotPosition';
|
|
59
|
+
export * from './math/state';
|
|
59
60
|
export * from './marinade';
|
|
60
61
|
export * from './orderParams';
|
|
61
62
|
export * from './slot/SlotSubscriber';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { StateAccount } from '../types';
|
|
2
|
+
import { BN, LAMPORTS_PRECISION, PERCENTAGE_PRECISION, ZERO } from '../';
|
|
3
|
+
|
|
4
|
+
export function calculateInitUserFee(stateAccount: StateAccount): BN {
|
|
5
|
+
const maxInitFee = new BN(stateAccount.maxInitializeUserFee)
|
|
6
|
+
.mul(LAMPORTS_PRECISION)
|
|
7
|
+
.divn(100);
|
|
8
|
+
const targetUtilization = PERCENTAGE_PRECISION.muln(8).divn(10);
|
|
9
|
+
|
|
10
|
+
const accountSpaceUtilization = stateAccount.numberOfSubAccounts
|
|
11
|
+
.addn(1)
|
|
12
|
+
.mul(PERCENTAGE_PRECISION)
|
|
13
|
+
.div(getMaxNumberOfSubAccounts(stateAccount));
|
|
14
|
+
|
|
15
|
+
if (accountSpaceUtilization.gt(targetUtilization)) {
|
|
16
|
+
return maxInitFee
|
|
17
|
+
.mul(accountSpaceUtilization.sub(targetUtilization))
|
|
18
|
+
.div(PERCENTAGE_PRECISION.sub(targetUtilization));
|
|
19
|
+
} else {
|
|
20
|
+
return ZERO;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function getMaxNumberOfSubAccounts(stateAccount: StateAccount): BN {
|
|
25
|
+
if (stateAccount.maxNumberOfSubAccounts <= 100) {
|
|
26
|
+
return new BN(stateAccount.maxNumberOfSubAccounts);
|
|
27
|
+
}
|
|
28
|
+
return new BN(stateAccount.maxNumberOfSubAccounts).muln(100);
|
|
29
|
+
}
|
|
@@ -10,6 +10,7 @@ import { WebsocketSubscription } from './WebsocketSubscription';
|
|
|
10
10
|
import StrictEventEmitter from 'strict-event-emitter-types';
|
|
11
11
|
import { EventEmitter } from 'events';
|
|
12
12
|
import { BN } from '../index';
|
|
13
|
+
import { decodeUser } from '../decode/user';
|
|
13
14
|
|
|
14
15
|
export class OrderSubscriber {
|
|
15
16
|
driftClient: DriftClient;
|
|
@@ -22,6 +23,7 @@ export class OrderSubscriber {
|
|
|
22
23
|
fetchPromiseResolver: () => void;
|
|
23
24
|
|
|
24
25
|
mostRecentSlot: number;
|
|
26
|
+
decodeFn: (name: string, data: Buffer) => UserAccount;
|
|
25
27
|
|
|
26
28
|
constructor(config: OrderSubscriberConfig) {
|
|
27
29
|
this.driftClient = config.driftClient;
|
|
@@ -39,6 +41,14 @@ export class OrderSubscriber {
|
|
|
39
41
|
resubTimeoutMs: config.subscriptionConfig.resubTimeoutMs,
|
|
40
42
|
});
|
|
41
43
|
}
|
|
44
|
+
if (config.fastDecode ?? true) {
|
|
45
|
+
this.decodeFn = (name, data) => decodeUser(data);
|
|
46
|
+
} else {
|
|
47
|
+
this.decodeFn =
|
|
48
|
+
this.driftClient.program.account.user.coder.accounts.decodeUnchecked.bind(
|
|
49
|
+
this.driftClient.program.account.user.coder.accounts
|
|
50
|
+
);
|
|
51
|
+
}
|
|
42
52
|
this.eventEmitter = new EventEmitter();
|
|
43
53
|
}
|
|
44
54
|
|
|
@@ -123,6 +133,13 @@ export class OrderSubscriber {
|
|
|
123
133
|
this.mostRecentSlot = slot;
|
|
124
134
|
}
|
|
125
135
|
|
|
136
|
+
this.eventEmitter.emit(
|
|
137
|
+
'updateReceived',
|
|
138
|
+
new PublicKey(key),
|
|
139
|
+
slot,
|
|
140
|
+
dataType
|
|
141
|
+
);
|
|
142
|
+
|
|
126
143
|
const slotAndUserAccount = this.usersAccounts.get(key);
|
|
127
144
|
if (!slotAndUserAccount || slotAndUserAccount.slot <= slot) {
|
|
128
145
|
let userAccount: UserAccount;
|
|
@@ -143,15 +160,19 @@ export class OrderSubscriber {
|
|
|
143
160
|
return;
|
|
144
161
|
}
|
|
145
162
|
|
|
146
|
-
userAccount =
|
|
147
|
-
this.driftClient.program.account.user.coder.accounts.decodeUnchecked(
|
|
148
|
-
'User',
|
|
149
|
-
buffer
|
|
150
|
-
) as UserAccount;
|
|
163
|
+
userAccount = this.decodeFn('User', buffer) as UserAccount;
|
|
151
164
|
} else {
|
|
152
165
|
userAccount = data as UserAccount;
|
|
153
166
|
}
|
|
154
167
|
|
|
168
|
+
this.eventEmitter.emit(
|
|
169
|
+
'userUpdated',
|
|
170
|
+
userAccount,
|
|
171
|
+
new PublicKey(key),
|
|
172
|
+
slot,
|
|
173
|
+
dataType
|
|
174
|
+
);
|
|
175
|
+
|
|
155
176
|
const newOrders = userAccount.orders.filter(
|
|
156
177
|
(order) =>
|
|
157
178
|
order.slot.toNumber() > (slotAndUserAccount?.slot ?? 0) &&
|
|
@@ -159,7 +180,7 @@ export class OrderSubscriber {
|
|
|
159
180
|
);
|
|
160
181
|
if (newOrders.length > 0) {
|
|
161
182
|
this.eventEmitter.emit(
|
|
162
|
-
'
|
|
183
|
+
'orderCreated',
|
|
163
184
|
userAccount,
|
|
164
185
|
newOrders,
|
|
165
186
|
new PublicKey(key),
|
|
@@ -38,9 +38,7 @@ export class WebsocketSubscription {
|
|
|
38
38
|
'OrderSubscriber',
|
|
39
39
|
'User',
|
|
40
40
|
this.orderSubscriber.driftClient.program,
|
|
41
|
-
this.orderSubscriber.
|
|
42
|
-
this.orderSubscriber.driftClient.program.account.user.coder.accounts
|
|
43
|
-
),
|
|
41
|
+
this.orderSubscriber.decodeFn,
|
|
44
42
|
{
|
|
45
43
|
filters: [getUserFilter(), getNonIdleUserFilter()],
|
|
46
44
|
commitment: this.commitment,
|