@drift-labs/sdk 2.35.1-beta.6 → 2.35.1-beta.8

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.35.1-beta.6
1
+ 2.35.1-beta.8
package/lib/dlob/DLOB.js CHANGED
@@ -491,11 +491,21 @@ class DLOB {
491
491
  }
492
492
  // All bids/asks that can expire
493
493
  // dont try to expire limit orders with tif as its inefficient use of blockspace
494
- const bidGenerators = [nodeLists.market.bid.getGenerator()];
495
- const askGenerators = [nodeLists.market.ask.getGenerator()];
494
+ const bidGenerators = [
495
+ nodeLists.takingLimit.bid.getGenerator(),
496
+ nodeLists.restingLimit.bid.getGenerator(),
497
+ nodeLists.floatingLimit.bid.getGenerator(),
498
+ nodeLists.market.bid.getGenerator(),
499
+ ];
500
+ const askGenerators = [
501
+ nodeLists.takingLimit.ask.getGenerator(),
502
+ nodeLists.restingLimit.ask.getGenerator(),
503
+ nodeLists.floatingLimit.ask.getGenerator(),
504
+ nodeLists.market.ask.getGenerator(),
505
+ ];
496
506
  for (const bidGenerator of bidGenerators) {
497
507
  for (const bid of bidGenerator) {
498
- if ((0, __1.isOrderExpired)(bid.order, ts)) {
508
+ if ((0, __1.isOrderExpired)(bid.order, ts, true)) {
499
509
  nodesToFill.push({
500
510
  node: bid,
501
511
  makerNodes: [],
@@ -505,7 +515,7 @@ class DLOB {
505
515
  }
506
516
  for (const askGenerator of askGenerators) {
507
517
  for (const ask of askGenerator) {
508
- if ((0, __1.isOrderExpired)(ask.order, ts)) {
518
+ if ((0, __1.isOrderExpired)(ask.order, ts, true)) {
509
519
  nodesToFill.push({
510
520
  node: ask,
511
521
  makerNodes: [],
@@ -13,7 +13,7 @@ export declare function hasAuctionPrice(order: Order, slot: number): boolean;
13
13
  export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number): boolean;
14
14
  export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
15
15
  export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
16
- export declare function isOrderExpired(order: Order, ts: number): boolean;
16
+ export declare function isOrderExpired(order: Order, ts: number, enforceBuffer?: boolean): boolean;
17
17
  export declare function isMarketOrder(order: Order): boolean;
18
18
  export declare function isLimitOrder(order: Order): boolean;
19
19
  export declare function mustBeTriggered(order: Order): boolean;
@@ -168,13 +168,20 @@ function isSameDirection(firstDirection, secondDirection) {
168
168
  return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
169
169
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
170
170
  }
171
- function isOrderExpired(order, ts) {
171
+ function isOrderExpired(order, ts, enforceBuffer = false) {
172
172
  if (mustBeTriggered(order) ||
173
173
  !(0, types_1.isVariant)(order.status, 'open') ||
174
174
  order.maxTs.eq(numericConstants_1.ZERO)) {
175
175
  return false;
176
176
  }
177
- return new anchor_1.BN(ts).gt(order.maxTs);
177
+ let maxTs;
178
+ if (enforceBuffer && isLimitOrder(order)) {
179
+ maxTs = order.maxTs.addn(15);
180
+ }
181
+ else {
182
+ maxTs = order.maxTs;
183
+ }
184
+ return new anchor_1.BN(ts).gt(maxTs);
178
185
  }
179
186
  exports.isOrderExpired = isOrderExpired;
180
187
  function isMarketOrder(order) {
package/lib/user.d.ts CHANGED
@@ -98,7 +98,7 @@ export declare class User {
98
98
  * calculates Buying Power = free collateral / initial margin ratio
99
99
  * @returns : Precision QUOTE_PRECISION
100
100
  */
101
- getPerpBuyingPower(marketIndex: number): BN;
101
+ getPerpBuyingPower(marketIndex: number, collateralBuffer?: any): BN;
102
102
  getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex: number, freeCollateral: BN, baseAssetAmount: BN): BN;
103
103
  /**
104
104
  * calculates Free Collateral = Total collateral - initial margin requirement
@@ -191,10 +191,11 @@ export declare class User {
191
191
  /**
192
192
  * calculates max allowable leverage exceeding hitting requirement category
193
193
  * for large sizes where imf factor activates, result is a lower bound
194
- * @params category {Initial, Maintenance}
194
+ * @param marginCategory {Initial, Maintenance}
195
+ * @param isLp if calculating max leveraging for adding lp, need to add buffer
195
196
  * @returns : Precision TEN_THOUSAND
196
197
  */
197
- getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory): BN;
198
+ getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory, isLp?: boolean): BN;
198
199
  /**
199
200
  * calculates max allowable leverage exceeding hitting requirement category
200
201
  * @param spotMarketIndex
@@ -262,7 +263,7 @@ export declare class User {
262
263
  * @param tradeSide
263
264
  * @returns tradeSizeAllowed : Precision QUOTE_PRECISION
264
265
  */
265
- getMaxTradeSizeUSDCForPerp(targetMarketIndex: number, tradeSide: PositionDirection): BN;
266
+ getMaxTradeSizeUSDCForPerp(targetMarketIndex: number, tradeSide: PositionDirection, isLp?: boolean): BN;
266
267
  /**
267
268
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
268
269
  *
package/lib/user.js CHANGED
@@ -363,12 +363,12 @@ class User {
363
363
  * calculates Buying Power = free collateral / initial margin ratio
364
364
  * @returns : Precision QUOTE_PRECISION
365
365
  */
366
- getPerpBuyingPower(marketIndex) {
366
+ getPerpBuyingPower(marketIndex, collateralBuffer = numericConstants_1.ZERO) {
367
367
  const perpPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, true)[0];
368
368
  const worstCaseBaseAssetAmount = perpPosition
369
369
  ? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
370
370
  : numericConstants_1.ZERO;
371
- const freeCollateral = this.getFreeCollateral();
371
+ const freeCollateral = this.getFreeCollateral().sub(collateralBuffer);
372
372
  return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
373
373
  }
374
374
  getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
@@ -818,10 +818,11 @@ class User {
818
818
  /**
819
819
  * calculates max allowable leverage exceeding hitting requirement category
820
820
  * for large sizes where imf factor activates, result is a lower bound
821
- * @params category {Initial, Maintenance}
821
+ * @param marginCategory {Initial, Maintenance}
822
+ * @param isLp if calculating max leveraging for adding lp, need to add buffer
822
823
  * @returns : Precision TEN_THOUSAND
823
824
  */
824
- getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial') {
825
+ getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial', isLp = false) {
825
826
  const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
826
827
  const marketPrice = this.driftClient.getOracleDataForPerpMarket(perpMarketIndex).price;
827
828
  const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
@@ -831,7 +832,10 @@ class User {
831
832
  return numericConstants_1.ZERO;
832
833
  }
833
834
  const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
834
- const freeCollateral = this.getFreeCollateral();
835
+ const lpBuffer = isLp
836
+ ? marketPrice.mul(market.amm.orderStepSize).div(numericConstants_1.AMM_RESERVE_PRECISION)
837
+ : numericConstants_1.ZERO;
838
+ const freeCollateral = this.getFreeCollateral().sub(lpBuffer);
835
839
  let rawMarginRatio;
836
840
  switch (marginCategory) {
837
841
  case 'Initial':
@@ -1145,7 +1149,7 @@ class User {
1145
1149
  * @param tradeSide
1146
1150
  * @returns tradeSizeAllowed : Precision QUOTE_PRECISION
1147
1151
  */
1148
- getMaxTradeSizeUSDCForPerp(targetMarketIndex, tradeSide) {
1152
+ getMaxTradeSizeUSDCForPerp(targetMarketIndex, tradeSide, isLp = false) {
1149
1153
  const currentPosition = this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
1150
1154
  this.getEmptyPosition(targetMarketIndex);
1151
1155
  const targetSide = (0, types_1.isVariant)(tradeSide, 'short') ? 'short' : 'long';
@@ -1156,11 +1160,17 @@ class User {
1156
1160
  ? true
1157
1161
  : targetSide === currentPositionSide;
1158
1162
  const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
1163
+ const marketAccount = this.driftClient.getPerpMarketAccount(targetMarketIndex);
1164
+ const lpBuffer = isLp
1165
+ ? oracleData.price
1166
+ .mul(marketAccount.amm.orderStepSize)
1167
+ .div(numericConstants_1.AMM_RESERVE_PRECISION)
1168
+ : numericConstants_1.ZERO;
1159
1169
  // add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
1160
1170
  const oppositeSizeValueUSDC = targetingSameSide
1161
1171
  ? numericConstants_1.ZERO
1162
1172
  : this.getPerpPositionValue(targetMarketIndex, oracleData);
1163
- let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex);
1173
+ let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex, lpBuffer);
1164
1174
  if (maxPositionSize.gte(numericConstants_1.ZERO)) {
1165
1175
  if (oppositeSizeValueUSDC.eq(numericConstants_1.ZERO)) {
1166
1176
  // case 1 : Regular trade where current total position less than max, and no opposite position to account for
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.35.1-beta.6",
3
+ "version": "2.35.1-beta.8",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/dlob/DLOB.ts CHANGED
@@ -931,12 +931,22 @@ export class DLOB {
931
931
 
932
932
  // All bids/asks that can expire
933
933
  // dont try to expire limit orders with tif as its inefficient use of blockspace
934
- const bidGenerators = [nodeLists.market.bid.getGenerator()];
935
- const askGenerators = [nodeLists.market.ask.getGenerator()];
934
+ const bidGenerators = [
935
+ nodeLists.takingLimit.bid.getGenerator(),
936
+ nodeLists.restingLimit.bid.getGenerator(),
937
+ nodeLists.floatingLimit.bid.getGenerator(),
938
+ nodeLists.market.bid.getGenerator(),
939
+ ];
940
+ const askGenerators = [
941
+ nodeLists.takingLimit.ask.getGenerator(),
942
+ nodeLists.restingLimit.ask.getGenerator(),
943
+ nodeLists.floatingLimit.ask.getGenerator(),
944
+ nodeLists.market.ask.getGenerator(),
945
+ ];
936
946
 
937
947
  for (const bidGenerator of bidGenerators) {
938
948
  for (const bid of bidGenerator) {
939
- if (isOrderExpired(bid.order, ts)) {
949
+ if (isOrderExpired(bid.order, ts, true)) {
940
950
  nodesToFill.push({
941
951
  node: bid,
942
952
  makerNodes: [],
@@ -947,7 +957,7 @@ export class DLOB {
947
957
 
948
958
  for (const askGenerator of askGenerators) {
949
959
  for (const ask of askGenerator) {
950
- if (isOrderExpired(ask.order, ts)) {
960
+ if (isOrderExpired(ask.order, ts, true)) {
951
961
  nodesToFill.push({
952
962
  node: ask,
953
963
  makerNodes: [],
@@ -279,7 +279,11 @@ function isSameDirection(
279
279
  );
280
280
  }
281
281
 
282
- export function isOrderExpired(order: Order, ts: number): boolean {
282
+ export function isOrderExpired(
283
+ order: Order,
284
+ ts: number,
285
+ enforceBuffer = false
286
+ ): boolean {
283
287
  if (
284
288
  mustBeTriggered(order) ||
285
289
  !isVariant(order.status, 'open') ||
@@ -288,7 +292,14 @@ export function isOrderExpired(order: Order, ts: number): boolean {
288
292
  return false;
289
293
  }
290
294
 
291
- return new BN(ts).gt(order.maxTs);
295
+ let maxTs;
296
+ if (enforceBuffer && isLimitOrder(order)) {
297
+ maxTs = order.maxTs.addn(15);
298
+ } else {
299
+ maxTs = order.maxTs;
300
+ }
301
+
302
+ return new BN(ts).gt(maxTs);
292
303
  }
293
304
 
294
305
  export function isMarketOrder(order: Order): boolean {
package/src/user.ts CHANGED
@@ -558,7 +558,7 @@ export class User {
558
558
  * calculates Buying Power = free collateral / initial margin ratio
559
559
  * @returns : Precision QUOTE_PRECISION
560
560
  */
561
- public getPerpBuyingPower(marketIndex: number): BN {
561
+ public getPerpBuyingPower(marketIndex: number, collateralBuffer = ZERO): BN {
562
562
  const perpPosition = this.getPerpPositionWithLPSettle(
563
563
  marketIndex,
564
564
  undefined,
@@ -568,7 +568,7 @@ export class User {
568
568
  ? calculateWorstCaseBaseAssetAmount(perpPosition)
569
569
  : ZERO;
570
570
 
571
- const freeCollateral = this.getFreeCollateral();
571
+ const freeCollateral = this.getFreeCollateral().sub(collateralBuffer);
572
572
 
573
573
  return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(
574
574
  marketIndex,
@@ -1490,12 +1490,14 @@ export class User {
1490
1490
  /**
1491
1491
  * calculates max allowable leverage exceeding hitting requirement category
1492
1492
  * for large sizes where imf factor activates, result is a lower bound
1493
- * @params category {Initial, Maintenance}
1493
+ * @param marginCategory {Initial, Maintenance}
1494
+ * @param isLp if calculating max leveraging for adding lp, need to add buffer
1494
1495
  * @returns : Precision TEN_THOUSAND
1495
1496
  */
1496
1497
  public getMaxLeverageForPerp(
1497
1498
  perpMarketIndex: number,
1498
- marginCategory: MarginCategory = 'Initial'
1499
+ marginCategory: MarginCategory = 'Initial',
1500
+ isLp = false
1499
1501
  ): BN {
1500
1502
  const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
1501
1503
  const marketPrice =
@@ -1514,7 +1516,11 @@ export class User {
1514
1516
 
1515
1517
  const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
1516
1518
 
1517
- const freeCollateral = this.getFreeCollateral();
1519
+ const lpBuffer = isLp
1520
+ ? marketPrice.mul(market.amm.orderStepSize).div(AMM_RESERVE_PRECISION)
1521
+ : ZERO;
1522
+
1523
+ const freeCollateral = this.getFreeCollateral().sub(lpBuffer);
1518
1524
 
1519
1525
  let rawMarginRatio;
1520
1526
 
@@ -2059,7 +2065,8 @@ export class User {
2059
2065
  */
2060
2066
  public getMaxTradeSizeUSDCForPerp(
2061
2067
  targetMarketIndex: number,
2062
- tradeSide: PositionDirection
2068
+ tradeSide: PositionDirection,
2069
+ isLp = false
2063
2070
  ): BN {
2064
2071
  const currentPosition =
2065
2072
  this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
@@ -2077,12 +2084,21 @@ export class User {
2077
2084
 
2078
2085
  const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
2079
2086
 
2087
+ const marketAccount =
2088
+ this.driftClient.getPerpMarketAccount(targetMarketIndex);
2089
+
2090
+ const lpBuffer = isLp
2091
+ ? oracleData.price
2092
+ .mul(marketAccount.amm.orderStepSize)
2093
+ .div(AMM_RESERVE_PRECISION)
2094
+ : ZERO;
2095
+
2080
2096
  // add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
2081
2097
  const oppositeSizeValueUSDC = targetingSameSide
2082
2098
  ? ZERO
2083
2099
  : this.getPerpPositionValue(targetMarketIndex, oracleData);
2084
2100
 
2085
- let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex);
2101
+ let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex, lpBuffer);
2086
2102
  if (maxPositionSize.gte(ZERO)) {
2087
2103
  if (oppositeSizeValueUSDC.eq(ZERO)) {
2088
2104
  // case 1 : Regular trade where current total position less than max, and no opposite position to account for