@drift-labs/sdk 2.143.0-beta.1 → 2.143.0-beta.2

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.143.0-beta.1
1
+ 2.143.0-beta.2
@@ -25,3 +25,12 @@ export declare function isTakingOrder(order: Order, slot: number): boolean;
25
25
  export declare function isSignedMsgOrder(order: Order): boolean;
26
26
  export declare function hasBuilder(order: Order): boolean;
27
27
  export declare function calculateOrderBaseAssetAmount(order: Order, existingBaseAssetAmount: BN): BN;
28
+ /**
29
+ * Invert the size-premium liability weight: given a target margin ratio (liability weight),
30
+ * return the max `size` (AMM_RESERVE_PRECISION units) that still yields <= target.
31
+ *
32
+ * Returns:
33
+ * - BN size (>=0) if bounded
34
+ * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
35
+ */
36
+ export declare function maxSizeForTargetLiabilityWeightBN(target: BN, imfFactor: BN, liabilityWeight: BN): BN | null;
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateOrderBaseAssetAmount = exports.hasBuilder = exports.isSignedMsgOrder = exports.isTakingOrder = exports.isRestingLimitOrder = exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasAuctionPrice = exports.hasLimitPrice = exports.applyProtectedMakerParams = exports.getLimitPrice = exports.standardizePrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.maxSizeForTargetLiabilityWeightBN = exports.calculateOrderBaseAssetAmount = exports.hasBuilder = exports.isSignedMsgOrder = exports.isTakingOrder = exports.isRestingLimitOrder = exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasAuctionPrice = exports.hasLimitPrice = exports.applyProtectedMakerParams = exports.getLimitPrice = exports.standardizePrice = 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("@coral-xyz/anchor");
7
7
  const auction_1 = require("./auction");
8
8
  const amm_1 = require("./amm");
