@drift-labs/sdk 2.37.1-beta.0 → 2.37.1-beta.10
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/adminClient.d.ts +1 -0
- package/lib/adminClient.js +10 -0
- package/lib/constants/perpMarkets.js +20 -0
- package/lib/events/eventSubscriber.js +3 -0
- package/lib/events/fetchLogs.js +3 -0
- package/lib/events/types.d.ts +1 -0
- package/lib/idl/drift.json +73 -8
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/math/auction.js +1 -1
- package/lib/orderSubscriber/OrderSubscriber.d.ts +5 -1
- package/lib/orderSubscriber/OrderSubscriber.js +10 -0
- package/lib/orderSubscriber/types.d.ts +5 -0
- package/lib/tx/baseTxSender.d.ts +30 -0
- package/lib/tx/baseTxSender.js +176 -0
- package/lib/tx/fastSingleTxSender.d.ts +27 -0
- package/lib/tx/fastSingleTxSender.js +83 -0
- package/lib/tx/retryTxSender.d.ts +5 -14
- package/lib/tx/retryTxSender.js +7 -158
- package/lib/types.d.ts +18 -0
- package/lib/types.js +1 -0
- package/lib/user.d.ts +10 -1
- package/lib/user.js +259 -61
- package/package.json +2 -2
- package/src/adminClient.ts +18 -0
- package/src/constants/perpMarkets.ts +20 -0
- package/src/events/eventSubscriber.ts +3 -0
- package/src/events/fetchLogs.ts +3 -0
- package/src/events/types.ts +1 -0
- package/src/idl/drift.json +73 -8
- package/src/index.ts +1 -0
- package/src/marinade/types.ts +70 -70
- package/src/math/auction.ts +1 -1
- package/src/orderSubscriber/OrderSubscriber.ts +19 -2
- package/src/orderSubscriber/types.ts +11 -0
- package/src/tx/baseTxSender.ts +276 -0
- package/src/tx/fastSingleTxSender.ts +142 -0
- package/src/tx/retryTxSender.ts +9 -235
- package/src/types.ts +19 -0
- package/src/user.ts +441 -101
- package/tests/amm/test.ts +83 -39
- package/tests/dlob/helpers.ts +2 -0
- package/tests/dlob/test.ts +19 -17
package/lib/user.js
CHANGED
|
@@ -145,6 +145,7 @@ class User {
|
|
|
145
145
|
lpShares: numericConstants_1.ZERO,
|
|
146
146
|
lastBaseAssetAmountPerLp: numericConstants_1.ZERO,
|
|
147
147
|
lastQuoteAssetAmountPerLp: numericConstants_1.ZERO,
|
|
148
|
+
perLpBase: 0,
|
|
148
149
|
};
|
|
149
150
|
}
|
|
150
151
|
getClonedPosition(position) {
|
|
@@ -258,17 +259,54 @@ class User {
|
|
|
258
259
|
}
|
|
259
260
|
const position = this.getClonedPosition(originalPosition);
|
|
260
261
|
const market = this.driftClient.getPerpMarketAccount(position.marketIndex);
|
|
262
|
+
if (market.amm.perLpBase != position.perLpBase) {
|
|
263
|
+
// perLpBase = 1 => per 10 LP shares, perLpBase = -1 => per 0.1 LP shares
|
|
264
|
+
const expoDiff = market.amm.perLpBase - position.perLpBase;
|
|
265
|
+
const marketPerLpRebaseScalar = new _1.BN(10 ** Math.abs(expoDiff));
|
|
266
|
+
if (expoDiff > 0) {
|
|
267
|
+
position.lastBaseAssetAmountPerLp =
|
|
268
|
+
position.lastBaseAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
269
|
+
position.lastQuoteAssetAmountPerLp =
|
|
270
|
+
position.lastQuoteAssetAmountPerLp.mul(marketPerLpRebaseScalar);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
position.lastBaseAssetAmountPerLp =
|
|
274
|
+
position.lastBaseAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
275
|
+
position.lastQuoteAssetAmountPerLp =
|
|
276
|
+
position.lastQuoteAssetAmountPerLp.div(marketPerLpRebaseScalar);
|
|
277
|
+
}
|
|
278
|
+
position.perLpBase = position.perLpBase + expoDiff;
|
|
279
|
+
}
|
|
261
280
|
const nShares = position.lpShares;
|
|
262
281
|
// incorp unsettled funding on pre settled position
|
|
263
282
|
const quoteFundingPnl = (0, _1.calculatePositionFundingPNL)(market, position);
|
|
283
|
+
let baseUnit = numericConstants_1.AMM_RESERVE_PRECISION;
|
|
284
|
+
if (market.amm.perLpBase == position.perLpBase) {
|
|
285
|
+
if (position.perLpBase >= 0 &&
|
|
286
|
+
position.perLpBase <= numericConstants_1.AMM_RESERVE_PRECISION_EXP.toNumber()) {
|
|
287
|
+
const marketPerLpRebase = new _1.BN(10 ** market.amm.perLpBase);
|
|
288
|
+
baseUnit = baseUnit.mul(marketPerLpRebase);
|
|
289
|
+
}
|
|
290
|
+
else if (position.perLpBase < 0 &&
|
|
291
|
+
position.perLpBase >= -numericConstants_1.AMM_RESERVE_PRECISION_EXP.toNumber()) {
|
|
292
|
+
const marketPerLpRebase = new _1.BN(10 ** Math.abs(market.amm.perLpBase));
|
|
293
|
+
baseUnit = baseUnit.div(marketPerLpRebase);
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
throw 'cannot calc';
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
throw 'market.amm.perLpBase != position.perLpBase';
|
|
301
|
+
}
|
|
264
302
|
const deltaBaa = market.amm.baseAssetAmountPerLp
|
|
265
303
|
.sub(position.lastBaseAssetAmountPerLp)
|
|
266
304
|
.mul(nShares)
|
|
267
|
-
.div(
|
|
305
|
+
.div(baseUnit);
|
|
268
306
|
const deltaQaa = market.amm.quoteAssetAmountPerLp
|
|
269
307
|
.sub(position.lastQuoteAssetAmountPerLp)
|
|
270
308
|
.mul(nShares)
|
|
271
|
-
.div(
|
|
309
|
+
.div(baseUnit);
|
|
272
310
|
function sign(v) {
|
|
273
311
|
return v.isNeg() ? new _1.BN(-1) : new _1.BN(1);
|
|
274
312
|
}
|
|
@@ -464,7 +502,7 @@ class User {
|
|
|
464
502
|
}
|
|
465
503
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
466
504
|
.mul(quotePrice)
|
|
467
|
-
.div(
|
|
505
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
468
506
|
if (withWeightMarginCategory !== undefined) {
|
|
469
507
|
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
470
508
|
positionUnrealizedPnl = positionUnrealizedPnl
|
|
@@ -660,64 +698,81 @@ class User {
|
|
|
660
698
|
}
|
|
661
699
|
return health;
|
|
662
700
|
}
|
|
701
|
+
calculateWeightedPerpPositionValue(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
702
|
+
const market = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
703
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
704
|
+
// is an lp, clone so we dont mutate the position
|
|
705
|
+
perpPosition = this.getPerpPositionWithLPSettle(market.marketIndex, this.getClonedPosition(perpPosition), !!marginCategory)[0];
|
|
706
|
+
}
|
|
707
|
+
let valuationPrice = this.getOracleDataForPerpMarket(market.marketIndex).price;
|
|
708
|
+
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
709
|
+
valuationPrice = market.expiryPrice;
|
|
710
|
+
}
|
|
711
|
+
const baseAssetAmount = includeOpenOrders
|
|
712
|
+
? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
|
|
713
|
+
: perpPosition.baseAssetAmount;
|
|
714
|
+
let baseAssetValue = baseAssetAmount
|
|
715
|
+
.abs()
|
|
716
|
+
.mul(valuationPrice)
|
|
717
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
718
|
+
if (marginCategory) {
|
|
719
|
+
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory));
|
|
720
|
+
if (marginCategory === 'Initial') {
|
|
721
|
+
marginRatio = _1.BN.max(marginRatio, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
722
|
+
}
|
|
723
|
+
if (liquidationBuffer !== undefined) {
|
|
724
|
+
marginRatio = marginRatio.add(liquidationBuffer);
|
|
725
|
+
}
|
|
726
|
+
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
727
|
+
marginRatio = numericConstants_1.ZERO;
|
|
728
|
+
}
|
|
729
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
|
|
730
|
+
const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(quoteSpotMarket.oracle).data;
|
|
731
|
+
let quotePrice;
|
|
732
|
+
if (strict) {
|
|
733
|
+
quotePrice = _1.BN.max(quoteOraclePriceData.price, quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min);
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
736
|
+
quotePrice = quoteOraclePriceData.price;
|
|
737
|
+
}
|
|
738
|
+
baseAssetValue = baseAssetValue
|
|
739
|
+
.mul(quotePrice)
|
|
740
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
741
|
+
.mul(marginRatio)
|
|
742
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
743
|
+
if (includeOpenOrders) {
|
|
744
|
+
baseAssetValue = baseAssetValue.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
745
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
746
|
+
baseAssetValue = baseAssetValue.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, valuationPrice
|
|
747
|
+
.mul(market.amm.orderStepSize)
|
|
748
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
749
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
750
|
+
.div(numericConstants_1.PRICE_PRECISION)));
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return baseAssetValue;
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* calculates position value of a single perp market in margin system
|
|
758
|
+
* @returns : Precision QUOTE_PRECISION
|
|
759
|
+
*/
|
|
760
|
+
getPerpMarketLiabilityValue(marketIndex, marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
761
|
+
const perpPosition = this.getPerpPosition(marketIndex);
|
|
762
|
+
if (!perpPosition) {
|
|
763
|
+
return numericConstants_1.ZERO;
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
return this.calculateWeightedPerpPositionValue(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
663
769
|
/**
|
|
664
770
|
* calculates sum of position value across all positions in margin system
|
|
665
771
|
* @returns : Precision QUOTE_PRECISION
|
|
666
772
|
*/
|
|
667
773
|
getTotalPerpPositionValue(marginCategory, liquidationBuffer, includeOpenOrders, strict = false) {
|
|
668
774
|
return this.getActivePerpPositions().reduce((totalPerpValue, perpPosition) => {
|
|
669
|
-
const
|
|
670
|
-
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
671
|
-
// is an lp, clone so we dont mutate the position
|
|
672
|
-
perpPosition = this.getPerpPositionWithLPSettle(market.marketIndex, this.getClonedPosition(perpPosition), !!marginCategory)[0];
|
|
673
|
-
}
|
|
674
|
-
let valuationPrice = this.getOracleDataForPerpMarket(market.marketIndex).price;
|
|
675
|
-
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
676
|
-
valuationPrice = market.expiryPrice;
|
|
677
|
-
}
|
|
678
|
-
const baseAssetAmount = includeOpenOrders
|
|
679
|
-
? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
|
|
680
|
-
: perpPosition.baseAssetAmount;
|
|
681
|
-
let baseAssetValue = baseAssetAmount
|
|
682
|
-
.abs()
|
|
683
|
-
.mul(valuationPrice)
|
|
684
|
-
.div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.PRICE_PRECISION));
|
|
685
|
-
if (marginCategory) {
|
|
686
|
-
let marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, baseAssetAmount.abs(), marginCategory));
|
|
687
|
-
if (marginCategory === 'Initial') {
|
|
688
|
-
marginRatio = _1.BN.max(marginRatio, new _1.BN(this.getUserAccount().maxMarginRatio));
|
|
689
|
-
}
|
|
690
|
-
if (liquidationBuffer !== undefined) {
|
|
691
|
-
marginRatio = marginRatio.add(liquidationBuffer);
|
|
692
|
-
}
|
|
693
|
-
if ((0, types_1.isVariant)(market.status, 'settlement')) {
|
|
694
|
-
marginRatio = numericConstants_1.ZERO;
|
|
695
|
-
}
|
|
696
|
-
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(market.quoteSpotMarketIndex);
|
|
697
|
-
const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(quoteSpotMarket.oracle).data;
|
|
698
|
-
let quotePrice;
|
|
699
|
-
if (strict) {
|
|
700
|
-
quotePrice = _1.BN.max(quoteOraclePriceData.price, quoteSpotMarket.historicalOracleData.lastOraclePriceTwap5Min);
|
|
701
|
-
}
|
|
702
|
-
else {
|
|
703
|
-
quotePrice = quoteOraclePriceData.price;
|
|
704
|
-
}
|
|
705
|
-
baseAssetValue = baseAssetValue
|
|
706
|
-
.mul(quotePrice)
|
|
707
|
-
.div(numericConstants_1.PRICE_PRECISION)
|
|
708
|
-
.mul(marginRatio)
|
|
709
|
-
.div(numericConstants_1.MARGIN_PRECISION);
|
|
710
|
-
if (includeOpenOrders) {
|
|
711
|
-
baseAssetValue = baseAssetValue.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
712
|
-
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
713
|
-
baseAssetValue = baseAssetValue.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, valuationPrice
|
|
714
|
-
.mul(market.amm.orderStepSize)
|
|
715
|
-
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
716
|
-
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
717
|
-
.div(numericConstants_1.PRICE_PRECISION)));
|
|
718
|
-
}
|
|
719
|
-
}
|
|
720
|
-
}
|
|
775
|
+
const baseAssetValue = this.calculateWeightedPerpPositionValue(perpPosition, marginCategory, liquidationBuffer, includeOpenOrders, strict);
|
|
721
776
|
return totalPerpValue.add(baseAssetValue);
|
|
722
777
|
}, numericConstants_1.ZERO);
|
|
723
778
|
}
|
|
@@ -1589,12 +1644,15 @@ class User {
|
|
|
1589
1644
|
if (canBypass) {
|
|
1590
1645
|
withdrawLimit = _1.BN.max(withdrawLimit, userDepositAmount);
|
|
1591
1646
|
}
|
|
1592
|
-
const
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1647
|
+
const assetWeight = (0, spotBalance_1.calculateAssetWeight)(userDepositAmount, spotMarket, 'Initial');
|
|
1648
|
+
const amountWithdrawable = assetWeight.eq(numericConstants_1.ZERO)
|
|
1649
|
+
? userDepositAmount
|
|
1650
|
+
: freeCollateral
|
|
1651
|
+
.mul(numericConstants_1.MARGIN_PRECISION)
|
|
1652
|
+
.div(assetWeight)
|
|
1653
|
+
.mul(numericConstants_1.PRICE_PRECISION)
|
|
1654
|
+
.div(oracleData.price)
|
|
1655
|
+
.mul(precisionIncrease);
|
|
1598
1656
|
const maxWithdrawValue = _1.BN.min(_1.BN.min(amountWithdrawable, userDepositAmount), withdrawLimit.abs());
|
|
1599
1657
|
if (reduceOnly) {
|
|
1600
1658
|
return _1.BN.max(maxWithdrawValue, numericConstants_1.ZERO);
|
|
@@ -1702,6 +1760,146 @@ class User {
|
|
|
1702
1760
|
spotTier: safestSpotTier,
|
|
1703
1761
|
};
|
|
1704
1762
|
}
|
|
1763
|
+
getHealthComponents({ marginCategory, }) {
|
|
1764
|
+
const healthComponents = {
|
|
1765
|
+
deposits: [],
|
|
1766
|
+
borrows: [],
|
|
1767
|
+
perpPositions: [],
|
|
1768
|
+
perpPnl: [],
|
|
1769
|
+
};
|
|
1770
|
+
for (const perpPosition of this.getActivePerpPositions()) {
|
|
1771
|
+
const perpMarket = this.driftClient.getPerpMarketAccount(perpPosition.marketIndex);
|
|
1772
|
+
const oraclePriceData = this.driftClient.getOraclePriceDataAndSlot(perpMarket.amm.oracle).data;
|
|
1773
|
+
const oraclePrice = oraclePriceData.price;
|
|
1774
|
+
const worstCaseBaseAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition);
|
|
1775
|
+
const marginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(perpMarket, worstCaseBaseAmount.abs(), marginCategory));
|
|
1776
|
+
const quoteSpotMarket = this.driftClient.getSpotMarketAccount(perpMarket.quoteSpotMarketIndex);
|
|
1777
|
+
const quoteOraclePriceData = this.driftClient.getOraclePriceDataAndSlot(quoteSpotMarket.oracle).data;
|
|
1778
|
+
const baseAssetValue = worstCaseBaseAmount
|
|
1779
|
+
.abs()
|
|
1780
|
+
.mul(oraclePrice)
|
|
1781
|
+
.div(numericConstants_1.BASE_PRECISION);
|
|
1782
|
+
let marginRequirement = baseAssetValue
|
|
1783
|
+
.mul(quoteOraclePriceData.price)
|
|
1784
|
+
.div(numericConstants_1.PRICE_PRECISION)
|
|
1785
|
+
.mul(marginRatio)
|
|
1786
|
+
.div(numericConstants_1.MARGIN_PRECISION);
|
|
1787
|
+
marginRequirement = marginRequirement.add(new _1.BN(perpPosition.openOrders).mul(numericConstants_1.OPEN_ORDER_MARGIN_REQUIREMENT));
|
|
1788
|
+
if (perpPosition.lpShares.gt(numericConstants_1.ZERO)) {
|
|
1789
|
+
marginRequirement = marginRequirement.add(_1.BN.max(numericConstants_1.QUOTE_PRECISION, oraclePrice
|
|
1790
|
+
.mul(perpMarket.amm.orderStepSize)
|
|
1791
|
+
.mul(numericConstants_1.QUOTE_PRECISION)
|
|
1792
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
1793
|
+
.div(numericConstants_1.PRICE_PRECISION)));
|
|
1794
|
+
}
|
|
1795
|
+
healthComponents.perpPositions.push({
|
|
1796
|
+
marketIndex: perpMarket.marketIndex,
|
|
1797
|
+
size: worstCaseBaseAmount,
|
|
1798
|
+
value: baseAssetValue,
|
|
1799
|
+
weight: marginRatio,
|
|
1800
|
+
weightedValue: marginRequirement,
|
|
1801
|
+
});
|
|
1802
|
+
const settledPerpPosition = this.getPerpPositionWithLPSettle(perpPosition.marketIndex, perpPosition)[0];
|
|
1803
|
+
const positionUnrealizedPnl = (0, _1.calculatePositionPNL)(perpMarket, settledPerpPosition, true, oraclePriceData);
|
|
1804
|
+
let pnlWeight;
|
|
1805
|
+
if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
|
|
1806
|
+
pnlWeight = (0, _1.calculateUnrealizedAssetWeight)(perpMarket, quoteSpotMarket, positionUnrealizedPnl, marginCategory, oraclePriceData);
|
|
1807
|
+
}
|
|
1808
|
+
else {
|
|
1809
|
+
pnlWeight = numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION;
|
|
1810
|
+
}
|
|
1811
|
+
const pnlValue = positionUnrealizedPnl
|
|
1812
|
+
.mul(quoteOraclePriceData.price)
|
|
1813
|
+
.div(numericConstants_1.PRICE_PRECISION);
|
|
1814
|
+
const wegithedPnlValue = pnlValue
|
|
1815
|
+
.mul(pnlWeight)
|
|
1816
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1817
|
+
healthComponents.perpPnl.push({
|
|
1818
|
+
marketIndex: perpMarket.marketIndex,
|
|
1819
|
+
size: positionUnrealizedPnl,
|
|
1820
|
+
value: pnlValue,
|
|
1821
|
+
weight: pnlWeight,
|
|
1822
|
+
weightedValue: wegithedPnlValue,
|
|
1823
|
+
});
|
|
1824
|
+
}
|
|
1825
|
+
let netQuoteValue = numericConstants_1.ZERO;
|
|
1826
|
+
for (const spotPosition of this.getActiveSpotPositions()) {
|
|
1827
|
+
const spotMarketAccount = this.driftClient.getSpotMarketAccount(spotPosition.marketIndex);
|
|
1828
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(spotPosition.marketIndex);
|
|
1829
|
+
if (spotPosition.marketIndex === numericConstants_1.QUOTE_SPOT_MARKET_INDEX) {
|
|
1830
|
+
const tokenAmount = (0, _1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
|
|
1831
|
+
netQuoteValue = netQuoteValue.add(tokenAmount);
|
|
1832
|
+
continue;
|
|
1833
|
+
}
|
|
1834
|
+
const [worstCaseTokenAmount, worstCaseQuoteTokenAmount] = (0, spotPosition_1.getWorstCaseTokenAmounts)(spotPosition, spotMarketAccount, oraclePriceData);
|
|
1835
|
+
netQuoteValue = netQuoteValue.add(worstCaseQuoteTokenAmount);
|
|
1836
|
+
const baseAssetValue = (0, _1.getTokenValue)(worstCaseTokenAmount.abs(), spotMarketAccount.decimals, oraclePriceData);
|
|
1837
|
+
const isLiability = (0, types_1.isVariant)(spotPosition.balanceType, 'borrow');
|
|
1838
|
+
let weight;
|
|
1839
|
+
if (isLiability) {
|
|
1840
|
+
weight = (0, spotBalance_1.calculateLiabilityWeight)(worstCaseTokenAmount.abs(), spotMarketAccount, marginCategory);
|
|
1841
|
+
}
|
|
1842
|
+
else {
|
|
1843
|
+
weight = (0, spotBalance_1.calculateAssetWeight)(worstCaseTokenAmount, spotMarketAccount, marginCategory);
|
|
1844
|
+
}
|
|
1845
|
+
const weightedValue = baseAssetValue
|
|
1846
|
+
.mul(weight)
|
|
1847
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1848
|
+
if (isLiability) {
|
|
1849
|
+
healthComponents.borrows.push({
|
|
1850
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1851
|
+
size: worstCaseTokenAmount,
|
|
1852
|
+
value: baseAssetValue,
|
|
1853
|
+
weight: weight,
|
|
1854
|
+
weightedValue: weightedValue,
|
|
1855
|
+
});
|
|
1856
|
+
}
|
|
1857
|
+
else {
|
|
1858
|
+
healthComponents.deposits.push({
|
|
1859
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1860
|
+
size: worstCaseTokenAmount,
|
|
1861
|
+
value: baseAssetValue,
|
|
1862
|
+
weight: weight,
|
|
1863
|
+
weightedValue: weightedValue,
|
|
1864
|
+
});
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
if (!netQuoteValue.eq(numericConstants_1.ZERO)) {
|
|
1868
|
+
const spotMarketAccount = this.driftClient.getQuoteSpotMarketAccount();
|
|
1869
|
+
const oraclePriceData = this.getOracleDataForSpotMarket(numericConstants_1.QUOTE_SPOT_MARKET_INDEX);
|
|
1870
|
+
const baseAssetValue = (0, _1.getTokenValue)(netQuoteValue.abs(), spotMarketAccount.decimals, oraclePriceData);
|
|
1871
|
+
const isLiability = netQuoteValue.lt(numericConstants_1.ZERO);
|
|
1872
|
+
let weight;
|
|
1873
|
+
if (isLiability) {
|
|
1874
|
+
weight = (0, spotBalance_1.calculateLiabilityWeight)(netQuoteValue.abs(), spotMarketAccount, marginCategory);
|
|
1875
|
+
}
|
|
1876
|
+
else {
|
|
1877
|
+
weight = (0, spotBalance_1.calculateAssetWeight)(netQuoteValue, spotMarketAccount, marginCategory);
|
|
1878
|
+
}
|
|
1879
|
+
const weightedValue = baseAssetValue
|
|
1880
|
+
.mul(weight)
|
|
1881
|
+
.div(numericConstants_1.SPOT_MARKET_WEIGHT_PRECISION);
|
|
1882
|
+
if (isLiability) {
|
|
1883
|
+
healthComponents.borrows.push({
|
|
1884
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1885
|
+
size: netQuoteValue,
|
|
1886
|
+
value: baseAssetValue,
|
|
1887
|
+
weight: weight,
|
|
1888
|
+
weightedValue: weightedValue,
|
|
1889
|
+
});
|
|
1890
|
+
}
|
|
1891
|
+
else {
|
|
1892
|
+
healthComponents.deposits.push({
|
|
1893
|
+
marketIndex: spotMarketAccount.marketIndex,
|
|
1894
|
+
size: netQuoteValue,
|
|
1895
|
+
value: baseAssetValue,
|
|
1896
|
+
weight: weight,
|
|
1897
|
+
weightedValue: weightedValue,
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
return healthComponents;
|
|
1902
|
+
}
|
|
1705
1903
|
/**
|
|
1706
1904
|
* Get the total position value, excluding any position coming from the given target market
|
|
1707
1905
|
* @param marketToIgnore
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.37.1-beta.
|
|
3
|
+
"version": "2.37.1-beta.10",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"eslint-plugin-prettier": "^3.4.0",
|
|
56
56
|
"lodash": "^4.17.21",
|
|
57
57
|
"mocha": "^10.0.0",
|
|
58
|
-
"prettier": "^
|
|
58
|
+
"prettier": "^3.0.1",
|
|
59
59
|
"ts-node": "^10.8.0",
|
|
60
60
|
"typescript": "^4.9.5"
|
|
61
61
|
},
|
package/src/adminClient.ts
CHANGED
|
@@ -691,6 +691,24 @@ export class AdminClient extends DriftClient {
|
|
|
691
691
|
});
|
|
692
692
|
}
|
|
693
693
|
|
|
694
|
+
public async updatePerpMarketPerLpBase(
|
|
695
|
+
perpMarketIndex: number,
|
|
696
|
+
perLpBase: number
|
|
697
|
+
): Promise<TransactionSignature> {
|
|
698
|
+
const perpMarketPublicKey = await getPerpMarketPublicKey(
|
|
699
|
+
this.program.programId,
|
|
700
|
+
perpMarketIndex
|
|
701
|
+
);
|
|
702
|
+
|
|
703
|
+
return await this.program.rpc.updatePerpMarketPerLpBase(perLpBase, {
|
|
704
|
+
accounts: {
|
|
705
|
+
admin: this.wallet.publicKey,
|
|
706
|
+
state: await this.getStatePublicKey(),
|
|
707
|
+
perpMarket: perpMarketPublicKey,
|
|
708
|
+
},
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
|
|
694
712
|
public async updatePerpMarketMaxSpread(
|
|
695
713
|
perpMarketIndex: number,
|
|
696
714
|
maxSpread: number
|
|
@@ -154,6 +154,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
154
154
|
launchTs: 1689270550000,
|
|
155
155
|
oracleSource: OracleSource.PYTH,
|
|
156
156
|
},
|
|
157
|
+
{
|
|
158
|
+
fullName: 'HNT',
|
|
159
|
+
category: ['IoT'],
|
|
160
|
+
symbol: 'HNT-PERP',
|
|
161
|
+
baseAssetSymbol: 'HNT',
|
|
162
|
+
marketIndex: 14,
|
|
163
|
+
oracle: new PublicKey('6Eg8YdfFJQF2HHonzPUBSCCmyUEhrStg9VBLK957sBe6'),
|
|
164
|
+
launchTs: 16922949550000,
|
|
165
|
+
oracleSource: OracleSource.PYTH,
|
|
166
|
+
},
|
|
157
167
|
];
|
|
158
168
|
|
|
159
169
|
export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
@@ -297,6 +307,16 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
297
307
|
launchTs: 1689270550000,
|
|
298
308
|
oracleSource: OracleSource.PYTH,
|
|
299
309
|
},
|
|
310
|
+
{
|
|
311
|
+
fullName: 'HNT',
|
|
312
|
+
category: ['IoT'],
|
|
313
|
+
symbol: 'HNT-PERP',
|
|
314
|
+
baseAssetSymbol: 'HNT',
|
|
315
|
+
marketIndex: 14,
|
|
316
|
+
oracle: new PublicKey('7moA1i5vQUpfDwSpK6Pw9s56ahB7WFGidtbL2ujWrVvm'),
|
|
317
|
+
launchTs: 16922949550000,
|
|
318
|
+
oracleSource: OracleSource.PYTH,
|
|
319
|
+
},
|
|
300
320
|
];
|
|
301
321
|
|
|
302
322
|
export const PerpMarkets: { [key in DriftEnv]: PerpMarketConfig[] } = {
|
|
@@ -168,6 +168,7 @@ export class EventSubscriber {
|
|
|
168
168
|
const records = [];
|
|
169
169
|
// @ts-ignore
|
|
170
170
|
const events = parseLogs(this.program, slot, logs);
|
|
171
|
+
let runningEventIndex = 0;
|
|
171
172
|
for (const event of events) {
|
|
172
173
|
// @ts-ignore
|
|
173
174
|
const expectRecordType = this.eventListMap.has(event.name);
|
|
@@ -175,8 +176,10 @@ export class EventSubscriber {
|
|
|
175
176
|
event.data.txSig = txSig;
|
|
176
177
|
event.data.slot = slot;
|
|
177
178
|
event.data.eventType = event.name;
|
|
179
|
+
event.data.txSigIndex = runningEventIndex;
|
|
178
180
|
records.push(event.data);
|
|
179
181
|
}
|
|
182
|
+
runningEventIndex++;
|
|
180
183
|
}
|
|
181
184
|
return records;
|
|
182
185
|
}
|
package/src/events/fetchLogs.ts
CHANGED
|
@@ -155,11 +155,14 @@ export class LogParser {
|
|
|
155
155
|
event.logs,
|
|
156
156
|
false
|
|
157
157
|
);
|
|
158
|
+
let runningEventIndex = 0;
|
|
158
159
|
for (const eventLog of eventGenerator) {
|
|
159
160
|
eventLog.data.txSig = event.txSig;
|
|
160
161
|
eventLog.data.slot = event.slot;
|
|
161
162
|
eventLog.data.eventType = eventLog.name;
|
|
163
|
+
eventLog.data.txSigIndex = runningEventIndex;
|
|
162
164
|
records.push(eventLog.data);
|
|
165
|
+
runningEventIndex++;
|
|
163
166
|
}
|
|
164
167
|
return records;
|
|
165
168
|
}
|
package/src/events/types.ts
CHANGED
|
@@ -64,6 +64,7 @@ export type EventSubscriptionOrderDirection = 'asc' | 'desc';
|
|
|
64
64
|
export type Event<T> = T & {
|
|
65
65
|
txSig: TransactionSignature;
|
|
66
66
|
slot: number;
|
|
67
|
+
txSigIndex: number; // Unique index for each event inside a tx
|
|
67
68
|
};
|
|
68
69
|
|
|
69
70
|
export type WrappedEvent<Type extends EventType> = EventMap[Type] & {
|
package/src/idl/drift.json
CHANGED
|
@@ -1122,6 +1122,31 @@
|
|
|
1122
1122
|
}
|
|
1123
1123
|
]
|
|
1124
1124
|
},
|
|
1125
|
+
{
|
|
1126
|
+
"name": "updateUserReduceOnly",
|
|
1127
|
+
"accounts": [
|
|
1128
|
+
{
|
|
1129
|
+
"name": "user",
|
|
1130
|
+
"isMut": true,
|
|
1131
|
+
"isSigner": false
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
"name": "authority",
|
|
1135
|
+
"isMut": false,
|
|
1136
|
+
"isSigner": true
|
|
1137
|
+
}
|
|
1138
|
+
],
|
|
1139
|
+
"args": [
|
|
1140
|
+
{
|
|
1141
|
+
"name": "subAccountId",
|
|
1142
|
+
"type": "u16"
|
|
1143
|
+
},
|
|
1144
|
+
{
|
|
1145
|
+
"name": "reduceOnly",
|
|
1146
|
+
"type": "bool"
|
|
1147
|
+
}
|
|
1148
|
+
]
|
|
1149
|
+
},
|
|
1125
1150
|
{
|
|
1126
1151
|
"name": "deleteUser",
|
|
1127
1152
|
"accounts": [
|
|
@@ -3857,6 +3882,32 @@
|
|
|
3857
3882
|
}
|
|
3858
3883
|
]
|
|
3859
3884
|
},
|
|
3885
|
+
{
|
|
3886
|
+
"name": "updatePerpMarketPerLpBase",
|
|
3887
|
+
"accounts": [
|
|
3888
|
+
{
|
|
3889
|
+
"name": "admin",
|
|
3890
|
+
"isMut": false,
|
|
3891
|
+
"isSigner": true
|
|
3892
|
+
},
|
|
3893
|
+
{
|
|
3894
|
+
"name": "state",
|
|
3895
|
+
"isMut": false,
|
|
3896
|
+
"isSigner": false
|
|
3897
|
+
},
|
|
3898
|
+
{
|
|
3899
|
+
"name": "perpMarket",
|
|
3900
|
+
"isMut": true,
|
|
3901
|
+
"isSigner": false
|
|
3902
|
+
}
|
|
3903
|
+
],
|
|
3904
|
+
"args": [
|
|
3905
|
+
{
|
|
3906
|
+
"name": "perLpBase",
|
|
3907
|
+
"type": "i8"
|
|
3908
|
+
}
|
|
3909
|
+
]
|
|
3910
|
+
},
|
|
3860
3911
|
{
|
|
3861
3912
|
"name": "updateLpCooldownTime",
|
|
3862
3913
|
"accounts": [
|
|
@@ -6953,9 +7004,20 @@
|
|
|
6953
7004
|
],
|
|
6954
7005
|
"type": "i32"
|
|
6955
7006
|
},
|
|
7007
|
+
{
|
|
7008
|
+
"name": "perLpBase",
|
|
7009
|
+
"docs": [
|
|
7010
|
+
"expo for unit of per_lp, base 10 (if per_lp_base=X, then per_lp unit is 10^X)"
|
|
7011
|
+
],
|
|
7012
|
+
"type": "i8"
|
|
7013
|
+
},
|
|
6956
7014
|
{
|
|
6957
7015
|
"name": "padding1",
|
|
6958
|
-
"type": "
|
|
7016
|
+
"type": "u8"
|
|
7017
|
+
},
|
|
7018
|
+
{
|
|
7019
|
+
"name": "padding2",
|
|
7020
|
+
"type": "u16"
|
|
6959
7021
|
},
|
|
6960
7022
|
{
|
|
6961
7023
|
"name": "totalFeeEarnedPerLp",
|
|
@@ -7422,13 +7484,8 @@
|
|
|
7422
7484
|
"type": "u8"
|
|
7423
7485
|
},
|
|
7424
7486
|
{
|
|
7425
|
-
"name": "
|
|
7426
|
-
"type":
|
|
7427
|
-
"array": [
|
|
7428
|
-
"u8",
|
|
7429
|
-
1
|
|
7430
|
-
]
|
|
7431
|
-
}
|
|
7487
|
+
"name": "perLpBase",
|
|
7488
|
+
"type": "i8"
|
|
7432
7489
|
}
|
|
7433
7490
|
]
|
|
7434
7491
|
}
|
|
@@ -8314,6 +8371,9 @@
|
|
|
8314
8371
|
},
|
|
8315
8372
|
{
|
|
8316
8373
|
"name": "Bankrupt"
|
|
8374
|
+
},
|
|
8375
|
+
{
|
|
8376
|
+
"name": "ReduceOnly"
|
|
8317
8377
|
}
|
|
8318
8378
|
]
|
|
8319
8379
|
}
|
|
@@ -10681,6 +10741,11 @@
|
|
|
10681
10741
|
"code": 6253,
|
|
10682
10742
|
"name": "CantUpdatePerpBidAskTwap",
|
|
10683
10743
|
"msg": "CantUpdatePerpBidAskTwap"
|
|
10744
|
+
},
|
|
10745
|
+
{
|
|
10746
|
+
"code": 6254,
|
|
10747
|
+
"name": "UserReduceOnly",
|
|
10748
|
+
"msg": "UserReduceOnly"
|
|
10684
10749
|
}
|
|
10685
10750
|
]
|
|
10686
10751
|
}
|
package/src/index.ts
CHANGED
|
@@ -61,6 +61,7 @@ export * from './serum/serumSubscriber';
|
|
|
61
61
|
export * from './serum/serumFulfillmentConfigMap';
|
|
62
62
|
export * from './phoenix/phoenixSubscriber';
|
|
63
63
|
export * from './phoenix/phoenixFulfillmentConfigMap';
|
|
64
|
+
export * from './tx/fastSingleTxSender';
|
|
64
65
|
export * from './tx/retryTxSender';
|
|
65
66
|
export * from './tx/types';
|
|
66
67
|
export * from './util/computeUnits';
|