@drift-labs/sdk 2.1.2 → 2.2.0-beta.1

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/lib/dlob/DLOB.js CHANGED
@@ -4,6 +4,13 @@ exports.DLOB = void 0;
4
4
  const NodeList_1 = require("./NodeList");
5
5
  const __1 = require("..");
6
6
  const exchangeStatus_1 = require("../math/exchangeStatus");
7
+ const SUPPORTED_ORDER_TYPES = [
8
+ 'market',
9
+ 'limit',
10
+ 'triggerMarket',
11
+ 'triggerLimit',
12
+ 'oracle',
13
+ ];
7
14
  class DLOB {
8
15
  constructor() {
9
16
  this.openOrders = new Map();
@@ -118,6 +125,9 @@ class DLOB {
118
125
  if ((0, __1.isVariant)(order.status, 'init')) {
119
126
  return;
120
127
  }
128
+ if (!(0, __1.isOneOfVariant)(order.orderType, SUPPORTED_ORDER_TYPES)) {
129
+ return;
130
+ }
121
131
  const marketType = (0, __1.getVariant)(order.marketType);
122
132
  if (!this.orderLists.get(marketType).has(order.marketIndex)) {
123
133
  this.addOrderList(marketType, order.marketIndex);
@@ -200,7 +210,7 @@ class DLOB {
200
210
  if (isInactiveTriggerOrder) {
201
211
  type = 'trigger';
202
212
  }
203
- else if ((0, __1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
213
+ else if ((0, __1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket', 'oracle'])) {
204
214
  type = 'market';
205
215
  }
206
216
  else if (order.oraclePriceOffset !== 0) {
@@ -2,4 +2,6 @@
2
2
  import { Order } from '../types';
3
3
  import { BN } from '../.';
4
4
  export declare function isAuctionComplete(order: Order, slot: number): boolean;
5
- export declare function getAuctionPrice(order: Order, slot: number): BN;
5
+ export declare function getAuctionPrice(order: Order, slot: number, oraclePrice: BN): BN;
6
+ export declare function getAuctionPriceForFixedAuction(order: Order, slot: number): BN;
7
+ export declare function getAuctionPriceForOracleOffsetAuction(order: Order, slot: number, oraclePrice: BN): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAuctionPrice = exports.isAuctionComplete = void 0;
3
+ exports.getAuctionPriceForOracleOffsetAuction = exports.getAuctionPriceForFixedAuction = exports.getAuctionPrice = exports.isAuctionComplete = void 0;
4
4
  const types_1 = require("../types");
5
5
  const _1 = require("../.");
6
6
  function isAuctionComplete(order, slot) {
@@ -10,7 +10,19 @@ function isAuctionComplete(order, slot) {
10
10
  return new _1.BN(slot).sub(order.slot).gt(new _1.BN(order.auctionDuration));
11
11
  }
12
12
  exports.isAuctionComplete = isAuctionComplete;
13
- function getAuctionPrice(order, slot) {
13
+ function getAuctionPrice(order, slot, oraclePrice) {
14
+ if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
15
+ return getAuctionPriceForFixedAuction(order, slot);
16
+ }
17
+ else if ((0, types_1.isVariant)(order.orderType, 'oracle')) {
18
+ return getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice);
19
+ }
20
+ else {
21
+ throw Error(`Cant get auction price for order type ${order.orderType}`);
22
+ }
23
+ }
24
+ exports.getAuctionPrice = getAuctionPrice;
25
+ function getAuctionPriceForFixedAuction(order, slot) {
14
26
  const slotsElapsed = new _1.BN(slot).sub(order.slot);
15
27
  const deltaDenominator = new _1.BN(order.auctionDuration);
16
28
  const deltaNumerator = _1.BN.min(slotsElapsed, deltaDenominator);
@@ -39,4 +51,34 @@ function getAuctionPrice(order, slot) {
39
51
  }
40
52
  return price;
41
53
  }
42
- exports.getAuctionPrice = getAuctionPrice;
54
+ exports.getAuctionPriceForFixedAuction = getAuctionPriceForFixedAuction;
55
+ function getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice) {
56
+ const slotsElapsed = new _1.BN(slot).sub(order.slot);
57
+ const deltaDenominator = new _1.BN(order.auctionDuration);
58
+ const deltaNumerator = _1.BN.min(slotsElapsed, deltaDenominator);
59
+ if (deltaDenominator.eq(_1.ZERO)) {
60
+ return order.auctionEndPrice.add(order.auctionEndPrice);
61
+ }
62
+ let priceOffsetDelta;
63
+ if ((0, types_1.isVariant)(order.direction, 'long')) {
64
+ priceOffsetDelta = order.auctionEndPrice
65
+ .sub(order.auctionStartPrice)
66
+ .mul(deltaNumerator)
67
+ .div(deltaDenominator);
68
+ }
69
+ else {
70
+ priceOffsetDelta = order.auctionStartPrice
71
+ .sub(order.auctionEndPrice)
72
+ .mul(deltaNumerator)
73
+ .div(deltaDenominator);
74
+ }
75
+ let priceOffset;
76
+ if ((0, types_1.isVariant)(order.direction, 'long')) {
77
+ priceOffset = order.auctionStartPrice.add(priceOffsetDelta);
78
+ }
79
+ else {
80
+ priceOffset = order.auctionStartPrice.sub(priceOffsetDelta);
81
+ }
82
+ return oraclePrice.add(priceOffset);
83
+ }
84
+ exports.getAuctionPriceForOracleOffsetAuction = getAuctionPriceForOracleOffsetAuction;
@@ -9,6 +9,7 @@ export declare function isOrderReduceOnly(user: User, order: Order): boolean;
9
9
  export declare function standardizeBaseAssetAmount(baseAssetAmount: BN, stepSize: BN): BN;
10
10
  export declare function getLimitPrice(order: Order, oraclePriceData: OraclePriceData, slot: number, fallbackPrice?: BN): BN | undefined;
11
11
  export declare function hasLimitPrice(order: Order, slot: number): boolean;
12
+ export declare function hasAuctionPrice(order: Order, slot: number): boolean;
12
13
  export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number): boolean;
13
14
  export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
14
15
  export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasLimitPrice = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasAuctionPrice = exports.hasLimitPrice = exports.getLimitPrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
4
4
  const types_1 = require("../types");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const anchor_1 = require("@project-serum/anchor");
@@ -81,19 +81,14 @@ function standardizeBaseAssetAmount(baseAssetAmount, stepSize) {
81
81
  exports.standardizeBaseAssetAmount = standardizeBaseAssetAmount;
82
82
  function getLimitPrice(order, oraclePriceData, slot, fallbackPrice) {
83
83
  let limitPrice;
84
- if (order.oraclePriceOffset !== 0) {
84
+ if (hasAuctionPrice(order, slot)) {
85
+ limitPrice = (0, auction_1.getAuctionPrice)(order, slot, oraclePriceData.price);
86
+ }
87
+ else if (order.oraclePriceOffset !== 0) {
85
88
  limitPrice = oraclePriceData.price.add(new anchor_1.BN(order.oraclePriceOffset));
86
89
  }
87
- else if ((0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket'])) {
88
- if (!(0, auction_1.isAuctionComplete)(order, slot)) {
89
- limitPrice = (0, auction_1.getAuctionPrice)(order, slot);
90
- }
91
- else if (!order.price.eq(numericConstants_1.ZERO)) {
92
- limitPrice = order.price;
93
- }
94
- else {
95
- limitPrice = fallbackPrice;
96
- }
90
+ else if (order.price.eq(numericConstants_1.ZERO)) {
91
+ limitPrice = fallbackPrice;
97
92
  }
98
93
  else {
99
94
  limitPrice = order.price;
@@ -107,6 +102,10 @@ function hasLimitPrice(order, slot) {
107
102
  !(0, auction_1.isAuctionComplete)(order, slot));
108
103
  }
109
104
  exports.hasLimitPrice = hasLimitPrice;
105
+ function hasAuctionPrice(order, slot) {
106
+ return isMarketOrder(order) && !(0, auction_1.isAuctionComplete)(order, slot);
107
+ }
108
+ exports.hasAuctionPrice = hasAuctionPrice;
110
109
  function isFillableByVAMM(order, market, oraclePriceData, slot, ts) {
111
110
  return (((0, auction_1.isAuctionComplete)(order, slot) &&
112
111
  !calculateBaseAssetAmountForAmmToFulfill(order, market, oraclePriceData, slot).eq(numericConstants_1.ZERO)) ||
@@ -149,7 +148,7 @@ function isSameDirection(firstDirection, secondDirection) {
149
148
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
150
149
  }
151
150
  function isOrderExpired(order, ts) {
152
- if ((0, types_1.isOneOfVariant)(order.orderType, ['triggerMarket', 'triggerLimit']) ||
151
+ if (mustBeTriggered(order) ||
153
152
  !(0, types_1.isVariant)(order.status, 'open') ||
154
153
  order.maxTs.eq(numericConstants_1.ZERO)) {
155
154
  return false;
@@ -158,7 +157,7 @@ function isOrderExpired(order, ts) {
158
157
  }
159
158
  exports.isOrderExpired = isOrderExpired;
160
159
  function isMarketOrder(order) {
161
- return (0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket']);
160
+ return (0, types_1.isOneOfVariant)(order.orderType, ['market', 'triggerMarket', 'oracle']);
162
161
  }
163
162
  exports.isMarketOrder = isMarketOrder;
164
163
  function isLimitOrder(order) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.1.2",
3
+ "version": "2.2.0-beta.1",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/dlob/DLOB.ts CHANGED
@@ -62,6 +62,14 @@ export type NodeToTrigger = {
62
62
  node: TriggerOrderNode;
63
63
  };
64
64
 
65
+ const SUPPORTED_ORDER_TYPES = [
66
+ 'market',
67
+ 'limit',
68
+ 'triggerMarket',
69
+ 'triggerLimit',
70
+ 'oracle',
71
+ ];
72
+
65
73
  export class DLOB {
66
74
  openOrders = new Map<MarketTypeStr, Set<string>>();
67
75
  orderLists = new Map<MarketTypeStr, Map<number, MarketNodeLists>>();
@@ -204,6 +212,10 @@ export class DLOB {
204
212
  return;
205
213
  }
206
214
 
215
+ if (!isOneOfVariant(order.orderType, SUPPORTED_ORDER_TYPES)) {
216
+ return;
217
+ }
218
+
207
219
  const marketType = getVariant(order.marketType) as MarketTypeStr;
208
220
 
209
221
  if (!this.orderLists.get(marketType).has(order.marketIndex)) {
@@ -313,7 +325,9 @@ export class DLOB {
313
325
  let type: DLOBNodeType;
314
326
  if (isInactiveTriggerOrder) {
315
327
  type = 'trigger';
316
- } else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
328
+ } else if (
329
+ isOneOfVariant(order.orderType, ['market', 'triggerMarket', 'oracle'])
330
+ ) {
317
331
  type = 'market';
318
332
  } else if (order.oraclePriceOffset !== 0) {
319
333
  type = 'floatingLimit';
@@ -1,4 +1,4 @@
1
- import { isVariant, Order } from '../types';
1
+ import { isOneOfVariant, isVariant, Order } from '../types';
2
2
  import { BN, ZERO } from '../.';
3
3
 
4
4
  export function isAuctionComplete(order: Order, slot: number): boolean {
@@ -9,7 +9,21 @@ export function isAuctionComplete(order: Order, slot: number): boolean {
9
9
  return new BN(slot).sub(order.slot).gt(new BN(order.auctionDuration));
10
10
  }
11
11
 
12
- export function getAuctionPrice(order: Order, slot: number): BN {
12
+ export function getAuctionPrice(
13
+ order: Order,
14
+ slot: number,
15
+ oraclePrice: BN
16
+ ): BN {
17
+ if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
18
+ return getAuctionPriceForFixedAuction(order, slot);
19
+ } else if (isVariant(order.orderType, 'oracle')) {
20
+ return getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice);
21
+ } else {
22
+ throw Error(`Cant get auction price for order type ${order.orderType}`);
23
+ }
24
+ }
25
+
26
+ export function getAuctionPriceForFixedAuction(order: Order, slot: number): BN {
13
27
  const slotsElapsed = new BN(slot).sub(order.slot);
14
28
 
15
29
  const deltaDenominator = new BN(order.auctionDuration);
@@ -41,3 +55,40 @@ export function getAuctionPrice(order: Order, slot: number): BN {
41
55
 
42
56
  return price;
43
57
  }
58
+
59
+ export function getAuctionPriceForOracleOffsetAuction(
60
+ order: Order,
61
+ slot: number,
62
+ oraclePrice: BN
63
+ ): BN {
64
+ const slotsElapsed = new BN(slot).sub(order.slot);
65
+
66
+ const deltaDenominator = new BN(order.auctionDuration);
67
+ const deltaNumerator = BN.min(slotsElapsed, deltaDenominator);
68
+
69
+ if (deltaDenominator.eq(ZERO)) {
70
+ return order.auctionEndPrice.add(order.auctionEndPrice);
71
+ }
72
+
73
+ let priceOffsetDelta;
74
+ if (isVariant(order.direction, 'long')) {
75
+ priceOffsetDelta = order.auctionEndPrice
76
+ .sub(order.auctionStartPrice)
77
+ .mul(deltaNumerator)
78
+ .div(deltaDenominator);
79
+ } else {
80
+ priceOffsetDelta = order.auctionStartPrice
81
+ .sub(order.auctionEndPrice)
82
+ .mul(deltaNumerator)
83
+ .div(deltaDenominator);
84
+ }
85
+
86
+ let priceOffset;
87
+ if (isVariant(order.direction, 'long')) {
88
+ priceOffset = order.auctionStartPrice.add(priceOffsetDelta);
89
+ } else {
90
+ priceOffset = order.auctionStartPrice.sub(priceOffsetDelta);
91
+ }
92
+
93
+ return oraclePrice.add(priceOffset);
94
+ }
@@ -131,16 +131,12 @@ export function getLimitPrice(
131
131
  fallbackPrice?: BN
132
132
  ): BN | undefined {
133
133
  let limitPrice;
134
- if (order.oraclePriceOffset !== 0) {
134
+ if (hasAuctionPrice(order, slot)) {
135
+ limitPrice = getAuctionPrice(order, slot, oraclePriceData.price);
136
+ } else if (order.oraclePriceOffset !== 0) {
135
137
  limitPrice = oraclePriceData.price.add(new BN(order.oraclePriceOffset));
136
- } else if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
137
- if (!isAuctionComplete(order, slot)) {
138
- limitPrice = getAuctionPrice(order, slot);
139
- } else if (!order.price.eq(ZERO)) {
140
- limitPrice = order.price;
141
- } else {
142
- limitPrice = fallbackPrice;
143
- }
138
+ } else if (order.price.eq(ZERO)) {
139
+ limitPrice = fallbackPrice;
144
140
  } else {
145
141
  limitPrice = order.price;
146
142
  }
@@ -156,6 +152,10 @@ export function hasLimitPrice(order: Order, slot: number): boolean {
156
152
  );
157
153
  }
158
154
 
155
+ export function hasAuctionPrice(order: Order, slot: number): boolean {
156
+ return isMarketOrder(order) && !isAuctionComplete(order, slot);
157
+ }
158
+
159
159
  export function isFillableByVAMM(
160
160
  order: Order,
161
161
  market: PerpMarketAccount,
@@ -252,7 +252,7 @@ function isSameDirection(
252
252
 
253
253
  export function isOrderExpired(order: Order, ts: number): boolean {
254
254
  if (
255
- isOneOfVariant(order.orderType, ['triggerMarket', 'triggerLimit']) ||
255
+ mustBeTriggered(order) ||
256
256
  !isVariant(order.status, 'open') ||
257
257
  order.maxTs.eq(ZERO)
258
258
  ) {
@@ -263,7 +263,7 @@ export function isOrderExpired(order: Order, ts: number): boolean {
263
263
  }
264
264
 
265
265
  export function isMarketOrder(order: Order): boolean {
266
- return isOneOfVariant(order.orderType, ['market', 'triggerMarket']);
266
+ return isOneOfVariant(order.orderType, ['market', 'triggerMarket', 'oracle']);
267
267
  }
268
268
 
269
269
  export function isLimitOrder(order: Order): boolean {