@drift-labs/sdk 2.49.0-beta.9 → 2.52.0-beta.0

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.
Files changed (62) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/{mockUserAccountSubscriber.d.ts → basicUserAccountSubscriber.d.ts} +2 -2
  3. package/lib/accounts/{mockUserAccountSubscriber.js → basicUserAccountSubscriber.js} +9 -6
  4. package/lib/adminClient.d.ts +1 -0
  5. package/lib/adminClient.js +8 -0
  6. package/lib/constants/perpMarkets.js +40 -0
  7. package/lib/constants/spotMarkets.js +10 -0
  8. package/lib/decode/user.d.ts +3 -0
  9. package/lib/decode/user.js +329 -0
  10. package/lib/driftClient.d.ts +5 -1
  11. package/lib/driftClient.js +28 -7
  12. package/lib/examples/loadDlob.js +10 -5
  13. package/lib/idl/drift.json +32 -2
  14. package/lib/index.d.ts +2 -1
  15. package/lib/index.js +2 -1
  16. package/lib/math/state.d.ts +5 -0
  17. package/lib/math/state.js +27 -0
  18. package/lib/math/superStake.d.ts +43 -0
  19. package/lib/math/superStake.js +64 -22
  20. package/lib/orderSubscriber/OrderSubscriber.d.ts +3 -0
  21. package/lib/orderSubscriber/OrderSubscriber.js +17 -3
  22. package/lib/orderSubscriber/WebsocketSubscription.d.ts +1 -1
  23. package/lib/orderSubscriber/WebsocketSubscription.js +8 -6
  24. package/lib/orderSubscriber/types.d.ts +4 -1
  25. package/lib/types.d.ts +2 -1
  26. package/lib/user.d.ts +2 -1
  27. package/lib/user.js +13 -5
  28. package/lib/userMap/PollingSubscription.d.ts +15 -0
  29. package/lib/userMap/PollingSubscription.js +28 -0
  30. package/lib/userMap/WebsocketSubscription.d.ts +23 -0
  31. package/lib/userMap/WebsocketSubscription.js +41 -0
  32. package/lib/userMap/userMap.d.ts +16 -18
  33. package/lib/userMap/userMap.js +73 -34
  34. package/lib/userMap/userMapConfig.d.ts +21 -0
  35. package/lib/userMap/userMapConfig.js +2 -0
  36. package/package.json +2 -1
  37. package/src/accounts/{mockUserAccountSubscriber.ts → basicUserAccountSubscriber.ts} +8 -6
  38. package/src/adminClient.ts +14 -0
  39. package/src/constants/perpMarkets.ts +40 -0
  40. package/src/constants/spotMarkets.ts +10 -0
  41. package/src/decode/user.ts +358 -0
  42. package/src/driftClient.ts +48 -7
  43. package/src/examples/loadDlob.ts +11 -6
  44. package/src/idl/drift.json +33 -3
  45. package/src/index.ts +2 -1
  46. package/src/math/state.ts +26 -0
  47. package/src/math/superStake.ts +108 -20
  48. package/src/orderSubscriber/OrderSubscriber.ts +33 -7
  49. package/src/orderSubscriber/WebsocketSubscription.ts +17 -16
  50. package/src/orderSubscriber/types.ts +15 -2
  51. package/src/types.ts +2 -1
  52. package/src/user.ts +19 -6
  53. package/src/userMap/PollingSubscription.ts +48 -0
  54. package/src/userMap/WebsocketSubscription.ts +76 -0
  55. package/src/userMap/userMap.ts +103 -70
  56. package/src/userMap/userMapConfig.ts +34 -0
  57. package/tests/amm/test.ts +6 -3
  58. package/tests/decode/test.ts +266 -0
  59. package/tests/decode/userAccountBufferStrings.ts +102 -0
  60. package/tests/dlob/helpers.ts +1 -0
  61. package/tests/dlob/test.ts +10 -8
  62. package/tests/user/helpers.ts +0 -1
