@drift-labs/sdk 0.2.0-master.1 → 0.2.0-master.2

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.
@@ -414,17 +414,14 @@
414
414
  "name": "authority",
415
415
  "isMut": false,
416
416
  "isSigner": true
417
- },
418
- {
419
- "name": "oracle",
420
- "isMut": false,
421
- "isSigner": false
422
417
  }
423
418
  ],
424
419
  "args": [
425
420
  {
426
421
  "name": "orderId",
427
- "type": "u64"
422
+ "type": {
423
+ "option": "u64"
424
+ }
428
425
  }
429
426
  ]
430
427
  },
@@ -445,11 +442,6 @@
445
442
  "name": "authority",
446
443
  "isMut": false,
447
444
  "isSigner": true
448
- },
449
- {
450
- "name": "oracle",
451
- "isMut": false,
452
- "isSigner": false
453
445
  }
454
446
  ],
455
447
  "args": [
@@ -491,7 +483,9 @@
491
483
  "args": [
492
484
  {
493
485
  "name": "orderId",
494
- "type": "u64"
486
+ "type": {
487
+ "option": "u64"
488
+ }
495
489
  },
496
490
  {
497
491
  "name": "makerOrderId",
@@ -582,6 +576,37 @@
582
576
  }
583
577
  ]
584
578
  },
579
+ {
580
+ "name": "triggerOrder",
581
+ "accounts": [
582
+ {
583
+ "name": "state",
584
+ "isMut": false,
585
+ "isSigner": false
586
+ },
587
+ {
588
+ "name": "authority",
589
+ "isMut": false,
590
+ "isSigner": true
591
+ },
592
+ {
593
+ "name": "filler",
594
+ "isMut": true,
595
+ "isSigner": false
596
+ },
597
+ {
598
+ "name": "user",
599
+ "isMut": true,
600
+ "isSigner": false
601
+ }
602
+ ],
603
+ "args": [
604
+ {
605
+ "name": "orderId",
606
+ "type": "u64"
607
+ }
608
+ ]
609
+ },
585
610
  {
586
611
  "name": "updateAmms",
587
612
  "accounts": [
@@ -993,11 +1018,6 @@
993
1018
  "name": "user",
994
1019
  "isMut": true,
995
1020
  "isSigner": false
996
- },
997
- {
998
- "name": "market",
999
- "isMut": false,
1000
- "isSigner": false
1001
1021
  }
1002
1022
  ],
1003
1023
  "args": []
@@ -1389,6 +1409,32 @@
1389
1409
  }
1390
1410
  ]
1391
1411
  },
1412
+ {
1413
+ "name": "updateMarketMaxSpread",
1414
+ "accounts": [
1415
+ {
1416
+ "name": "admin",
1417
+ "isMut": false,
1418
+ "isSigner": true
1419
+ },
1420
+ {
1421
+ "name": "state",
1422
+ "isMut": false,
1423
+ "isSigner": false
1424
+ },
1425
+ {
1426
+ "name": "market",
1427
+ "isMut": true,
1428
+ "isSigner": false
1429
+ }
1430
+ ],
1431
+ "args": [
1432
+ {
1433
+ "name": "maxSpread",
1434
+ "type": "u32"
1435
+ }
1436
+ ]
1437
+ },
1392
1438
  {
1393
1439
  "name": "updateMarketBaseAssetAmountStepSize",
1394
1440
  "accounts": [
@@ -2194,6 +2240,10 @@
2194
2240
  "name": "shortSpread",
2195
2241
  "type": "u128"
2196
2242
  },
2243
+ {
2244
+ "name": "maxSpread",
2245
+ "type": "u32"
2246
+ },
2197
2247
  {
2198
2248
  "name": "askBaseAssetReserve",
2199
2249
  "type": "u128"
@@ -2252,7 +2302,7 @@
2252
2302
  },
2253
2303
  {
2254
2304
  "name": "totalFeeMinusDistributions",
2255
- "type": "u128"
2305
+ "type": "i128"
2256
2306
  },
2257
2307
  {
2258
2308
  "name": "totalFeeWithdrawn",
@@ -2712,6 +2762,10 @@
2712
2762
  "defined": "OrderTriggerCondition"
2713
2763
  }
2714
2764
  },
