@drift-labs/sdk 2.22.0 → 2.23.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/constants/spotMarkets.js +4 -4
- package/lib/driftClient.d.ts +2 -1
- package/lib/driftClient.js +123 -36
- package/lib/factory/oracleClient.js +3 -0
- package/lib/idl/drift.json +13 -2
- package/lib/oracles/pythClient.d.ts +2 -1
- package/lib/oracles/pythClient.js +18 -3
- package/lib/tx/utils.js +6 -2
- package/lib/types.d.ts +4 -0
- package/lib/types.js +1 -0
- package/lib/user.d.ts +3 -3
- package/lib/user.js +44 -25
- package/package.json +1 -1
- package/src/constants/spotMarkets.ts +4 -4
- package/src/driftClient.ts +127 -30
- package/src/factory/oracleClient.ts +4 -0
- package/src/idl/drift.json +13 -2
- package/src/oracles/pythClient.ts +38 -12
- package/src/tx/utils.ts +2 -0
- package/src/types.ts +2 -0
- package/src/user.ts +104 -44
- package/tests/dlob/helpers.ts +3 -0
package/src/user.ts
CHANGED
|
@@ -424,7 +424,8 @@ export class User {
|
|
|
424
424
|
return this.getTotalPerpPositionValue(
|
|
425
425
|
marginCategory,
|
|
426
426
|
liquidationBuffer,
|
|
427
|
-
true
|
|
427
|
+
true,
|
|
428
|
+
strict
|
|
428
429
|
).add(
|
|
429
430
|
this.getSpotMarketLiabilityValue(
|
|
430
431
|
undefined,
|
|
@@ -467,9 +468,9 @@ export class User {
|
|
|
467
468
|
public getUnrealizedPNL(
|
|
468
469
|
withFunding?: boolean,
|
|
469
470
|
marketIndex?: number,
|
|
470
|
-
withWeightMarginCategory?: MarginCategory
|
|
471
|
+
withWeightMarginCategory?: MarginCategory,
|
|
472
|
+
strict = false
|
|
471
473
|
): BN {
|
|
472
|
-
const quoteSpotMarket = this.driftClient.getQuoteSpotMarketAccount();
|
|
473
474
|
return this.getActivePerpPositions()
|
|
474
475
|
.filter((pos) => (marketIndex ? pos.marketIndex === marketIndex : true))
|
|
475
476
|
.reduce((unrealizedPnl, perpPosition) => {
|
|
@@ -480,6 +481,13 @@ export class User {
|
|
|
480
481
|
market.marketIndex
|
|
481
482
|
);
|
|
482
483
|
|
|
484
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(
|
|
485
|
+
market.quoteSpotMarketIndex
|
|
486
|
+
);
|
|
487
|
+
const quoteOraclePriceData = this.getOracleDataForSpotMarket(
|
|
488
|
+
market.quoteSpotMarketIndex
|
|
489
|
+
);
|
|
490
|
+
|
|
483
491
|
if (perpPosition.lpShares.gt(ZERO)) {
|
|
484
492
|
perpPosition = this.getSettledLPPosition(perpPosition.marketIndex)[0];
|
|
485
493
|
}
|
|
@@ -491,6 +499,25 @@ export class User {
|
|
|
491
499
|
oraclePriceData
|
|
492
500
|
);
|
|
493
501
|
|
|
502
|
+
let quotePrice;
|
|
503
|
+
if (strict && positionUnrealizedPnl.gt(ZERO)) {
|
|
504
|
+
quotePrice = BN.min(
|
|
505
|
+
quoteOraclePriceData.price,
|
|
506
|
+
quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min
|
|
507
|
+
);
|
|
508
|
+
} else if (strict && positionUnrealizedPnl.lt(ZERO)) {
|
|
509
|
+
quotePrice = BN.max(
|
|
510
|
+
quoteOraclePriceData.price,
|
|
511
|
+
quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min
|
|
512
|
+
);
|
|
513
|
+
} else {
|
|
514
|
+
quotePrice = quoteOraclePriceData.price;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
positionUnrealizedPnl = positionUnrealizedPnl
|
|
518
|
+
.mul(quotePrice)
|
|
519
|
+
.div(new BN(PRICE_PRECISION));
|
|
520
|
+
|
|
494
521
|
if (withWeightMarginCategory !== undefined) {
|
|
495
522
|
if (positionUnrealizedPnl.gt(ZERO)) {
|
|
496
523
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
@@ -558,55 +585,60 @@ export class User {
|
|
|
558
585
|
const spotMarketAccount: SpotMarketAccount =
|
|
559
586
|
this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
560
587
|
|
|
588
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(
|
|
589
|
+
spotPosition.marketIndex
|
|
590
|
+
);
|
|
591
|
+
|
|
561
592
|
if (
|
|
562
593
|
spotPosition.marketIndex === QUOTE_SPOT_MARKET_INDEX &&
|
|
563
594
|
countForQuote
|
|
564
595
|
) {
|
|
565
|
-
|
|
566
|
-
|
|
596
|
+
const tokenAmount = getSignedTokenAmount(
|
|
597
|
+
getTokenAmount(
|
|
567
598
|
spotPosition.scaledBalance,
|
|
568
599
|
spotMarketAccount,
|
|
569
600
|
spotPosition.balanceType
|
|
570
|
-
)
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
if (marginCategory === 'Initial') {
|
|
574
|
-
weight = BN.max(
|
|
575
|
-
weight,
|
|
576
|
-
new BN(this.getUserAccount().maxMarginRatio)
|
|
577
|
-
);
|
|
578
|
-
}
|
|
601
|
+
),
|
|
602
|
+
spotPosition.balanceType
|
|
603
|
+
);
|
|
579
604
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
605
|
+
if (isVariant(spotPosition.balanceType, 'borrow')) {
|
|
606
|
+
const weightedTokenValue = this.getSpotLiabilityValue(
|
|
607
|
+
tokenAmount,
|
|
608
|
+
oraclePriceData,
|
|
609
|
+
spotMarketAccount,
|
|
610
|
+
marginCategory,
|
|
611
|
+
liquidationBuffer,
|
|
612
|
+
strict,
|
|
613
|
+
now
|
|
614
|
+
).abs();
|
|
583
615
|
|
|
584
616
|
netQuoteValue = netQuoteValue.sub(weightedTokenValue);
|
|
585
|
-
|
|
586
|
-
continue;
|
|
587
617
|
} else {
|
|
588
|
-
const
|
|
589
|
-
|
|
618
|
+
const weightedTokenValue = this.getSpotAssetValue(
|
|
619
|
+
tokenAmount,
|
|
620
|
+
oraclePriceData,
|
|
590
621
|
spotMarketAccount,
|
|
591
|
-
|
|
622
|
+
marginCategory,
|
|
623
|
+
strict,
|
|
624
|
+
now
|
|
592
625
|
);
|
|
593
626
|
|
|
594
|
-
netQuoteValue = netQuoteValue.add(
|
|
595
|
-
|
|
596
|
-
continue;
|
|
627
|
+
netQuoteValue = netQuoteValue.add(weightedTokenValue);
|
|
597
628
|
}
|
|
598
|
-
}
|
|
599
629
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
);
|
|
630
|
+
continue;
|
|
631
|
+
}
|
|
603
632
|
|
|
604
633
|
if (!includeOpenOrders && countForBase) {
|
|
605
634
|
if (isVariant(spotPosition.balanceType, 'borrow')) {
|
|
606
|
-
const tokenAmount =
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
635
|
+
const tokenAmount = getSignedTokenAmount(
|
|
636
|
+
getTokenAmount(
|
|
637
|
+
spotPosition.scaledBalance,
|
|
638
|
+
spotMarketAccount,
|
|
639
|
+
spotPosition.balanceType
|
|
640
|
+
),
|
|
641
|
+
SpotBalanceType.BORROW
|
|
610
642
|
);
|
|
611
643
|
const liabilityValue = this.getSpotLiabilityValue(
|
|
612
644
|
tokenAmount,
|
|
@@ -616,7 +648,7 @@ export class User {
|
|
|
616
648
|
liquidationBuffer,
|
|
617
649
|
strict,
|
|
618
650
|
now
|
|
619
|
-
);
|
|
651
|
+
).abs();
|
|
620
652
|
totalLiabilityValue = totalLiabilityValue.add(liabilityValue);
|
|
621
653
|
|
|
622
654
|
continue;
|
|
@@ -662,14 +694,14 @@ export class User {
|
|
|
662
694
|
|
|
663
695
|
if (worstCaseTokenAmount.lt(ZERO) && countForBase) {
|
|
664
696
|
const baseLiabilityValue = this.getSpotLiabilityValue(
|
|
665
|
-
worstCaseTokenAmount
|
|
697
|
+
worstCaseTokenAmount,
|
|
666
698
|
oraclePriceData,
|
|
667
699
|
spotMarketAccount,
|
|
668
700
|
marginCategory,
|
|
669
701
|
liquidationBuffer,
|
|
670
702
|
strict,
|
|
671
703
|
now
|
|
672
|
-
);
|
|
704
|
+
).abs();
|
|
673
705
|
|
|
674
706
|
totalLiabilityValue = totalLiabilityValue.add(baseLiabilityValue);
|
|
675
707
|
}
|
|
@@ -738,7 +770,7 @@ export class User {
|
|
|
738
770
|
): BN {
|
|
739
771
|
let liabilityValue = null;
|
|
740
772
|
|
|
741
|
-
if (strict
|
|
773
|
+
if (strict) {
|
|
742
774
|
const estOracleTwap = calculateLiveOracleTwap(
|
|
743
775
|
spotMarketAccount.historicalOracleData,
|
|
744
776
|
oraclePriceData,
|
|
@@ -809,7 +841,7 @@ export class User {
|
|
|
809
841
|
now?: BN
|
|
810
842
|
): BN {
|
|
811
843
|
let assetValue = null;
|
|
812
|
-
if (strict
|
|
844
|
+
if (strict) {
|
|
813
845
|
const estOracleTwap = calculateLiveOracleTwap(
|
|
814
846
|
spotMarketAccount.historicalOracleData,
|
|
815
847
|
oraclePriceData,
|
|
@@ -886,10 +918,16 @@ export class User {
|
|
|
886
918
|
* calculates TotalCollateral: collateral + unrealized pnl
|
|
887
919
|
* @returns : Precision QUOTE_PRECISION
|
|
888
920
|
*/
|
|
889
|
-
public getTotalCollateral(
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
921
|
+
public getTotalCollateral(
|
|
922
|
+
marginCategory: MarginCategory = 'Initial',
|
|
923
|
+
strict = false
|
|
924
|
+
): BN {
|
|
925
|
+
return this.getSpotMarketAssetValue(
|
|
926
|
+
undefined,
|
|
927
|
+
marginCategory,
|
|
928
|
+
true,
|
|
929
|
+
strict
|
|
930
|
+
).add(this.getUnrealizedPNL(true, undefined, marginCategory, strict));
|
|
893
931
|
}
|
|
894
932
|
|
|
895
933
|
/**
|
|
@@ -941,7 +979,8 @@ export class User {
|
|
|
941
979
|
getTotalPerpPositionValue(
|
|
942
980
|
marginCategory?: MarginCategory,
|
|
943
981
|
liquidationBuffer?: BN,
|
|
944
|
-
includeOpenOrders?: boolean
|
|
982
|
+
includeOpenOrders?: boolean,
|
|
983
|
+
strict = false
|
|
945
984
|
): BN {
|
|
946
985
|
return this.getActivePerpPositions().reduce(
|
|
947
986
|
(totalPerpValue, perpPosition) => {
|
|
@@ -1011,7 +1050,27 @@ export class User {
|
|
|
1011
1050
|
marginRatio = ZERO;
|
|
1012
1051
|
}
|
|
1013
1052
|
|
|
1053
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(
|
|
1054
|
+
market.quoteSpotMarketIndex
|
|
1055
|
+
);
|
|
1056
|
+
const quoteOraclePriceData =
|
|
1057
|
+
this.driftClient.getOraclePriceDataAndSlot(
|
|
1058
|
+
quoteSpotMarket.oracle
|
|
1059
|
+
).data;
|
|
1060
|
+
|
|
1061
|
+
let quotePrice;
|
|
1062
|
+
if (strict) {
|
|
1063
|
+
quotePrice = BN.max(
|
|
1064
|
+
quoteOraclePriceData.price,
|
|
1065
|
+
quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min
|
|
1066
|
+
);
|
|
1067
|
+
} else {
|
|
1068
|
+
quotePrice = quoteOraclePriceData.price;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1014
1071
|
baseAssetValue = baseAssetValue
|
|
1072
|
+
.mul(quotePrice)
|
|
1073
|
+
.div(PRICE_PRECISION)
|
|
1015
1074
|
.mul(marginRatio)
|
|
1016
1075
|
.div(MARGIN_PRECISION);
|
|
1017
1076
|
|
|
@@ -2178,7 +2237,8 @@ export class User {
|
|
|
2178
2237
|
}
|
|
2179
2238
|
|
|
2180
2239
|
const userLastActiveSlot = userAccount.lastActiveSlot;
|
|
2181
|
-
|
|
2240
|
+
const slotsSinceLastActive = slot.sub(userLastActiveSlot);
|
|
2241
|
+
if (slotsSinceLastActive.lt(slotsBeforeIdle)) {
|
|
2182
2242
|
return false;
|
|
2183
2243
|
}
|
|
2184
2244
|
|
package/tests/dlob/helpers.ts
CHANGED
|
@@ -172,6 +172,7 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
|
|
|
172
172
|
quoteSettledInsurance: new BN(0),
|
|
173
173
|
quoteMaxInsurance: new BN(0),
|
|
174
174
|
},
|
|
175
|
+
quoteSpotMarketIndex: 0,
|
|
175
176
|
},
|
|
176
177
|
{
|
|
177
178
|
status: MarketStatus.INITIALIZED,
|
|
@@ -208,6 +209,7 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
|
|
|
208
209
|
quoteSettledInsurance: new BN(0),
|
|
209
210
|
quoteMaxInsurance: new BN(0),
|
|
210
211
|
},
|
|
212
|
+
quoteSpotMarketIndex: 0,
|
|
211
213
|
},
|
|
212
214
|
{
|
|
213
215
|
status: MarketStatus.INITIALIZED,
|
|
@@ -244,6 +246,7 @@ export const mockPerpMarkets: Array<PerpMarketAccount> = [
|
|
|
244
246
|
quoteSettledInsurance: new BN(0),
|
|
245
247
|
quoteMaxInsurance: new BN(0),
|
|
246
248
|
},
|
|
249
|
+
quoteSpotMarketIndex: 0,
|
|
247
250
|
},
|
|
248
251
|
];
|
|
249
252
|
|