@drift-labs/sdk 2.38.1-beta.0 → 2.38.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/VERSION +1 -1
  2. package/lib/accounts/fetch.js +2 -2
  3. package/lib/accounts/pollingDriftClientAccountSubscriber.js +2 -2
  4. package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
  5. package/lib/adminClient.d.ts +1 -0
  6. package/lib/adminClient.js +11 -0
  7. package/lib/config.d.ts +1 -0
  8. package/lib/config.js +2 -0
  9. package/lib/driftClient.d.ts +22 -2
  10. package/lib/driftClient.js +101 -15
  11. package/lib/examples/loadDlob.js +3 -1
  12. package/lib/examples/makeTradeExample.js +3 -1
  13. package/lib/idl/drift.json +36 -1
  14. package/lib/index.d.ts +3 -0
  15. package/lib/index.js +3 -0
  16. package/lib/jupiter/jupiterClient.d.ts +197 -0
  17. package/lib/jupiter/jupiterClient.js +48 -3
  18. package/lib/math/spotBalance.d.ts +6 -5
  19. package/lib/math/spotBalance.js +28 -11
  20. package/lib/math/spotMarket.d.ts +1 -1
  21. package/lib/math/spotMarket.js +2 -2
  22. package/lib/math/spotPosition.d.ts +16 -3
  23. package/lib/math/spotPosition.js +53 -9
  24. package/lib/oracles/strictOraclePrice.d.ts +8 -0
  25. package/lib/oracles/strictOraclePrice.js +17 -0
  26. package/lib/priorityFee/priorityFeeSubscriber.d.ts +22 -0
  27. package/lib/priorityFee/priorityFeeSubscriber.js +46 -0
  28. package/lib/tokenFaucet.js +1 -0
  29. package/lib/types.d.ts +4 -0
  30. package/lib/types.js +3 -0
  31. package/lib/user.d.ts +5 -4
  32. package/lib/user.js +71 -105
  33. package/package.json +2 -2
  34. package/src/accounts/fetch.ts +2 -2
  35. package/src/accounts/pollingDriftClientAccountSubscriber.ts +2 -2
  36. package/src/accounts/pollingUserStatsAccountSubscriber.ts +10 -8
  37. package/src/adminClient.ts +23 -0
  38. package/src/config.ts +3 -0
  39. package/src/driftClient.ts +173 -13
  40. package/src/examples/loadDlob.ts +1 -0
  41. package/src/examples/makeTradeExample.ts +1 -0
  42. package/src/idl/drift.json +36 -1
  43. package/src/index.ts +3 -0
  44. package/src/jupiter/jupiterClient.ts +246 -3
  45. package/src/math/spotBalance.ts +37 -11
  46. package/src/math/spotMarket.ts +7 -1
  47. package/src/math/spotPosition.ts +133 -18
  48. package/src/oracles/strictOraclePrice.ts +19 -0
  49. package/src/priorityFee/priorityFeeSubscriber.ts +75 -0
  50. package/src/tokenFaucet.ts +1 -0
  51. package/src/types.ts +4 -0
  52. package/src/user.ts +171 -228
  53. package/tests/dlob/helpers.ts +10 -7
  54. package/tests/user/test.ts +77 -4
@@ -113,7 +113,12 @@ import { isSpotPositionAvailable } from './math/spotPosition';
113
113
  import { calculateMarketMaxAvailableInsurance } from './math/market';
114
114
  import { fetchUserStatsAccount } from './accounts/fetch';
115
115
  import { castNumberToSpotPrecision } from './math/spotMarket';
116
- import { JupiterClient, Route, SwapMode } from './jupiter/jupiterClient';
116
+ import {
117
+ JupiterClient,
118
+ QuoteResponse,
119
+ Route,
120
+ SwapMode,
121
+ } from './jupiter/jupiterClient';
117
122
  import { getNonIdleUserFilter } from './memcmp';
118
123
  import { UserStatsSubscriptionConfig } from './userStatsConfig';
119
124
  import { getMarinadeDepositIx, getMarinadeFinanceProgram } from './marinade';
