@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.
- package/.env +4 -0
- package/VERSION +1 -1
- package/lib/browser/accounts/grpcMultiUserAccountSubscriber.js +8 -1
- package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
- package/lib/browser/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
- package/lib/browser/adminClient.d.ts +5 -1
- package/lib/browser/adminClient.js +57 -23
- package/lib/browser/constants/numericConstants.d.ts +2 -0
- package/lib/browser/constants/numericConstants.js +5 -1
- package/lib/browser/constants/perpMarkets.js +0 -2
- package/lib/browser/decode/user.js +4 -0
- package/lib/browser/driftClient.d.ts +25 -10
- package/lib/browser/driftClient.js +238 -41
- package/lib/browser/driftClientConfig.d.ts +7 -2
- package/lib/browser/idl/drift.json +245 -22
- package/lib/browser/index.d.ts +4 -0
- package/lib/browser/index.js +9 -1
- package/lib/browser/marginCalculation.d.ts +86 -0
- package/lib/browser/marginCalculation.js +209 -0
- package/lib/browser/math/margin.d.ts +1 -1
- package/lib/browser/math/margin.js +8 -1
- package/lib/browser/math/position.d.ts +1 -0
- package/lib/browser/math/position.js +10 -2
- package/lib/browser/math/spotPosition.d.ts +1 -1
- package/lib/browser/math/spotPosition.js +3 -2
- package/lib/browser/math/superStake.d.ts +3 -2
- package/lib/browser/types.d.ts +13 -0
- package/lib/browser/types.js +12 -1
- package/lib/browser/user.d.ts +59 -11
- package/lib/browser/user.js +348 -43
- package/lib/node/accounts/grpcMultiUserAccountSubscriber.d.ts.map +1 -1
- package/lib/node/accounts/grpcMultiUserAccountSubscriber.js +8 -1
- package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts +99 -7
- package/lib/node/accounts/webSocketProgramAccountSubscriberV2.d.ts.map +1 -1
- package/lib/node/accounts/webSocketProgramAccountSubscriberV2.js +435 -144
- package/lib/node/adminClient.d.ts +5 -1
- package/lib/node/adminClient.d.ts.map +1 -1
- package/lib/node/adminClient.js +57 -23
- package/lib/node/constants/numericConstants.d.ts +2 -0
- package/lib/node/constants/numericConstants.d.ts.map +1 -1
- package/lib/node/constants/numericConstants.js +5 -1
- package/lib/node/constants/perpMarkets.d.ts.map +1 -1
- package/lib/node/constants/perpMarkets.js +0 -2
- package/lib/node/decode/user.d.ts.map +1 -1
- package/lib/node/decode/user.js +4 -0
- package/lib/node/driftClient.d.ts +25 -10
- package/lib/node/driftClient.d.ts.map +1 -1
- package/lib/node/driftClient.js +238 -41
- package/lib/node/driftClientConfig.d.ts +7 -2
- package/lib/node/driftClientConfig.d.ts.map +1 -1
- package/lib/node/idl/drift.json +245 -22
- package/lib/node/index.d.ts +4 -0
- package/lib/node/index.d.ts.map +1 -1
- package/lib/node/index.js +9 -1
- package/lib/node/marginCalculation.d.ts +87 -0
- package/lib/node/marginCalculation.d.ts.map +1 -0
- package/lib/node/marginCalculation.js +209 -0
- package/lib/node/math/margin.d.ts +1 -1
- package/lib/node/math/margin.d.ts.map +1 -1
- package/lib/node/math/margin.js +8 -1
- package/lib/node/math/position.d.ts +1 -0
- package/lib/node/math/position.d.ts.map +1 -1
- package/lib/node/math/position.js +10 -2
- package/lib/node/math/spotPosition.d.ts +1 -1
- package/lib/node/math/spotPosition.d.ts.map +1 -1
- package/lib/node/math/spotPosition.js +3 -2
- package/lib/node/math/superStake.d.ts +3 -2
- package/lib/node/math/superStake.d.ts.map +1 -1
- package/lib/node/types.d.ts +13 -0
- package/lib/node/types.d.ts.map +1 -1
- package/lib/node/types.js +12 -1
- package/lib/node/user.d.ts +59 -11
- package/lib/node/user.d.ts.map +1 -1
- package/lib/node/user.js +348 -43
- package/package.json +1 -1
- package/scripts/deposit-isolated-positions.ts +110 -0
- package/scripts/single-grpc-client-test.ts +71 -21
- package/scripts/withdraw-isolated-positions.ts +174 -0
- package/src/accounts/grpcMultiUserAccountSubscriber.ts +8 -1
- package/src/accounts/webSocketProgramAccountSubscriberV2.ts +566 -167
- package/src/adminClient.ts +74 -25
- package/src/constants/numericConstants.ts +5 -0
- package/src/constants/perpMarkets.ts +0 -3
- package/src/decode/user.ts +7 -1
- package/src/driftClient.ts +465 -52
- package/src/driftClientConfig.ts +15 -8
- package/src/idl/drift.json +246 -23
- package/src/index.ts +4 -0
- package/src/margin/README.md +143 -0
- package/src/marginCalculation.ts +306 -0
- package/src/math/margin.ts +13 -1
- package/src/math/position.ts +12 -2
- package/src/math/spotPosition.ts +6 -2
- package/src/types.ts +16 -0
- package/src/user.ts +623 -81
- package/tests/amm/test.ts +1 -1
- package/tests/dlob/helpers.ts +6 -3
- package/tests/user/getMarginCalculation.ts +405 -0
- 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<
|
|
31
|
-
export declare function fetchBSolDriftEmissions(): Promise<
|
|
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;
|
package/lib/browser/types.d.ts
CHANGED
|
@@ -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
|
} & {
|
package/lib/browser/types.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
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";
|
package/lib/browser/user.d.ts
CHANGED
|
@@ -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?:
|
|
102
|
+
getFreeCollateral(marginCategory?: MarginCategory, enterHighLeverageMode?: boolean, perpMarketIndex?: number): BN;
|
|
100
103
|
/**
|
|
101
|
-
* @
|
|
104
|
+
* @deprecated Use the overload that includes { marginType, perpMarketIndex }
|
|
102
105
|
*/
|
|
103
|
-
getMarginRequirement(marginCategory: MarginCategory, liquidationBuffer?: BN, strict?: boolean, includeOpenOrders?: boolean, enteringHighLeverage?:
|
|
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?:
|
|
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
|
-
|
|
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?:
|
|
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
|
}
|