@drift-labs/sdk 2.12.0-beta.1 → 2.12.0-beta.3
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/accounts/bulkAccountLoader.js +3 -3
- package/lib/accounts/fetch.js +2 -2
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +7 -7
- package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +2 -2
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
- package/lib/accounts/webSocketAccountSubscriber.js +1 -1
- package/lib/accounts/webSocketDriftClientAccountSubscriber.js +3 -3
- package/lib/addresses/marketAddresses.js +1 -1
- package/lib/addresses/pda.js +1 -5
- package/lib/adminClient.js +57 -61
- package/lib/dlob/DLOB.js +67 -67
- package/lib/dlob/DLOBNode.js +7 -7
- package/lib/dlob/NodeList.js +2 -2
- package/lib/driftClient.d.ts +3 -3
- package/lib/driftClient.js +83 -87
- package/lib/events/eventSubscriber.js +2 -2
- package/lib/events/pollingLogProvider.js +1 -1
- package/lib/examples/makeTradeExample.js +9 -9
- package/lib/factory/bigNum.js +9 -9
- package/lib/factory/oracleClient.js +2 -2
- package/lib/idl/drift.json +7 -11
- package/lib/index.js +1 -5
- package/lib/math/amm.js +23 -23
- package/lib/math/auction.js +6 -6
- package/lib/math/exchangeStatus.js +7 -5
- package/lib/math/funding.js +2 -2
- package/lib/math/margin.js +5 -5
- package/lib/math/market.js +12 -12
- package/lib/math/oracles.js +1 -1
- package/lib/math/orders.js +23 -23
- package/lib/math/position.js +5 -5
- package/lib/math/repeg.js +1 -1
- package/lib/math/spotBalance.js +7 -7
- package/lib/math/spotPosition.js +3 -3
- package/lib/math/trade.js +34 -34
- package/lib/oracles/oracleClientCache.js +1 -1
- package/lib/oracles/pythClient.js +1 -1
- package/lib/tokenFaucet.js +1 -5
- package/lib/tx/retryTxSender.js +1 -1
- package/lib/tx/utils.d.ts +1 -1
- package/lib/tx/utils.js +7 -4
- package/lib/types.d.ts +15 -23
- package/lib/types.js +12 -10
- package/lib/user.js +48 -48
- package/lib/userMap/userMap.js +1 -1
- package/lib/userMap/userStatsMap.js +3 -3
- package/lib/userStats.js +2 -2
- package/package.json +1 -1
- package/src/driftClient.ts +11 -4
- package/src/idl/drift.json +7 -11
- package/src/math/exchangeStatus.ts +6 -4
- package/src/tx/utils.ts +11 -3
- package/src/types.ts +16 -9
- package/src/user.ts +1 -1
- package/tests/dlob/helpers.ts +1 -2
package/lib/user.js
CHANGED
|
@@ -141,7 +141,7 @@ class User {
|
|
|
141
141
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
142
142
|
}
|
|
143
143
|
const market = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
144
|
-
const [marketOpenBids, marketOpenAsks] =
|
|
144
|
+
const [marketOpenBids, marketOpenAsks] = amm_1.calculateMarketOpenBidAsk(market.amm.baseAssetReserve, market.amm.minBaseAssetReserve, market.amm.maxBaseAssetReserve, market.amm.orderStepSize);
|
|
145
145
|
const lpOpenBids = marketOpenBids
|
|
146
146
|
.mul(position.lpShares)
|
|
147
147
|
.div(market.amm.sqrtK);
|
|
@@ -294,11 +294,11 @@ class User {
|
|
|
294
294
|
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
295
295
|
perpPosition = this.getSettledLPPosition(perpPosition.marketIndex)[0];
|
|
296
296
|
}
|
|
297
|
-
let positionUnrealizedPnl =
|
|
297
|
+
let positionUnrealizedPnl = _1.calculatePositionPNL(market, perpPosition, withFunding, oraclePriceData);
|
|
298
298
|
if (withWeightMarginCategory !== undefined) {
|
|
299
299
|
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
300
300
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
301
|
-
.mul(
|
|
301
|
+
.mul(_1.calculateUnrealizedAssetWeight(market, quoteSpotMarket, positionUnrealizedPnl, withWeightMarginCategory, oraclePriceData))
|
|
302
302
|
.div(new _1.BN(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION));
|
|
303
303
|
}
|
|
304
304
|
}
|
|
@@ -314,20 +314,20 @@ class User {
|
|
|
314
314
|
.perpPositions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
|
|
315
315
|
.reduce((pnl, perpPosition) => {
|
|
316
316
|
const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
317
|
-
return pnl.add(
|
|
317
|
+
return pnl.add(_1.calculatePositionFundingPNL(market, perpPosition));
|
|
318
318
|
}, numericConstants_1.ZERO);
|
|
319
319
|
}
|
|
320
320
|
getSpotMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders) {
|
|
321
321
|
return this.getUserAccount().spotPositions.reduce((totalLiabilityValue, spotPosition) => {
|
|
322
|
-
if (
|
|
322
|
+
if (spotPosition_1.isSpotPositionAvailable(spotPosition) ||
|
|
323
323
|
(marketIndex !== undefined &&
|
|
324
324
|
spotPosition.marketIndex !== marketIndex)) {
|
|
325
325
|
return totalLiabilityValue;
|
|
326
326
|
}
|
|
327
327
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
328
328
|
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
329
|
-
if (
|
|
330
|
-
const tokenAmount =
|
|
329
|
+
if (types_1.isVariant(spotPosition.balanceType, 'borrow')) {
|
|
330
|
+
const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
331
331
|
let weight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
|
|
332
332
|
if (marginCategory === 'Initial') {
|
|
333
333
|
weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
@@ -343,8 +343,8 @@ class User {
|
|
|
343
343
|
}
|
|
344
344
|
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
345
345
|
if (!includeOpenOrders) {
|
|
346
|
-
if (
|
|
347
|
-
const tokenAmount =
|
|
346
|
+
if (types_1.isVariant(spotPosition.balanceType, 'borrow')) {
|
|
347
|
+
const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
348
348
|
const liabilityValue = this.getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer);
|
|
349
349
|
return totalLiabilityValue.add(liabilityValue);
|
|
350
350
|
}
|
|
@@ -352,7 +352,7 @@ class User {
|
|
|
352
352
|
return totalLiabilityValue;
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
|
-
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] =
|
|
355
|
+
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = spotPosition_1.getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
|
|
356
356
|
let newTotalLiabilityValue = totalLiabilityValue;
|
|
357
357
|
if (worstCaseTokenAmount.lt(numericConstants_1.ZERO)) {
|
|
358
358
|
const baseLiabilityValue = this.getSpotLiabilityValue(worstCaseTokenAmount.abs(), oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer);
|
|
@@ -376,9 +376,9 @@ class User {
|
|
|
376
376
|
}, numericConstants_1.ZERO);
|
|
377
377
|
}
|
|
378
378
|
getSpotLiabilityValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory, liquidationBuffer) {
|
|
379
|
-
let liabilityValue =
|
|
379
|
+
let liabilityValue = _1.getTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
|
|
380
380
|
if (marginCategory !== undefined) {
|
|
381
|
-
let weight =
|
|
381
|
+
let weight = spotBalance_1.calculateLiabilityWeight(tokenAmount, spotMarketAccount, marginCategory);
|
|
382
382
|
if (marginCategory === 'Initial') {
|
|
383
383
|
weight = _1.BN.max(weight, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
384
384
|
}
|
|
@@ -393,7 +393,7 @@ class User {
|
|
|
393
393
|
}
|
|
394
394
|
getSpotMarketAssetValue(marketIndex, marginCategory, includeOpenOrders) {
|
|
395
395
|
return this.getUserAccount().spotPositions.reduce((totalAssetValue, spotPosition) => {
|
|
396
|
-
if (
|
|
396
|
+
if (spotPosition_1.isSpotPositionAvailable(spotPosition) ||
|
|
397
397
|
(marketIndex !== undefined &&
|
|
398
398
|
spotPosition.marketIndex !== marketIndex)) {
|
|
399
399
|
return totalAssetValue;
|
|
@@ -401,8 +401,8 @@ class User {
|
|
|
401
401
|
// Todo this needs to account for whether it's based on initial or maintenance requirements
|
|
402
402
|
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
403
403
|
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
404
|
-
if (
|
|
405
|
-
const tokenAmount =
|
|
404
|
+
if (types_1.isVariant(spotPosition.balanceType, 'deposit')) {
|
|
405
|
+
const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
406
406
|
return totalAssetValue.add(tokenAmount);
|
|
407
407
|
}
|
|
408
408
|
else {
|
|
@@ -411,8 +411,8 @@ class User {
|
|
|
411
411
|
}
|
|
412
412
|
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
413
413
|
if (!includeOpenOrders) {
|
|
414
|
-
if (
|
|
415
|
-
const tokenAmount =
|
|
414
|
+
if (types_1.isVariant(spotPosition.balanceType, 'deposit')) {
|
|
415
|
+
const tokenAmount = spotBalance_1.getTokenAmount(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType);
|
|
416
416
|
const assetValue = this.getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory);
|
|
417
417
|
return totalAssetValue.add(assetValue);
|
|
418
418
|
}
|
|
@@ -420,7 +420,7 @@ class User {
|
|
|
420
420
|
return totalAssetValue;
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
|
-
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] =
|
|
423
|
+
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = spotPosition_1.getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, this.getOracleDataForSpotMarket(spotPosition.marketIndex));
|
|
424
424
|
let newTotalAssetValue = totalAssetValue;
|
|
425
425
|
if (worstCaseTokenAmount.gt(numericConstants_1.ZERO)) {
|
|
426
426
|
const baseAssetValue = this.getSpotAssetValue(worstCaseTokenAmount, oraclePriceData, spotMarketAccount, marginCategory);
|
|
@@ -433,9 +433,9 @@ class User {
|
|
|
433
433
|
}, numericConstants_1.ZERO);
|
|
434
434
|
}
|
|
435
435
|
getSpotAssetValue(tokenAmount, oraclePriceData, spotMarketAccount, marginCategory) {
|
|
436
|
-
let assetValue =
|
|
436
|
+
let assetValue = _1.getTokenValue(tokenAmount, spotMarketAccount.decimals, oraclePriceData);
|
|
437
437
|
if (marginCategory !== undefined) {
|
|
438
|
-
const weight =
|
|
438
|
+
const weight = spotBalance_1.calculateAssetWeight(tokenAmount, spotMarketAccount, marginCategory);
|
|
439
439
|
assetValue = assetValue.mul(weight).div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
440
440
|
}
|
|
441
441
|
return assetValue;
|
|
@@ -456,8 +456,8 @@ class User {
|
|
|
456
456
|
*/
|
|
457
457
|
getHealth() {
|
|
458
458
|
const userAccount = this.getUserAccount();
|
|
459
|
-
if (
|
|
460
|
-
|
|
459
|
+
if (types_1.isVariant(userAccount.status, 'beingLiquidated') ||
|
|
460
|
+
types_1.isVariant(userAccount.status, 'bankrupt')) {
|
|
461
461
|
return 0;
|
|
462
462
|
}
|
|
463
463
|
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
@@ -507,25 +507,25 @@ class User {
|
|
|
507
507
|
perpPosition.openBids = totalOpenBids;
|
|
508
508
|
}
|
|
509
509
|
let valuationPrice = this.getOracleDataForPerpMarket(market.marketIndex).price;
|
|
510
|
-
if (
|
|
510
|
+
if (types_1.isVariant(market.status, 'settlement')) {
|
|
511
511
|
valuationPrice = market.expiryPrice;
|
|
512
512
|
}
|
|
513
513
|
const baseAssetAmount = includeOpenOrders
|
|
514
|
-
?
|
|
514
|
+
? margin_1.calculateWorstCaseBaseAssetAmount(perpPosition)
|
|
515
515
|
: perpPosition.baseAssetAmount;
|
|
516
516
|
let baseAssetValue = baseAssetAmount
|
|
517
517
|
.abs()
|
|
518
518
|
.mul(valuationPrice)
|
|
519
519
|
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.PRICE_PRECISION));
|
|
520
520
|
if (marginCategory) {
|
|
521
|
-
let marginRatio = new _1.BN(
|
|
521
|
+
let marginRatio = new _1.BN(_1.calculateMarketMarginRatio(market, baseAssetAmount.abs(), marginCategory));
|
|
522
522
|
if (marginCategory === 'Initial') {
|
|
523
523
|
marginRatio = _1.BN.max(marginRatio, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
524
524
|
}
|
|
525
525
|
if (liquidationBuffer !== undefined) {
|
|
526
526
|
marginRatio = marginRatio.add(liquidationBuffer);
|
|
527
527
|
}
|
|
528
|
-
if (
|
|
528
|
+
if (types_1.isVariant(market.status, 'settlement')) {
|
|
529
529
|
marginRatio = numericConstants_1.ZERO;
|
|
530
530
|
}
|
|
531
531
|
baseAssetValue = baseAssetValue
|
|
@@ -545,7 +545,7 @@ class User {
|
|
|
545
545
|
getPerpPositionValue(marketIndex, oraclePriceData) {
|
|
546
546
|
const userPosition = this.getPerpPosition(marketIndex) || this.getEmptyPosition(marketIndex);
|
|
547
547
|
const market = this.driftClient.getPerpMarketAccount(userPosition.marketIndex);
|
|
548
|
-
return
|
|
548
|
+
return margin_1.calculateBaseAssetValueWithOracle(market, userPosition, oraclePriceData);
|
|
549
549
|
}
|
|
550
550
|
getPositionSide(currentPosition) {
|
|
551
551
|
if (currentPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
@@ -564,11 +564,11 @@ class User {
|
|
|
564
564
|
*/
|
|
565
565
|
getPositionEstimatedExitPriceAndPnl(position, amountToClose, useAMMClose = false) {
|
|
566
566
|
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
567
|
-
const entryPrice =
|
|
567
|
+
const entryPrice = position_1.calculateEntryPrice(position);
|
|
568
568
|
const oraclePriceData = this.getOracleDataForPerpMarket(position.marketIndex);
|
|
569
569
|
if (amountToClose) {
|
|
570
570
|
if (amountToClose.eq(numericConstants_1.ZERO)) {
|
|
571
|
-
return [
|
|
571
|
+
return [_1.calculateReservePrice(market, oraclePriceData), numericConstants_1.ZERO];
|
|
572
572
|
}
|
|
573
573
|
position = {
|
|
574
574
|
baseAssetAmount: amountToClose,
|
|
@@ -579,10 +579,10 @@ class User {
|
|
|
579
579
|
}
|
|
580
580
|
let baseAssetValue;
|
|
581
581
|
if (useAMMClose) {
|
|
582
|
-
baseAssetValue =
|
|
582
|
+
baseAssetValue = _1.calculateBaseAssetValue(market, position, oraclePriceData);
|
|
583
583
|
}
|
|
584
584
|
else {
|
|
585
|
-
baseAssetValue =
|
|
585
|
+
baseAssetValue = margin_1.calculateBaseAssetValueWithOracle(market, position, oraclePriceData);
|
|
586
586
|
}
|
|
587
587
|
if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
|
|
588
588
|
return [numericConstants_1.ZERO, numericConstants_1.ZERO];
|
|
@@ -628,7 +628,7 @@ class User {
|
|
|
628
628
|
return numericConstants_1.ZERO;
|
|
629
629
|
}
|
|
630
630
|
const totalLiabilityValue = this.getTotalLiabilityValue();
|
|
631
|
-
const marginRatio =
|
|
631
|
+
const marginRatio = _1.calculateMarketMarginRatio(market,
|
|
632
632
|
// worstCaseBaseAssetAmount.abs(),
|
|
633
633
|
numericConstants_1.ZERO, // todo
|
|
634
634
|
category);
|
|
@@ -658,7 +658,7 @@ class User {
|
|
|
658
658
|
const totalCollateral = this.getTotalCollateral('Maintenance');
|
|
659
659
|
// if user being liq'd, can continue to be liq'd until total collateral above the margin requirement plus buffer
|
|
660
660
|
let liquidationBuffer = undefined;
|
|
661
|
-
const isBeingLiquidated =
|
|
661
|
+
const isBeingLiquidated = types_1.isVariant(this.getUserAccount().status, 'beingLiquidated');
|
|
662
662
|
if (isBeingLiquidated) {
|
|
663
663
|
liquidationBuffer = new _1.BN(this.driftClient.getStateAccount().liquidationMarginBufferRatio);
|
|
664
664
|
}
|
|
@@ -666,13 +666,13 @@ class User {
|
|
|
666
666
|
return totalCollateral.lt(maintenanceRequirement);
|
|
667
667
|
}
|
|
668
668
|
isBeingLiquidated() {
|
|
669
|
-
return
|
|
669
|
+
return types_1.isOneOfVariant(this.getUserAccount().status, [
|
|
670
670
|
'beingLiquidated',
|
|
671
671
|
'bankrupt',
|
|
672
672
|
]);
|
|
673
673
|
}
|
|
674
674
|
isBankrupt() {
|
|
675
|
-
return
|
|
675
|
+
return types_1.isVariant(this.getUserAccount().status, 'bankrupt');
|
|
676
676
|
}
|
|
677
677
|
/**
|
|
678
678
|
* Checks if any user position cumulative funding differs from respective market cumulative funding
|
|
@@ -708,7 +708,7 @@ class User {
|
|
|
708
708
|
const mmr = this.getMaintenanceMarginRequirement();
|
|
709
709
|
const deltaValueToLiq = mtc.sub(mmr); // QUOTE_PRECISION
|
|
710
710
|
const currentSpotMarket = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
711
|
-
const tokenAmount =
|
|
711
|
+
const tokenAmount = spotBalance_1.getTokenAmount(currentSpotPosition.scaledBalance, currentSpotMarket, currentSpotPosition.balanceType);
|
|
712
712
|
const tokenAmountQP = tokenAmount
|
|
713
713
|
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
714
714
|
.div(new _1.BN(10 ** currentSpotMarket.decimals));
|
|
@@ -716,7 +716,7 @@ class User {
|
|
|
716
716
|
return new _1.BN(-1);
|
|
717
717
|
}
|
|
718
718
|
let liqPriceDelta;
|
|
719
|
-
if (
|
|
719
|
+
if (types_1.isVariant(currentSpotPosition.balanceType, 'borrow')) {
|
|
720
720
|
liqPriceDelta = deltaValueToLiq
|
|
721
721
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
722
722
|
.mul(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION)
|
|
@@ -780,15 +780,15 @@ class User {
|
|
|
780
780
|
if (proposedBaseAssetAmount.eq(numericConstants_1.ZERO))
|
|
781
781
|
return new _1.BN(-1);
|
|
782
782
|
const market = this.driftClient.getPerpMarketAccount(proposedPerpPosition.marketIndex);
|
|
783
|
-
const proposedPerpPositionValue =
|
|
783
|
+
const proposedPerpPositionValue = margin_1.calculateBaseAssetValueWithOracle(market, proposedPerpPosition, this.getOracleDataForPerpMarket(market.marketIndex));
|
|
784
784
|
// total position value after trade
|
|
785
785
|
const totalPositionValueAfterTrade = totalPositionValueExcludingTargetMarket.add(proposedPerpPositionValue);
|
|
786
786
|
const marginRequirementExcludingTargetMarket = this.getUserAccount().perpPositions.reduce((totalMarginRequirement, position) => {
|
|
787
787
|
if (position.marketIndex !== perpPosition.marketIndex) {
|
|
788
788
|
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
789
|
-
const positionValue =
|
|
789
|
+
const positionValue = margin_1.calculateBaseAssetValueWithOracle(market, position, this.getOracleDataForPerpMarket(market.marketIndex));
|
|
790
790
|
const marketMarginRequirement = positionValue
|
|
791
|
-
.mul(new _1.BN(
|
|
791
|
+
.mul(new _1.BN(_1.calculateMarketMarginRatio(market, position.baseAssetAmount.abs(), 'Maintenance')))
|
|
792
792
|
.div(numericConstants_1.MARGIN_PRECISION);
|
|
793
793
|
totalMarginRequirement = totalMarginRequirement.add(marketMarginRequirement);
|
|
794
794
|
}
|
|
@@ -797,11 +797,11 @@ class User {
|
|
|
797
797
|
const freeCollateralExcludingTargetMarket = totalCollateral.sub(marginRequirementExcludingTargetMarket);
|
|
798
798
|
// if the position value after the trade is less than free collateral, there is no liq price
|
|
799
799
|
if (totalPositionValueAfterTrade.lte(freeCollateralExcludingTargetMarket) &&
|
|
800
|
-
proposedPerpPosition.baseAssetAmount.
|
|
800
|
+
proposedPerpPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
|
|
801
801
|
return new _1.BN(-1);
|
|
802
802
|
}
|
|
803
803
|
const marginRequirementAfterTrade = marginRequirementExcludingTargetMarket.add(proposedPerpPositionValue
|
|
804
|
-
.mul(new _1.BN(
|
|
804
|
+
.mul(new _1.BN(_1.calculateMarketMarginRatio(market, proposedPerpPosition.baseAssetAmount.abs(), 'Maintenance')))
|
|
805
805
|
.div(numericConstants_1.MARGIN_PRECISION));
|
|
806
806
|
const freeCollateralAfterTrade = totalCollateral.sub(marginRequirementAfterTrade);
|
|
807
807
|
const marketMaxLeverage = this.getMaxLeverage(proposedPerpPosition.marketIndex, 'Maintenance');
|
|
@@ -824,13 +824,13 @@ class User {
|
|
|
824
824
|
}
|
|
825
825
|
let markPriceAfterTrade;
|
|
826
826
|
if (positionBaseSizeChange.eq(numericConstants_1.ZERO)) {
|
|
827
|
-
markPriceAfterTrade =
|
|
827
|
+
markPriceAfterTrade = _1.calculateReservePrice(this.driftClient.getPerpMarketAccount(perpPosition.marketIndex), this.getOracleDataForPerpMarket(perpPosition.marketIndex));
|
|
828
828
|
}
|
|
829
829
|
else {
|
|
830
830
|
const direction = positionBaseSizeChange.gt(numericConstants_1.ZERO)
|
|
831
831
|
? _1.PositionDirection.LONG
|
|
832
832
|
: _1.PositionDirection.SHORT;
|
|
833
|
-
markPriceAfterTrade =
|
|
833
|
+
markPriceAfterTrade = _1.calculateTradeSlippage(direction, positionBaseSizeChange.abs(), this.driftClient.getPerpMarketAccount(perpPosition.marketIndex), 'base', this.getOracleDataForPerpMarket(perpPosition.marketIndex))[3]; // newPrice after swap
|
|
834
834
|
}
|
|
835
835
|
if (priceDelta.gt(markPriceAfterTrade)) {
|
|
836
836
|
return new _1.BN(-1);
|
|
@@ -881,7 +881,7 @@ class User {
|
|
|
881
881
|
getMaxTradeSizeUSDC(targetMarketIndex, tradeSide) {
|
|
882
882
|
const currentPosition = this.getPerpPosition(targetMarketIndex) ||
|
|
883
883
|
this.getEmptyPosition(targetMarketIndex);
|
|
884
|
-
const targetSide =
|
|
884
|
+
const targetSide = types_1.isVariant(tradeSide, 'short') ? 'short' : 'long';
|
|
885
885
|
const currentPositionSide = (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())
|
|
886
886
|
? 'short'
|
|
887
887
|
: 'long';
|
|
@@ -992,7 +992,7 @@ class User {
|
|
|
992
992
|
getWithdrawalLimit(marketIndex, reduceOnly) {
|
|
993
993
|
const nowTs = new _1.BN(Math.floor(Date.now() / 1000));
|
|
994
994
|
const spotMarket = this.driftClient.getSpotMarketAccount(marketIndex);
|
|
995
|
-
const { borrowLimit, withdrawLimit } =
|
|
995
|
+
const { borrowLimit, withdrawLimit } = spotBalance_1.calculateWithdrawLimit(spotMarket, nowTs);
|
|
996
996
|
const freeCollateral = this.getFreeCollateral();
|
|
997
997
|
const oracleData = this.getOracleDataForSpotMarket(marketIndex);
|
|
998
998
|
const precisionIncrease = numericConstants_1.TEN.pow(new _1.BN(spotMarket.decimals - 6));
|
|
@@ -1002,10 +1002,10 @@ class User {
|
|
|
1002
1002
|
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1003
1003
|
.div(oracleData.price)
|
|
1004
1004
|
.mul(precisionIncrease);
|
|
1005
|
-
const userSpotPosition = this.getUserAccount().spotPositions.find((spotPosition) =>
|
|
1005
|
+
const userSpotPosition = this.getUserAccount().spotPositions.find((spotPosition) => types_1.isVariant(spotPosition.balanceType, 'deposit') &&
|
|
1006
1006
|
spotPosition.marketIndex == marketIndex);
|
|
1007
1007
|
const userSpotBalance = userSpotPosition
|
|
1008
|
-
?
|
|
1008
|
+
? spotBalance_1.getTokenAmount(userSpotPosition.scaledBalance, this.driftClient.getSpotMarketAccount(marketIndex), _1.SpotBalanceType.DEPOSIT)
|
|
1009
1009
|
: numericConstants_1.ZERO;
|
|
1010
1010
|
const maxWithdrawValue = _1.BN.min(_1.BN.min(amountWithdrawable, userSpotBalance), withdrawLimit.abs());
|
|
1011
1011
|
if (reduceOnly) {
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -26,7 +26,7 @@ class UserMap {
|
|
|
26
26
|
userAccountArray.push(programUserAccount.account);
|
|
27
27
|
}
|
|
28
28
|
if (this.accountSubscription.type === 'polling') {
|
|
29
|
-
await
|
|
29
|
+
await __1.bulkPollingUserSubscribe(userArray, this.accountSubscription.accountLoader);
|
|
30
30
|
}
|
|
31
31
|
else {
|
|
32
32
|
await Promise.all(userArray.map((user, i) => user.subscribe(userAccountArray[i])));
|
|
@@ -23,14 +23,14 @@ class UserStatsMap {
|
|
|
23
23
|
}
|
|
24
24
|
const chUserStat = new __1.UserStats({
|
|
25
25
|
driftClient: this.driftClient,
|
|
26
|
-
userStatsAccountPublicKey:
|
|
26
|
+
userStatsAccountPublicKey: __1.getUserStatsAccountPublicKey(this.driftClient.program.programId, userStat.authority),
|
|
27
27
|
accountSubscription: this.accountSubscription,
|
|
28
28
|
});
|
|
29
29
|
userStatArray.push(chUserStat);
|
|
30
30
|
userStatsAccountArray.push(userStat);
|
|
31
31
|
}
|
|
32
32
|
if (this.accountSubscription.type === 'polling') {
|
|
33
|
-
await
|
|
33
|
+
await __1.bulkPollingUserStatsSubscribe(userStatArray, this.accountSubscription.accountLoader);
|
|
34
34
|
}
|
|
35
35
|
else {
|
|
36
36
|
await Promise.all(userStatArray.map((userStat, i) => userStat.subscribe(userStatsAccountArray[i])));
|
|
@@ -42,7 +42,7 @@ class UserStatsMap {
|
|
|
42
42
|
async addUserStat(authority) {
|
|
43
43
|
const userStat = new __1.UserStats({
|
|
44
44
|
driftClient: this.driftClient,
|
|
45
|
-
userStatsAccountPublicKey:
|
|
45
|
+
userStatsAccountPublicKey: __1.getUserStatsAccountPublicKey(this.driftClient.program.programId, authority),
|
|
46
46
|
accountSubscription: this.accountSubscription,
|
|
47
47
|
});
|
|
48
48
|
await userStat.subscribe();
|
package/lib/userStats.js
CHANGED
|
@@ -40,8 +40,8 @@ class UserStats {
|
|
|
40
40
|
}
|
|
41
41
|
else {
|
|
42
42
|
return {
|
|
43
|
-
referrer:
|
|
44
|
-
referrerStats:
|
|
43
|
+
referrer: pda_1.getUserAccountPublicKeySync(this.driftClient.program.programId, this.getAccount().referrer, 0),
|
|
44
|
+
referrerStats: pda_1.getUserStatsAccountPublicKey(this.driftClient.program.programId, this.getAccount().referrer),
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
}
|
package/package.json
CHANGED
package/src/driftClient.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
OrderType,
|
|
23
23
|
ReferrerInfo,
|
|
24
24
|
MarketType,
|
|
25
|
+
TxParams,
|
|
25
26
|
SerumV3FulfillmentConfigAccount,
|
|
26
27
|
isVariant,
|
|
27
28
|
} from './types';
|
|
@@ -2248,7 +2249,8 @@ export class DriftClient {
|
|
|
2248
2249
|
order?: Order,
|
|
2249
2250
|
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
2250
2251
|
makerInfo?: MakerInfo,
|
|
2251
|
-
referrerInfo?: ReferrerInfo
|
|
2252
|
+
referrerInfo?: ReferrerInfo,
|
|
2253
|
+
txParams?: TxParams
|
|
2252
2254
|
): Promise<TransactionSignature> {
|
|
2253
2255
|
const { txSig } = await this.sendTransaction(
|
|
2254
2256
|
wrapInTx(
|
|
@@ -2259,7 +2261,9 @@ export class DriftClient {
|
|
|
2259
2261
|
fulfillmentConfig,
|
|
2260
2262
|
makerInfo,
|
|
2261
2263
|
referrerInfo
|
|
2262
|
-
)
|
|
2264
|
+
),
|
|
2265
|
+
txParams?.computeUnits,
|
|
2266
|
+
txParams?.computeUnitsPrice
|
|
2263
2267
|
),
|
|
2264
2268
|
[],
|
|
2265
2269
|
this.opts
|
|
@@ -2704,7 +2708,8 @@ export class DriftClient {
|
|
|
2704
2708
|
orderParams: OptionalOrderParams,
|
|
2705
2709
|
fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
|
|
2706
2710
|
makerInfo?: MakerInfo,
|
|
2707
|
-
referrerInfo?: ReferrerInfo
|
|
2711
|
+
referrerInfo?: ReferrerInfo,
|
|
2712
|
+
txParams?: TxParams
|
|
2708
2713
|
): Promise<TransactionSignature> {
|
|
2709
2714
|
const { txSig, slot } = await this.sendTransaction(
|
|
2710
2715
|
wrapInTx(
|
|
@@ -2713,7 +2718,9 @@ export class DriftClient {
|
|
|
2713
2718
|
fulfillmentConfig,
|
|
2714
2719
|
makerInfo,
|
|
2715
2720
|
referrerInfo
|
|
2716
|
-
)
|
|
2721
|
+
),
|
|
2722
|
+
txParams?.computeUnits,
|
|
2723
|
+
txParams?.computeUnitsPrice
|
|
2717
2724
|
),
|
|
2718
2725
|
[],
|
|
2719
2726
|
this.opts
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.12.0-beta.
|
|
2
|
+
"version": "2.12.0-beta.3",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -3705,9 +3705,7 @@
|
|
|
3705
3705
|
"args": [
|
|
3706
3706
|
{
|
|
3707
3707
|
"name": "exchangeStatus",
|
|
3708
|
-
"type":
|
|
3709
|
-
"defined": "ExchangeStatus"
|
|
3710
|
-
}
|
|
3708
|
+
"type": "u8"
|
|
3711
3709
|
}
|
|
3712
3710
|
]
|
|
3713
3711
|
},
|
|
@@ -4384,9 +4382,7 @@
|
|
|
4384
4382
|
},
|
|
4385
4383
|
{
|
|
4386
4384
|
"name": "exchangeStatus",
|
|
4387
|
-
"type":
|
|
4388
|
-
"defined": "ExchangeStatus"
|
|
4389
|
-
}
|
|
4385
|
+
"type": "u8"
|
|
4390
4386
|
},
|
|
4391
4387
|
{
|
|
4392
4388
|
"name": "liquidationDuration",
|
|
@@ -6360,10 +6356,10 @@
|
|
|
6360
6356
|
"kind": "enum",
|
|
6361
6357
|
"variants": [
|
|
6362
6358
|
{
|
|
6363
|
-
"name": "
|
|
6359
|
+
"name": "DepositPaused"
|
|
6364
6360
|
},
|
|
6365
6361
|
{
|
|
6366
|
-
"name": "
|
|
6362
|
+
"name": "WithdrawPaused"
|
|
6367
6363
|
},
|
|
6368
6364
|
{
|
|
6369
6365
|
"name": "AmmPaused"
|
|
@@ -6375,10 +6371,10 @@
|
|
|
6375
6371
|
"name": "LiqPaused"
|
|
6376
6372
|
},
|
|
6377
6373
|
{
|
|
6378
|
-
"name": "
|
|
6374
|
+
"name": "FundingPaused"
|
|
6379
6375
|
},
|
|
6380
6376
|
{
|
|
6381
|
-
"name": "
|
|
6377
|
+
"name": "SettlePnlPaused"
|
|
6382
6378
|
}
|
|
6383
6379
|
]
|
|
6384
6380
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
|
+
ExchangeStatus,
|
|
2
3
|
isOneOfVariant,
|
|
3
|
-
isVariant,
|
|
4
4
|
PerpMarketAccount,
|
|
5
5
|
SpotMarketAccount,
|
|
6
6
|
StateAccount,
|
|
7
7
|
} from '../types';
|
|
8
8
|
|
|
9
9
|
export function exchangePaused(state: StateAccount): boolean {
|
|
10
|
-
return
|
|
10
|
+
return state.exchangeStatus !== ExchangeStatus.ACTIVE;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export function fillPaused(
|
|
@@ -15,7 +15,8 @@ export function fillPaused(
|
|
|
15
15
|
market: PerpMarketAccount | SpotMarketAccount
|
|
16
16
|
): boolean {
|
|
17
17
|
return (
|
|
18
|
-
|
|
18
|
+
(state.exchangeStatus & ExchangeStatus.FILL_PAUSED) ===
|
|
19
|
+
ExchangeStatus.FILL_PAUSED ||
|
|
19
20
|
isOneOfVariant(market.status, ['paused', 'fillPaused'])
|
|
20
21
|
);
|
|
21
22
|
}
|
|
@@ -25,7 +26,8 @@ export function ammPaused(
|
|
|
25
26
|
market: PerpMarketAccount | SpotMarketAccount
|
|
26
27
|
): boolean {
|
|
27
28
|
return (
|
|
28
|
-
|
|
29
|
+
(state.exchangeStatus & ExchangeStatus.AMM_PAUSED) ===
|
|
30
|
+
ExchangeStatus.AMM_PAUSED ||
|
|
29
31
|
isOneOfVariant(market.status, ['paused', 'ammPaused'])
|
|
30
32
|
);
|
|
31
33
|
}
|
package/src/tx/utils.ts
CHANGED
|
@@ -8,14 +8,22 @@ const COMPUTE_UNITS_DEFAULT = 200_000;
|
|
|
8
8
|
|
|
9
9
|
export function wrapInTx(
|
|
10
10
|
instruction: TransactionInstruction,
|
|
11
|
-
computeUnits = 600_000
|
|
11
|
+
computeUnits = 600_000,
|
|
12
|
+
computeUnitsPrice = 0
|
|
12
13
|
): Transaction {
|
|
13
14
|
const tx = new Transaction();
|
|
14
15
|
if (computeUnits != COMPUTE_UNITS_DEFAULT) {
|
|
15
16
|
tx.add(
|
|
16
|
-
ComputeBudgetProgram.
|
|
17
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
17
18
|
units: computeUnits,
|
|
18
|
-
|
|
19
|
+
})
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (computeUnitsPrice != 0) {
|
|
24
|
+
tx.add(
|
|
25
|
+
ComputeBudgetProgram.setComputeUnitPrice({
|
|
26
|
+
microLamports: computeUnitsPrice,
|
|
19
27
|
})
|
|
20
28
|
);
|
|
21
29
|
}
|
package/src/types.ts
CHANGED
|
@@ -3,14 +3,16 @@ import { BN, ZERO } from '.';
|
|
|
3
3
|
|
|
4
4
|
// # Utility Types / Enums / Constants
|
|
5
5
|
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
export enum ExchangeStatus {
|
|
7
|
+
ACTIVE = 0,
|
|
8
|
+
DEPOSIT_PAUSED = 1,
|
|
9
|
+
WITHDRAW_PAUSED = 2,
|
|
10
|
+
AMM_PAUSED = 4,
|
|
11
|
+
FILL_PAUSED = 8,
|
|
12
|
+
LIQ_PAUSED = 16,
|
|
13
|
+
FUNDING_PAUSED = 32,
|
|
14
|
+
SETTLE_PNL_PAUSED = 64,
|
|
15
|
+
PAUSED = 127,
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
export class MarketStatus {
|
|
@@ -501,7 +503,7 @@ export type OrderActionRecord = {
|
|
|
501
503
|
|
|
502
504
|
export type StateAccount = {
|
|
503
505
|
admin: PublicKey;
|
|
504
|
-
exchangeStatus:
|
|
506
|
+
exchangeStatus: number;
|
|
505
507
|
whitelistMint: PublicKey;
|
|
506
508
|
discountMint: PublicKey;
|
|
507
509
|
oracleGuardRails: OracleGuardRails;
|
|
@@ -907,6 +909,11 @@ export type ReferrerInfo = {
|
|
|
907
909
|
referrerStats: PublicKey;
|
|
908
910
|
};
|
|
909
911
|
|
|
912
|
+
export type TxParams = {
|
|
913
|
+
computeUnits?: number;
|
|
914
|
+
computeUnitsPrice?: number;
|
|
915
|
+
};
|
|
916
|
+
|
|
910
917
|
// # Misc Types
|
|
911
918
|
export interface IWallet {
|
|
912
919
|
signTransaction(tx: Transaction): Promise<Transaction>;
|
package/src/user.ts
CHANGED
|
@@ -1335,7 +1335,7 @@ export class User {
|
|
|
1335
1335
|
// if the position value after the trade is less than free collateral, there is no liq price
|
|
1336
1336
|
if (
|
|
1337
1337
|
totalPositionValueAfterTrade.lte(freeCollateralExcludingTargetMarket) &&
|
|
1338
|
-
proposedPerpPosition.baseAssetAmount.
|
|
1338
|
+
proposedPerpPosition.baseAssetAmount.gt(ZERO)
|
|
1339
1339
|
) {
|
|
1340
1340
|
return new BN(-1);
|
|
1341
1341
|
}
|
package/tests/dlob/helpers.ts
CHANGED
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
UserMapInterface,
|
|
20
20
|
Wallet,
|
|
21
21
|
OrderRecord,
|
|
22
|
-
ExchangeStatus,
|
|
23
22
|
ZERO,
|
|
24
23
|
ContractTier,
|
|
25
24
|
} from '../../src';
|
|
@@ -478,7 +477,7 @@ export const mockStateAccount: StateAccount = {
|
|
|
478
477
|
defaultMarketOrderTimeInForce: 0,
|
|
479
478
|
defaultSpotAuctionDuration: 0,
|
|
480
479
|
discountMint: PublicKey.default,
|
|
481
|
-
exchangeStatus:
|
|
480
|
+
exchangeStatus: 0,
|
|
482
481
|
liquidationMarginBufferRatio: 0,
|
|
483
482
|
lpCooldownTime: new BN(0),
|
|
484
483
|
minPerpAuctionDuration: 0,
|