@drift-labs/sdk 2.108.0-beta.9 → 2.109.0-beta.0

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 (43) hide show
  1. package/VERSION +1 -1
  2. package/lib/browser/constants/spotMarkets.js +14 -2
  3. package/lib/browser/dlob/DLOB.d.ts +6 -2
  4. package/lib/browser/dlob/DLOB.js +31 -23
  5. package/lib/browser/dlob/DLOBNode.d.ts +10 -7
  6. package/lib/browser/dlob/DLOBNode.js +25 -12
  7. package/lib/browser/dlob/NodeList.d.ts +1 -1
  8. package/lib/browser/dlob/NodeList.js +2 -2
  9. package/lib/browser/driftClient.d.ts +9 -0
  10. package/lib/browser/driftClient.js +12 -0
  11. package/lib/browser/idl/drift.json +6 -1
  12. package/lib/browser/math/conversion.d.ts +2 -0
  13. package/lib/browser/math/conversion.js +11 -1
  14. package/lib/browser/math/market.d.ts +1 -0
  15. package/lib/browser/math/market.js +12 -1
  16. package/lib/browser/user.d.ts +4 -3
  17. package/lib/browser/user.js +18 -11
  18. package/lib/node/constants/spotMarkets.js +14 -2
  19. package/lib/node/dlob/DLOB.d.ts +6 -2
  20. package/lib/node/dlob/DLOB.js +31 -23
  21. package/lib/node/dlob/DLOBNode.d.ts +10 -7
  22. package/lib/node/dlob/DLOBNode.js +25 -12
  23. package/lib/node/dlob/NodeList.d.ts +1 -1
  24. package/lib/node/dlob/NodeList.js +2 -2
  25. package/lib/node/driftClient.d.ts +9 -0
  26. package/lib/node/driftClient.js +12 -0
  27. package/lib/node/idl/drift.json +6 -1
  28. package/lib/node/math/conversion.d.ts +2 -0
  29. package/lib/node/math/conversion.js +11 -1
  30. package/lib/node/math/market.d.ts +1 -0
  31. package/lib/node/math/market.js +12 -1
  32. package/lib/node/user.d.ts +4 -3
  33. package/lib/node/user.js +18 -11
  34. package/package.json +1 -1
  35. package/src/constants/spotMarkets.ts +15 -2
  36. package/src/dlob/DLOB.ts +53 -58
  37. package/src/dlob/DLOBNode.ts +46 -23
  38. package/src/dlob/NodeList.ts +4 -2
  39. package/src/driftClient.ts +18 -0
  40. package/src/idl/drift.json +6 -1
  41. package/src/math/conversion.ts +11 -0
  42. package/src/math/market.ts +16 -0
  43. package/src/user.ts +41 -14
package/VERSION CHANGED
@@ -1 +1 @@
1
- 2.108.0-beta.9
1
+ 2.109.0-beta.0
@@ -508,7 +508,7 @@ exports.MainnetSpotMarkets = [
508
508
  pythLazerId: 9,
509
509
  },
