@drift-labs/sdk 2.0.14 → 2.0.16
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 +3 -0
- package/lib/constants/numericConstants.js +4 -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 +8 -7
- package/lib/math/amm.js +116 -61
- package/lib/math/oracles.d.ts +2 -0
- package/lib/math/oracles.js +23 -1
- package/lib/math/utils.d.ts +2 -1
- 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 +7 -0
- package/src/dlob/DLOB.ts +152 -237
- package/src/idl/drift.json +65 -7
- package/src/math/amm.ts +220 -100
- package/src/math/oracles.ts +52 -0
- package/src/math/utils.ts +5 -1
- 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/events/eventList.js +0 -77
package/tests/dlob/test.ts
CHANGED
|
@@ -4448,6 +4448,258 @@ describe('DLOB Spot Tests', () => {
|
|
|
4448
4448
|
expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(3);
|
|
4449
4449
|
});
|
|
4450
4450
|
|
|
4451
|
+
it('Test market orders skipping maker with same authority', () => {
|
|
4452
|
+
const vAsk = new BN(15);
|
|
4453
|
+
const vBid = new BN(8);
|
|
4454
|
+
|
|
4455
|
+
const mockUserMap = new MockUserMap();
|
|
4456
|
+
const user0 = Keypair.generate();
|
|
4457
|
+
const userAuth0 = Keypair.generate();
|
|
4458
|
+
const user1 = Keypair.generate();
|
|
4459
|
+
const userAuth1 = Keypair.generate();
|
|
4460
|
+
|
|
4461
|
+
mockUserMap.addUserAccountAuthority(user0.publicKey, userAuth0.publicKey);
|
|
4462
|
+
mockUserMap.addUserAccountAuthority(user1.publicKey, userAuth1.publicKey);
|
|
4463
|
+
|
|
4464
|
+
const dlob = new DLOB(
|
|
4465
|
+
mockPerpMarkets,
|
|
4466
|
+
mockSpotMarkets,
|
|
4467
|
+
mockStateAccount,
|
|
4468
|
+
mockUserMap,
|
|
4469
|
+
false
|
|
4470
|
+
);
|
|
4471
|
+
const marketIndex = 0;
|
|
4472
|
+
|
|
4473
|
+
const slot = 12;
|
|
4474
|
+
const oracle = {
|
|
4475
|
+
price: vBid.add(vAsk).div(new BN(2)),
|
|
4476
|
+
slot: new BN(slot),
|
|
4477
|
+
confidence: new BN(1),
|
|
4478
|
+
hasSufficientNumberOfDataPoints: true,
|
|
4479
|
+
};
|
|
4480
|
+
|
|
4481
|
+
// insert some limit sells below vAMM ask, above bid
|
|
4482
|
+
insertOrderToDLOB(
|
|
4483
|
+
dlob,
|
|
4484
|
+
user0.publicKey,
|
|
4485
|
+
OrderType.LIMIT,
|
|
4486
|
+
MarketType.PERP,
|
|
4487
|
+
1, // orderId
|
|
4488
|
+
marketIndex,
|
|
4489
|
+
new BN(14), // price
|
|
4490
|
+
BASE_PRECISION, // quantity
|
|
4491
|
+
PositionDirection.SHORT,
|
|
4492
|
+
vBid,
|
|
4493
|
+
vAsk
|
|
4494
|
+
);
|
|
4495
|
+
insertOrderToDLOB(
|
|
4496
|
+
dlob,
|
|
4497
|
+
user1.publicKey,
|
|
4498
|
+
OrderType.LIMIT,
|
|
4499
|
+
MarketType.PERP,
|
|
4500
|
+
2, // orderId
|
|
4501
|
+
marketIndex,
|
|
4502
|
+
new BN(13), // price
|
|
4503
|
+
BASE_PRECISION, // quantity
|
|
4504
|
+
PositionDirection.SHORT,
|
|
4505
|
+
vBid,
|
|
4506
|
+
vAsk
|
|
4507
|
+
);
|
|
4508
|
+
|
|
4509
|
+
// should have no crossing orders
|
|
4510
|
+
const nodesToFillBefore = dlob.findNodesToFill(
|
|
4511
|
+
marketIndex,
|
|
4512
|
+
undefined,
|
|
4513
|
+
undefined,
|
|
4514
|
+
12, // auction over
|
|
4515
|
+
Date.now(),
|
|
4516
|
+
MarketType.PERP,
|
|
4517
|
+
oracle
|
|
4518
|
+
);
|
|
4519
|
+
expect(nodesToFillBefore.length).to.equal(0);
|
|
4520
|
+
|
|
4521
|
+
// place two market buy orders to eat the best ask
|
|
4522
|
+
insertOrderToDLOB(
|
|
4523
|
+
dlob,
|
|
4524
|
+
user1.publicKey,
|
|
4525
|
+
OrderType.MARKET,
|
|
4526
|
+
MarketType.PERP,
|
|
4527
|
+
3, // orderId
|
|
4528
|
+
marketIndex,
|
|
4529
|
+
new BN(0), // price
|
|
4530
|
+
BASE_PRECISION, // quantity
|
|
4531
|
+
PositionDirection.LONG,
|
|
4532
|
+
vBid,
|
|
4533
|
+
vAsk
|
|
4534
|
+
);
|
|
4535
|
+
insertOrderToDLOB(
|
|
4536
|
+
dlob,
|
|
4537
|
+
user0.publicKey,
|
|
4538
|
+
OrderType.MARKET,
|
|
4539
|
+
MarketType.PERP,
|
|
4540
|
+
4, // orderId
|
|
4541
|
+
marketIndex,
|
|
4542
|
+
new BN(0), // price
|
|
4543
|
+
BASE_PRECISION, // quantity
|
|
4544
|
+
PositionDirection.LONG,
|
|
4545
|
+
vBid,
|
|
4546
|
+
vAsk
|
|
4547
|
+
);
|
|
4548
|
+
|
|
4549
|
+
const nodesToFillAfter = dlob.findNodesToFill(
|
|
4550
|
+
marketIndex,
|
|
4551
|
+
undefined,
|
|
4552
|
+
undefined,
|
|
4553
|
+
slot, // auction over
|
|
4554
|
+
Date.now(),
|
|
4555
|
+
MarketType.PERP,
|
|
4556
|
+
oracle
|
|
4557
|
+
);
|
|
4558
|
+
|
|
4559
|
+
printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
|
|
4560
|
+
|
|
4561
|
+
for (const n of nodesToFillAfter) {
|
|
4562
|
+
console.log(
|
|
4563
|
+
`cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmountFilled.toString()}/${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmountFilled.toString()}/${n.makerNode?.order?.baseAssetAmount.toString()}`
|
|
4564
|
+
);
|
|
4565
|
+
}
|
|
4566
|
+
expect(nodesToFillAfter.length).to.equal(2);
|
|
4567
|
+
|
|
4568
|
+
// taker should fill completely with best maker
|
|
4569
|
+
expect(nodesToFillAfter[0].node.order?.orderId).to.equal(3);
|
|
4570
|
+
expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(1);
|
|
4571
|
+
|
|
4572
|
+
// taker should fill completely with second best maker
|
|
4573
|
+
expect(nodesToFillAfter[1].node.order?.orderId).to.equal(4);
|
|
4574
|
+
expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(2);
|
|
4575
|
+
});
|
|
4576
|
+
|
|
4577
|
+
it('Test limit orders skipping maker with same authority', () => {
|
|
4578
|
+
const vAsk = new BN(15);
|
|
4579
|
+
const vBid = new BN(8);
|
|
4580
|
+
|
|
4581
|
+
const mockUserMap = new MockUserMap();
|
|
4582
|
+
const user0 = Keypair.generate();
|
|
4583
|
+
const userAuth0 = Keypair.generate();
|
|
4584
|
+
const user1 = Keypair.generate();
|
|
4585
|
+
const userAuth1 = Keypair.generate();
|
|
4586
|
+
|
|
4587
|
+
mockUserMap.addUserAccountAuthority(user0.publicKey, userAuth0.publicKey);
|
|
4588
|
+
mockUserMap.addUserAccountAuthority(user1.publicKey, userAuth1.publicKey);
|
|
4589
|
+
|
|
4590
|
+
const dlob = new DLOB(
|
|
4591
|
+
mockPerpMarkets,
|
|
4592
|
+
mockSpotMarkets,
|
|
4593
|
+
mockStateAccount,
|
|
4594
|
+
mockUserMap,
|
|
4595
|
+
false
|
|
4596
|
+
);
|
|
4597
|
+
const marketIndex = 0;
|
|
4598
|
+
|
|
4599
|
+
const slot = 12;
|
|
4600
|
+
const oracle = {
|
|
4601
|
+
price: vBid.add(vAsk).div(new BN(2)),
|
|
4602
|
+
slot: new BN(slot),
|
|
4603
|
+
confidence: new BN(1),
|
|
4604
|
+
hasSufficientNumberOfDataPoints: true,
|
|
4605
|
+
};
|
|
4606
|
+
|
|
4607
|
+
// insert some limit sells below vAMM ask, above bid
|
|
4608
|
+
insertOrderToDLOB(
|
|
4609
|
+
dlob,
|
|
4610
|
+
user0.publicKey,
|
|
4611
|
+
OrderType.LIMIT,
|
|
4612
|
+
MarketType.PERP,
|
|
4613
|
+
1, // orderId
|
|
4614
|
+
marketIndex,
|
|
4615
|
+
new BN(14), // price
|
|
4616
|
+
BASE_PRECISION, // quantity
|
|
4617
|
+
PositionDirection.SHORT,
|
|
4618
|
+
vBid,
|
|
4619
|
+
vAsk
|
|
4620
|
+
);
|
|
4621
|
+
insertOrderToDLOB(
|
|
4622
|
+
dlob,
|
|
4623
|
+
user1.publicKey,
|
|
4624
|
+
OrderType.LIMIT,
|
|
4625
|
+
MarketType.PERP,
|
|
4626
|
+
2, // orderId
|
|
4627
|
+
marketIndex,
|
|
4628
|
+
new BN(13), // price
|
|
4629
|
+
BASE_PRECISION, // quantity
|
|
4630
|
+
PositionDirection.SHORT,
|
|
4631
|
+
vBid,
|
|
4632
|
+
vAsk
|
|
4633
|
+
);
|
|
4634
|
+
|
|
4635
|
+
// should have no crossing orders
|
|
4636
|
+
const nodesToFillBefore = dlob.findNodesToFill(
|
|
4637
|
+
marketIndex,
|
|
4638
|
+
undefined,
|
|
4639
|
+
undefined,
|
|
4640
|
+
12, // auction over
|
|
4641
|
+
Date.now(),
|
|
4642
|
+
MarketType.PERP,
|
|
4643
|
+
oracle
|
|
4644
|
+
);
|
|
4645
|
+
expect(nodesToFillBefore.length).to.equal(0);
|
|
4646
|
+
|
|
4647
|
+
// place two market buy orders to eat the best ask
|
|
4648
|
+
insertOrderToDLOB(
|
|
4649
|
+
dlob,
|
|
4650
|
+
user1.publicKey,
|
|
4651
|
+
OrderType.LIMIT,
|
|
4652
|
+
MarketType.PERP,
|
|
4653
|
+
3, // orderId
|
|
4654
|
+
marketIndex,
|
|
4655
|
+
new BN(15), // price
|
|
4656
|
+
BASE_PRECISION, // quantity
|
|
4657
|
+
PositionDirection.LONG,
|
|
4658
|
+
vBid,
|
|
4659
|
+
vAsk
|
|
4660
|
+
);
|
|
4661
|
+
insertOrderToDLOB(
|
|
4662
|
+
dlob,
|
|
4663
|
+
user0.publicKey,
|
|
4664
|
+
OrderType.LIMIT,
|
|
4665
|
+
MarketType.PERP,
|
|
4666
|
+
4, // orderId
|
|
4667
|
+
marketIndex,
|
|
4668
|
+
new BN(14), // price
|
|
4669
|
+
BASE_PRECISION, // quantity
|
|
4670
|
+
PositionDirection.LONG,
|
|
4671
|
+
vBid,
|
|
4672
|
+
vAsk
|
|
4673
|
+
);
|
|
4674
|
+
|
|
4675
|
+
const nodesToFillAfter = dlob.findNodesToFill(
|
|
4676
|
+
marketIndex,
|
|
4677
|
+
undefined,
|
|
4678
|
+
undefined,
|
|
4679
|
+
slot, // auction over
|
|
4680
|
+
Date.now(),
|
|
4681
|
+
MarketType.PERP,
|
|
4682
|
+
oracle
|
|
4683
|
+
);
|
|
4684
|
+
|
|
4685
|
+
printBookState(dlob, marketIndex, vBid, vAsk, slot, oracle);
|
|
4686
|
+
|
|
4687
|
+
for (const n of nodesToFillAfter) {
|
|
4688
|
+
console.log(
|
|
4689
|
+
`cross found: taker orderId: ${n.node.order?.orderId.toString()}: BAA: ${n.node.order?.baseAssetAmountFilled.toString()}/${n.node.order?.baseAssetAmount.toString()}, maker orderId: ${n.makerNode?.order?.orderId.toString()}: BAA: ${n.makerNode?.order?.baseAssetAmountFilled.toString()}/${n.makerNode?.order?.baseAssetAmount.toString()}`
|
|
4690
|
+
);
|
|
4691
|
+
}
|
|
4692
|
+
expect(nodesToFillAfter.length).to.equal(2);
|
|
4693
|
+
|
|
4694
|
+
// taker should fill completely with best maker
|
|
4695
|
+
expect(nodesToFillAfter[0].node.order?.orderId).to.equal(2);
|
|
4696
|
+
expect(nodesToFillAfter[0].makerNode?.order?.orderId).to.equal(4);
|
|
4697
|
+
|
|
4698
|
+
// taker should fill completely with second best maker
|
|
4699
|
+
expect(nodesToFillAfter[1].node.order?.orderId).to.equal(1);
|
|
4700
|
+
expect(nodesToFillAfter[1].makerNode?.order?.orderId).to.equal(3);
|
|
4701
|
+
});
|
|
4702
|
+
|
|
4451
4703
|
it('Test trigger orders', () => {
|
|
4452
4704
|
const vAsk = new BN(15);
|
|
4453
4705
|
const vBid = new BN(8);
|
package/src/events/eventList.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.EventList = void 0;
|
|
4
|
-
class Node {
|
|
5
|
-
constructor(event, next, prev) {
|
|
6
|
-
this.event = event;
|
|
7
|
-
this.next = next;
|
|
8
|
-
this.prev = prev;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
class EventList {
|
|
12
|
-
constructor(eventType, maxSize, sortFn, orderDirection) {
|
|
13
|
-
this.eventType = eventType;
|
|
14
|
-
this.maxSize = maxSize;
|
|
15
|
-
this.sortFn = sortFn;
|
|
16
|
-
this.orderDirection = orderDirection;
|
|
17
|
-
this.size = 0;
|
|
18
|
-
}
|
|
19
|
-
insert(event) {
|
|
20
|
-
this.size++;
|
|
21
|
-
const newNode = new Node(event);
|
|
22
|
-
if (this.head === undefined) {
|
|
23
|
-
this.head = this.tail = newNode;
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
if (this.sortFn(this.head.event, newNode.event) ===
|
|
27
|
-
(this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
|
|
28
|
-
this.head.prev = newNode;
|
|
29
|
-
newNode.next = this.head;
|
|
30
|
-
this.head = newNode;
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
let currentNode = this.head;
|
|
34
|
-
while (currentNode.next !== undefined &&
|
|
35
|
-
this.sortFn(currentNode.next.event, newNode.event) !==
|
|
36
|
-
(this.orderDirection === 'asc' ? 'less than' : 'greater than')) {
|
|
37
|
-
currentNode = currentNode.next;
|
|
38
|
-
}
|
|
39
|
-
newNode.next = currentNode.next;
|
|
40
|
-
if (currentNode.next !== undefined) {
|
|
41
|
-
newNode.next.prev = newNode;
|
|
42
|
-
}
|
|
43
|
-
currentNode.next = newNode;
|
|
44
|
-
newNode.prev = currentNode;
|
|
45
|
-
}
|
|
46
|
-
if (this.size > this.maxSize) {
|
|
47
|
-
this.detach();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
detach() {
|
|
51
|
-
const node = this.tail;
|
|
52
|
-
if (node.prev !== undefined) {
|
|
53
|
-
node.prev.next = node.next;
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
this.head = node.next;
|
|
57
|
-
}
|
|
58
|
-
if (node.next !== undefined) {
|
|
59
|
-
node.next.prev = node.prev;
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
this.tail = node.prev;
|
|
63
|
-
}
|
|
64
|
-
this.size--;
|
|
65
|
-
}
|
|
66
|
-
toArray() {
|
|
67
|
-
return Array.from(this);
|
|
68
|
-
}
|
|
69
|
-
*[Symbol.iterator]() {
|
|
70
|
-
let node = this.head;
|
|
71
|
-
while (node) {
|
|
72
|
-
yield node.event;
|
|
73
|
-
node = node.next;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
exports.EventList = EventList;
|