@drift-labs/sdk 2.145.0 → 2.146.0-alpha.13

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.
Files changed (99) hide show
  1. package/.env +4 -0
  2. package/VERSION +1 -1
  3. package/lib/browser/accounts/grpcMultiUserAccountSubscriber.js +8 -1
  4. package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
  5. package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
  6. package/lib/browser/adminClient.d.ts +5 -1
  7. package/lib/browser/adminClient.js +57 -23
  8. package/lib/browser/constants/numericConstants.d.ts +2 -0
  9. package/lib/browser/constants/numericConstants.js +5 -1
  10. package/lib/browser/constants/perpMarkets.js +0 -2
  11. package/lib/browser/decode/user.js +4 -0
  12. package/lib/browser/driftClient.d.ts +25 -10
  13. package/lib/browser/driftClient.js +238 -41
  14. package/lib/browser/driftClientConfig.d.ts +7 -2
  15. package/lib/browser/idl/drift.json +245 -22
  16. package/lib/browser/index.d.ts +4 -0
  17. package/lib/browser/index.js +9 -1
  18. package/lib/browser/marginCalculation.d.ts +86 -0
  19. package/lib/browser/marginCalculation.js +209 -0
  20. package/lib/browser/math/margin.d.ts +1 -1
  21. package/lib/browser/math/margin.js +8 -1
  22. package/lib/browser/math/position.d.ts +1 -0
  23. package/lib/browser/math/position.js +10 -2
  24. package/lib/browser/math/spotPosition.d.ts +1 -1
  25. package/lib/browser/math/spotPosition.js +3 -2
  26. package/lib/browser/math/superStake.d.ts +3 -2
  27. package/lib/browser/types.d.ts +13 -0
  28. package/lib/browser/types.js +12 -1
  29. package/lib/browser/user.d.ts +59 -11
  30. package/lib/browser/user.js +348 -43
  31. package/lib/node/accounts/grpcMultiUserAccountSubscriber.d.ts.map +1 -1
  32. package/lib/node/accounts/grpcMultiUserAccountSubscriber.js +8 -1
  33. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
  34. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts.map +1 -1
  35. package/lib/node/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
  36. package/lib/node/adminClient.d.ts +5 -1
  37. package/lib/node/adminClient.d.ts.map +1 -1
  38. package/lib/node/adminClient.js +57 -23
  39. package/lib/node/constants/numericConstants.d.ts +2 -0
  40. package/lib/node/constants/numericConstants.d.ts.map +1 -1
  41. package/lib/node/constants/numericConstants.js +5 -1
  42. package/lib/node/constants/perpMarkets.d.ts.map +1 -1
  43. package/lib/node/constants/perpMarkets.js +0 -2
  44. package/lib/node/decode/user.d.ts.map +1 -1
  45. package/lib/node/decode/user.js +4 -0
  46. package/lib/node/driftClient.d.ts +25 -10
  47. package/lib/node/driftClient.d.ts.map +1 -1
  48. package/lib/node/driftClient.js +238 -41
  49. package/lib/node/driftClientConfig.d.ts +7 -2
  50. package/lib/node/driftClientConfig.d.ts.map +1 -1
  51. package/lib/node/idl/drift.json +245 -22
  52. package/lib/node/index.d.ts +4 -0
  53. package/lib/node/index.d.ts.map +1 -1
  54. package/lib/node/index.js +9 -1
  55. package/lib/node/marginCalculation.d.ts +87 -0
  56. package/lib/node/marginCalculation.d.ts.map +1 -0
  57. package/lib/node/marginCalculation.js +209 -0
  58. package/lib/node/math/margin.d.ts +1 -1
  59. package/lib/node/math/margin.d.ts.map +1 -1
  60. package/lib/node/math/margin.js +8 -1
  61. package/lib/node/math/position.d.ts +1 -0
  62. package/lib/node/math/position.d.ts.map +1 -1
  63. package/lib/node/math/position.js +10 -2
  64. package/lib/node/math/spotPosition.d.ts +1 -1
  65. package/lib/node/math/spotPosition.d.ts.map +1 -1
  66. package/lib/node/math/spotPosition.js +3 -2
  67. package/lib/node/math/superStake.d.ts +3 -2
  68. package/lib/node/math/superStake.d.ts.map +1 -1
  69. package/lib/node/types.d.ts +13 -0
  70. package/lib/node/types.d.ts.map +1 -1
  71. package/lib/node/types.js +12 -1
  72. package/lib/node/user.d.ts +59 -11
  73. package/lib/node/user.d.ts.map +1 -1
  74. package/lib/node/user.js +348 -43
  75. package/package.json +1 -1
  76. package/scripts/deposit-isolated-positions.ts +110 -0
  77. package/scripts/single-grpc-client-test.ts +71 -21
  78. package/scripts/withdraw-isolated-positions.ts +174 -0
  79. package/src/accounts/grpcMultiUserAccountSubscriber.ts +8 -1
  80. package/src/accounts/webSocketProgramAccountSubscriberV2.ts +566 -167
  81. package/src/adminClient.ts +74 -25
  82. package/src/constants/numericConstants.ts +5 -0
  83. package/src/constants/perpMarkets.ts +0 -3
  84. package/src/decode/user.ts +7 -1
  85. package/src/driftClient.ts +465 -52
  86. package/src/driftClientConfig.ts +15 -8
  87. package/src/idl/drift.json +246 -23
  88. package/src/index.ts +4 -0
  89. package/src/margin/README.md +143 -0
  90. package/src/marginCalculation.ts +306 -0
  91. package/src/math/margin.ts +13 -1
  92. package/src/math/position.ts +12 -2
  93. package/src/math/spotPosition.ts +6 -2
  94. package/src/types.ts +16 -0
  95. package/src/user.ts +623 -81
  96. package/tests/amm/test.ts +1 -1
  97. package/tests/dlob/helpers.ts +6 -3
  98. package/tests/user/getMarginCalculation.ts +405 -0
  99. package/tests/user/test.ts +0 -7
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarginCalculation = exports.IsolatedMarginCalculation = exports.MarginContext = exports.MarketIdentifier = void 0;
4
+ const anchor_1 = require("@coral-xyz/anchor");
5
+ const numericConstants_1 = require("./constants/numericConstants");
6
+ const types_1 = require("./types");
7
+ class MarketIdentifier {
8
+ constructor(marketType, marketIndex) {
9
+ this.marketType = marketType;
10
+ this.marketIndex = marketIndex;
11
+ }
12
+ static spot(marketIndex) {
13
+ return new MarketIdentifier(types_1.MarketType.SPOT, marketIndex);
14
+ }
15
+ static perp(marketIndex) {
16
+ return new MarketIdentifier(types_1.MarketType.PERP, marketIndex);
17
+ }
18
+ equals(other) {
19
+ return (!!other &&
20
+ this.marketType === other.marketType &&
21
+ this.marketIndex === other.marketIndex);
22
+ }
23
+ }
24
+ exports.MarketIdentifier = MarketIdentifier;
25
+ class MarginContext {
26
+ constructor(marginType) {
27
+ this.marginType = marginType;
28
+ this.mode = { type: 'Standard' };
29
+ this.strict = false;
30
+ this.ignoreInvalidDepositOracles = false;
31
+ this.marginBuffer = new anchor_1.BN(0);
32
+ }
33
+ static standard(marginType) {
34
+ return new MarginContext(marginType);
35
+ }
36
+ static liquidation(marginBuffer) {
37
+ const ctx = new MarginContext('Maintenance');
38
+ ctx.mode = { type: 'Liquidation' };
39
+ ctx.marginBuffer = marginBuffer !== null && marginBuffer !== void 0 ? marginBuffer : new anchor_1.BN(0);
40
+ return ctx;
41
+ }
42
+ strictMode(strict) {
43
+ this.strict = strict;
44
+ return this;
45
+ }
46
+ ignoreInvalidDeposits(ignore) {
47
+ this.ignoreInvalidDepositOracles = ignore;
48
+ return this;
49
+ }
50
+ setMarginBuffer(buffer) {
51
+ this.marginBuffer = buffer !== null && buffer !== void 0 ? buffer : new anchor_1.BN(0);
52
+ return this;
53
+ }
54
+ setMarginRatioOverride(ratio) {
55
+ this.marginRatioOverride = ratio;
56
+ return this;
57
+ }
58
+ }
59
+ exports.MarginContext = MarginContext;
60
+ class IsolatedMarginCalculation {
61
+ constructor() {
62
+ this.marginRequirement = new anchor_1.BN(0);
63
+ this.totalCollateral = new anchor_1.BN(0);
64
+ this.totalCollateralBuffer = new anchor_1.BN(0);
65
+ this.marginRequirementPlusBuffer = new anchor_1.BN(0);
66
+ }
67
+ getTotalCollateralPlusBuffer() {
68
+ return this.totalCollateral.add(this.totalCollateralBuffer);
69
+ }
70
+ meetsMarginRequirement() {
71
+ return this.totalCollateral.gte(this.marginRequirement);
72
+ }
73
+ meetsMarginRequirementWithBuffer() {
74
+ return this.getTotalCollateralPlusBuffer().gte(this.marginRequirementPlusBuffer);
75
+ }
76
+ marginShortage() {
77
+ const shortage = this.marginRequirementPlusBuffer.sub(this.getTotalCollateralPlusBuffer());
78
+ return shortage.isNeg() ? new anchor_1.BN(0) : shortage;
79
+ }
80
+ }
81
+ exports.IsolatedMarginCalculation = IsolatedMarginCalculation;
82
+ class MarginCalculation {
83
+ constructor(context) {
84
+ this.context = context;
85
+ this.totalCollateral = new anchor_1.BN(0);
86
+ this.totalCollateralBuffer = new anchor_1.BN(0);
87
+ this.marginRequirement = new anchor_1.BN(0);
88
+ this.marginRequirementPlusBuffer = new anchor_1.BN(0);
89
+ this.isolatedMarginCalculations = new Map();
90
+ this.numSpotLiabilities = 0;
91
+ this.numPerpLiabilities = 0;
92
+ this.allDepositOraclesValid = true;
93
+ this.allLiabilityOraclesValid = true;
94
+ this.withPerpIsolatedLiability = false;
95
+ this.withSpotIsolatedLiability = false;
96
+ this.totalSpotLiabilityValue = new anchor_1.BN(0);
97
+ this.totalPerpLiabilityValue = new anchor_1.BN(0);
98
+ this.trackedMarketMarginRequirement = new anchor_1.BN(0);
99
+ this.fuelDeposits = 0;
100
+ this.fuelBorrows = 0;
101
+ this.fuelPositions = 0;
102
+ }
103
+ addCrossMarginTotalCollateral(delta) {
104
+ this.totalCollateral = this.totalCollateral.add(delta);
105
+ if (this.context.marginBuffer.gt(new anchor_1.BN(0)) && delta.isNeg()) {
106
+ this.totalCollateralBuffer = this.totalCollateralBuffer.add(delta.mul(this.context.marginBuffer).div(numericConstants_1.MARGIN_PRECISION));
107
+ }
108
+ }
109
+ addCrossMarginRequirement(marginRequirement, liabilityValue) {
110
+ this.marginRequirement = this.marginRequirement.add(marginRequirement);
111
+ if (this.context.marginBuffer.gt(new anchor_1.BN(0))) {
112
+ this.marginRequirementPlusBuffer = this.marginRequirementPlusBuffer.add(marginRequirement.add(liabilityValue.mul(this.context.marginBuffer).div(numericConstants_1.MARGIN_PRECISION)));
113
+ }
114
+ }
115
+ addIsolatedMarginCalculation(marketIndex, depositValue, pnl, liabilityValue, marginRequirement) {
116
+ const totalCollateral = depositValue.add(pnl);
117
+ const totalCollateralBuffer = this.context.marginBuffer.gt(new anchor_1.BN(0)) && pnl.isNeg()
118
+ ? pnl.mul(this.context.marginBuffer).div(numericConstants_1.MARGIN_PRECISION)
119
+ : new anchor_1.BN(0);
120
+ const marginRequirementPlusBuffer = this.context.marginBuffer.gt(new anchor_1.BN(0))
121
+ ? marginRequirement.add(liabilityValue.mul(this.context.marginBuffer).div(numericConstants_1.MARGIN_PRECISION))
122
+ : new anchor_1.BN(0);
123
+ const iso = new IsolatedMarginCalculation();
124
+ iso.marginRequirement = marginRequirement;
125
+ iso.totalCollateral = totalCollateral;
126
+ iso.totalCollateralBuffer = totalCollateralBuffer;
127
+ iso.marginRequirementPlusBuffer = marginRequirementPlusBuffer;
128
+ this.isolatedMarginCalculations.set(marketIndex, iso);
129
+ }
130
+ addSpotLiability() {
131
+ this.numSpotLiabilities += 1;
132
+ }
133
+ addPerpLiability() {
134
+ this.numPerpLiabilities += 1;
135
+ }
136
+ addSpotLiabilityValue(spotLiabilityValue) {
137
+ this.totalSpotLiabilityValue =
138
+ this.totalSpotLiabilityValue.add(spotLiabilityValue);
139
+ }
140
+ addPerpLiabilityValue(perpLiabilityValue) {
141
+ this.totalPerpLiabilityValue =
142
+ this.totalPerpLiabilityValue.add(perpLiabilityValue);
143
+ }
144
+ updateAllDepositOraclesValid(valid) {
145
+ this.allDepositOraclesValid = this.allDepositOraclesValid && valid;
146
+ }
147
+ updateAllLiabilityOraclesValid(valid) {
148
+ this.allLiabilityOraclesValid = this.allLiabilityOraclesValid && valid;
149
+ }
150
+ updateWithSpotIsolatedLiability(isolated) {
151
+ this.withSpotIsolatedLiability = this.withSpotIsolatedLiability || isolated;
152
+ }
153
+ updateWithPerpIsolatedLiability(isolated) {
154
+ this.withPerpIsolatedLiability = this.withPerpIsolatedLiability || isolated;
155
+ }
156
+ validateNumSpotLiabilities() {
157
+ if (this.numSpotLiabilities > 0 && this.marginRequirement.eq(new anchor_1.BN(0))) {
158
+ throw new Error('InvalidMarginRatio: num_spot_liabilities>0 but margin_requirement=0');
159
+ }
160
+ }
161
+ getNumOfLiabilities() {
162
+ return this.numSpotLiabilities + this.numPerpLiabilities;
163
+ }
164
+ getCrossTotalCollateralPlusBuffer() {
165
+ return this.totalCollateral.add(this.totalCollateralBuffer);
166
+ }
167
+ meetsCrossMarginRequirement() {
168
+ return this.totalCollateral.gte(this.marginRequirement);
169
+ }
170
+ meetsCrossMarginRequirementWithBuffer() {
171
+ return this.getCrossTotalCollateralPlusBuffer().gte(this.marginRequirementPlusBuffer);
172
+ }
173
+ meetsMarginRequirement() {
174
+ if (!this.meetsCrossMarginRequirement())
175
+ return false;
176
+ for (const [, iso] of this.isolatedMarginCalculations) {
177
+ if (!iso.meetsMarginRequirement())
178
+ return false;
179
+ }
180
+ return true;
181
+ }
182
+ meetsMarginRequirementWithBuffer() {
183
+ if (!this.meetsCrossMarginRequirementWithBuffer())
184
+ return false;
185
+ for (const [, iso] of this.isolatedMarginCalculations) {
186
+ if (!iso.meetsMarginRequirementWithBuffer())
187
+ return false;
188
+ }
189
+ return true;
190
+ }
191
+ getCrossFreeCollateral() {
192
+ const free = this.totalCollateral.sub(this.marginRequirement);
193
+ return free.isNeg() ? new anchor_1.BN(0) : free;
194
+ }
195
+ getIsolatedFreeCollateral(marketIndex) {
196
+ const iso = this.isolatedMarginCalculations.get(marketIndex);
197
+ if (!iso)
198
+ throw new Error('InvalidMarginCalculation: missing isolated calc');
199
+ const free = iso.totalCollateral.sub(iso.marginRequirement);
200
+ return free.isNeg() ? new anchor_1.BN(0) : free;
201
+ }
202
+ getIsolatedMarginCalculation(marketIndex) {
203
+ return this.isolatedMarginCalculations.get(marketIndex);
204
+ }
205
+ hasIsolatedMarginCalculation(marketIndex) {
206
+ return this.isolatedMarginCalculations.has(marketIndex);
207
+ }
208
+ }
209
+ exports.MarginCalculation = MarginCalculation;
@@ -19,7 +19,7 @@ export declare function calculateOraclePriceForPerpMargin(perpPosition: PerpPosi
19
19
  */
20
20
  export declare function calculateBaseAssetValueWithOracle(market: PerpMarketAccount, perpPosition: PerpPosition, oraclePriceData: Pick<OraclePriceData, 'price'>, includeOpenOrders?: boolean): BN;
21
21
  export declare function calculateWorstCaseBaseAssetAmount(perpPosition: PerpPosition, perpMarket: PerpMarketAccount, oraclePrice: BN): BN;
22
- export declare function calculateWorstCasePerpLiabilityValue(perpPosition: PerpPosition, perpMarket: PerpMarketAccount, oraclePrice: BN): {
22
+ export declare function calculateWorstCasePerpLiabilityValue(perpPosition: PerpPosition, perpMarket: PerpMarketAccount, oraclePrice: BN, includeOpenOrders?: boolean): {
23
23
  worstCaseBaseAssetAmount: BN;
24
24
  worstCaseLiabilityValue: BN;
25
25
  };
@@ -89,7 +89,14 @@ function calculateWorstCaseBaseAssetAmount(perpPosition, perpMarket, oraclePrice
89
89
  return calculateWorstCasePerpLiabilityValue(perpPosition, perpMarket, oraclePrice).worstCaseBaseAssetAmount;
90
90
  }
91
91
  exports.calculateWorstCaseBaseAssetAmount = calculateWorstCaseBaseAssetAmount;
92
- function calculateWorstCasePerpLiabilityValue(perpPosition, perpMarket, oraclePrice) {
92
+ function calculateWorstCasePerpLiabilityValue(perpPosition, perpMarket, oraclePrice, includeOpenOrders = true) {
93
+ // return early if no open orders required
94
+ if (!includeOpenOrders) {
95
+ return {
96
+ worstCaseBaseAssetAmount: perpPosition.baseAssetAmount,
97
+ worstCaseLiabilityValue: calculatePerpLiabilityValue(perpPosition.baseAssetAmount, oraclePrice, (0, types_1.isVariant)(perpMarket.contractType, 'prediction')),
98
+ };
99
+ }
93
100
  const allBids = perpPosition.baseAssetAmount.add(perpPosition.openBids);
94
101
  const allAsks = perpPosition.baseAssetAmount.add(perpPosition.openAsks);
95
102
  const isPredictionMarket = (0, types_1.isVariant)(perpMarket.contractType, 'prediction');
@@ -46,6 +46,7 @@ export declare function calculateUnsettledFundingPnl(market: PerpMarketAccount,
46
46
  */
47
47
  export declare function calculatePositionFundingPNL(market: PerpMarketAccount, perpPosition: PerpPosition): BN;
48
48
  export declare function positionIsAvailable(position: PerpPosition): boolean;
49
+ export declare function positionIsBeingLiquidated(position: PerpPosition): boolean;
49
50
  /**
50
51
  *
51
52
  * @param userPosition
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasOpenOrders = exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.calculateBreakEvenPrice = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledFundingPnl = exports.calculateFeesAndFundingPnl = exports.calculateClaimablePnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
3
+ exports.hasOpenOrders = exports.isEmptyPosition = exports.positionCurrentDirection = exports.findDirectionToClose = exports.calculateCostBasis = exports.calculateEntryPrice = exports.calculateBreakEvenPrice = exports.positionIsBeingLiquidated = exports.positionIsAvailable = exports.calculatePositionFundingPNL = exports.calculateUnsettledFundingPnl = exports.calculateFeesAndFundingPnl = exports.calculateClaimablePnl = exports.calculatePositionPNL = exports.calculateBaseAssetValue = void 0;
4
4
  const anchor_1 = require("@coral-xyz/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
@@ -149,9 +149,17 @@ function positionIsAvailable(position) {
149
149
  return (position.baseAssetAmount.eq(numericConstants_1.ZERO) &&
150
150
  position.openOrders === 0 &&
151
151
  position.quoteAssetAmount.eq(numericConstants_1.ZERO) &&
152
- position.lpShares.eq(numericConstants_1.ZERO));
152
+ position.lpShares.eq(numericConstants_1.ZERO) &&
153
+ position.isolatedPositionScaledBalance.eq(numericConstants_1.ZERO) &&
154
+ !positionIsBeingLiquidated(position));
153
155
  }
154
156
  exports.positionIsAvailable = positionIsAvailable;
157
+ function positionIsBeingLiquidated(position) {
158
+ return ((position.positionFlag &
159
+ (types_1.PositionFlag.BeingLiquidated | types_1.PositionFlag.Bankruptcy)) >
160
+ 0);
161
+ }
162
+ exports.positionIsBeingLiquidated = positionIsBeingLiquidated;
155
163
  /**
156
164
  *
157
165
  * @param userPosition
@@ -11,7 +11,7 @@ export type OrderFillSimulation = {
11
11
  weightedTokenValue: BN;
12
12
  freeCollateralContribution: any;
13
13
  };
14
- export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory, customMarginRatio?: number): OrderFillSimulation;
14
+ export declare function getWorstCaseTokenAmounts(spotPosition: SpotPosition, spotMarketAccount: SpotMarketAccount, strictOraclePrice: StrictOraclePrice, marginCategory: MarginCategory, customMarginRatio?: number, includeOpenOrders?: boolean): OrderFillSimulation;
15
15
  export declare function calculateWeightedTokenValue(tokenAmount: BN, tokenValue: BN, oraclePrice: BN, spotMarket: SpotMarketAccount, marginCategory: MarginCategory, customMarginRatio?: number): {
16
16
  weight: BN;
17
17
  weightedTokenValue: BN;
@@ -8,10 +8,11 @@ function isSpotPositionAvailable(position) {
8
8
  return position.scaledBalance.eq(numericConstants_1.ZERO) && position.openOrders === 0;
9
9
  }
10
10
  exports.isSpotPositionAvailable = isSpotPositionAvailable;
11
- function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, customMarginRatio) {
11
+ function getWorstCaseTokenAmounts(spotPosition, spotMarketAccount, strictOraclePrice, marginCategory, customMarginRatio, includeOpenOrders = true) {
12
12
  const tokenAmount = (0, spotBalance_1.getSignedTokenAmount)((0, spotBalance_1.getTokenAmount)(spotPosition.scaledBalance, spotMarketAccount, spotPosition.balanceType), spotPosition.balanceType);
13
13
  const tokenValue = (0, spotBalance_1.getStrictTokenValue)(tokenAmount, spotMarketAccount.decimals, strictOraclePrice);
14
- if (spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) {
14
+ if ((spotPosition.openBids.eq(numericConstants_1.ZERO) && spotPosition.openAsks.eq(numericConstants_1.ZERO)) ||
15
+ !includeOpenOrders) {
15
16
  const { weight, weightedTokenValue } = calculateWeightedTokenValue(tokenAmount, tokenValue, strictOraclePrice.current, spotMarketAccount, marginCategory, customMarginRatio);
16
17
  return {
17
18
  tokenAmount,
@@ -5,6 +5,7 @@ import { DriftClient } from '../driftClient';
5
5
  import { BN } from '@coral-xyz/anchor';
6
6
  import { User } from '../user';
7
7
  import { DepositRecord } from '../types';
8
+ import fetch from 'node-fetch';
8
9
  export type BSOL_STATS_API_RESPONSE = {
9
10
  success: boolean;
10
11
  stats?: {
@@ -27,8 +28,8 @@ export type BSOL_EMISSIONS_API_RESPONSE = {
27
28
  lend: number;
28
29
  };
29
30
  };
30
- export declare function fetchBSolMetrics(): Promise<any>;
31
- export declare function fetchBSolDriftEmissions(): Promise<any>;
31
+ export declare function fetchBSolMetrics(): Promise<fetch.Response>;
32
+ export declare function fetchBSolDriftEmissions(): Promise<fetch.Response>;
32
33
  export declare function findBestSuperStakeIxs({ marketIndex, amount, jupiterClient, driftClient, userAccountPublicKey, price, forceMarinade, onlyDirectRoutes, jupiterQuote, }: {
33
34
  marketIndex: number;
34
35
  amount: BN;
@@ -696,6 +696,9 @@ export type SpotBankruptcyRecord = {
696
696
  cumulativeDepositInterestDelta: BN;
697
697
  ifPayment: BN;
698
698
  };
699
+ export declare class LiquidationBitFlag {
700
+ static readonly IsolatedPosition = 1;
701
+ }
699
702
  export type SettlePnlRecord = {
700
703
  ts: BN;
701
704
  user: PublicKey;
@@ -1191,6 +1194,8 @@ export type PerpPosition = {
1191
1194
  lastBaseAssetAmountPerLp: BN;
1192
1195
  lastQuoteAssetAmountPerLp: BN;
1193
1196
  perLpBase: number;
1197
+ positionFlag: number;
1198
+ isolatedPositionScaledBalance: BN;
1194
1199
  };
1195
1200
  export type UserStatsAccount = {
1196
1201
  numberOfSubAccounts: number;
@@ -1340,6 +1345,11 @@ export declare class OrderParamsBitFlag {
1340
1345
  static readonly ImmediateOrCancel = 1;
1341
1346
  static readonly UpdateHighLeverageMode = 2;
1342
1347
  }
1348
+ export declare class PositionFlag {
1349
+ static readonly IsolatedPosition = 1;
1350
+ static readonly BeingLiquidated = 2;
1351
+ static readonly Bankruptcy = 3;
1352
+ }
1343
1353
  export type NecessaryOrderParams = {
1344
1354
  orderType: OrderType;
1345
1355
  marketIndex: number;
@@ -1349,6 +1359,9 @@ export type NecessaryOrderParams = {
1349
1359
  export type OptionalOrderParams = {
1350
1360
  [Property in keyof OrderParams]?: OrderParams[Property];
1351
1361
  } & NecessaryOrderParams;
1362
+ export type PerpOrderIsolatedExtras = {
1363
+ isolatedPositionDepositAmount?: BN;
1364
+ };
1352
1365
  export type ModifyOrderParams = {
1353
1366
  [Property in keyof OrderParams]?: OrderParams[Property] | null;
1354
1367
  } & {
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConstituentLpOperation = exports.ConstituentStatus = exports.OracleValidity = exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.FuelOverflowStatus = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.OrderParamsBitFlag = exports.PostOnlyParams = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderBitFlag = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSourceNum = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.TokenProgramFlag = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.MarginMode = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.FeatureBitFlags = exports.ExchangeStatus = void 0;
3
+ exports.ConstituentStatus = exports.OracleValidity = exports.SwapReduceOnly = exports.PlaceAndTakeOrderSuccessCondition = exports.FuelOverflowStatus = exports.ReferrerStatus = exports.DefaultOrderParams = exports.ModifyOrderPolicy = exports.PositionFlag = exports.OrderParamsBitFlag = exports.PostOnlyParams = exports.LiquidationBitFlag = exports.LiquidationType = exports.LPAction = exports.TradeSide = exports.getVariant = exports.isOneOfVariant = exports.isVariant = exports.SettlePnlMode = exports.StakeAction = exports.SpotFulfillmentConfigStatus = exports.SettlePnlExplanation = exports.DepositExplanation = exports.SpotFulfillmentStatus = exports.SpotFulfillmentType = exports.OrderTriggerCondition = exports.OrderActionExplanation = exports.OrderAction = exports.OrderBitFlag = exports.OrderStatus = exports.MarketType = exports.OrderType = exports.OracleSourceNum = exports.OracleSource = exports.DepositDirection = exports.PositionDirection = exports.SpotBalanceType = exports.SwapDirection = exports.TokenProgramFlag = exports.AssetTier = exports.ContractTier = exports.ContractType = exports.MarginMode = exports.UserStatus = exports.InsuranceFundOperation = exports.SpotOperation = exports.PerpOperation = exports.MarketStatus = exports.FeatureBitFlags = exports.ExchangeStatus = void 0;
4
+ exports.ConstituentLpOperation = void 0;
4
5
  const numericConstants_1 = require("./constants/numericConstants");
5
6
  // # Utility Types / Enums / Constants
6
7
  var ExchangeStatus;
@@ -352,6 +353,10 @@ LiquidationType.SPOT_BANKRUPTCY = {
352
353
  LiquidationType.LIQUIDATE_SPOT = {
353
354
  liquidateSpot: {},
354
355
  };
356
+ class LiquidationBitFlag {
357
+ }
358
+ exports.LiquidationBitFlag = LiquidationBitFlag;
359
+ LiquidationBitFlag.IsolatedPosition = 1;
355
360
  class PostOnlyParams {
356
361
  }
357
362
  exports.PostOnlyParams = PostOnlyParams;
@@ -364,6 +369,12 @@ class OrderParamsBitFlag {
364
369
  exports.OrderParamsBitFlag = OrderParamsBitFlag;
365
370
  OrderParamsBitFlag.ImmediateOrCancel = 1;
366
371
  OrderParamsBitFlag.UpdateHighLeverageMode = 2;
372
+ class PositionFlag {
373
+ }
374
+ exports.PositionFlag = PositionFlag;
375
+ PositionFlag.IsolatedPosition = 1;
376
+ PositionFlag.BeingLiquidated = 2;
377
+ PositionFlag.Bankruptcy = 3;
367
378
  var ModifyOrderPolicy;
368
379
  (function (ModifyOrderPolicy) {
369
380
  ModifyOrderPolicy[ModifyOrderPolicy["MustModify"] = 1] = "MustModify";
@@ -12,6 +12,8 @@ import { UserStats } from './userStats';
12
12
  import { OraclePriceData } from './oracles/types';
13
13
  import { UserConfig } from './userConfig';
14
14
  import { StrictOraclePrice } from './oracles/strictOraclePrice';
15
+ import { MarginCalculation } from './marginCalculation';
16
+ export type MarginType = 'Cross' | 'Isolated';
15
17
  export declare class User {
16
18
  driftClient: DriftClient;
17
19
  userAccountPublicKey: PublicKey;
@@ -60,6 +62,7 @@ export declare class User {
60
62
  */
61
63
  getTokenAmount(marketIndex: number): BN;
62
64
  getEmptyPosition(marketIndex: number): PerpPosition;
65
+ getIsolatePerpPositionTokenAmount(perpMarketIndex: number): BN;
63
66
  getClonedPosition(position: PerpPosition): PerpPosition;
64
67
  getOrderForUserAccount(userAccount: UserAccount, orderId: number): Order | undefined;
65
68
  /**
@@ -96,19 +99,32 @@ export declare class User {
96
99
  * calculates Free Collateral = Total collateral - margin requirement
97
100
  * @returns : Precision QUOTE_PRECISION
98
101
  */
99
- getFreeCollateral(marginCategory?: MarginCategory, enterHighLeverageMode?: any): BN;
102
+ getFreeCollateral(marginCategory?: MarginCategory, enterHighLeverageMode?: boolean, perpMarketIndex?: number): BN;
100
103
  /**
101
- * @returns The margin requirement of a certain type (Initial or Maintenance) in USDC. : QUOTE_PRECISION
104
+ * @deprecated Use the overload that includes { marginType, perpMarketIndex }
102
105
  */
103
- getMarginRequirement(marginCategory: MarginCategory, liquidationBuffer?: BN, strict?: boolean, includeOpenOrders?: boolean, enteringHighLeverage?: any): BN;
106
+ getMarginRequirement(marginCategory: MarginCategory, liquidationBuffer?: BN, strict?: boolean, includeOpenOrders?: boolean, enteringHighLeverage?: boolean): BN;
107
+ /**
108
+ * Calculates the margin requirement based on the specified parameters.
109
+ *
110
+ * @param marginCategory - The category of margin to calculate ('Initial' or 'Maintenance').
111
+ * @param liquidationBuffer - Optional buffer amount to consider during liquidation scenarios.
112
+ * @param strict - Optional flag to enforce strict margin calculations.
113
+ * @param includeOpenOrders - Optional flag to include open orders in the margin calculation.
114
+ * @param enteringHighLeverage - Optional flag indicating if the user is entering high leverage mode.
115
+ * @param perpMarketIndex - Optional index of the perpetual market. Required if marginType is 'Isolated'.
116
+ *
117
+ * @returns The calculated margin requirement as a BN (BigNumber).
118
+ */
119
+ getMarginRequirement(marginCategory: MarginCategory, liquidationBuffer?: BN, strict?: boolean, includeOpenOrders?: boolean, enteringHighLeverage?: boolean, perpMarketIndex?: number): BN;
104
120
  /**
105
121
  * @returns The initial margin requirement in USDC. : QUOTE_PRECISION
106
122
  */
107
- getInitialMarginRequirement(enterHighLeverageMode?: any): BN;
123
+ getInitialMarginRequirement(enterHighLeverageMode?: boolean, perpMarketIndex?: number): BN;
108
124
  /**
109
125
  * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
110
126
  */
111
- getMaintenanceMarginRequirement(liquidationBuffer?: BN): BN;
127
+ getMaintenanceMarginRequirement(liquidationBuffer?: BN, perpMarketIndex?: number): BN;
112
128
  getActivePerpPositionsForUserAccount(userAccount: UserAccount): PerpPosition[];
113
129
  getActivePerpPositions(): PerpPosition[];
114
130
  getActivePerpPositionsAndSlot(): DataAndSlot<PerpPosition[]>;
@@ -147,13 +163,13 @@ export declare class User {
147
163
  * calculates TotalCollateral: collateral + unrealized pnl
148
164
  * @returns : Precision QUOTE_PRECISION
149
165
  */
150
- getTotalCollateral(marginCategory?: MarginCategory, strict?: boolean, includeOpenOrders?: boolean, liquidationBuffer?: BN): BN;
166
+ getTotalCollateral(marginCategory?: MarginCategory, strict?: boolean, includeOpenOrders?: boolean, liquidationBuffer?: BN, perpMarketIndex?: number): BN;
151
167
  getLiquidationBuffer(): BN | undefined;
152
168
  /**
153
169
  * calculates User Health by comparing total collateral and maint. margin requirement
154
170
  * @returns : number (value from [0, 100])
155
171
  */
156
- getHealth(): number;
172
+ getHealth(perpMarketIndex?: number): number;
157
173
  calculateWeightedPerpPositionLiability(perpPosition: PerpPosition, marginCategory?: MarginCategory, liquidationBuffer?: BN, includeOpenOrders?: boolean, strict?: boolean, enteringHighLeverage?: any): BN;
158
174
  /**
159
175
  * calculates position value of a single perp market in margin system
@@ -185,14 +201,14 @@ export declare class User {
185
201
  * calculates current user leverage which is (total liability size) / (net asset value)
186
202
  * @returns : Precision TEN_THOUSAND
187
203
  */
188
- getLeverage(includeOpenOrders?: boolean): BN;
204
+ getLeverage(includeOpenOrders?: boolean, perpMarketIndex?: number): BN;
189
205
  calculateLeverageFromComponents({ perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue, }: {
190
206
  perpLiabilityValue: BN;
191
207
  perpPnl: BN;
192
208
  spotAssetValue: BN;
193
209
  spotLiabilityValue: BN;
194
210
  }): BN;
195
- getLeverageComponents(includeOpenOrders?: boolean, marginCategory?: MarginCategory): {
211
+ getLeverageComponents(includeOpenOrders?: boolean, marginCategory?: MarginCategory, perpMarketIndex?: number): {
196
212
  perpLiabilityValue: BN;
197
213
  perpPnl: BN;
198
214
  spotAssetValue: BN;
@@ -234,8 +250,28 @@ export declare class User {
234
250
  canBeLiquidated: boolean;
235
251
  marginRequirement: BN;
236
252
  totalCollateral: BN;
253
+ liquidationStatuses: Map<'cross' | number, {
254
+ canBeLiquidated: boolean;
255
+ marginRequirement: BN;
256
+ totalCollateral: BN;
257
+ }>;
237
258
  };
238
- isBeingLiquidated(): boolean;
259
+ /**
260
+ * New API: Returns liquidation status for cross and each isolated perp position.
261
+ * Map keys:
262
+ * - 'cross' for cross margin
263
+ * - marketIndex (number) for each isolated perp position
264
+ */
265
+ getLiquidationStatuses(marginCalc?: MarginCalculation): Map<'cross' | number, {
266
+ canBeLiquidated: boolean;
267
+ marginRequirement: BN;
268
+ totalCollateral: BN;
269
+ }>;
270
+ isBeingLiquidated(marginCalc?: MarginCalculation): boolean;
271
+ /** Returns true if cross margin is currently below maintenance requirement (no buffer). */
272
+ isCrossMarginBeingLiquidated(marginCalc?: MarginCalculation): boolean;
273
+ /** Returns true if any isolated perp position is currently below its maintenance requirement (no buffer). */
274
+ isIsolatedMarginBeingLiquidated(marginCalc?: MarginCalculation): boolean;
239
275
  hasStatus(status: UserStatus): boolean;
240
276
  isBankrupt(): boolean;
241
277
  isHighLeverageMode(marginCategory: MarginCategory): boolean;
@@ -260,7 +296,7 @@ export declare class User {
260
296
  * @param offsetCollateral // allows calculating the liquidation price after this offset collateral is added to the user's account (e.g. : what will the liquidation price be for this position AFTER I deposit $x worth of collateral)
261
297
  * @returns Precision : PRICE_PRECISION
262
298
  */
263
- liquidationPrice(marketIndex: number, positionBaseSizeChange?: BN, estimatedEntryPrice?: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean, offsetCollateral?: BN, enteringHighLeverage?: any): BN;
299
+ liquidationPrice(marketIndex: number, positionBaseSizeChange?: BN, estimatedEntryPrice?: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean, offsetCollateral?: BN, enteringHighLeverage?: boolean, marginType?: MarginType): BN;
264
300
  calculateEntriesEffectOnFreeCollateral(market: PerpMarketAccount, oraclePrice: BN, perpPosition: PerpPosition, positionBaseSizeChange: BN, estimatedEntryPrice: BN, includeOpenOrders: boolean, enteringHighLeverage?: any, marginCategory?: MarginCategory): BN;
265
301
  calculateFreeCollateralDeltaForPerp(market: PerpMarketAccount, perpPosition: PerpPosition, positionBaseSizeChange: BN, oraclePrice: BN, marginCategory?: MarginCategory, includeOpenOrders?: boolean, enteringHighLeverage?: any): BN | undefined;
266
302
  calculateFreeCollateralDeltaForSpot(market: SpotMarketAccount, signedTokenAmount: BN, marginCategory?: MarginCategory): BN;
@@ -395,4 +431,16 @@ export declare class User {
395
431
  activePerpPositions: number[];
396
432
  activeSpotPositions: number[];
397
433
  };
434
+ /**
435
+ * Compute a consolidated margin snapshot once, without caching.
436
+ * Consumers can use this to avoid duplicating work across separate calls.
437
+ */
438
+ getMarginCalculation(marginCategory?: MarginCategory, opts?: {
439
+ strict?: boolean;
440
+ includeOpenOrders?: boolean;
441
+ enteringHighLeverage?: boolean;
442
+ liquidationBuffer?: BN;
443
+ marginRatioOverride?: number;
444
+ }): MarginCalculation;
445
+ private isPerpPositionIsolated;
398
446
  }