2765
+ {
2766
+ "name": "triggered",
2767
+ "type": "bool"
2768
+ },
2715
2769
  {
2716
2770
  "name": "referrer",
2717
2771
  "type": "publicKey"
@@ -2848,6 +2902,9 @@
2848
2902
  {
2849
2903
  "name": "Fill"
2850
2904
  },
2905
+ {
2906
+ "name": "Trigger"
2907
+ },
2851
2908
  {
2852
2909
  "name": "Expire"
2853
2910
  }
@@ -3016,6 +3073,11 @@
3016
3073
  "type": "u64",
3017
3074
  "index": false
3018
3075
  },
3076
+ {
3077
+ "name": "oraclePrice",
3078
+ "type": "i128",
3079
+ "index": false
3080
+ },
3019
3081
  {
3020
3082
  "name": "from",
3021
3083
  "type": {
@@ -3217,7 +3279,7 @@
3217
3279
  },
3218
3280
  {
3219
3281
  "name": "totalFeeMinusDistributions",
3220
- "type": "u128",
3282
+ "type": "i128",
3221
3283
  "index": false
3222
3284
  },
3223
3285
  {
@@ -3349,6 +3411,16 @@
3349
3411
  },
3350
3412
  "index": false
3351
3413
  },
3414
+ {
3415
+ "name": "makerUnsettledPnl",
3416
+ "type": "i128",
3417
+ "index": false
3418
+ },
3419
+ {
3420
+ "name": "takerUnsettledPnl",
3421
+ "type": "i128",
3422
+ "index": false
3423
+ },
3352
3424
  {
3353
3425
  "name": "action",
3354
3426
  "type": {
@@ -3854,6 +3926,21 @@
3854
3926
  },
3855
3927
  {
3856
3928
  "code": 6087,
3929
+ "name": "OrderMustBeTriggeredFirst",
3930
+ "msg": "OrderMustBeTriggeredFirst"
3931
+ },
3932
+ {
3933
+ "code": 6088,
3934
+ "name": "OrderNotTriggerable",
3935
+ "msg": "OrderNotTriggerable"
3936
+ },
3937
+ {
3938
+ "code": 6089,
3939
+ "name": "OrderDidNotSatisfyTriggerCondition",
3940
+ "msg": "OrderDidNotSatisfyTriggerCondition"
3941
+ },
3942
+ {
3943
+ "code": 6090,
3857
3944
  "name": "DefaultError",
3858
3945
  "msg": "DefaultError"
3859
3946
  }
package/src/math/amm.ts CHANGED
@@ -6,8 +6,10 @@ import {
6
6
  ZERO,
7
7
  BID_ASK_SPREAD_PRECISION,
8
8
  ONE,
9
- // QUOTE_PRECISION,
10
9
  AMM_TO_QUOTE_PRECISION_RATIO,
10
+ QUOTE_PRECISION,
11
+ MARGIN_PRECISION,
12
+ PRICE_DIV_PEG,
11
13
  } from '../constants/numericConstants';
12
14
  import {
13
15
  AMM,
@@ -25,6 +27,70 @@ import {
25
27
  calculateAdjustKCost,
26
28
  calculateBudgetedPeg,
27
29
  } from './repeg';
30
+
31
+ export function calculatePegFromTargetPrice(
32
+ targetPrice: BN,
33
+ baseAssetReserve: BN,
34
+ quoteAssetReserve: BN
35
+ ): BN {
36
+ return targetPrice
37
+ .mul(baseAssetReserve)
38
+ .div(quoteAssetReserve)
39
+ .add(PRICE_DIV_PEG.div(new BN(2)))
40
+ .div(PRICE_DIV_PEG);
41
+ }
42
+
43
+ export function calculateOptimalPegAndBudget(
44
+ amm: AMM,
45
+ oraclePriceData: OraclePriceData
46
+ ): [BN, BN, BN, boolean] {
47
+ const markPriceBefore = calculatePrice(
48
+ amm.baseAssetReserve,
49
+ amm.quoteAssetReserve,
50
+ amm.pegMultiplier
51
+ );
52
+ const targetPrice = oraclePriceData.price;
53
+ const newPeg = calculatePegFromTargetPrice(
54
+ targetPrice,
55
+ amm.baseAssetReserve,
56
+ amm.quoteAssetReserve
57
+ );
58
+ const prePegCost = calculateRepegCost(amm, newPeg);
59
+
60
+ const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
61
+ const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
62
+ if (budget.lt(prePegCost)) {
63
+ const maxPriceSpread = new BN(amm.maxSpread)
64
+ .mul(targetPrice)
65
+ .div(BID_ASK_SPREAD_PRECISION);
66
+
67
+ let newTargetPrice: BN;
68
+ let newOptimalPeg: BN;
69
+ let newBudget: BN;
70
+ const targetPriceGap = markPriceBefore.sub(targetPrice);
71
+ if (targetPriceGap.abs().gt(maxPriceSpread)) {
72
+ const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
73
+
74
+ if (targetPriceGap.lt(new BN(0))) {
75
+ newTargetPrice = markPriceBefore.add(markAdj);
76
+ } else {
77
+ newTargetPrice = markPriceBefore.sub(markAdj);
78
+ }
79
+
80
+ newOptimalPeg = calculatePegFromTargetPrice(
81
+ newTargetPrice,
82
+ amm.baseAssetReserve,
83
+ amm.quoteAssetReserve
84
+ );
85
+
86
+ newBudget = calculateRepegCost(amm, newOptimalPeg);
87
+ return [newTargetPrice, newOptimalPeg, newBudget, false];
88
+ }
89
+ }
90
+
91
+ return [targetPrice, newPeg, budget, true];
92
+ }
93
+
28
94
  export function calculateNewAmm(
29
95
  amm: AMM,
30
96
  oraclePriceData: OraclePriceData
@@ -32,18 +98,12 @@ export function calculateNewAmm(
32
98
  let pKNumer = new BN(1);
33
99
  let pKDenom = new BN(1);
34
100
 
35
- const targetPrice = oraclePriceData.price;
36
- let newPeg = targetPrice
37
- .mul(amm.baseAssetReserve)
38
- .div(amm.quoteAssetReserve)
39
- .add(MARK_PRICE_PRECISION.div(PEG_PRECISION).div(new BN(2)))
40
- .div(MARK_PRICE_PRECISION.div(PEG_PRECISION));
41
- let prePegCost = calculateRepegCost(amm, newPeg);
42
-
43
- const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
44
- const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
101
+ const [targetPrice, _newPeg, budget, checkLowerBound] =
102
+ calculateOptimalPegAndBudget(amm, oraclePriceData);
103
+ let prePegCost = calculateRepegCost(amm, _newPeg);
104
+ let newPeg = _newPeg;
45
105
 
46
- if (prePegCost.gt(budget)) {
106
+ if (prePegCost.gt(budget) && checkLowerBound) {
47
107
  [pKNumer, pKDenom] = [new BN(999), new BN(1000)];
48
108
  const deficitMadeup = calculateAdjustKCost(amm, pKNumer, pKDenom);
49
109
  assert(deficitMadeup.lte(new BN(0)));
@@ -136,9 +196,16 @@ export function calculateUpdatedAMMSpreadReserves(
136
196
 
137
197
  export function calculateBidAskPrice(
138
198
  amm: AMM,
139
- oraclePriceData: OraclePriceData
199
+ oraclePriceData: OraclePriceData,
200
+ withUpdate = true
140
201
  ): [BN, BN] {
141
- const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
202
+ let newAmm: AMM;
203
+ if (withUpdate) {
204
+ newAmm = calculateUpdatedAMM(amm, oraclePriceData);
205
+ } else {
206
+ newAmm = amm;
207
+ }
208
+
142
209
  const askReserves = calculateSpreadReserves(
143
210
  newAmm,
144
211
  PositionDirection.LONG,
@@ -237,6 +304,108 @@ export function calculateAmmReservesAfterSwap(
237
304
  return [newQuoteAssetReserve, newBaseAssetReserve];
238
305
  }
239
306
 
307
+ export function calculateEffectiveLeverage(
308
+ baseSpread: number,
309
+ quoteAssetReserve: BN,
310
+ terminalQuoteAssetReserve: BN,
311
+ pegMultiplier: BN,
312
+ netBaseAssetAmount: BN,
313
+ markPrice: BN,
314
+ totalFeeMinusDistributions: BN
315
+ ): number {
316
+ // inventory skew
317
+ const netBaseAssetValue = quoteAssetReserve
318
+ .sub(terminalQuoteAssetReserve)
319
+ .mul(pegMultiplier)
320
+ .div(AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
321
+
322
+ const localBaseAssetValue = netBaseAssetAmount
323
+ .mul(markPrice)
324
+ .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
325
+
326
+ const effectiveLeverage =
327
+ localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
328
+ (Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
329
+ 1 / QUOTE_PRECISION.toNumber();
330
+
331
+ return effectiveLeverage;
332
+ }
333
+
334
+ export function calculateMaxSpread(marginRatioInitial: number): number {
335
+ const maxTargetSpread: number = new BN(marginRatioInitial)
336
+ .mul(BID_ASK_SPREAD_PRECISION.div(MARGIN_PRECISION))
337
+ .toNumber();
338
+
339
+ return maxTargetSpread;
340
+ }
341
+
342
+ export function calculateSpreadBN(
343
+ baseSpread: number,
344
+ lastOracleMarkSpreadPct: BN,
345
+ lastOracleConfPct: BN,
346
+ maxSpread: number,
347
+ quoteAssetReserve: BN,
348
+ terminalQuoteAssetReserve: BN,
349
+ pegMultiplier: BN,
350
+ netBaseAssetAmount: BN,
351
+ markPrice: BN,
352
+ totalFeeMinusDistributions: BN
353
+ ): [number, number] {
354
+ let longSpread = baseSpread / 2;
355
+ let shortSpread = baseSpread / 2;
356
+
357
+ if (lastOracleMarkSpreadPct.gt(ZERO)) {
358
+ shortSpread = Math.max(
359
+ shortSpread,
360
+ lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
361
+ );
362
+ } else if (lastOracleMarkSpreadPct.lt(ZERO)) {
363
+ longSpread = Math.max(
364
+ longSpread,
365
+ lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber()
366
+ );
367
+ }
368
+
369
+ const maxTargetSpread: number = maxSpread;
370
+
371
+ const MAX_INVENTORY_SKEW = 5;
372
+
373
+ const effectiveLeverage = calculateEffectiveLeverage(
374
+ baseSpread,
375
+ quoteAssetReserve,
376
+ terminalQuoteAssetReserve,
377
+ pegMultiplier,
378
+ netBaseAssetAmount,
379
+ markPrice,
380
+ totalFeeMinusDistributions
381
+ );
382
+
383
+ if (totalFeeMinusDistributions.gt(ZERO)) {
384
+ const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
385
+ if (netBaseAssetAmount.gt(ZERO)) {
386
+ longSpread *= spreadScale;
387
+ } else {
388
+ shortSpread *= spreadScale;
389
+ }
390
+ } else {
391
+ longSpread *= MAX_INVENTORY_SKEW;
392
+ shortSpread *= MAX_INVENTORY_SKEW;
393
+ }
394
+
395
+ const totalSpread = longSpread + shortSpread;
396
+ if (totalSpread > maxTargetSpread) {
397
+ if (longSpread > shortSpread) {
398
+ longSpread = Math.min(longSpread, maxTargetSpread);
399
+ shortSpread = maxTargetSpread - longSpread;
400
+ } else {
401
+ shortSpread = Math.min(shortSpread, maxTargetSpread);
402
+ longSpread = maxTargetSpread - shortSpread;
403
+ }
404
+ }
405
+
406
+ return [longSpread, shortSpread];
407
+ }
408
+
240
409
  export function calculateSpread(
241
410
  amm: AMM,
242
411
  direction: PositionDirection,
@@ -255,18 +424,26 @@ export function calculateSpread(
255
424
  );
256
425
 
257
426
  const targetPrice = oraclePriceData?.price || markPrice;
427
+ const confInterval = oraclePriceData.confidence || ZERO;
258
428
 
259
429
  const targetMarkSpreadPct = markPrice
260
430
  .sub(targetPrice)
261
431
  .mul(BID_ASK_SPREAD_PRECISION)
262
432
  .div(markPrice);
263
433
 
434
+ const confIntervalPct = confInterval
435
+ .mul(BID_ASK_SPREAD_PRECISION)
436
+ .div(markPrice);
437
+
264
438
  // oracle retreat
265
439
  if (
266
440
  (isVariant(direction, 'long') && targetMarkSpreadPct.lt(ZERO)) ||
267
441
  (isVariant(direction, 'short') && targetMarkSpreadPct.gt(ZERO))
268
442
  ) {
269
- spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
443
+ spread = Math.max(
444
+ spread,
445
+ targetMarkSpreadPct.abs().toNumber() + confIntervalPct.abs().toNumber()
446
+ );
270
447
  }
271
448
 
272
449
  // inventory skew
@@ -294,10 +471,18 @@ export function calculateSpread(
294
471
  if (amm.totalFeeMinusDistributions.gt(ZERO)) {
295
472
  effectiveLeverage =
296
473
  localPnl.sub(netPnl).toNumber() /
297
- amm.totalFeeMinusDistributions.toNumber();
474
+ (amm.totalFeeMinusDistributions.toNumber() + 1);
475
+ }
476
+
477
+ let spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
478
+ const maxTargetSpread = BID_ASK_SPREAD_PRECISION.toNumber() / 50; // 2%
479
+ // cap the scale to attempt to only scale up to maxTargetSpread
480
+ // always let the oracle retreat methods go through 100%
481
+ if (spreadScale * spread > maxTargetSpread) {
482
+ spreadScale = Math.max(1.05, maxTargetSpread / spread);
298
483
  }
299
484
 
300
- spread *= Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
485
+ spread *= spreadScale;
301
486
  }
302
487
 
303
488
  return spread;
package/src/math/repeg.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  AMM_RESERVE_PRECISION,
6
6
  PEG_PRECISION,
7
7
  AMM_TO_QUOTE_PRECISION_RATIO,
8
+ PRICE_DIV_PEG,
8
9
  QUOTE_PRECISION,
9
10
  ZERO,
10
11
  } from '../constants/numericConstants';
@@ -142,7 +143,7 @@ export function calculateBudgetedPeg(amm: AMM, cost: BN, targetPrice: BN): BN {
142
143
  const targetPeg = targetPrice
143
144
  .mul(amm.baseAssetReserve)
144
145
  .div(amm.quoteAssetReserve)
145
- .div(MARK_PRICE_PRECISION.div(PEG_PRECISION));
146
+ .div(PRICE_DIV_PEG);
146
147
 
147
148
  const k = amm.sqrtK.mul(amm.sqrtK);
148
149
  const x = amm.baseAssetReserve;
package/src/orders.ts CHANGED
@@ -3,27 +3,13 @@ import {
3
3
  MarketAccount,
4
4
  Order,
5
5
  PositionDirection,
6
- SwapDirection,
7
6
  UserAccount,
8
7
  UserPosition,
9
8
  } from './types';
10
- import {
11
- BN,
12
- calculateAmmReservesAfterSwap,
13
- calculateBaseAssetValue,
14
- calculateSpreadReserves,
15
- ClearingHouseUser,
16
- isOrderRiskIncreasingInSameDirection,
17
- standardizeBaseAssetAmount,
18
- TEN_THOUSAND,
19
- } from '.';
20
- import {
21
- calculateMarkPrice,
22
- calculateNewMarketAfterTrade,
23
- } from './math/market';
9
+ import { BN, standardizeBaseAssetAmount } from '.';
10
+ import { calculateNewMarketAfterTrade } from './math/market';
24
11
  import {
25
12
  AMM_TO_QUOTE_PRECISION_RATIO,
26
- TWO,
27
13
  PEG_PRECISION,
28
14
  ZERO,
29
15
  } from './constants/numericConstants';
@@ -182,7 +168,6 @@ export function calculateBaseAssetAmountMarketCanExecute(
182
168
  } else if (isVariant(order.orderType, 'triggerLimit')) {
183
169
  return calculateAmountToTradeForTriggerLimit(market, order);
184
170
  } else if (isVariant(order.orderType, 'market')) {
185
- // should never be a market order queued
186
171
  return ZERO;
187
172
  } else {
188
173
  return calculateAmountToTradeForTriggerMarket(market, order);
@@ -237,14 +222,8 @@ export function calculateAmountToTradeForTriggerLimit(
237
222
  market: MarketAccount,
238
223
  order: Order
239
224
  ): BN {
240
- if (order.baseAssetAmountFilled.eq(ZERO)) {
241
- const baseAssetAmount = calculateAmountToTradeForTriggerMarket(
242
- market,
243
- order
244
- );
245
- if (baseAssetAmount.eq(ZERO)) {
246
- return ZERO;
247
- }
225
+ if (!order.triggered) {
226
+ return ZERO;
248
227
  }
249
228
 
250
229
  return calculateAmountToTradeForLimit(market, order);
@@ -264,105 +243,9 @@ function calculateAmountToTradeForTriggerMarket(
264
243
  market: MarketAccount,
265
244
  order: Order
266
245
  ): BN {
267
- return isTriggerConditionSatisfied(market, order)
268
- ? order.baseAssetAmount
269
- : ZERO;
270
- }
271
-
272
- function isTriggerConditionSatisfied(
273
- market: MarketAccount,
274
- order: Order,
275
- oraclePriceData?: OraclePriceData
276
- ): boolean {
277
- const markPrice = calculateMarkPrice(market, oraclePriceData);
278
- if (isVariant(order.triggerCondition, 'above')) {
279
- return markPrice.gt(order.triggerPrice);
280
- } else {
281
- return markPrice.lt(order.triggerPrice);
282
- }
283
- }
284
-
285
- export function calculateBaseAssetAmountUserCanExecute(
286
- market: MarketAccount,
287
- order: Order,
288
- user: ClearingHouseUser,
289
- oraclePriceData?: OraclePriceData
290
- ): BN {
291
- const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
292
- const freeCollateral = user.getFreeCollateral();
293
- let quoteAssetAmount: BN;
294
- if (isOrderRiskIncreasingInSameDirection(user, order)) {
295
- quoteAssetAmount = freeCollateral.mul(maxLeverage).div(TEN_THOUSAND);
296
- } else {
297
- const position =
298
- user.getUserPosition(order.marketIndex) ||
299
- user.getEmptyPosition(order.marketIndex);
300
- const positionValue = calculateBaseAssetValue(
301
- market,
302
- position,
303
- oraclePriceData
304
- );
305
- quoteAssetAmount = freeCollateral
306
- .mul(maxLeverage)
307
- .div(TEN_THOUSAND)
308
- .add(positionValue.mul(TWO));
309
- }
310
-
311
- if (quoteAssetAmount.lte(ZERO)) {
246
+ if (!order.triggered) {
312
247
  return ZERO;
313
248
  }
314
249
 
315
- const swapDirection = isVariant(order.direction, 'long')
316
- ? SwapDirection.ADD
317
- : SwapDirection.REMOVE;
318
-
319
- const useSpread = !order.postOnly;
320
- let amm: Parameters<typeof calculateAmmReservesAfterSwap>[0];
321
- if (useSpread) {
322
- const { baseAssetReserve, quoteAssetReserve } = calculateSpreadReserves(
323
- market.amm,
324
- order.direction,
325
- oraclePriceData
326
- );
327
- amm = {
328
- baseAssetReserve,
329
- quoteAssetReserve,
330
- sqrtK: market.amm.sqrtK,
331
- pegMultiplier: market.amm.pegMultiplier,
332
- };
333
- } else {
334
- amm = market.amm;
335
- }
336
-
337
- const baseAssetReservesBefore = amm.baseAssetReserve;
338
- const [_, baseAssetReservesAfter] = calculateAmmReservesAfterSwap(
339
- amm,
340
- 'quote',
341
- quoteAssetAmount,
342
- swapDirection
343
- );
344
-
345
- let baseAssetAmount = baseAssetReservesBefore
346
- .sub(baseAssetReservesAfter)
347
- .abs();
348
- if (order.reduceOnly) {
349
- const position =
350
- user.getUserPosition(order.marketIndex) ||
351
- user.getEmptyPosition(order.marketIndex);
352
- if (
353
- isVariant(order.direction, 'long') &&
354
- position.baseAssetAmount.gte(ZERO)
355
- ) {
356
- baseAssetAmount = ZERO;
357
- } else if (
358
- isVariant(order.direction, 'short') &&
359
- position.baseAssetAmount.lte(ZERO)
360
- ) {
361
- baseAssetAmount = ZERO;
362
- } else {
363
- BN.min(baseAssetAmount, position.baseAssetAmount.abs());
364
- }
365
- }
366
-
367
- return baseAssetAmount;
250
+ return order.baseAssetAmount;
368
251
  }
package/src/types.ts CHANGED
@@ -48,6 +48,7 @@ export class OrderAction {
48
48
  static readonly CANCEL = { cancel: {} };
49
49
  static readonly EXPIRE = { expire: {} };
50
50
  static readonly FILL = { fill: {} };
51
+ static readonly TRIGGER = { trigger: {} };
51
52
  }
52
53
 
53
54
  export class OrderTriggerCondition {
@@ -290,6 +291,7 @@ export type AMM = {
290
291
  lastAskPriceTwap: BN;
291
292
  longSpread: BN;
292
293
  shortSpread: BN;
294
+ maxSpread: number;
293
295
  };
294
296
 
295
297
  // # User Account Types
@@ -347,8 +349,9 @@ export type Order = {
347
349
  reduceOnly: boolean;
348
350
  triggerPrice: BN;
349
351
  triggerCondition: OrderTriggerCondition;
352
+ triggered: boolean;
350
353
  discountTier: OrderDiscountTier;
351
- existingPositionDirection: PositionDirection,
354
+ existingPositionDirection: PositionDirection;
352
355
  referrer: PublicKey;
353
356
  postOnly: boolean;
354
357
  immediateOrCancel: boolean;