510
510
  {
511
- symbol: 'JLP',
511
+ symbol: 'JLP-1',
512
512
  marketIndex: 33,
513
513
  poolId: 1,
514
514
  oracle: new web3_js_1.PublicKey('5Mb11e5rt1Sp6A286B145E4TmgMzsM2UX9nCF2vas5bs'),
@@ -520,7 +520,7 @@ exports.MainnetSpotMarkets = [
520
520
  launchTs: 1735255852000,
521
521
  },
522
522
  {
523
- symbol: 'USDC',
523
+ symbol: 'USDC-1',
524
524
  marketIndex: 34,
525
525
  poolId: 1,
526
526
  oracle: new web3_js_1.PublicKey('En8hkHLkRe9d9DraYmBTrus518BvmVH448YcvmrFM6Ce'),
@@ -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;
@@ -190,6 +190,15 @@ export declare class DriftClient {
190
190
  getForceDeleteUserIx(userAccountPublicKey: PublicKey, userAccount: UserAccount): Promise<anchor.web3.TransactionInstruction>;
191
191
  deleteSwiftUserOrders(txParams?: TxParams): Promise<TransactionSignature>;
192
192
  getSwiftUserOrdersDeletionIx(authority: PublicKey): Promise<anchor.web3.TransactionInstruction>;
193
+ /**
194
+ * Checks if a Swift User Orders account exists for the given authority.
195
+ * The account pubkey is derived using the program ID and authority as seeds.
196
+ * Makes an RPC call to check if the account exists on-chain.
197
+ *
198
+ * @param authority The authority public key to check for
199
+ * @returns Promise that resolves to true if the account exists, false otherwise
200
+ */
201
+ isSwiftUserOrdersAccountInitialized(authority: PublicKey): Promise<boolean>;
193
202
  reclaimRent(subAccountId?: number, txParams?: TxParams): Promise<TransactionSignature>;
194
203
  getReclaimRentIx(userAccountPublicKey: PublicKey): Promise<anchor.web3.TransactionInstruction>;
195
204
  getUser(subAccountId?: number, authority?: PublicKey): User;
@@ -1011,6 +1011,18 @@ class DriftClient {
1011
1011
  });
1012
1012
  return ix;
1013
1013
  }
1014
+ /**
1015
+ * Checks if a Swift User Orders account exists for the given authority.
1016
+ * The account pubkey is derived using the program ID and authority as seeds.
1017
+ * Makes an RPC call to check if the account exists on-chain.
1018
+ *
1019
+ * @param authority The authority public key to check for
1020
+ * @returns Promise that resolves to true if the account exists, false otherwise
1021
+ */
1022
+ async isSwiftUserOrdersAccountInitialized(authority) {
1023
+ const swiftUserOrdersAccountPublicKey = (0, pda_1.getSwiftUserAccountPublicKey)(this.program.programId, authority);
1024
+ return this.checkIfAccountExists(swiftUserOrdersAccountPublicKey);
1025
+ }
1014
1026
  async reclaimRent(subAccountId = 0, txParams) {
1015
1027
  const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, subAccountId);
1016
1028
  const ix = await this.getReclaimRentIx(userAccountPublicKey);
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.107.0",
2
+ "version": "2.108.0",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -14642,6 +14642,11 @@
14642
14642
  "code": 6308,
14643
14643
  "name": "InvalidLiquidateSpotWithSwap",
14644
14644
  "msg": "InvalidLiquidateSpotWithSwap"
14645
+ },
14646
+ {
14647
+ "code": 6309,
14648
+ "name": "SwiftUserContextUserMismatch",
14649
+ "msg": "User in swift message does not match user in ix context"
14645
14650
  }
14646
14651
  ],
14647
14652
  "metadata": {
@@ -1,2 +1,4 @@
1
+ /// <reference types="bn.js" />
1
2
  import { BN } from '../';
2
3
  export declare const convertToNumber: (bigNumber: BN, precision?: BN) => number;
4
+ export declare function convertToBN(value: number, precision: BN): BN;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.convertToNumber = void 0;
3
+ exports.convertToBN = exports.convertToNumber = void 0;
4
+ const __1 = require("../");
4
5
  const numericConstants_1 = require("../constants/numericConstants");
5
6
  const convertToNumber = (bigNumber, precision = numericConstants_1.PRICE_PRECISION) => {
6
7
  if (!bigNumber)
@@ -9,3 +10,12 @@ const convertToNumber = (bigNumber, precision = numericConstants_1.PRICE_PRECISI
9
10
  bigNumber.mod(precision).toNumber() / precision.toNumber());
10
11
  };
11
12
  exports.convertToNumber = convertToNumber;
13
+ function convertToBN(value, precision) {
14
+ // Get the whole part using Math.floor
15
+ const wholePart = Math.floor(value);
16
+ // Get decimal part by subtracting whole part and multiplying by precision
17
+ const decimalPart = Math.round((value - wholePart) * precision.toNumber());
18
+ // Combine: wholePart * PRECISION + decimalPart
19
+ return new __1.BN(wholePart).mul(precision).add(new __1.BN(decimalPart));
20
+ }
21
+ exports.convertToBN = convertToBN;
@@ -37,3 +37,4 @@ export declare function calculateAvailablePerpLiquidity(market: PerpMarketAccoun
37
37
  bids: BN;
38
38
  asks: BN;
39
39
  };
40
+ export declare function calculatePerpMarketBaseLiquidatorFee(market: PerpMarketAccount, userHighLeverageMode: boolean): number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateAvailablePerpLiquidity = exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketMaxAvailableInsurance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateOracleReserveSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateReservePrice = void 0;
3
+ exports.calculatePerpMarketBaseLiquidatorFee = exports.calculateAvailablePerpLiquidity = exports.calculateNetUserPnlImbalance = exports.calculateNetUserPnl = exports.calculateMarketMaxAvailableInsurance = exports.calculateMarketAvailablePNL = exports.calculateUnrealizedAssetWeight = exports.calculateMarketMarginRatio = exports.calculateOracleSpread = exports.calculateOracleReserveSpread = exports.calculateNewMarketAfterTrade = exports.calculateAskPrice = exports.calculateBidPrice = exports.calculateReservePrice = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const types_1 = require("../types");
6
6
  const amm_1 = require("./amm");
@@ -161,3 +161,14 @@ function calculateAvailablePerpLiquidity(market, oraclePriceData, dlob, slot) {
161
161
  };
162
162
  }
