@drift-labs/sdk 2.52.0-beta.1 → 2.52.0-beta.10
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/examples/phoenix.ts +11 -4
- package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -1
- package/lib/accounts/webSocketAccountSubscriber.js +7 -4
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +1 -1
- package/lib/accounts/webSocketProgramAccountSubscriber.js +7 -4
- package/lib/dlob/orderBookLevels.d.ts +22 -0
- package/lib/dlob/orderBookLevels.js +115 -1
- package/lib/driftClient.d.ts +3 -1
- package/lib/driftClient.js +30 -8
- package/lib/events/webSocketLogProvider.js +3 -3
- package/lib/factory/bigNum.d.ts +1 -1
- package/lib/factory/bigNum.js +5 -2
- package/lib/idl/drift.json +52 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.js +1 -1
- package/lib/math/amm.d.ts +5 -1
- package/lib/math/amm.js +62 -13
- package/lib/math/state.js +3 -0
- package/lib/orderSubscriber/OrderSubscriber.js +1 -0
- package/lib/orderSubscriber/WebsocketSubscription.d.ts +4 -1
- package/lib/orderSubscriber/WebsocketSubscription.js +25 -1
- package/lib/orderSubscriber/types.d.ts +1 -0
- package/lib/phoenix/phoenixSubscriber.js +10 -6
- package/lib/priorityFee/averageOverSlotsStrategy.d.ts +12 -0
- package/lib/priorityFee/averageOverSlotsStrategy.js +28 -0
- package/lib/priorityFee/averageStrategy.d.ts +7 -0
- package/lib/priorityFee/averageStrategy.js +11 -0
- package/lib/priorityFee/ewmaStrategy.d.ts +13 -0
- package/lib/priorityFee/ewmaStrategy.js +33 -0
- package/lib/priorityFee/index.d.ts +7 -0
- package/lib/priorityFee/index.js +23 -0
- package/lib/priorityFee/maxOverSlotsStrategy.d.ts +12 -0
- package/lib/priorityFee/maxOverSlotsStrategy.js +29 -0
- package/lib/priorityFee/maxStrategy.d.ts +7 -0
- package/lib/priorityFee/maxStrategy.js +9 -0
- package/lib/priorityFee/priorityFeeSubscriber.d.ts +15 -4
- package/lib/priorityFee/priorityFeeSubscriber.js +38 -14
- package/lib/priorityFee/types.d.ts +6 -0
- package/lib/priorityFee/types.js +2 -0
- package/lib/slot/SlotSubscriber.d.ts +11 -3
- package/lib/slot/SlotSubscriber.js +40 -4
- package/lib/types.d.ts +4 -1
- package/lib/types.js +1 -0
- package/lib/user.d.ts +1 -1
- package/lib/user.js +15 -8
- package/lib/userMap/userMap.d.ts +3 -0
- package/lib/userMap/userMap.js +9 -0
- package/package.json +1 -1
- package/src/accounts/webSocketAccountSubscriber.ts +7 -4
- package/src/accounts/webSocketProgramAccountSubscriber.ts +7 -4
- package/src/dlob/orderBookLevels.ts +136 -0
- package/src/driftClient.ts +46 -8
- package/src/events/webSocketLogProvider.ts +3 -3
- package/src/factory/bigNum.ts +11 -2
- package/src/idl/drift.json +52 -1
- package/src/index.ts +1 -1
- package/src/math/amm.ts +159 -25
- package/src/math/state.ts +3 -0
- package/src/orderSubscriber/OrderSubscriber.ts +1 -0
- package/src/orderSubscriber/WebsocketSubscription.ts +28 -0
- package/src/orderSubscriber/types.ts +1 -0
- package/src/phoenix/phoenixSubscriber.ts +14 -8
- package/src/priorityFee/averageOverSlotsStrategy.ts +30 -0
- package/src/priorityFee/averageStrategy.ts +11 -0
- package/src/priorityFee/ewmaStrategy.ts +40 -0
- package/src/priorityFee/index.ts +7 -0
- package/src/priorityFee/maxOverSlotsStrategy.ts +31 -0
- package/src/priorityFee/maxStrategy.ts +7 -0
- package/src/priorityFee/priorityFeeSubscriber.ts +46 -19
- package/src/priorityFee/types.ts +5 -0
- package/src/slot/SlotSubscriber.ts +52 -5
- package/src/types.ts +2 -1
- package/src/user.ts +25 -8
- package/src/userMap/userMap.ts +12 -0
- package/tests/amm/test.ts +219 -11
- package/tests/bn/test.ts +27 -0
- package/tests/dlob/helpers.ts +1 -1
- package/tests/dlob/test.ts +372 -2
- package/tests/tx/priorityFeeStrategy.ts +97 -0
- package/tests/user/helpers.ts +1 -0
|
@@ -3,7 +3,9 @@ import { EventEmitter } from 'events';
|
|
|
3
3
|
import StrictEventEmitter from 'strict-event-emitter-types/types/src';
|
|
4
4
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
6
|
-
type SlotSubscriberConfig = {
|
|
6
|
+
type SlotSubscriberConfig = {
|
|
7
|
+
resubTimeoutMs?: number;
|
|
8
|
+
}; // for future customization
|
|
7
9
|
|
|
8
10
|
export interface SlotSubscriberEvents {
|
|
9
11
|
newSlot: (newSlot: number) => void;
|
|
@@ -14,15 +16,22 @@ export class SlotSubscriber {
|
|
|
14
16
|
subscriptionId: number;
|
|
15
17
|
eventEmitter: StrictEventEmitter<EventEmitter, SlotSubscriberEvents>;
|
|
16
18
|
|
|
19
|
+
// Reconnection
|
|
20
|
+
timeoutId?: NodeJS.Timeout;
|
|
21
|
+
resubTimeoutMs?: number;
|
|
22
|
+
isUnsubscribing = false;
|
|
23
|
+
receivingData = false;
|
|
24
|
+
|
|
17
25
|
public constructor(
|
|
18
26
|
private connection: Connection,
|
|
19
|
-
|
|
27
|
+
config?: SlotSubscriberConfig
|
|
20
28
|
) {
|
|
21
29
|
this.eventEmitter = new EventEmitter();
|
|
30
|
+
this.resubTimeoutMs = config?.resubTimeoutMs;
|
|
22
31
|
}
|
|
23
32
|
|
|
24
33
|
public async subscribe(): Promise<void> {
|
|
25
|
-
if (this.subscriptionId) {
|
|
34
|
+
if (this.subscriptionId != null) {
|
|
26
35
|
return;
|
|
27
36
|
}
|
|
28
37
|
|
|
@@ -30,19 +39,57 @@ export class SlotSubscriber {
|
|
|
30
39
|
|
|
31
40
|
this.subscriptionId = this.connection.onSlotChange((slotInfo) => {
|
|
32
41
|
if (!this.currentSlot || this.currentSlot < slotInfo.slot) {
|
|
42
|
+
if (this.resubTimeoutMs && !this.isUnsubscribing) {
|
|
43
|
+
this.receivingData = true;
|
|
44
|
+
clearTimeout(this.timeoutId);
|
|
45
|
+
this.setTimeout();
|
|
46
|
+
}
|
|
33
47
|
this.currentSlot = slotInfo.slot;
|
|
34
48
|
this.eventEmitter.emit('newSlot', slotInfo.slot);
|
|
35
49
|
}
|
|
36
50
|
});
|
|
51
|
+
|
|
52
|
+
if (this.resubTimeoutMs) {
|
|
53
|
+
this.setTimeout();
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private setTimeout(): void {
|
|
58
|
+
this.timeoutId = setTimeout(async () => {
|
|
59
|
+
if (this.isUnsubscribing) {
|
|
60
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.receivingData) {
|
|
65
|
+
console.log(
|
|
66
|
+
`No new slot in ${this.resubTimeoutMs}ms, slot subscriber resubscribing`
|
|
67
|
+
);
|
|
68
|
+
await this.unsubscribe(true);
|
|
69
|
+
this.receivingData = false;
|
|
70
|
+
await this.subscribe();
|
|
71
|
+
}
|
|
72
|
+
}, this.resubTimeoutMs);
|
|
37
73
|
}
|
|
38
74
|
|
|
39
75
|
public getSlot(): number {
|
|
40
76
|
return this.currentSlot;
|
|
41
77
|
}
|
|
42
78
|
|
|
43
|
-
public async unsubscribe(): Promise<void> {
|
|
44
|
-
if (
|
|
79
|
+
public async unsubscribe(onResub = false): Promise<void> {
|
|
80
|
+
if (!onResub) {
|
|
81
|
+
this.resubTimeoutMs = undefined;
|
|
82
|
+
}
|
|
83
|
+
this.isUnsubscribing = true;
|
|
84
|
+
clearTimeout(this.timeoutId);
|
|
85
|
+
this.timeoutId = undefined;
|
|
86
|
+
|
|
87
|
+
if (this.subscriptionId != null) {
|
|
45
88
|
await this.connection.removeSlotChangeListener(this.subscriptionId);
|
|
89
|
+
this.subscriptionId = undefined;
|
|
90
|
+
this.isUnsubscribing = false;
|
|
91
|
+
} else {
|
|
92
|
+
this.isUnsubscribing = false;
|
|
46
93
|
}
|
|
47
94
|
}
|
|
48
95
|
}
|
package/src/types.ts
CHANGED
|
@@ -182,6 +182,7 @@ export class SpotFulfillmentStatus {
|
|
|
182
182
|
export class DepositExplanation {
|
|
183
183
|
static readonly NONE = { none: {} };
|
|
184
184
|
static readonly TRANSFER = { transfer: {} };
|
|
185
|
+
static readonly BORROW = { borrow: {} };
|
|
185
186
|
}
|
|
186
187
|
|
|
187
188
|
export class SettlePnlExplanation {
|
|
@@ -710,7 +711,7 @@ export type AMM = {
|
|
|
710
711
|
pegMultiplier: BN;
|
|
711
712
|
cumulativeFundingRateLong: BN;
|
|
712
713
|
cumulativeFundingRateShort: BN;
|
|
713
|
-
|
|
714
|
+
last24HAvgFundingRate: BN;
|
|
714
715
|
lastFundingRateShort: BN;
|
|
715
716
|
lastFundingRateLong: BN;
|
|
716
717
|
|
package/src/user.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
OPEN_ORDER_MARGIN_REQUIREMENT,
|
|
28
28
|
PRICE_PRECISION,
|
|
29
29
|
QUOTE_PRECISION,
|
|
30
|
+
QUOTE_PRECISION_EXP,
|
|
30
31
|
QUOTE_SPOT_MARKET_INDEX,
|
|
31
32
|
SPOT_MARKET_WEIGHT_PRECISION,
|
|
32
33
|
TEN,
|
|
@@ -40,6 +41,7 @@ import {
|
|
|
40
41
|
UserAccountSubscriber,
|
|
41
42
|
} from './accounts/types';
|
|
42
43
|
import {
|
|
44
|
+
BigNum,
|
|
43
45
|
BN,
|
|
44
46
|
calculateBaseAssetValue,
|
|
45
47
|
calculateMarketMarginRatio,
|
|
@@ -1399,8 +1401,12 @@ export class User {
|
|
|
1399
1401
|
includeOpenOrders = false
|
|
1400
1402
|
): BN {
|
|
1401
1403
|
const userPosition =
|
|
1402
|
-
this.getPerpPositionWithLPSettle(
|
|
1403
|
-
|
|
1404
|
+
this.getPerpPositionWithLPSettle(
|
|
1405
|
+
marketIndex,
|
|
1406
|
+
undefined,
|
|
1407
|
+
false,
|
|
1408
|
+
true
|
|
1409
|
+
)[0] || this.getEmptyPosition(marketIndex);
|
|
1404
1410
|
const market = this.driftClient.getPerpMarketAccount(
|
|
1405
1411
|
userPosition.marketIndex
|
|
1406
1412
|
);
|
|
@@ -3013,7 +3019,7 @@ export class User {
|
|
|
3013
3019
|
let makerFee =
|
|
3014
3020
|
feeTier.makerRebateNumerator / feeTier.makerRebateDenominator;
|
|
3015
3021
|
|
|
3016
|
-
if (marketIndex && isVariant(marketType, 'perp')) {
|
|
3022
|
+
if (marketIndex !== undefined && isVariant(marketType, 'perp')) {
|
|
3017
3023
|
const marketAccount = this.driftClient.getPerpMarketAccount(marketIndex);
|
|
3018
3024
|
takerFee += (takerFee * marketAccount.feeAdjustment) / 100;
|
|
3019
3025
|
makerFee += (makerFee * marketAccount.feeAdjustment) / 100;
|
|
@@ -3030,11 +3036,22 @@ export class User {
|
|
|
3030
3036
|
* @param quoteAmount
|
|
3031
3037
|
* @returns feeForQuote : Precision QUOTE_PRECISION
|
|
3032
3038
|
*/
|
|
3033
|
-
public calculateFeeForQuoteAmount(quoteAmount: BN): BN {
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3039
|
+
public calculateFeeForQuoteAmount(quoteAmount: BN, marketIndex?: number): BN {
|
|
3040
|
+
if (marketIndex !== undefined) {
|
|
3041
|
+
const takerFeeMultiplier = this.getMarketFees(
|
|
3042
|
+
MarketType.PERP,
|
|
3043
|
+
marketIndex
|
|
3044
|
+
).takerFee;
|
|
3045
|
+
const feeAmountNum =
|
|
3046
|
+
BigNum.from(quoteAmount, QUOTE_PRECISION_EXP).toNum() *
|
|
3047
|
+
takerFeeMultiplier;
|
|
3048
|
+
return BigNum.fromPrint(feeAmountNum.toString(), QUOTE_PRECISION_EXP).val;
|
|
3049
|
+
} else {
|
|
3050
|
+
const feeTier = this.getUserFeeTier(MarketType.PERP);
|
|
3051
|
+
return quoteAmount
|
|
3052
|
+
.mul(new BN(feeTier.feeNumerator))
|
|
3053
|
+
.div(new BN(feeTier.feeDenominator));
|
|
3054
|
+
}
|
|
3038
3055
|
}
|
|
3039
3056
|
|
|
3040
3057
|
/**
|
package/src/userMap/userMap.ts
CHANGED
|
@@ -60,6 +60,7 @@ export class UserMap implements UserMapInterface {
|
|
|
60
60
|
}
|
|
61
61
|
};
|
|
62
62
|
private decode;
|
|
63
|
+
private mostRecentSlot = 0;
|
|
63
64
|
|
|
64
65
|
private syncPromise?: Promise<void>;
|
|
65
66
|
private syncPromiseResolver: () => void;
|
|
@@ -312,6 +313,8 @@ export class UserMap implements UserMapInterface {
|
|
|
312
313
|
|
|
313
314
|
const slot = rpcResponseAndContext.context.slot;
|
|
314
315
|
|
|
316
|
+
this.updateLatestSlot(slot);
|
|
317
|
+
|
|
315
318
|
const programAccountBufferMap = new Map<string, Buffer>();
|
|
316
319
|
for (const programAccount of rpcResponseAndContext.value) {
|
|
317
320
|
programAccountBufferMap.set(
|
|
@@ -373,6 +376,7 @@ export class UserMap implements UserMapInterface {
|
|
|
373
376
|
userAccount: UserAccount,
|
|
374
377
|
slot: number
|
|
375
378
|
) {
|
|
379
|
+
this.updateLatestSlot(slot);
|
|
376
380
|
if (!this.userMap.has(key)) {
|
|
377
381
|
this.addPubkey(new PublicKey(key), userAccount, slot);
|
|
378
382
|
} else {
|
|
@@ -380,4 +384,12 @@ export class UserMap implements UserMapInterface {
|
|
|
380
384
|
user.accountSubscriber.updateData(userAccount, slot);
|
|
381
385
|
}
|
|
382
386
|
}
|
|
387
|
+
|
|
388
|
+
updateLatestSlot(slot: number): void {
|
|
389
|
+
this.mostRecentSlot = Math.max(slot, this.mostRecentSlot);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
public getSlot(): number {
|
|
393
|
+
return this.mostRecentSlot;
|
|
394
|
+
}
|
|
383
395
|
}
|
package/tests/amm/test.ts
CHANGED
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
PRICE_PRECISION,
|
|
5
5
|
AMM_RESERVE_PRECISION,
|
|
6
6
|
QUOTE_PRECISION,
|
|
7
|
+
PERCENTAGE_PRECISION,
|
|
8
|
+
calculateSpread,
|
|
7
9
|
calculateSpreadBN,
|
|
8
10
|
ZERO,
|
|
9
11
|
ONE,
|
|
@@ -19,6 +21,12 @@ import {
|
|
|
19
21
|
L2Level,
|
|
20
22
|
calculateUpdatedAMM,
|
|
21
23
|
calculateMarketOpenBidAsk,
|
|
24
|
+
calculateSpreadReserves,
|
|
25
|
+
calculatePrice,
|
|
26
|
+
BID_ASK_SPREAD_PRECISION,
|
|
27
|
+
squareRootBN,
|
|
28
|
+
calculateReferencePriceOffset,
|
|
29
|
+
calculateInventoryLiquidityRatio,
|
|
22
30
|
} from '../../src';
|
|
23
31
|
import { mockPerpMarkets } from '../dlob/helpers';
|
|
24
32
|
|
|
@@ -293,7 +301,7 @@ describe('AMM Tests', () => {
|
|
|
293
301
|
volume24H,
|
|
294
302
|
true
|
|
295
303
|
);
|
|
296
|
-
console.log(terms1);
|
|
304
|
+
// console.log(terms1);
|
|
297
305
|
|
|
298
306
|
console.log('long/short spread:', l1, s1);
|
|
299
307
|
assert(l1 == 14864);
|
|
@@ -326,11 +334,77 @@ describe('AMM Tests', () => {
|
|
|
326
334
|
true
|
|
327
335
|
);
|
|
328
336
|
|
|
329
|
-
console.log(terms2);
|
|
337
|
+
// console.log(terms2);
|
|
330
338
|
assert(terms2.effectiveLeverageCapped >= 1.0002);
|
|
331
339
|
assert(terms2.inventorySpreadScale == 1.73492);
|
|
332
340
|
assert(terms2.longSpread == 4262);
|
|
333
341
|
assert(terms2.shortSpread == 43238);
|
|
342
|
+
|
|
343
|
+
// add spread offset
|
|
344
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
345
|
+
// @ts-ignore
|
|
346
|
+
const terms3: AMMSpreadTerms = calculateSpreadBN(
|
|
347
|
+
300,
|
|
348
|
+
new BN(0),
|
|
349
|
+
new BN(484),
|
|
350
|
+
47500,
|
|
351
|
+
new BN(923807816209694),
|
|
352
|
+
new BN(925117623772584),
|
|
353
|
+
new BN(13731157),
|
|
354
|
+
new BN(-1314027016625),
|
|
355
|
+
new BN(13667686),
|
|
356
|
+
new BN(115876379475),
|
|
357
|
+
new BN(91316628),
|
|
358
|
+
new BN(928097825691666),
|
|
359
|
+
new BN(907979542352912),
|
|
360
|
+
new BN(945977491145601),
|
|
361
|
+
new BN(161188),
|
|
362
|
+
new BN(1459632439),
|
|
363
|
+
new BN(12358265776),
|
|
364
|
+
new BN(72230366233),
|
|
365
|
+
new BN(432067603632),
|
|
366
|
+
true
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
console.log(terms3);
|
|
370
|
+
assert(terms3.effectiveLeverageCapped >= 1.0002);
|
|
371
|
+
assert(terms3.inventorySpreadScale == 1.73492);
|
|
372
|
+
assert(terms3.longSpread == 4262);
|
|
373
|
+
assert(terms3.shortSpread == 43238);
|
|
374
|
+
assert(terms3.longSpread + terms3.shortSpread == 47500);
|
|
375
|
+
|
|
376
|
+
// add spread offset
|
|
377
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
378
|
+
// @ts-ignore
|
|
379
|
+
const terms4: AMMSpreadTerms = calculateSpreadBN(
|
|
380
|
+
300,
|
|
381
|
+
new BN(0),
|
|
382
|
+
new BN(484),
|
|
383
|
+
47500,
|
|
384
|
+
new BN(923807816209694),
|
|
385
|
+
new BN(925117623772584),
|
|
386
|
+
new BN(13731157),
|
|
387
|
+
new BN(-1314027016625),
|
|
388
|
+
new BN(13667686),
|
|
389
|
+
new BN(115876379475),
|
|
390
|
+
new BN(91316628),
|
|
391
|
+
new BN(928097825691666),
|
|
392
|
+
new BN(907979542352912),
|
|
393
|
+
new BN(945977491145601),
|
|
394
|
+
new BN(161188),
|
|
395
|
+
new BN(1459632439),
|
|
396
|
+
new BN(12358265776),
|
|
397
|
+
new BN(72230366233),
|
|
398
|
+
new BN(432067603632),
|
|
399
|
+
true
|
|
400
|
+
);
|
|
401
|
+
|
|
402
|
+
console.log(terms4);
|
|
403
|
+
assert(terms4.effectiveLeverageCapped >= 1.0002);
|
|
404
|
+
assert(terms4.inventorySpreadScale == 1.73492);
|
|
405
|
+
assert(terms4.longSpread == 4262);
|
|
406
|
+
assert(terms4.shortSpread == 43238);
|
|
407
|
+
assert(terms4.longSpread + terms4.shortSpread == 47500);
|
|
334
408
|
});
|
|
335
409
|
|
|
336
410
|
it('Corner Case Spreads', () => {
|
|
@@ -361,16 +435,150 @@ describe('AMM Tests', () => {
|
|
|
361
435
|
|
|
362
436
|
console.log(terms2);
|
|
363
437
|
assert(terms2.effectiveLeverageCapped <= 1.000001);
|
|
364
|
-
assert(
|
|
365
|
-
|
|
366
|
-
|
|
438
|
+
assert(terms2.inventorySpreadScale == 1.0306);
|
|
439
|
+
assert(terms2.longSpread == 515);
|
|
440
|
+
assert(terms2.shortSpread == 5668);
|
|
441
|
+
});
|
|
442
|
+
|
|
443
|
+
it('Spread Reserves (with offset)', () => {
|
|
444
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
445
|
+
const mockMarket1 = myMockPerpMarkets[0];
|
|
446
|
+
const mockAmm = mockMarket1.amm;
|
|
447
|
+
const now = new BN(new Date().getTime() / 1000); //todo
|
|
448
|
+
|
|
449
|
+
const oraclePriceData = {
|
|
450
|
+
price: new BN(13.553 * PRICE_PRECISION.toNumber()),
|
|
451
|
+
slot: new BN(68 + 1),
|
|
452
|
+
confidence: new BN(1),
|
|
453
|
+
hasSufficientNumberOfDataPoints: true,
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
const reserves = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
457
|
+
assert(reserves[0].baseAssetReserve.eq(new BN('1000000000')));
|
|
458
|
+
assert(reserves[0].quoteAssetReserve.eq(new BN('12000000000')));
|
|
459
|
+
assert(reserves[1].baseAssetReserve.eq(new BN('1000000000')));
|
|
460
|
+
assert(reserves[1].quoteAssetReserve.eq(new BN('12000000000')));
|
|
461
|
+
|
|
462
|
+
mockAmm.baseAssetReserve = new BN(1000000000);
|
|
463
|
+
mockAmm.quoteAssetReserve = new BN(1000000000);
|
|
464
|
+
mockAmm.sqrtK = new BN(1000000000);
|
|
465
|
+
|
|
466
|
+
mockAmm.baseAssetAmountWithAmm = new BN(0);
|
|
467
|
+
mockAmm.pegMultiplier = new BN(13.553 * PEG_PRECISION.toNumber());
|
|
468
|
+
mockAmm.ammJitIntensity = 100;
|
|
469
|
+
mockAmm.curveUpdateIntensity = 200;
|
|
470
|
+
mockAmm.baseSpread = 2500;
|
|
471
|
+
mockAmm.maxSpread = 25000;
|
|
472
|
+
|
|
473
|
+
mockAmm.last24HAvgFundingRate = new BN(7590328523);
|
|
474
|
+
|
|
475
|
+
mockAmm.lastMarkPriceTwap = new BN(
|
|
476
|
+
(oraclePriceData.price.toNumber() / 1e6 - 0.01) * 1e6
|
|
477
|
+
);
|
|
478
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap = new BN(
|
|
479
|
+
(oraclePriceData.price.toNumber() / 1e6 + 0.015) * 1e6
|
|
367
480
|
);
|
|
368
|
-
|
|
369
|
-
|
|
481
|
+
|
|
482
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap5Min = new BN(
|
|
483
|
+
(oraclePriceData.price.toNumber() / 1e6 + 0.005) * 1e6
|
|
484
|
+
);
|
|
485
|
+
mockAmm.lastMarkPriceTwap5Min = new BN(
|
|
486
|
+
(oraclePriceData.price.toNumber() / 1e6 - 0.005) * 1e6
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
console.log('starting rr:');
|
|
490
|
+
let reservePrice = undefined;
|
|
491
|
+
if (!reservePrice) {
|
|
492
|
+
reservePrice = calculatePrice(
|
|
493
|
+
mockAmm.baseAssetReserve,
|
|
494
|
+
mockAmm.quoteAssetReserve,
|
|
495
|
+
mockAmm.pegMultiplier
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
const targetPrice = oraclePriceData?.price || reservePrice;
|
|
500
|
+
const confInterval = oraclePriceData.confidence || ZERO;
|
|
501
|
+
const targetMarkSpreadPct = reservePrice
|
|
502
|
+
.sub(targetPrice)
|
|
503
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
504
|
+
.div(reservePrice);
|
|
505
|
+
|
|
506
|
+
const confIntervalPct = confInterval
|
|
507
|
+
.mul(BID_ASK_SPREAD_PRECISION)
|
|
508
|
+
.div(reservePrice);
|
|
509
|
+
|
|
510
|
+
// now = now || new BN(new Date().getTime() / 1000); //todo
|
|
511
|
+
const liveOracleStd = calculateLiveOracleStd(mockAmm, oraclePriceData, now);
|
|
512
|
+
console.log('reservePrice:', reservePrice.toString());
|
|
513
|
+
console.log('targetMarkSpreadPct:', targetMarkSpreadPct.toString());
|
|
514
|
+
console.log('confIntervalPct:', confIntervalPct.toString());
|
|
515
|
+
|
|
516
|
+
console.log('liveOracleStd:', liveOracleStd.toString());
|
|
517
|
+
|
|
518
|
+
const tt = calculateSpread(mockAmm, oraclePriceData, now);
|
|
519
|
+
console.log(tt);
|
|
520
|
+
|
|
521
|
+
console.log('amm.baseAssetReserve:', mockAmm.baseAssetReserve.toString());
|
|
522
|
+
assert(mockAmm.baseAssetReserve.eq(new BN('1000000000')));
|
|
523
|
+
const reserves2 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
524
|
+
console.log(reserves2[1].baseAssetReserve.toString());
|
|
525
|
+
console.log(reserves2[1].quoteAssetReserve.toString());
|
|
526
|
+
|
|
527
|
+
assert(reserves2[0].baseAssetReserve.eq(new BN('1006711408')));
|
|
528
|
+
assert(reserves2[0].quoteAssetReserve.eq(new BN('993333334')));
|
|
529
|
+
assert(reserves2[1].baseAssetReserve.eq(new BN('993377484')));
|
|
530
|
+
assert(reserves2[1].quoteAssetReserve.eq(new BN('1006666666')));
|
|
531
|
+
|
|
532
|
+
// create imbalance for reference price offset
|
|
533
|
+
mockAmm.baseAssetReserve = new BN(1000000000 * 1.1);
|
|
534
|
+
mockAmm.quoteAssetReserve = new BN(1000000000 / 1.1);
|
|
535
|
+
mockAmm.sqrtK = squareRootBN(
|
|
536
|
+
mockAmm.baseAssetReserve.mul(mockAmm.quoteAssetReserve)
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
mockAmm.baseAssetAmountWithAmm = new BN(-1000000000 * 0.1);
|
|
540
|
+
|
|
541
|
+
const maxOffset = Math.max(
|
|
542
|
+
mockAmm.maxSpread / 5,
|
|
543
|
+
PERCENTAGE_PRECISION.toNumber() / 1000
|
|
544
|
+
);
|
|
545
|
+
const liquidityFraction = calculateInventoryLiquidityRatio(
|
|
546
|
+
mockAmm.baseAssetAmountWithAmm,
|
|
547
|
+
mockAmm.baseAssetReserve,
|
|
548
|
+
mockAmm.minBaseAssetReserve,
|
|
549
|
+
mockAmm.maxBaseAssetReserve
|
|
550
|
+
);
|
|
551
|
+
console.log('liquidityFraction:', liquidityFraction.toString());
|
|
552
|
+
assert(liquidityFraction.eq(new BN(1000000))); // full
|
|
553
|
+
|
|
554
|
+
const referencePriceOffset = calculateReferencePriceOffset(
|
|
555
|
+
reservePrice,
|
|
556
|
+
mockAmm.last24HAvgFundingRate,
|
|
557
|
+
liquidityFraction,
|
|
558
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap5Min,
|
|
559
|
+
mockAmm.lastMarkPriceTwap5Min,
|
|
560
|
+
mockAmm.historicalOracleData.lastOraclePriceTwap,
|
|
561
|
+
mockAmm.lastMarkPriceTwap,
|
|
562
|
+
maxOffset
|
|
563
|
+
);
|
|
564
|
+
console.log('referencePriceOffset:', referencePriceOffset.toString());
|
|
565
|
+
assert(referencePriceOffset.eq(new BN(5000)));
|
|
566
|
+
assert(referencePriceOffset.eq(new BN(maxOffset)));
|
|
567
|
+
|
|
568
|
+
const reserves3 = calculateSpreadReserves(mockAmm, oraclePriceData, now);
|
|
569
|
+
console.log(reserves3[1].baseAssetReserve.toString());
|
|
570
|
+
console.log(reserves3[1].quoteAssetReserve.toString());
|
|
571
|
+
|
|
572
|
+
assert(reserves3[0].baseAssetReserve.eq(new BN('1164705879')));
|
|
573
|
+
assert(reserves3[0].quoteAssetReserve.eq(new BN('858585859')));
|
|
574
|
+
assert(reserves3[1].baseAssetReserve.eq(new BN('1042105261')));
|
|
575
|
+
assert(reserves3[1].quoteAssetReserve.eq(new BN('959595959')));
|
|
370
576
|
});
|
|
371
577
|
|
|
372
578
|
it('live update functions', () => {
|
|
373
|
-
const
|
|
579
|
+
const myMockPerpMarkets = _.cloneDeep(mockPerpMarkets);
|
|
580
|
+
const mockMarket1 = myMockPerpMarkets[0];
|
|
581
|
+
const mockAmm = mockMarket1.amm;
|
|
374
582
|
const now = new BN(new Date().getTime() / 1000); //todo
|
|
375
583
|
|
|
376
584
|
const oraclePriceData = {
|
|
@@ -469,8 +677,8 @@ describe('AMM Tests', () => {
|
|
|
469
677
|
|
|
470
678
|
assert(markTwapLive.eq(new BN('1949826')));
|
|
471
679
|
assert(oracleTwapLive.eq(new BN('1942510')));
|
|
472
|
-
assert(est1.eq(new BN('
|
|
473
|
-
assert(est2.eq(new BN('
|
|
680
|
+
assert(est1.eq(new BN('16525')));
|
|
681
|
+
assert(est2.eq(new BN('16525')));
|
|
474
682
|
});
|
|
475
683
|
|
|
476
684
|
it('predicted funding rate mock2', async () => {
|
|
@@ -559,7 +767,7 @@ describe('AMM Tests', () => {
|
|
|
559
767
|
assert(markTwapLive.eq(new BN('1222131')));
|
|
560
768
|
assert(oracleTwapLive.eq(new BN('1222586')));
|
|
561
769
|
assert(est1.eq(est2));
|
|
562
|
-
assert(est2.eq(new BN('-
|
|
770
|
+
assert(est2.eq(new BN('-719')));
|
|
563
771
|
});
|
|
564
772
|
|
|
565
773
|
it('orderbook L2 gen (no topOfBookQuoteAmounts, 10 numOrders, low liquidity)', async () => {
|
package/tests/bn/test.ts
CHANGED
|
@@ -147,6 +147,33 @@ describe('BigNum Tests', () => {
|
|
|
147
147
|
'-1.0000000000000'
|
|
148
148
|
);
|
|
149
149
|
expect(BigNum.from('-100', 6).print()).to.equal('-0.000100');
|
|
150
|
+
|
|
151
|
+
// Case 7: really large numbers + switching between scientific/financial
|
|
152
|
+
expect(BigNum.fromPrint('123000000000').toMillified(3)).to.equal('123B');
|
|
153
|
+
expect(
|
|
154
|
+
BigNum.fromPrint('123000000000').toMillified(3, undefined, 'scientific')
|
|
155
|
+
).to.equal('123G'); // (G = Giga)
|
|
156
|
+
expect(BigNum.fromPrint('123000000000000').toMillified(3)).to.equal('123T');
|
|
157
|
+
expect(
|
|
158
|
+
BigNum.fromPrint('123000000000000').toMillified(
|
|
159
|
+
3,
|
|
160
|
+
undefined,
|
|
161
|
+
'scientific'
|
|
162
|
+
)
|
|
163
|
+
).to.equal('123T'); // (T = Tera)
|
|
164
|
+
expect(BigNum.fromPrint('123000000000000000').toMillified(3)).to.equal(
|
|
165
|
+
'123Q'
|
|
166
|
+
);
|
|
167
|
+
expect(
|
|
168
|
+
BigNum.fromPrint('123000000000000000').toMillified(
|
|
169
|
+
3,
|
|
170
|
+
undefined,
|
|
171
|
+
'scientific'
|
|
172
|
+
)
|
|
173
|
+
).to.equal('123P'); // (P = Peta)
|
|
174
|
+
|
|
175
|
+
// TODO : Need to make the appropriate changes for the next line to pass
|
|
176
|
+
// expect(BigNum.fromPrint('123000000000000000000').toMillified(3)).to.equal('123000Q');
|
|
150
177
|
});
|
|
151
178
|
|
|
152
179
|
it('can initialise from string values correctly', () => {
|
package/tests/dlob/helpers.ts
CHANGED
|
@@ -84,7 +84,7 @@ export const mockAMM: AMM = {
|
|
|
84
84
|
baseAssetAmountWithUnsettledLp: new BN(0),
|
|
85
85
|
orderStepSize: new BN(0),
|
|
86
86
|
orderTickSize: new BN(1),
|
|
87
|
-
|
|
87
|
+
last24HAvgFundingRate: new BN(0),
|
|
88
88
|
lastFundingRateShort: new BN(0),
|
|
89
89
|
lastFundingRateLong: new BN(0),
|
|
90
90
|
concentrationCoef: new BN(0),
|