@drift-labs/sdk 2.0.14 → 2.0.15
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/README.md +3 -3
- package/lib/accounts/pollingDriftClientAccountSubscriber.js +0 -3
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +0 -3
- package/lib/adminClient.d.ts +2 -0
- package/lib/adminClient.js +16 -0
- package/lib/constants/numericConstants.d.ts +2 -0
- package/lib/constants/numericConstants.js +3 -1
- package/lib/dlob/DLOB.d.ts +2 -7
- package/lib/dlob/DLOB.js +84 -166
- package/lib/idl/drift.json +65 -7
- package/lib/math/amm.d.ts +3 -2
- package/lib/math/amm.js +61 -27
- package/lib/math/oracles.d.ts +2 -0
- package/lib/math/oracles.js +23 -1
- package/lib/math/utils.d.ts +1 -0
- package/lib/math/utils.js +5 -1
- package/lib/types.d.ts +6 -2
- package/lib/user.js +10 -6
- package/package.json +1 -1
- package/src/accounts/pollingDriftClientAccountSubscriber.ts +0 -4
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +0 -4
- package/src/adminClient.ts +28 -0
- package/src/constants/numericConstants.ts +3 -0
- package/src/dlob/DLOB.ts +152 -237
- package/src/idl/drift.json +65 -7
- package/src/math/amm.ts +126 -42
- package/src/math/oracles.ts +52 -0
- package/src/math/utils.ts +4 -0
- package/src/types.ts +6 -2
- package/src/user.ts +17 -6
- package/tests/dlob/helpers.ts +4 -2
- package/tests/dlob/test.ts +252 -0
package/src/math/amm.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
QUOTE_PRECISION,
|
|
11
11
|
MARGIN_PRECISION,
|
|
12
12
|
PRICE_DIV_PEG,
|
|
13
|
+
PERCENTAGE_PRECISION,
|
|
14
|
+
BASE_PRECISION,
|
|
13
15
|
} from '../constants/numericConstants';
|
|
14
16
|
import {
|
|
15
17
|
AMM,
|
|
@@ -19,7 +21,7 @@ import {
|
|
|
19
21
|
isVariant,
|
|
20
22
|
} from '../types';
|
|
21
23
|
import { assert } from '../assert/assert';
|
|
22
|
-
import { squareRootBN, standardizeBaseAssetAmount } from '..';
|
|
24
|
+
import { squareRootBN, clampBN, standardizeBaseAssetAmount } from '..';
|
|
23
25
|
|
|
24
26
|
import { OraclePriceData } from '../oracles/types';
|
|
25
27
|
import {
|
|
@@ -28,6 +30,8 @@ import {
|
|
|
28
30
|
calculateBudgetedPeg,
|
|
29
31
|
} from './repeg';
|
|
30
32
|
|
|
33
|
+
import { calculateLiveOracleStd } from './oracles';
|
|
34
|
+
|
|
31
35
|
export function calculatePegFromTargetPrice(
|
|
32
36
|
targetPrice: BN,
|
|
33
37
|
baseAssetReserve: BN,
|
|
@@ -63,7 +67,8 @@ export function calculateOptimalPegAndBudget(
|
|
|
63
67
|
const totalFeeLB = amm.totalExchangeFee.div(new BN(2));
|
|
64
68
|
const budget = BN.max(ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
|
|
65
69
|
if (budget.lt(prePegCost)) {
|
|
66
|
-
const
|
|
70
|
+
const halfMaxPriceSpread = new BN(amm.maxSpread)
|
|
71
|
+
.div(new BN(2))
|
|
67
72
|
.mul(targetPrice)
|
|
68
73
|
.div(BID_ASK_SPREAD_PRECISION);
|
|
69
74
|
|
|
@@ -72,8 +77,8 @@ export function calculateOptimalPegAndBudget(
|
|
|
72
77
|
let newBudget: BN;
|
|
73
78
|
const targetPriceGap = reservePriceBefore.sub(targetPrice);
|
|
74
79
|
|
|
75
|
-
if (targetPriceGap.abs().gt(
|
|
76
|
-
const markAdj = targetPriceGap.abs().sub(
|
|
80
|
+
if (targetPriceGap.abs().gt(halfMaxPriceSpread)) {
|
|
81
|
+
const markAdj = targetPriceGap.abs().sub(halfMaxPriceSpread);
|
|
77
82
|
|
|
78
83
|
if (targetPriceGap.lt(new BN(0))) {
|
|
79
84
|
newTargetPrice = reservePriceBefore.add(markAdj);
|
|
@@ -173,6 +178,8 @@ export function calculateUpdatedAMM(
|
|
|
173
178
|
|
|
174
179
|
newAmm.totalFeeMinusDistributions =
|
|
175
180
|
newAmm.totalFeeMinusDistributions.sub(prepegCost);
|
|
181
|
+
newAmm.netRevenueSinceLastFunding =
|
|
182
|
+
newAmm.netRevenueSinceLastFunding.sub(prepegCost);
|
|
176
183
|
|
|
177
184
|
return newAmm;
|
|
178
185
|
}
|
|
@@ -315,14 +322,14 @@ export function calculateMarketOpenBidAsk(
|
|
|
315
322
|
): [BN, BN] {
|
|
316
323
|
// open orders
|
|
317
324
|
let openAsks;
|
|
318
|
-
if (maxBaseAssetReserve
|
|
325
|
+
if (maxBaseAssetReserve.gt(baseAssetReserve)) {
|
|
319
326
|
openAsks = maxBaseAssetReserve.sub(baseAssetReserve).mul(new BN(-1));
|
|
320
327
|
} else {
|
|
321
328
|
openAsks = ZERO;
|
|
322
329
|
}
|
|
323
330
|
|
|
324
331
|
let openBids;
|
|
325
|
-
if (minBaseAssetReserve
|
|
332
|
+
if (minBaseAssetReserve.lt(baseAssetReserve)) {
|
|
326
333
|
openBids = baseAssetReserve.sub(minBaseAssetReserve);
|
|
327
334
|
} else {
|
|
328
335
|
openBids = ZERO;
|
|
@@ -331,12 +338,18 @@ export function calculateMarketOpenBidAsk(
|
|
|
331
338
|
}
|
|
332
339
|
|
|
333
340
|
export function calculateInventoryScale(
|
|
334
|
-
|
|
341
|
+
baseAssetAmountWithAmm: BN,
|
|
335
342
|
baseAssetReserve: BN,
|
|
336
343
|
minBaseAssetReserve: BN,
|
|
337
|
-
maxBaseAssetReserve: BN
|
|
344
|
+
maxBaseAssetReserve: BN,
|
|
345
|
+
directionalSpread: number,
|
|
346
|
+
maxSpread: number
|
|
338
347
|
): number {
|
|
339
|
-
|
|
348
|
+
if (baseAssetAmountWithAmm.eq(ZERO)) {
|
|
349
|
+
return 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
const defaultLargeBidAskFactor = BID_ASK_SPREAD_PRECISION.mul(new BN(10));
|
|
340
353
|
// inventory skew
|
|
341
354
|
const [openBids, openAsks] = calculateMarketOpenBidAsk(
|
|
342
355
|
baseAssetReserve,
|
|
@@ -348,13 +361,27 @@ export function calculateInventoryScale(
|
|
|
348
361
|
new BN(1),
|
|
349
362
|
BN.min(openBids.abs(), openAsks.abs())
|
|
350
363
|
);
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
364
|
+
|
|
365
|
+
const inventoryScaleMax =
|
|
366
|
+
BN.max(
|
|
367
|
+
defaultLargeBidAskFactor,
|
|
368
|
+
new BN(maxSpread / 2)
|
|
369
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
370
|
+
.div(new BN(Math.max(directionalSpread, 1)))
|
|
355
371
|
).toNumber() / BID_ASK_SPREAD_PRECISION.toNumber();
|
|
356
372
|
|
|
357
|
-
|
|
373
|
+
const inventoryScale =
|
|
374
|
+
baseAssetAmountWithAmm
|
|
375
|
+
.mul(BN.max(baseAssetAmountWithAmm.abs(), BASE_PRECISION))
|
|
376
|
+
.div(BASE_PRECISION)
|
|
377
|
+
.mul(defaultLargeBidAskFactor)
|
|
378
|
+
.div(minSideLiquidity)
|
|
379
|
+
.abs()
|
|
380
|
+
.toNumber() / BID_ASK_SPREAD_PRECISION.toNumber();
|
|
381
|
+
|
|
382
|
+
const inventorySpreadScale = Math.min(inventoryScaleMax, 1 + inventoryScale);
|
|
383
|
+
|
|
384
|
+
return inventorySpreadScale;
|
|
358
385
|
}
|
|
359
386
|
|
|
360
387
|
export function calculateEffectiveLeverage(
|
|
@@ -392,6 +419,47 @@ export function calculateMaxSpread(marginRatioInitial: number): number {
|
|
|
392
419
|
return maxTargetSpread;
|
|
393
420
|
}
|
|
394
421
|
|
|
422
|
+
export function calculateVolSpreadBN(
|
|
423
|
+
lastOracleConfPct: BN,
|
|
424
|
+
reservePrice: BN,
|
|
425
|
+
markStd: BN,
|
|
426
|
+
oracleStd: BN,
|
|
427
|
+
longIntensity: BN,
|
|
428
|
+
shortIntensity: BN,
|
|
429
|
+
volume24H: BN
|
|
430
|
+
): [BN, BN] {
|
|
431
|
+
const marketAvgStdPct = markStd
|
|
432
|
+
.add(oracleStd)
|
|
433
|
+
.mul(PERCENTAGE_PRECISION)
|
|
434
|
+
.div(reservePrice.mul(new BN(2)));
|
|
435
|
+
const volSpread = BN.max(lastOracleConfPct, marketAvgStdPct.div(new BN(2)));
|
|
436
|
+
|
|
437
|
+
const clampMax = PERCENTAGE_PRECISION.mul(new BN(16)).div(new BN(10));
|
|
438
|
+
const clampMin = PERCENTAGE_PRECISION.div(new BN(10));
|
|
439
|
+
|
|
440
|
+
const longVolSpreadFactor = clampBN(
|
|
441
|
+
longIntensity.mul(PERCENTAGE_PRECISION).div(BN.max(ONE, volume24H)),
|
|
442
|
+
clampMin,
|
|
443
|
+
clampMax
|
|
444
|
+
);
|
|
445
|
+
const shortVolSpreadFactor = clampBN(
|
|
446
|
+
shortIntensity.mul(PERCENTAGE_PRECISION).div(BN.max(ONE, volume24H)),
|
|
447
|
+
clampMin,
|
|
448
|
+
clampMax
|
|
449
|
+
);
|
|
450
|
+
|
|
451
|
+
const longVolSpread = BN.max(
|
|
452
|
+
lastOracleConfPct,
|
|
453
|
+
volSpread.mul(longVolSpreadFactor).div(PERCENTAGE_PRECISION)
|
|
454
|
+
);
|
|
455
|
+
const shortVolSpread = BN.max(
|
|
456
|
+
lastOracleConfPct,
|
|
457
|
+
volSpread.mul(shortVolSpreadFactor).div(PERCENTAGE_PRECISION)
|
|
458
|
+
);
|
|
459
|
+
|
|
460
|
+
return [longVolSpread, shortVolSpread];
|
|
461
|
+
}
|
|
462
|
+
|
|
395
463
|
export function calculateSpreadBN(
|
|
396
464
|
baseSpread: number,
|
|
397
465
|
lastOracleReservePriceSpreadPct: BN,
|
|
@@ -400,27 +468,42 @@ export function calculateSpreadBN(
|
|
|
400
468
|
quoteAssetReserve: BN,
|
|
401
469
|
terminalQuoteAssetReserve: BN,
|
|
402
470
|
pegMultiplier: BN,
|
|
403
|
-
|
|
471
|
+
baseAssetAmountWithAmm: BN,
|
|
404
472
|
reservePrice: BN,
|
|
405
473
|
totalFeeMinusDistributions: BN,
|
|
406
474
|
baseAssetReserve: BN,
|
|
407
475
|
minBaseAssetReserve: BN,
|
|
408
|
-
maxBaseAssetReserve: BN
|
|
476
|
+
maxBaseAssetReserve: BN,
|
|
477
|
+
markStd: BN,
|
|
478
|
+
oracleStd: BN,
|
|
479
|
+
longIntensity: BN,
|
|
480
|
+
shortIntensity: BN,
|
|
481
|
+
volume24H: BN
|
|
409
482
|
): [number, number] {
|
|
410
|
-
|
|
411
|
-
|
|
483
|
+
const [longVolSpread, shortVolSpread] = calculateVolSpreadBN(
|
|
484
|
+
lastOracleConfPct,
|
|
485
|
+
reservePrice,
|
|
486
|
+
markStd,
|
|
487
|
+
oracleStd,
|
|
488
|
+
longIntensity,
|
|
489
|
+
shortIntensity,
|
|
490
|
+
volume24H
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
let longSpread = Math.max(baseSpread / 2, longVolSpread.toNumber());
|
|
494
|
+
let shortSpread = Math.max(baseSpread / 2, shortVolSpread.toNumber());
|
|
412
495
|
|
|
413
|
-
if (lastOracleReservePriceSpreadPct.
|
|
496
|
+
if (lastOracleReservePriceSpreadPct.gt(ZERO)) {
|
|
414
497
|
shortSpread = Math.max(
|
|
415
498
|
shortSpread,
|
|
416
499
|
lastOracleReservePriceSpreadPct.abs().toNumber() +
|
|
417
|
-
|
|
500
|
+
shortVolSpread.toNumber()
|
|
418
501
|
);
|
|
419
502
|
} else if (lastOracleReservePriceSpreadPct.lt(ZERO)) {
|
|
420
503
|
longSpread = Math.max(
|
|
421
504
|
longSpread,
|
|
422
505
|
lastOracleReservePriceSpreadPct.abs().toNumber() +
|
|
423
|
-
|
|
506
|
+
longVolSpread.toNumber()
|
|
424
507
|
);
|
|
425
508
|
}
|
|
426
509
|
|
|
@@ -429,22 +512,18 @@ export function calculateSpreadBN(
|
|
|
429
512
|
lastOracleReservePriceSpreadPct.abs().toNumber()
|
|
430
513
|
);
|
|
431
514
|
|
|
432
|
-
const
|
|
433
|
-
|
|
434
|
-
const inventoryScale = calculateInventoryScale(
|
|
435
|
-
netBaseAssetAmount,
|
|
515
|
+
const inventorySpreadScale = calculateInventoryScale(
|
|
516
|
+
baseAssetAmountWithAmm,
|
|
436
517
|
baseAssetReserve,
|
|
437
518
|
minBaseAssetReserve,
|
|
438
|
-
maxBaseAssetReserve
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
MAX_BID_ASK_INVENTORY_SKEW_FACTOR,
|
|
442
|
-
1 + inventoryScale
|
|
519
|
+
maxBaseAssetReserve,
|
|
520
|
+
baseAssetAmountWithAmm.gt(ZERO) ? longSpread : shortSpread,
|
|
521
|
+
maxTargetSpread
|
|
443
522
|
);
|
|
444
523
|
|
|
445
|
-
if (
|
|
524
|
+
if (baseAssetAmountWithAmm.gt(ZERO)) {
|
|
446
525
|
longSpread *= inventorySpreadScale;
|
|
447
|
-
} else if (
|
|
526
|
+
} else if (baseAssetAmountWithAmm.lt(ZERO)) {
|
|
448
527
|
shortSpread *= inventorySpreadScale;
|
|
449
528
|
}
|
|
450
529
|
|
|
@@ -453,24 +532,22 @@ export function calculateSpreadBN(
|
|
|
453
532
|
quoteAssetReserve,
|
|
454
533
|
terminalQuoteAssetReserve,
|
|
455
534
|
pegMultiplier,
|
|
456
|
-
|
|
535
|
+
baseAssetAmountWithAmm,
|
|
457
536
|
reservePrice,
|
|
458
537
|
totalFeeMinusDistributions
|
|
459
538
|
);
|
|
460
539
|
|
|
540
|
+
const MAX_SPREAD_SCALE = 10;
|
|
461
541
|
if (totalFeeMinusDistributions.gt(ZERO)) {
|
|
462
|
-
const spreadScale = Math.min(
|
|
463
|
-
|
|
464
|
-
1 + effectiveLeverage
|
|
465
|
-
);
|
|
466
|
-
if (netBaseAssetAmount.gt(ZERO)) {
|
|
542
|
+
const spreadScale = Math.min(MAX_SPREAD_SCALE, 1 + effectiveLeverage);
|
|
543
|
+
if (baseAssetAmountWithAmm.gt(ZERO)) {
|
|
467
544
|
longSpread *= spreadScale;
|
|
468
545
|
} else {
|
|
469
546
|
shortSpread *= spreadScale;
|
|
470
547
|
}
|
|
471
548
|
} else {
|
|
472
|
-
longSpread *=
|
|
473
|
-
shortSpread *=
|
|
549
|
+
longSpread *= MAX_SPREAD_SCALE;
|
|
550
|
+
shortSpread *= MAX_SPREAD_SCALE;
|
|
474
551
|
}
|
|
475
552
|
|
|
476
553
|
const totalSpread = longSpread + shortSpread;
|
|
@@ -504,7 +581,6 @@ export function calculateSpread(
|
|
|
504
581
|
|
|
505
582
|
const targetPrice = oraclePriceData?.price || reservePrice;
|
|
506
583
|
const confInterval = oraclePriceData.confidence || ZERO;
|
|
507
|
-
|
|
508
584
|
const targetMarkSpreadPct = reservePrice
|
|
509
585
|
.sub(targetPrice)
|
|
510
586
|
.mul(BID_ASK_SPREAD_PRECISION)
|
|
@@ -514,6 +590,9 @@ export function calculateSpread(
|
|
|
514
590
|
.mul(BID_ASK_SPREAD_PRECISION)
|
|
515
591
|
.div(reservePrice);
|
|
516
592
|
|
|
593
|
+
const now = new BN(new Date().getTime() / 1000); //todo
|
|
594
|
+
const liveOracleStd = calculateLiveOracleStd(amm, oraclePriceData, now);
|
|
595
|
+
|
|
517
596
|
const [longSpread, shortSpread] = calculateSpreadBN(
|
|
518
597
|
amm.baseSpread,
|
|
519
598
|
targetMarkSpreadPct,
|
|
@@ -527,7 +606,12 @@ export function calculateSpread(
|
|
|
527
606
|
amm.totalFeeMinusDistributions,
|
|
528
607
|
amm.baseAssetReserve,
|
|
529
608
|
amm.minBaseAssetReserve,
|
|
530
|
-
amm.maxBaseAssetReserve
|
|
609
|
+
amm.maxBaseAssetReserve,
|
|
610
|
+
amm.markStd,
|
|
611
|
+
liveOracleStd,
|
|
612
|
+
amm.longIntensityVolume,
|
|
613
|
+
amm.shortIntensityVolume,
|
|
614
|
+
amm.volume24H
|
|
531
615
|
);
|
|
532
616
|
|
|
533
617
|
let spread: number;
|
package/src/math/oracles.ts
CHANGED
|
@@ -88,3 +88,55 @@ export function isOracleTooDivergent(
|
|
|
88
88
|
|
|
89
89
|
return tooDivergent;
|
|
90
90
|
}
|
|
91
|
+
|
|
92
|
+
export function calculateLiveOracleTwap(
|
|
93
|
+
amm: AMM,
|
|
94
|
+
oraclePriceData: OraclePriceData,
|
|
95
|
+
now: BN
|
|
96
|
+
): BN {
|
|
97
|
+
const sinceLastUpdate = now.sub(
|
|
98
|
+
amm.historicalOracleData.lastOraclePriceTwapTs
|
|
99
|
+
);
|
|
100
|
+
const sinceStart = BN.max(ZERO, amm.fundingPeriod.sub(sinceLastUpdate));
|
|
101
|
+
|
|
102
|
+
const clampRange = amm.historicalOracleData.lastOraclePriceTwap.div(
|
|
103
|
+
new BN(3)
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const clampedOraclePrice = BN.min(
|
|
107
|
+
amm.historicalOracleData.lastOraclePriceTwap.add(clampRange),
|
|
108
|
+
BN.max(
|
|
109
|
+
oraclePriceData.price,
|
|
110
|
+
amm.historicalOracleData.lastOraclePriceTwap.sub(clampRange)
|
|
111
|
+
)
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const newOracleTwap = amm.historicalOracleData.lastOraclePriceTwap
|
|
115
|
+
.mul(sinceStart)
|
|
116
|
+
.add(clampedOraclePrice)
|
|
117
|
+
.mul(sinceLastUpdate)
|
|
118
|
+
.div(sinceStart.add(sinceLastUpdate));
|
|
119
|
+
|
|
120
|
+
return newOracleTwap;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function calculateLiveOracleStd(
|
|
124
|
+
amm: AMM,
|
|
125
|
+
oraclePriceData: OraclePriceData,
|
|
126
|
+
now: BN
|
|
127
|
+
): BN {
|
|
128
|
+
const sinceLastUpdate = now.sub(
|
|
129
|
+
amm.historicalOracleData.lastOraclePriceTwapTs
|
|
130
|
+
);
|
|
131
|
+
const sinceStart = BN.max(ZERO, amm.fundingPeriod.sub(sinceLastUpdate));
|
|
132
|
+
|
|
133
|
+
const liveOracleTwap = calculateLiveOracleTwap(amm, oraclePriceData, now);
|
|
134
|
+
|
|
135
|
+
const priceDeltaVsTwap = oraclePriceData.price.sub(liveOracleTwap).abs();
|
|
136
|
+
|
|
137
|
+
const oracleStd = priceDeltaVsTwap.add(
|
|
138
|
+
amm.oracleStd.mul(sinceStart).div(sinceStart.add(sinceLastUpdate))
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
return oracleStd;
|
|
142
|
+
}
|
package/src/math/utils.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -519,6 +519,8 @@ export type StateAccount = {
|
|
|
519
519
|
perpFeeStructure: FeeStructure;
|
|
520
520
|
spotFeeStructure: FeeStructure;
|
|
521
521
|
lpCooldownTime: BN;
|
|
522
|
+
initialPctToLiquidate: number;
|
|
523
|
+
liquidationDuration: number;
|
|
522
524
|
};
|
|
523
525
|
|
|
524
526
|
export type PerpMarketAccount = {
|
|
@@ -745,8 +747,8 @@ export type PerpPosition = {
|
|
|
745
747
|
settledPnl: BN;
|
|
746
748
|
lpShares: BN;
|
|
747
749
|
remainderBaseAssetAmount: number;
|
|
748
|
-
|
|
749
|
-
|
|
750
|
+
lastBaseAssetAmountPerLp: BN;
|
|
751
|
+
lastQuoteAssetAmountPerLp: BN;
|
|
750
752
|
};
|
|
751
753
|
|
|
752
754
|
export type UserStatsAccount = {
|
|
@@ -790,6 +792,8 @@ export type UserAccount = {
|
|
|
790
792
|
totalWithdraws: BN;
|
|
791
793
|
totalSocialLoss: BN;
|
|
792
794
|
cumulativePerpFunding: BN;
|
|
795
|
+
liquidationMarginFreed: BN;
|
|
796
|
+
liquidationStartSlot: BN;
|
|
793
797
|
};
|
|
794
798
|
|
|
795
799
|
export type SpotPosition = {
|
package/src/user.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
SPOT_MARKET_WEIGHT_PRECISION,
|
|
26
26
|
QUOTE_SPOT_MARKET_INDEX,
|
|
27
27
|
TEN,
|
|
28
|
+
OPEN_ORDER_MARGIN_REQUIREMENT,
|
|
28
29
|
} from './constants/numericConstants';
|
|
29
30
|
import {
|
|
30
31
|
UserAccountSubscriber,
|
|
@@ -163,8 +164,8 @@ export class User {
|
|
|
163
164
|
openAsks: ZERO,
|
|
164
165
|
settledPnl: ZERO,
|
|
165
166
|
lpShares: ZERO,
|
|
166
|
-
|
|
167
|
-
|
|
167
|
+
lastBaseAssetAmountPerLp: ZERO,
|
|
168
|
+
lastQuoteAssetAmountPerLp: ZERO,
|
|
168
169
|
};
|
|
169
170
|
}
|
|
170
171
|
|
|
@@ -267,11 +268,11 @@ export class User {
|
|
|
267
268
|
const nShares = position.lpShares;
|
|
268
269
|
|
|
269
270
|
const deltaBaa = market.amm.baseAssetAmountPerLp
|
|
270
|
-
.sub(position.
|
|
271
|
+
.sub(position.lastBaseAssetAmountPerLp)
|
|
271
272
|
.mul(nShares)
|
|
272
273
|
.div(AMM_RESERVE_PRECISION);
|
|
273
274
|
const deltaQaa = market.amm.quoteAssetAmountPerLp
|
|
274
|
-
.sub(position.
|
|
275
|
+
.sub(position.lastQuoteAssetAmountPerLp)
|
|
275
276
|
.mul(nShares)
|
|
276
277
|
.div(AMM_RESERVE_PRECISION);
|
|
277
278
|
|
|
@@ -593,6 +594,10 @@ export class User {
|
|
|
593
594
|
newTotalLiabilityValue.add(weightedTokenValue);
|
|
594
595
|
}
|
|
595
596
|
|
|
597
|
+
newTotalLiabilityValue = newTotalLiabilityValue.add(
|
|
598
|
+
new BN(spotPosition.openOrders).mul(OPEN_ORDER_MARGIN_REQUIREMENT)
|
|
599
|
+
);
|
|
600
|
+
|
|
596
601
|
return newTotalLiabilityValue;
|
|
597
602
|
},
|
|
598
603
|
ZERO
|
|
@@ -893,6 +898,12 @@ export class User {
|
|
|
893
898
|
baseAssetValue = baseAssetValue
|
|
894
899
|
.mul(marginRatio)
|
|
895
900
|
.div(MARGIN_PRECISION);
|
|
901
|
+
|
|
902
|
+
if (includeOpenOrders) {
|
|
903
|
+
baseAssetValue = baseAssetValue.add(
|
|
904
|
+
new BN(perpPosition.openOrders).mul(OPEN_ORDER_MARGIN_REQUIREMENT)
|
|
905
|
+
);
|
|
906
|
+
}
|
|
896
907
|
}
|
|
897
908
|
|
|
898
909
|
return totalPerpValue.add(baseAssetValue);
|
|
@@ -1251,8 +1262,8 @@ export class User {
|
|
|
1251
1262
|
openAsks: new BN(0),
|
|
1252
1263
|
settledPnl: ZERO,
|
|
1253
1264
|
lpShares: ZERO,
|
|
1254
|
-
|
|
1255
|
-
|
|
1265
|
+
lastBaseAssetAmountPerLp: ZERO,
|
|
1266
|
+
lastQuoteAssetAmountPerLp: ZERO,
|
|
1256
1267
|
};
|
|
1257
1268
|
|
|
1258
1269
|
if (proposedBaseAssetAmount.eq(ZERO)) return new BN(-1);
|
package/tests/dlob/helpers.ts
CHANGED
|
@@ -37,8 +37,8 @@ export const mockPerpPosition: PerpPosition = {
|
|
|
37
37
|
settledPnl: new BN(0),
|
|
38
38
|
lpShares: new BN(0),
|
|
39
39
|
remainderBaseAssetAmount: 0,
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
lastBaseAssetAmountPerLp: new BN(0),
|
|
41
|
+
lastQuoteAssetAmountPerLp: new BN(0),
|
|
42
42
|
};
|
|
43
43
|
|
|
44
44
|
export const mockAMM: AMM = {
|
|
@@ -486,6 +486,8 @@ export const mockStateAccount: StateAccount = {
|
|
|
486
486
|
numberOfSpotMarkets: 0,
|
|
487
487
|
numberOfSubAccounts: new BN(0),
|
|
488
488
|
numberOfAuthorities: new BN(0),
|
|
489
|
+
initialPctToLiquidate: 0,
|
|
490
|
+
liquidationDuration: 0,
|
|
489
491
|
oracleGuardRails: {
|
|
490
492
|
priceDivergence: {
|
|
491
493
|
markOracleDivergenceNumerator: new BN(0),
|