163
163
  exports.calculateAvailablePerpLiquidity = calculateAvailablePerpLiquidity;
164
+ function calculatePerpMarketBaseLiquidatorFee(market, userHighLeverageMode) {
165
+ if (userHighLeverageMode && market.highLeverageMarginRatioMaintenance > 0) {
166
+ // min(liquidator_fee, .8 * high_leverage_margin_ratio_maintenance)
167
+ return Math.min(market.liquidatorFee, market.highLeverageMarginRatioMaintenance -
168
+ Math.floor(market.highLeverageMarginRatioMaintenance / 5));
169
+ }
170
+ else {
171
+ return market.liquidatorFee;
172
+ }
173
+ }
174
+ exports.calculatePerpMarketBaseLiquidatorFee = calculatePerpMarketBaseLiquidatorFee;
@@ -119,7 +119,7 @@ export declare class User {
119
119
  /**
120
120
  * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
121
121
  */
122
- getMaintenanceMarginRequirement(): BN;
122
+ getMaintenanceMarginRequirement(liquidationBuffer?: BN): BN;
123
123
  getActivePerpPositionsForUserAccount(userAccount: UserAccount): PerpPosition[];
124
124
  getActivePerpPositions(): PerpPosition[];
125
125
  getActivePerpPositionsAndSlot(): DataAndSlot<PerpPosition[]>;
@@ -130,7 +130,7 @@ export declare class User {
130
130
  * calculates unrealized position price pnl
131
131
  * @returns : Precision QUOTE_PRECISION
132
132
  */
133
- getUnrealizedPNL(withFunding?: boolean, marketIndex?: number, withWeightMarginCategory?: MarginCategory, strict?: boolean): BN;
133
+ getUnrealizedPNL(withFunding?: boolean, marketIndex?: number, withWeightMarginCategory?: MarginCategory, strict?: boolean, liquidationBuffer?: BN): BN;
134
134
  /**
135
135
  * calculates unrealized funding payment pnl
136
136
  * @returns : Precision QUOTE_PRECISION
@@ -158,7 +158,8 @@ export declare class User {
158
158
  * calculates TotalCollateral: collateral + unrealized pnl
159
159
  * @returns : Precision QUOTE_PRECISION
160
160
  */
161
- getTotalCollateral(marginCategory?: MarginCategory, strict?: boolean, includeOpenOrders?: boolean): BN;
161
+ getTotalCollateral(marginCategory?: MarginCategory, strict?: boolean, includeOpenOrders?: boolean, liquidationBuffer?: BN): BN;
162
+ getLiquidationBuffer(): BN | undefined;
162
163
  /**
163
164
  * calculates User Health by comparing total collateral and maint. margin requirement
164
165
  * @returns : number (value from [0, 100])
@@ -457,12 +457,7 @@ class User {
457
457
  /**
458
458
  * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
459
459
  */
460
- getMaintenanceMarginRequirement() {
461
- // if user being liq'd, can continue to be liq'd until total collateral above the margin requirement plus buffer
462
- let liquidationBuffer = undefined;
463
- if (this.isBeingLiquidated()) {
464
- liquidationBuffer = new _1.BN(this.driftClient.getStateAccount().liquidationMarginBufferRatio);
465
- }
460
+ getMaintenanceMarginRequirement(liquidationBuffer) {
466
461
  return this.getMarginRequirement('Maintenance', liquidationBuffer);
467
462
  }
468
463
  getActivePerpPositionsForUserAccount(userAccount) {
@@ -502,7 +497,7 @@ class User {
502
497
  * calculates unrealized position price pnl
503
498
  * @returns : Precision QUOTE_PRECISION
504
499
  */
505
- getUnrealizedPNL(withFunding, marketIndex, withWeightMarginCategory, strict = false) {
500
+ getUnrealizedPNL(withFunding, marketIndex, withWeightMarginCategory, strict = false, liquidationBuffer) {
506
501
  return this.getActivePerpPositions()
507
502
  .filter((pos) => marketIndex !== undefined ? pos.marketIndex === marketIndex : true)
508
503
  .reduce((unrealizedPnl, perpPosition) => {
@@ -533,6 +528,9 @@ class User {
533
528
  .mul((0, _1.calculateUnrealizedAssetWeight)(market, quoteSpotMarket, positionUnrealizedPnl, withWeightMarginCategory, oraclePriceData))
534
529
  .div(new _1.BN(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION));
535
530
  }
531
+ if (liquidationBuffer && positionUnrealizedPnl.lt(numericConstants_1.ZERO)) {
532
+ positionUnrealizedPnl = positionUnrealizedPnl.add(positionUnrealizedPnl.mul(liquidationBuffer).div(numericConstants_1.MARGIN_PRECISION));
533
+ }
536
534
  }
537
535
  return unrealizedPnl.add(positionUnrealizedPnl);
538
536
  }, numericConstants_1.ZERO);
@@ -731,8 +729,16 @@ class User {
731
729
  * calculates TotalCollateral: collateral + unrealized pnl
732
730
  * @returns : Precision QUOTE_PRECISION
733
731
  */
734
- getTotalCollateral(marginCategory = 'Initial', strict = false, includeOpenOrders = true) {
735
- return this.getSpotMarketAssetValue(undefined, marginCategory, includeOpenOrders, strict).add(this.getUnrealizedPNL(true, undefined, marginCategory, strict));
732
+ getTotalCollateral(marginCategory = 'Initial', strict = false, includeOpenOrders = true, liquidationBuffer) {
733
+ return this.getSpotMarketAssetValue(undefined, marginCategory, includeOpenOrders, strict).add(this.getUnrealizedPNL(true, undefined, marginCategory, strict, liquidationBuffer));
734
+ }
735
+ getLiquidationBuffer() {
736
+ // if user being liq'd, can continue to be liq'd until total collateral above the margin requirement plus buffer
737
+ let liquidationBuffer = undefined;
738
+ if (this.isBeingLiquidated()) {
739
+ liquidationBuffer = new _1.BN(this.driftClient.getStateAccount().liquidationMarginBufferRatio);
740
+ }
741
+ return liquidationBuffer;
736
742
  }
737
743
  /**
738
744
  * calculates User Health by comparing total collateral and maint. margin requirement
@@ -1105,8 +1111,9 @@ class User {
1105
1111
  return netAssetValue.mul(numericConstants_1.TEN_THOUSAND).div(totalLiabilityValue);
1106
1112
  }
1107
1113
  canBeLiquidated() {
1108
- const totalCollateral = this.getTotalCollateral('Maintenance');
1109
- const marginRequirement = this.getMaintenanceMarginRequirement();
1114
+ const liquidationBuffer = this.getLiquidationBuffer();
1115
+ const totalCollateral = this.getTotalCollateral('Maintenance', undefined, undefined, liquidationBuffer);
1116
+ const marginRequirement = this.getMaintenanceMarginRequirement(liquidationBuffer);
1110
1117
  const canBeLiquidated = totalCollateral.lt(marginRequirement);
1111
1118
  return {
1112
1119
  canBeLiquidated,
@@ -508,7 +508,7 @@ exports.MainnetSpotMarkets = [
508
508
  pythLazerId: 9,
509
509
  },
510
510
  {
511
- symbol: 'JLP',
511
+ symbol: 'JLP-1',
512
512
  marketIndex: 33,
513
513
  poolId: 1,
514
514
  oracle: new web3_js_1.PublicKey('5Mb11e5rt1Sp6A286B145E4TmgMzsM2UX9nCF2vas5bs'),
@@ -520,7 +520,7 @@ exports.MainnetSpotMarkets = [
520
520
  launchTs: 1735255852000,
521
521
  },
522
522
  {
523
- symbol: 'USDC',
523
+ symbol: 'USDC-1',
524
524
  marketIndex: 34,
525
525
  poolId: 1,
526
526
  oracle: new web3_js_1.PublicKey('En8hkHLkRe9d9DraYmBTrus518BvmVH448YcvmrFM6Ce'),
@@ -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,