@drift-labs/sdk 0.2.0-master.30 → 0.2.0-master.32

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 (60) hide show
  1. package/lib/admin.d.ts +11 -7
  2. package/lib/admin.js +50 -12
  3. package/lib/clearingHouse.d.ts +26 -23
  4. package/lib/clearingHouse.js +290 -652
  5. package/lib/clearingHouseUser.d.ts +1 -1
  6. package/lib/clearingHouseUser.js +9 -12
  7. package/lib/config.js +1 -1
  8. package/lib/constants/numericConstants.d.ts +7 -0
  9. package/lib/constants/numericConstants.js +8 -1
  10. package/lib/constants/spotMarkets.js +4 -4
  11. package/lib/dlob/DLOB.d.ts +7 -5
  12. package/lib/dlob/DLOB.js +159 -88
  13. package/lib/dlob/DLOBNode.d.ts +2 -0
  14. package/lib/dlob/DLOBNode.js +3 -0
  15. package/lib/dlob/NodeList.d.ts +2 -1
  16. package/lib/dlob/NodeList.js +10 -4
  17. package/lib/events/types.d.ts +2 -1
  18. package/lib/events/types.js +1 -0
  19. package/lib/factory/bigNum.d.ts +1 -0
  20. package/lib/factory/bigNum.js +14 -0
  21. package/lib/idl/clearing_house.json +1091 -611
  22. package/lib/math/amm.d.ts +2 -2
  23. package/lib/math/amm.js +31 -28
  24. package/lib/math/market.d.ts +1 -1
  25. package/lib/math/market.js +6 -6
  26. package/lib/math/spotBalance.js +7 -8
  27. package/lib/math/trade.js +11 -11
  28. package/lib/types.d.ts +118 -41
  29. package/lib/types.js +34 -4
  30. package/package.json +4 -2
  31. package/src/admin.ts +129 -29
  32. package/src/clearingHouse.ts +380 -787
  33. package/src/clearingHouseUser.ts +11 -14
  34. package/src/config.ts +1 -1
  35. package/src/constants/numericConstants.ts +7 -0
  36. package/src/constants/spotMarkets.ts +5 -4
  37. package/src/dlob/DLOB.ts +221 -103
  38. package/src/dlob/DLOBNode.ts +5 -0
  39. package/src/dlob/NodeList.ts +15 -5
  40. package/src/events/types.ts +3 -0
  41. package/src/factory/bigNum.ts +23 -0
  42. package/src/idl/clearing_house.json +1091 -611
  43. package/src/math/amm.ts +42 -29
  44. package/src/math/market.ts +9 -4
  45. package/src/math/spotBalance.ts +11 -8
  46. package/src/math/trade.ts +11 -11
  47. package/src/types.ts +82 -41
  48. package/tests/bn/test.ts +13 -8
  49. package/tests/dlob/helpers.ts +56 -33
  50. package/tests/dlob/test.ts +1397 -495
  51. package/src/assert/assert.js +0 -9
  52. package/src/events/eventList.js +0 -77
  53. package/src/examples/makeTradeExample.js +0 -157
  54. package/src/token/index.js +0 -38
  55. package/src/tx/types.js +0 -2
  56. package/src/tx/utils.js +0 -17
  57. package/src/util/computeUnits.js +0 -27
  58. package/src/util/getTokenAddress.js +0 -9
  59. package/src/util/promiseTimeout.js +0 -14
  60. package/src/util/tps.js +0 -27
@@ -11,6 +11,11 @@ import {
11
11
  OrderStatus,
12
12
  OrderType,
13
13
  OrderTriggerCondition,
14
+ PRICE_PRECISION,
15
+ DLOBNode,
16
+ OraclePriceData,
17
+ NodeToFill,
18
+ isOrderExpired,
14
19
  } from '../../src';
15
20
 
16
21
  import { mockPerpMarkets, mockSpotMarkets } from './helpers';
