@drift-labs/sdk 2.65.0-beta.4 → 2.65.0-beta.5

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 CHANGED
@@ -1 +1 @@
1
- 2.65.0-beta.4
1
+ 2.65.0-beta.5
@@ -311,6 +311,18 @@ function uncrossL2(bids, asks, oraclePrice, oracleTwap5Min, markTwap5Min, groupi
311
311
  const referencePrice = oraclePrice.add(markTwap5Min.sub(oracleTwap5Min));
312
312
  let bidIndex = 0;
313
313
  let askIndex = 0;
314
+ let maxBid;
315
+ let minAsk;
316
+ const getPriceAndSetBound = (newPrice, direction) => {
317
+ if ((0, __1.isVariant)(direction, 'long')) {
318
+ maxBid = maxBid ? __1.BN.min(maxBid, newPrice) : newPrice;
319
+ return maxBid;
320
+ }
321
+ else {
322
+ minAsk = minAsk ? __1.BN.max(minAsk, newPrice) : newPrice;
323
+ return minAsk;
324
+ }
325
+ };
314
326
  while (bidIndex < bids.length || askIndex < asks.length) {
315
327
  const nextBid = cloneL2Level(bids[bidIndex]);
316
328
  const nextAsk = cloneL2Level(asks[askIndex]);
@@ -337,19 +349,23 @@ function uncrossL2(bids, asks, oraclePrice, oracleTwap5Min, markTwap5Min, groupi
337
349
  }
338
350
  if (nextBid.price.gt(referencePrice) &&
339
351
  nextAsk.price.gt(referencePrice)) {
340
- const newBidPrice = nextAsk.price.sub(grouping);
352
+ let newBidPrice = nextAsk.price.sub(grouping);
353
+ newBidPrice = getPriceAndSetBound(newBidPrice, __1.PositionDirection.LONG);
341
354
  updateLevels(newBidPrice, nextBid, newBids);
342
355
  bidIndex++;
343
356
  }
344
357
  else if (nextAsk.price.lt(referencePrice) &&
345
358
  nextBid.price.lt(referencePrice)) {
346
- const newAskPrice = nextBid.price.add(grouping);
359
+ let newAskPrice = nextBid.price.add(grouping);
360
+ newAskPrice = getPriceAndSetBound(newAskPrice, __1.PositionDirection.SHORT);
347
361
  updateLevels(newAskPrice, nextAsk, newAsks);
348
362
  askIndex++;
349
363
  }
350
364
  else {
351
- const newBidPrice = referencePrice.sub(grouping);
352
- const newAskPrice = referencePrice.add(grouping);
365
+ let newBidPrice = referencePrice.sub(grouping);
366
+ let newAskPrice = referencePrice.add(grouping);
367
+ newBidPrice = getPriceAndSetBound(newBidPrice, __1.PositionDirection.LONG);
368
+ newAskPrice = getPriceAndSetBound(newAskPrice, __1.PositionDirection.SHORT);
353
369
  updateLevels(newBidPrice, nextBid, newBids);
354
370
  updateLevels(newAskPrice, nextAsk, newAsks);
355
371
  bidIndex++;
@@ -357,9 +373,21 @@ function uncrossL2(bids, asks, oraclePrice, oracleTwap5Min, markTwap5Min, groupi
357
373
  }
358
374
  }
359
375
  else {
360
- newAsks.push(nextAsk);
376
+ if (minAsk && nextAsk.price.lte(minAsk)) {
377
+ const newAskPrice = getPriceAndSetBound(nextAsk.price, __1.PositionDirection.SHORT);
378
+ updateLevels(newAskPrice, nextAsk, newAsks);
379
+ }
380
+ else {
381
+ newAsks.push(nextAsk);
382
+ }
361
383
  askIndex++;
362
- newBids.push(nextBid);
384
+ if (maxBid && nextBid.price.gte(maxBid)) {
385
+ const newBidPrice = getPriceAndSetBound(nextBid.price, __1.PositionDirection.LONG);
386
+ updateLevels(newBidPrice, nextBid, newBids);
387
+ }
388
+ else {
389
+ newBids.push(nextBid);
390
+ }
363
391
  bidIndex++;
364
392
  }
365
393
  }
@@ -8,8 +8,8 @@ export interface UserMapInterface {
8
8
  has(key: string): boolean;
9
9
  get(key: string): User | undefined;
10
10
  getWithSlot(key: string): DataAndSlot<User> | undefined;
11
- mustGet(key: string): Promise<User>;
12
- mustGetWithSlot(key: string): Promise<DataAndSlot<User>>;
11
+ mustGet(key: string, accountSubscription?: UserSubscriptionConfig): Promise<User>;
12
+ mustGetWithSlot(key: string, accountSubscription?: UserSubscriptionConfig): Promise<DataAndSlot<User>>;
13
13
  getUserAuthority(key: string): PublicKey | undefined;
14
14
  updateWithOrderRecord(record: OrderRecord): Promise<void>;
15
15
  values(): IterableIterator<User>;
@@ -73,6 +73,7 @@ class UserMap {
73
73
  await this.subscription.subscribe();
74
74
  }
75
75
  async addPubkey(userAccountPublicKey, userAccount, slot, accountSubscription) {
76
+ var _a;
76
77
  const user = new __1.User({
77
78
  driftClient: this.driftClient,
78
79
  userAccountPublicKey,
@@ -84,7 +85,7 @@ class UserMap {
84
85
  await user.subscribe(userAccount);
85
86
  this.userMap.set(userAccountPublicKey.toString(), {
86
87
  data: user,
87
- slot: slot !== null && slot !== void 0 ? slot : -1,
88
+ slot: (_a = user.getUserAccountAndSlot().slot) !== null && _a !== void 0 ? _a : -1,
88
89
  });
89
90
  }
90
91
  has(key) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "2.65.0-beta.4",
3
+ "version": "2.65.0-beta.5",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -7,6 +7,7 @@ import {
7
7
  calculateSpreadReserves,
8
8
  calculateUpdatedAMM,
9
9
  DLOBNode,
10
+ isVariant,
10
11
  OraclePriceData,
11
12
  PerpMarketAccount,
12
13
  PositionDirection,
@@ -492,6 +493,19 @@ export function uncrossL2(
492
493
 
493
494
  let bidIndex = 0;
494
495
  let askIndex = 0;
496
+ let maxBid: BN;
497
+ let minAsk: BN;
498
+
499
+ const getPriceAndSetBound = (newPrice: BN, direction: PositionDirection) => {
500
+ if (isVariant(direction, 'long')) {
501
+ maxBid = maxBid ? BN.min(maxBid, newPrice) : newPrice;
502
+ return maxBid;
503
+ } else {
504
+ minAsk = minAsk ? BN.max(minAsk, newPrice) : newPrice;
505
+ return minAsk;
506
+ }
507
+ };
508
+
495
509
  while (bidIndex < bids.length || askIndex < asks.length) {
496
510
  const nextBid = cloneL2Level(bids[bidIndex]);
497
511
  const nextAsk = cloneL2Level(asks[askIndex]);
@@ -525,29 +539,51 @@ export function uncrossL2(
525
539
  nextBid.price.gt(referencePrice) &&
526
540
  nextAsk.price.gt(referencePrice)
527
541
  ) {
528
- const newBidPrice = nextAsk.price.sub(grouping);
542
+ let newBidPrice = nextAsk.price.sub(grouping);
543
+ newBidPrice = getPriceAndSetBound(newBidPrice, PositionDirection.LONG);
529
544
  updateLevels(newBidPrice, nextBid, newBids);
530
545
  bidIndex++;
531
546
  } else if (
532
547
  nextAsk.price.lt(referencePrice) &&
533
548
  nextBid.price.lt(referencePrice)
534
549
  ) {
535
- const newAskPrice = nextBid.price.add(grouping);
550
+ let newAskPrice = nextBid.price.add(grouping);
551
+ newAskPrice = getPriceAndSetBound(newAskPrice, PositionDirection.SHORT);
536
552
  updateLevels(newAskPrice, nextAsk, newAsks);
537
553
  askIndex++;
538
554
  } else {
539
- const newBidPrice = referencePrice.sub(grouping);
540
- const newAskPrice = referencePrice.add(grouping);
555
+ let newBidPrice = referencePrice.sub(grouping);
556
+ let newAskPrice = referencePrice.add(grouping);
557
+
558
+ newBidPrice = getPriceAndSetBound(newBidPrice, PositionDirection.LONG);
559
+ newAskPrice = getPriceAndSetBound(newAskPrice, PositionDirection.SHORT);
560
+
541
561
  updateLevels(newBidPrice, nextBid, newBids);
542
562
  updateLevels(newAskPrice, nextAsk, newAsks);
543
563
  bidIndex++;
544
564
  askIndex++;
545
565
  }
546
566
  } else {
547
- newAsks.push(nextAsk);
567
+ if (minAsk && nextAsk.price.lte(minAsk)) {
568
+ const newAskPrice = getPriceAndSetBound(
569
+ nextAsk.price,
570
+ PositionDirection.SHORT
571
+ );
572
+ updateLevels(newAskPrice, nextAsk, newAsks);
573
+ } else {
574
+ newAsks.push(nextAsk);
575
+ }
548
576
  askIndex++;
549
577
 
550
- newBids.push(nextBid);
578
+ if (maxBid && nextBid.price.gte(maxBid)) {
579
+ const newBidPrice = getPriceAndSetBound(
580
+ nextBid.price,
581
+ PositionDirection.LONG
582
+ );
583
+ updateLevels(newBidPrice, nextBid, newBids);
584
+ } else {
585
+ newBids.push(nextBid);
586
+ }
551
587
  bidIndex++;
552
588
  }
553
589
  }
@@ -42,8 +42,14 @@ export interface UserMapInterface {
42
42
  has(key: string): boolean;
43
43
  get(key: string): User | undefined;
44
44
  getWithSlot(key: string): DataAndSlot<User> | undefined;
45
- mustGet(key: string): Promise<User>;
46
- mustGetWithSlot(key: string): Promise<DataAndSlot<User>>;
45
+ mustGet(
46
+ key: string,
47
+ accountSubscription?: UserSubscriptionConfig
48
+ ): Promise<User>;
49
+ mustGetWithSlot(
50
+ key: string,
51
+ accountSubscription?: UserSubscriptionConfig
52
+ ): Promise<DataAndSlot<User>>;
47
53
  getUserAuthority(key: string): PublicKey | undefined;
48
54
  updateWithOrderRecord(record: OrderRecord): Promise<void>;
49
55
  values(): IterableIterator<User>;
@@ -158,7 +164,7 @@ export class UserMap implements UserMapInterface {
158
164
  await user.subscribe(userAccount);
159
165
  this.userMap.set(userAccountPublicKey.toString(), {
160
166
  data: user,
161
- slot: slot ?? -1,
167
+ slot: user.getUserAccountAndSlot().slot ?? -1,
162
168
  });
163
169
  }
164
170
 
@@ -6677,4 +6677,67 @@ describe('Uncross L2', () => {
6677
6677
  expect(asksAreSortedAsc(newAsks), "Uncrossed asks are ascending").to.be.true;
6678
6678
  expect(bidsAreSortedDesc(newBids), "Uncrossed bids are descending").to.be.true;
6679
6679
  });
6680
+
6681
+ it('Crossing edge case : top bid and ask have a big cross, following ones dont - shouldnt get uncrossed out of order', () => {
6682
+ const bids = [
6683
+ "101825900",
6684
+ "101783900",
6685
+ "101783000",
6686
+ "101782600",
6687
+ "101770700",
6688
+ "101770200",
6689
+ "101749857",
6690
+ "101735900",
6691
+ "101729994",
6692
+ "101726900",
6693
+ ].map(priceStr => (
6694
+ {
6695
+ price: new BN(priceStr),
6696
+ size: new BN(1).mul(BASE_PRECISION),
6697
+ sources: { vamm: new BN(1).mul(BASE_PRECISION) },
6698
+ }
6699
+ ));
6700
+
6701
+ const asks = [
6702
+ "101750700",
6703
+ "101790467",
6704
+ "101793400",
6705
+ "101794116",
6706
+ "101798548",
6707
+ "101799532",
6708
+ "101803500",
6709
+ "101820927",
6710
+ "101823900",
6711
+ "101827638",
6712
+ ].map(priceStr => ({
6713
+ price: new BN(priceStr),
6714
+ size: new BN(1).mul(BASE_PRECISION),
6715
+ sources: { vamm: new BN(1).mul(BASE_PRECISION) },
6716
+ }));
6717
+
6718
+ expect(asksAreSortedAsc(asks), "Input asks are ascending").to.be.true;
6719
+ expect(bidsAreSortedDesc(bids), "Input bids are descending").to.be.true;
6720
+
6721
+ const oraclePrice = new BN("101711384");
6722
+ const oraclePrice5Min = new BN("101805000");
6723
+ const markPrice5Min = new BN("101867000");
6724
+
6725
+ const groupingSize = new BN("100");
6726
+
6727
+ const userAsks = new Set<string>();
6728
+
6729
+ const { bids: newBids, asks: newAsks } = uncrossL2(
6730
+ bids,
6731
+ asks,
6732
+ oraclePrice,
6733
+ oraclePrice5Min,
6734
+ markPrice5Min,
6735
+ groupingSize,
6736
+ new Set<string>(),
6737
+ userAsks
6738
+ );
6739
+
6740
+ expect(asksAreSortedAsc(newAsks), "Uncrossed asks are ascending").to.be.true;
6741
+ expect(bidsAreSortedDesc(newBids), "Uncrossed bids are descending").to.be.true;
6742
+ });
6680
6743
  });