@@ -174,6 +179,7 @@ export class DriftClient {
174
179
  this.opts = config.opts || AnchorProvider.defaultOptions();
175
180
  this.provider = new AnchorProvider(
176
181
  config.connection,
182
+ // @ts-ignore
177
183
  config.wallet,
178
184
  this.opts
179
185
  );
@@ -512,6 +518,7 @@ export class DriftClient {
512
518
  ): Promise<boolean> {
513
519
  const newProvider = new AnchorProvider(
514
520
  this.connection,
521
+ // @ts-ignore
515
522
  newWallet,
516
523
  this.opts
517
524
  );
@@ -2473,6 +2480,7 @@ export class DriftClient {
2473
2480
  );
2474
2481
  this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
2475
2482
 
2483
+ // @ts-ignore
2476
2484
  return { txSig, signedFillTx: signedVersionedFillTx };
2477
2485
  } else {
2478
2486
  const marketOrderTx = wrapInTx(
@@ -3415,6 +3423,7 @@ export class DriftClient {
3415
3423
  route,
3416
3424
  reduceOnly,
3417
3425
  txParams,
3426
+ v6,
3418
3427
  }: {
3419
3428
  jupiterClient: JupiterClient;
3420
3429
  outMarketIndex: number;
@@ -3427,19 +3436,44 @@ export class DriftClient {
3427
3436
  route?: Route;
3428
3437
  reduceOnly?: SwapReduceOnly;
3429
3438
  txParams?: TxParams;
3439
+ v6?: {
3440
+ quote?: QuoteResponse;
3441
+ };
3430
3442
  }): Promise<TransactionSignature> {
3431
- const { ixs, lookupTables } = await this.getJupiterSwapIx({
3432
- jupiterClient,
3433
- outMarketIndex,
3434
- inMarketIndex,
3435
- outAssociatedTokenAccount,
3436
- inAssociatedTokenAccount,
3437
- amount,
3438
- slippageBps,
3439
- swapMode,
3440
- route,
3441
- reduceOnly,
3442
- });
3443
+ let ixs: anchor.web3.TransactionInstruction[];
3444
+ let lookupTables: anchor.web3.AddressLookupTableAccount[];
3445
+
3446
+ if (v6) {
3447
+ const res = await this.getJupiterSwapIxV6({
3448
+ jupiterClient,
3449
+ outMarketIndex,
3450
+ inMarketIndex,
3451
+ outAssociatedTokenAccount,
3452
+ inAssociatedTokenAccount,
3453
+ amount,
3454
+ slippageBps,
3455
+ swapMode,
3456
+ quote: v6.quote,
3457
+ reduceOnly,
3458
+ });
3459
+ ixs = res.ixs;
3460
+ lookupTables = res.lookupTables;
3461
+ } else {
3462
+ const res = await this.getJupiterSwapIx({
3463
+ jupiterClient,
3464
+ outMarketIndex,
3465
+ inMarketIndex,
3466
+ outAssociatedTokenAccount,
3467
+ inAssociatedTokenAccount,
3468
+ amount,
3469
+ slippageBps,
3470
+ swapMode,
3471
+ route,
3472
+ reduceOnly,
3473
+ });
3474
+ ixs = res.ixs;
3475
+ lookupTables = res.lookupTables;
3476
+ }
3443
3477
 
3444
3478
  const tx = (await this.buildTransaction(
3445
3479
  ixs,
@@ -3585,6 +3619,132 @@ export class DriftClient {
3585
3619
  return { ixs, lookupTables };
3586
3620
  }
3587
3621
 
3622
+ public async getJupiterSwapIxV6({
3623
+ jupiterClient,
3624
+ outMarketIndex,
3625
+ inMarketIndex,
3626
+ outAssociatedTokenAccount,
3627
+ inAssociatedTokenAccount,
3628
+ amount,
3629
+ slippageBps,
3630
+ swapMode,
3631
+ onlyDirectRoutes,
3632
+ quote,
3633
+ reduceOnly,
3634
+ userAccountPublicKey,
3635
+ }: {
3636
+ jupiterClient: JupiterClient;
3637
+ outMarketIndex: number;
3638
+ inMarketIndex: number;
3639
+ outAssociatedTokenAccount?: PublicKey;
3640
+ inAssociatedTokenAccount?: PublicKey;
3641
+ amount: BN;
3642
+ slippageBps?: number;
3643
+ swapMode?: SwapMode;
3644
+ onlyDirectRoutes?: boolean;
3645
+ quote?: QuoteResponse;
3646
+ reduceOnly?: SwapReduceOnly;
3647
+ userAccountPublicKey?: PublicKey;
3648
+ }): Promise<{
3649
+ ixs: TransactionInstruction[];
3650
+ lookupTables: AddressLookupTableAccount[];
3651
+ }> {
3652
+ const outMarket = this.getSpotMarketAccount(outMarketIndex);
3653
+ const inMarket = this.getSpotMarketAccount(inMarketIndex);
3654
+
3655
+ if (!quote) {
3656
+ const fetchedQuote = await jupiterClient.getQuote({
3657
+ inputMint: inMarket.mint,
3658
+ outputMint: outMarket.mint,
3659
+ amount,
3660
+ slippageBps,
3661
+ swapMode,
3662
+ onlyDirectRoutes,
3663
+ });
3664
+
3665
+ quote = fetchedQuote;
3666
+ }
3667
+
3668
+ const transaction = await jupiterClient.getSwap({
3669
+ quote,
3670
+ userPublicKey: this.provider.wallet.publicKey,
3671
+ slippageBps,
3672
+ });
3673
+
3674
+ const { transactionMessage, lookupTables } =
3675
+ await jupiterClient.getTransactionMessageAndLookupTables({
3676
+ transaction,
3677
+ });
3678
+
3679
+ const jupiterInstructions = jupiterClient.getJupiterInstructions({
3680
+ transactionMessage,
3681
+ inputMint: inMarket.mint,
3682
+ outputMint: outMarket.mint,
3683
+ });
3684
+
3685
+ const preInstructions = [];
3686
+ if (!outAssociatedTokenAccount) {
3687
+ outAssociatedTokenAccount = await this.getAssociatedTokenAccount(
3688
+ outMarket.marketIndex,
3689
+ false
3690
+ );
3691
+
3692
+ const accountInfo = await this.connection.getAccountInfo(
3693
+ outAssociatedTokenAccount
3694
+ );
3695
+ if (!accountInfo) {
3696
+ preInstructions.push(
3697
+ this.createAssociatedTokenAccountIdempotentInstruction(
3698
+ outAssociatedTokenAccount,
3699
+ this.provider.wallet.publicKey,
3700
+ this.provider.wallet.publicKey,
3701
+ outMarket.mint
3702
+ )
3703
+ );
3704
+ }
3705
+ }
3706
+
3707
+ if (!inAssociatedTokenAccount) {
3708
+ inAssociatedTokenAccount = await this.getAssociatedTokenAccount(
3709
+ inMarket.marketIndex,
3710
+ false
3711
+ );
3712
+
3713
+ const accountInfo = await this.connection.getAccountInfo(
3714
+ inAssociatedTokenAccount
3715
+ );
3716
+ if (!accountInfo) {
3717
+ preInstructions.push(
3718
+ this.createAssociatedTokenAccountIdempotentInstruction(
3719
+ inAssociatedTokenAccount,
3720
+ this.provider.wallet.publicKey,
3721
+ this.provider.wallet.publicKey,
3722
+ inMarket.mint
3723
+ )
3724
+ );
3725
+ }
3726
+ }
3727
+
3728
+ const { beginSwapIx, endSwapIx } = await this.getSwapIx({
3729
+ outMarketIndex,
3730
+ inMarketIndex,
3731
+ amountIn: amount,
3732
+ inTokenAccount: inAssociatedTokenAccount,
3733
+ outTokenAccount: outAssociatedTokenAccount,
3734
+ reduceOnly,
3735
+ userAccountPublicKey,
3736
+ });
3737
+
3738
+ const ixs = [
3739
+ ...preInstructions,
3740
+ beginSwapIx,
3741
+ ...jupiterInstructions,
3742
+ endSwapIx,
3743
+ ];
3744
+
3745
+ return { ixs, lookupTables };
3746
+ }
3747
+
3588
3748
  /**
3589
3749
  * Get the drift begin_swap and end_swap instructions
3590
3750
  *
@@ -28,6 +28,7 @@ const main = async () => {
28
28
  // Set up the Provider
29
29
  const provider = new AnchorProvider(
30
30
  connection,
31
+ // @ts-ignore
31
32
  wallet,
32
33
  AnchorProvider.defaultOptions()
33
34
  );
@@ -51,6 +51,7 @@ const main = async () => {
51
51
  // Set up the Provider
52
52
  const provider = new AnchorProvider(
53
53
  connection,
54
+ // @ts-ignore
54
55
  wallet,
55
56
  AnchorProvider.defaultOptions()
56
57
  );
@@ -3538,6 +3538,32 @@
3538
3538
  }
3539
3539
  ]
3540
3540
  },
3541
+ {
3542
+ "name": "updateSpotMarketScaleInitialAssetWeightStart",
3543
+ "accounts": [
3544
+ {
3545
+ "name": "admin",
3546
+ "isMut": false,
3547
+ "isSigner": true
3548
+ },
3549
+ {
3550
+ "name": "state",
3551
+ "isMut": false,
3552
+ "isSigner": false
3553
+ },
3554
+ {
3555
+ "name": "spotMarket",
3556
+ "isMut": true,
3557
+ "isSigner": false
3558
+ }
3559
+ ],
3560
+ "args": [
3561
+ {
3562
+ "name": "scaleInitialAssetWeightStart",
3563
+ "type": "u64"
3564
+ }
3565
+ ]
3566
+ },
3541
3567
  {
3542
3568
  "name": "updateSpotMarketOracle",
3543
3569
  "accounts": [
@@ -5357,12 +5383,21 @@
5357
5383
  ],
5358
5384
  "type": "u64"
5359
5385
  },
5386
+ {
5387
+ "name": "scaleInitialAssetWeightStart",
5388
+ "docs": [
5389
+ "When to begin scaling down the initial asset weight",
5390
+ "disabled when 0",
5391
+ "precision: QUOTE_PRECISION"
5392
+ ],
5393
+ "type": "u64"
5394
+ },
5360
5395
  {
5361
5396
  "name": "padding",
5362
5397
  "type": {
5363
5398
  "array": [
5364
5399
  "u8",
5365
- 56
5400
+ 48
5366
5401
  ]
5367
5402
  }
5368
5403
  }
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import pyth from '@pythnetwork/client';
5
5
  export * from './tokenFaucet';
6
6
  export * from './oracles/types';
7
7
  export * from './oracles/pythClient';
8
+ export * from './oracles/strictOraclePrice';
8
9
  export * from './types';
9
10
  export * from './constants/perpMarkets';
10
11
  export * from './accounts/fetch';
@@ -49,6 +50,7 @@ export * from './math/repeg';
49
50
  export * from './math/margin';
50
51
  export * from './math/insurance';
51
52
  export * from './math/superStake';
53
+ export * from './math/spotPosition';
52
54
  export * from './marinade';
53
55
  export * from './orderParams';
54
56
  export * from './slot/SlotSubscriber';
@@ -60,6 +62,7 @@ export * from './constants/numericConstants';
60
62
  export * from './serum/serumSubscriber';
61
63
  export * from './serum/serumFulfillmentConfigMap';
62
64
  export * from './phoenix/phoenixSubscriber';
65
+ export * from './priorityFee/priorityFeeSubscriber';
63
66
  export * from './phoenix/phoenixFulfillmentConfigMap';
64
67
  export * from './tx/fastSingleTxSender';
65
68
  export * from './tx/retryTxSender';
@@ -41,8 +41,179 @@ export interface Route {
41
41
  swapMode: SwapMode;
42
42
  }
43
43
 
44
+ /**
45
+ *
46
+ * @export
47
+ * @interface RoutePlanStep
48
+ */
49
+ export interface RoutePlanStep {
50
+ /**
51
+ *
52
+ * @type {SwapInfo}
53
+ * @memberof RoutePlanStep
54
+ */
55
+ swapInfo: SwapInfo;
56
+ /**
57
+ *
58
+ * @type {number}
59
+ * @memberof RoutePlanStep
60
+ */
61
+ percent: number;
62
+ }
63
+
64
+ export interface SwapInfo {
65
+ /**
66
+ *
67
+ * @type {string}
68
+ * @memberof SwapInfo
69
+ */
70
+ ammKey: string;
71
+ /**
72
+ *
73
+ * @type {string}
74
+ * @memberof SwapInfo
75
+ */
76
+ label?: string;
77
+ /**
78
+ *
79
+ * @type {string}
80
+ * @memberof SwapInfo
81
+ */
82
+ inputMint: string;
83
+ /**
84
+ *
85
+ * @type {string}
86
+ * @memberof SwapInfo
87
+ */
88
+ outputMint: string;
89
+ /**
90
+ *
91
+ * @type {string}
92
+ * @memberof SwapInfo
93
+ */
94
+ inAmount: string;
95
+ /**
96
+ *
97
+ * @type {string}
98
+ * @memberof SwapInfo
99
+ */
100
+ outAmount: string;
101
+ /**
102
+ *
103
+ * @type {string}
104
+ * @memberof SwapInfo
105
+ */
106
+ feeAmount: string;
107
+ /**
108
+ *
109
+ * @type {string}
110
+ * @memberof SwapInfo
111
+ */
112
+ feeMint: string;
113
+ }
114
+
115
+ /**
116
+ *
117
+ * @export
118
+ * @interface PlatformFee
119
+ */
120
+ export interface PlatformFee {
121
+ /**
122
+ *
123
+ * @type {string}
124
+ * @memberof PlatformFee
125
+ */
126
+ amount?: string;
127
+ /**
128
+ *
129
+ * @type {number}
130
+ * @memberof PlatformFee
131
+ */
132
+ feeBps?: number;
133
+ }
134
+
135
+ /**
136
+ *
137
+ * @export
138
+ * @interface QuoteResponse
139
+ */
140
+ export interface QuoteResponse {
141
+ /**
142
+ *
143
+ * @type {string}
144
+ * @memberof QuoteResponse
145
+ */
146
+ inputMint: string;
147
+ /**
148
+ *
149
+ * @type {string}
150
+ * @memberof QuoteResponse
151
+ */
152
+ inAmount: string;
153
+ /**
154
+ *
155
+ * @type {string}
156
+ * @memberof QuoteResponse
157
+ */
158
+ outputMint: string;
159
+ /**
160
+ *
161
+ * @type {string}
162
+ * @memberof QuoteResponse
163
+ */
164
+ outAmount: string;
165
+ /**
166
+ *
167
+ * @type {string}
168
+ * @memberof QuoteResponse
169
+ */
170
+ otherAmountThreshold: string;
171
+ /**
172
+ *
173
+ * @type {SwapMode}
174
+ * @memberof QuoteResponse
175
+ */
176
+ swapMode: SwapMode;
177
+ /**
178
+ *
179
+ * @type {number}
180
+ * @memberof QuoteResponse
181
+ */
182
+ slippageBps: number;
183
+ /**
184
+ *
185
+ * @type {PlatformFee}
186
+ * @memberof QuoteResponse
187
+ */
188
+ platformFee?: PlatformFee;
189
+ /**
190
+ *
191
+ * @type {string}
192
+ * @memberof QuoteResponse
193
+ */
194
+ priceImpactPct: string;
195
+ /**
196
+ *
197
+ * @type {Array<RoutePlanStep>}
198
+ * @memberof QuoteResponse
199
+ */
200
+ routePlan: Array<RoutePlanStep>;
201
+ /**
202
+ *
203
+ * @type {number}
204
+ * @memberof QuoteResponse
205
+ */
206
+ contextSlot?: number;
207
+ /**
208
+ *
209
+ * @type {number}
210
+ * @memberof QuoteResponse
211
+ */
212
+ timeTaken?: number;
213
+ }
214
+
44
215
  export class JupiterClient {
45
- url = 'https://quote-api.jup.ag/v4';
216
+ url = 'https://quote-api.jup.ag';
46
217
  connection: Connection;
47
218
  lookupTableCahce = new Map<string, AddressLookupTableAccount>();
48
219
 
@@ -51,6 +222,7 @@ export class JupiterClient {
51
222
  }
52
223
 
53
224
  /**
225
+ * ** @deprecated - use getQuote
54
226
  * Get routes for a swap
55
227
  * @param inputMint the mint of the input token
56
228
  * @param outputMint the mint of the output token
@@ -84,13 +256,84 @@ export class JupiterClient {
84
256
  }).toString();
85
257
 
86
258
  const { data: routes } = await (
87
- await fetch(`https://quote-api.jup.ag/v4/quote?${params}`)
259
+ await fetch(`${this.url}/v4/quote?${params}`)
88
260
  ).json();
89
261
 
90
262
  return routes;
91
263
  }
92
264
 
93
265
  /**
266
+ * Get routes for a swap
267
+ * @param inputMint the mint of the input token
268
+ * @param outputMint the mint of the output token
269
+ * @param amount the amount of the input token
270
+ * @param slippageBps the slippage tolerance in basis points
271
+ * @param swapMode the swap mode (ExactIn or ExactOut)
272
+ * @param onlyDirectRoutes whether to only return direct routes
273
+ */
274
+ public async getQuote({
275
+ inputMint,
276
+ outputMint,
277
+ amount,
278
+ slippageBps = 50,
279
+ swapMode = 'ExactIn',
280
+ onlyDirectRoutes = false,
281
+ }: {
282
+ inputMint: PublicKey;
283
+ outputMint: PublicKey;
284
+ amount: BN;
285
+ slippageBps?: number;
286
+ swapMode?: SwapMode;
287
+ onlyDirectRoutes?: boolean;
288
+ }): Promise<QuoteResponse> {
289
+ const params = new URLSearchParams({
290
+ inputMint: inputMint.toString(),
291
+ outputMint: outputMint.toString(),
292
+ amount: amount.toString(),
293
+ slippageBps: slippageBps.toString(),
294
+ swapMode,
295
+ onlyDirectRoutes: onlyDirectRoutes.toString(),
296
+ }).toString();
297
+ const quote = await (await fetch(`${this.url}/v6/quote?${params}`)).json();
298
+ return quote;
299
+ }
300
+
301
+ /**
302
+ * Get a swap transaction for quote
303
+ * @param quoteResponse quote to perform swap
304
+ * @param userPublicKey the signer's wallet public key
305
+ * @param slippageBps the slippage tolerance in basis points
306
+ */
307
+ public async getSwap({
308
+ quote,
309
+ userPublicKey,
310
+ slippageBps = 50,
311
+ }: {
312
+ quote: QuoteResponse;
313
+ userPublicKey: PublicKey;
314
+ slippageBps?: number;
315
+ }): Promise<VersionedTransaction> {
316
+ const resp = await (
317
+ await fetch(`${this.url}/v6/swap`, {
318
+ method: 'POST',
319
+ headers: {
320
+ 'Content-Type': 'application/json',
321
+ },
322
+ body: JSON.stringify({
323
+ quoteResponse: quote,
324
+ userPublicKey,
325
+ slippageBps,
326
+ }),
327
+ })
328
+ ).json();
329
+ const { swapTransaction } = resp;
330
+
331
+ const swapTransactionBuf = Buffer.from(swapTransaction, 'base64');
332
+ return VersionedTransaction.deserialize(swapTransactionBuf);
333
+ }
334
+
335
+ /**
336
+ * ** @deprecated - use getSwap
94
337
  * Get a swap transaction for a route
95
338
  * @param route the route to perform swap
96
339
  * @param userPublicKey the signer's wallet public key
@@ -106,7 +349,7 @@ export class JupiterClient {
106
349
  slippageBps?: number;
107
350
  }): Promise<VersionedTransaction> {
108
351
  const resp = await (
109
- await fetch(`${this.url}/swap`, {
352
+ await fetch(`${this.url}/v4/swap`, {
110
353
  method: 'POST',
111
354
  headers: {
112
355
  'Content-Type': 'application/json',
@@ -22,6 +22,7 @@ import {
22
22
  import { OraclePriceData } from '../oracles/types';
23
23
  import { PERCENTAGE_PRECISION } from '../constants/numericConstants';
24
24
  import { divCeil } from './utils';
25
+ import { StrictOraclePrice } from '../oracles/strictOraclePrice';
25
26
 
26
27
  /**
27
28
  * Calculates the balance of a given token amount including any accumulated interest. This
@@ -102,25 +103,23 @@ export function getSignedTokenAmount(
102
103
  *
103
104
  * @param {BN} tokenAmount - The amount of tokens to calculate the value for (from `getTokenAmount`)
104
105
  * @param {number} spotDecimals - The number of decimals in the token.
105
- * @param {OraclePriceData} oraclePriceData - The oracle price data (typically a token/USD oracle).
106
- * @param {BN} oraclePriceTwap - The Time-Weighted Average Price of the oracle.
106
+ * @param {StrictOraclePrice} strictOraclePrice - Contains oracle price and 5min twap.
107
107
  * @return {BN} The calculated value of the given token amount, scaled by `PRICE_PRECISION`
108
108
  */
109
109
  export function getStrictTokenValue(
110
110
  tokenAmount: BN,
111
111
  spotDecimals: number,
112
- oraclePriceData: OraclePriceData,
113
- oraclePriceTwap: BN
112
+ strictOraclePrice: StrictOraclePrice
114
113
  ): BN {
115
114
  if (tokenAmount.eq(ZERO)) {
116
115
  return ZERO;
117
116
  }
118
117
 
119
- let price = oraclePriceData.price;
120
- if (tokenAmount.gt(ZERO)) {
121
- price = BN.min(oraclePriceData.price, oraclePriceTwap);
118
+ let price;
119
+ if (tokenAmount.gte(ZERO)) {
120
+ price = strictOraclePrice.min();
122
121
  } else {
123
- price = BN.max(oraclePriceData.price, oraclePriceTwap);
122
+ price = strictOraclePrice.max();
124
123
  }
125
124
 
126
125
  const precisionDecrease = TEN.pow(new BN(spotDecimals));
@@ -139,7 +138,7 @@ export function getStrictTokenValue(
139
138
  export function getTokenValue(
140
139
  tokenAmount: BN,
141
140
  spotDecimals: number,
142
- oraclePriceData: OraclePriceData
141
+ oraclePriceData: Pick<OraclePriceData, 'price'>
143
142
  ): BN {
144
143
  if (tokenAmount.eq(ZERO)) {
145
144
  return ZERO;
@@ -152,6 +151,7 @@ export function getTokenValue(
152
151
 
153
152
  export function calculateAssetWeight(
154
153
  balanceAmount: BN,
154
+ oraclePrice: BN,
155
155
  spotMarket: SpotMarketAccount,
156
156
  marginCategory: MarginCategory
157
157
  ): BN {
@@ -174,7 +174,7 @@ export function calculateAssetWeight(
174
174
  assetWeight = calculateSizeDiscountAssetWeight(
175
175
  sizeInAmmReservePrecision,
176
176
  new BN(spotMarket.imfFactor),
177
- new BN(spotMarket.initialAssetWeight)
177
+ calculateScaledInitialAssetWeight(spotMarket, oraclePrice)
178
178
  );
179
179
  break;
180
180
  case 'Maintenance':
@@ -185,13 +185,39 @@ export function calculateAssetWeight(
185
185
  );
186
186
  break;
187
187
  default:
188
- assetWeight = new BN(spotMarket.initialAssetWeight);
188
+ assetWeight = calculateScaledInitialAssetWeight(spotMarket, oraclePrice);
189
189
  break;
190
190
  }
191
191
 
192
192
  return assetWeight;
193
193
  }
194
194
 
195
+ export function calculateScaledInitialAssetWeight(
196
+ spotMarket: SpotMarketAccount,
197
+ oraclePrice: BN
198
+ ): BN {
199
+ if (spotMarket.scaleInitialAssetWeightStart.eq(ZERO)) {
200
+ return new BN(spotMarket.initialAssetWeight);
201
+ }
202
+
203
+ const deposits = getTokenAmount(
204
+ spotMarket.depositBalance,
205
+ spotMarket,
206
+ SpotBalanceType.DEPOSIT
207
+ );
208
+ const depositsValue = getTokenValue(deposits, spotMarket.decimals, {
209
+ price: oraclePrice,
210
+ });
211
+
212
+ if (depositsValue.lt(spotMarket.scaleInitialAssetWeightStart)) {
213
+ return new BN(spotMarket.initialAssetWeight);
214
+ } else {
215
+ return new BN(spotMarket.initialAssetWeight)
216
+ .mul(spotMarket.scaleInitialAssetWeightStart)
217
+ .div(depositsValue);
218
+ }
219
+ }
220
+
195
221
  export function calculateLiabilityWeight(
196
222
  size: BN,
197
223
  spotMarket: SpotMarketAccount,