@@ -20,15 +25,16 @@ function insertOrderToDLOB(
20
25
  userAccount: PublicKey,
21
26
  orderType: OrderType,
22
27
  marketType: MarketType,
23
- orderId: BN,
24
- marketIndex: BN,
28
+ orderId: number,
29
+ marketIndex: number,
25
30
  price: BN,
26
31
  baseAssetAmount: BN,
27
32
  direction: PositionDirection,
28
33
  auctionStartPrice: BN,
29
34
  auctionEndPrice: BN,
30
35
  slot?: BN,
31
- timeInForce = 30
36
+ timeInForce = 30,
37
+ oraclePriceOffset = new BN(0)
32
38
  ) {
33
39
  dlob.insertOrder(
34
40
  {
@@ -54,7 +60,7 @@ function insertOrderToDLOB(
54
60
  existingPositionDirection: PositionDirection.LONG,
55
61
  postOnly: false,
56
62
  immediateOrCancel: true,
57
- oraclePriceOffset: new BN(0),
63
+ oraclePriceOffset,
58
64
  auctionDuration: 10,
59
65
  auctionStartPrice,
60
66
  auctionEndPrice,
@@ -69,8 +75,8 @@ function insertTriggerOrderToDLOB(
69
75
  userAccount: PublicKey,
70
76
  orderType: OrderType,
71
77
  marketType: MarketType,
72
- orderId: BN,
73
- marketIndex: BN,
78
+ orderId: number,
79
+ marketIndex: number,
74
80
  price: BN,
75
81
  baseAssetAmount: BN,
76
82
  direction: PositionDirection,
@@ -79,7 +85,8 @@ function insertTriggerOrderToDLOB(
79
85
  auctionStartPrice: BN,
80
86
  auctionEndPrice: BN,
81
87
  slot?: BN,
82
- timeInForce = 30
88
+ timeInForce = 30,
89
+ oraclePriceOffset = new BN(0)
83
90
  ) {
84
91
  dlob.insertOrder(
85
92
  {
@@ -105,7 +112,7 @@ function insertTriggerOrderToDLOB(
105
112
  existingPositionDirection: PositionDirection.LONG,
106
113
  postOnly: false,
107
114
  immediateOrCancel: true,
108
- oraclePriceOffset: new BN(0),
115
+ oraclePriceOffset,
109
116
  auctionDuration: 10,
110
117
  auctionStartPrice,
111
118
  auctionEndPrice,
@@ -115,6 +122,98 @@ function insertTriggerOrderToDLOB(
115
122
  );
116
123
  }
117
124
 
125
+ function printOrderNode(
126
+ node: DLOBNode,
127
+ oracle: OraclePriceData | undefined,
128
+ slot: number | undefined
129
+ ) {
130
+ console.log(
131
+ ` . vAMMNode? ${node.isVammNode()},\t${
132
+ node.order ? getVariant(node.order?.orderType) : '~'
133
+ } ${node.order ? getVariant(node.order?.direction) : '~'}\t, ts: ${
134
+ node.order?.ts.toString() || '~'
135
+ }, orderId: ${node.order?.orderId.toString() || '~'},\tnode.getPrice: ${
136
+ oracle ? node.getPrice(oracle, slot!) : '~'
137
+ }, node.price: ${node.order?.price.toString() || '~'}, priceOffset: ${
138
+ node.order?.oraclePriceOffset.toString() || '~'
139
+ } quantity: ${node.order?.baseAssetAmountFilled.toString() || '~'}/${
140
+ node.order?.baseAssetAmount.toString() || '~'
141
+ }`
142
+ );
143
+ }
144
+
145
+ function printBookState(
146
+ dlob: DLOB,
147
+ marketIndex: number,
148
+ vBid: BN | undefined,
149
+ vAsk: BN | undefined,
150
+ slot: number,
151
+ oracle: OraclePriceData
152
+ ) {
153
+ const askNodes = dlob.getAsks(
154
+ marketIndex,
155
+ vAsk,
156
+ slot,
157
+ MarketType.PERP,
158
+ oracle
159
+ );
160
+ let aa = 0;
161
+ console.log(`Oracle price: ${oracle.price.toNumber()}`);
162
+ console.log(`asks:`);
163
+ for (const a of askNodes) {
164
+ printOrderNode(a, oracle, slot);
165
+ aa++;
166
+ }
167
+ console.log(`Total ask nodes: ${aa}`);
168
+
169
+ const bidNodes = dlob.getBids(
170
+ marketIndex,
171
+ vBid,
172
+ slot,
173
+ MarketType.PERP,
174
+ oracle
175
+ );
176
+ let bb = 0;
177
+ console.log(`bids:`);
178
+ for (const b of bidNodes) {
179
+ printOrderNode(b, oracle, slot);
180
+ bb++;
181
+ }
182
+ console.log(`Total bid nodes: ${bb}`);
183
+ }
184
+
185
+ function printCrossedNodes(n: NodeToFill, slot: number) {
186
+ console.log(
187
+ `Cross Found, taker: ${n.node.order !== undefined}, maker: ${
188
+ n.makerNode !== undefined
189
+ }`
190
+ );
191
+ if (n.node.order) {
192
+ const t = n.node.order;
193
+ const exp = isOrderExpired(t, slot);
194
+ console.log(
195
+ ` taker orderId: ${t.orderId}, ${getVariant(t.orderType)}, ${getVariant(
196
+ t.direction
197
+ )},\texpired: ${exp}, price: ${t.price.toString()}, priceOffset: ${t.oraclePriceOffset.toString()}, baseAmtFileld: ${t.baseAssetAmountFilled.toString()}/${t.baseAssetAmount.toString()}`
198
+ );
199
+ }
200
+ if (n.makerNode) {
201
+ if (n.makerNode.isVammNode()) {
202
+ console.log(` maker is vAMM node`);
203
+ } else {
204
+ const m = n.makerNode.order!;
205
+ const exp = isOrderExpired(m, slot);
206
+ console.log(
207
+ ` maker orderId: ${m.orderId}, ${getVariant(
208
+ m.orderType
209
+ )}, ${getVariant(
210
+ m.direction
211
+ )},\texpired: ${exp}, price: ${m.price.toString()}, priceOffset: ${m.oraclePriceOffset.toString()}, baseAmtFileld: ${m.baseAssetAmountFilled.toString()}/${m.baseAssetAmount.toString()}`
212
+ );
213
+ }
214
+ }
215
+ }
216
+
118
217
  let mockTs = 1;
119
218
  function getMockTimestamp(): number {
120
219
  return mockTs++;
@@ -185,6 +284,85 @@ describe('DLOB Tests', () => {
185
284
  expect(foundBids).to.equal(0);
186
285
  }
187
286
  });
287
+
288
+ it('Can clear DLOB', () => {
289
+ const vAsk = new BN(15);
290
+ const vBid = new BN(10);
291
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
292
+ const marketIndex = 0;
293
+
294
+ const slot = 12;
295
+ const oracle = {
296
+ price: vBid.add(vAsk).div(new BN(2)),
297
+ slot: new BN(slot),
298
+ confidence: new BN(1),
299
+ hasSufficientNumberOfDataPoints: true,
300
+ };
301
+
302
+ insertOrderToDLOB(
303
+ dlob,
304
+ Keypair.generate().publicKey,
305
+ OrderType.LIMIT,
306
+ MarketType.PERP,
307
+ 0, // orderId
308
+ marketIndex,
309
+ new BN(9), // price
310
+ BASE_PRECISION, // quantity
311
+ PositionDirection.LONG,
312
+ vBid,
313
+ vAsk
314
+ );
315
+ insertOrderToDLOB(
316
+ dlob,
317
+ Keypair.generate().publicKey,
318
+ OrderType.LIMIT,
319
+ MarketType.PERP,
320
+ 1, // orderId
321
+ marketIndex,
322
+ new BN(8), // price
323
+ BASE_PRECISION, // quantity
324
+ PositionDirection.LONG,
325
+ vBid,
326
+ vAsk
327
+ );
328
+ insertOrderToDLOB(
329
+ dlob,
330
+ Keypair.generate().publicKey,
331
+ OrderType.LIMIT,
332
+ MarketType.PERP,
333
+ 2, // orderId
334
+ marketIndex,
335
+ new BN(8), // price
336
+ BASE_PRECISION, // quantity
337
+ PositionDirection.LONG,
338
+ vBid,
339
+ vAsk
340
+ );
341
+
342
+ const bids = dlob.getBids(
343
+ marketIndex,
344
+ undefined,
345
+ 0,
346
+ MarketType.PERP,
347
+ oracle
348
+ );
349
+ let b = 0;
350
+ for (const _bid of bids) {
351
+ b++;
352
+ }
353
+ expect(b).to.equal(3);
354
+
355
+ dlob.clear();
356
+ let thrown = false;
357
+ try {
358
+ const bids1 = dlob.getBids(marketIndex, vBid, 0, MarketType.PERP, oracle);
359
+ bids1.next();
360
+ } catch (e) {
361
+ console.error(e);
362
+ thrown = true;
363
+ }
364
+ expect(thrown, 'should throw after clearing').to.equal(true);
365
+ });
188
366
  });
189
367
 
190
368
  describe('DLOB Perp Tests', () => {
@@ -192,7 +370,7 @@ describe('DLOB Perp Tests', () => {
192
370
  const vAsk = new BN(15);
193
371
  const vBid = new BN(10);
194
372
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
195
- const marketIndex = new BN(0);
373
+ const marketIndex = 0;
196
374
 
197
375
  const slot = 12;
198
376
  const oracle = {
@@ -203,41 +381,41 @@ describe('DLOB Perp Tests', () => {
203
381
  };
204
382
  const testCases = [
205
383
  {
206
- expectedIdx: 3,
384
+ expectedIdx: 0,
207
385
  isVamm: false,
208
- orderId: new BN(5),
386
+ orderId: 5,
209
387
  price: new BN(0),
210
388
  direction: PositionDirection.LONG,
211
389
  orderType: OrderType.MARKET,
212
390
  },
213
391
  {
214
- expectedIdx: 4,
392
+ expectedIdx: 1,
215
393
  isVamm: false,
216
- orderId: new BN(6),
394
+ orderId: 6,
217
395
  price: new BN(0),
218
396
  direction: PositionDirection.LONG,
219
397
  orderType: OrderType.MARKET,
220
398
  },
221
399
  {
222
- expectedIdx: 5,
400
+ expectedIdx: 2,
223
401
  isVamm: false,
224
- orderId: new BN(7),
402
+ orderId: 7,
225
403
  price: new BN(0),
226
404
  direction: PositionDirection.LONG,
227
405
  orderType: OrderType.MARKET,
228
406
  },
229
407
  {
230
- expectedIdx: 0,
408
+ expectedIdx: 3,
231
409
  isVamm: false,
232
- orderId: new BN(1),
410
+ orderId: 1,
233
411
  price: new BN(12),
234
412
  direction: PositionDirection.LONG,
235
413
  orderType: OrderType.LIMIT,
236
414
  },
237
415
  {
238
- expectedIdx: 1,
416
+ expectedIdx: 4,
239
417
  isVamm: false,
240
- orderId: new BN(2),
418
+ orderId: 2,
241
419
  price: new BN(11),
242
420
  direction: PositionDirection.LONG,
243
421
  orderType: OrderType.LIMIT,
@@ -245,13 +423,13 @@ describe('DLOB Perp Tests', () => {
245
423
  {
246
424
  expectedIdx: 7,
247
425
  isVamm: false,
248
- orderId: new BN(3),
426
+ orderId: 3,
249
427
  price: new BN(8),
250
428
  direction: PositionDirection.LONG,
251
429
  orderType: OrderType.LIMIT,
252
430
  },
253
431
  {
254
- expectedIdx: 2,
432
+ expectedIdx: 5,
255
433
  isVamm: true,
256
434
  orderId: undefined,
257
435
  price: undefined,
@@ -261,7 +439,7 @@ describe('DLOB Perp Tests', () => {
261
439
  {
262
440
  expectedIdx: 6,
263
441
  isVamm: false,
264
- orderId: new BN(4),
442
+ orderId: 4,
265
443
  price: new BN(9),
266
444
  direction: PositionDirection.LONG,
267
445
  orderType: OrderType.LIMIT,
@@ -277,7 +455,7 @@ describe('DLOB Perp Tests', () => {
277
455
  Keypair.generate().publicKey,
278
456
  t.orderType || OrderType.LIMIT,
279
457
  MarketType.PERP,
280
- t.orderId || new BN(0), // orderId
458
+ t.orderId || 0, // orderId
281
459
  marketIndex,
282
460
  t.price || new BN(0), // price
283
461
  BASE_PRECISION, // quantity
@@ -294,28 +472,26 @@ describe('DLOB Perp Tests', () => {
294
472
  const bids = dlob.getBids(marketIndex, vBid, slot, MarketType.PERP, oracle);
295
473
 
296
474
  console.log('The Book Bids:');
475
+ const gotBids: Array<DLOBNode> = [];
297
476
  let countBids = 0;
298
477
  for (const bid of bids) {
299
- console.log(
300
- ` . vAMMNode? ${bid.isVammNode()}, ${JSON.stringify(
301
- bid.order?.orderType
302
- )} , ${bid.order?.orderId.toString()} , vammTestgetPRice: ${bid.getPrice(
303
- oracle,
304
- slot
305
- )}, price: ${bid.order?.price.toString()}, quantity: ${bid.order?.baseAssetAmountFilled.toString()}/${bid.order?.baseAssetAmount.toString()}`
478
+ gotBids.push(bid);
479
+ printOrderNode(bid, oracle, slot);
480
+ }
481
+ for (const bid of gotBids) {
482
+ expect(bid.isVammNode(), `expected vAMM node`).to.be.eq(
483
+ expectedTestCase[countBids].isVamm
306
484
  );
307
-
308
- expect(bid.isVammNode()).to.be.eq(expectedTestCase[countBids].isVamm);
309
- expect(bid.order?.orderId.toNumber()).to.equal(
310
- expectedTestCase[countBids].orderId?.toNumber()
485
+ expect(bid.order?.orderId, `expected orderId`).to.equal(
486
+ expectedTestCase[countBids].orderId
311
487
  );
312
- expect(bid.order?.price.toNumber()).to.equal(
488
+ expect(bid.order?.price.toNumber(), `expected price`).to.equal(
313
489
  expectedTestCase[countBids].price?.toNumber()
314
490
  );
315
- expect(bid.order?.direction).to.equal(
491
+ expect(bid.order?.direction, `expected order direction`).to.equal(
316
492
  expectedTestCase[countBids].direction
317
493
  );
318
- expect(bid.order?.orderType).to.equal(
494
+ expect(bid.order?.orderType, `expected order type`).to.equal(
319
495
  expectedTestCase[countBids].orderType
320
496
  );
321
497
  countBids++;
@@ -328,8 +504,8 @@ describe('DLOB Perp Tests', () => {
328
504
  const vAsk = new BN(15);
329
505
  const vBid = new BN(10);
330
506
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
331
- const marketIndex0 = new BN(0);
332
- const marketIndex1 = new BN(1);
507
+ const marketIndex0 = 0;
508
+ const marketIndex1 = 1;
333
509
 
334
510
  const slot = 12;
335
511
  const oracle = {
@@ -342,7 +518,7 @@ describe('DLOB Perp Tests', () => {
342
518
  {
343
519
  expectedIdx: 3,
344
520
  isVamm: false,
345
- orderId: new BN(5),
521
+ orderId: 5,
346
522
  price: new BN(0),
347
523
  direction: PositionDirection.LONG,
348
524
  orderType: OrderType.MARKET,
@@ -351,7 +527,7 @@ describe('DLOB Perp Tests', () => {
351
527
  {
352
528
  expectedIdx: 4,
353
529
  isVamm: false,
354
- orderId: new BN(6),
530
+ orderId: 6,
355
531
  price: new BN(0),
356
532
  direction: PositionDirection.LONG,
357
533
  orderType: OrderType.MARKET,
@@ -360,7 +536,7 @@ describe('DLOB Perp Tests', () => {
360
536
  {
361
537
  expectedIdx: 5,
362
538
  isVamm: false,
363
- orderId: new BN(7),
539
+ orderId: 7,
364
540
  price: new BN(0),
365
541
  direction: PositionDirection.LONG,
366
542
  orderType: OrderType.MARKET,
@@ -369,7 +545,7 @@ describe('DLOB Perp Tests', () => {
369
545
  {
370
546
  expectedIdx: 0,
371
547
  isVamm: false,
372
- orderId: new BN(1),
548
+ orderId: 1,
373
549
  price: new BN(12),
374
550
  direction: PositionDirection.LONG,
375
551
  orderType: OrderType.LIMIT,
@@ -378,7 +554,7 @@ describe('DLOB Perp Tests', () => {
378
554
  {
379
555
  expectedIdx: 1,
380
556
  isVamm: false,
381
- orderId: new BN(2),
557
+ orderId: 2,
382
558
  price: new BN(11),
383
559
  direction: PositionDirection.LONG,
384
560
  orderType: OrderType.LIMIT,
@@ -387,7 +563,7 @@ describe('DLOB Perp Tests', () => {
387
563
  {
388
564
  expectedIdx: 7,
389
565
  isVamm: false,
390
- orderId: new BN(3),
566
+ orderId: 3,
391
567
  price: new BN(8),
392
568
  direction: PositionDirection.LONG,
393
569
  orderType: OrderType.LIMIT,
@@ -396,7 +572,7 @@ describe('DLOB Perp Tests', () => {
396
572
  {
397
573
  expectedIdx: 6,
398
574
  isVamm: false,
399
- orderId: new BN(4),
575
+ orderId: 4,
400
576
  price: new BN(9),
401
577
  direction: PositionDirection.LONG,
402
578
  orderType: OrderType.LIMIT,
@@ -413,7 +589,7 @@ describe('DLOB Perp Tests', () => {
413
589
  Keypair.generate().publicKey,
414
590
  t.orderType || OrderType.LIMIT,
415
591
  MarketType.PERP,
416
- t.orderId || new BN(0), // orderId
592
+ t.orderId || 0, // orderId
417
593
  t.marketIndex,
418
594
  t.price || new BN(0), // price
419
595
  BASE_PRECISION, // quantity
@@ -471,7 +647,7 @@ describe('DLOB Perp Tests', () => {
471
647
  const vAsk = new BN(15);
472
648
  const vBid = new BN(10);
473
649
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
474
- const marketIndex = new BN(0);
650
+ const marketIndex = 0;
475
651
 
476
652
  const slot = 12;
477
653
  const oracle = {
@@ -484,7 +660,7 @@ describe('DLOB Perp Tests', () => {
484
660
  {
485
661
  expectedIdx: 0,
486
662
  isVamm: false,
487
- orderId: new BN(3),
663
+ orderId: 3,
488
664
  price: new BN(0),
489
665
  direction: PositionDirection.SHORT,
490
666
  orderType: OrderType.MARKET,
@@ -492,7 +668,7 @@ describe('DLOB Perp Tests', () => {
492
668
  {
493
669
  expectedIdx: 1,
494
670
  isVamm: false,
495
- orderId: new BN(4),
671
+ orderId: 4,
496
672
  price: new BN(0),
497
673
  direction: PositionDirection.SHORT,
498
674
  orderType: OrderType.MARKET,
@@ -500,7 +676,7 @@ describe('DLOB Perp Tests', () => {
500
676
  {
501
677
  expectedIdx: 2,
502
678
  isVamm: false,
503
- orderId: new BN(5),
679
+ orderId: 5,
504
680
  price: new BN(0),
505
681
  direction: PositionDirection.SHORT,
506
682
  orderType: OrderType.MARKET,
@@ -508,7 +684,7 @@ describe('DLOB Perp Tests', () => {
508
684
  {
509
685
  expectedIdx: 3,
510
686
  isVamm: false,
511
- orderId: new BN(1),
687
+ orderId: 1,
512
688
  price: new BN(13),
513
689
  direction: PositionDirection.SHORT,
514
690
  orderType: OrderType.LIMIT,
@@ -516,7 +692,7 @@ describe('DLOB Perp Tests', () => {
516
692
  {
517
693
  expectedIdx: 6,
518
694
  isVamm: false,
519
- orderId: new BN(6),
695
+ orderId: 6,
520
696
  price: new BN(16),
521
697
  direction: PositionDirection.SHORT,
522
698
  orderType: OrderType.LIMIT,
@@ -532,7 +708,7 @@ describe('DLOB Perp Tests', () => {
532
708
  {
533
709
  expectedIdx: 7,
534
710
  isVamm: false,
535
- orderId: new BN(7),
711
+ orderId: 7,
536
712
  price: new BN(17),
537
713
  direction: PositionDirection.SHORT,
538
714
  orderType: OrderType.LIMIT,
@@ -540,7 +716,7 @@ describe('DLOB Perp Tests', () => {
540
716
  {
541
717
  expectedIdx: 4,
542
718
  isVamm: false,
543
- orderId: new BN(2),
719
+ orderId: 2,
544
720
  price: new BN(14),
545
721
  direction: PositionDirection.SHORT,
546
722
  orderType: OrderType.LIMIT,
@@ -556,7 +732,7 @@ describe('DLOB Perp Tests', () => {
556
732
  Keypair.generate().publicKey,
557
733
  t.orderType || OrderType.LIMIT,
558
734
  MarketType.PERP,
559
- t.orderId || new BN(0), // orderId
735
+ t.orderId || 0, // orderId
560
736
  marketIndex,
561
737
  t.price || new BN(0), // price
562
738
  BASE_PRECISION, // quantity
@@ -585,9 +761,7 @@ describe('DLOB Perp Tests', () => {
585
761
  );
586
762
 
587
763
  expect(ask.isVammNode()).to.be.eq(expectedTestCase[countAsks].isVamm);
588
- expect(ask.order?.orderId.toNumber()).to.equal(
589
- expectedTestCase[countAsks].orderId?.toNumber()
590
- );
764
+ expect(ask.order?.orderId).to.equal(expectedTestCase[countAsks].orderId);
591
765
  expect(ask.order?.price.toNumber()).to.equal(
592
766
  expectedTestCase[countAsks].price?.toNumber()
593
767
  );
@@ -607,7 +781,7 @@ describe('DLOB Perp Tests', () => {
607
781
  const vAsk = new BN(11);
608
782
  const vBid = new BN(10);
609
783
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
610
- const marketIndex = new BN(0);
784
+ const marketIndex = 0;
611
785
  const oracle = {
612
786
  price: vBid.add(vAsk).div(new BN(2)),
613
787
  slot: new BN(12),
@@ -622,7 +796,7 @@ describe('DLOB Perp Tests', () => {
622
796
  Keypair.generate().publicKey,
623
797
  OrderType.MARKET,
624
798
  MarketType.PERP,
625
- new BN(i + 1),
799
+ i + 1,
626
800
  marketIndex,
627
801
  new BN(0),
628
802
  BASE_PRECISION,
@@ -639,7 +813,7 @@ describe('DLOB Perp Tests', () => {
639
813
  Keypair.generate().publicKey,
640
814
  OrderType.MARKET,
641
815
  MarketType.PERP,
642
- new BN(i + 1),
816
+ i + 1,
643
817
  marketIndex,
644
818
  new BN(0),
645
819
  BASE_PRECISION,
@@ -665,7 +839,7 @@ describe('DLOB Perp Tests', () => {
665
839
  expect(getVariant(ask.order?.status)).to.equal('open');
666
840
  expect(getVariant(ask.order?.orderType)).to.equal('market');
667
841
  expect(getVariant(ask.order?.direction)).to.equal('short');
668
- expect(ask.order?.orderId.toNumber()).to.equal(asks);
842
+ expect(ask.order?.orderId).to.equal(asks);
669
843
  }
670
844
  }
671
845
  expect(asks).to.equal(4); // vamm ask + 3 orders
@@ -686,7 +860,7 @@ describe('DLOB Perp Tests', () => {
686
860
  expect(getVariant(bid.order?.status)).to.equal('open');
687
861
  expect(getVariant(bid.order?.orderType)).to.equal('market');
688
862
  expect(getVariant(bid.order?.direction)).to.equal('long');
689
- expect(bid.order?.orderId.toNumber()).to.equal(bids);
863
+ expect(bid.order?.orderId).to.equal(bids);
690
864
  }
691
865
  bids++;
692
866
  }
@@ -704,13 +878,13 @@ describe('DLOB Perp Tests', () => {
704
878
  hasSufficientNumberOfDataPoints: true,
705
879
  };
706
880
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
707
- const marketIndex = new BN(0);
881
+ const marketIndex = 0;
708
882
  insertOrderToDLOB(
709
883
  dlob,
710
884
  Keypair.generate().publicKey,
711
885
  OrderType.LIMIT,
712
886
  MarketType.PERP,
713
- new BN(3),
887
+ 3, // orderId
714
888
  marketIndex,
715
889
  new BN(5),
716
890
  BASE_PRECISION,
@@ -724,7 +898,7 @@ describe('DLOB Perp Tests', () => {
724
898
  Keypair.generate().publicKey,
725
899
  OrderType.LIMIT,
726
900
  MarketType.PERP,
727
- new BN(2),
901
+ 2,
728
902
  marketIndex,
729
903
  new BN(6),
730
904
  BASE_PRECISION,
@@ -738,7 +912,7 @@ describe('DLOB Perp Tests', () => {
738
912
  Keypair.generate().publicKey,
739
913
  OrderType.LIMIT,
740
914
  MarketType.PERP,
741
- new BN(1),
915
+ 1, // orderId
742
916
  marketIndex,
743
917
  new BN(7),
744
918
  BASE_PRECISION,
@@ -752,7 +926,7 @@ describe('DLOB Perp Tests', () => {
752
926
  Keypair.generate().publicKey,
753
927
  OrderType.LIMIT,
754
928
  MarketType.PERP,
755
- new BN(1),
929
+ 1, // orderId
756
930
  marketIndex,
757
931
  new BN(12),
758
932
  BASE_PRECISION,
@@ -766,7 +940,7 @@ describe('DLOB Perp Tests', () => {
766
940
  Keypair.generate().publicKey,
767
941
  OrderType.LIMIT,
768
942
  MarketType.PERP,
769
- new BN(2),
943
+ 2, // orderId
770
944
  marketIndex,
771
945
  new BN(13),
772
946
  BASE_PRECISION,
@@ -780,7 +954,7 @@ describe('DLOB Perp Tests', () => {
780
954
  Keypair.generate().publicKey,
781
955
  OrderType.LIMIT,
782
956
  MarketType.PERP,
783
- new BN(3),
957
+ 3, // orderId
784
958
  marketIndex,
785
959
  new BN(14),
786
960
  BASE_PRECISION,
@@ -803,7 +977,7 @@ describe('DLOB Perp Tests', () => {
803
977
  expect(getVariant(ask.order?.status)).to.equal('open');
804
978
  expect(getVariant(ask.order?.orderType)).to.equal('limit');
805
979
  expect(getVariant(ask.order?.direction)).to.equal('short');
806
- expect(ask.order?.orderId.toNumber()).to.equal(asks);
980
+ expect(ask.order?.orderId).to.equal(asks);
807
981
  expect(ask.order?.price.gt(vAsk)).to.equal(true);
808
982
  }
809
983
 
@@ -829,7 +1003,7 @@ describe('DLOB Perp Tests', () => {
829
1003
  expect(getVariant(bid.order?.status)).to.equal('open');
830
1004
  expect(getVariant(bid.order?.orderType)).to.equal('limit');
831
1005
  expect(getVariant(bid.order?.direction)).to.equal('long');
832
- expect(bid.order?.orderId.toNumber()).to.equal(bids);
1006
+ expect(bid.order?.orderId).to.equal(bids);
833
1007
  expect(bid.order?.price.lt(vBid)).to.equal(true);
834
1008
  }
835
1009
  bids++;
@@ -837,11 +1011,182 @@ describe('DLOB Perp Tests', () => {
837
1011
  expect(bids).to.equal(4); // vamm bid + 3 orders
838
1012
  });
839
1013
 
1014
+ it('Test insert floatinglimit orders', () => {
1015
+ const slot = 12;
1016
+ const vAsk = new BN(11).mul(PRICE_PRECISION);
1017
+ const vBid = new BN(10).mul(PRICE_PRECISION);
1018
+ const oracle = {
1019
+ price: vBid.add(vAsk).div(new BN(2)),
1020
+ slot: new BN(slot),
1021
+ confidence: new BN(1),
1022
+ hasSufficientNumberOfDataPoints: true,
1023
+ };
1024
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1025
+ const marketIndex = 0;
1026
+
1027
+ // insert floating bids
1028
+ insertOrderToDLOB(
1029
+ dlob,
1030
+ Keypair.generate().publicKey,
1031
+ OrderType.LIMIT,
1032
+ MarketType.PERP,
1033
+ 1, // orderId
1034
+ marketIndex,
1035
+ new BN(0), // price
1036
+ BASE_PRECISION, // quantity
1037
+ PositionDirection.LONG,
1038
+ vBid,
1039
+ vAsk,
1040
+ new BN(slot),
1041
+ 30, // TiF
1042
+ new BN(-1).mul(PRICE_PRECISION) // oraclePriceOffset
1043
+ );
1044
+ insertOrderToDLOB(
1045
+ dlob,
1046
+ Keypair.generate().publicKey,
1047
+ OrderType.LIMIT,
1048
+ MarketType.PERP,
1049
+ 3, // orderId
1050
+ marketIndex,
1051
+ new BN(0), // price
1052
+ BASE_PRECISION, // quantity
1053
+ PositionDirection.LONG,
1054
+ vBid,
1055
+ vAsk,
1056
+ new BN(slot),
1057
+ 30, // TiF
1058
+ new BN(-3).mul(PRICE_PRECISION) // oraclePriceOffset
1059
+ );
1060
+ insertOrderToDLOB(
1061
+ dlob,
1062
+ Keypair.generate().publicKey,
1063
+ OrderType.LIMIT,
1064
+ MarketType.PERP,
1065
+ 2, // orderId
1066
+ marketIndex,
1067
+ new BN(0), // price
1068
+ BASE_PRECISION, // quantity
1069
+ PositionDirection.LONG,
1070
+ vBid,
1071
+ vAsk,
1072
+ new BN(slot),
1073
+ 30, // TiF
1074
+ new BN(-2).mul(PRICE_PRECISION) // oraclePriceOffset
1075
+ );
1076
+
1077
+ // insert floating asks
1078
+ insertOrderToDLOB(
1079
+ dlob,
1080
+ Keypair.generate().publicKey,
1081
+ OrderType.LIMIT,
1082
+ MarketType.PERP,
1083
+ 5, // orderId
1084
+ marketIndex,
1085
+ new BN(0), // price
1086
+ BASE_PRECISION, // quantity
1087
+ PositionDirection.SHORT,
1088
+ vAsk,
1089
+ vBid,
1090
+ new BN(slot),
1091
+ 30, // TiF
1092
+ new BN(2).mul(PRICE_PRECISION) // oraclePriceOffset
1093
+ );
1094
+ insertOrderToDLOB(
1095
+ dlob,
1096
+ Keypair.generate().publicKey,
1097
+ OrderType.LIMIT,
1098
+ MarketType.PERP,
1099
+ 6, // orderId
1100
+ marketIndex,
1101
+ new BN(0), // price
1102
+ BASE_PRECISION, // quantity
1103
+ PositionDirection.SHORT,
1104
+ vAsk,
1105
+ vBid,
1106
+ new BN(slot),
1107
+ 30, // TiF
1108
+ new BN(3).mul(PRICE_PRECISION) // oraclePriceOffset
1109
+ );
1110
+ insertOrderToDLOB(
1111
+ dlob,
1112
+ Keypair.generate().publicKey,
1113
+ OrderType.LIMIT,
1114
+ MarketType.PERP,
1115
+ 4, // orderId
1116
+ marketIndex,
1117
+ new BN(0), // price
1118
+ BASE_PRECISION, // quantity
1119
+ PositionDirection.SHORT,
1120
+ vAsk,
1121
+ vBid,
1122
+ new BN(slot),
1123
+ 30, // TiF
1124
+ new BN(1).mul(PRICE_PRECISION) // oraclePriceOffset
1125
+ );
1126
+
1127
+ // check floating bids
1128
+ console.log(`bids:`);
1129
+ let lastBidPrice = new BN(9999999999999); // very big
1130
+ let bids = 0;
1131
+ for (const bid of dlob.getBids(
1132
+ marketIndex,
1133
+ vBid,
1134
+ slot,
1135
+ MarketType.PERP,
1136
+ oracle
1137
+ )) {
1138
+ printOrderNode(bid, oracle, slot);
1139
+
1140
+ if (!bid.isVammNode()) {
1141
+ expect(getVariant(bid.order?.status)).to.equal('open');
1142
+ expect(getVariant(bid.order?.orderType)).to.equal('limit');
1143
+ expect(getVariant(bid.order?.direction)).to.equal('long');
1144
+
1145
+ // price should be getting worse (getting lower) as we iterate
1146
+ const currentPrice = bid.getPrice(oracle, slot);
1147
+ expect(
1148
+ currentPrice.lte(lastBidPrice),
1149
+ `each bid should be lte the last. current: ${currentPrice.toString()}, last: ${lastBidPrice.toString()}`
1150
+ ).to.be.true;
1151
+ }
1152
+ lastBidPrice = bid.getPrice(oracle, slot);
1153
+ bids++;
1154
+ }
1155
+ expect(bids).to.equal(4); // vamm bid + 3 orders
1156
+
1157
+ // check floating asks
1158
+ console.log(`asks:`);
1159
+ let asks = 0;
1160
+ for (const ask of dlob.getAsks(
1161
+ marketIndex,
1162
+ vAsk,
1163
+ slot,
1164
+ MarketType.PERP,
1165
+ oracle
1166
+ )) {
1167
+ printOrderNode(ask, oracle, slot);
1168
+ if (!ask.isVammNode()) {
1169
+ expect(getVariant(ask.order?.status)).to.equal('open');
1170
+ expect(getVariant(ask.order?.orderType)).to.equal('limit');
1171
+ expect(getVariant(ask.order?.direction)).to.equal('short');
1172
+
1173
+ // price should be getting worse (getting higher) as we iterate
1174
+ const currentPrice = ask.getPrice(oracle, slot);
1175
+ expect(
1176
+ currentPrice.gte(lastBidPrice),
1177
+ `each ask should be gte the last. current: ${currentPrice.toString()}, last: ${lastBidPrice.toString()}`
1178
+ ).to.be.true;
1179
+ }
1180
+ asks++;
1181
+ }
1182
+ expect(asks).to.equal(4); // vamm ask + 3 orders
1183
+ });
1184
+
840
1185
  it('Test multiple market orders fill with multiple limit orders', () => {
841
1186
  const vAsk = new BN(15);
842
1187
  const vBid = new BN(10);
843
1188
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
844
- const marketIndex = new BN(0);
1189
+ const marketIndex = 0;
845
1190
 
846
1191
  // insert some limit buys above vamm bid, below ask
847
1192
  insertOrderToDLOB(
@@ -849,7 +1194,7 @@ describe('DLOB Perp Tests', () => {
849
1194
  Keypair.generate().publicKey,
850
1195
  OrderType.LIMIT,
851
1196
  MarketType.PERP,
852
- new BN(1), // orderId
1197
+ 1, // orderId
853
1198
  marketIndex,
854
1199
  new BN(11), // price
855
1200
  BASE_PRECISION, // quantity
@@ -862,7 +1207,7 @@ describe('DLOB Perp Tests', () => {
862
1207
  Keypair.generate().publicKey,
863
1208
  OrderType.LIMIT,
864
1209
  MarketType.PERP,
865
- new BN(2), // orderId
1210
+ 2, // orderId
866
1211
  marketIndex,
867
1212
  new BN(12), // price
868
1213
  BASE_PRECISION, // quantity
@@ -875,7 +1220,7 @@ describe('DLOB Perp Tests', () => {
875
1220
  Keypair.generate().publicKey,
876
1221
  OrderType.LIMIT,
877
1222
  MarketType.PERP,
878
- new BN(3), // orderId
1223
+ 3, // orderId
879
1224
  marketIndex,
880
1225
  new BN(13), // price
881
1226
  BASE_PRECISION, // quantity
@@ -887,8 +1232,6 @@ describe('DLOB Perp Tests', () => {
887
1232
  // should have no crossing orders
888
1233
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
889
1234
  marketIndex,
890
- vBid,
891
- vAsk,
892
1235
  12, // auction over
893
1236
  MarketType.PERP,
894
1237
  {
@@ -906,7 +1249,7 @@ describe('DLOB Perp Tests', () => {
906
1249
  Keypair.generate().publicKey,
907
1250
  OrderType.MARKET,
908
1251
  MarketType.PERP,
909
- new BN(4), // orderId
1252
+ 4, // orderId
910
1253
  marketIndex,
911
1254
  new BN(12), // price
912
1255
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -919,7 +1262,7 @@ describe('DLOB Perp Tests', () => {
919
1262
  Keypair.generate().publicKey,
920
1263
  OrderType.MARKET,
921
1264
  MarketType.PERP,
922
- new BN(5), // orderId
1265
+ 5, // orderId
923
1266
  marketIndex,
924
1267
  new BN(12), // price
925
1268
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -930,8 +1273,6 @@ describe('DLOB Perp Tests', () => {
930
1273
 
931
1274
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
932
1275
  marketIndex,
933
- vBid,
934
- vAsk,
935
1276
  12, // auction over
936
1277
  MarketType.PERP,
937
1278
  {
@@ -941,31 +1282,26 @@ describe('DLOB Perp Tests', () => {
941
1282
  hasSufficientNumberOfDataPoints: true,
942
1283
  }
943
1284
  );
1285
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
944
1286
  for (const n of nodesToFillAfter) {
945
- console.log(
946
- `cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmount.toString()}`
947
- );
1287
+ printCrossedNodes(n, 12);
948
1288
  }
949
1289
  expect(nodesToFillAfter.length).to.equal(2);
950
1290
 
951
1291
  // first taker should fill with best maker
952
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
953
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
954
- 3
955
- );
1292
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
1293
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
956
1294
 
957
1295
  // second taker should fill with second best maker
958
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(5);
959
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
960
- 2
961
- );
1296
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
1297
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
962
1298
  });
963
1299
 
964
1300
  it('Test one market orders fills two limit orders', () => {
965
1301
  const vAsk = new BN(15);
966
1302
  const vBid = new BN(10);
967
1303
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
968
- const marketIndex = new BN(0);
1304
+ const marketIndex = 0;
969
1305
 
970
1306
  // insert some limit sells below vAMM ask, above bid
971
1307
  insertOrderToDLOB(
@@ -973,7 +1309,7 @@ describe('DLOB Perp Tests', () => {
973
1309
  Keypair.generate().publicKey,
974
1310
  OrderType.LIMIT,
975
1311
  MarketType.PERP,
976
- new BN(1), // orderId
1312
+ 1, // orderId
977
1313
  marketIndex,
978
1314
  new BN(14), // price
979
1315
  BASE_PRECISION, // quantity
@@ -986,7 +1322,7 @@ describe('DLOB Perp Tests', () => {
986
1322
  Keypair.generate().publicKey,
987
1323
  OrderType.LIMIT,
988
1324
  MarketType.PERP,
989
- new BN(2), // orderId
1325
+ 2, // orderId
990
1326
  marketIndex,
991
1327
  new BN(13), // price
992
1328
  BASE_PRECISION, // quantity
@@ -999,7 +1335,7 @@ describe('DLOB Perp Tests', () => {
999
1335
  Keypair.generate().publicKey,
1000
1336
  OrderType.LIMIT,
1001
1337
  MarketType.PERP,
1002
- new BN(3), // orderId
1338
+ 3, // orderId
1003
1339
  marketIndex,
1004
1340
  new BN(12), // price
1005
1341
  BASE_PRECISION, // quantity
@@ -1011,8 +1347,6 @@ describe('DLOB Perp Tests', () => {
1011
1347
  // should have no crossing orders
1012
1348
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
1013
1349
  marketIndex,
1014
- vBid,
1015
- vAsk,
1016
1350
  12, // auction over
1017
1351
  MarketType.PERP,
1018
1352
  {
@@ -1030,7 +1364,7 @@ describe('DLOB Perp Tests', () => {
1030
1364
  Keypair.generate().publicKey,
1031
1365
  OrderType.MARKET,
1032
1366
  MarketType.PERP,
1033
- new BN(4), // orderId
1367
+ 4, // orderId
1034
1368
  marketIndex,
1035
1369
  new BN(13), // price
1036
1370
  new BN(2).mul(BASE_PRECISION), // quantity
@@ -1041,8 +1375,6 @@ describe('DLOB Perp Tests', () => {
1041
1375
 
1042
1376
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
1043
1377
  marketIndex,
1044
- vBid,
1045
- vAsk,
1046
1378
  12, // auction over
1047
1379
  MarketType.PERP,
1048
1380
  {
@@ -1052,31 +1384,26 @@ describe('DLOB Perp Tests', () => {
1052
1384
  hasSufficientNumberOfDataPoints: true,
1053
1385
  }
1054
1386
  );
1387
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
1055
1388
  for (const n of nodesToFillAfter) {
1056
- console.log(
1057
- `cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmountFilled.toString()}/${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmountFilled.toString()}/${n.makerNode?.order?.baseAssetAmount.toString()}`
1058
- );
1389
+ printCrossedNodes(n, 12);
1059
1390
  }
1060
1391
  expect(nodesToFillAfter.length).to.equal(2);
1061
1392
 
1062
1393
  // taker should fill completely with best maker
1063
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
1064
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
1065
- 3
1066
- );
1394
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
1395
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
1067
1396
 
1068
1397
  // taker should fill completely with second best maker
1069
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(4);
1070
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
1071
- 2
1072
- );
1398
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(4);
1399
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
1073
1400
  });
1074
1401
 
1075
1402
  it('Test two market orders to fill one limit order', () => {
1076
1403
  const vAsk = new BN(15);
1077
1404
  const vBid = new BN(8);
1078
1405
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1079
- const marketIndex = new BN(0);
1406
+ const marketIndex = 0;
1080
1407
 
1081
1408
  const slot = 12;
1082
1409
  const oracle = {
@@ -1092,7 +1419,7 @@ describe('DLOB Perp Tests', () => {
1092
1419
  Keypair.generate().publicKey,
1093
1420
  OrderType.LIMIT,
1094
1421
  MarketType.PERP,
1095
- new BN(1), // orderId
1422
+ 1, // orderId
1096
1423
  marketIndex,
1097
1424
  new BN(14), // price
1098
1425
  BASE_PRECISION, // quantity
@@ -1105,7 +1432,7 @@ describe('DLOB Perp Tests', () => {
1105
1432
  Keypair.generate().publicKey,
1106
1433
  OrderType.LIMIT,
1107
1434
  MarketType.PERP,
1108
- new BN(2), // orderId
1435
+ 2, // orderId
1109
1436
  marketIndex,
1110
1437
  new BN(13), // price
1111
1438
  BASE_PRECISION, // quantity
@@ -1118,7 +1445,7 @@ describe('DLOB Perp Tests', () => {
1118
1445
  Keypair.generate().publicKey,
1119
1446
  OrderType.LIMIT,
1120
1447
  MarketType.PERP,
1121
- new BN(3), // orderId
1448
+ 3, // orderId
1122
1449
  marketIndex,
1123
1450
  new BN(9), // price <-- best price
1124
1451
  new BN(3).mul(BASE_PRECISION), // quantity
@@ -1130,8 +1457,6 @@ describe('DLOB Perp Tests', () => {
1130
1457
  // should have no crossing orders
1131
1458
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
1132
1459
  marketIndex,
1133
- vBid,
1134
- vAsk,
1135
1460
  12, // auction over
1136
1461
  MarketType.PERP,
1137
1462
  oracle
@@ -1144,7 +1469,7 @@ describe('DLOB Perp Tests', () => {
1144
1469
  Keypair.generate().publicKey,
1145
1470
  OrderType.MARKET,
1146
1471
  MarketType.PERP,
1147
- new BN(4), // orderId
1472
+ 4, // orderId
1148
1473
  marketIndex,
1149
1474
  new BN(0), // price
1150
1475
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -1157,7 +1482,7 @@ describe('DLOB Perp Tests', () => {
1157
1482
  Keypair.generate().publicKey,
1158
1483
  OrderType.MARKET,
1159
1484
  MarketType.PERP,
1160
- new BN(5), // orderId
1485
+ 5, // orderId
1161
1486
  marketIndex,
1162
1487
  new BN(0), // price
1163
1488
  new BN(2).mul(BASE_PRECISION), // quantity
@@ -1168,87 +1493,39 @@ describe('DLOB Perp Tests', () => {
1168
1493
 
1169
1494
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
1170
1495
  marketIndex,
1171
- vBid,
1172
- vAsk,
1173
1496
  slot, // auction over
1174
1497
  MarketType.PERP,
1175
1498
  oracle
1176
1499
  );
1177
- const mktNodes = dlob.findMarketNodesToFill(
1500
+ const mktNodes = dlob.findExpiredMarketNodesToFill(
1178
1501
  marketIndex,
1179
1502
  slot,
1180
1503
  MarketType.PERP
1181
1504
  );
1182
1505
  console.log(`market nodes: ${mktNodes.length}`);
1183
1506
 
1184
- const askNodes = dlob.getAsks(
1185
- marketIndex,
1186
- vAsk,
1187
- slot,
1188
- MarketType.PERP,
1189
- oracle
1190
- );
1191
- let aa = 0;
1192
- for (const b of askNodes) {
1193
- console.log(
1194
- ` . ask: ${b.order?.orderId.toString()}: p1: ${b.order?.price.toString()} p2: ${b.getPrice(
1195
- oracle,
1196
- slot
1197
- )}, ${JSON.stringify(
1198
- b.order?.orderType
1199
- )} BAA: ${b.order?.baseAssetAmountFilled.toString()}/${b.order?.baseAssetAmount.toString()}`
1200
- );
1201
- aa++;
1202
- }
1203
- expect(aa).to.equal(4);
1507
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
1204
1508
 
1205
- const bidNodes = dlob.getBids(
1206
- marketIndex,
1207
- vBid,
1208
- slot,
1209
- MarketType.PERP,
1210
- oracle
1211
- );
1212
- let bb = 0;
1213
- for (const b of bidNodes) {
1214
- console.log(
1215
- ` . bid: ${b.order?.orderId.toString()}: p1: ${b.order?.price.toString()} p2: ${b.getPrice(
1216
- oracle,
1217
- slot
1218
- )}, ${JSON.stringify(
1219
- b.order?.orderType
1220
- )} BAA: ${b.order?.baseAssetAmountFilled.toString()}/${b.order?.baseAssetAmount.toString()}`
1221
- );
1222
- bb++;
1223
- }
1224
- expect(bb).to.equal(3);
1225
-
1226
- console.log(`bids nodes: ${bb}`);
1509
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
1227
1510
  for (const n of nodesToFillAfter) {
1228
- console.log(
1229
- `cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmountFilled.toString()}/${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmountFilled.toString()}/${n.makerNode?.order?.baseAssetAmount.toString()}`
1230
- );
1511
+ printCrossedNodes(n, slot);
1231
1512
  }
1232
1513
  expect(nodesToFillAfter.length).to.equal(2);
1233
1514
 
1234
1515
  // taker should fill completely with best maker
1235
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
1236
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
1237
- 3
1238
- );
1516
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
1517
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
1239
1518
 
1240
1519
  // taker should fill completely with second best maker
1241
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(5);
1242
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
1243
- 3
1244
- );
1520
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
1521
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(3);
1245
1522
  });
1246
1523
 
1247
1524
  it('Test trigger orders', () => {
1248
1525
  const vAsk = new BN(15);
1249
1526
  const vBid = new BN(8);
1250
1527
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1251
- const marketIndex = new BN(0);
1528
+ const marketIndex = 0;
1252
1529
 
1253
1530
  const slot = 20;
1254
1531
  const oracle = {
@@ -1267,7 +1544,7 @@ describe('DLOB Perp Tests', () => {
1267
1544
  Keypair.generate().publicKey,
1268
1545
  OrderType.TRIGGER_LIMIT,
1269
1546
  MarketType.PERP,
1270
- new BN(1), //orderId
1547
+ 1, //orderId
1271
1548
  marketIndex, // marketIndex
1272
1549
  vBid, // price
1273
1550
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -1283,7 +1560,7 @@ describe('DLOB Perp Tests', () => {
1283
1560
  Keypair.generate().publicKey,
1284
1561
  OrderType.TRIGGER_LIMIT,
1285
1562
  MarketType.PERP,
1286
- new BN(2), //orderId
1563
+ 2, //orderId
1287
1564
  marketIndex, // marketIndex
1288
1565
  vBid, // price
1289
1566
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -1299,7 +1576,7 @@ describe('DLOB Perp Tests', () => {
1299
1576
  Keypair.generate().publicKey,
1300
1577
  OrderType.TRIGGER_MARKET,
1301
1578
  MarketType.PERP,
1302
- new BN(3), //orderId
1579
+ 3, //orderId
1303
1580
  marketIndex, // marketIndex
1304
1581
  vAsk, // price
1305
1582
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -1315,7 +1592,7 @@ describe('DLOB Perp Tests', () => {
1315
1592
  Keypair.generate().publicKey,
1316
1593
  OrderType.TRIGGER_MARKET,
1317
1594
  MarketType.PERP,
1318
- new BN(4), //orderId
1595
+ 4, //orderId
1319
1596
  marketIndex, // marketIndex
1320
1597
  vBid, // price
1321
1598
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -1329,223 +1606,924 @@ describe('DLOB Perp Tests', () => {
1329
1606
  insertTriggerOrderToDLOB(
1330
1607
  dlob,
1331
1608
  Keypair.generate().publicKey,
1332
- OrderType.TRIGGER_LIMIT,
1609
+ OrderType.TRIGGER_LIMIT,
1610
+ MarketType.PERP,
1611
+ 5, //orderId
1612
+ marketIndex, // marketIndex
1613
+ vBid, // price
1614
+ BASE_PRECISION, // baseAssetAmount: BN,
1615
+ PositionDirection.LONG,
1616
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1617
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1618
+ vBid,
1619
+ vAsk
1620
+ );
1621
+ // should trigger limit sell with below condition
1622
+ insertTriggerOrderToDLOB(
1623
+ dlob,
1624
+ Keypair.generate().publicKey,
1625
+ OrderType.TRIGGER_LIMIT,
1626
+ MarketType.PERP,
1627
+ 6, //orderId
1628
+ marketIndex, // marketIndex
1629
+ vBid, // price
1630
+ BASE_PRECISION, // baseAssetAmount: BN,
1631
+ PositionDirection.SHORT,
1632
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1633
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1634
+ vBid,
1635
+ vAsk
1636
+ );
1637
+ // should trigger market buy with below condition
1638
+ insertTriggerOrderToDLOB(
1639
+ dlob,
1640
+ Keypair.generate().publicKey,
1641
+ OrderType.TRIGGER_MARKET,
1642
+ MarketType.PERP,
1643
+ 7, //orderId
1644
+ marketIndex, // marketIndex
1645
+ vBid, // price
1646
+ BASE_PRECISION, // baseAssetAmount: BN,
1647
+ PositionDirection.LONG,
1648
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1649
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1650
+ vBid,
1651
+ vAsk
1652
+ );
1653
+ // should trigger market sell with below condition
1654
+ insertTriggerOrderToDLOB(
1655
+ dlob,
1656
+ Keypair.generate().publicKey,
1657
+ OrderType.TRIGGER_MARKET,
1658
+ MarketType.PERP,
1659
+ 8, //orderId
1660
+ marketIndex, // marketIndex
1661
+ vBid, // price
1662
+ BASE_PRECISION, // baseAssetAmount: BN,
1663
+ PositionDirection.LONG,
1664
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1665
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1666
+ vBid,
1667
+ vAsk
1668
+ );
1669
+
1670
+ // should NOT trigger market sell with above condition
1671
+ insertTriggerOrderToDLOB(
1672
+ dlob,
1673
+ Keypair.generate().publicKey,
1674
+ OrderType.TRIGGER_MARKET,
1675
+ MarketType.PERP,
1676
+ 9, //orderId
1677
+ marketIndex, // marketIndex
1678
+ vBid, // price
1679
+ BASE_PRECISION, // baseAssetAmount: BN,
1680
+ PositionDirection.SHORT,
1681
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1682
+ OrderTriggerCondition.ABOVE, // triggerCondition: OrderTriggerCondition,
1683
+ vBid,
1684
+ vAsk
1685
+ );
1686
+ // should NOT trigger market sell with below condition
1687
+ insertTriggerOrderToDLOB(
1688
+ dlob,
1689
+ Keypair.generate().publicKey,
1690
+ OrderType.TRIGGER_MARKET,
1691
+ MarketType.PERP,
1692
+ 10, //orderId
1693
+ marketIndex, // marketIndex
1694
+ vBid, // price
1695
+ BASE_PRECISION, // baseAssetAmount: BN,
1696
+ PositionDirection.SHORT,
1697
+ oracle.price.sub(new BN(1)), // triggerPrice: BN,
1698
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1699
+ vBid,
1700
+ vAsk
1701
+ );
1702
+ // should NOT trigger market buy with above condition
1703
+ insertTriggerOrderToDLOB(
1704
+ dlob,
1705
+ Keypair.generate().publicKey,
1706
+ OrderType.TRIGGER_MARKET,
1707
+ MarketType.PERP,
1708
+ 11, //orderId
1709
+ marketIndex, // marketIndex
1710
+ vBid, // price
1711
+ BASE_PRECISION, // baseAssetAmount: BN,
1712
+ PositionDirection.LONG,
1713
+ oracle.price.add(new BN(1)), // triggerPrice: BN,
1714
+ OrderTriggerCondition.ABOVE, // triggerCondition: OrderTriggerCondition,
1715
+ vBid,
1716
+ vAsk
1717
+ );
1718
+ // should NOT trigger market buy with below condition
1719
+ insertTriggerOrderToDLOB(
1720
+ dlob,
1721
+ Keypair.generate().publicKey,
1722
+ OrderType.TRIGGER_MARKET,
1723
+ MarketType.PERP,
1724
+ 12, //orderId
1725
+ marketIndex, // marketIndex
1726
+ vBid, // price
1727
+ BASE_PRECISION, // baseAssetAmount: BN,
1728
+ PositionDirection.LONG,
1729
+ oracle.price.sub(new BN(1)), // triggerPrice: BN,
1730
+ OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1731
+ vBid,
1732
+ vAsk
1733
+ );
1734
+
1735
+ const nodesToTrigger = dlob.findNodesToTrigger(
1736
+ marketIndex,
1737
+ slot,
1738
+ oracle.price,
1739
+ MarketType.PERP
1740
+ );
1741
+ console.log(`nodesToTriggeR: ${nodesToTrigger.length}`);
1742
+ for (const [idx, n] of nodesToTrigger.entries()) {
1743
+ expect(n.node.order?.orderId).to.equal(orderIdsToTrigger[idx]);
1744
+ console.log(`nodeToTrigger: ${n.node.order?.orderId.toString()}`);
1745
+ }
1746
+ });
1747
+
1748
+ it('Test will return expired market orders to fill', () => {
1749
+ const vAsk = new BN(15);
1750
+ const vBid = new BN(8);
1751
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1752
+ const marketIndex = 0;
1753
+
1754
+ const slot = 20;
1755
+ const timeInForce = 30;
1756
+
1757
+ // non crossing bid
1758
+ insertOrderToDLOB(
1759
+ dlob,
1760
+ Keypair.generate().publicKey,
1761
+ OrderType.MARKET,
1762
+ MarketType.PERP,
1763
+ 255, // orderId
1764
+ marketIndex,
1765
+ new BN(2), // price, very low, don't cross vamm
1766
+ BASE_PRECISION, // quantity
1767
+ PositionDirection.LONG,
1768
+ vBid,
1769
+ vAsk,
1770
+ new BN(slot),
1771
+ timeInForce
1772
+ );
1773
+ insertOrderToDLOB(
1774
+ dlob,
1775
+ Keypair.generate().publicKey,
1776
+ OrderType.MARKET,
1777
+ MarketType.PERP,
1778
+ 2, // orderId
1779
+ marketIndex,
1780
+ new BN(30), // price, very high, don't cross vamm
1781
+ BASE_PRECISION, // quantity
1782
+ PositionDirection.SHORT,
1783
+ vAsk,
1784
+ vBid,
1785
+ new BN(slot),
1786
+ timeInForce
1787
+ );
1788
+
1789
+ // order auction is not yet complete, and order is not expired.
1790
+ const slot0 = slot;
1791
+ const nodesToFillBefore = dlob.findNodesToFill(
1792
+ marketIndex,
1793
+ vBid,
1794
+ vAsk,
1795
+ slot0,
1796
+ MarketType.PERP,
1797
+ {
1798
+ price: vBid.add(vAsk).div(new BN(2)),
1799
+ slot: new BN(slot0),
1800
+ confidence: new BN(1),
1801
+ hasSufficientNumberOfDataPoints: true,
1802
+ }
1803
+ );
1804
+ expect(nodesToFillBefore.length).to.equal(0);
1805
+
1806
+ // should get order to fill after timeInForce
1807
+ const slot1 = slot0 + timeInForce * 2; // overshoots expiry
1808
+ const nodesToFillAfter = dlob.findNodesToFill(
1809
+ marketIndex,
1810
+ vBid,
1811
+ vAsk,
1812
+ slot1, // auction is over, and order ix expired
1813
+ MarketType.PERP,
1814
+ {
1815
+ price: vBid.add(vAsk).div(new BN(2)),
1816
+ slot: new BN(slot1),
1817
+ confidence: new BN(1),
1818
+ hasSufficientNumberOfDataPoints: true,
1819
+ }
1820
+ );
1821
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
1822
+ for (const n of nodesToFillAfter) {
1823
+ printCrossedNodes(n, slot1);
1824
+ }
1825
+ expect(nodesToFillAfter.length).to.equal(2);
1826
+
1827
+ // check that the nodes have no makers
1828
+ expect(nodesToFillAfter[0].makerNode).to.equal(undefined);
1829
+ expect(nodesToFillAfter[1].makerNode).to.equal(undefined);
1830
+ });
1831
+
1832
+ it('Test skips vAMM and fills market buy order with floating limit order during auction', () => {
1833
+ const vAsk = new BN(15).mul(PRICE_PRECISION);
1834
+ const vBid = new BN(8).mul(PRICE_PRECISION);
1835
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1836
+ const marketIndex = 0;
1837
+
1838
+ const slot = 12;
1839
+ const oracle = {
1840
+ price: vBid.add(vAsk).div(new BN(2)),
1841
+ slot: new BN(slot),
1842
+ confidence: new BN(1),
1843
+ hasSufficientNumberOfDataPoints: true,
1844
+ };
1845
+
1846
+ // insert some floating limit sells above vAMM ask
1847
+ insertOrderToDLOB(
1848
+ dlob,
1849
+ Keypair.generate().publicKey,
1850
+ OrderType.LIMIT,
1851
+ MarketType.PERP,
1852
+ 1, // orderId
1853
+ marketIndex,
1854
+ new BN(14).mul(PRICE_PRECISION), // price
1855
+ BASE_PRECISION, // quantity
1856
+ PositionDirection.SHORT,
1857
+ vBid,
1858
+ vAsk,
1859
+ new BN(slot),
1860
+ 30,
1861
+ new BN(1).mul(PRICE_PRECISION)
1862
+ );
1863
+ insertOrderToDLOB(
1864
+ dlob,
1865
+ Keypair.generate().publicKey,
1866
+ OrderType.LIMIT,
1867
+ MarketType.PERP,
1868
+ 2, // orderId
1869
+ marketIndex,
1870
+ new BN(13).mul(PRICE_PRECISION), // price
1871
+ BASE_PRECISION, // quantity
1872
+ PositionDirection.SHORT,
1873
+ vBid,
1874
+ vAsk,
1875
+ new BN(slot),
1876
+ 30,
1877
+ new BN(1).mul(PRICE_PRECISION)
1878
+ );
1879
+ insertOrderToDLOB(
1880
+ dlob,
1881
+ Keypair.generate().publicKey,
1882
+ OrderType.LIMIT,
1883
+ MarketType.PERP,
1884
+ 3, // orderId
1885
+ marketIndex,
1886
+ new BN(9).mul(PRICE_PRECISION), // price <-- best price
1887
+ new BN(3).mul(BASE_PRECISION), // quantity
1888
+ PositionDirection.SHORT,
1889
+ vBid,
1890
+ vAsk,
1891
+ new BN(slot),
1892
+ 30,
1893
+ new BN(1).mul(PRICE_PRECISION)
1894
+ );
1895
+
1896
+ // should have no crossing orders
1897
+ const nodesToFillBefore = dlob.findNodesToFill(
1898
+ marketIndex,
1899
+ vBid,
1900
+ vAsk,
1901
+ slot,
1902
+ MarketType.PERP,
1903
+ {
1904
+ price: vBid.add(vAsk).div(new BN(2)),
1905
+ slot: new BN(slot),
1906
+ confidence: new BN(1),
1907
+ hasSufficientNumberOfDataPoints: true,
1908
+ }
1909
+ );
1910
+ expect(nodesToFillBefore.length).to.equal(0);
1911
+
1912
+ // place two market buy orders to eat the best ask
1913
+ insertOrderToDLOB(
1914
+ dlob,
1915
+ Keypair.generate().publicKey,
1916
+ OrderType.MARKET,
1917
+ MarketType.PERP,
1918
+ 4, // orderId
1919
+ marketIndex,
1920
+ new BN(15).mul(PRICE_PRECISION), // price
1921
+ new BN(1).mul(BASE_PRECISION), // quantity
1922
+ PositionDirection.LONG,
1923
+ vBid,
1924
+ vAsk
1925
+ );
1926
+ insertOrderToDLOB(
1927
+ dlob,
1928
+ Keypair.generate().publicKey,
1929
+ OrderType.MARKET,
1930
+ MarketType.PERP,
1931
+ 5, // orderId
1932
+ marketIndex,
1933
+ new BN(15).mul(PRICE_PRECISION), // price
1934
+ new BN(2).mul(BASE_PRECISION), // quantity
1935
+ PositionDirection.LONG,
1936
+ vBid,
1937
+ vAsk
1938
+ );
1939
+
1940
+ const nodesToFillAfter = dlob.findNodesToFill(
1941
+ marketIndex,
1942
+ vBid,
1943
+ vAsk,
1944
+ slot,
1945
+ MarketType.PERP,
1946
+ {
1947
+ price: vBid.add(vAsk).div(new BN(2)),
1948
+ slot: new BN(slot),
1949
+ confidence: new BN(1),
1950
+ hasSufficientNumberOfDataPoints: true,
1951
+ }
1952
+ );
1953
+ const mktNodes = dlob.findExpiredMarketNodesToFill(
1954
+ marketIndex,
1955
+ slot,
1956
+ MarketType.PERP
1957
+ );
1958
+ console.log(`market nodes: ${mktNodes.length}`);
1959
+
1960
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
1961
+
1962
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
1963
+ for (const n of nodesToFillAfter) {
1964
+ printCrossedNodes(n, slot);
1965
+ }
1966
+ expect(nodesToFillAfter.length).to.equal(3);
1967
+
1968
+ // taker should fill first order completely with best maker (1/1)
1969
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
1970
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(1);
1971
+
1972
+ // taker should fill partially with second best maker (1/2)
1973
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
1974
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
1975
+
1976
+ // taker should fill completely with third best maker (2/2)
1977
+ expect(nodesToFillAfter[2].node.order?.orderId).to.equal(5);
1978
+ expect(nodesToFillAfter[2].makerNode?.order?.orderId).to.equal(3);
1979
+ });
1980
+
1981
+ it('Test fills market buy order with better priced vAMM after auction', () => {
1982
+ const vAsk = new BN(15).mul(PRICE_PRECISION);
1983
+ const vBid = new BN(8).mul(PRICE_PRECISION);
1984
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1985
+ const marketIndex = 0;
1986
+
1987
+ const slot = 12;
1988
+ const oracle = {
1989
+ price: vBid.add(vAsk).div(new BN(2)),
1990
+ slot: new BN(slot),
1991
+ confidence: new BN(1),
1992
+ hasSufficientNumberOfDataPoints: true,
1993
+ };
1994
+
1995
+ // insert some floating limit sells above vAMM ask
1996
+ insertOrderToDLOB(
1997
+ dlob,
1998
+ Keypair.generate().publicKey,
1999
+ OrderType.LIMIT,
2000
+ MarketType.PERP,
2001
+ 1, // orderId
2002
+ marketIndex,
2003
+ new BN(14).mul(PRICE_PRECISION), // price
2004
+ BASE_PRECISION, // quantity
2005
+ PositionDirection.SHORT,
2006
+ vBid,
2007
+ vAsk,
2008
+ new BN(slot),
2009
+ 0,
2010
+ new BN(3).mul(PRICE_PRECISION)
2011
+ );
2012
+ insertOrderToDLOB(
2013
+ dlob,
2014
+ Keypair.generate().publicKey,
2015
+ OrderType.LIMIT,
2016
+ MarketType.PERP,
2017
+ 2, // orderId
2018
+ marketIndex,
2019
+ new BN(13).mul(PRICE_PRECISION), // price
2020
+ BASE_PRECISION, // quantity
2021
+ PositionDirection.SHORT,
2022
+ vBid,
2023
+ vAsk,
2024
+ new BN(slot),
2025
+ 0,
2026
+ new BN(4).mul(PRICE_PRECISION)
2027
+ );
2028
+ insertOrderToDLOB(
2029
+ dlob,
2030
+ Keypair.generate().publicKey,
2031
+ OrderType.LIMIT,
2032
+ MarketType.PERP,
2033
+ 3, // orderId
2034
+ marketIndex,
2035
+ new BN(9).mul(PRICE_PRECISION), // price <-- best price
2036
+ new BN(3).mul(BASE_PRECISION), // quantity
2037
+ PositionDirection.SHORT,
2038
+ vBid,
2039
+ vAsk,
2040
+ new BN(slot),
2041
+ 0,
2042
+ new BN(5).mul(PRICE_PRECISION)
2043
+ );
2044
+
2045
+ // should have no crossing orders
2046
+ const auctionOverSlot = slot * 10;
2047
+ const nodesToFillBefore = dlob.findCrossingNodesToFill(
2048
+ marketIndex,
2049
+ auctionOverSlot, // auction over
2050
+ MarketType.PERP,
2051
+ oracle
2052
+ );
2053
+ expect(nodesToFillBefore.length).to.equal(0);
2054
+
2055
+ // place two market buy orders
2056
+ insertOrderToDLOB(
2057
+ dlob,
2058
+ Keypair.generate().publicKey,
2059
+ OrderType.MARKET,
2060
+ MarketType.PERP,
2061
+ 4, // orderId
2062
+ marketIndex,
2063
+ new BN(15).mul(PRICE_PRECISION), // price
2064
+ new BN(1).mul(BASE_PRECISION), // quantity
2065
+ PositionDirection.LONG,
2066
+ vBid,
2067
+ vAsk,
2068
+ new BN(slot),
2069
+ 0
2070
+ );
2071
+ insertOrderToDLOB(
2072
+ dlob,
2073
+ Keypair.generate().publicKey,
2074
+ OrderType.MARKET,
2075
+ MarketType.PERP,
2076
+ 5, // orderId
2077
+ marketIndex,
2078
+ new BN(15).mul(PRICE_PRECISION), // price
2079
+ new BN(2).mul(BASE_PRECISION), // quantity
2080
+ PositionDirection.LONG,
2081
+ vBid,
2082
+ vAsk,
2083
+ new BN(slot),
2084
+ 0
2085
+ );
2086
+
2087
+ const nodesToFillAfter = dlob.findNodesToFill(
2088
+ marketIndex,
2089
+ vBid,
2090
+ vAsk,
2091
+ auctionOverSlot, // auction in progress
2092
+ MarketType.PERP,
2093
+ oracle
2094
+ );
2095
+
2096
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
2097
+ for (const n of nodesToFillAfter) {
2098
+ printCrossedNodes(n, auctionOverSlot);
2099
+ }
2100
+ expect(nodesToFillAfter.length).to.equal(2);
2101
+
2102
+ // taker should fill completely with best maker
2103
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
2104
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(1);
2105
+
2106
+ // taker should fill the rest with the vAMM
2107
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
2108
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(undefined);
2109
+ });
2110
+
2111
+ it('Test skips vAMM and fills market sell order with floating limit buys during auction', () => {
2112
+ const vAsk = new BN(15).mul(PRICE_PRECISION);
2113
+ const vBid = new BN(8).mul(PRICE_PRECISION);
2114
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2115
+ const marketIndex = 0;
2116
+
2117
+ const slot = 12;
2118
+ const oracle = {
2119
+ price: vBid.add(vAsk).div(new BN(2)), // 11.5
2120
+ slot: new BN(slot),
2121
+ confidence: new BN(1),
2122
+ hasSufficientNumberOfDataPoints: true,
2123
+ };
2124
+
2125
+ // insert some floating limit buy below vAMM bid
2126
+ insertOrderToDLOB(
2127
+ dlob,
2128
+ Keypair.generate().publicKey,
2129
+ OrderType.LIMIT,
2130
+ MarketType.PERP,
2131
+ 2, // orderId
2132
+ marketIndex,
2133
+ new BN(0).mul(PRICE_PRECISION), // price, ignored since it's a floating limit
2134
+ BASE_PRECISION, // quantity
2135
+ PositionDirection.LONG,
2136
+ vBid,
2137
+ vAsk,
2138
+ new BN(slot),
2139
+ 30,
2140
+ new BN(-4).mul(PRICE_PRECISION) // second best bid, but worse than vBid (8): 7.5
2141
+ );
2142
+ insertOrderToDLOB(
2143
+ dlob,
2144
+ Keypair.generate().publicKey,
2145
+ OrderType.LIMIT,
2146
+ MarketType.PERP,
2147
+ 3, // orderId
2148
+ marketIndex,
2149
+ new BN(0).mul(PRICE_PRECISION), // price; ignored since it's a floating limit
2150
+ new BN(1).mul(BASE_PRECISION), // quantity
2151
+ PositionDirection.LONG,
2152
+ vBid,
2153
+ vAsk,
2154
+ new BN(slot),
2155
+ 30,
2156
+ new BN(-1).mul(PRICE_PRECISION) // best price: 10.5
2157
+ );
2158
+ insertOrderToDLOB(
2159
+ dlob,
2160
+ Keypair.generate().publicKey,
2161
+ OrderType.LIMIT,
2162
+ MarketType.PERP,
2163
+ 1, // orderId
2164
+ marketIndex,
2165
+ new BN(0).mul(PRICE_PRECISION), // price; ignored since it's a floating limit
2166
+ BASE_PRECISION, // quantity
2167
+ PositionDirection.LONG,
2168
+ vBid,
2169
+ vAsk,
2170
+ new BN(slot),
2171
+ 30,
2172
+ new BN(-5).mul(PRICE_PRECISION) // third best bid, worse than vBid (8): 6.5
2173
+ );
2174
+
2175
+ // should have no crossing orders
2176
+ const nodesToFillBefore = dlob.findCrossingNodesToFill(
2177
+ marketIndex,
2178
+ slot,
2179
+ MarketType.PERP,
2180
+ oracle
2181
+ );
2182
+ expect(nodesToFillBefore.length).to.equal(0);
2183
+
2184
+ // place two market sell orders to eat the best bid
2185
+ insertOrderToDLOB(
2186
+ dlob,
2187
+ Keypair.generate().publicKey,
2188
+ OrderType.MARKET,
2189
+ MarketType.PERP,
2190
+ 4, // orderId
2191
+ marketIndex,
2192
+ new BN(5).mul(PRICE_PRECISION), // price
2193
+ new BN(1).mul(BASE_PRECISION), // quantity
2194
+ PositionDirection.SHORT,
2195
+ vBid,
2196
+ vAsk
2197
+ );
2198
+ insertOrderToDLOB(
2199
+ dlob,
2200
+ Keypair.generate().publicKey,
2201
+ OrderType.MARKET,
2202
+ MarketType.PERP,
2203
+ 5, // orderId
2204
+ marketIndex,
2205
+ new BN(4).mul(PRICE_PRECISION), // price
2206
+ new BN(2).mul(BASE_PRECISION), // quantity
2207
+ PositionDirection.SHORT,
2208
+ vBid,
2209
+ vAsk
2210
+ );
2211
+
2212
+ const nodesToFillAfter = dlob.findCrossingNodesToFill(
2213
+ marketIndex,
2214
+ slot, // auction in progress
2215
+ MarketType.PERP,
2216
+ oracle
2217
+ );
2218
+ const mktNodes = dlob.findExpiredMarketNodesToFill(
2219
+ marketIndex,
2220
+ slot,
2221
+ MarketType.PERP
2222
+ );
2223
+ console.log(`market nodes: ${mktNodes.length}`);
2224
+
2225
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
2226
+
2227
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
2228
+ for (const n of nodesToFillAfter) {
2229
+ printCrossedNodes(n, slot);
2230
+ }
2231
+ expect(nodesToFillAfter.length).to.equal(3);
2232
+
2233
+ // taker should fill first order completely with best maker (1/1)
2234
+ expect(
2235
+ nodesToFillAfter[0].node.order?.orderId,
2236
+ 'wrong taker orderId'
2237
+ ).to.equal(4);
2238
+ expect(
2239
+ nodesToFillAfter[0].makerNode?.order?.orderId,
2240
+ 'wrong maker orderId'
2241
+ ).to.equal(3);
2242
+
2243
+ // taker should fill partially with second best maker (1/2)
2244
+ expect(
2245
+ nodesToFillAfter[1].node.order?.orderId,
2246
+ 'wrong maker orderId'
2247
+ ).to.equal(5);
2248
+ expect(
2249
+ nodesToFillAfter[1].makerNode?.order?.orderId,
2250
+ 'wrong maker orderId'
2251
+ ).to.equal(2);
2252
+
2253
+ // taker should fill completely with third best maker (2/2)
2254
+ expect(
2255
+ nodesToFillAfter[2].node.order?.orderId,
2256
+ 'wrong taker orderId'
2257
+ ).to.equal(5);
2258
+ expect(
2259
+ nodesToFillAfter[2].makerNode?.order?.orderId,
2260
+ 'wrong maker orderId'
2261
+ ).to.equal(1);
2262
+ });
2263
+
2264
+ it('Test fills market sell order with better priced vAMM after auction', () => {
2265
+ const vAsk = new BN(15).mul(PRICE_PRECISION);
2266
+ const vBid = new BN(8).mul(PRICE_PRECISION);
2267
+ const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2268
+ const marketIndex = 0;
2269
+
2270
+ const slot = 12;
2271
+ const oracle = {
2272
+ price: vBid.add(vAsk).div(new BN(2)), // 11.5
2273
+ slot: new BN(slot),
2274
+ confidence: new BN(1),
2275
+ hasSufficientNumberOfDataPoints: true,
2276
+ };
2277
+
2278
+ // insert some floating limit buy below vAMM bid
2279
+ insertOrderToDLOB(
2280
+ dlob,
2281
+ Keypair.generate().publicKey,
2282
+ OrderType.LIMIT,
1333
2283
  MarketType.PERP,
1334
- new BN(5), //orderId
1335
- marketIndex, // marketIndex
1336
- vBid, // price
1337
- BASE_PRECISION, // baseAssetAmount: BN,
2284
+ 2, // orderId
2285
+ marketIndex,
2286
+ new BN(0).mul(PRICE_PRECISION), // price, ignored since it's a floating limit
2287
+ BASE_PRECISION, // quantity
1338
2288
  PositionDirection.LONG,
1339
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1340
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1341
2289
  vBid,
1342
- vAsk
2290
+ vAsk,
2291
+ new BN(slot),
2292
+ 30,
2293
+ new BN(-4).mul(PRICE_PRECISION) // second best bid, but worse than vBid (8): 7.5
1343
2294
  );
1344
- // should trigger limit sell with below condition
1345
- insertTriggerOrderToDLOB(
2295
+ insertOrderToDLOB(
1346
2296
  dlob,
1347
2297
  Keypair.generate().publicKey,
1348
- OrderType.TRIGGER_LIMIT,
2298
+ OrderType.LIMIT,
1349
2299
  MarketType.PERP,
1350
- new BN(6), //orderId
1351
- marketIndex, // marketIndex
1352
- vBid, // price
1353
- BASE_PRECISION, // baseAssetAmount: BN,
1354
- PositionDirection.SHORT,
1355
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1356
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
2300
+ 3, // orderId
2301
+ marketIndex,
2302
+ new BN(0).mul(PRICE_PRECISION), // price; ignored since it's a floating limit
2303
+ new BN(1).mul(BASE_PRECISION), // quantity
2304
+ PositionDirection.LONG,
1357
2305
  vBid,
1358
- vAsk
2306
+ vAsk,
2307
+ new BN(slot),
2308
+ 30,
2309
+ new BN(-1).mul(PRICE_PRECISION) // best price: 10.5
1359
2310
  );
1360
- // should trigger market buy with below condition
1361
- insertTriggerOrderToDLOB(
2311
+ insertOrderToDLOB(
1362
2312
  dlob,
1363
2313
  Keypair.generate().publicKey,
1364
- OrderType.TRIGGER_MARKET,
2314
+ OrderType.LIMIT,
1365
2315
  MarketType.PERP,
1366
- new BN(7), //orderId
1367
- marketIndex, // marketIndex
1368
- vBid, // price
1369
- BASE_PRECISION, // baseAssetAmount: BN,
2316
+ 1, // orderId
2317
+ marketIndex,
2318
+ new BN(0).mul(PRICE_PRECISION), // price; ignored since it's a floating limit
2319
+ BASE_PRECISION, // quantity
1370
2320
  PositionDirection.LONG,
1371
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1372
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1373
2321
  vBid,
1374
- vAsk
2322
+ vAsk,
2323
+ new BN(slot),
2324
+ 30,
2325
+ new BN(-5).mul(PRICE_PRECISION) // third best bid, worse than vBid (8): 6.5
1375
2326
  );
1376
- // should trigger market sell with below condition
1377
- insertTriggerOrderToDLOB(
1378
- dlob,
1379
- Keypair.generate().publicKey,
1380
- OrderType.TRIGGER_MARKET,
1381
- MarketType.PERP,
1382
- new BN(8), //orderId
1383
- marketIndex, // marketIndex
1384
- vBid, // price
1385
- BASE_PRECISION, // baseAssetAmount: BN,
1386
- PositionDirection.LONG,
1387
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1388
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
2327
+
2328
+ console.log('DLOB state before fill:');
2329
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
2330
+
2331
+ const nodesToFillBefore = dlob.findNodesToFill(
2332
+ marketIndex,
1389
2333
  vBid,
1390
- vAsk
2334
+ vAsk,
2335
+ slot,
2336
+ MarketType.PERP,
2337
+ oracle
1391
2338
  );
2339
+ expect(nodesToFillBefore.length).to.equal(0);
1392
2340
 
1393
- // should NOT trigger market sell with above condition
1394
- insertTriggerOrderToDLOB(
2341
+ // place two market sell orders to eat the best bid
2342
+ insertOrderToDLOB(
1395
2343
  dlob,
1396
2344
  Keypair.generate().publicKey,
1397
- OrderType.TRIGGER_MARKET,
2345
+ OrderType.MARKET,
1398
2346
  MarketType.PERP,
1399
- new BN(9), //orderId
1400
- marketIndex, // marketIndex
1401
- vBid, // price
1402
- BASE_PRECISION, // baseAssetAmount: BN,
2347
+ 4, // orderId
2348
+ marketIndex,
2349
+ new BN(5).mul(PRICE_PRECISION), // price
2350
+ new BN(1).mul(BASE_PRECISION), // quantity, should consume best bid floating limit
1403
2351
  PositionDirection.SHORT,
1404
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1405
- OrderTriggerCondition.ABOVE, // triggerCondition: OrderTriggerCondition,
1406
2352
  vBid,
1407
- vAsk
2353
+ vAsk,
2354
+ new BN(slot)
1408
2355
  );
1409
- // should NOT trigger market sell with below condition
1410
- insertTriggerOrderToDLOB(
2356
+ insertOrderToDLOB(
1411
2357
  dlob,
1412
2358
  Keypair.generate().publicKey,
1413
- OrderType.TRIGGER_MARKET,
2359
+ OrderType.MARKET,
1414
2360
  MarketType.PERP,
1415
- new BN(10), //orderId
1416
- marketIndex, // marketIndex
1417
- vBid, // price
1418
- BASE_PRECISION, // baseAssetAmount: BN,
2361
+ 5, // orderId
2362
+ marketIndex,
2363
+ // new BN(8).mul(PRICE_PRECISION), // price, this price will fill with vamm
2364
+ new BN(4).mul(PRICE_PRECISION), // price, this SHOULD fill with vamm
2365
+ new BN(2).mul(BASE_PRECISION), // quantity, should be filled with next best bid (vAMM)
1419
2366
  PositionDirection.SHORT,
1420
- oracle.price.sub(new BN(1)), // triggerPrice: BN,
1421
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1422
2367
  vBid,
1423
- vAsk
2368
+ vAsk,
2369
+ new BN(slot)
1424
2370
  );
1425
- // should NOT trigger market buy with above condition
1426
- insertTriggerOrderToDLOB(
1427
- dlob,
1428
- Keypair.generate().publicKey,
1429
- OrderType.TRIGGER_MARKET,
1430
- MarketType.PERP,
1431
- new BN(11), //orderId
1432
- marketIndex, // marketIndex
1433
- vBid, // price
1434
- BASE_PRECISION, // baseAssetAmount: BN,
1435
- PositionDirection.LONG,
1436
- oracle.price.add(new BN(1)), // triggerPrice: BN,
1437
- OrderTriggerCondition.ABOVE, // triggerCondition: OrderTriggerCondition,
2371
+
2372
+ // auction ends, but order not expired
2373
+ const afterAuctionSlot = slot + 11;
2374
+ printBookState(dlob, marketIndex, vBid, vAsk, afterAuctionSlot, oracle);
2375
+
2376
+ const nodesToFillAfter = dlob.findNodesToFill(
2377
+ marketIndex,
1438
2378
  vBid,
1439
- vAsk
1440
- );
1441
- // should NOT trigger market buy with below condition
1442
- insertTriggerOrderToDLOB(
1443
- dlob,
1444
- Keypair.generate().publicKey,
1445
- OrderType.TRIGGER_MARKET,
2379
+ vAsk,
2380
+ afterAuctionSlot,
1446
2381
  MarketType.PERP,
1447
- new BN(12), //orderId
1448
- marketIndex, // marketIndex
1449
- vBid, // price
1450
- BASE_PRECISION, // baseAssetAmount: BN,
1451
- PositionDirection.LONG,
1452
- oracle.price.sub(new BN(1)), // triggerPrice: BN,
1453
- OrderTriggerCondition.BELOW, // triggerCondition: OrderTriggerCondition,
1454
- vBid,
1455
- vAsk
2382
+ oracle
1456
2383
  );
1457
2384
 
1458
- const nodesToTrigger = dlob.findNodesToTrigger(
1459
- marketIndex,
1460
- slot,
1461
- oracle.price,
1462
- MarketType.PERP
1463
- );
1464
- console.log(`nodesToTriggeR: ${nodesToTrigger.length}`);
1465
- for (const [idx, n] of nodesToTrigger.entries()) {
1466
- expect(n.node.order?.orderId.toNumber()).to.equal(orderIdsToTrigger[idx]);
1467
- console.log(`nodeToTrigger: ${n.node.order?.orderId.toString()}`);
2385
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
2386
+ for (const n of nodesToFillAfter) {
2387
+ printCrossedNodes(n, afterAuctionSlot);
1468
2388
  }
2389
+
2390
+ // taker should fill first order completely with best maker (1/1)
2391
+ expect(
2392
+ nodesToFillAfter[0].node.order?.orderId,
2393
+ 'wrong taker orderId'
2394
+ ).to.equal(4);
2395
+ expect(
2396
+ nodesToFillAfter[0].makerNode?.order?.orderId,
2397
+ 'wrong maker orderId'
2398
+ ).to.equal(3);
2399
+
2400
+ // taker should fill second order completely with vamm
2401
+ expect(
2402
+ nodesToFillAfter[1].node.order?.orderId,
2403
+ 'wrong taker orderId'
2404
+ ).to.equal(5);
2405
+ expect(
2406
+ nodesToFillAfter[1].makerNode?.order?.orderId,
2407
+ 'wrong maker orderId'
2408
+ ).to.equal(2); // filler should match the DLOB makers, protocol will fill the taker with vAMM if it offers a better price.
2409
+
2410
+ expect(nodesToFillAfter.length).to.equal(3);
1469
2411
  });
1470
2412
 
1471
- it('Test will return expired market orders to fill', () => {
1472
- const vAsk = new BN(15);
1473
- const vBid = new BN(8);
2413
+ it('Test fills crossing bids with vAMM after auction ends', () => {
2414
+ const vAsk = new BN(15).mul(PRICE_PRECISION);
2415
+ const vBid = new BN(8).mul(PRICE_PRECISION);
1474
2416
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1475
- const marketIndex = new BN(0);
2417
+ const marketIndex = 0;
1476
2418
 
1477
- const slot = 20;
1478
- const timeInForce = 30;
2419
+ const slot = 12;
2420
+ const oracle = {
2421
+ price: vBid.add(vAsk).div(new BN(2)), // 11.5
2422
+ slot: new BN(slot),
2423
+ confidence: new BN(1),
2424
+ hasSufficientNumberOfDataPoints: true,
2425
+ };
1479
2426
 
1480
- // non crossing bid
2427
+ // insert some floating limit buy below vAMM bid
1481
2428
  insertOrderToDLOB(
1482
2429
  dlob,
1483
2430
  Keypair.generate().publicKey,
1484
- OrderType.MARKET,
2431
+ OrderType.LIMIT,
1485
2432
  MarketType.PERP,
1486
- new BN(255), // orderId
2433
+ 2, // orderId
1487
2434
  marketIndex,
1488
- new BN(2), // price, very low, don't cross vamm
2435
+ new BN(17).mul(PRICE_PRECISION), // price, crosses vAsk
1489
2436
  BASE_PRECISION, // quantity
1490
2437
  PositionDirection.LONG,
1491
2438
  vBid,
1492
2439
  vAsk,
1493
2440
  new BN(slot),
1494
- timeInForce
2441
+ 30
1495
2442
  );
1496
2443
  insertOrderToDLOB(
1497
2444
  dlob,
1498
2445
  Keypair.generate().publicKey,
1499
- OrderType.MARKET,
2446
+ OrderType.LIMIT,
1500
2447
  MarketType.PERP,
1501
- new BN(2), // orderId
2448
+ 3, // orderId
1502
2449
  marketIndex,
1503
- new BN(30), // price, very high, don't cross vamm
1504
- BASE_PRECISION, // quantity
1505
- PositionDirection.SHORT,
2450
+ new BN(19).mul(PRICE_PRECISION), // price; crosses vAsk
2451
+ new BN(1).mul(BASE_PRECISION), // quantity
2452
+ PositionDirection.LONG,
2453
+ vBid,
1506
2454
  vAsk,
2455
+ new BN(slot),
2456
+ 30
2457
+ );
2458
+ insertOrderToDLOB(
2459
+ dlob,
2460
+ Keypair.generate().publicKey,
2461
+ OrderType.LIMIT,
2462
+ MarketType.PERP,
2463
+ 1, // orderId
2464
+ marketIndex,
2465
+ new BN(5).mul(PRICE_PRECISION), // price; doens't cross
2466
+ BASE_PRECISION, // quantity
2467
+ PositionDirection.LONG,
1507
2468
  vBid,
2469
+ vAsk,
1508
2470
  new BN(slot),
1509
- timeInForce
2471
+ 30
1510
2472
  );
2473
+ console.log(`Book state before fill:`);
2474
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
1511
2475
 
1512
- // order auction is not yet complete, and order is not expired.
1513
- const slot0 = slot;
1514
2476
  const nodesToFillBefore = dlob.findNodesToFill(
1515
2477
  marketIndex,
1516
2478
  vBid,
1517
2479
  vAsk,
1518
- slot0,
2480
+ slot,
1519
2481
  MarketType.PERP,
1520
- {
1521
- price: vBid.add(vAsk).div(new BN(2)),
1522
- slot: new BN(slot0),
1523
- confidence: new BN(1),
1524
- hasSufficientNumberOfDataPoints: true,
1525
- }
2482
+ oracle
1526
2483
  );
1527
2484
  expect(nodesToFillBefore.length).to.equal(0);
1528
2485
 
1529
- // should get order to fill after timeInForce
1530
- const slot1 = slot0 + timeInForce; // overshoots expiry
2486
+ // auction ends now
2487
+ const afterAuctionSlot = 10 * slot;
2488
+
1531
2489
  const nodesToFillAfter = dlob.findNodesToFill(
1532
2490
  marketIndex,
1533
2491
  vBid,
1534
2492
  vAsk,
1535
- slot1, // auction is over, and order ix expired
2493
+ afterAuctionSlot,
1536
2494
  MarketType.PERP,
1537
- {
1538
- price: vBid.add(vAsk).div(new BN(2)),
1539
- slot: new BN(slot1),
1540
- confidence: new BN(1),
1541
- hasSufficientNumberOfDataPoints: true,
1542
- }
2495
+ oracle
1543
2496
  );
1544
- expect(nodesToFillAfter.length).to.equal(2);
1545
2497
 
1546
- // check that the nodes have no makers
1547
- expect(nodesToFillAfter[0].makerNode).to.equal(undefined);
1548
- expect(nodesToFillAfter[1].makerNode).to.equal(undefined);
2498
+ console.log(`Book state after fill:`);
2499
+ printBookState(dlob, marketIndex, vBid, vAsk, afterAuctionSlot, oracle);
2500
+
2501
+ console.log(`Filled nodes: ${nodesToFillAfter.length}`);
2502
+ for (const n of nodesToFillAfter) {
2503
+ printCrossedNodes(n, afterAuctionSlot);
2504
+ }
2505
+
2506
+ // taker should fill first order completely with best maker (1/1)
2507
+ expect(
2508
+ nodesToFillAfter[0].node.order?.orderId,
2509
+ 'wrong taker orderId'
2510
+ ).to.equal(3);
2511
+ expect(
2512
+ nodesToFillAfter[0].makerNode?.order?.orderId,
2513
+ 'wrong maker orderId'
2514
+ ).to.equal(undefined);
2515
+
2516
+ // taker should fill second order completely with vamm
2517
+ expect(
2518
+ nodesToFillAfter[1].node.order?.orderId,
2519
+ 'wrong taker orderId'
2520
+ ).to.equal(2);
2521
+ expect(
2522
+ nodesToFillAfter[1].makerNode?.order?.orderId,
2523
+ 'wrong maker orderId'
2524
+ ).to.equal(undefined);
2525
+
2526
+ expect(nodesToFillAfter.length).to.equal(2);
1549
2527
  });
1550
2528
  });
1551
2529
 
@@ -1554,7 +2532,7 @@ describe('DLOB Spot Tests', () => {
1554
2532
  const vAsk = new BN(115);
1555
2533
  const vBid = new BN(100);
1556
2534
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1557
- const marketIndex = new BN(0);
2535
+ const marketIndex = 0;
1558
2536
 
1559
2537
  const slot = 12;
1560
2538
  const oracle = {
@@ -1566,49 +2544,49 @@ describe('DLOB Spot Tests', () => {
1566
2544
  const testCases = [
1567
2545
  {
1568
2546
  expectedIdx: 3,
1569
- orderId: new BN(5),
2547
+ orderId: 5,
1570
2548
  price: new BN(0), // will calc 108
1571
2549
  direction: PositionDirection.LONG,
1572
2550
  orderType: OrderType.MARKET,
1573
2551
  },
1574
2552
  {
1575
2553
  expectedIdx: 4,
1576
- orderId: new BN(6),
2554
+ orderId: 6,
1577
2555
  price: new BN(0), // will calc 108
1578
2556
  direction: PositionDirection.LONG,
1579
2557
  orderType: OrderType.MARKET,
1580
2558
  },
1581
2559
  {
1582
2560
  expectedIdx: 5,
1583
- orderId: new BN(7),
2561
+ orderId: 7,
1584
2562
  price: new BN(0), // will calc 108
1585
2563
  direction: PositionDirection.LONG,
1586
2564
  orderType: OrderType.MARKET,
1587
2565
  },
1588
2566
  {
1589
2567
  expectedIdx: 0,
1590
- orderId: new BN(1),
2568
+ orderId: 1,
1591
2569
  price: new BN(110),
1592
2570
  direction: PositionDirection.LONG,
1593
2571
  orderType: OrderType.LIMIT,
1594
2572
  },
1595
2573
  {
1596
2574
  expectedIdx: 1,
1597
- orderId: new BN(2),
2575
+ orderId: 2,
1598
2576
  price: new BN(109),
1599
2577
  direction: PositionDirection.LONG,
1600
2578
  orderType: OrderType.LIMIT,
1601
2579
  },
1602
2580
  {
1603
2581
  expectedIdx: 6,
1604
- orderId: new BN(3),
2582
+ orderId: 3,
1605
2583
  price: new BN(107),
1606
2584
  direction: PositionDirection.LONG,
1607
2585
  orderType: OrderType.LIMIT,
1608
2586
  },
1609
2587
  {
1610
2588
  expectedIdx: 7,
1611
- orderId: new BN(4),
2589
+ orderId: 4,
1612
2590
  price: new BN(106),
1613
2591
  direction: PositionDirection.LONG,
1614
2592
  orderType: OrderType.LIMIT,
@@ -1621,7 +2599,7 @@ describe('DLOB Spot Tests', () => {
1621
2599
  Keypair.generate().publicKey,
1622
2600
  t.orderType || OrderType.LIMIT,
1623
2601
  MarketType.SPOT,
1624
- t.orderId || new BN(0), // orderId
2602
+ t.orderId || 0, // orderId
1625
2603
  marketIndex,
1626
2604
  t.price || new BN(0), // price
1627
2605
  BASE_PRECISION, // quantity
@@ -1646,18 +2624,9 @@ describe('DLOB Spot Tests', () => {
1646
2624
  console.log('The Book Bids:');
1647
2625
  let countBids = 0;
1648
2626
  for (const bid of bids) {
1649
- console.log(
1650
- ` . vAMMNode? ${bid.isVammNode()}, ${JSON.stringify(
1651
- bid.order?.orderType
1652
- )} , ${bid.order?.orderId.toString()} , vammTestgetPRice: ${bid.getPrice(
1653
- oracle,
1654
- slot
1655
- )}, price: ${bid.order?.price.toString()}, quantity: ${bid.order?.baseAssetAmountFilled.toString()}/${bid.order?.baseAssetAmount.toString()}`
1656
- );
2627
+ printOrderNode(bid, oracle, slot);
1657
2628
 
1658
- expect(bid.order?.orderId.toNumber()).to.equal(
1659
- expectedTestCase[countBids].orderId?.toNumber()
1660
- );
2629
+ expect(bid.order?.orderId).to.equal(expectedTestCase[countBids].orderId);
1661
2630
  expect(bid.order?.price.toNumber()).to.equal(
1662
2631
  expectedTestCase[countBids].price?.toNumber()
1663
2632
  );
@@ -1677,8 +2646,8 @@ describe('DLOB Spot Tests', () => {
1677
2646
  const vAsk = new BN(15);
1678
2647
  const vBid = new BN(10);
1679
2648
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1680
- const marketIndex0 = new BN(0);
1681
- const marketIndex1 = new BN(1);
2649
+ const marketIndex0 = 0;
2650
+ const marketIndex1 = 1;
1682
2651
 
1683
2652
  const slot = 12;
1684
2653
  const oracle = {
@@ -1690,7 +2659,7 @@ describe('DLOB Spot Tests', () => {
1690
2659
  const testCases = [
1691
2660
  {
1692
2661
  expectedIdx: 3,
1693
- orderId: new BN(5),
2662
+ orderId: 5,
1694
2663
  price: new BN(0),
1695
2664
  direction: PositionDirection.LONG,
1696
2665
  orderType: OrderType.MARKET,
@@ -1698,7 +2667,7 @@ describe('DLOB Spot Tests', () => {
1698
2667
  },
1699
2668
  {
1700
2669
  expectedIdx: 4,
1701
- orderId: new BN(6),
2670
+ orderId: 6,
1702
2671
  price: new BN(0),
1703
2672
  direction: PositionDirection.LONG,
1704
2673
  orderType: OrderType.MARKET,
@@ -1706,7 +2675,7 @@ describe('DLOB Spot Tests', () => {
1706
2675
  },
1707
2676
  {
1708
2677
  expectedIdx: 5,
1709
- orderId: new BN(7),
2678
+ orderId: 7,
1710
2679
  price: new BN(0),
1711
2680
  direction: PositionDirection.LONG,
1712
2681
  orderType: OrderType.MARKET,
@@ -1714,7 +2683,7 @@ describe('DLOB Spot Tests', () => {
1714
2683
  },
1715
2684
  {
1716
2685
  expectedIdx: 0,
1717
- orderId: new BN(1),
2686
+ orderId: 1,
1718
2687
  price: new BN(12),
1719
2688
  direction: PositionDirection.LONG,
1720
2689
  orderType: OrderType.LIMIT,
@@ -1722,7 +2691,7 @@ describe('DLOB Spot Tests', () => {
1722
2691
  },
1723
2692
  {
1724
2693
  expectedIdx: 1,
1725
- orderId: new BN(2),
2694
+ orderId: 2,
1726
2695
  price: new BN(11),
1727
2696
  direction: PositionDirection.LONG,
1728
2697
  orderType: OrderType.LIMIT,
@@ -1730,7 +2699,7 @@ describe('DLOB Spot Tests', () => {
1730
2699
  },
1731
2700
  {
1732
2701
  expectedIdx: 7,
1733
- orderId: new BN(3),
2702
+ orderId: 3,
1734
2703
  price: new BN(8),
1735
2704
  direction: PositionDirection.LONG,
1736
2705
  orderType: OrderType.LIMIT,
@@ -1738,7 +2707,7 @@ describe('DLOB Spot Tests', () => {
1738
2707
  },
1739
2708
  {
1740
2709
  expectedIdx: 6,
1741
- orderId: new BN(4),
2710
+ orderId: 4,
1742
2711
  price: new BN(9),
1743
2712
  direction: PositionDirection.LONG,
1744
2713
  orderType: OrderType.LIMIT,
@@ -1752,7 +2721,7 @@ describe('DLOB Spot Tests', () => {
1752
2721
  Keypair.generate().publicKey,
1753
2722
  t.orderType || OrderType.LIMIT,
1754
2723
  MarketType.SPOT,
1755
- t.orderId || new BN(0), // orderId
2724
+ t.orderId || 0, // orderId
1756
2725
  t.marketIndex,
1757
2726
  t.price || new BN(0), // price
1758
2727
  BASE_PRECISION, // quantity
@@ -1810,7 +2779,7 @@ describe('DLOB Spot Tests', () => {
1810
2779
  const vAsk = new BN(15);
1811
2780
  const vBid = new BN(10);
1812
2781
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1813
- const marketIndex = new BN(0);
2782
+ const marketIndex = 0;
1814
2783
 
1815
2784
  const slot = 12;
1816
2785
  const oracle = {
@@ -1822,49 +2791,49 @@ describe('DLOB Spot Tests', () => {
1822
2791
  const testCases = [
1823
2792
  {
1824
2793
  expectedIdx: 0,
1825
- orderId: new BN(3),
2794
+ orderId: 3,
1826
2795
  price: new BN(0),
1827
2796
  direction: PositionDirection.SHORT,
1828
2797
  orderType: OrderType.MARKET,
1829
2798
  },
1830
2799
  {
1831
2800
  expectedIdx: 1,
1832
- orderId: new BN(4),
2801
+ orderId: 4,
1833
2802
  price: new BN(0),
1834
2803
  direction: PositionDirection.SHORT,
1835
2804
  orderType: OrderType.MARKET,
1836
2805
  },
1837
2806
  {
1838
2807
  expectedIdx: 2,
1839
- orderId: new BN(5),
2808
+ orderId: 5,
1840
2809
  price: new BN(0),
1841
2810
  direction: PositionDirection.SHORT,
1842
2811
  orderType: OrderType.MARKET,
1843
2812
  },
1844
2813
  {
1845
2814
  expectedIdx: 3,
1846
- orderId: new BN(1),
2815
+ orderId: 1,
1847
2816
  price: new BN(13),
1848
2817
  direction: PositionDirection.SHORT,
1849
2818
  orderType: OrderType.LIMIT,
1850
2819
  },
1851
2820
  {
1852
2821
  expectedIdx: 6,
1853
- orderId: new BN(6),
2822
+ orderId: 6,
1854
2823
  price: new BN(16),
1855
2824
  direction: PositionDirection.SHORT,
1856
2825
  orderType: OrderType.LIMIT,
1857
2826
  },
1858
2827
  {
1859
2828
  expectedIdx: 7,
1860
- orderId: new BN(7),
2829
+ orderId: 7,
1861
2830
  price: new BN(17),
1862
2831
  direction: PositionDirection.SHORT,
1863
2832
  orderType: OrderType.LIMIT,
1864
2833
  },
1865
2834
  {
1866
2835
  expectedIdx: 4,
1867
- orderId: new BN(2),
2836
+ orderId: 2,
1868
2837
  price: new BN(14),
1869
2838
  direction: PositionDirection.SHORT,
1870
2839
  orderType: OrderType.LIMIT,
@@ -1877,7 +2846,7 @@ describe('DLOB Spot Tests', () => {
1877
2846
  Keypair.generate().publicKey,
1878
2847
  t.orderType || OrderType.LIMIT,
1879
2848
  MarketType.SPOT,
1880
- t.orderId || new BN(0), // orderId
2849
+ t.orderId || 0, // orderId
1881
2850
  marketIndex,
1882
2851
  t.price || new BN(0), // price
1883
2852
  BASE_PRECISION, // quantity
@@ -1905,9 +2874,7 @@ describe('DLOB Spot Tests', () => {
1905
2874
  )}, price: ${ask.order?.price.toString()}, quantity: ${ask.order?.baseAssetAmountFilled.toString()}/${ask.order?.baseAssetAmount.toString()}`
1906
2875
  );
1907
2876
 
1908
- expect(ask.order?.orderId.toNumber()).to.equal(
1909
- expectedTestCase[countAsks].orderId?.toNumber()
1910
- );
2877
+ expect(ask.order?.orderId).to.equal(expectedTestCase[countAsks].orderId);
1911
2878
  expect(ask.order?.price.toNumber()).to.equal(
1912
2879
  expectedTestCase[countAsks].price?.toNumber()
1913
2880
  );
@@ -1934,7 +2901,7 @@ describe('DLOB Spot Tests', () => {
1934
2901
  hasSufficientNumberOfDataPoints: true,
1935
2902
  };
1936
2903
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
1937
- const marketIndex = new BN(0);
2904
+ const marketIndex = 0;
1938
2905
 
1939
2906
  // 3 mkt buys
1940
2907
  for (let i = 0; i < 3; i++) {
@@ -1943,7 +2910,7 @@ describe('DLOB Spot Tests', () => {
1943
2910
  Keypair.generate().publicKey,
1944
2911
  OrderType.MARKET,
1945
2912
  MarketType.SPOT,
1946
- new BN(i + 1),
2913
+ i + 1,
1947
2914
  marketIndex,
1948
2915
  new BN(0),
1949
2916
  BASE_PRECISION,
@@ -1960,7 +2927,7 @@ describe('DLOB Spot Tests', () => {
1960
2927
  Keypair.generate().publicKey,
1961
2928
  OrderType.MARKET,
1962
2929
  MarketType.SPOT,
1963
- new BN(i + 1),
2930
+ i + 1,
1964
2931
  marketIndex,
1965
2932
  new BN(0),
1966
2933
  BASE_PRECISION,
@@ -1986,7 +2953,7 @@ describe('DLOB Spot Tests', () => {
1986
2953
  expect(getVariant(ask.order?.status)).to.equal('open');
1987
2954
  expect(getVariant(ask.order?.orderType)).to.equal('market');
1988
2955
  expect(getVariant(ask.order?.direction)).to.equal('short');
1989
- expect(ask.order?.orderId.toNumber()).to.equal(asks);
2956
+ expect(ask.order?.orderId).to.equal(asks);
1990
2957
  }
1991
2958
  }
1992
2959
  expect(asks).to.equal(3);
@@ -2003,7 +2970,7 @@ describe('DLOB Spot Tests', () => {
2003
2970
  expect(getVariant(bid.order?.status)).to.equal('open');
2004
2971
  expect(getVariant(bid.order?.orderType)).to.equal('market');
2005
2972
  expect(getVariant(bid.order?.direction)).to.equal('long');
2006
- expect(bid.order?.orderId.toNumber()).to.equal(bids + 1);
2973
+ expect(bid.order?.orderId).to.equal(bids + 1);
2007
2974
  bids++;
2008
2975
  }
2009
2976
  expect(bids).to.equal(3); // 3 orders
@@ -2020,13 +2987,13 @@ describe('DLOB Spot Tests', () => {
2020
2987
  hasSufficientNumberOfDataPoints: true,
2021
2988
  };
2022
2989
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2023
- const marketIndex = new BN(0);
2990
+ const marketIndex = 0;
2024
2991
  insertOrderToDLOB(
2025
2992
  dlob,
2026
2993
  Keypair.generate().publicKey,
2027
2994
  OrderType.LIMIT,
2028
2995
  MarketType.SPOT,
2029
- new BN(3),
2996
+ 3, // orderId
2030
2997
  marketIndex,
2031
2998
  new BN(50),
2032
2999
  BASE_PRECISION,
@@ -2040,7 +3007,7 @@ describe('DLOB Spot Tests', () => {
2040
3007
  Keypair.generate().publicKey,
2041
3008
  OrderType.LIMIT,
2042
3009
  MarketType.SPOT,
2043
- new BN(2),
3010
+ 2, // orderId
2044
3011
  marketIndex,
2045
3012
  new BN(60),
2046
3013
  BASE_PRECISION,
@@ -2054,7 +3021,7 @@ describe('DLOB Spot Tests', () => {
2054
3021
  Keypair.generate().publicKey,
2055
3022
  OrderType.LIMIT,
2056
3023
  MarketType.SPOT,
2057
- new BN(1),
3024
+ 1, // orderId
2058
3025
  marketIndex,
2059
3026
  new BN(70),
2060
3027
  BASE_PRECISION,
@@ -2068,7 +3035,7 @@ describe('DLOB Spot Tests', () => {
2068
3035
  Keypair.generate().publicKey,
2069
3036
  OrderType.LIMIT,
2070
3037
  MarketType.SPOT,
2071
- new BN(1),
3038
+ 1, // orderId
2072
3039
  marketIndex,
2073
3040
  new BN(120),
2074
3041
  BASE_PRECISION,
@@ -2082,7 +3049,7 @@ describe('DLOB Spot Tests', () => {
2082
3049
  Keypair.generate().publicKey,
2083
3050
  OrderType.LIMIT,
2084
3051
  MarketType.SPOT,
2085
- new BN(2),
3052
+ 2, // orderId
2086
3053
  marketIndex,
2087
3054
  new BN(130),
2088
3055
  BASE_PRECISION,
@@ -2096,7 +3063,7 @@ describe('DLOB Spot Tests', () => {
2096
3063
  Keypair.generate().publicKey,
2097
3064
  OrderType.LIMIT,
2098
3065
  MarketType.SPOT,
2099
- new BN(3),
3066
+ 3, // orderId
2100
3067
  marketIndex,
2101
3068
  new BN(140),
2102
3069
  BASE_PRECISION,
@@ -2122,7 +3089,7 @@ describe('DLOB Spot Tests', () => {
2122
3089
  expect(getVariant(ask.order?.status)).to.equal('open');
2123
3090
  expect(getVariant(ask.order?.orderType)).to.equal('limit');
2124
3091
  expect(getVariant(ask.order?.direction)).to.equal('short');
2125
- expect(ask.order?.orderId.toNumber()).to.equal(asks + 1);
3092
+ expect(ask.order?.orderId).to.equal(asks + 1);
2126
3093
  expect(ask.order?.price.gt(vAsk)).to.equal(true);
2127
3094
  asks++;
2128
3095
  }
@@ -2145,7 +3112,7 @@ describe('DLOB Spot Tests', () => {
2145
3112
  expect(getVariant(bid.order?.status)).to.equal('open');
2146
3113
  expect(getVariant(bid.order?.orderType)).to.equal('limit');
2147
3114
  expect(getVariant(bid.order?.direction)).to.equal('long');
2148
- expect(bid.order?.orderId.toNumber()).to.equal(bids + 1);
3115
+ expect(bid.order?.orderId).to.equal(bids + 1);
2149
3116
  expect(bid.order?.price.lt(vBid)).to.equal(true);
2150
3117
  bids++;
2151
3118
  }
@@ -2156,7 +3123,7 @@ describe('DLOB Spot Tests', () => {
2156
3123
  const vAsk = new BN(15);
2157
3124
  const vBid = new BN(10);
2158
3125
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2159
- const marketIndex = new BN(0);
3126
+ const marketIndex = 0;
2160
3127
 
2161
3128
  // insert some limit buys above vamm bid, below ask
2162
3129
  insertOrderToDLOB(
@@ -2164,7 +3131,7 @@ describe('DLOB Spot Tests', () => {
2164
3131
  Keypair.generate().publicKey,
2165
3132
  OrderType.LIMIT,
2166
3133
  MarketType.SPOT,
2167
- new BN(1), // orderId
3134
+ 1, // orderId
2168
3135
  marketIndex,
2169
3136
  new BN(11), // price
2170
3137
  BASE_PRECISION, // quantity
@@ -2177,7 +3144,7 @@ describe('DLOB Spot Tests', () => {
2177
3144
  Keypair.generate().publicKey,
2178
3145
  OrderType.LIMIT,
2179
3146
  MarketType.SPOT,
2180
- new BN(2), // orderId
3147
+ 2, // orderId
2181
3148
  marketIndex,
2182
3149
  new BN(12), // price
2183
3150
  BASE_PRECISION, // quantity
@@ -2190,7 +3157,7 @@ describe('DLOB Spot Tests', () => {
2190
3157
  Keypair.generate().publicKey,
2191
3158
  OrderType.LIMIT,
2192
3159
  MarketType.SPOT,
2193
- new BN(3), // orderId
3160
+ 3, // orderId
2194
3161
  marketIndex,
2195
3162
  new BN(13), // price
2196
3163
  BASE_PRECISION, // quantity
@@ -2202,8 +3169,6 @@ describe('DLOB Spot Tests', () => {
2202
3169
  // should have no crossing orders
2203
3170
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
2204
3171
  marketIndex,
2205
- vBid,
2206
- vAsk,
2207
3172
  12, // auction over
2208
3173
  MarketType.SPOT,
2209
3174
  {
@@ -2221,7 +3186,7 @@ describe('DLOB Spot Tests', () => {
2221
3186
  Keypair.generate().publicKey,
2222
3187
  OrderType.MARKET,
2223
3188
  MarketType.SPOT,
2224
- new BN(4), // orderId
3189
+ 4, // orderId
2225
3190
  marketIndex,
2226
3191
  new BN(12), // price
2227
3192
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -2234,7 +3199,7 @@ describe('DLOB Spot Tests', () => {
2234
3199
  Keypair.generate().publicKey,
2235
3200
  OrderType.MARKET,
2236
3201
  MarketType.SPOT,
2237
- new BN(5), // orderId
3202
+ 5, // orderId
2238
3203
  marketIndex,
2239
3204
  new BN(12), // price
2240
3205
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -2245,8 +3210,6 @@ describe('DLOB Spot Tests', () => {
2245
3210
 
2246
3211
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
2247
3212
  marketIndex,
2248
- vBid,
2249
- vAsk,
2250
3213
  12, // auction over
2251
3214
  MarketType.SPOT,
2252
3215
  {
@@ -2264,23 +3227,19 @@ describe('DLOB Spot Tests', () => {
2264
3227
  expect(nodesToFillAfter.length).to.equal(2);
2265
3228
 
2266
3229
  // first taker should fill with best maker
2267
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
2268
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
2269
- 3
2270
- );
3230
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
3231
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
2271
3232
 
2272
3233
  // second taker should fill with second best maker
2273
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(5);
2274
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
2275
- 2
2276
- );
3234
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
3235
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
2277
3236
  });
2278
3237
 
2279
3238
  it('Test one market order fills two limit orders', () => {
2280
3239
  const vAsk = new BN(15);
2281
3240
  const vBid = new BN(10);
2282
3241
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2283
- const marketIndex = new BN(0);
3242
+ const marketIndex = 0;
2284
3243
 
2285
3244
  // insert some limit sells below vAMM ask, above bid
2286
3245
  insertOrderToDLOB(
@@ -2288,7 +3247,7 @@ describe('DLOB Spot Tests', () => {
2288
3247
  Keypair.generate().publicKey,
2289
3248
  OrderType.LIMIT,
2290
3249
  MarketType.SPOT,
2291
- new BN(1), // orderId
3250
+ 1, // orderId
2292
3251
  marketIndex,
2293
3252
  new BN(14), // price
2294
3253
  BASE_PRECISION, // quantity
@@ -2301,7 +3260,7 @@ describe('DLOB Spot Tests', () => {
2301
3260
  Keypair.generate().publicKey,
2302
3261
  OrderType.LIMIT,
2303
3262
  MarketType.SPOT,
2304
- new BN(2), // orderId
3263
+ 2, // orderId
2305
3264
  marketIndex,
2306
3265
  new BN(12), // price
2307
3266
  BASE_PRECISION, // quantity
@@ -2314,7 +3273,7 @@ describe('DLOB Spot Tests', () => {
2314
3273
  Keypair.generate().publicKey,
2315
3274
  OrderType.LIMIT,
2316
3275
  MarketType.SPOT,
2317
- new BN(3), // orderId
3276
+ 3, // orderId
2318
3277
  marketIndex,
2319
3278
  new BN(11), // price
2320
3279
  BASE_PRECISION, // quantity
@@ -2326,8 +3285,6 @@ describe('DLOB Spot Tests', () => {
2326
3285
  // should have no crossing orders
2327
3286
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
2328
3287
  marketIndex,
2329
- vBid,
2330
- vAsk,
2331
3288
  12, // auction over
2332
3289
  MarketType.SPOT,
2333
3290
  {
@@ -2345,7 +3302,7 @@ describe('DLOB Spot Tests', () => {
2345
3302
  Keypair.generate().publicKey,
2346
3303
  OrderType.MARKET,
2347
3304
  MarketType.SPOT,
2348
- new BN(4), // orderId
3305
+ 4, // orderId
2349
3306
  marketIndex,
2350
3307
  new BN(12), // price
2351
3308
  new BN(2).mul(BASE_PRECISION), // quantity
@@ -2356,8 +3313,6 @@ describe('DLOB Spot Tests', () => {
2356
3313
 
2357
3314
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
2358
3315
  marketIndex,
2359
- vBid,
2360
- vAsk,
2361
3316
  12, // auction over
2362
3317
  MarketType.SPOT,
2363
3318
  {
@@ -2375,23 +3330,19 @@ describe('DLOB Spot Tests', () => {
2375
3330
  expect(nodesToFillAfter.length).to.equal(2);
2376
3331
 
2377
3332
  // taker should fill completely with best maker
2378
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
2379
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
2380
- 3
2381
- );
3333
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
3334
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
2382
3335
 
2383
3336
  // taker should fill completely with second best maker
2384
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(4);
2385
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
2386
- 2
2387
- );
3337
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(4);
3338
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
2388
3339
  });
2389
3340
 
2390
3341
  it('Test two market orders to fill one limit order', () => {
2391
3342
  const vAsk = new BN(15);
2392
3343
  const vBid = new BN(8);
2393
3344
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2394
- const marketIndex = new BN(0);
3345
+ const marketIndex = 0;
2395
3346
 
2396
3347
  const slot = 12;
2397
3348
  const oracle = {
@@ -2407,7 +3358,7 @@ describe('DLOB Spot Tests', () => {
2407
3358
  Keypair.generate().publicKey,
2408
3359
  OrderType.LIMIT,
2409
3360
  MarketType.SPOT,
2410
- new BN(1), // orderId
3361
+ 1, // orderId
2411
3362
  marketIndex,
2412
3363
  new BN(14), // price
2413
3364
  BASE_PRECISION, // quantity
@@ -2420,7 +3371,7 @@ describe('DLOB Spot Tests', () => {
2420
3371
  Keypair.generate().publicKey,
2421
3372
  OrderType.LIMIT,
2422
3373
  MarketType.SPOT,
2423
- new BN(2), // orderId
3374
+ 2, // orderId
2424
3375
  marketIndex,
2425
3376
  new BN(13), // price
2426
3377
  BASE_PRECISION, // quantity
@@ -2433,7 +3384,7 @@ describe('DLOB Spot Tests', () => {
2433
3384
  Keypair.generate().publicKey,
2434
3385
  OrderType.LIMIT,
2435
3386
  MarketType.SPOT,
2436
- new BN(3), // orderId
3387
+ 3, // orderId
2437
3388
  marketIndex,
2438
3389
  new BN(8), // price <-- best price
2439
3390
  new BN(3).mul(BASE_PRECISION), // quantity
@@ -2445,8 +3396,6 @@ describe('DLOB Spot Tests', () => {
2445
3396
  // should have no crossing orders
2446
3397
  const nodesToFillBefore = dlob.findCrossingNodesToFill(
2447
3398
  marketIndex,
2448
- vBid,
2449
- vAsk,
2450
3399
  12, // auction over
2451
3400
  MarketType.SPOT,
2452
3401
  oracle
@@ -2459,7 +3408,7 @@ describe('DLOB Spot Tests', () => {
2459
3408
  Keypair.generate().publicKey,
2460
3409
  OrderType.MARKET,
2461
3410
  MarketType.SPOT,
2462
- new BN(4), // orderId
3411
+ 4, // orderId
2463
3412
  marketIndex,
2464
3413
  new BN(0), // price
2465
3414
  new BN(1).mul(BASE_PRECISION), // quantity
@@ -2472,7 +3421,7 @@ describe('DLOB Spot Tests', () => {
2472
3421
  Keypair.generate().publicKey,
2473
3422
  OrderType.MARKET,
2474
3423
  MarketType.SPOT,
2475
- new BN(5), // orderId
3424
+ 5, // orderId
2476
3425
  marketIndex,
2477
3426
  new BN(0), // price
2478
3427
  new BN(2).mul(BASE_PRECISION), // quantity
@@ -2483,62 +3432,19 @@ describe('DLOB Spot Tests', () => {
2483
3432
 
2484
3433
  const nodesToFillAfter = dlob.findCrossingNodesToFill(
2485
3434
  marketIndex,
2486
- vBid,
2487
- vAsk,
2488
3435
  slot, // auction over
2489
3436
  MarketType.SPOT,
2490
3437
  oracle
2491
3438
  );
2492
- const mktNodes = dlob.findMarketNodesToFill(
3439
+ const mktNodes = dlob.findExpiredMarketNodesToFill(
2493
3440
  marketIndex,
2494
3441
  slot,
2495
3442
  MarketType.SPOT
2496
3443
  );
2497
3444
  console.log(`market nodes: ${mktNodes.length}`);
2498
3445
 
2499
- const askNodes = dlob.getAsks(
2500
- marketIndex,
2501
- vAsk,
2502
- slot,
2503
- MarketType.SPOT,
2504
- oracle
2505
- );
2506
- let aa = 0;
2507
- for (const b of askNodes) {
2508
- console.log(
2509
- ` . ask: ${b.order?.orderId.toString()}: p1: ${b.order?.price.toString()} p2: ${b.getPrice(
2510
- oracle,
2511
- slot
2512
- )}, ${JSON.stringify(
2513
- b.order?.orderType
2514
- )} BAA: ${b.order?.baseAssetAmountFilled.toString()}/${b.order?.baseAssetAmount.toString()}`
2515
- );
2516
- aa++;
2517
- }
2518
- expect(aa).to.equal(3);
2519
-
2520
- const bidNodes = dlob.getBids(
2521
- marketIndex,
2522
- vBid,
2523
- slot,
2524
- MarketType.SPOT,
2525
- oracle
2526
- );
2527
- let bb = 0;
2528
- for (const b of bidNodes) {
2529
- console.log(
2530
- ` . bid: ${b.order?.orderId.toString()}: p1: ${b.order?.price.toString()} p2: ${b.getPrice(
2531
- oracle,
2532
- slot
2533
- )}, ${JSON.stringify(
2534
- b.order?.orderType
2535
- )} BAA: ${b.order?.baseAssetAmountFilled.toString()}/${b.order?.baseAssetAmount.toString()}`
2536
- );
2537
- bb++;
2538
- }
2539
- expect(bb).to.equal(2);
3446
+ printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
2540
3447
 
2541
- console.log(`bids nodes: ${bb}`);
2542
3448
  for (const n of nodesToFillAfter) {
2543
3449
  console.log(
2544
3450
  `cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmountFilled.toString()}/${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmountFilled.toString()}/${n.makerNode?.order?.baseAssetAmount.toString()}`
@@ -2547,23 +3453,19 @@ describe('DLOB Spot Tests', () => {
2547
3453
  expect(nodesToFillAfter.length).to.equal(2);
2548
3454
 
2549
3455
  // taker should fill completely with best maker
2550
- expect(nodesToFillAfter[0].node.order?.orderId.toNumber()).to.equal(4);
2551
- expect(nodesToFillAfter[0].makerNode?.order?.orderId.toNumber()).to.equal(
2552
- 3
2553
- );
3456
+ expect(nodesToFillAfter[0].node.order?.orderId).to.equal(4);
3457
+ expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(3);
2554
3458
 
2555
3459
  // taker should fill completely with second best maker
2556
- expect(nodesToFillAfter[1].node.order?.orderId.toNumber()).to.equal(5);
2557
- expect(nodesToFillAfter[1].makerNode?.order?.orderId.toNumber()).to.equal(
2558
- 3
2559
- );
3460
+ expect(nodesToFillAfter[1].node.order?.orderId).to.equal(5);
3461
+ expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(3);
2560
3462
  });
2561
3463
 
2562
3464
  it('Test trigger orders', () => {
2563
3465
  const vAsk = new BN(15);
2564
3466
  const vBid = new BN(8);
2565
3467
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2566
- const marketIndex = new BN(0);
3468
+ const marketIndex = 0;
2567
3469
 
2568
3470
  const slot = 20;
2569
3471
  const oracle = {
@@ -2582,7 +3484,7 @@ describe('DLOB Spot Tests', () => {
2582
3484
  Keypair.generate().publicKey,
2583
3485
  OrderType.TRIGGER_LIMIT,
2584
3486
  MarketType.SPOT,
2585
- new BN(1), //orderId
3487
+ 1, //orderId
2586
3488
  marketIndex, // marketIndex
2587
3489
  vBid, // price
2588
3490
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2598,7 +3500,7 @@ describe('DLOB Spot Tests', () => {
2598
3500
  Keypair.generate().publicKey,
2599
3501
  OrderType.TRIGGER_LIMIT,
2600
3502
  MarketType.SPOT,
2601
- new BN(2), //orderId
3503
+ 2, //orderId
2602
3504
  marketIndex, // marketIndex
2603
3505
  vBid, // price
2604
3506
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2614,7 +3516,7 @@ describe('DLOB Spot Tests', () => {
2614
3516
  Keypair.generate().publicKey,
2615
3517
  OrderType.TRIGGER_MARKET,
2616
3518
  MarketType.SPOT,
2617
- new BN(3), //orderId
3519
+ 3, //orderId
2618
3520
  marketIndex, // marketIndex
2619
3521
  vAsk, // price
2620
3522
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2630,7 +3532,7 @@ describe('DLOB Spot Tests', () => {
2630
3532
  Keypair.generate().publicKey,
2631
3533
  OrderType.TRIGGER_MARKET,
2632
3534
  MarketType.SPOT,
2633
- new BN(4), //orderId
3535
+ 4, //orderId
2634
3536
  marketIndex, // marketIndex
2635
3537
  vBid, // price
2636
3538
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2646,7 +3548,7 @@ describe('DLOB Spot Tests', () => {
2646
3548
  Keypair.generate().publicKey,
2647
3549
  OrderType.TRIGGER_LIMIT,
2648
3550
  MarketType.SPOT,
2649
- new BN(5), //orderId
3551
+ 5, //orderId
2650
3552
  marketIndex, // marketIndex
2651
3553
  vBid, // price
2652
3554
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2662,7 +3564,7 @@ describe('DLOB Spot Tests', () => {
2662
3564
  Keypair.generate().publicKey,
2663
3565
  OrderType.TRIGGER_LIMIT,
2664
3566
  MarketType.SPOT,
2665
- new BN(6), //orderId
3567
+ 6, //orderId
2666
3568
  marketIndex, // marketIndex
2667
3569
  vBid, // price
2668
3570
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2678,7 +3580,7 @@ describe('DLOB Spot Tests', () => {
2678
3580
  Keypair.generate().publicKey,
2679
3581
  OrderType.TRIGGER_MARKET,
2680
3582
  MarketType.SPOT,
2681
- new BN(7), //orderId
3583
+ 7, //orderId
2682
3584
  marketIndex, // marketIndex
2683
3585
  vBid, // price
2684
3586
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2694,7 +3596,7 @@ describe('DLOB Spot Tests', () => {
2694
3596
  Keypair.generate().publicKey,
2695
3597
  OrderType.TRIGGER_MARKET,
2696
3598
  MarketType.SPOT,
2697
- new BN(8), //orderId
3599
+ 8, //orderId
2698
3600
  marketIndex, // marketIndex
2699
3601
  vBid, // price
2700
3602
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2711,7 +3613,7 @@ describe('DLOB Spot Tests', () => {
2711
3613
  Keypair.generate().publicKey,
2712
3614
  OrderType.TRIGGER_MARKET,
2713
3615
  MarketType.SPOT,
2714
- new BN(9), //orderId
3616
+ 9, //orderId
2715
3617
  marketIndex, // marketIndex
2716
3618
  vBid, // price
2717
3619
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2727,7 +3629,7 @@ describe('DLOB Spot Tests', () => {
2727
3629
  Keypair.generate().publicKey,
2728
3630
  OrderType.TRIGGER_MARKET,
2729
3631
  MarketType.SPOT,
2730
- new BN(10), //orderId
3632
+ 10, //orderId
2731
3633
  marketIndex, // marketIndex
2732
3634
  vBid, // price
2733
3635
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2743,7 +3645,7 @@ describe('DLOB Spot Tests', () => {
2743
3645
  Keypair.generate().publicKey,
2744
3646
  OrderType.TRIGGER_MARKET,
2745
3647
  MarketType.SPOT,
2746
- new BN(11), //orderId
3648
+ 11, //orderId
2747
3649
  marketIndex, // marketIndex
2748
3650
  vBid, // price
2749
3651
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2759,7 +3661,7 @@ describe('DLOB Spot Tests', () => {
2759
3661
  Keypair.generate().publicKey,
2760
3662
  OrderType.TRIGGER_MARKET,
2761
3663
  MarketType.SPOT,
2762
- new BN(12), //orderId
3664
+ 12, //orderId
2763
3665
  marketIndex, // marketIndex
2764
3666
  vBid, // price
2765
3667
  BASE_PRECISION, // baseAssetAmount: BN,
@@ -2778,8 +3680,8 @@ describe('DLOB Spot Tests', () => {
2778
3680
  );
2779
3681
  console.log(`nodesToTriggeR: ${nodesToTrigger.length}`);
2780
3682
  for (const [idx, n] of nodesToTrigger.entries()) {
2781
- expect(n.node.order?.orderId.toNumber()).to.equal(orderIdsToTrigger[idx]);
2782
- console.log(`nodeToTrigger: ${n.node.order?.orderId.toString()}`);
3683
+ expect(n.node.order?.orderId).to.equal(orderIdsToTrigger[idx]);
3684
+ console.log(`nodeToTrigger: ${n.node.order?.orderId}`);
2783
3685
  }
2784
3686
  });
2785
3687
 
@@ -2787,7 +3689,7 @@ describe('DLOB Spot Tests', () => {
2787
3689
  const vAsk = new BN(15);
2788
3690
  const vBid = new BN(8);
2789
3691
  const dlob = new DLOB(mockPerpMarkets, mockSpotMarkets, false);
2790
- const marketIndex = new BN(0);
3692
+ const marketIndex = 0;
2791
3693
 
2792
3694
  const slot = 20;
2793
3695
  const timeInForce = 30;
@@ -2798,7 +3700,7 @@ describe('DLOB Spot Tests', () => {
2798
3700
  Keypair.generate().publicKey,
2799
3701
  OrderType.MARKET,
2800
3702
  MarketType.SPOT,
2801
- new BN(255), // orderId
3703
+ 255, // orderId
2802
3704
  marketIndex,
2803
3705
  new BN(2), // price, very low, don't cross vamm
2804
3706
  BASE_PRECISION, // quantity
@@ -2813,7 +3715,7 @@ describe('DLOB Spot Tests', () => {
2813
3715
  Keypair.generate().publicKey,
2814
3716
  OrderType.MARKET,
2815
3717
  MarketType.SPOT,
2816
- new BN(2), // orderId
3718
+ 2, // orderId
2817
3719
  marketIndex,
2818
3720
  new BN(30), // price, very high, don't cross vamm
2819
3721
  BASE_PRECISION, // quantity
@@ -2842,7 +3744,7 @@ describe('DLOB Spot Tests', () => {
2842
3744
  expect(nodesToFillBefore.length).to.equal(0);
2843
3745
 
2844
3746
  // should get order to fill after timeInForce
2845
- const slot1 = slot0 + timeInForce; // overshoots expiry
3747
+ const slot1 = slot0 + timeInForce * 2; // overshoots expiry
2846
3748
  const nodesToFillAfter = dlob.findNodesToFill(
2847
3749
  marketIndex,
2848
3750
  vBid,