@drift-labs/sdk 2.35.1-beta.6 → 2.35.1-beta.8
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/dlob/DLOB.js +14 -4
- package/lib/math/orders.d.ts +1 -1
- package/lib/math/orders.js +9 -2
- package/lib/user.d.ts +5 -4
- package/lib/user.js +17 -7
- package/package.json +1 -1
- package/src/dlob/DLOB.ts +14 -4
- package/src/math/orders.ts +13 -2
- package/src/user.ts +23 -7
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.35.1-beta.
|
|
1
|
+
2.35.1-beta.8
|
package/lib/dlob/DLOB.js
CHANGED
|
@@ -491,11 +491,21 @@ class DLOB {
|
|
|
491
491
|
}
|
|
492
492
|
// All bids/asks that can expire
|
|
493
493
|
// dont try to expire limit orders with tif as its inefficient use of blockspace
|
|
494
|
-
const bidGenerators = [
|
|
495
|
-
|
|
494
|
+
const bidGenerators = [
|
|
495
|
+
nodeLists.takingLimit.bid.getGenerator(),
|
|
496
|
+
nodeLists.restingLimit.bid.getGenerator(),
|
|
497
|
+
nodeLists.floatingLimit.bid.getGenerator(),
|
|
498
|
+
nodeLists.market.bid.getGenerator(),
|
|
499
|
+
];
|
|
500
|
+
const askGenerators = [
|
|
501
|
+
nodeLists.takingLimit.ask.getGenerator(),
|
|
502
|
+
nodeLists.restingLimit.ask.getGenerator(),
|
|
503
|
+
nodeLists.floatingLimit.ask.getGenerator(),
|
|
504
|
+
nodeLists.market.ask.getGenerator(),
|
|
505
|
+
];
|
|
496
506
|
for (const bidGenerator of bidGenerators) {
|
|
497
507
|
for (const bid of bidGenerator) {
|
|
498
|
-
if ((0, __1.isOrderExpired)(bid.order, ts)) {
|
|
508
|
+
if ((0, __1.isOrderExpired)(bid.order, ts, true)) {
|
|
499
509
|
nodesToFill.push({
|
|
500
510
|
node: bid,
|
|
501
511
|
makerNodes: [],
|
|
@@ -505,7 +515,7 @@ class DLOB {
|
|
|
505
515
|
}
|
|
506
516
|
for (const askGenerator of askGenerators) {
|
|
507
517
|
for (const ask of askGenerator) {
|
|
508
|
-
if ((0, __1.isOrderExpired)(ask.order, ts)) {
|
|
518
|
+
if ((0, __1.isOrderExpired)(ask.order, ts, true)) {
|
|
509
519
|
nodesToFill.push({
|
|
510
520
|
node: ask,
|
|
511
521
|
makerNodes: [],
|
package/lib/math/orders.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function hasAuctionPrice(order: Order, slot: number): boolean;
|
|
|
13
13
|
export declare function isFillableByVAMM(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number, ts: number): boolean;
|
|
14
14
|
export declare function calculateBaseAssetAmountForAmmToFulfill(order: Order, market: PerpMarketAccount, oraclePriceData: OraclePriceData, slot: number): BN;
|
|
15
15
|
export declare function calculateBaseAssetAmountToFillUpToLimitPrice(order: Order, amm: AMM, limitPrice: BN, oraclePriceData: OraclePriceData): BN;
|
|
16
|
-
export declare function isOrderExpired(order: Order, ts: number): boolean;
|
|
16
|
+
export declare function isOrderExpired(order: Order, ts: number, enforceBuffer?: boolean): boolean;
|
|
17
17
|
export declare function isMarketOrder(order: Order): boolean;
|
|
18
18
|
export declare function isLimitOrder(order: Order): boolean;
|
|
19
19
|
export declare function mustBeTriggered(order: Order): boolean;
|
package/lib/math/orders.js
CHANGED
|
@@ -168,13 +168,20 @@ function isSameDirection(firstDirection, secondDirection) {
|
|
|
168
168
|
return (((0, types_1.isVariant)(firstDirection, 'long') && (0, types_1.isVariant)(secondDirection, 'long')) ||
|
|
169
169
|
((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
|
|
170
170
|
}
|
|
171
|
-
function isOrderExpired(order, ts) {
|
|
171
|
+
function isOrderExpired(order, ts, enforceBuffer = false) {
|
|
172
172
|
if (mustBeTriggered(order) ||
|
|
173
173
|
!(0, types_1.isVariant)(order.status, 'open') ||
|
|
174
174
|
order.maxTs.eq(numericConstants_1.ZERO)) {
|
|
175
175
|
return false;
|
|
176
176
|
}
|
|
177
|
-
|
|
177
|
+
let maxTs;
|
|
178
|
+
if (enforceBuffer && isLimitOrder(order)) {
|
|
179
|
+
maxTs = order.maxTs.addn(15);
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
maxTs = order.maxTs;
|
|
183
|
+
}
|
|
184
|
+
return new anchor_1.BN(ts).gt(maxTs);
|
|
178
185
|
}
|
|
179
186
|
exports.isOrderExpired = isOrderExpired;
|
|
180
187
|
function isMarketOrder(order) {
|
package/lib/user.d.ts
CHANGED
|
@@ -98,7 +98,7 @@ export declare class User {
|
|
|
98
98
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
99
99
|
* @returns : Precision QUOTE_PRECISION
|
|
100
100
|
*/
|
|
101
|
-
getPerpBuyingPower(marketIndex: number): BN;
|
|
101
|
+
getPerpBuyingPower(marketIndex: number, collateralBuffer?: any): BN;
|
|
102
102
|
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex: number, freeCollateral: BN, baseAssetAmount: BN): BN;
|
|
103
103
|
/**
|
|
104
104
|
* calculates Free Collateral = Total collateral - initial margin requirement
|
|
@@ -191,10 +191,11 @@ export declare class User {
|
|
|
191
191
|
/**
|
|
192
192
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
193
193
|
* for large sizes where imf factor activates, result is a lower bound
|
|
194
|
-
* @
|
|
194
|
+
* @param marginCategory {Initial, Maintenance}
|
|
195
|
+
* @param isLp if calculating max leveraging for adding lp, need to add buffer
|
|
195
196
|
* @returns : Precision TEN_THOUSAND
|
|
196
197
|
*/
|
|
197
|
-
getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory): BN;
|
|
198
|
+
getMaxLeverageForPerp(perpMarketIndex: number, marginCategory?: MarginCategory, isLp?: boolean): BN;
|
|
198
199
|
/**
|
|
199
200
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
200
201
|
* @param spotMarketIndex
|
|
@@ -262,7 +263,7 @@ export declare class User {
|
|
|
262
263
|
* @param tradeSide
|
|
263
264
|
* @returns tradeSizeAllowed : Precision QUOTE_PRECISION
|
|
264
265
|
*/
|
|
265
|
-
getMaxTradeSizeUSDCForPerp(targetMarketIndex: number, tradeSide: PositionDirection): BN;
|
|
266
|
+
getMaxTradeSizeUSDCForPerp(targetMarketIndex: number, tradeSide: PositionDirection, isLp?: boolean): BN;
|
|
266
267
|
/**
|
|
267
268
|
* Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
|
|
268
269
|
*
|
package/lib/user.js
CHANGED
|
@@ -363,12 +363,12 @@ class User {
|
|
|
363
363
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
364
364
|
* @returns : Precision QUOTE_PRECISION
|
|
365
365
|
*/
|
|
366
|
-
getPerpBuyingPower(marketIndex) {
|
|
366
|
+
getPerpBuyingPower(marketIndex, collateralBuffer = numericConstants_1.ZERO) {
|
|
367
367
|
const perpPosition = this.getPerpPositionWithLPSettle(marketIndex, undefined, true)[0];
|
|
368
368
|
const worstCaseBaseAssetAmount = perpPosition
|
|
369
369
|
? (0, margin_1.calculateWorstCaseBaseAssetAmount)(perpPosition)
|
|
370
370
|
: numericConstants_1.ZERO;
|
|
371
|
-
const freeCollateral = this.getFreeCollateral();
|
|
371
|
+
const freeCollateral = this.getFreeCollateral().sub(collateralBuffer);
|
|
372
372
|
return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, worstCaseBaseAssetAmount);
|
|
373
373
|
}
|
|
374
374
|
getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(marketIndex, freeCollateral, baseAssetAmount) {
|
|
@@ -818,10 +818,11 @@ class User {
|
|
|
818
818
|
/**
|
|
819
819
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
820
820
|
* for large sizes where imf factor activates, result is a lower bound
|
|
821
|
-
* @
|
|
821
|
+
* @param marginCategory {Initial, Maintenance}
|
|
822
|
+
* @param isLp if calculating max leveraging for adding lp, need to add buffer
|
|
822
823
|
* @returns : Precision TEN_THOUSAND
|
|
823
824
|
*/
|
|
824
|
-
getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial') {
|
|
825
|
+
getMaxLeverageForPerp(perpMarketIndex, marginCategory = 'Initial', isLp = false) {
|
|
825
826
|
const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
|
|
826
827
|
const marketPrice = this.driftClient.getOracleDataForPerpMarket(perpMarketIndex).price;
|
|
827
828
|
const { perpLiabilityValue, perpPnl, spotAssetValue, spotLiabilityValue } = this.getLeverageComponents();
|
|
@@ -831,7 +832,10 @@ class User {
|
|
|
831
832
|
return numericConstants_1.ZERO;
|
|
832
833
|
}
|
|
833
834
|
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
834
|
-
const
|
|
835
|
+
const lpBuffer = isLp
|
|
836
|
+
? marketPrice.mul(market.amm.orderStepSize).div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
837
|
+
: numericConstants_1.ZERO;
|
|
838
|
+
const freeCollateral = this.getFreeCollateral().sub(lpBuffer);
|
|
835
839
|
let rawMarginRatio;
|
|
836
840
|
switch (marginCategory) {
|
|
837
841
|
case 'Initial':
|
|
@@ -1145,7 +1149,7 @@ class User {
|
|
|
1145
1149
|
* @param tradeSide
|
|
1146
1150
|
* @returns tradeSizeAllowed : Precision QUOTE_PRECISION
|
|
1147
1151
|
*/
|
|
1148
|
-
getMaxTradeSizeUSDCForPerp(targetMarketIndex, tradeSide) {
|
|
1152
|
+
getMaxTradeSizeUSDCForPerp(targetMarketIndex, tradeSide, isLp = false) {
|
|
1149
1153
|
const currentPosition = this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
|
|
1150
1154
|
this.getEmptyPosition(targetMarketIndex);
|
|
1151
1155
|
const targetSide = (0, types_1.isVariant)(tradeSide, 'short') ? 'short' : 'long';
|
|
@@ -1156,11 +1160,17 @@ class User {
|
|
|
1156
1160
|
? true
|
|
1157
1161
|
: targetSide === currentPositionSide;
|
|
1158
1162
|
const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
|
|
1163
|
+
const marketAccount = this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
1164
|
+
const lpBuffer = isLp
|
|
1165
|
+
? oracleData.price
|
|
1166
|
+
.mul(marketAccount.amm.orderStepSize)
|
|
1167
|
+
.div(numericConstants_1.AMM_RESERVE_PRECISION)
|
|
1168
|
+
: numericConstants_1.ZERO;
|
|
1159
1169
|
// add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
|
|
1160
1170
|
const oppositeSizeValueUSDC = targetingSameSide
|
|
1161
1171
|
? numericConstants_1.ZERO
|
|
1162
1172
|
: this.getPerpPositionValue(targetMarketIndex, oracleData);
|
|
1163
|
-
let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex);
|
|
1173
|
+
let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex, lpBuffer);
|
|
1164
1174
|
if (maxPositionSize.gte(numericConstants_1.ZERO)) {
|
|
1165
1175
|
if (oppositeSizeValueUSDC.eq(numericConstants_1.ZERO)) {
|
|
1166
1176
|
// case 1 : Regular trade where current total position less than max, and no opposite position to account for
|
package/package.json
CHANGED
package/src/dlob/DLOB.ts
CHANGED
|
@@ -931,12 +931,22 @@ export class DLOB {
|
|
|
931
931
|
|
|
932
932
|
// All bids/asks that can expire
|
|
933
933
|
// dont try to expire limit orders with tif as its inefficient use of blockspace
|
|
934
|
-
const bidGenerators = [
|
|
935
|
-
|
|
934
|
+
const bidGenerators = [
|
|
935
|
+
nodeLists.takingLimit.bid.getGenerator(),
|
|
936
|
+
nodeLists.restingLimit.bid.getGenerator(),
|
|
937
|
+
nodeLists.floatingLimit.bid.getGenerator(),
|
|
938
|
+
nodeLists.market.bid.getGenerator(),
|
|
939
|
+
];
|
|
940
|
+
const askGenerators = [
|
|
941
|
+
nodeLists.takingLimit.ask.getGenerator(),
|
|
942
|
+
nodeLists.restingLimit.ask.getGenerator(),
|
|
943
|
+
nodeLists.floatingLimit.ask.getGenerator(),
|
|
944
|
+
nodeLists.market.ask.getGenerator(),
|
|
945
|
+
];
|
|
936
946
|
|
|
937
947
|
for (const bidGenerator of bidGenerators) {
|
|
938
948
|
for (const bid of bidGenerator) {
|
|
939
|
-
if (isOrderExpired(bid.order, ts)) {
|
|
949
|
+
if (isOrderExpired(bid.order, ts, true)) {
|
|
940
950
|
nodesToFill.push({
|
|
941
951
|
node: bid,
|
|
942
952
|
makerNodes: [],
|
|
@@ -947,7 +957,7 @@ export class DLOB {
|
|
|
947
957
|
|
|
948
958
|
for (const askGenerator of askGenerators) {
|
|
949
959
|
for (const ask of askGenerator) {
|
|
950
|
-
if (isOrderExpired(ask.order, ts)) {
|
|
960
|
+
if (isOrderExpired(ask.order, ts, true)) {
|
|
951
961
|
nodesToFill.push({
|
|
952
962
|
node: ask,
|
|
953
963
|
makerNodes: [],
|
package/src/math/orders.ts
CHANGED
|
@@ -279,7 +279,11 @@ function isSameDirection(
|
|
|
279
279
|
);
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
-
export function isOrderExpired(
|
|
282
|
+
export function isOrderExpired(
|
|
283
|
+
order: Order,
|
|
284
|
+
ts: number,
|
|
285
|
+
enforceBuffer = false
|
|
286
|
+
): boolean {
|
|
283
287
|
if (
|
|
284
288
|
mustBeTriggered(order) ||
|
|
285
289
|
!isVariant(order.status, 'open') ||
|
|
@@ -288,7 +292,14 @@ export function isOrderExpired(order: Order, ts: number): boolean {
|
|
|
288
292
|
return false;
|
|
289
293
|
}
|
|
290
294
|
|
|
291
|
-
|
|
295
|
+
let maxTs;
|
|
296
|
+
if (enforceBuffer && isLimitOrder(order)) {
|
|
297
|
+
maxTs = order.maxTs.addn(15);
|
|
298
|
+
} else {
|
|
299
|
+
maxTs = order.maxTs;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
return new BN(ts).gt(maxTs);
|
|
292
303
|
}
|
|
293
304
|
|
|
294
305
|
export function isMarketOrder(order: Order): boolean {
|
package/src/user.ts
CHANGED
|
@@ -558,7 +558,7 @@ export class User {
|
|
|
558
558
|
* calculates Buying Power = free collateral / initial margin ratio
|
|
559
559
|
* @returns : Precision QUOTE_PRECISION
|
|
560
560
|
*/
|
|
561
|
-
public getPerpBuyingPower(marketIndex: number): BN {
|
|
561
|
+
public getPerpBuyingPower(marketIndex: number, collateralBuffer = ZERO): BN {
|
|
562
562
|
const perpPosition = this.getPerpPositionWithLPSettle(
|
|
563
563
|
marketIndex,
|
|
564
564
|
undefined,
|
|
@@ -568,7 +568,7 @@ export class User {
|
|
|
568
568
|
? calculateWorstCaseBaseAssetAmount(perpPosition)
|
|
569
569
|
: ZERO;
|
|
570
570
|
|
|
571
|
-
const freeCollateral = this.getFreeCollateral();
|
|
571
|
+
const freeCollateral = this.getFreeCollateral().sub(collateralBuffer);
|
|
572
572
|
|
|
573
573
|
return this.getPerpBuyingPowerFromFreeCollateralAndBaseAssetAmount(
|
|
574
574
|
marketIndex,
|
|
@@ -1490,12 +1490,14 @@ export class User {
|
|
|
1490
1490
|
/**
|
|
1491
1491
|
* calculates max allowable leverage exceeding hitting requirement category
|
|
1492
1492
|
* for large sizes where imf factor activates, result is a lower bound
|
|
1493
|
-
* @
|
|
1493
|
+
* @param marginCategory {Initial, Maintenance}
|
|
1494
|
+
* @param isLp if calculating max leveraging for adding lp, need to add buffer
|
|
1494
1495
|
* @returns : Precision TEN_THOUSAND
|
|
1495
1496
|
*/
|
|
1496
1497
|
public getMaxLeverageForPerp(
|
|
1497
1498
|
perpMarketIndex: number,
|
|
1498
|
-
marginCategory: MarginCategory = 'Initial'
|
|
1499
|
+
marginCategory: MarginCategory = 'Initial',
|
|
1500
|
+
isLp = false
|
|
1499
1501
|
): BN {
|
|
1500
1502
|
const market = this.driftClient.getPerpMarketAccount(perpMarketIndex);
|
|
1501
1503
|
const marketPrice =
|
|
@@ -1514,7 +1516,11 @@ export class User {
|
|
|
1514
1516
|
|
|
1515
1517
|
const totalLiabilityValue = perpLiabilityValue.add(spotLiabilityValue);
|
|
1516
1518
|
|
|
1517
|
-
const
|
|
1519
|
+
const lpBuffer = isLp
|
|
1520
|
+
? marketPrice.mul(market.amm.orderStepSize).div(AMM_RESERVE_PRECISION)
|
|
1521
|
+
: ZERO;
|
|
1522
|
+
|
|
1523
|
+
const freeCollateral = this.getFreeCollateral().sub(lpBuffer);
|
|
1518
1524
|
|
|
1519
1525
|
let rawMarginRatio;
|
|
1520
1526
|
|
|
@@ -2059,7 +2065,8 @@ export class User {
|
|
|
2059
2065
|
*/
|
|
2060
2066
|
public getMaxTradeSizeUSDCForPerp(
|
|
2061
2067
|
targetMarketIndex: number,
|
|
2062
|
-
tradeSide: PositionDirection
|
|
2068
|
+
tradeSide: PositionDirection,
|
|
2069
|
+
isLp = false
|
|
2063
2070
|
): BN {
|
|
2064
2071
|
const currentPosition =
|
|
2065
2072
|
this.getPerpPositionWithLPSettle(targetMarketIndex, undefined, true)[0] ||
|
|
@@ -2077,12 +2084,21 @@ export class User {
|
|
|
2077
2084
|
|
|
2078
2085
|
const oracleData = this.getOracleDataForPerpMarket(targetMarketIndex);
|
|
2079
2086
|
|
|
2087
|
+
const marketAccount =
|
|
2088
|
+
this.driftClient.getPerpMarketAccount(targetMarketIndex);
|
|
2089
|
+
|
|
2090
|
+
const lpBuffer = isLp
|
|
2091
|
+
? oracleData.price
|
|
2092
|
+
.mul(marketAccount.amm.orderStepSize)
|
|
2093
|
+
.div(AMM_RESERVE_PRECISION)
|
|
2094
|
+
: ZERO;
|
|
2095
|
+
|
|
2080
2096
|
// add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
|
|
2081
2097
|
const oppositeSizeValueUSDC = targetingSameSide
|
|
2082
2098
|
? ZERO
|
|
2083
2099
|
: this.getPerpPositionValue(targetMarketIndex, oracleData);
|
|
2084
2100
|
|
|
2085
|
-
let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex);
|
|
2101
|
+
let maxPositionSize = this.getPerpBuyingPower(targetMarketIndex, lpBuffer);
|
|
2086
2102
|
if (maxPositionSize.gte(ZERO)) {
|
|
2087
2103
|
if (oppositeSizeValueUSDC.eq(ZERO)) {
|
|
2088
2104
|
// case 1 : Regular trade where current total position less than max, and no opposite position to account for
|