@drift-labs/sdk 2.49.0-beta.2 → 2.49.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.49.0-beta.2
1
+ 2.49.0-beta.4
@@ -68,11 +68,15 @@ export declare class DLOB {
68
68
  updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
69
69
  getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
70
70
  findNodesToFill(marketIndex: number, fallbackBid: BN | undefined, fallbackAsk: BN | undefined, slot: number, ts: number, marketType: MarketType, oraclePriceData: OraclePriceData, stateAccount: StateAccount, marketAccount: PerpMarketAccount | SpotMarketAccount): NodeToFill[];
71
+ getMakerRebate(marketType: MarketType, stateAccount: StateAccount, marketAccount: PerpMarketAccount | SpotMarketAccount): {
72
+ makerRebateNumerator: number;
73
+ makerRebateDenominator: number;
74
+ };
71
75
  mergeNodesToFill(restingLimitOrderNodesToFill: NodeToFill[], takingOrderNodesToFill: NodeToFill[]): NodeToFill[];
72
- findRestingLimitOrderNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
76
+ findRestingLimitOrderNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, makerRebateNumerator: number, makerRebateDenominator: number, fallbackAsk: BN | undefined, fallbackBid: BN | undefined): NodeToFill[];
73
77
  findTakingNodesToFill(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, isAmmPaused: boolean, minAuctionDuration: number, fallbackAsk: BN | undefined, fallbackBid?: BN | undefined): NodeToFill[];
74
78
  findTakingNodesCrossingMakerNodes(marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData, takerNodeGenerator: Generator<DLOBNode>, makerNodeGeneratorFn: (marketIndex: number, slot: number, marketType: MarketType, oraclePriceData: OraclePriceData) => Generator<DLOBNode>, doesCross: (takerPrice: BN | undefined, makerPrice: BN) => boolean): NodeToFill[];
75
- findNodesCrossingFallbackLiquidity(marketType: MarketType, slot: number, oraclePriceData: OraclePriceData, nodeGenerator: Generator<DLOBNode>, fallbackPrice: BN, doesCross: (nodePrice: BN | undefined, fallbackPrice: BN) => boolean, minAuctionDuration: number): NodeToFill[];
79
+ findNodesCrossingFallbackLiquidity(marketType: MarketType, slot: number, oraclePriceData: OraclePriceData, nodeGenerator: Generator<DLOBNode>, doesCross: (nodePrice: BN | undefined) => boolean, minAuctionDuration: number): NodeToFill[];
76
80
  findExpiredNodesToFill(marketIndex: number, ts: number, marketType: MarketType): NodeToFill[];
77
81
  findJitAuctionNodesToFill(marketIndex: number, slot: number, oraclePriceData: OraclePriceData, marketType: MarketType): NodeToFill[];
78
82
  getTakingBids(marketIndex: number, marketType: MarketType, slot: number, oraclePriceData: OraclePriceData): Generator<DLOBNode>;
package/lib/dlob/DLOB.js CHANGED
@@ -304,7 +304,8 @@ class DLOB {
304
304
  const minAuctionDuration = (0, __1.isVariant)(marketType, 'perp')
305
305
  ? stateAccount.minPerpAuctionDuration
306
306
  : 0;
307
- const restingLimitOrderNodesToFill = this.findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid);
307
+ const { makerRebateNumerator, makerRebateDenominator } = this.getMakerRebate(marketType, stateAccount, marketAccount);
308
+ const restingLimitOrderNodesToFill = this.findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, makerRebateNumerator, makerRebateDenominator, fallbackAsk, fallbackBid);
308
309
  const takingOrderNodesToFill = this.findTakingNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid);
309
310
  // get expired market nodes
310
311
  const expiredNodesToFill = this.findExpiredNodesToFill(marketIndex, ts, marketType);
@@ -314,6 +315,28 @@ class DLOB {
314
315
  }
315
316
  return this.mergeNodesToFill(restingLimitOrderNodesToFill, takingOrderNodesToFill).concat(expiredNodesToFill);
316
317
  }
