@drift-labs/sdk-browser 2.137.0-beta.0 → 2.137.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 +1 -1
- package/lib/browser/accounts/webSocketAccountSubscriberV2.d.ts +1 -1
- package/lib/browser/accounts/webSocketProgramAccountsSubscriberV2.d.ts +1 -1
- package/lib/browser/decode/user.js +3 -2
- package/lib/browser/driftClient.d.ts +2 -0
- package/lib/browser/driftClient.js +17 -0
- package/lib/browser/idl/drift.json +28 -175
- package/lib/browser/math/bankruptcy.js +1 -2
- package/lib/browser/types.d.ts +2 -0
- package/lib/browser/user.d.ts +2 -15
- package/lib/browser/user.js +29 -225
- package/lib/node/accounts/webSocketAccountSubscriberV2.d.ts +1 -1
- package/lib/node/accounts/webSocketAccountSubscriberV2.d.ts.map +1 -1
- package/lib/node/accounts/webSocketProgramAccountsSubscriberV2.d.ts +1 -1
- package/lib/node/accounts/webSocketProgramAccountsSubscriberV2.d.ts.map +1 -1
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +3 -2
- package/lib/node/driftClient.d.ts +2 -0
- package/lib/node/driftClient.d.ts.map +1 -1
- package/lib/node/driftClient.js +17 -0
- package/lib/node/idl/drift.json +28 -175
- package/lib/node/math/bankruptcy.d.ts.map +1 -1
- package/lib/node/math/bankruptcy.js +1 -2
- package/lib/node/types.d.ts +2 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/user.d.ts +2 -15
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +29 -225
- package/package.json +1 -1
- package/src/accounts/webSocketAccountSubscriberV2.ts +2 -2
- package/src/accounts/webSocketProgramAccountsSubscriberV2.ts +2 -2
- package/src/decode/user.ts +3 -2
- package/src/driftClient.ts +44 -0
- package/src/idl/drift.json +29 -176
- package/src/math/bankruptcy.ts +1 -2
- package/src/types.ts +2 -0
- package/src/user.ts +47 -343
package/src/user.ts
CHANGED
|
@@ -22,14 +22,12 @@ import {
|
|
|
22
22
|
} from './math/position';
|
|
23
23
|
import {
|
|
24
24
|
AMM_RESERVE_PRECISION,
|
|
25
|
-
AMM_RESERVE_PRECISION_EXP,
|
|
26
25
|
AMM_TO_QUOTE_PRECISION_RATIO,
|
|
27
26
|
BASE_PRECISION,
|
|
28
27
|
BN_MAX,
|
|
29
28
|
DUST_POSITION_SIZE,
|
|
30
29
|
FIVE_MINUTE,
|
|
31
30
|
MARGIN_PRECISION,
|
|
32
|
-
ONE,
|
|
33
31
|
OPEN_ORDER_MARGIN_REQUIREMENT,
|
|
34
32
|
PRICE_PRECISION,
|
|
35
33
|
QUOTE_PRECISION,
|
|
@@ -84,7 +82,6 @@ import {
|
|
|
84
82
|
getSpotLiabilityValue,
|
|
85
83
|
getTokenAmount,
|
|
86
84
|
} from './math/spotBalance';
|
|
87
|
-
import { calculateMarketOpenBidAsk } from './math/amm';
|
|
88
85
|
import {
|
|
89
86
|
calculateBaseAssetValueWithOracle,
|
|
90
87
|
calculateCollateralDepositRequiredForTrade,
|
|
@@ -227,6 +224,14 @@ export class User {
|
|
|
227
224
|
return this.getPerpPositionForUserAccount(userAccount, marketIndex);
|
|
228
225
|
}
|
|
229
226
|
|
|
227
|
+
public getPerpPositionOrEmpty(marketIndex: number): PerpPosition {
|
|
228
|
+
const userAccount = this.getUserAccount();
|
|
229
|
+
return (
|
|
230
|
+
this.getPerpPositionForUserAccount(userAccount, marketIndex) ??
|
|
231
|
+
this.getEmptyPosition(marketIndex)
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
230
235
|
public getPerpPositionAndSlot(
|
|
231
236
|
marketIndex: number
|
|
232
237
|
): DataAndSlot<PerpPosition | undefined> {
|
|
@@ -325,6 +330,7 @@ export class User {
|
|
|
325
330
|
lastBaseAssetAmountPerLp: ZERO,
|
|
326
331
|
lastQuoteAssetAmountPerLp: ZERO,
|
|
327
332
|
perLpBase: 0,
|
|
333
|
+
maxMarginRatio: 0,
|
|
328
334
|
};
|
|
329
335
|
}
|
|
330
336
|
|
|
@@ -430,243 +436,12 @@ export class User {
|
|
|
430
436
|
public getPerpBidAsks(marketIndex: number): [BN, BN] {
|
|
431
437
|
const position = this.getPerpPosition(marketIndex);
|
|
432
438
|
|
|
433
|
-
const
|
|
434
|
-
|
|
435
|
-
const totalOpenBids = lpOpenBids.add(position.openBids);
|
|
436
|
-
const totalOpenAsks = lpOpenAsks.add(position.openAsks);
|
|
439
|
+
const totalOpenBids = position.openBids;
|
|
440
|
+
const totalOpenAsks = position.openAsks;
|
|
437
441
|
|
|
438
442
|
return [totalOpenBids, totalOpenAsks];
|
|
439
443
|
}
|
|
440
444
|
|
|
441
|
-
/**
|
|
442
|
-
* calculates the open bids and asks for an lp
|
|
443
|
-
* optionally pass in lpShares to see what bid/asks a user *would* take on
|
|
444
|
-
* @returns : lp open bids
|
|
445
|
-
* @returns : lp open asks
|
|
446
|
-
*/
|
|
447
|
-
public getLPBidAsks(marketIndex: number, lpShares?: BN): [BN, BN] {
|
|
448
|
-
const position = this.getPerpPosition(marketIndex);
|
|
449
|
-
|
|
450
|
-
const lpSharesToCalc = lpShares ?? position?.lpShares;
|
|
451
|
-
|
|
452
|
-
if (!lpSharesToCalc || lpSharesToCalc.eq(ZERO)) {
|
|
453
|
-
return [ZERO, ZERO];
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
457
|
-
const [marketOpenBids, marketOpenAsks] = calculateMarketOpenBidAsk(
|
|
458
|
-
market.amm.baseAssetReserve,
|
|
459
|
-
market.amm.minBaseAssetReserve,
|
|
460
|
-
market.amm.maxBaseAssetReserve,
|
|
461
|
-
market.amm.orderStepSize
|
|
462
|
-
);
|
|
463
|
-
|
|
464
|
-
const lpOpenBids = marketOpenBids.mul(lpSharesToCalc).div(market.amm.sqrtK);
|
|
465
|
-
const lpOpenAsks = marketOpenAsks.mul(lpSharesToCalc).div(market.amm.sqrtK);
|
|
466
|
-
|
|
467
|
-
return [lpOpenBids, lpOpenAsks];
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
/**
|
|
471
|
-
* calculates the market position if the lp position was settled
|
|
472
|
-
* @returns : the settled userPosition
|
|
473
|
-
* @returns : the dust base asset amount (ie, < stepsize)
|
|
474
|
-
* @returns : pnl from settle
|
|
475
|
-
*/
|
|
476
|
-
public getPerpPositionWithLPSettle(
|
|
477
|
-
marketIndex: number,
|
|
478
|
-
originalPosition?: PerpPosition,
|
|
479
|
-
burnLpShares = false,
|
|
480
|
-
includeRemainderInBaseAmount = false
|
|
481
|
-
): [PerpPosition, BN, BN] {
|
|
482
|
-
originalPosition =
|
|
483
|
-
originalPosition ??
|
|
484
|
-
this.getPerpPosition(marketIndex) ??
|
|
485
|
-
this.getEmptyPosition(marketIndex);
|
|
486
|
-
|
|
487
|
-
if (originalPosition.lpShares.eq(ZERO)) {
|
|
488
|
-
return [originalPosition, ZERO, ZERO];
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
const position = this.getClonedPosition(originalPosition);
|
|
492
|
-
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
493
|
-
|
|
494
|
-
if (market.amm.perLpBase != position.perLpBase) {
|
|
495
|
-
// perLpBase = 1 => per 10 LP shares, perLpBase = -1 => per 0.1 LP shares
|
|
496
|
-
const expoDiff = market.amm.perLpBase - position.perLpBase;
|
|
497
|
-
const marketPerLpRebaseScalar = new BN(10 ** Math.abs(expoDiff));
|
|
498
|
-
|
|
499
|
-
if (expoDiff > 0) {
|
|
500
|
-
position.lastBaseAssetAmountPerLp =
|
|
501
|
-
position.lastBaseAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
502
|
-
position.lastQuoteAssetAmountPerLp =
|
|
503
|
-
position.lastQuoteAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
504
|
-
} else {
|
|
505
|
-
position.lastBaseAssetAmountPerLp =
|
|
506
|
-
position.lastBaseAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
507
|
-
position.lastQuoteAssetAmountPerLp =
|
|
508
|
-
position.lastQuoteAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
position.perLpBase = position.perLpBase + expoDiff;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
const nShares = position.lpShares;
|
|
515
|
-
|
|
516
|
-
// incorp unsettled funding on pre settled position
|
|
517
|
-
const quoteFundingPnl = calculateUnsettledFundingPnl(market, position);
|
|
518
|
-
|
|
519
|
-
let baseUnit = AMM_RESERVE_PRECISION;
|
|
520
|
-
if (market.amm.perLpBase == position.perLpBase) {
|
|
521
|
-
if (
|
|
522
|
-
position.perLpBase >= 0 &&
|
|
523
|
-
position.perLpBase <= AMM_RESERVE_PRECISION_EXP.toNumber()
|
|
524
|
-
) {
|
|
525
|
-
const marketPerLpRebase = new BN(10 ** market.amm.perLpBase);
|
|
526
|
-
baseUnit = baseUnit.mul(marketPerLpRebase);
|
|
527
|
-
} else if (
|
|
528
|
-
position.perLpBase < 0 &&
|
|
529
|
-
position.perLpBase >= -AMM_RESERVE_PRECISION_EXP.toNumber()
|
|
530
|
-
) {
|
|
531
|
-
const marketPerLpRebase = new BN(10 ** Math.abs(market.amm.perLpBase));
|
|
532
|
-
baseUnit = baseUnit.div(marketPerLpRebase);
|
|
533
|
-
} else {
|
|
534
|
-
throw 'cannot calc';
|
|
535
|
-
}
|
|
536
|
-
} else {
|
|
537
|
-
throw 'market.amm.perLpBase != position.perLpBase';
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
const deltaBaa = market.amm.baseAssetAmountPerLp
|
|
541
|
-
.sub(position.lastBaseAssetAmountPerLp)
|
|
542
|
-
.mul(nShares)
|
|
543
|
-
.div(baseUnit);
|
|
544
|
-
const deltaQaa = market.amm.quoteAssetAmountPerLp
|
|
545
|
-
.sub(position.lastQuoteAssetAmountPerLp)
|
|
546
|
-
.mul(nShares)
|
|
547
|
-
.div(baseUnit);
|
|
548
|
-
|
|
549
|
-
function sign(v: BN) {
|
|
550
|
-
return v.isNeg() ? new BN(-1) : new BN(1);
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
function standardize(amount: BN, stepSize: BN) {
|
|
554
|
-
const remainder = amount.abs().mod(stepSize).mul(sign(amount));
|
|
555
|
-
const standardizedAmount = amount.sub(remainder);
|
|
556
|
-
return [standardizedAmount, remainder];
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
const [standardizedBaa, remainderBaa] = standardize(
|
|
560
|
-
deltaBaa,
|
|
561
|
-
market.amm.orderStepSize
|
|
562
|
-
);
|
|
563
|
-
|
|
564
|
-
position.remainderBaseAssetAmount += remainderBaa.toNumber();
|
|
565
|
-
|
|
566
|
-
if (
|
|
567
|
-
Math.abs(position.remainderBaseAssetAmount) >
|
|
568
|
-
market.amm.orderStepSize.toNumber()
|
|
569
|
-
) {
|
|
570
|
-
const [newStandardizedBaa, newRemainderBaa] = standardize(
|
|
571
|
-
new BN(position.remainderBaseAssetAmount),
|
|
572
|
-
market.amm.orderStepSize
|
|
573
|
-
);
|
|
574
|
-
position.baseAssetAmount =
|
|
575
|
-
position.baseAssetAmount.add(newStandardizedBaa);
|
|
576
|
-
position.remainderBaseAssetAmount = newRemainderBaa.toNumber();
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
let dustBaseAssetValue = ZERO;
|
|
580
|
-
if (burnLpShares && position.remainderBaseAssetAmount != 0) {
|
|
581
|
-
const oraclePriceData = this.driftClient.getOracleDataForPerpMarket(
|
|
582
|
-
position.marketIndex
|
|
583
|
-
);
|
|
584
|
-
dustBaseAssetValue = new BN(Math.abs(position.remainderBaseAssetAmount))
|
|
585
|
-
.mul(oraclePriceData.price)
|
|
586
|
-
.div(AMM_RESERVE_PRECISION)
|
|
587
|
-
.add(ONE);
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
let updateType;
|
|
591
|
-
if (position.baseAssetAmount.eq(ZERO)) {
|
|
592
|
-
updateType = 'open';
|
|
593
|
-
} else if (sign(position.baseAssetAmount).eq(sign(deltaBaa))) {
|
|
594
|
-
updateType = 'increase';
|
|
595
|
-
} else if (position.baseAssetAmount.abs().gt(deltaBaa.abs())) {
|
|
596
|
-
updateType = 'reduce';
|
|
597
|
-
} else if (position.baseAssetAmount.abs().eq(deltaBaa.abs())) {
|
|
598
|
-
updateType = 'close';
|
|
599
|
-
} else {
|
|
600
|
-
updateType = 'flip';
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
let newQuoteEntry;
|
|
604
|
-
let pnl;
|
|
605
|
-
if (updateType == 'open' || updateType == 'increase') {
|
|
606
|
-
newQuoteEntry = position.quoteEntryAmount.add(deltaQaa);
|
|
607
|
-
pnl = ZERO;
|
|
608
|
-
} else if (updateType == 'reduce' || updateType == 'close') {
|
|
609
|
-
newQuoteEntry = position.quoteEntryAmount.sub(
|
|
610
|
-
position.quoteEntryAmount
|
|
611
|
-
.mul(deltaBaa.abs())
|
|
612
|
-
.div(position.baseAssetAmount.abs())
|
|
613
|
-
);
|
|
614
|
-
pnl = position.quoteEntryAmount.sub(newQuoteEntry).add(deltaQaa);
|
|
615
|
-
} else {
|
|
616
|
-
newQuoteEntry = deltaQaa.sub(
|
|
617
|
-
deltaQaa.mul(position.baseAssetAmount.abs()).div(deltaBaa.abs())
|
|
618
|
-
);
|
|
619
|
-
pnl = position.quoteEntryAmount.add(deltaQaa.sub(newQuoteEntry));
|
|
620
|
-
}
|
|
621
|
-
position.quoteEntryAmount = newQuoteEntry;
|
|
622
|
-
position.baseAssetAmount = position.baseAssetAmount.add(standardizedBaa);
|
|
623
|
-
position.quoteAssetAmount = position.quoteAssetAmount
|
|
624
|
-
.add(deltaQaa)
|
|
625
|
-
.add(quoteFundingPnl)
|
|
626
|
-
.sub(dustBaseAssetValue);
|
|
627
|
-
position.quoteBreakEvenAmount = position.quoteBreakEvenAmount
|
|
628
|
-
.add(deltaQaa)
|
|
629
|
-
.add(quoteFundingPnl)
|
|
630
|
-
.sub(dustBaseAssetValue);
|
|
631
|
-
|
|
632
|
-
// update open bids/asks
|
|
633
|
-
const [marketOpenBids, marketOpenAsks] = calculateMarketOpenBidAsk(
|
|
634
|
-
market.amm.baseAssetReserve,
|
|
635
|
-
market.amm.minBaseAssetReserve,
|
|
636
|
-
market.amm.maxBaseAssetReserve,
|
|
637
|
-
market.amm.orderStepSize
|
|
638
|
-
);
|
|
639
|
-
const lpOpenBids = marketOpenBids
|
|
640
|
-
.mul(position.lpShares)
|
|
641
|
-
.div(market.amm.sqrtK);
|
|
642
|
-
const lpOpenAsks = marketOpenAsks
|
|
643
|
-
.mul(position.lpShares)
|
|
644
|
-
.div(market.amm.sqrtK);
|
|
645
|
-
position.openBids = lpOpenBids.add(position.openBids);
|
|
646
|
-
position.openAsks = lpOpenAsks.add(position.openAsks);
|
|
647
|
-
|
|
648
|
-
// eliminate counting funding on settled position
|
|
649
|
-
if (position.baseAssetAmount.gt(ZERO)) {
|
|
650
|
-
position.lastCumulativeFundingRate = market.amm.cumulativeFundingRateLong;
|
|
651
|
-
} else if (position.baseAssetAmount.lt(ZERO)) {
|
|
652
|
-
position.lastCumulativeFundingRate =
|
|
653
|
-
market.amm.cumulativeFundingRateShort;
|
|
654
|
-
} else {
|
|
655
|
-
position.lastCumulativeFundingRate = ZERO;
|
|
656
|
-
}
|
|
657
|
-
|
|
658
|
-
const remainderBeforeRemoval = new BN(position.remainderBaseAssetAmount);
|
|
659
|
-
|
|
660
|
-
if (includeRemainderInBaseAmount) {
|
|
661
|
-
position.baseAssetAmount = position.baseAssetAmount.add(
|
|
662
|
-
remainderBeforeRemoval
|
|
663
|
-
);
|
|
664
|
-
position.remainderBaseAssetAmount = 0;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
return [position, remainderBeforeRemoval, pnl];
|
|
668
|
-
}
|
|
669
|
-
|
|
670
445
|
/**
|
|
671
446
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
672
447
|
* @returns : Precision QUOTE_PRECISION
|
|
@@ -676,11 +451,7 @@ export class User {
|
|
|
676
451
|
collateralBuffer = ZERO,
|
|
677
452
|
enterHighLeverageMode = undefined
|
|
678
453
|
): BN {
|
|
679
|
-
const perpPosition = this.
|
|
680
|
-
marketIndex,
|
|
681
|
-
undefined,
|
|
682
|
-
true
|
|
683
|
-
)[0];
|
|
454
|
+
const perpPosition = this.getPerpPositionOrEmpty(marketIndex);
|
|
684
455
|
|
|
685
456
|
const perpMarket = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
686
457
|
const oraclePriceData = this.getOracleDataForPerpMarket(marketIndex);
|
|
@@ -701,7 +472,8 @@ export class User {
|
|
|
701
472
|
marketIndex,
|
|
702
473
|
freeCollateral,
|
|
703
474
|
worstCaseBaseAssetAmount,
|
|
704
|
-
enterHighLeverageMode
|
|
475
|
+
enterHighLeverageMode,
|
|
476
|
+
perpPosition
|
|
705
477
|
);
|
|
706
478
|
}
|
|
707
479
|
|
|
@@ -709,13 +481,18 @@ export class User {
|
|
|
709
481
|
marketIndex: number,
|
|
710
482
|
freeCollateral: BN,
|
|
711
483
|
baseAssetAmount: BN,
|
|
712
|
-
enterHighLeverageMode = undefined
|
|
484
|
+
enterHighLeverageMode = undefined,
|
|
485
|
+
perpPosition?: PerpPosition
|
|
713
486
|
): BN {
|
|
487
|
+
const userCustomMargin = Math.max(
|
|
488
|
+
perpPosition?.maxMarginRatio ?? 0,
|
|
489
|
+
this.getUserAccount().maxMarginRatio
|
|
490
|
+
);
|
|
714
491
|
const marginRatio = calculateMarketMarginRatio(
|
|
715
492
|
this.driftClient.getPerpMarketAccount(marketIndex),
|
|
716
493
|
baseAssetAmount,
|
|
717
494
|
'Initial',
|
|
718
|
-
|
|
495
|
+
userCustomMargin,
|
|
719
496
|
enterHighLeverageMode || this.isHighLeverageMode('Initial')
|
|
720
497
|
);
|
|
721
498
|
|
|
@@ -793,8 +570,7 @@ export class User {
|
|
|
793
570
|
(pos) =>
|
|
794
571
|
!pos.baseAssetAmount.eq(ZERO) ||
|
|
795
572
|
!pos.quoteAssetAmount.eq(ZERO) ||
|
|
796
|
-
!(pos.openOrders == 0)
|
|
797
|
-
!pos.lpShares.eq(ZERO)
|
|
573
|
+
!(pos.openOrders == 0)
|
|
798
574
|
);
|
|
799
575
|
}
|
|
800
576
|
|
|
@@ -866,14 +642,6 @@ export class User {
|
|
|
866
642
|
market.quoteSpotMarketIndex
|
|
867
643
|
);
|
|
868
644
|
|
|
869
|
-
if (perpPosition.lpShares.gt(ZERO)) {
|
|
870
|
-
perpPosition = this.getPerpPositionWithLPSettle(
|
|
871
|
-
perpPosition.marketIndex,
|
|
872
|
-
undefined,
|
|
873
|
-
!!withWeightMarginCategory
|
|
874
|
-
)[0];
|
|
875
|
-
}
|
|
876
|
-
|
|
877
645
|
let positionUnrealizedPnl = calculatePositionPNL(
|
|
878
646
|
market,
|
|
879
647
|
perpPosition,
|
|
@@ -1450,15 +1218,6 @@ export class User {
|
|
|
1450
1218
|
perpPosition.marketIndex
|
|
1451
1219
|
);
|
|
1452
1220
|
|
|
1453
|
-
if (perpPosition.lpShares.gt(ZERO)) {
|
|
1454
|
-
// is an lp, clone so we dont mutate the position
|
|
1455
|
-
perpPosition = this.getPerpPositionWithLPSettle(
|
|
1456
|
-
market.marketIndex,
|
|
1457
|
-
this.getClonedPosition(perpPosition),
|
|
1458
|
-
!!marginCategory
|
|
1459
|
-
)[0];
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
1221
|
let valuationPrice = this.getOracleDataForPerpMarket(
|
|
1463
1222
|
market.marketIndex
|
|
1464
1223
|
).price;
|
|
@@ -1537,19 +1296,6 @@ export class User {
|
|
|
1537
1296
|
liabilityValue = liabilityValue.add(
|
|
1538
1297
|
new BN(perpPosition.openOrders).mul(OPEN_ORDER_MARGIN_REQUIREMENT)
|
|
1539
1298
|
);
|
|
1540
|
-
|
|
1541
|
-
if (perpPosition.lpShares.gt(ZERO)) {
|
|
1542
|
-
liabilityValue = liabilityValue.add(
|
|
1543
|
-
BN.max(
|
|
1544
|
-
QUOTE_PRECISION,
|
|
1545
|
-
valuationPrice
|
|
1546
|
-
.mul(market.amm.orderStepSize)
|
|
1547
|
-
.mul(QUOTE_PRECISION)
|
|
1548
|
-
.div(AMM_RESERVE_PRECISION)
|
|
1549
|
-
.div(PRICE_PRECISION)
|
|
1550
|
-
)
|
|
1551
|
-
);
|
|
1552
|
-
}
|
|
1553
1299
|
}
|
|
1554
1300
|
}
|
|
1555
1301
|
|
|
@@ -1613,13 +1359,7 @@ export class User {
|
|
|
1613
1359
|
oraclePriceData: Pick<OraclePriceData, 'price'>,
|
|
1614
1360
|
includeOpenOrders = false
|
|
1615
1361
|
): BN {
|
|
1616
|
-
const userPosition =
|
|
1617
|
-
this.getPerpPositionWithLPSettle(
|
|
1618
|
-
marketIndex,
|
|
1619
|
-
undefined,
|
|
1620
|
-
false,
|
|
1621
|
-
true
|
|
1622
|
-
)[0] || this.getEmptyPosition(marketIndex);
|
|
1362
|
+
const userPosition = this.getPerpPositionOrEmpty(marketIndex);
|
|
1623
1363
|
const market = this.driftClient.getPerpMarketAccount(
|
|
1624
1364
|
userPosition.marketIndex
|
|
1625
1365
|
);
|
|
@@ -1640,13 +1380,7 @@ export class User {
|
|
|
1640
1380
|
oraclePriceData: OraclePriceData,
|
|
1641
1381
|
includeOpenOrders = false
|
|
1642
1382
|
): BN {
|
|
1643
|
-
const userPosition =
|
|
1644
|
-
this.getPerpPositionWithLPSettle(
|
|
1645
|
-
marketIndex,
|
|
1646
|
-
undefined,
|
|
1647
|
-
false,
|
|
1648
|
-
true
|
|
1649
|
-
)[0] || this.getEmptyPosition(marketIndex);
|
|
1383
|
+
const userPosition = this.getPerpPositionOrEmpty(marketIndex);
|
|
1650
1384
|
const market = this.driftClient.getPerpMarketAccount(
|
|
1651
1385
|
userPosition.marketIndex
|
|
1652
1386
|
);
|
|
@@ -2197,11 +1931,9 @@ export class User {
|
|
|
2197
1931
|
const oraclePrice =
|
|
2198
1932
|
this.driftClient.getOracleDataForSpotMarket(marketIndex).price;
|
|
2199
1933
|
if (perpMarketWithSameOracle) {
|
|
2200
|
-
const perpPosition = this.
|
|
2201
|
-
perpMarketWithSameOracle.marketIndex
|
|
2202
|
-
|
|
2203
|
-
true
|
|
2204
|
-
)[0];
|
|
1934
|
+
const perpPosition = this.getPerpPositionOrEmpty(
|
|
1935
|
+
perpMarketWithSameOracle.marketIndex
|
|
1936
|
+
);
|
|
2205
1937
|
if (perpPosition) {
|
|
2206
1938
|
let freeCollateralDeltaForPerp =
|
|
2207
1939
|
this.calculateFreeCollateralDeltaForPerp(
|
|
@@ -2287,9 +2019,7 @@ export class User {
|
|
|
2287
2019
|
this.driftClient.getOracleDataForPerpMarket(marketIndex).price;
|
|
2288
2020
|
|
|
2289
2021
|
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
2290
|
-
const currentPerpPosition =
|
|
2291
|
-
this.getPerpPositionWithLPSettle(marketIndex, undefined, true)[0] ||
|
|
2292
|
-
this.getEmptyPosition(marketIndex);
|
|
2022
|
+
const currentPerpPosition = this.getPerpPositionOrEmpty(marketIndex);
|
|
2293
2023
|
|
|
2294
2024
|
positionBaseSizeChange = standardizeBaseAssetAmount(
|
|
2295
2025
|
positionBaseSizeChange,
|
|
@@ -2439,7 +2169,10 @@ export class User {
|
|
|
2439
2169
|
);
|
|
2440
2170
|
}
|
|
2441
2171
|
|
|
2442
|
-
const userCustomMargin =
|
|
2172
|
+
const userCustomMargin = Math.max(
|
|
2173
|
+
perpPosition.maxMarginRatio,
|
|
2174
|
+
this.getUserAccount().maxMarginRatio
|
|
2175
|
+
);
|
|
2443
2176
|
const marginRatio = calculateMarketMarginRatio(
|
|
2444
2177
|
market,
|
|
2445
2178
|
baseAssetAmount.abs(),
|
|
@@ -2489,7 +2222,10 @@ export class User {
|
|
|
2489
2222
|
|
|
2490
2223
|
const proposedBaseAssetAmount = baseAssetAmount.add(positionBaseSizeChange);
|
|
2491
2224
|
|
|
2492
|
-
const userCustomMargin =
|
|
2225
|
+
const userCustomMargin = Math.max(
|
|
2226
|
+
perpPosition.maxMarginRatio,
|
|
2227
|
+
this.getUserAccount().maxMarginRatio
|
|
2228
|
+
);
|
|
2493
2229
|
|
|
2494
2230
|
const marginRatio = calculateMarketMarginRatio(
|
|
2495
2231
|
market,
|
|
@@ -2587,12 +2323,7 @@ export class User {
|
|
|
2587
2323
|
closeQuoteAmount: BN,
|
|
2588
2324
|
estimatedEntryPrice: BN = ZERO
|
|
2589
2325
|
): BN {
|
|
2590
|
-
const currentPosition =
|
|
2591
|
-
this.getPerpPositionWithLPSettle(
|
|
2592
|
-
positionMarketIndex,
|
|
2593
|
-
undefined,
|
|
2594
|
-
true
|
|
2595
|
-
)[0] || this.getEmptyPosition(positionMarketIndex);
|
|
2326
|
+
const currentPosition = this.getPerpPositionOrEmpty(positionMarketIndex);
|
|
2596
2327
|
|
|
2597
2328
|
const closeBaseAmount = currentPosition.baseAssetAmount
|
|
2598
2329
|
.mul(closeQuoteAmount)
|
|
@@ -2658,9 +2389,7 @@ export class User {
|
|
|
2658
2389
|
): { tradeSize: BN; oppositeSideTradeSize: BN } {
|
|
2659
2390
|
let tradeSize = ZERO;
|
|
2660
2391
|
let oppositeSideTradeSize = ZERO;
|
|
2661
|
-
const currentPosition =
|
|
2662
|
-
this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
|
|
2663
|
-
this.getEmptyPosition(targetMarketIndex);
|
|
2392
|
+
const currentPosition = this.getPerpPositionOrEmpty(targetMarketIndex);
|
|
2664
2393
|
|
|
2665
2394
|
const targetSide = isVariant(tradeSide, 'short') ? 'short' : 'long';
|
|
2666
2395
|
|
|
@@ -3433,9 +3162,7 @@ export class User {
|
|
|
3433
3162
|
return newLeverage;
|
|
3434
3163
|
}
|
|
3435
3164
|
|
|
3436
|
-
const currentPosition =
|
|
3437
|
-
this.getPerpPositionWithLPSettle(targetMarketIndex)[0] ||
|
|
3438
|
-
this.getEmptyPosition(targetMarketIndex);
|
|
3165
|
+
const currentPosition = this.getPerpPositionOrEmpty(targetMarketIndex);
|
|
3439
3166
|
|
|
3440
3167
|
const perpMarket = this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
3441
3168
|
const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
|
|
@@ -3848,10 +3575,6 @@ export class User {
|
|
|
3848
3575
|
oraclePriceData?: OraclePriceData;
|
|
3849
3576
|
quoteOraclePriceData?: OraclePriceData;
|
|
3850
3577
|
}): HealthComponent {
|
|
3851
|
-
const settledLpPosition = this.getPerpPositionWithLPSettle(
|
|
3852
|
-
perpPosition.marketIndex,
|
|
3853
|
-
perpPosition
|
|
3854
|
-
)[0];
|
|
3855
3578
|
const perpMarket = this.driftClient.getPerpMarketAccount(
|
|
3856
3579
|
perpPosition.marketIndex
|
|
3857
3580
|
);
|
|
@@ -3863,17 +3586,21 @@ export class User {
|
|
|
3863
3586
|
worstCaseBaseAssetAmount: worstCaseBaseAmount,
|
|
3864
3587
|
worstCaseLiabilityValue,
|
|
3865
3588
|
} = calculateWorstCasePerpLiabilityValue(
|
|
3866
|
-
|
|
3589
|
+
perpPosition,
|
|
3867
3590
|
perpMarket,
|
|
3868
3591
|
oraclePrice
|
|
3869
3592
|
);
|
|
3870
3593
|
|
|
3594
|
+
const userCustomMargin = Math.max(
|
|
3595
|
+
perpPosition.maxMarginRatio,
|
|
3596
|
+
this.getUserAccount().maxMarginRatio
|
|
3597
|
+
);
|
|
3871
3598
|
const marginRatio = new BN(
|
|
3872
3599
|
calculateMarketMarginRatio(
|
|
3873
3600
|
perpMarket,
|
|
3874
3601
|
worstCaseBaseAmount.abs(),
|
|
3875
3602
|
marginCategory,
|
|
3876
|
-
|
|
3603
|
+
userCustomMargin,
|
|
3877
3604
|
this.isHighLeverageMode(marginCategory)
|
|
3878
3605
|
)
|
|
3879
3606
|
);
|
|
@@ -3892,19 +3619,6 @@ export class User {
|
|
|
3892
3619
|
new BN(perpPosition.openOrders).mul(OPEN_ORDER_MARGIN_REQUIREMENT)
|
|
3893
3620
|
);
|
|
3894
3621
|
|
|
3895
|
-
if (perpPosition.lpShares.gt(ZERO)) {
|
|
3896
|
-
marginRequirement = marginRequirement.add(
|
|
3897
|
-
BN.max(
|
|
3898
|
-
QUOTE_PRECISION,
|
|
3899
|
-
oraclePrice
|
|
3900
|
-
.mul(perpMarket.amm.orderStepSize)
|
|
3901
|
-
.mul(QUOTE_PRECISION)
|
|
3902
|
-
.div(AMM_RESERVE_PRECISION)
|
|
3903
|
-
.div(PRICE_PRECISION)
|
|
3904
|
-
)
|
|
3905
|
-
);
|
|
3906
|
-
}
|
|
3907
|
-
|
|
3908
3622
|
return {
|
|
3909
3623
|
marketIndex: perpMarket.marketIndex,
|
|
3910
3624
|
size: worstCaseBaseAmount,
|
|
@@ -3952,14 +3666,9 @@ export class User {
|
|
|
3952
3666
|
perpMarket.quoteSpotMarketIndex
|
|
3953
3667
|
);
|
|
3954
3668
|
|
|
3955
|
-
const settledPerpPosition = this.getPerpPositionWithLPSettle(
|
|
3956
|
-
perpPosition.marketIndex,
|
|
3957
|
-
perpPosition
|
|
3958
|
-
)[0];
|
|
3959
|
-
|
|
3960
3669
|
const positionUnrealizedPnl = calculatePositionPNL(
|
|
3961
3670
|
perpMarket,
|
|
3962
|
-
|
|
3671
|
+
perpPosition,
|
|
3963
3672
|
true,
|
|
3964
3673
|
oraclePriceData
|
|
3965
3674
|
);
|
|
@@ -4111,12 +3820,7 @@ export class User {
|
|
|
4111
3820
|
liquidationBuffer?: BN,
|
|
4112
3821
|
includeOpenOrders?: boolean
|
|
4113
3822
|
): BN {
|
|
4114
|
-
const currentPerpPosition =
|
|
4115
|
-
this.getPerpPositionWithLPSettle(
|
|
4116
|
-
marketToIgnore,
|
|
4117
|
-
undefined,
|
|
4118
|
-
!!marginCategory
|
|
4119
|
-
)[0] || this.getEmptyPosition(marketToIgnore);
|
|
3823
|
+
const currentPerpPosition = this.getPerpPositionOrEmpty(marketToIgnore);
|
|
4120
3824
|
|
|
4121
3825
|
const oracleData = this.getOracleDataForPerpMarket(marketToIgnore);
|
|
4122
3826
|
|