@drift-labs/sdk 2.108.0-beta.13 → 2.108.0-beta.15

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.108.0-beta.13
1
+ 2.108.0-beta.15
@@ -568,6 +568,18 @@ exports.MainnetSpotMarkets = [
568
568
  pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
569
569
  launchTs: 1737360280000,
570
570
  },
571
+ {
572
+ symbol: 'AUSD',
573
+ marketIndex: 38,
574
+ poolId: 0,
575
+ oracle: new web3_js_1.PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
576
+ oracleSource: __1.OracleSource.PYTH_STABLE_COIN_PULL,
577
+ mint: new web3_js_1.PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
578
+ precision: new __1.BN(10).pow(numericConstants_1.SIX),
579
+ precisionExp: numericConstants_1.SIX,
580
+ pythFeedId: '0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
581
+ launchTs: 1738255943000,
582
+ },
571
583
  ];
572
584
  exports.SpotMarkets = {
573
585
  devnet: exports.DevnetSpotMarkets,
@@ -17,6 +17,10 @@ export type MarketNodeLists = {
17
17
  ask: NodeList<'floatingLimit'>;
18
18
  bid: NodeList<'floatingLimit'>;
19
19
  };
20
+ protectedFloatingLimit: {
21
+ ask: NodeList<'protectedFloatingLimit'>;
22
+ bid: NodeList<'protectedFloatingLimit'>;
23
+ };
20
24
  takingLimit: {
21
25
  ask: NodeList<'takingLimit'>;
22
26
  bid: NodeList<'takingLimit'>;
@@ -67,8 +71,8 @@ export declare class DLOB {
67
71
  insertOrder(order: Order, userAccount: string, slot: number, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
68
72
  insertSwiftOrder(order: Order, userAccount: string, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
69
73
  addOrderList(marketType: MarketTypeStr, marketIndex: number): void;
70
- delete(order: Order, userAccount: PublicKey, slot: number, onDelete?: OrderBookCallback): void;
71
- getListForOnChainOrder(order: Order, slot: number): NodeList<any> | undefined;
74
+ delete(order: Order, userAccount: PublicKey, slot: number, isUserProtectedMaker: boolean, onDelete?: OrderBookCallback): void;
75
+ getListForOnChainOrder(order: Order, slot: number, isProtectedMaker: boolean): NodeList<any> | undefined;
72
76
  updateRestingLimitOrders(slot: number): void;
73
77
  updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
74
78
  getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
@@ -88,7 +88,7 @@ class DLOB {
88
88
  .get(marketType)
89
89
  .add((0, NodeList_1.getOrderSignature)(order.orderId, userAccount));
90
90
  }
91
- (_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker);
91
+ (_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
92
92
  if (onInsert) {
93
93
  onInsert();
94
94
  }
@@ -106,7 +106,7 @@ class DLOB {
106
106
  this.orderLists
107
107
  .get(marketType)
108
108
  .get(marketIndex)
109
- .swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker);
109
+ .swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
110
110
  if (onInsert) {
111
111
  onInsert();
112
112
  }
@@ -121,6 +121,10 @@ class DLOB {
121
121
  ask: new NodeList_1.NodeList('floatingLimit', 'asc'),
122
122
  bid: new NodeList_1.NodeList('floatingLimit', 'desc'),
123
123
  },
124
+ protectedFloatingLimit: {
125
+ ask: new NodeList_1.NodeList('protectedFloatingLimit', 'asc'),
126
+ bid: new NodeList_1.NodeList('protectedFloatingLimit', 'desc'),
127
+ },
124
128
  takingLimit: {
125
129
  ask: new NodeList_1.NodeList('takingLimit', 'asc'),
126
130
  bid: new NodeList_1.NodeList('takingLimit', 'asc'), // always sort ascending for market orders
@@ -139,18 +143,18 @@ class DLOB {
139
143
  },
140
144
  });
141
145
  }
142
- delete(order, userAccount, slot, onDelete) {
146
+ delete(order, userAccount, slot, isUserProtectedMaker, onDelete) {
143
147
  var _a;
144
148
  if ((0, __1.isVariant)(order.status, 'init')) {
145
149
  return;
146
150
  }
147
151
  this.updateRestingLimitOrders(slot);
148
- (_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
152
+ (_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
149
153
  if (onDelete) {
150
154
  onDelete();
151
155
  }
152
156
  }
153
- getListForOnChainOrder(order, slot) {
157
+ getListForOnChainOrder(order, slot, isProtectedMaker) {
154
158
  const isInactiveTriggerOrder = (0, __1.mustBeTriggered)(order) && !(0, __1.isTriggered)(order);
155
159
  let type;
156
160
  if (isInactiveTriggerOrder) {
@@ -160,7 +164,7 @@ class DLOB {
160
164
  type = 'market';
161
165
  }
162
166
  else if (order.oraclePriceOffset !== 0) {
163
- type = 'floatingLimit';
167
+ type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
164
168
  }
165
169
  else {
166
170
  const isResting = (0, __1.isRestingLimitOrder)(order, slot);
@@ -211,7 +215,7 @@ class DLOB {
211
215
  for (const nodeToUpdate of nodesToUpdate) {
212
216
  const { side, node } = nodeToUpdate;
213
217
  nodeLists.takingLimit[side].remove(node.order, node.userAccount);
214
- nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount);
218
+ nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount, node.isProtectedMaker, this.protectedMakerView);
215
219
  }
216
220
  }
217
221
  }
@@ -374,7 +378,7 @@ class DLOB {
374
378
  if (sameUser) {
375
379
  continue;
376
380
  }
377
- const makerPrice = makerNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
381
+ const makerPrice = makerNode.getPrice(oraclePriceData, slot);
378
382
  const takerPrice = takerNode.getPrice(oraclePriceData, slot);
379
383
  const ordersCross = doesCross(takerPrice, makerPrice);
380
384
  if (!ordersCross) {
@@ -394,11 +398,11 @@ class DLOB {
394
398
  const newMakerOrder = { ...makerOrder };
395
399
  newMakerOrder.baseAssetAmountFilled =
396
400
  makerOrder.baseAssetAmountFilled.add(baseFilled);
397
- this.getListForOnChainOrder(newMakerOrder, slot).update(newMakerOrder, makerNode.userAccount);
401
+ this.getListForOnChainOrder(newMakerOrder, slot, makerNode.isProtectedMaker).update(newMakerOrder, makerNode.userAccount);
398
402
  const newTakerOrder = { ...takerOrder };
399
403
  newTakerOrder.baseAssetAmountFilled =
400
404
  takerOrder.baseAssetAmountFilled.add(baseFilled);
401
- this.getListForOnChainOrder(newTakerOrder, slot).update(newTakerOrder, takerNode.userAccount);
405
+ this.getListForOnChainOrder(newTakerOrder, slot, takerNode.isProtectedMaker).update(newTakerOrder, takerNode.userAccount);
402
406
  if (newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)) {
403
407
  break;
404
408
  }
@@ -572,8 +576,8 @@ class DLOB {
572
576
  ];
573
577
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
574
578
  return bestNode
575
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
576
- .lt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
579
+ .getPrice(oraclePriceData, slot)
580
+ .lt(currentNode.getPrice(oraclePriceData, slot));
577
581
  }, filterFcn);
578
582
  }
579
583
  *getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData, filterFcn) {
@@ -592,8 +596,8 @@ class DLOB {
592
596
  ];
593
597
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
594
598
  return bestNode
595
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
596
- .gt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
599
+ .getPrice(oraclePriceData, slot)
600
+ .gt(currentNode.getPrice(oraclePriceData, slot));
597
601
  }, filterFcn);
598
602
  }
599
603
  /**
@@ -615,8 +619,8 @@ class DLOB {
615
619
  ];
616
620
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
617
621
  var _a, _b;
618
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.ZERO;
619
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.ZERO;
622
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.ZERO;
623
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.ZERO;
620
624
  if (bestNodePrice.eq(currentNodePrice)) {
621
625
  return bestNode.order.slot.lt(currentNode.order.slot);
622
626
  }
@@ -642,8 +646,8 @@ class DLOB {
642
646
  ];
643
647
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
644
648
  var _a, _b;
645
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
646
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
649
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
650
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
647
651
  if (bestNodePrice.eq(currentNodePrice)) {
648
652
  return bestNode.order.slot.lt(currentNode.order.slot);
649
653
  }
@@ -655,8 +659,8 @@ class DLOB {
655
659
  for (const askNode of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
656
660
  const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
657
661
  for (const bidNode of bidGenerator) {
658
- const bidPrice = bidNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
659
- const askPrice = askNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
662
+ const bidPrice = bidNode.getPrice(oraclePriceData, slot);
663
+ const askPrice = askNode.getPrice(oraclePriceData, slot);
660
664
  // orders don't cross
661
665
  if (bidPrice.lt(askPrice)) {
662
666
  break;
@@ -680,12 +684,12 @@ class DLOB {
680
684
  const newBidOrder = { ...bidOrder };
681
685
  newBidOrder.baseAssetAmountFilled =
682
686
  bidOrder.baseAssetAmountFilled.add(baseFilled);
683
- this.getListForOnChainOrder(newBidOrder, slot).update(newBidOrder, bidNode.userAccount);
687
+ this.getListForOnChainOrder(newBidOrder, slot, bidNode.isProtectedMaker).update(newBidOrder, bidNode.userAccount);
684
688
  // ask completely filled
685
689
  const newAskOrder = { ...askOrder };
686
690
  newAskOrder.baseAssetAmountFilled =
687
691
  askOrder.baseAssetAmountFilled.add(baseFilled);
688
- this.getListForOnChainOrder(newAskOrder, slot).update(newAskOrder, askNode.userAccount);
692
+ this.getListForOnChainOrder(newAskOrder, slot, askNode.isProtectedMaker).update(newAskOrder, askNode.userAccount);
689
693
  nodesToFill.push({
690
694
  node: takerNode,
691
695
  makerNodes: [makerNode],
@@ -731,7 +735,7 @@ class DLOB {
731
735
  getBestAsk(marketIndex, slot, marketType, oraclePriceData) {
732
736
  const bestAsk = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData).next().value;
733
737
  if (bestAsk) {
734
- return bestAsk.getPrice(oraclePriceData, slot, this.protectedMakerView);
738
+ return bestAsk.getPrice(oraclePriceData, slot);
735
739
  }
736
740
  return undefined;
737
741
  }
@@ -909,6 +913,8 @@ class DLOB {
909
913
  yield nodeLists.market.ask;
910
914
  yield nodeLists.floatingLimit.bid;
911
915
  yield nodeLists.floatingLimit.ask;
916
+ yield nodeLists.protectedFloatingLimit.bid;
917
+ yield nodeLists.protectedFloatingLimit.ask;
912
918
  yield nodeLists.trigger.above;
913
919
  yield nodeLists.trigger.below;
914
920
  }
@@ -921,6 +927,8 @@ class DLOB {
921
927
  yield nodeLists.market.ask;
922
928
  yield nodeLists.floatingLimit.bid;
923
929
  yield nodeLists.floatingLimit.ask;
930
+ yield nodeLists.protectedFloatingLimit.bid;
931
+ yield nodeLists.protectedFloatingLimit.ask;
924
932
  yield nodeLists.trigger.above;
925
933
  yield nodeLists.trigger.below;
926
934
  }
@@ -1,13 +1,14 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN, OraclePriceData, Order } from '..';
3
3
  export interface DLOBNode {
4
- getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
4
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
5
5
  isVammNode(): boolean;
6
6
  order: Order | undefined;
7
7
  isBaseFilled(): boolean;
8
8
  haveFilled: boolean;
9
9
  userAccount: string | undefined;
10
- isUserProtectedMaker: boolean;
10
+ isProtectedMaker: boolean;
11
+ applyProtectedMakerOffset: boolean;
11
12
  isSwift: boolean | undefined;
12
13
  }
13
14
  export declare abstract class OrderNode implements DLOBNode {
@@ -16,12 +17,13 @@ export declare abstract class OrderNode implements DLOBNode {
16
17
  sortValue: BN;
17
18
  haveFilled: boolean;
18
19
  haveTrigger: boolean;
19
- isUserProtectedMaker: boolean;
20
+ isProtectedMaker: boolean;
21
+ applyProtectedMakerOffset: boolean;
20
22
  isSwift: boolean;
21
- constructor(order: Order, userAccount: string, isUserProtectedMaker: boolean, isSwift?: boolean);
23
+ constructor(order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean, isSwift?: boolean);
22
24
  abstract getSortValue(order: Order): BN;
23
25
  getLabel(): string;
24
- getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
26
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
25
27
  isBaseFilled(): boolean;
26
28
  isVammNode(): boolean;
27
29
  }
@@ -60,9 +62,10 @@ export type DLOBNodeMap = {
60
62
  restingLimit: RestingLimitOrderNode;
61
63
  takingLimit: TakingLimitOrderNode;
62
64
  floatingLimit: FloatingLimitOrderNode;
65
+ protectedFloatingLimit: FloatingLimitOrderNode;
63
66
  market: MarketOrderNode;
64
67
  trigger: TriggerOrderNode;
65
68
  swift: SwiftOrderNode;
66
69
  };
67
- export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
68
- export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isUserProtectedMaker: boolean): DLOBNodeMap[T];
70
+ export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'protectedFloatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
71
+ export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): DLOBNodeMap[T];
@@ -5,14 +5,15 @@ const __1 = require("..");
5
5
  // import { PublicKey } from '@solana/web3.js';
6
6
  const NodeList_1 = require("./NodeList");
7
7
  class OrderNode {
8
- constructor(order, userAccount, isUserProtectedMaker, isSwift = false) {
8
+ constructor(order, userAccount, isProtectedMaker, applyProtectedMakerOffset, isSwift = false) {
9
9
  this.haveFilled = false;
10
10
  this.haveTrigger = false;
11
11
  // Copy the order over to the node
12
12
  this.order = { ...order };
13
13
  this.userAccount = userAccount;
14
14
  this.sortValue = this.getSortValue(order);
15
- this.isUserProtectedMaker = isUserProtectedMaker;
15
+ this.isProtectedMaker = isProtectedMaker;
16
+ this.applyProtectedMakerOffset = applyProtectedMakerOffset;
16
17
  this.isSwift = isSwift;
17
18
  }
18
19
  getLabel() {
@@ -28,8 +29,8 @@ class OrderNode {
28
29
  }
29
30
  return msg;
30
31
  }
31
- getPrice(oraclePriceData, slot, protectedMakerView) {
32
- return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, protectedMakerView && this.isUserProtectedMaker);
32
+ getPrice(oraclePriceData, slot) {
33
+ return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, this.applyProtectedMakerOffset);
33
34
  }
34
35
  isBaseFilled() {
35
36
  return this.order.baseAssetAmountFilled.eq(this.order.baseAssetAmount);
@@ -47,7 +48,17 @@ class TakingLimitOrderNode extends OrderNode {
47
48
  exports.TakingLimitOrderNode = TakingLimitOrderNode;
48
49
  class RestingLimitOrderNode extends OrderNode {
49
50
  getSortValue(order) {
50
- return order.price;
51
+ let sortValue = order.price;
52
+ if (this.applyProtectedMakerOffset) {
53
+ const offset = sortValue.divn(1000);
54
+ if ((0, __1.isVariant)(order.direction, 'long')) {
55
+ sortValue = sortValue.sub(offset);
56
+ }
57
+ else {
58
+ sortValue = sortValue.add(offset);
59
+ }
60
+ }
61
+ return sortValue;
51
62
  }
52
63
  }
53
64
  exports.RestingLimitOrderNode = RestingLimitOrderNode;
@@ -72,25 +83,27 @@ exports.TriggerOrderNode = TriggerOrderNode;
72
83
  // We'll use the swift uuid for the order id since it's not yet on-chain
73
84
  class SwiftOrderNode extends OrderNode {
74
85
  constructor(order, userAccount) {
75
- super(order, userAccount, false, true);
86
+ super(order, userAccount, false, false, true);
76
87
  }
77
88
  getSortValue(order) {
78
89
  return order.slot;
79
90
  }
80
91
  }
81
92
  exports.SwiftOrderNode = SwiftOrderNode;
82
- function createNode(nodeType, order, userAccount, isUserProtectedMaker) {
93
+ function createNode(nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
83
94
  switch (nodeType) {
84
95
  case 'floatingLimit':
85
- return new FloatingLimitOrderNode(order, userAccount, isUserProtectedMaker);
96
+ return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
97
+ case 'protectedFloatingLimit':
98
+ return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
86
99
  case 'restingLimit':
87
- return new RestingLimitOrderNode(order, userAccount, isUserProtectedMaker);
100
+ return new RestingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
88
101
  case 'takingLimit':
89
- return new TakingLimitOrderNode(order, userAccount, isUserProtectedMaker);
102
+ return new TakingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
90
103
  case 'market':
91
- return new MarketOrderNode(order, userAccount, isUserProtectedMaker);
104
+ return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
92
105
  case 'trigger':
93
- return new TriggerOrderNode(order, userAccount, isUserProtectedMaker);
106
+ return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
94
107
  case 'swift':
95
108
  return new SwiftOrderNode(order, userAccount);
96
109
  default:
@@ -13,7 +13,7 @@ export declare class NodeList<NodeType extends keyof DLOBNodeMap> implements DLO
13
13
  nodeMap: Map<string, DLOBNodeMap[NodeType]>;
14
14
  constructor(nodeType: NodeType, sortDirection: SortDirection);
15
15
  clear(): void;
16
- insert(order: Order, marketType: MarketTypeStr, userAccount: string, isUserProtectedMaker: boolean): void;
16
+ insert(order: Order, marketType: MarketTypeStr, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): void;
17
17
  prependNode(currentNode: DLOBNodeMap[NodeType], newNode: DLOBNodeMap[NodeType]): boolean;
18
18
  update(order: Order, userAccount: string): void;
19
19
  remove(order: Order, userAccount: string): void;
@@ -19,11 +19,11 @@ class NodeList {
19
19
  this.length = 0;
20
20
  this.nodeMap.clear();
21
21
  }
22
- insert(order, marketType, userAccount, isUserProtectedMaker) {
22
+ insert(order, marketType, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
23
23
  if ((0, __1.isVariant)(order.status, 'init')) {
24
24
  return;
25
25
  }
26
- const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isUserProtectedMaker);
26
+ const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
27
27
  const orderSignature = getOrderSignature(order.orderId, userAccount);
28
28
  if (this.nodeMap.has(orderSignature)) {
29
29
  return;
@@ -568,6 +568,18 @@ exports.MainnetSpotMarkets = [
568
568
  pythFeedId: '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
569
569
  launchTs: 1737360280000,
570
570
  },
571
+ {
572
+ symbol: 'AUSD',
573
+ marketIndex: 38,
574
+ poolId: 0,
575
+ oracle: new web3_js_1.PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
576
+ oracleSource: __1.OracleSource.PYTH_STABLE_COIN_PULL,
577
+ mint: new web3_js_1.PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
578
+ precision: new __1.BN(10).pow(numericConstants_1.SIX),
579
+ precisionExp: numericConstants_1.SIX,
580
+ pythFeedId: '0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
581
+ launchTs: 1738255943000,
582
+ },
571
583
  ];
572
584
  exports.SpotMarkets = {
573
585
  devnet: exports.DevnetSpotMarkets,
@@ -17,6 +17,10 @@ export type MarketNodeLists = {
17
17
  ask: NodeList<'floatingLimit'>;
18
18
  bid: NodeList<'floatingLimit'>;
19
19
  };
20
+ protectedFloatingLimit: {
21
+ ask: NodeList<'protectedFloatingLimit'>;
22
+ bid: NodeList<'protectedFloatingLimit'>;
23
+ };
20
24
  takingLimit: {
21
25
  ask: NodeList<'takingLimit'>;
22
26
  bid: NodeList<'takingLimit'>;
@@ -67,8 +71,8 @@ export declare class DLOB {
67
71
  insertOrder(order: Order, userAccount: string, slot: number, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
68
72
  insertSwiftOrder(order: Order, userAccount: string, isUserProtectedMaker: boolean, onInsert?: OrderBookCallback): void;
69
73
  addOrderList(marketType: MarketTypeStr, marketIndex: number): void;
70
- delete(order: Order, userAccount: PublicKey, slot: number, onDelete?: OrderBookCallback): void;
71
- getListForOnChainOrder(order: Order, slot: number): NodeList<any> | undefined;
74
+ delete(order: Order, userAccount: PublicKey, slot: number, isUserProtectedMaker: boolean, onDelete?: OrderBookCallback): void;
75
+ getListForOnChainOrder(order: Order, slot: number, isProtectedMaker: boolean): NodeList<any> | undefined;
72
76
  updateRestingLimitOrders(slot: number): void;
73
77
  updateRestingLimitOrdersForMarketType(slot: number, marketTypeStr: MarketTypeStr): void;
74
78
  getOrder(orderId: number, userAccount: PublicKey): Order | undefined;
@@ -88,7 +88,7 @@ class DLOB {
88
88
  .get(marketType)
89
89
  .add((0, NodeList_1.getOrderSignature)(order.orderId, userAccount));
90
90
  }
91
- (_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker);
91
+ (_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
92
92
  if (onInsert) {
93
93
  onInsert();
94
94
  }
@@ -106,7 +106,7 @@ class DLOB {
106
106
  this.orderLists
107
107
  .get(marketType)
108
108
  .get(marketIndex)
109
- .swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker);
109
+ .swift[bidOrAsk].insert(order, marketType, userAccount, isUserProtectedMaker, this.protectedMakerView);
110
110
  if (onInsert) {
111
111
  onInsert();
112
112
  }
@@ -121,6 +121,10 @@ class DLOB {
121
121
  ask: new NodeList_1.NodeList('floatingLimit', 'asc'),
122
122
  bid: new NodeList_1.NodeList('floatingLimit', 'desc'),
123
123
  },
124
+ protectedFloatingLimit: {
125
+ ask: new NodeList_1.NodeList('protectedFloatingLimit', 'asc'),
126
+ bid: new NodeList_1.NodeList('protectedFloatingLimit', 'desc'),
127
+ },
124
128
  takingLimit: {
125
129
  ask: new NodeList_1.NodeList('takingLimit', 'asc'),
126
130
  bid: new NodeList_1.NodeList('takingLimit', 'asc'), // always sort ascending for market orders
@@ -139,18 +143,18 @@ class DLOB {
139
143
  },
140
144
  });
141
145
  }
142
- delete(order, userAccount, slot, onDelete) {
146
+ delete(order, userAccount, slot, isUserProtectedMaker, onDelete) {
143
147
  var _a;
144
148
  if ((0, __1.isVariant)(order.status, 'init')) {
145
149
  return;
146
150
  }
147
151
  this.updateRestingLimitOrders(slot);
148
- (_a = this.getListForOnChainOrder(order, slot)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
152
+ (_a = this.getListForOnChainOrder(order, slot, isUserProtectedMaker)) === null || _a === void 0 ? void 0 : _a.remove(order, userAccount.toString());
149
153
  if (onDelete) {
150
154
  onDelete();
151
155
  }
152
156
  }
153
- getListForOnChainOrder(order, slot) {
157
+ getListForOnChainOrder(order, slot, isProtectedMaker) {
154
158
  const isInactiveTriggerOrder = (0, __1.mustBeTriggered)(order) && !(0, __1.isTriggered)(order);
155
159
  let type;
156
160
  if (isInactiveTriggerOrder) {
@@ -160,7 +164,7 @@ class DLOB {
160
164
  type = 'market';
161
165
  }
162
166
  else if (order.oraclePriceOffset !== 0) {
163
- type = 'floatingLimit';
167
+ type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
164
168
  }
165
169
  else {
166
170
  const isResting = (0, __1.isRestingLimitOrder)(order, slot);
@@ -211,7 +215,7 @@ class DLOB {
211
215
  for (const nodeToUpdate of nodesToUpdate) {
212
216
  const { side, node } = nodeToUpdate;
213
217
  nodeLists.takingLimit[side].remove(node.order, node.userAccount);
214
- nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount);
218
+ nodeLists.restingLimit[side].insert(node.order, marketTypeStr, node.userAccount, node.isProtectedMaker, this.protectedMakerView);
215
219
  }
216
220
  }
217
221
  }
@@ -374,7 +378,7 @@ class DLOB {
374
378
  if (sameUser) {
375
379
  continue;
376
380
  }
377
- const makerPrice = makerNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
381
+ const makerPrice = makerNode.getPrice(oraclePriceData, slot);
378
382
  const takerPrice = takerNode.getPrice(oraclePriceData, slot);
379
383
  const ordersCross = doesCross(takerPrice, makerPrice);
380
384
  if (!ordersCross) {
@@ -394,11 +398,11 @@ class DLOB {
394
398
  const newMakerOrder = { ...makerOrder };
395
399
  newMakerOrder.baseAssetAmountFilled =
396
400
  makerOrder.baseAssetAmountFilled.add(baseFilled);
397
- this.getListForOnChainOrder(newMakerOrder, slot).update(newMakerOrder, makerNode.userAccount);
401
+ this.getListForOnChainOrder(newMakerOrder, slot, makerNode.isProtectedMaker).update(newMakerOrder, makerNode.userAccount);
398
402
  const newTakerOrder = { ...takerOrder };
399
403
  newTakerOrder.baseAssetAmountFilled =
400
404
  takerOrder.baseAssetAmountFilled.add(baseFilled);
401
- this.getListForOnChainOrder(newTakerOrder, slot).update(newTakerOrder, takerNode.userAccount);
405
+ this.getListForOnChainOrder(newTakerOrder, slot, takerNode.isProtectedMaker).update(newTakerOrder, takerNode.userAccount);
402
406
  if (newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)) {
403
407
  break;
404
408
  }
@@ -572,8 +576,8 @@ class DLOB {
572
576
  ];
573
577
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
574
578
  return bestNode
575
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
576
- .lt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
579
+ .getPrice(oraclePriceData, slot)
580
+ .lt(currentNode.getPrice(oraclePriceData, slot));
577
581
  }, filterFcn);
578
582
  }
579
583
  *getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData, filterFcn) {
@@ -592,8 +596,8 @@ class DLOB {
592
596
  ];
593
597
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
594
598
  return bestNode
595
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
596
- .gt(currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView));
599
+ .getPrice(oraclePriceData, slot)
600
+ .gt(currentNode.getPrice(oraclePriceData, slot));
597
601
  }, filterFcn);
598
602
  }
599
603
  /**
@@ -615,8 +619,8 @@ class DLOB {
615
619
  ];
616
620
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
617
621
  var _a, _b;
618
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.ZERO;
619
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.ZERO;
622
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.ZERO;
623
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.ZERO;
620
624
  if (bestNodePrice.eq(currentNodePrice)) {
621
625
  return bestNode.order.slot.lt(currentNode.order.slot);
622
626
  }
@@ -642,8 +646,8 @@ class DLOB {
642
646
  ];
643
647
  yield* this.getBestNode(generatorList, oraclePriceData, slot, (bestNode, currentNode, slot, oraclePriceData) => {
644
648
  var _a, _b;
645
- const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
646
- const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
649
+ const bestNodePrice = (_a = bestNode.getPrice(oraclePriceData, slot)) !== null && _a !== void 0 ? _a : __1.BN_MAX;
650
+ const currentNodePrice = (_b = currentNode.getPrice(oraclePriceData, slot)) !== null && _b !== void 0 ? _b : __1.BN_MAX;
647
651
  if (bestNodePrice.eq(currentNodePrice)) {
648
652
  return bestNode.order.slot.lt(currentNode.order.slot);
649
653
  }
@@ -655,8 +659,8 @@ class DLOB {
655
659
  for (const askNode of this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData)) {
656
660
  const bidGenerator = this.getRestingLimitBids(marketIndex, slot, marketType, oraclePriceData);
657
661
  for (const bidNode of bidGenerator) {
658
- const bidPrice = bidNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
659
- const askPrice = askNode.getPrice(oraclePriceData, slot, this.protectedMakerView);
662
+ const bidPrice = bidNode.getPrice(oraclePriceData, slot);
663
+ const askPrice = askNode.getPrice(oraclePriceData, slot);
660
664
  // orders don't cross
661
665
  if (bidPrice.lt(askPrice)) {
662
666
  break;
@@ -680,12 +684,12 @@ class DLOB {
680
684
  const newBidOrder = { ...bidOrder };
681
685
  newBidOrder.baseAssetAmountFilled =
682
686
  bidOrder.baseAssetAmountFilled.add(baseFilled);
683
- this.getListForOnChainOrder(newBidOrder, slot).update(newBidOrder, bidNode.userAccount);
687
+ this.getListForOnChainOrder(newBidOrder, slot, bidNode.isProtectedMaker).update(newBidOrder, bidNode.userAccount);
684
688
  // ask completely filled
685
689
  const newAskOrder = { ...askOrder };
686
690
  newAskOrder.baseAssetAmountFilled =
687
691
  askOrder.baseAssetAmountFilled.add(baseFilled);
688
- this.getListForOnChainOrder(newAskOrder, slot).update(newAskOrder, askNode.userAccount);
692
+ this.getListForOnChainOrder(newAskOrder, slot, askNode.isProtectedMaker).update(newAskOrder, askNode.userAccount);
689
693
  nodesToFill.push({
690
694
  node: takerNode,
691
695
  makerNodes: [makerNode],
@@ -731,7 +735,7 @@ class DLOB {
731
735
  getBestAsk(marketIndex, slot, marketType, oraclePriceData) {
732
736
  const bestAsk = this.getRestingLimitAsks(marketIndex, slot, marketType, oraclePriceData).next().value;
733
737
  if (bestAsk) {
734
- return bestAsk.getPrice(oraclePriceData, slot, this.protectedMakerView);
738
+ return bestAsk.getPrice(oraclePriceData, slot);
735
739
  }
736
740
  return undefined;
737
741
  }
@@ -909,6 +913,8 @@ class DLOB {
909
913
  yield nodeLists.market.ask;
910
914
  yield nodeLists.floatingLimit.bid;
911
915
  yield nodeLists.floatingLimit.ask;
916
+ yield nodeLists.protectedFloatingLimit.bid;
917
+ yield nodeLists.protectedFloatingLimit.ask;
912
918
  yield nodeLists.trigger.above;
913
919
  yield nodeLists.trigger.below;
914
920
  }
@@ -921,6 +927,8 @@ class DLOB {
921
927
  yield nodeLists.market.ask;
922
928
  yield nodeLists.floatingLimit.bid;
923
929
  yield nodeLists.floatingLimit.ask;
930
+ yield nodeLists.protectedFloatingLimit.bid;
931
+ yield nodeLists.protectedFloatingLimit.ask;
924
932
  yield nodeLists.trigger.above;
925
933
  yield nodeLists.trigger.below;
926
934
  }
@@ -1,13 +1,14 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { BN, OraclePriceData, Order } from '..';
3
3
  export interface DLOBNode {
4
- getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
4
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
5
5
  isVammNode(): boolean;
6
6
  order: Order | undefined;
7
7
  isBaseFilled(): boolean;
8
8
  haveFilled: boolean;
9
9
  userAccount: string | undefined;
10
- isUserProtectedMaker: boolean;
10
+ isProtectedMaker: boolean;
11
+ applyProtectedMakerOffset: boolean;
11
12
  isSwift: boolean | undefined;
12
13
  }
13
14
  export declare abstract class OrderNode implements DLOBNode {
@@ -16,12 +17,13 @@ export declare abstract class OrderNode implements DLOBNode {
16
17
  sortValue: BN;
17
18
  haveFilled: boolean;
18
19
  haveTrigger: boolean;
19
- isUserProtectedMaker: boolean;
20
+ isProtectedMaker: boolean;
21
+ applyProtectedMakerOffset: boolean;
20
22
  isSwift: boolean;
21
- constructor(order: Order, userAccount: string, isUserProtectedMaker: boolean, isSwift?: boolean);
23
+ constructor(order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean, isSwift?: boolean);
22
24
  abstract getSortValue(order: Order): BN;
23
25
  getLabel(): string;
24
- getPrice(oraclePriceData: OraclePriceData, slot: number, protectedMakerView?: boolean): BN;
26
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
25
27
  isBaseFilled(): boolean;
26
28
  isVammNode(): boolean;
27
29
  }
@@ -60,9 +62,10 @@ export type DLOBNodeMap = {
60
62
  restingLimit: RestingLimitOrderNode;
61
63
  takingLimit: TakingLimitOrderNode;
62
64
  floatingLimit: FloatingLimitOrderNode;
65
+ protectedFloatingLimit: FloatingLimitOrderNode;
63
66
  market: MarketOrderNode;
64
67
  trigger: TriggerOrderNode;
65
68
  swift: SwiftOrderNode;
66
69
  };
67
- export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
68
- export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isUserProtectedMaker: boolean): DLOBNodeMap[T];
70
+ export type DLOBNodeType = 'swift' | 'restingLimit' | 'takingLimit' | 'floatingLimit' | 'protectedFloatingLimit' | 'market' | ('trigger' & keyof DLOBNodeMap);
71
+ export declare function createNode<T extends DLOBNodeType>(nodeType: T, order: Order, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): DLOBNodeMap[T];
@@ -5,14 +5,15 @@ const __1 = require("..");
5
5
  // import { PublicKey } from '@solana/web3.js';
6
6
  const NodeList_1 = require("./NodeList");
7
7
  class OrderNode {
8
- constructor(order, userAccount, isUserProtectedMaker, isSwift = false) {
8
+ constructor(order, userAccount, isProtectedMaker, applyProtectedMakerOffset, isSwift = false) {
9
9
  this.haveFilled = false;
10
10
  this.haveTrigger = false;
11
11
  // Copy the order over to the node
12
12
  this.order = { ...order };
13
13
  this.userAccount = userAccount;
14
14
  this.sortValue = this.getSortValue(order);
15
- this.isUserProtectedMaker = isUserProtectedMaker;
15
+ this.isProtectedMaker = isProtectedMaker;
16
+ this.applyProtectedMakerOffset = applyProtectedMakerOffset;
16
17
  this.isSwift = isSwift;
17
18
  }
18
19
  getLabel() {
@@ -28,8 +29,8 @@ class OrderNode {
28
29
  }
29
30
  return msg;
30
31
  }
31
- getPrice(oraclePriceData, slot, protectedMakerView) {
32
- return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, protectedMakerView && this.isUserProtectedMaker);
32
+ getPrice(oraclePriceData, slot) {
33
+ return (0, __1.getLimitPrice)(this.order, oraclePriceData, slot, undefined, this.applyProtectedMakerOffset);
33
34
  }
34
35
  isBaseFilled() {
35
36
  return this.order.baseAssetAmountFilled.eq(this.order.baseAssetAmount);
@@ -47,7 +48,17 @@ class TakingLimitOrderNode extends OrderNode {
47
48
  exports.TakingLimitOrderNode = TakingLimitOrderNode;
48
49
  class RestingLimitOrderNode extends OrderNode {
49
50
  getSortValue(order) {
50
- return order.price;
51
+ let sortValue = order.price;
52
+ if (this.applyProtectedMakerOffset) {
53
+ const offset = sortValue.divn(1000);
54
+ if ((0, __1.isVariant)(order.direction, 'long')) {
55
+ sortValue = sortValue.sub(offset);
56
+ }
57
+ else {
58
+ sortValue = sortValue.add(offset);
59
+ }
60
+ }
61
+ return sortValue;
51
62
  }
52
63
  }
53
64
  exports.RestingLimitOrderNode = RestingLimitOrderNode;
@@ -72,25 +83,27 @@ exports.TriggerOrderNode = TriggerOrderNode;
72
83
  // We'll use the swift uuid for the order id since it's not yet on-chain
73
84
  class SwiftOrderNode extends OrderNode {
74
85
  constructor(order, userAccount) {
75
- super(order, userAccount, false, true);
86
+ super(order, userAccount, false, false, true);
76
87
  }
77
88
  getSortValue(order) {
78
89
  return order.slot;
79
90
  }
80
91
  }
81
92
  exports.SwiftOrderNode = SwiftOrderNode;
82
- function createNode(nodeType, order, userAccount, isUserProtectedMaker) {
93
+ function createNode(nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
83
94
  switch (nodeType) {
84
95
  case 'floatingLimit':
85
- return new FloatingLimitOrderNode(order, userAccount, isUserProtectedMaker);
96
+ return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
97
+ case 'protectedFloatingLimit':
98
+ return new FloatingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
86
99
  case 'restingLimit':
87
- return new RestingLimitOrderNode(order, userAccount, isUserProtectedMaker);
100
+ return new RestingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
88
101
  case 'takingLimit':
89
- return new TakingLimitOrderNode(order, userAccount, isUserProtectedMaker);
102
+ return new TakingLimitOrderNode(order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
90
103
  case 'market':
91
- return new MarketOrderNode(order, userAccount, isUserProtectedMaker);
104
+ return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
92
105
  case 'trigger':
93
- return new TriggerOrderNode(order, userAccount, isUserProtectedMaker);
106
+ return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
94
107
  case 'swift':
95
108
  return new SwiftOrderNode(order, userAccount);
96
109
  default:
@@ -13,7 +13,7 @@ export declare class NodeList<NodeType extends keyof DLOBNodeMap> implements DLO
13
13
  nodeMap: Map<string, DLOBNodeMap[NodeType]>;
14
14
  constructor(nodeType: NodeType, sortDirection: SortDirection);
15
15
  clear(): void;
16
- insert(order: Order, marketType: MarketTypeStr, userAccount: string, isUserProtectedMaker: boolean): void;
16
+ insert(order: Order, marketType: MarketTypeStr, userAccount: string, isProtectedMaker: boolean, applyProtectedMakerOffset: boolean): void;
17
17
  prependNode(currentNode: DLOBNodeMap[NodeType], newNode: DLOBNodeMap[NodeType]): boolean;
18
18
  update(order: Order, userAccount: string): void;
19
19
  remove(order: Order, userAccount: string): void;
@@ -19,11 +19,11 @@ class NodeList {
19
19
  this.length = 0;
20
20
  this.nodeMap.clear();
21
21
  }
22
- insert(order, marketType, userAccount, isUserProtectedMaker) {
22
+ insert(order, marketType, userAccount, isProtectedMaker, applyProtectedMakerOffset) {
23
23
  if ((0, __1.isVariant)(order.status, 'init')) {
24
24
  return;
25
25
  }
26
- const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isUserProtectedMaker);
26
+ const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, userAccount, isProtectedMaker, applyProtectedMakerOffset);
27
27
  const orderSignature = getOrderSignature(order.orderId, userAccount);
28
28
  if (this.nodeMap.has(orderSignature)) {
29
29
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.108.0-beta.13",
3
+ "version": "2.108.0-beta.15",
4
4
  "main": "lib/node/index.js",
5
5
  "types": "lib/node/index.d.ts",
6
6
  "browser": "./lib/browser/index.js",
@@ -673,6 +673,19 @@ export const MainnetSpotMarkets: SpotMarketConfig[] = [
673
673
  '0x8fef7d52c7f4e3a6258d663f9d27e64a1b6fd95ab5f7d545dbf9a515353d0064',
674
674
  launchTs: 1737360280000,
675
675
  },
676
+ {
677
+ symbol: 'AUSD',
678
+ marketIndex: 38,
679
+ poolId: 0,
680
+ oracle: new PublicKey('8FZhpiM8n3mpgvENWLcEvHsKB1bBhYBAyL4Ypr4gptLZ'),
681
+ oracleSource: OracleSource.PYTH_STABLE_COIN_PULL,
682
+ mint: new PublicKey('AUSD1jCcCyPLybk1YnvPWsHQSrZ46dxwoMniN4N2UEB9'),
683
+ precision: new BN(10).pow(SIX),
684
+ precisionExp: SIX,
685
+ pythFeedId:
686
+ '0xd9912df360b5b7f21a122f15bdd5e27f62ce5e72bd316c291f7c86620e07fb2a',
687
+ launchTs: 1738255943000,
688
+ },
676
689
  ];
677
690
 
678
691
  export const SpotMarkets: { [key in DriftEnv]: SpotMarketConfig[] } = {
package/src/dlob/DLOB.ts CHANGED
@@ -57,6 +57,10 @@ export type MarketNodeLists = {
57
57
  ask: NodeList<'floatingLimit'>;
58
58
  bid: NodeList<'floatingLimit'>;
59
59
  };
60
+ protectedFloatingLimit: {
61
+ ask: NodeList<'protectedFloatingLimit'>;
62
+ bid: NodeList<'protectedFloatingLimit'>;
63
+ };
60
64
  takingLimit: {
61
65
  ask: NodeList<'takingLimit'>;
62
66
  bid: NodeList<'takingLimit'>;
@@ -203,11 +207,12 @@ export class DLOB {
203
207
  .get(marketType)
204
208
  .add(getOrderSignature(order.orderId, userAccount));
205
209
  }
206
- this.getListForOnChainOrder(order, slot)?.insert(
210
+ this.getListForOnChainOrder(order, slot, isUserProtectedMaker)?.insert(
207
211
  order,
208
212
  marketType,
209
213
  userAccount,
210
- isUserProtectedMaker
214
+ isUserProtectedMaker,
215
+ this.protectedMakerView
211
216
  );
212
217
 
213
218
  if (onInsert) {
@@ -237,7 +242,8 @@ export class DLOB {
237
242
  order,
238
243
  marketType,
239
244
  userAccount,
240
- isUserProtectedMaker
245
+ isUserProtectedMaker,
246
+ this.protectedMakerView
241
247
  );
242
248
  if (onInsert) {
243
249
  onInsert();
@@ -254,6 +260,10 @@ export class DLOB {
254
260
  ask: new NodeList('floatingLimit', 'asc'),
255
261
  bid: new NodeList('floatingLimit', 'desc'),
256
262
  },
263
+ protectedFloatingLimit: {
264
+ ask: new NodeList('protectedFloatingLimit', 'asc'),
265
+ bid: new NodeList('protectedFloatingLimit', 'desc'),
266
+ },
257
267
  takingLimit: {
258
268
  ask: new NodeList('takingLimit', 'asc'),
259
269
  bid: new NodeList('takingLimit', 'asc'), // always sort ascending for market orders
@@ -277,6 +287,7 @@ export class DLOB {
277
287
  order: Order,
278
288
  userAccount: PublicKey,
279
289
  slot: number,
290
+ isUserProtectedMaker: boolean,
280
291
  onDelete?: OrderBookCallback
281
292
  ): void {
282
293
  if (isVariant(order.status, 'init')) {
@@ -285,7 +296,7 @@ export class DLOB {
285
296
 
286
297
  this.updateRestingLimitOrders(slot);
287
298
 
288
- this.getListForOnChainOrder(order, slot)?.remove(
299
+ this.getListForOnChainOrder(order, slot, isUserProtectedMaker)?.remove(
289
300
  order,
290
301
  userAccount.toString()
291
302
  );
@@ -297,7 +308,8 @@ export class DLOB {
297
308
 
298
309
  public getListForOnChainOrder(
299
310
  order: Order,
300
- slot: number
311
+ slot: number,
312
+ isProtectedMaker: boolean
301
313
  ): NodeList<any> | undefined {
302
314
  const isInactiveTriggerOrder =
303
315
  mustBeTriggered(order) && !isTriggered(order);
@@ -310,7 +322,7 @@ export class DLOB {
310
322
  ) {
311
323
  type = 'market';
312
324
  } else if (order.oraclePriceOffset !== 0) {
313
- type = 'floatingLimit';
325
+ type = isProtectedMaker ? 'protectedFloatingLimit' : 'floatingLimit';
314
326
  } else {
315
327
  const isResting = isRestingLimitOrder(order, slot);
316
328
  type = isResting ? 'restingLimit' : 'takingLimit';
@@ -380,7 +392,9 @@ export class DLOB {
380
392
  nodeLists.restingLimit[side].insert(
381
393
  node.order,
382
394
  marketTypeStr,
383
- node.userAccount
395
+ node.userAccount,
396
+ node.isProtectedMaker,
397
+ this.protectedMakerView
384
398
  );
385
399
  }
386
400
  }
@@ -765,11 +779,7 @@ export class DLOB {
765
779
  continue;
766
780
  }
767
781
 
768
- const makerPrice = makerNode.getPrice(
769
- oraclePriceData,
770
- slot,
771
- this.protectedMakerView
772
- );
782
+ const makerPrice = makerNode.getPrice(oraclePriceData, slot);
773
783
  const takerPrice = takerNode.getPrice(oraclePriceData, slot);
774
784
 
775
785
  const ordersCross = doesCross(takerPrice, makerPrice);
@@ -799,18 +809,20 @@ export class DLOB {
799
809
  const newMakerOrder = { ...makerOrder };
800
810
  newMakerOrder.baseAssetAmountFilled =
801
811
  makerOrder.baseAssetAmountFilled.add(baseFilled);
802
- this.getListForOnChainOrder(newMakerOrder, slot).update(
812
+ this.getListForOnChainOrder(
803
813
  newMakerOrder,
804
- makerNode.userAccount
805
- );
814
+ slot,
815
+ makerNode.isProtectedMaker
816
+ ).update(newMakerOrder, makerNode.userAccount);
806
817
 
807
818
  const newTakerOrder = { ...takerOrder };
808
819
  newTakerOrder.baseAssetAmountFilled =
809
820
  takerOrder.baseAssetAmountFilled.add(baseFilled);
810
- this.getListForOnChainOrder(newTakerOrder, slot).update(
821
+ this.getListForOnChainOrder(
811
822
  newTakerOrder,
812
- takerNode.userAccount
813
- );
823
+ slot,
824
+ takerNode.isProtectedMaker
825
+ ).update(newTakerOrder, takerNode.userAccount);
814
826
 
815
827
  if (
816
828
  newTakerOrder.baseAssetAmountFilled.eq(takerOrder.baseAssetAmount)
@@ -1089,10 +1101,8 @@ export class DLOB {
1089
1101
  slot,
1090
1102
  (bestNode, currentNode, slot, oraclePriceData) => {
1091
1103
  return bestNode
1092
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
1093
- .lt(
1094
- currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)
1095
- );
1104
+ .getPrice(oraclePriceData, slot)
1105
+ .lt(currentNode.getPrice(oraclePriceData, slot));
1096
1106
  },
1097
1107
  filterFcn
1098
1108
  );
@@ -1129,10 +1139,8 @@ export class DLOB {
1129
1139
  slot,
1130
1140
  (bestNode, currentNode, slot, oraclePriceData) => {
1131
1141
  return bestNode
1132
- .getPrice(oraclePriceData, slot, this.protectedMakerView)
1133
- .gt(
1134
- currentNode.getPrice(oraclePriceData, slot, this.protectedMakerView)
1135
- );
1142
+ .getPrice(oraclePriceData, slot)
1143
+ .gt(currentNode.getPrice(oraclePriceData, slot));
1136
1144
  },
1137
1145
  filterFcn
1138
1146
  );
@@ -1169,15 +1177,9 @@ export class DLOB {
1169
1177
  oraclePriceData,
1170
1178
  slot,
1171
1179
  (bestNode, currentNode, slot, oraclePriceData) => {
1172
- const bestNodePrice =
1173
- bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView) ??
1174
- ZERO;
1180
+ const bestNodePrice = bestNode.getPrice(oraclePriceData, slot) ?? ZERO;
1175
1181
  const currentNodePrice =
1176
- currentNode.getPrice(
1177
- oraclePriceData,
1178
- slot,
1179
- this.protectedMakerView
1180
- ) ?? ZERO;
1182
+ currentNode.getPrice(oraclePriceData, slot) ?? ZERO;
1181
1183
 
1182
1184
  if (bestNodePrice.eq(currentNodePrice)) {
1183
1185
  return bestNode.order.slot.lt(currentNode.order.slot);
@@ -1221,14 +1223,9 @@ export class DLOB {
1221
1223
  slot,
1222
1224
  (bestNode, currentNode, slot, oraclePriceData) => {
1223
1225
  const bestNodePrice =
1224
- bestNode.getPrice(oraclePriceData, slot, this.protectedMakerView) ??
1225
- BN_MAX;
1226
+ bestNode.getPrice(oraclePriceData, slot) ?? BN_MAX;
1226
1227
  const currentNodePrice =
1227
- currentNode.getPrice(
1228
- oraclePriceData,
1229
- slot,
1230
- this.protectedMakerView
1231
- ) ?? BN_MAX;
1228
+ currentNode.getPrice(oraclePriceData, slot) ?? BN_MAX;
1232
1229
 
1233
1230
  if (bestNodePrice.eq(currentNodePrice)) {
1234
1231
  return bestNode.order.slot.lt(currentNode.order.slot);
@@ -1262,16 +1259,8 @@ export class DLOB {
1262
1259
  );
1263
1260
 
1264
1261
  for (const bidNode of bidGenerator) {
1265
- const bidPrice = bidNode.getPrice(
1266
- oraclePriceData,
1267
- slot,
1268
- this.protectedMakerView
1269
- );
1270
- const askPrice = askNode.getPrice(
1271
- oraclePriceData,
1272
- slot,
1273
- this.protectedMakerView
1274
- );
1262
+ const bidPrice = bidNode.getPrice(oraclePriceData, slot);
1263
+ const askPrice = askNode.getPrice(oraclePriceData, slot);
1275
1264
 
1276
1265
  // orders don't cross
1277
1266
  if (bidPrice.lt(askPrice)) {
@@ -1308,19 +1297,21 @@ export class DLOB {
1308
1297
  const newBidOrder = { ...bidOrder };
1309
1298
  newBidOrder.baseAssetAmountFilled =
1310
1299
  bidOrder.baseAssetAmountFilled.add(baseFilled);
1311
- this.getListForOnChainOrder(newBidOrder, slot).update(
1300
+ this.getListForOnChainOrder(
1312
1301
  newBidOrder,
1313
- bidNode.userAccount
1314
- );
1302
+ slot,
1303
+ bidNode.isProtectedMaker
1304
+ ).update(newBidOrder, bidNode.userAccount);
1315
1305
 
1316
1306
  // ask completely filled
1317
1307
  const newAskOrder = { ...askOrder };
1318
1308
  newAskOrder.baseAssetAmountFilled =
1319
1309
  askOrder.baseAssetAmountFilled.add(baseFilled);
1320
- this.getListForOnChainOrder(newAskOrder, slot).update(
1310
+ this.getListForOnChainOrder(
1321
1311
  newAskOrder,
1322
- askNode.userAccount
1323
- );
1312
+ slot,
1313
+ askNode.isProtectedMaker
1314
+ ).update(newAskOrder, askNode.userAccount);
1324
1315
 
1325
1316
  nodesToFill.push({
1326
1317
  node: takerNode,
@@ -1386,7 +1377,7 @@ export class DLOB {
1386
1377
  ).next().value;
1387
1378
 
1388
1379
  if (bestAsk) {
1389
- return bestAsk.getPrice(oraclePriceData, slot, this.protectedMakerView);
1380
+ return bestAsk.getPrice(oraclePriceData, slot);
1390
1381
  }
1391
1382
  return undefined;
1392
1383
  }
@@ -1684,6 +1675,8 @@ export class DLOB {
1684
1675
  yield nodeLists.market.ask;
1685
1676
  yield nodeLists.floatingLimit.bid;
1686
1677
  yield nodeLists.floatingLimit.ask;
1678
+ yield nodeLists.protectedFloatingLimit.bid;
1679
+ yield nodeLists.protectedFloatingLimit.ask;
1687
1680
  yield nodeLists.trigger.above;
1688
1681
  yield nodeLists.trigger.below;
1689
1682
  }
@@ -1697,6 +1690,8 @@ export class DLOB {
1697
1690
  yield nodeLists.market.ask;
1698
1691
  yield nodeLists.floatingLimit.bid;
1699
1692
  yield nodeLists.floatingLimit.ask;
1693
+ yield nodeLists.protectedFloatingLimit.bid;
1694
+ yield nodeLists.protectedFloatingLimit.ask;
1700
1695
  yield nodeLists.trigger.above;
1701
1696
  yield nodeLists.trigger.below;
1702
1697
  }
@@ -13,17 +13,14 @@ import {
13
13
  import { getOrderSignature } from './NodeList';
14
14
 
15
15
  export interface DLOBNode {
16
- getPrice(
17
- oraclePriceData: OraclePriceData,
18
- slot: number,
19
- protectedMakerView?: boolean
20
- ): BN;
16
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN;
21
17
  isVammNode(): boolean;
22
18
  order: Order | undefined;
23
19
  isBaseFilled(): boolean;
24
20
  haveFilled: boolean;
25
21
  userAccount: string | undefined;
26
- isUserProtectedMaker: boolean;
22
+ isProtectedMaker: boolean;
23
+ applyProtectedMakerOffset: boolean;
27
24
  isSwift: boolean | undefined;
28
25
  }
29
26
 
@@ -33,20 +30,23 @@ export abstract class OrderNode implements DLOBNode {
33
30
  sortValue: BN;
34
31
  haveFilled = false;
35
32
  haveTrigger = false;
36
- isUserProtectedMaker: boolean;
33
+ isProtectedMaker: boolean;
34
+ applyProtectedMakerOffset: boolean;
37
35
  isSwift: boolean;
38
36
 
39
37
  constructor(
40
38
  order: Order,
41
39
  userAccount: string,
42
- isUserProtectedMaker: boolean,
40
+ isProtectedMaker: boolean,
41
+ applyProtectedMakerOffset: boolean,
43
42
  isSwift = false
44
43
  ) {
45
44
  // Copy the order over to the node
46
45
  this.order = { ...order };
47
46
  this.userAccount = userAccount;
48
47
  this.sortValue = this.getSortValue(order);
49
- this.isUserProtectedMaker = isUserProtectedMaker;
48
+ this.isProtectedMaker = isProtectedMaker;
49
+ this.applyProtectedMakerOffset = applyProtectedMakerOffset;
50
50
  this.isSwift = isSwift;
51
51
  }
52
52
 
@@ -79,17 +79,13 @@ export abstract class OrderNode implements DLOBNode {
79
79
  return msg;
80
80
  }
81
81
 
82
- getPrice(
83
- oraclePriceData: OraclePriceData,
84
- slot: number,
85
- protectedMakerView?: boolean
86
- ): BN {
82
+ getPrice(oraclePriceData: OraclePriceData, slot: number): BN {
87
83
  return getLimitPrice(
88
84
  this.order,
89
85
  oraclePriceData,
90
86
  slot,
91
87
  undefined,
92
- protectedMakerView && this.isUserProtectedMaker
88
+ this.applyProtectedMakerOffset
93
89
  );
94
90
  }
95
91
 
@@ -116,7 +112,17 @@ export class RestingLimitOrderNode extends OrderNode {
116
112
  previous?: RestingLimitOrderNode;
117
113
 
118
114
  getSortValue(order: Order): BN {
119
- return order.price;
115
+ let sortValue = order.price;
116
+ if (this.applyProtectedMakerOffset) {
117
+ const offset = sortValue.divn(1000);
118
+
119
+ if (isVariant(order.direction, 'long')) {
120
+ sortValue = sortValue.sub(offset);
121
+ } else {
122
+ sortValue = sortValue.add(offset);
123
+ }
124
+ }
125
+ return sortValue;
120
126
  }
121
127
  }
122
128
 
@@ -153,7 +159,7 @@ export class SwiftOrderNode extends OrderNode {
153
159
  previous?: SwiftOrderNode;
154
160
 
155
161
  constructor(order: Order, userAccount: string) {
156
- super(order, userAccount, false, true);
162
+ super(order, userAccount, false, false, true);
157
163
  }
158
164
 
159
165
  getSortValue(order: Order): BN {
@@ -165,6 +171,7 @@ export type DLOBNodeMap = {
165
171
  restingLimit: RestingLimitOrderNode;
166
172
  takingLimit: TakingLimitOrderNode;
167
173
  floatingLimit: FloatingLimitOrderNode;
174
+ protectedFloatingLimit: FloatingLimitOrderNode;
168
175
  market: MarketOrderNode;
169
176
  trigger: TriggerOrderNode;
170
177
  swift: SwiftOrderNode;
@@ -175,6 +182,7 @@ export type DLOBNodeType =
175
182
  | 'restingLimit'
176
183
  | 'takingLimit'
177
184
  | 'floatingLimit'
185
+ | 'protectedFloatingLimit'
178
186
  | 'market'
179
187
  | ('trigger' & keyof DLOBNodeMap);
180
188
 
@@ -182,27 +190,42 @@ export function createNode<T extends DLOBNodeType>(
182
190
  nodeType: T,
183
191
  order: Order,
184
192
  userAccount: string,
185
- isUserProtectedMaker: boolean
193
+ isProtectedMaker: boolean,
194
+ applyProtectedMakerOffset: boolean
186
195
  ): DLOBNodeMap[T] {
187
196
  switch (nodeType) {
188
197
  case 'floatingLimit':
189
198
  return new FloatingLimitOrderNode(
190
199
  order,
191
200
  userAccount,
192
- isUserProtectedMaker
201
+ isProtectedMaker,
202
+ applyProtectedMakerOffset
203
+ );
204
+ case 'protectedFloatingLimit':
205
+ return new FloatingLimitOrderNode(
206
+ order,
207
+ userAccount,
208
+ isProtectedMaker,
209
+ applyProtectedMakerOffset
193
210
  );
194
211
  case 'restingLimit':
195
212
  return new RestingLimitOrderNode(
196
213
  order,
197
214
  userAccount,
198
- isUserProtectedMaker
215
+ isProtectedMaker,
216
+ applyProtectedMakerOffset
199
217
  );
200
218
  case 'takingLimit':
201
- return new TakingLimitOrderNode(order, userAccount, isUserProtectedMaker);
219
+ return new TakingLimitOrderNode(
220
+ order,
221
+ userAccount,
222
+ isProtectedMaker,
223
+ applyProtectedMakerOffset
224
+ );
202
225
  case 'market':
203
- return new MarketOrderNode(order, userAccount, isUserProtectedMaker);
226
+ return new MarketOrderNode(order, userAccount, isProtectedMaker, false);
204
227
  case 'trigger':
205
- return new TriggerOrderNode(order, userAccount, isUserProtectedMaker);
228
+ return new TriggerOrderNode(order, userAccount, isProtectedMaker, false);
206
229
  case 'swift':
207
230
  return new SwiftOrderNode(order, userAccount);
208
231
  default:
@@ -36,7 +36,8 @@ export class NodeList<NodeType extends keyof DLOBNodeMap>
36
36
  order: Order,
37
37
  marketType: MarketTypeStr,
38
38
  userAccount: string,
39
- isUserProtectedMaker: boolean
39
+ isProtectedMaker: boolean,
40
+ applyProtectedMakerOffset: boolean
40
41
  ): void {
41
42
  if (isVariant(order.status, 'init')) {
42
43
  return;
@@ -46,7 +47,8 @@ export class NodeList<NodeType extends keyof DLOBNodeMap>
46
47
  this.nodeType,
47
48
  order,
48
49
  userAccount,
49
- isUserProtectedMaker
50
+ isProtectedMaker,
51
+ applyProtectedMakerOffset
50
52
  );
51
53
 
52
54
  const orderSignature = getOrderSignature(order.orderId, userAccount);