9
+ const margin_1 = require("./margin");
9
10
  function isOrderRiskIncreasing(user, order) {
10
11
  if (!(0, types_1.isVariant)(order.status, 'open')) {
11
12
  return false;
@@ -257,3 +258,45 @@ function calculateOrderBaseAssetAmount(order, existingBaseAssetAmount) {
257
258
  }
258
259
  }
259
260
  exports.calculateOrderBaseAssetAmount = calculateOrderBaseAssetAmount;
261
+ // ---------- inverse ----------
262
+ /**
263
+ * Invert the size-premium liability weight: given a target margin ratio (liability weight),
264
+ * return the max `size` (AMM_RESERVE_PRECISION units) that still yields <= target.
265
+ *
266
+ * Returns:
267
+ * - BN size (>=0) if bounded
268
+ * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
269
+ */
270
+ function maxSizeForTargetLiabilityWeightBN(target, imfFactor, liabilityWeight) {
271
+ if (target.lt(liabilityWeight))
272
+ return null;
273
+ if (imfFactor.isZero())
274
+ return null;
275
+ const base = liabilityWeight.muln(4).divn(5);
276
+ const denom = new anchor_1.BN(100000)
277
+ .mul(numericConstants_1.SPOT_MARKET_IMF_PRECISION)
278
+ .div(numericConstants_1.MARGIN_PRECISION);
279
+ if (denom.isZero())
280
+ throw new Error('denom=0: bad precision/spotImfPrecision');
281
+ const allowedInc = target.gt(base) ? target.sub(base) : numericConstants_1.ZERO;
282
+ const maxSqrt = allowedInc.mul(denom).div(imfFactor);
283
+ if (maxSqrt.lte(numericConstants_1.ZERO)) {
284
+ const fitsZero = (0, margin_1.calculateSizePremiumLiabilityWeight)(numericConstants_1.ZERO, imfFactor, liabilityWeight, numericConstants_1.MARGIN_PRECISION).lte(target);
285
+ return fitsZero ? numericConstants_1.ZERO : null;
286
+ }
287
+ let hi = maxSqrt.mul(maxSqrt).sub(numericConstants_1.ONE).divn(10);
288
+ if (hi.isNeg())
289
+ hi = numericConstants_1.ZERO;
290
+ let lo = numericConstants_1.ZERO;
291
+ while (lo.lt(hi)) {
292
+ const mid = lo.add(hi).add(numericConstants_1.ONE).divn(2); // upper mid to prevent infinite loop
293
+ if ((0, margin_1.calculateSizePremiumLiabilityWeight)(mid, imfFactor, liabilityWeight, numericConstants_1.MARGIN_PRECISION).lte(target)) {
294
+ lo = mid;
295
+ }
296
+ else {
297
+ hi = mid.sub(numericConstants_1.ONE);
298
+ }
299
+ }
300
+ return lo;
301
+ }
302
+ exports.maxSizeForTargetLiabilityWeightBN = maxSizeForTargetLiabilityWeightBN;
@@ -25,4 +25,13 @@ export declare function isTakingOrder(order: Order, slot: number): boolean;
25
25
  export declare function isSignedMsgOrder(order: Order): boolean;
26
26
  export declare function hasBuilder(order: Order): boolean;
27
27
  export declare function calculateOrderBaseAssetAmount(order: Order, existingBaseAssetAmount: BN): BN;
28
+ /**
29
+ * Invert the size-premium liability weight: given a target margin ratio (liability weight),
30
+ * return the max `size` (AMM_RESERVE_PRECISION units) that still yields <= target.
31
+ *
32
+ * Returns:
33
+ * - BN size (>=0) if bounded
34
+ * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
35
+ */
36
+ export declare function maxSizeForTargetLiabilityWeightBN(target: BN, imfFactor: BN, liabilityWeight: BN): BN | null;
28
37
  //# sourceMappingURL=orders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../../src/math/orders.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orders.d.ts","sourceRoot":"","sources":["../../../src/math/orders.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateOrderBaseAssetAmount = exports.hasBuilder = exports.isSignedMsgOrder = exports.isTakingOrder = exports.isRestingLimitOrder = exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasAuctionPrice = exports.hasLimitPrice = exports.applyProtectedMakerParams = exports.getLimitPrice = exports.standardizePrice = exports.standardizeBaseAssetAmount = exports.isOrderReduceOnly = exports.isOrderRiskIncreasingInSameDirection = exports.isOrderRiskIncreasing = void 0;
3
+ exports.maxSizeForTargetLiabilityWeightBN = exports.calculateOrderBaseAssetAmount = exports.hasBuilder = exports.isSignedMsgOrder = exports.isTakingOrder = exports.isRestingLimitOrder = exports.isTriggered = exports.mustBeTriggered = exports.isLimitOrder = exports.isMarketOrder = exports.isOrderExpired = exports.calculateBaseAssetAmountToFillUpToLimitPrice = exports.calculateBaseAssetAmountForAmmToFulfill = exports.isFillableByVAMM = exports.hasAuctionPrice = exports.hasLimitPrice = exports.applyProtectedMakerParams = exports.getLimitPrice = exports.standardizePrice = 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("@coral-xyz/anchor");
7
7
  const auction_1 = require("./auction");
8
8
  const amm_1 = require("./amm");
9
+ const margin_1 = require("./margin");
9
10
  function isOrderRiskIncreasing(user, order) {
10
11
  if (!(0, types_1.isVariant)(order.status, 'open')) {
11
12
  return false;
@@ -257,3 +258,45 @@ function calculateOrderBaseAssetAmount(order, existingBaseAssetAmount) {
257
258
  }
258
259
  }
259
260
  exports.calculateOrderBaseAssetAmount = calculateOrderBaseAssetAmount;
261
+ // ---------- inverse ----------
262
+ /**
263
+ * Invert the size-premium liability weight: given a target margin ratio (liability weight),
264
+ * return the max `size` (AMM_RESERVE_PRECISION units) that still yields <= target.
265
+ *
266
+ * Returns:
267
+ * - BN size (>=0) if bounded
268
+ * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
269
+ */
270
+ function maxSizeForTargetLiabilityWeightBN(target, imfFactor, liabilityWeight) {
271
+ if (target.lt(liabilityWeight))
272
+ return null;
273
+ if (imfFactor.isZero())
274
+ return null;
275
+ const base = liabilityWeight.muln(4).divn(5);
276
+ const denom = new anchor_1.BN(100000)
277
+ .mul(numericConstants_1.SPOT_MARKET_IMF_PRECISION)
278
+ .div(numericConstants_1.MARGIN_PRECISION);
279
+ if (denom.isZero())
280
+ throw new Error('denom=0: bad precision/spotImfPrecision');
281
+ const allowedInc = target.gt(base) ? target.sub(base) : numericConstants_1.ZERO;
282
+ const maxSqrt = allowedInc.mul(denom).div(imfFactor);
283
+ if (maxSqrt.lte(numericConstants_1.ZERO)) {
284
+ const fitsZero = (0, margin_1.calculateSizePremiumLiabilityWeight)(numericConstants_1.ZERO, imfFactor, liabilityWeight, numericConstants_1.MARGIN_PRECISION).lte(target);
285
+ return fitsZero ? numericConstants_1.ZERO : null;
286
+ }
287
+ let hi = maxSqrt.mul(maxSqrt).sub(numericConstants_1.ONE).divn(10);
288
+ if (hi.isNeg())
289
+ hi = numericConstants_1.ZERO;
290
+ let lo = numericConstants_1.ZERO;
291
+ while (lo.lt(hi)) {
292
+ const mid = lo.add(hi).add(numericConstants_1.ONE).divn(2); // upper mid to prevent infinite loop
293
+ if ((0, margin_1.calculateSizePremiumLiabilityWeight)(mid, imfFactor, liabilityWeight, numericConstants_1.MARGIN_PRECISION).lte(target)) {
294
+ lo = mid;
295
+ }
296
+ else {
297
+ hi = mid.sub(numericConstants_1.ONE);
298
+ }
299
+ }
300
+ return lo;
301
+ }
302
+ exports.maxSizeForTargetLiabilityWeightBN = maxSizeForTargetLiabilityWeightBN;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.143.0-beta.1",
3
+ "version": "2.143.0-beta.2",
4
4
  "main": "lib/node/index.js",
5
5
  "types": "lib/node/index.d.ts",
6
6
  "module": "./lib/browser/index.js",
@@ -9,7 +9,13 @@ import {
9
9
  ProtectedMakerParams,
10
10
  MarketTypeStr,
11
11
  } from '../types';
12
- import { ZERO, TWO, ONE } from '../constants/numericConstants';
12
+ import {
13
+ ZERO,
14
+ TWO,
15
+ ONE,
16
+ SPOT_MARKET_IMF_PRECISION,
17
+ MARGIN_PRECISION,
18
+ } from '../constants/numericConstants';
13
19
  import { BN } from '@coral-xyz/anchor';
14
20
  import { MMOraclePriceData, OraclePriceData } from '../oracles/types';
15
21
  import {
@@ -22,6 +28,7 @@ import {
22
28
  calculateMaxBaseAssetAmountToTrade,
23
29
  calculateUpdatedAMM,
24
30
  } from './amm';
31
+ import { calculateSizePremiumLiabilityWeight } from './margin';
25
32
 
26
33
  export function isOrderRiskIncreasing(user: User, order: Order): boolean {
27
34
  if (!isVariant(order.status, 'open')) {
@@ -411,3 +418,65 @@ export function calculateOrderBaseAssetAmount(
411
418
  return BN.min(BN.max(existingBaseAssetAmount, ZERO), order.baseAssetAmount);
412
419
  }
413
420
  }
421
+
422
+ // ---------- inverse ----------
423
+ /**
424
+ * Invert the size-premium liability weight: given a target margin ratio (liability weight),
425
+ * return the max `size` (AMM_RESERVE_PRECISION units) that still yields <= target.
426
+ *
427
+ * Returns:
428
+ * - BN size (>=0) if bounded
429
+ * - null if impossible (target < liabilityWeight) OR imfFactor == 0 (unbounded)
430
+ */
431
+ export function maxSizeForTargetLiabilityWeightBN(
432
+ target: BN,
433
+ imfFactor: BN,
434
+ liabilityWeight: BN
435
+ ): BN | null {
436
+ if (target.lt(liabilityWeight)) return null;
437
+ if (imfFactor.isZero()) return null;
438
+
439
+ const base = liabilityWeight.muln(4).divn(5);
440
+
441
+ const denom = new BN(100_000)
442
+ .mul(SPOT_MARKET_IMF_PRECISION)
443
+ .div(MARGIN_PRECISION);
444
+ if (denom.isZero())
445
+ throw new Error('denom=0: bad precision/spotImfPrecision');
446
+
447
+ const allowedInc = target.gt(base) ? target.sub(base) : ZERO;
448
+
449
+ const maxSqrt = allowedInc.mul(denom).div(imfFactor);
450
+
451
+ if (maxSqrt.lte(ZERO)) {
452
+ const fitsZero = calculateSizePremiumLiabilityWeight(
453
+ ZERO,
454
+ imfFactor,
455
+ liabilityWeight,
456
+ MARGIN_PRECISION
457
+ ).lte(target);
458
+ return fitsZero ? ZERO : null;
459
+ }
460
+
461
+ let hi = maxSqrt.mul(maxSqrt).sub(ONE).divn(10);
462
+ if (hi.isNeg()) hi = ZERO;
463
+
464
+ let lo = ZERO;
465
+ while (lo.lt(hi)) {
466
+ const mid = lo.add(hi).add(ONE).divn(2); // upper mid to prevent infinite loop
467
+ if (
468
+ calculateSizePremiumLiabilityWeight(
469
+ mid,
470
+ imfFactor,
471
+ liabilityWeight,
472
+ MARGIN_PRECISION
473
+ ).lte(target)
474
+ ) {
475
+ lo = mid;
476
+ } else {
477
+ hi = mid.sub(ONE);
478
+ }
479
+ }
480
+
481
+ return lo;
482
+ }