@@ -0,0 +1,358 @@
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
+ quoteAssetAmount: undefined,
246
+ baseAssetAmountFilled,
247
+ quoteAssetAmountFilled,
248
+ triggerPrice,
249
+ auctionStartPrice,
250
+ auctionEndPrice,
251
+ maxTs,
252
+ oraclePriceOffset,
253
+ orderId,
254
+ marketIndex,
255
+ status,
256
+ orderType,
257
+ marketType,
258
+ userOrderId,
259
+ existingPositionDirection,
260
+ direction,
261
+ reduceOnly,
262
+ postOnly,
263
+ immediateOrCancel,
264
+ triggerCondition,
265
+ auctionDuration,
266
+ });
267
+ }
268
+
269
+ const lastAddPerpLpSharesTs = readSignedBigInt64LE(buffer, offset);
270
+ offset += 8;
271
+
272
+ const totalDeposits = readUnsignedBigInt64LE(buffer, offset);
273
+ offset += 8;
274
+
275
+ const totalWithdraws = readUnsignedBigInt64LE(buffer, offset);
276
+ offset += 8;
277
+
278
+ const totalSocialLoss = readUnsignedBigInt64LE(buffer, offset);
279
+ offset += 8;
280
+
281
+ const settledPerpPnl = readSignedBigInt64LE(buffer, offset);
282
+ offset += 8;
283
+
284
+ const cumulativeSpotFees = readSignedBigInt64LE(buffer, offset);
285
+ offset += 8;
286
+
287
+ const cumulativePerpFunding = readSignedBigInt64LE(buffer, offset);
288
+ offset += 8;
289
+
290
+ const liquidationMarginFreed = readUnsignedBigInt64LE(buffer, offset);
291
+ offset += 8;
292
+
293
+ const lastActiveSlot = readUnsignedBigInt64LE(buffer, offset);
294
+ offset += 8;
295
+
296
+ const nextOrderId = buffer.readUInt32LE(offset);
297
+ offset += 4;
298
+
299
+ const maxMarginRatio = buffer.readUInt32LE(offset);
300
+ offset += 4;
301
+
302
+ const nextLiquidationId = buffer.readUInt16LE(offset);
303
+ offset += 2;
304
+
305
+ const subAccountId = buffer.readUInt16LE(offset);
306
+ offset += 2;
307
+
308
+ const status = buffer.readUInt8(offset);
309
+ offset += 1;
310
+
311
+ const isMarginTradingEnabled = buffer.readUInt8(offset) === 1;
312
+ offset += 1;
313
+
314
+ const idle = buffer.readUInt8(offset) === 1;
315
+ offset += 1;
316
+
317
+ const openOrders = buffer.readUInt8(offset);
318
+ offset += 1;
319
+
320
+ const hasOpenOrder = buffer.readUInt8(offset) === 1;
321
+ offset += 1;
322
+
323
+ const openAuctions = buffer.readUInt8(offset);
324
+ offset += 1;
325
+
326
+ const hasOpenAuction = buffer.readUInt8(offset) === 1;
327
+ offset += 1;
328
+
329
+ // @ts-ignore
330
+ return {
331
+ authority,
332
+ delegate,
333
+ name,
334
+ spotPositions,
335
+ perpPositions,
336
+ orders,
337
+ lastAddPerpLpSharesTs,
338
+ totalDeposits,
339
+ totalWithdraws,
340
+ totalSocialLoss,
341
+ settledPerpPnl,
342
+ cumulativeSpotFees,
343
+ cumulativePerpFunding,
344
+ liquidationMarginFreed,
345
+ lastActiveSlot,
346
+ nextOrderId,
347
+ maxMarginRatio,
348
+ nextLiquidationId,
349
+ subAccountId,
350
+ status,
351
+ isMarginTradingEnabled,
352
+ idle,
353
+ openOrders,
354
+ hasOpenOrder,
355
+ openAuctions,
356
+ hasOpenAuction,
357
+ };
358
+ }
@@ -1811,6 +1811,9 @@ export class DriftClient {
1811
1811
  * @param subAccountId
1812
1812
  * @param name
1813
1813
  * @param fromSubAccountId
1814
+ * @param referrerInfo
1815
+ * @param donateAmount
1816
+ * @param txParams
1814
1817
  * @returns
1815
1818
  */
1816
1819
  public async initializeUserAccountAndDepositCollateral(
@@ -1821,6 +1824,7 @@ export class DriftClient {
1821
1824
  name?: string,
1822
1825
  fromSubAccountId?: number,
1823
1826
  referrerInfo?: ReferrerInfo,
1827
+ donateAmount?: BN,
1824
1828
  txParams?: TxParams
1825
1829
  ): Promise<[TransactionSignature, PublicKey]> {
1826
1830
  const ixs = [];
@@ -1856,14 +1860,26 @@ export class DriftClient {
1856
1860
  fromSubAccountId !== undefined &&
1857
1861
  !isNaN(fromSubAccountId);
1858
1862
 
1863
+ donateAmount = donateAmount ? donateAmount : ZERO;
1864
+
1859
1865
  const createWSOLTokenAccount =
1860
- isSolMarket && userTokenAccount.equals(authority) && !isFromSubaccount;
1866
+ (isSolMarket &&
1867
+ userTokenAccount.equals(authority) &&
1868
+ !isFromSubaccount) ||
1869
+ !donateAmount.eq(ZERO);
1861
1870
 
1871
+ const wSolAmount = isSolMarket ? amount.add(donateAmount) : donateAmount;
1872
+
1873
+ let wsolTokenAccount: PublicKey;
1862
1874
  if (createWSOLTokenAccount) {
1863
1875
  const { ixs: startIxs, pubkey } =
1864
- await this.getWrappedSolAccountCreationIxs(amount, true);
1876
+ await this.getWrappedSolAccountCreationIxs(wSolAmount, true);
1865
1877
 
1866
- userTokenAccount = pubkey;
1878
+ wsolTokenAccount = pubkey;
1879
+
1880
+ if (isSolMarket) {
1881
+ userTokenAccount = pubkey;
1882
+ }
1867
1883
 
1868
1884
  ixs.push(...startIxs);
1869
1885
  }
@@ -1893,11 +1909,21 @@ export class DriftClient {
1893
1909
  }
1894
1910
  ixs.push(initializeUserAccountIx, depositCollateralIx);
1895
1911
 
1912
+ if (!donateAmount.eq(ZERO)) {
1913
+ const donateIx = await this.getDepositIntoSpotMarketRevenuePoolIx(
1914
+ 1,
1915
+ donateAmount,
1916
+ wsolTokenAccount
1917
+ );
1918
+
1919
+ ixs.push(donateIx);
1920
+ }
1921
+
1896
1922
  // Close the wrapped sol account at the end of the transaction
1897
1923
  if (createWSOLTokenAccount) {
1898
1924
  ixs.push(
1899
1925
  createCloseAccountInstruction(
1900
- userTokenAccount,
1926
+ wsolTokenAccount,
1901
1927
  authority,
1902
1928
  authority,
1903
1929
  []
@@ -5995,13 +6021,13 @@ export class DriftClient {
5995
6021
  );
5996
6022
  }
5997
6023
 
5998
- public async depositIntoSpotMarketRevenuePool(
6024
+ public async getDepositIntoSpotMarketRevenuePoolIx(
5999
6025
  marketIndex: number,
6000
6026
  amount: BN,
6001
6027
  userTokenAccountPublicKey: PublicKey
6002
- ): Promise<TransactionSignature> {
6028
+ ): Promise<TransactionInstruction> {
6003
6029
  const spotMarket = await this.getSpotMarketAccount(marketIndex);
6004
- const tx = await this.program.transaction.depositIntoSpotMarketRevenuePool(
6030
+ const ix = await this.program.instruction.depositIntoSpotMarketRevenuePool(
6005
6031
  amount,
6006
6032
  {
6007
6033
  accounts: {
@@ -6015,6 +6041,21 @@ export class DriftClient {
6015
6041
  }
6016
6042
  );
6017
6043
 
6044
+ return ix;
6045
+ }
6046
+
6047
+ public async depositIntoSpotMarketRevenuePool(
6048
+ marketIndex: number,
6049
+ amount: BN,
6050
+ userTokenAccountPublicKey: PublicKey
6051
+ ): Promise<TransactionSignature> {
6052
+ const ix = await this.getDepositIntoSpotMarketRevenuePoolIx(
6053
+ marketIndex,
6054
+ amount,
6055
+ userTokenAccountPublicKey
6056
+ );
6057
+ const tx = await this.buildTransaction([ix]);
6058
+
6018
6059
  const { txSig } = await this.sendTransaction(tx, [], this.opts);
6019
6060
  return txSig;
6020
6061
  }
@@ -1,5 +1,5 @@
1
1
  import { AnchorProvider } from '@coral-xyz/anchor';
2
- import { DLOB, UserMap, Wallet } from '..';
2
+ import { UserMap, Wallet } from '..';
3
3
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
4
4
  import {
5
5
  DriftClient,
@@ -55,17 +55,22 @@ const main = async () => {
55
55
  await driftClient.subscribe();
56
56
 
57
57
  console.log('Loading user map...');
58
- const userMap = new UserMap(driftClient, {
59
- type: 'polling',
60
- accountLoader: bulkAccountLoader,
58
+ const userMap = new UserMap({
59
+ driftClient,
60
+ subscriptionConfig: {
61
+ type: 'websocket',
62
+ commitment: 'processed',
63
+ },
64
+ skipInitialLoad: false,
65
+ includeIdle: false,
61
66
  });
62
67
 
63
68
  // fetches all users and subscribes for updates
64
69
  await userMap.subscribe();
65
70
 
66
71
  console.log('Loading dlob from user map...');
67
- const dlob = new DLOB();
68
- await dlob.initFromUserMap(userMap, bulkAccountLoader.mostRecentSlot);
72
+ const slot = await driftClient.connection.getSlot();
73
+ const dlob = await userMap.getDLOB(slot);
69
74
 
70
75
  console.log('number of orders', dlob.getDLOBOrders().length);
71
76
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.48.0",
2
+ "version": "2.51.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -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
- 12
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
@@ -20,7 +20,7 @@ export * from './accounts/pollingTokenAccountSubscriber';
20
20
  export * from './accounts/pollingUserAccountSubscriber';
21
21
  export * from './accounts/pollingUserStatsAccountSubscriber';
22
22
  export * from './accounts/pollingInsuranceFundStakeAccountSubscriber';
23
- export * from './accounts/mockUserAccountSubscriber';
23
+ export * from './accounts/basicUserAccountSubscriber';
24
24
  export * from './accounts/types';
25
25
  export * from './addresses/pda';
26
26
  export * from './adminClient';
@@ -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,26 @@
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
+ return new BN(stateAccount.maxNumberOfSubAccounts).muln(100);
26
+ }