@drift-labs/sdk 2.13.0-beta.0 → 2.13.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/constants/numericConstants.d.ts +2 -0
- package/lib/constants/numericConstants.js +3 -1
- package/lib/driftClient.d.ts +9 -0
- package/lib/driftClient.js +49 -0
- package/lib/idl/drift.json +1 -1
- package/lib/math/margin.d.ts +1 -1
- package/lib/math/margin.js +7 -7
- package/lib/math/market.d.ts +5 -0
- package/lib/math/market.js +18 -1
- package/lib/math/oracles.d.ts +2 -2
- package/lib/math/oracles.js +17 -8
- package/lib/math/orders.js +1 -1
- package/lib/math/spotBalance.d.ts +5 -0
- package/lib/math/spotBalance.js +30 -3
- package/lib/math/trade.js +8 -2
- package/lib/math/utils.js +3 -0
- package/lib/user.d.ts +15 -8
- package/lib/user.js +146 -88
- package/package.json +1 -1
- package/src/constants/numericConstants.ts +2 -0
- package/src/driftClient.ts +64 -0
- package/src/idl/drift.json +1 -1
- package/src/math/margin.ts +9 -7
- package/src/math/market.ts +51 -0
- package/src/math/oracles.ts +27 -16
- package/src/math/orders.ts +2 -2
- package/src/math/spotBalance.ts +51 -3
- package/src/math/trade.ts +10 -2
- package/src/math/utils.ts +5 -1
- package/src/user.ts +321 -153
- package/tests/amm/test.ts +3 -2
package/src/math/market.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
MarginCategory,
|
|
6
6
|
SpotMarketAccount,
|
|
7
7
|
SpotBalanceType,
|
|
8
|
+
MarketType,
|
|
8
9
|
} from '../types';
|
|
9
10
|
import {
|
|
10
11
|
calculateAmmReservesAfterSwap,
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
calculateUpdatedAMMSpreadReserves,
|
|
13
14
|
getSwapDirection,
|
|
14
15
|
calculateUpdatedAMM,
|
|
16
|
+
calculateMarketOpenBidAsk,
|
|
15
17
|
} from './amm';
|
|
16
18
|
import {
|
|
17
19
|
calculateSizeDiscountAssetWeight,
|
|
@@ -25,6 +27,7 @@ import {
|
|
|
25
27
|
ZERO,
|
|
26
28
|
} from '../constants/numericConstants';
|
|
27
29
|
import { getTokenAmount } from './spotBalance';
|
|
30
|
+
import { DLOB } from '../dlob/DLOB';
|
|
28
31
|
|
|
29
32
|
/**
|
|
30
33
|
* Calculates market mark price
|
|
@@ -232,3 +235,51 @@ export function calculateNetUserPnlImbalance(
|
|
|
232
235
|
|
|
233
236
|
return imbalance;
|
|
234
237
|
}
|
|
238
|
+
|
|
239
|
+
export function calculateAvailablePerpLiquidity(
|
|
240
|
+
market: PerpMarketAccount,
|
|
241
|
+
oraclePriceData: OraclePriceData,
|
|
242
|
+
dlob: DLOB,
|
|
243
|
+
slot: number
|
|
244
|
+
): { bids: BN; asks: BN } {
|
|
245
|
+
let [bids, asks] = calculateMarketOpenBidAsk(
|
|
246
|
+
market.amm.baseAssetReserve,
|
|
247
|
+
market.amm.minBaseAssetReserve,
|
|
248
|
+
market.amm.maxBaseAssetReserve,
|
|
249
|
+
market.amm.orderStepSize
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
asks = asks.abs();
|
|
253
|
+
|
|
254
|
+
const bidPrice = calculateBidPrice(market, oraclePriceData);
|
|
255
|
+
const askPrice = calculateAskPrice(market, oraclePriceData);
|
|
256
|
+
|
|
257
|
+
for (const bid of dlob.getMakerLimitBids(
|
|
258
|
+
market.marketIndex,
|
|
259
|
+
slot,
|
|
260
|
+
MarketType.PERP,
|
|
261
|
+
oraclePriceData,
|
|
262
|
+
askPrice
|
|
263
|
+
)) {
|
|
264
|
+
bids = bids.add(
|
|
265
|
+
bid.order.baseAssetAmount.sub(bid.order.baseAssetAmountFilled)
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
for (const ask of dlob.getMakerLimitAsks(
|
|
270
|
+
market.marketIndex,
|
|
271
|
+
slot,
|
|
272
|
+
MarketType.PERP,
|
|
273
|
+
oraclePriceData,
|
|
274
|
+
bidPrice
|
|
275
|
+
)) {
|
|
276
|
+
asks = asks.add(
|
|
277
|
+
ask.order.baseAssetAmount.sub(ask.order.baseAssetAmountFilled)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
bids: bids,
|
|
283
|
+
asks: asks,
|
|
284
|
+
};
|
|
285
|
+
}
|
package/src/math/oracles.ts
CHANGED
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
PRICE_PRECISION,
|
|
7
7
|
ONE,
|
|
8
8
|
ZERO,
|
|
9
|
+
FIVE_MINUTE,
|
|
9
10
|
} from '../constants/numericConstants';
|
|
10
|
-
import { BN, PerpMarketAccount } from '../index';
|
|
11
|
+
import { BN, HistoricalOracleData, PerpMarketAccount } from '../index';
|
|
11
12
|
import { assert } from '../assert/assert';
|
|
12
13
|
|
|
13
14
|
export function oraclePriceBands(
|
|
@@ -68,7 +69,7 @@ export function isOracleTooDivergent(
|
|
|
68
69
|
const sinceLastUpdate = now.sub(
|
|
69
70
|
amm.historicalOracleData.lastOraclePriceTwapTs
|
|
70
71
|
);
|
|
71
|
-
const sinceStart = BN.max(ZERO,
|
|
72
|
+
const sinceStart = BN.max(ZERO, FIVE_MINUTE.sub(sinceLastUpdate));
|
|
72
73
|
const oracleTwap5min = amm.historicalOracleData.lastOraclePriceTwap5Min
|
|
73
74
|
.mul(sinceStart)
|
|
74
75
|
.add(oraclePriceData.price)
|
|
@@ -90,29 +91,34 @@ export function isOracleTooDivergent(
|
|
|
90
91
|
}
|
|
91
92
|
|
|
92
93
|
export function calculateLiveOracleTwap(
|
|
93
|
-
|
|
94
|
+
histOracleData: HistoricalOracleData,
|
|
94
95
|
oraclePriceData: OraclePriceData,
|
|
95
|
-
now: BN
|
|
96
|
+
now: BN,
|
|
97
|
+
period: BN
|
|
96
98
|
): BN {
|
|
99
|
+
let oracleTwap = undefined;
|
|
100
|
+
if (period.eq(FIVE_MINUTE)) {
|
|
101
|
+
oracleTwap = histOracleData.lastOraclePriceTwap5Min;
|
|
102
|
+
} else {
|
|
103
|
+
//todo: assumes its fundingPeriod (1hr)
|
|
104
|
+
// period = amm.fundingPeriod;
|
|
105
|
+
oracleTwap = histOracleData.lastOraclePriceTwap;
|
|
106
|
+
}
|
|
107
|
+
|
|
97
108
|
const sinceLastUpdate = BN.max(
|
|
98
109
|
ONE,
|
|
99
|
-
now.sub(
|
|
110
|
+
now.sub(histOracleData.lastOraclePriceTwapTs)
|
|
100
111
|
);
|
|
101
|
-
const sinceStart = BN.max(ZERO,
|
|
112
|
+
const sinceStart = BN.max(ZERO, period.sub(sinceLastUpdate));
|
|
102
113
|
|
|
103
|
-
const clampRange =
|
|
104
|
-
new BN(3)
|
|
105
|
-
);
|
|
114
|
+
const clampRange = oracleTwap.div(new BN(3));
|
|
106
115
|
|
|
107
116
|
const clampedOraclePrice = BN.min(
|
|
108
|
-
|
|
109
|
-
BN.max(
|
|
110
|
-
oraclePriceData.price,
|
|
111
|
-
amm.historicalOracleData.lastOraclePriceTwap.sub(clampRange)
|
|
112
|
-
)
|
|
117
|
+
oracleTwap.add(clampRange),
|
|
118
|
+
BN.max(oraclePriceData.price, oracleTwap.sub(clampRange))
|
|
113
119
|
);
|
|
114
120
|
|
|
115
|
-
const newOracleTwap =
|
|
121
|
+
const newOracleTwap = oracleTwap
|
|
116
122
|
.mul(sinceStart)
|
|
117
123
|
.add(clampedOraclePrice.mul(sinceLastUpdate))
|
|
118
124
|
.div(sinceStart.add(sinceLastUpdate));
|
|
@@ -131,7 +137,12 @@ export function calculateLiveOracleStd(
|
|
|
131
137
|
);
|
|
132
138
|
const sinceStart = BN.max(ZERO, amm.fundingPeriod.sub(sinceLastUpdate));
|
|
133
139
|
|
|
134
|
-
const liveOracleTwap = calculateLiveOracleTwap(
|
|
140
|
+
const liveOracleTwap = calculateLiveOracleTwap(
|
|
141
|
+
amm.historicalOracleData,
|
|
142
|
+
oraclePriceData,
|
|
143
|
+
now,
|
|
144
|
+
amm.fundingPeriod
|
|
145
|
+
);
|
|
135
146
|
|
|
136
147
|
const priceDeltaVsTwap = oraclePriceData.price.sub(liveOracleTwap).abs();
|
|
137
148
|
|
package/src/math/orders.ts
CHANGED
|
@@ -165,12 +165,12 @@ export function isFillableByVAMM(
|
|
|
165
165
|
): boolean {
|
|
166
166
|
return (
|
|
167
167
|
(isAuctionComplete(order, slot) &&
|
|
168
|
-
|
|
168
|
+
calculateBaseAssetAmountForAmmToFulfill(
|
|
169
169
|
order,
|
|
170
170
|
market,
|
|
171
171
|
oraclePriceData,
|
|
172
172
|
slot
|
|
173
|
-
).
|
|
173
|
+
).gte(market.amm.minOrderSize)) ||
|
|
174
174
|
isOrderExpired(order, ts)
|
|
175
175
|
);
|
|
176
176
|
}
|
package/src/math/spotBalance.ts
CHANGED
|
@@ -67,6 +67,28 @@ export function getSignedTokenAmount(
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
export function getStrictTokenValue(
|
|
71
|
+
tokenAmount: BN,
|
|
72
|
+
spotDecimals: number,
|
|
73
|
+
oraclePriceData: OraclePriceData,
|
|
74
|
+
oraclePriceTwap: BN
|
|
75
|
+
): BN {
|
|
76
|
+
if (tokenAmount.eq(ZERO)) {
|
|
77
|
+
return ZERO;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let price = oraclePriceData.price;
|
|
81
|
+
if (tokenAmount.gt(ZERO)) {
|
|
82
|
+
price = BN.min(oraclePriceData.price, oraclePriceTwap);
|
|
83
|
+
} else {
|
|
84
|
+
price = BN.max(oraclePriceData.price, oraclePriceTwap);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const precisionDecrease = TEN.pow(new BN(spotDecimals));
|
|
88
|
+
|
|
89
|
+
return tokenAmount.mul(price).div(precisionDecrease);
|
|
90
|
+
}
|
|
91
|
+
|
|
70
92
|
export function getTokenValue(
|
|
71
93
|
tokenAmount: BN,
|
|
72
94
|
spotDecimals: number,
|
|
@@ -268,7 +290,14 @@ export function calculateInterestAccumulated(
|
|
|
268
290
|
export function calculateWithdrawLimit(
|
|
269
291
|
spotMarket: SpotMarketAccount,
|
|
270
292
|
now: BN
|
|
271
|
-
): {
|
|
293
|
+
): {
|
|
294
|
+
borrowLimit: BN;
|
|
295
|
+
withdrawLimit: BN;
|
|
296
|
+
minDepositAmount: BN;
|
|
297
|
+
maxBorrowAmount: BN;
|
|
298
|
+
currentDepositAmount;
|
|
299
|
+
currentBorrowAmount;
|
|
300
|
+
} {
|
|
272
301
|
const marketDepositTokenAmount = getTokenAmount(
|
|
273
302
|
spotMarket.depositBalance,
|
|
274
303
|
spotMarket,
|
|
@@ -311,8 +340,27 @@ export function calculateWithdrawLimit(
|
|
|
311
340
|
)
|
|
312
341
|
);
|
|
313
342
|
|
|
343
|
+
let withdrawLimit = BN.max(
|
|
344
|
+
marketDepositTokenAmount.sub(minDepositTokens),
|
|
345
|
+
ZERO
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
let borrowLimit = BN.max(maxBorrowTokens.sub(marketBorrowTokenAmount), ZERO);
|
|
349
|
+
|
|
350
|
+
if (borrowLimit.eq(ZERO)) {
|
|
351
|
+
withdrawLimit = ZERO;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (withdrawLimit.eq(ZERO)) {
|
|
355
|
+
borrowLimit = ZERO;
|
|
356
|
+
}
|
|
357
|
+
|
|
314
358
|
return {
|
|
315
|
-
borrowLimit
|
|
316
|
-
withdrawLimit
|
|
359
|
+
borrowLimit,
|
|
360
|
+
withdrawLimit,
|
|
361
|
+
maxBorrowAmount: maxBorrowTokens,
|
|
362
|
+
minDepositAmount: minDepositTokens,
|
|
363
|
+
currentDepositAmount: marketDepositTokenAmount,
|
|
364
|
+
currentBorrowAmount: marketBorrowTokenAmount,
|
|
317
365
|
};
|
|
318
366
|
}
|
package/src/math/trade.ts
CHANGED
|
@@ -529,7 +529,11 @@ export function calculateEstimatedPerpEntryPrice(
|
|
|
529
529
|
}
|
|
530
530
|
}
|
|
531
531
|
|
|
532
|
-
if (limitOrder
|
|
532
|
+
if (!limitOrder) {
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
if (usersToSkip.has(limitOrder.userAccount)) {
|
|
533
537
|
continue;
|
|
534
538
|
}
|
|
535
539
|
|
|
@@ -615,7 +619,11 @@ export function calculateEstimatedPerpEntryPrice(
|
|
|
615
619
|
}
|
|
616
620
|
}
|
|
617
621
|
|
|
618
|
-
if (limitOrder
|
|
622
|
+
if (!limitOrder) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if (usersToSkip.has(limitOrder.userAccount)) {
|
|
619
627
|
continue;
|
|
620
628
|
}
|
|
621
629
|
|
package/src/math/utils.ts
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import { BN } from '../';
|
|
1
|
+
import { BN, ZERO } from '../';
|
|
2
2
|
|
|
3
3
|
export function clampBN(x: BN, min: BN, max: BN): BN {
|
|
4
4
|
return BN.max(min, BN.min(x, max));
|
|
5
5
|
}
|
|
6
6
|
|
|
7
7
|
export const squareRootBN = (n, closeness = new BN(1)): BN => {
|
|
8
|
+
if (n.lt(ZERO)) {
|
|
9
|
+
throw new Error('square root of negative number');
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
// Assuming the sqrt of n as n only
|
|
9
13
|
let x = n;
|
|
10
14
|
|