318
+ getMakerRebate(marketType, stateAccount, marketAccount) {
319
+ let makerRebateNumerator;
320
+ let makerRebateDenominator;
321
+ if ((0, __1.isVariant)(marketType, 'perp')) {
322
+ makerRebateNumerator =
323
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateNumerator;
324
+ makerRebateDenominator =
325
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateDenominator;
326
+ }
327
+ else {
328
+ makerRebateNumerator =
329
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateNumerator;
330
+ makerRebateDenominator =
331
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateDenominator;
332
+ }
333
+ // @ts-ignore
334
+ const feeAdjustment = marketAccount.feeAdjustment || 0;
335
+ if (feeAdjustment !== 0) {
336
+ makerRebateNumerator += (makerRebateNumerator * feeAdjustment) / 100;
337
+ }
338
+ return { makerRebateNumerator, makerRebateDenominator };
339
+ }
317
340
  mergeNodesToFill(restingLimitOrderNodesToFill, takingOrderNodesToFill) {
318
341
  const mergedNodesToFill = new Map();
319
342
  const mergeNodesToFillHelper = (nodesToFillArray) => {
@@ -336,7 +359,7 @@ class DLOB {
336
359
  mergeNodesToFillHelper(takingOrderNodesToFill);
337
360
  return Array.from(mergedNodesToFill.values());
338
361
  }
339
- findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, fallbackAsk, fallbackBid) {
362
+ findRestingLimitOrderNodesToFill(marketIndex, slot, marketType, oraclePriceData, isAmmPaused, minAuctionDuration, makerRebateNumerator, makerRebateDenominator, fallbackAsk, fallbackBid) {
340
363
  const nodesToFill = new Array();
341
364
  const crossingNodes = this.findCrossingRestingLimitOrders(marketIndex, slot, marketType, oraclePriceData);
342
365
  for (const crossingNode of crossingNodes) {
@@ -344,8 +367,9 @@ class DLOB {
344
367
  }
345
368
  if (fallbackBid && !isAmmPaused) {
346
369
  const askGenerator = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData);
347
- const asksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, askGenerator, fallbackBid, (askPrice, fallbackPrice) => {
348
- return askPrice.lte(fallbackPrice);
370
+ const fallbackBidWithBuffer = fallbackBid.sub(fallbackBid.muln(makerRebateNumerator).divn(makerRebateDenominator));
371
+ const asksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, askGenerator, (askPrice) => {
372
+ return askPrice.lte(fallbackBidWithBuffer);
349
373
  }, minAuctionDuration);
350
374
  for (const askCrossingFallback of asksCrossingFallback) {
351
375
  nodesToFill.push(askCrossingFallback);
@@ -353,8 +377,9 @@ class DLOB {
353
377
  }
354
378
  if (fallbackAsk && !isAmmPaused) {
355
379
  const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
356
- const bidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, bidGenerator, fallbackAsk, (bidPrice, fallbackPrice) => {
357
- return bidPrice.gte(fallbackPrice);
380
+ const fallbackAskWithBuffer = fallbackAsk.add(fallbackAsk.muln(makerRebateNumerator).divn(makerRebateDenominator));
381
+ const bidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, bidGenerator, (bidPrice) => {
382
+ return bidPrice.gte(fallbackAskWithBuffer);
358
383
  }, minAuctionDuration);
359
384
  for (const bidCrossingFallback of bidsCrossingFallback) {
360
385
  nodesToFill.push(bidCrossingFallback);
@@ -381,8 +406,8 @@ class DLOB {
381
406
  }
382
407
  if (fallbackBid && !isAmmPaused) {
383
408
  takingOrderGenerator = this.getTakingAsks(marketIndex, marketType, slot, oraclePriceData);
384
- const takingAsksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, fallbackBid, (takerPrice, fallbackPrice) => {
385
- return takerPrice === undefined || takerPrice.lte(fallbackPrice);
409
+ const takingAsksCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, (takerPrice) => {
410
+ return takerPrice === undefined || takerPrice.lte(fallbackBid);
386
411
  }, minAuctionDuration);
387
412
  for (const takingAskCrossingFallback of takingAsksCrossingFallback) {
388
413
  nodesToFill.push(takingAskCrossingFallback);
@@ -405,8 +430,8 @@ class DLOB {
405
430
  }
406
431
  if (fallbackAsk && !isAmmPaused) {
407
432
  takingOrderGenerator = this.getTakingBids(marketIndex, marketType, slot, oraclePriceData);
408
- const takingBidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, fallbackAsk, (takerPrice, fallbackPrice) => {
409
- return takerPrice === undefined || takerPrice.gte(fallbackPrice);
433
+ const takingBidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, takingOrderGenerator, (takerPrice) => {
434
+ return takerPrice === undefined || takerPrice.gte(fallbackAsk);
410
435
  }, minAuctionDuration);
411
436
  for (const marketBidCrossingFallback of takingBidsCrossingFallback) {
412
437
  nodesToFill.push(marketBidCrossingFallback);
@@ -456,7 +481,7 @@ class DLOB {
456
481
  }
457
482
  return nodesToFill;
458
483
  }
459
- findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, nodeGenerator, fallbackPrice, doesCross, minAuctionDuration) {
484
+ findNodesCrossingFallbackLiquidity(marketType, slot, oraclePriceData, nodeGenerator, doesCross, minAuctionDuration) {
460
485
  var _a;
461
486
  const nodesToFill = new Array();
462
487
  let nextNode = nodeGenerator.next();
@@ -468,7 +493,7 @@ class DLOB {
468
493
  }
469
494
  const nodePrice = (0, __1.getLimitPrice)(node.order, oraclePriceData, slot);
470
495
  // order crosses if there is no limit price or it crosses fallback price
471
- const crosses = doesCross(nodePrice, fallbackPrice);
496
+ const crosses = doesCross(nodePrice);
472
497
  // fallback is available if auction is complete or it's a spot order
473
498
  const fallbackAvailable = (0, __1.isVariant)(marketType, 'spot') ||
474
499
  (0, __1.isFallbackAvailableLiquiditySource)(node.order, minAuctionDuration, slot);
@@ -23,7 +23,7 @@ class EventSubscriber {
23
23
  this.txEventCache = new txEventCache_1.TxEventCache(this.options.maxTx);
24
24
  this.eventListMap = new Map();
25
25
  for (const eventType of this.options.eventTypes) {
26
- this.eventListMap.set(eventType, new eventList_1.EventList(eventType, this.options.maxEventsPerType, (0, sort_1.getSortFn)(this.options.orderBy, this.options.orderDir, eventType), this.options.orderDir));
26
+ this.eventListMap.set(eventType, new eventList_1.EventList(eventType, this.options.maxEventsPerType, (0, sort_1.getSortFn)(this.options.orderBy, this.options.orderDir), this.options.orderDir));
27
27
  }
28
28
  this.eventEmitter = new events_1.EventEmitter();
29
29
  if (this.options.logProviderConfig.type === 'websocket') {
@@ -1,2 +1,2 @@
1
- import { EventSubscriptionOrderBy, EventSubscriptionOrderDirection, EventType, SortFn } from './types';
2
- export declare function getSortFn(orderBy: EventSubscriptionOrderBy, orderDir: EventSubscriptionOrderDirection, eventType: EventType): SortFn;
1
+ import { EventSubscriptionOrderBy, EventSubscriptionOrderDirection, SortFn } from './types';
2
+ export declare function getSortFn(orderBy: EventSubscriptionOrderBy, orderDir: EventSubscriptionOrderDirection): SortFn;
@@ -1,41 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getSortFn = void 0;
4
- const index_1 = require("../index");
5
4
  function clientSortAscFn() {
6
5
  return 'less than';
7
6
  }
8
7
  function clientSortDescFn() {
9
8
  return 'greater than';
10
9
  }
11
- function defaultBlockchainSortFn(currentEvent, newEvent) {
12
- return currentEvent.slot <= newEvent.slot ? 'less than' : 'greater than';
13
- }
14
- function orderActionRecordSortFn(currentEvent, newEvent) {
15
- var _a, _b;
16
- const currentEventMarketIndex = currentEvent.marketIndex;
17
- const newEventMarketIndex = newEvent.marketIndex;
18
- if (currentEventMarketIndex !== newEventMarketIndex) {
19
- return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
20
- }
21
- if (((_a = currentEvent.fillRecordId) === null || _a === void 0 ? void 0 : _a.gt(index_1.ZERO)) && ((_b = newEvent.fillRecordId) === null || _b === void 0 ? void 0 : _b.gt(index_1.ZERO))) {
22
- return currentEvent.fillRecordId.lte(newEvent.fillRecordId)
10
+ function blockchainSortFn(currentEvent, newEvent) {
11
+ if (currentEvent.slot == newEvent.slot) {
12
+ return currentEvent.txSigIndex < newEvent.txSigIndex
23
13
  ? 'less than'
24
14
  : 'greater than';
25
15
  }
26
- else {
27
- return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
28
- }
16
+ return currentEvent.slot < newEvent.slot ? 'less than' : 'greater than';
29
17
  }
30
- function getSortFn(orderBy, orderDir, eventType) {
18
+ function getSortFn(orderBy, orderDir) {
31
19
  if (orderBy === 'client') {
32
20
  return orderDir === 'asc' ? clientSortAscFn : clientSortDescFn;
33
21
  }
34
- switch (eventType) {
35
- case 'OrderActionRecord':
36
- return orderActionRecordSortFn;
37
- default:
38
- return defaultBlockchainSortFn;
39
- }
22
+ return blockchainSortFn;
40
23
  }
41
24
  exports.getSortFn = getSortFn;
package/lib/types.d.ts CHANGED
@@ -1025,8 +1025,6 @@ export interface IVersionedWallet {
1025
1025
  }
1026
1026
  export type FeeStructure = {
1027
1027
  feeTiers: FeeTier[];
1028
- makerRebateNumerator: BN;
1029
- makerRebateDenominator: BN;
1030
1028
  fillerRewardStructure: OrderFillerRewardStructure;
1031
1029
  flatFillerFee: BN;
1032
1030
  referrerRewardEpochUpperBound: BN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.49.0-beta.2",
3
+ "version": "2.49.0-beta.4",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/dlob/DLOB.ts CHANGED
@@ -504,6 +504,9 @@ export class DLOB {
504
504
  ? stateAccount.minPerpAuctionDuration
505
505
  : 0;
506
506
 
507
+ const { makerRebateNumerator, makerRebateDenominator } =
508
+ this.getMakerRebate(marketType, stateAccount, marketAccount);
509
+
507
510
  const restingLimitOrderNodesToFill: Array<NodeToFill> =
508
511
  this.findRestingLimitOrderNodesToFill(
509
512
  marketIndex,
@@ -512,6 +515,8 @@ export class DLOB {
512
515
  oraclePriceData,
513
516
  isAmmPaused,
514
517
  minAuctionDuration,
518
+ makerRebateNumerator,
519
+ makerRebateDenominator,
515
520
  fallbackAsk,
516
521
  fallbackBid
517
522
  );
@@ -549,6 +554,34 @@ export class DLOB {
549
554
  ).concat(expiredNodesToFill);
550
555
  }
551
556
 
557
+ getMakerRebate(
558
+ marketType: MarketType,
559
+ stateAccount: StateAccount,
560
+ marketAccount: PerpMarketAccount | SpotMarketAccount
561
+ ): { makerRebateNumerator: number; makerRebateDenominator: number } {
562
+ let makerRebateNumerator: number;
563
+ let makerRebateDenominator: number;
564
+ if (isVariant(marketType, 'perp')) {
565
+ makerRebateNumerator =
566
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateNumerator;
567
+ makerRebateDenominator =
568
+ stateAccount.perpFeeStructure.feeTiers[0].makerRebateDenominator;
569
+ } else {
570
+ makerRebateNumerator =
571
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateNumerator;
572
+ makerRebateDenominator =
573
+ stateAccount.spotFeeStructure.feeTiers[0].makerRebateDenominator;
574
+ }
575
+
576
+ // @ts-ignore
577
+ const feeAdjustment = marketAccount.feeAdjustment || 0;
578
+ if (feeAdjustment !== 0) {
579
+ makerRebateNumerator += (makerRebateNumerator * feeAdjustment) / 100;
580
+ }
581
+
582
+ return { makerRebateNumerator, makerRebateDenominator };
583
+ }
584
+
552
585
  mergeNodesToFill(
553
586
  restingLimitOrderNodesToFill: NodeToFill[],
554
587
  takingOrderNodesToFill: NodeToFill[]
@@ -590,6 +623,8 @@ export class DLOB {
590
623
  oraclePriceData: OraclePriceData,
591
624
  isAmmPaused: boolean,
592
625
  minAuctionDuration: number,
626
+ makerRebateNumerator: number,
627
+ makerRebateDenominator: number,
593
628
  fallbackAsk: BN | undefined,
594
629
  fallbackBid: BN | undefined
595
630
  ): NodeToFill[] {
@@ -613,14 +648,18 @@ export class DLOB {
613
648
  marketType,
614
649
  oraclePriceData
615
650
  );
651
+
652
+ const fallbackBidWithBuffer = fallbackBid.sub(
653
+ fallbackBid.muln(makerRebateNumerator).divn(makerRebateDenominator)
654
+ );
655
+
616
656
  const asksCrossingFallback = this.findNodesCrossingFallbackLiquidity(
617
657
  marketType,
618
658
  slot,
619
659
  oraclePriceData,
620
660
  askGenerator,
621
- fallbackBid,
622
- (askPrice, fallbackPrice) => {
623
- return askPrice.lte(fallbackPrice);
661
+ (askPrice) => {
662
+ return askPrice.lte(fallbackBidWithBuffer);
624
663
  },
625
664
  minAuctionDuration
626
665
  );
@@ -637,14 +676,18 @@ export class DLOB {
637
676
  marketType,
638
677
  oraclePriceData
639
678
  );
679
+
680
+ const fallbackAskWithBuffer = fallbackAsk.add(
681
+ fallbackAsk.muln(makerRebateNumerator).divn(makerRebateDenominator)
682
+ );
683
+
640
684
  const bidsCrossingFallback = this.findNodesCrossingFallbackLiquidity(
641
685
  marketType,
642
686
  slot,
643
687
  oraclePriceData,
644
688
  bidGenerator,
645
- fallbackAsk,
646
- (bidPrice, fallbackPrice) => {
647
- return bidPrice.gte(fallbackPrice);
689
+ (bidPrice) => {
690
+ return bidPrice.gte(fallbackAskWithBuffer);
648
691
  },
649
692
  minAuctionDuration
650
693
  );
@@ -713,9 +756,8 @@ export class DLOB {
713
756
  slot,
714
757
  oraclePriceData,
715
758
  takingOrderGenerator,
716
- fallbackBid,
717
- (takerPrice, fallbackPrice) => {
718
- return takerPrice === undefined || takerPrice.lte(fallbackPrice);
759
+ (takerPrice) => {
760
+ return takerPrice === undefined || takerPrice.lte(fallbackBid);
719
761
  },
720
762
  minAuctionDuration
721
763
  );
@@ -771,9 +813,8 @@ export class DLOB {
771
813
  slot,
772
814
  oraclePriceData,
773
815
  takingOrderGenerator,
774
- fallbackAsk,
775
- (takerPrice, fallbackPrice) => {
776
- return takerPrice === undefined || takerPrice.gte(fallbackPrice);
816
+ (takerPrice) => {
817
+ return takerPrice === undefined || takerPrice.gte(fallbackAsk);
777
818
  },
778
819
  minAuctionDuration
779
820
  );
@@ -875,8 +916,7 @@ export class DLOB {
875
916
  slot: number,
876
917
  oraclePriceData: OraclePriceData,
877
918
  nodeGenerator: Generator<DLOBNode>,
878
- fallbackPrice: BN,
879
- doesCross: (nodePrice: BN | undefined, fallbackPrice: BN) => boolean,
919
+ doesCross: (nodePrice: BN | undefined) => boolean,
880
920
  minAuctionDuration: number
881
921
  ): NodeToFill[] {
882
922
  const nodesToFill = new Array<NodeToFill>();
@@ -893,7 +933,7 @@ export class DLOB {
893
933
  const nodePrice = getLimitPrice(node.order, oraclePriceData, slot);
894
934
 
895
935
  // order crosses if there is no limit price or it crosses fallback price
896
- const crosses = doesCross(nodePrice, fallbackPrice);
936
+ const crosses = doesCross(nodePrice);
897
937
 
898
938
  // fallback is available if auction is complete or it's a spot order
899
939
  const fallbackAvailable =
@@ -47,7 +47,7 @@ export class EventSubscriber {
47
47
  new EventList(
48
48
  eventType,
49
49
  this.options.maxEventsPerType,
50
- getSortFn(this.options.orderBy, this.options.orderDir, eventType),
50
+ getSortFn(this.options.orderBy, this.options.orderDir),
51
51
  this.options.orderDir
52
52
  )
53
53
  );
@@ -4,10 +4,7 @@ import {
4
4
  EventSubscriptionOrderDirection,
5
5
  EventType,
6
6
  SortFn,
7
- Event,
8
7
  } from './types';
9
- import { OrderActionRecord } from '../types';
10
- import { ZERO } from '../index';
11
8
 
12
9
  function clientSortAscFn(): 'less than' {
13
10
  return 'less than';
@@ -17,45 +14,26 @@ function clientSortDescFn(): 'greater than' {
17
14
  return 'greater than';
18
15
  }
19
16
 
20
- function defaultBlockchainSortFn(
17
+ function blockchainSortFn(
21
18
  currentEvent: EventMap[EventType],
22
19
  newEvent: EventMap[EventType]
23
20
  ): 'less than' | 'greater than' {
24
- return currentEvent.slot <= newEvent.slot ? 'less than' : 'greater than';
25
- }
26
-
27
- function orderActionRecordSortFn(
28
- currentEvent: Event<OrderActionRecord>,
29
- newEvent: Event<OrderActionRecord>
30
- ): 'less than' | 'greater than' {
31
- const currentEventMarketIndex = currentEvent.marketIndex;
32
- const newEventMarketIndex = newEvent.marketIndex;
33
- if (currentEventMarketIndex !== newEventMarketIndex) {
34
- return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
35
- }
36
-
37
- if (currentEvent.fillRecordId?.gt(ZERO) && newEvent.fillRecordId?.gt(ZERO)) {
38
- return currentEvent.fillRecordId.lte(newEvent.fillRecordId)
21
+ if (currentEvent.slot == newEvent.slot) {
22
+ return currentEvent.txSigIndex < newEvent.txSigIndex
39
23
  ? 'less than'
40
24
  : 'greater than';
41
- } else {
42
- return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
43
25
  }
26
+
27
+ return currentEvent.slot < newEvent.slot ? 'less than' : 'greater than';
44
28
  }
45
29
 
46
30
  export function getSortFn(
47
31
  orderBy: EventSubscriptionOrderBy,
48
- orderDir: EventSubscriptionOrderDirection,
49
- eventType: EventType
32
+ orderDir: EventSubscriptionOrderDirection
50
33
  ): SortFn {
51
34
  if (orderBy === 'client') {
52
35
  return orderDir === 'asc' ? clientSortAscFn : clientSortDescFn;
53
36
  }
54
37
 
55
- switch (eventType) {
56
- case 'OrderActionRecord':
57
- return orderActionRecordSortFn;
58
- default:
59
- return defaultBlockchainSortFn;
60
- }
38
+ return blockchainSortFn;
61
39
  }
package/src/types.ts CHANGED
@@ -1000,8 +1000,6 @@ export interface IVersionedWallet {
1000
1000
 
1001
1001
  export type FeeStructure = {
1002
1002
  feeTiers: FeeTier[];
1003
- makerRebateNumerator: BN;
1004
- makerRebateDenominator: BN;
1005
1003
  fillerRewardStructure: OrderFillerRewardStructure;
1006
1004
  flatFillerFee: BN;
1007
1005
  referrerRewardEpochUpperBound: BN;
@@ -539,15 +539,13 @@ export const mockStateAccount: StateAccount = {
539
539
  feeNumerator: 0,
540
540
  feeDenominator: 0,
541
541
  makerRebateNumerator: 0,
542
- makerRebateDenominator: 0,
542
+ makerRebateDenominator: 1,
543
543
  referrerRewardNumerator: 0,
544
544
  referrerRewardDenominator: 0,
545
545
  refereeFeeNumerator: 0,
546
546
  refereeFeeDenominator: 0,
547
547
  },
548
548
  ],
549
- makerRebateNumerator: new BN(0),
550
- makerRebateDenominator: new BN(0),
551
549
  fillerRewardStructure: {
552
550
  rewardNumerator: new BN(0),
553
551
  rewardDenominator: new BN(0),
@@ -565,15 +563,13 @@ export const mockStateAccount: StateAccount = {
565
563
  feeNumerator: 0,
566
564
  feeDenominator: 0,
567
565
  makerRebateNumerator: 0,
568
- makerRebateDenominator: 0,
566
+ makerRebateDenominator: 1,
569
567
  referrerRewardNumerator: 0,
570
568
  referrerRewardDenominator: 0,
571
569
  refereeFeeNumerator: 0,
572
570
  refereeFeeDenominator: 0,
573
571
  },
574
572
  ],
575
- makerRebateNumerator: new BN(0),
576
- makerRebateDenominator: new BN(0),
577
573
  fillerRewardStructure: {
578
574
  rewardNumerator: new BN(0),
579
575
  rewardDenominator: new BN(0),
@@ -1914,6 +1914,8 @@ describe('DLOB Perp Tests', () => {
1914
1914
  },
1915
1915
  false,
1916
1916
  10,
1917
+ 0,
1918
+ 1,
1917
1919
  undefined,
1918
1920
  undefined
1919
1921
  );
@@ -2059,6 +2061,8 @@ describe('DLOB Perp Tests', () => {
2059
2061
  },
2060
2062
  false,
2061
2063
  10,
2064
+ 0,
2065
+ 1,
2062
2066
  undefined,
2063
2067
  undefined
2064
2068
  );
@@ -2267,6 +2271,190 @@ describe('DLOB Perp Tests', () => {
2267
2271
  expect(nodesToFillAfter[1].makerNodes[0]?.order?.orderId).to.equal(3);
2268
2272
  });
2269
2273
 
2274
+ it('Test post only bid fills against fallback', async () => {
2275
+ const vAsk = new BN(150);
2276
+ const vBid = new BN(100);
2277
+
2278
+ const user0 = Keypair.generate();
2279
+
2280
+ const dlob = new DLOB();
2281
+ const marketIndex = 0;
2282
+
2283
+ const makerRebateNumerator = 1;
2284
+ const makerRebateDenominator = 10;
2285
+
2286
+ // post only bid same as ask
2287
+ insertOrderToDLOB(
2288
+ dlob,
2289
+ user0.publicKey,
2290
+ OrderType.LIMIT,
2291
+ MarketType.PERP,
2292
+ 1, // orderId
2293
+ marketIndex,
2294
+ vAsk, // same price as vAsk
2295
+ BASE_PRECISION, // quantity
2296
+ PositionDirection.LONG,
2297
+ vBid,
2298
+ vAsk,
2299
+ undefined,
2300
+ undefined,
2301
+ undefined,
2302
+ true
2303
+ );
2304
+
2305
+ // should have no crossing orders
2306
+ const nodesToFillBefore = dlob.findRestingLimitOrderNodesToFill(
2307
+ marketIndex,
2308
+ 12, // auction over
2309
+ MarketType.PERP,
2310
+ {
2311
+ price: vBid.add(vAsk).div(new BN(2)),
2312
+ slot: new BN(12),
2313
+ confidence: new BN(1),
2314
+ hasSufficientNumberOfDataPoints: true,
2315
+ },
2316
+ false,
2317
+ 10,
2318
+ makerRebateNumerator,
2319
+ makerRebateDenominator,
2320
+ vAsk,
2321
+ vBid
2322
+ );
2323
+ expect(nodesToFillBefore.length).to.equal(0);
2324
+
2325
+ // post only bid crosses ask
2326
+ const price = vAsk.add(vAsk.muln(makerRebateNumerator).divn(makerRebateDenominator));
2327
+ insertOrderToDLOB(
2328
+ dlob,
2329
+ user0.publicKey,
2330
+ OrderType.LIMIT,
2331
+ MarketType.PERP,
2332
+ 2, // orderId
2333
+ marketIndex,
2334
+ price, // crosses vask
2335
+ BASE_PRECISION, // quantity
2336
+ PositionDirection.LONG,
2337
+ vBid,
2338
+ vAsk,
2339
+ undefined,
2340
+ undefined,
2341
+ undefined,
2342
+ true
2343
+ );
2344
+
2345
+ // should have no crossing orders
2346
+ const nodesToFillAfter = dlob.findRestingLimitOrderNodesToFill(
2347
+ marketIndex,
2348
+ 12, // auction over
2349
+ MarketType.PERP,
2350
+ {
2351
+ price: vBid.add(vAsk).div(new BN(2)),
2352
+ slot: new BN(12),
2353
+ confidence: new BN(1),
2354
+ hasSufficientNumberOfDataPoints: true,
2355
+ },
2356
+ false,
2357
+ 10,
2358
+ makerRebateNumerator,
2359
+ makerRebateDenominator,
2360
+ vAsk,
2361
+ vBid
2362
+ );
2363
+ expect(nodesToFillAfter.length).to.equal(1);
2364
+ });
2365
+
2366
+ it('Test post only ask fills against fallback', async () => {
2367
+ const vAsk = new BN(150);
2368
+ const vBid = new BN(100);
2369
+
2370
+ const user0 = Keypair.generate();
2371
+
2372
+ const dlob = new DLOB();
2373
+ const marketIndex = 0;
2374
+
2375
+ const makerRebateNumerator = 1;
2376
+ const makerRebateDenominator = 10;
2377
+
2378
+ // post only bid same as ask
2379
+ insertOrderToDLOB(
2380
+ dlob,
2381
+ user0.publicKey,
2382
+ OrderType.LIMIT,
2383
+ MarketType.PERP,
2384
+ 1, // orderId
2385
+ marketIndex,
2386
+ vBid, // same price as vAsk
2387
+ BASE_PRECISION, // quantity
2388
+ PositionDirection.SHORT,
2389
+ vBid,
2390
+ vAsk,
2391
+ undefined,
2392
+ undefined,
2393
+ undefined,
2394
+ true
2395
+ );
2396
+
2397
+ // should have no crossing orders
2398
+ const nodesToFillBefore = dlob.findRestingLimitOrderNodesToFill(
2399
+ marketIndex,
2400
+ 12, // auction over
2401
+ MarketType.PERP,
2402
+ {
2403
+ price: vBid.add(vAsk).div(new BN(2)),
2404
+ slot: new BN(12),
2405
+ confidence: new BN(1),
2406
+ hasSufficientNumberOfDataPoints: true,
2407
+ },
2408
+ false,
2409
+ 10,
2410
+ makerRebateNumerator,
2411
+ makerRebateDenominator,
2412
+ vAsk,
2413
+ vBid
2414
+ );
2415
+ expect(nodesToFillBefore.length).to.equal(0);
2416
+
2417
+ // post only bid crosses ask
2418
+ const price = vBid.sub(vAsk.muln(makerRebateNumerator).divn(makerRebateDenominator));
2419
+ insertOrderToDLOB(
2420
+ dlob,
2421
+ user0.publicKey,
2422
+ OrderType.LIMIT,
2423
+ MarketType.PERP,
2424
+ 2, // orderId
2425
+ marketIndex,
2426
+ price, // crosses vask
2427
+ BASE_PRECISION, // quantity
2428
+ PositionDirection.SHORT,
2429
+ vBid,
2430
+ vAsk,
2431
+ undefined,
2432
+ undefined,
2433
+ undefined,
2434
+ true
2435
+ );
2436
+
2437
+ // should have no crossing orders
2438
+ const nodesToFillAfter = dlob.findRestingLimitOrderNodesToFill(
2439
+ marketIndex,
2440
+ 12, // auction over
2441
+ MarketType.PERP,
2442
+ {
2443
+ price: vBid.add(vAsk).div(new BN(2)),
2444
+ slot: new BN(12),
2445
+ confidence: new BN(1),
2446
+ hasSufficientNumberOfDataPoints: true,
2447
+ },
2448
+ false,
2449
+ 10,
2450
+ makerRebateNumerator,
2451
+ makerRebateDenominator,
2452
+ vAsk,
2453
+ vBid
2454
+ );
2455
+ expect(nodesToFillAfter.length).to.equal(1);
2456
+ });
2457
+
2270
2458
  it('Test trigger orders', () => {
2271
2459
  const vAsk = new BN(15);
2272
2460
  const vBid = new BN(8);
@@ -2901,6 +3089,8 @@ describe('DLOB Perp Tests', () => {
2901
3089
  oracle,
2902
3090
  false,
2903
3091
  10,
3092
+ 0,
3093
+ 1,
2904
3094
  undefined,
2905
3095
  undefined
2906
3096
  );