@drift-labs/sdk 2.43.0-beta.8 → 2.44.0-beta.0
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/lib/accounts/webSocketAccountSubscriber.d.ts +1 -0
- package/lib/accounts/webSocketAccountSubscriber.js +18 -3
- package/lib/accounts/webSocketProgramAccountSubscriber.d.ts +1 -0
- package/lib/accounts/webSocketProgramAccountSubscriber.js +18 -3
- package/lib/adminClient.d.ts +1 -0
- package/lib/adminClient.js +8 -0
- package/lib/constants/perpMarkets.js +20 -0
- package/lib/dlob/DLOB.d.ts +9 -3
- package/lib/dlob/DLOB.js +77 -14
- package/lib/dlob/orderBookLevels.js +1 -0
- package/lib/driftClient.d.ts +3 -1
- package/lib/driftClient.js +86 -69
- package/lib/idl/drift.json +22 -1
- package/lib/jupiter/jupiterClient.js +10 -2
- package/lib/math/amm.js +2 -1
- package/lib/math/trade.js +18 -24
- package/lib/tx/fastSingleTxSender.js +6 -1
- package/lib/user.js +7 -8
- package/package.json +1 -1
- package/src/accounts/webSocketAccountSubscriber.ts +20 -6
- package/src/accounts/webSocketProgramAccountSubscriber.ts +19 -6
- package/src/adminClient.ts +14 -0
- package/src/constants/perpMarkets.ts +20 -0
- package/src/dlob/DLOB.ts +114 -20
- package/src/dlob/orderBookLevels.ts +1 -0
- package/src/driftClient.ts +129 -82
- package/src/idl/drift.json +22 -1
- package/src/jupiter/jupiterClient.ts +12 -2
- package/src/math/amm.ts +2 -2
- package/src/math/trade.ts +26 -26
- package/src/tx/fastSingleTxSender.ts +7 -3
- package/src/user.ts +12 -8
|
@@ -21,6 +21,7 @@ export class WebSocketProgramAccountSubscriber<T>
|
|
|
21
21
|
onChange: (accountId: PublicKey, data: T, context: Context) => void;
|
|
22
22
|
listenerId?: number;
|
|
23
23
|
resubTimeoutMs?: number;
|
|
24
|
+
isUnsubscribing = false;
|
|
24
25
|
timeoutId?: NodeJS.Timeout;
|
|
25
26
|
options: { filters: MemcmpFilter[]; commitment?: Commitment };
|
|
26
27
|
|
|
@@ -48,7 +49,7 @@ export class WebSocketProgramAccountSubscriber<T>
|
|
|
48
49
|
async subscribe(
|
|
49
50
|
onChange: (accountId: PublicKey, data: T, context: Context) => void
|
|
50
51
|
): Promise<void> {
|
|
51
|
-
if (this.listenerId) {
|
|
52
|
+
if (this.listenerId || this.isUnsubscribing) {
|
|
52
53
|
return;
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -81,6 +82,11 @@ export class WebSocketProgramAccountSubscriber<T>
|
|
|
81
82
|
throw new Error('onChange callback function must be set');
|
|
82
83
|
}
|
|
83
84
|
this.timeoutId = setTimeout(async () => {
|
|
85
|
+
if (this.isUnsubscribing) {
|
|
86
|
+
// If we are in the process of unsubscribing, do not attempt to resubscribe
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
84
90
|
if (this.receivingData) {
|
|
85
91
|
console.log(
|
|
86
92
|
`No ws data from ${this.subscriptionName} in ${this.resubTimeoutMs}ms, resubscribing`
|
|
@@ -140,13 +146,20 @@ export class WebSocketProgramAccountSubscriber<T>
|
|
|
140
146
|
}
|
|
141
147
|
|
|
142
148
|
unsubscribe(): Promise<void> {
|
|
149
|
+
this.isUnsubscribing = true;
|
|
150
|
+
clearTimeout(this.timeoutId);
|
|
151
|
+
this.timeoutId = undefined;
|
|
152
|
+
|
|
143
153
|
if (this.listenerId) {
|
|
144
|
-
const promise =
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
154
|
+
const promise = this.program.provider.connection
|
|
155
|
+
.removeAccountChangeListener(this.listenerId)
|
|
156
|
+
.then(() => {
|
|
157
|
+
this.listenerId = undefined;
|
|
158
|
+
this.isUnsubscribing = false;
|
|
159
|
+
});
|
|
149
160
|
return promise;
|
|
161
|
+
} else {
|
|
162
|
+
this.isUnsubscribing = false;
|
|
150
163
|
}
|
|
151
164
|
}
|
|
152
165
|
}
|
package/src/adminClient.ts
CHANGED
|
@@ -787,6 +787,20 @@ export class AdminClient extends DriftClient {
|
|
|
787
787
|
);
|
|
788
788
|
}
|
|
789
789
|
|
|
790
|
+
public async updateLiquidationMarginBufferRatio(
|
|
791
|
+
updateLiquidationMarginBufferRatio: number
|
|
792
|
+
): Promise<TransactionSignature> {
|
|
793
|
+
return await this.program.rpc.updateLiquidationMarginBufferRatio(
|
|
794
|
+
updateLiquidationMarginBufferRatio,
|
|
795
|
+
{
|
|
796
|
+
accounts: {
|
|
797
|
+
admin: this.wallet.publicKey,
|
|
798
|
+
state: await this.getStatePublicKey(),
|
|
799
|
+
},
|
|
800
|
+
}
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
|
|
790
804
|
public async updateOracleGuardRails(
|
|
791
805
|
oracleGuardRails: OracleGuardRails
|
|
792
806
|
): Promise<TransactionSignature> {
|
|
@@ -184,6 +184,16 @@ export const DevnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
184
184
|
launchTs: 1698074659000,
|
|
185
185
|
oracleSource: OracleSource.PYTH,
|
|
186
186
|
},
|
|
187
|
+
{
|
|
188
|
+
fullName: 'Rollbit',
|
|
189
|
+
category: ['Exchange'],
|
|
190
|
+
symbol: 'RLB-PERP',
|
|
191
|
+
baseAssetSymbol: 'RLB',
|
|
192
|
+
marketIndex: 17,
|
|
193
|
+
oracle: new PublicKey('6BmJozusMugAySsfNfMFsU1YRWcGwyP3oycNX9Pv9oCz'),
|
|
194
|
+
launchTs: 11699265968000,
|
|
195
|
+
oracleSource: OracleSource.PYTH,
|
|
196
|
+
},
|
|
187
197
|
];
|
|
188
198
|
|
|
189
199
|
export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
@@ -357,6 +367,16 @@ export const MainnetPerpMarkets: PerpMarketConfig[] = [
|
|
|
357
367
|
launchTs: 1698074659000,
|
|
358
368
|
oracleSource: OracleSource.PYTH,
|
|
359
369
|
},
|
|
370
|
+
{
|
|
371
|
+
fullName: 'Rollbit',
|
|
372
|
+
category: ['Exchange'],
|
|
373
|
+
symbol: 'RLB-PERP',
|
|
374
|
+
baseAssetSymbol: 'RLB',
|
|
375
|
+
marketIndex: 17,
|
|
376
|
+
oracle: new PublicKey('4BA3RcS4zE32WWgp49vvvre2t6nXY1W1kMyKZxeeuUey'),
|
|
377
|
+
launchTs: 11699265968000,
|
|
378
|
+
oracleSource: OracleSource.PYTH,
|
|
379
|
+
},
|
|
360
380
|
];
|
|
361
381
|
|
|
362
382
|
export const PerpMarkets: { [key in DriftEnv]: PerpMarketConfig[] } = {
|
package/src/dlob/DLOB.ts
CHANGED
|
@@ -2,9 +2,8 @@ import { getOrderSignature, getVammNodeGenerator, NodeList } from './NodeList';
|
|
|
2
2
|
import {
|
|
3
3
|
BASE_PRECISION,
|
|
4
4
|
BN,
|
|
5
|
-
calculateAskPrice,
|
|
6
|
-
calculateBidPrice,
|
|
7
5
|
convertToNumber,
|
|
6
|
+
decodeName,
|
|
8
7
|
DLOBNode,
|
|
9
8
|
DLOBNodeType,
|
|
10
9
|
DriftClient,
|
|
@@ -1430,14 +1429,12 @@ export class DLOB {
|
|
|
1430
1429
|
|
|
1431
1430
|
public getBestAsk(
|
|
1432
1431
|
marketIndex: number,
|
|
1433
|
-
fallbackAsk: BN | undefined,
|
|
1434
1432
|
slot: number,
|
|
1435
1433
|
marketType: MarketType,
|
|
1436
1434
|
oraclePriceData: OraclePriceData
|
|
1437
1435
|
): BN {
|
|
1438
|
-
return this.
|
|
1436
|
+
return this.getRestingLimitAsks(
|
|
1439
1437
|
marketIndex,
|
|
1440
|
-
fallbackAsk,
|
|
1441
1438
|
slot,
|
|
1442
1439
|
marketType,
|
|
1443
1440
|
oraclePriceData
|
|
@@ -1448,14 +1445,12 @@ export class DLOB {
|
|
|
1448
1445
|
|
|
1449
1446
|
public getBestBid(
|
|
1450
1447
|
marketIndex: number,
|
|
1451
|
-
fallbackBid: BN | undefined,
|
|
1452
1448
|
slot: number,
|
|
1453
1449
|
marketType: MarketType,
|
|
1454
1450
|
oraclePriceData: OraclePriceData
|
|
1455
1451
|
): BN {
|
|
1456
|
-
return this.
|
|
1452
|
+
return this.getRestingLimitBids(
|
|
1457
1453
|
marketIndex,
|
|
1458
|
-
fallbackBid,
|
|
1459
1454
|
slot,
|
|
1460
1455
|
marketType,
|
|
1461
1456
|
oraclePriceData
|
|
@@ -1464,6 +1459,108 @@ export class DLOB {
|
|
|
1464
1459
|
.value.getPrice(oraclePriceData, slot);
|
|
1465
1460
|
}
|
|
1466
1461
|
|
|
1462
|
+
public *getStopLosses(
|
|
1463
|
+
marketIndex: number,
|
|
1464
|
+
marketType: MarketType,
|
|
1465
|
+
direction: PositionDirection
|
|
1466
|
+
): Generator<DLOBNode> {
|
|
1467
|
+
const marketTypeStr = getVariant(marketType) as MarketTypeStr;
|
|
1468
|
+
const marketNodeLists = this.orderLists.get(marketTypeStr).get(marketIndex);
|
|
1469
|
+
|
|
1470
|
+
if (isVariant(direction, 'long') && marketNodeLists.trigger.below) {
|
|
1471
|
+
for (const node of marketNodeLists.trigger.below.getGenerator()) {
|
|
1472
|
+
if (isVariant(node.order.direction, 'short')) {
|
|
1473
|
+
yield node;
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
} else if (isVariant(direction, 'short') && marketNodeLists.trigger.above) {
|
|
1477
|
+
for (const node of marketNodeLists.trigger.above.getGenerator()) {
|
|
1478
|
+
if (isVariant(node.order.direction, 'long')) {
|
|
1479
|
+
yield node;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
public *getStopLossMarkets(
|
|
1486
|
+
marketIndex: number,
|
|
1487
|
+
marketType: MarketType,
|
|
1488
|
+
direction: PositionDirection
|
|
1489
|
+
): Generator<DLOBNode> {
|
|
1490
|
+
for (const node of this.getStopLosses(marketIndex, marketType, direction)) {
|
|
1491
|
+
if (isVariant(node.order.orderType, 'triggerMarket')) {
|
|
1492
|
+
yield node;
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
public *getStopLossLimits(
|
|
1498
|
+
marketIndex: number,
|
|
1499
|
+
marketType: MarketType,
|
|
1500
|
+
direction: PositionDirection
|
|
1501
|
+
): Generator<DLOBNode> {
|
|
1502
|
+
for (const node of this.getStopLosses(marketIndex, marketType, direction)) {
|
|
1503
|
+
if (isVariant(node.order.orderType, 'triggerLimit')) {
|
|
1504
|
+
yield node;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
public *getTakeProfits(
|
|
1510
|
+
marketIndex: number,
|
|
1511
|
+
marketType: MarketType,
|
|
1512
|
+
direction: PositionDirection
|
|
1513
|
+
): Generator<DLOBNode> {
|
|
1514
|
+
const marketTypeStr = getVariant(marketType) as MarketTypeStr;
|
|
1515
|
+
const marketNodeLists = this.orderLists.get(marketTypeStr).get(marketIndex);
|
|
1516
|
+
|
|
1517
|
+
if (isVariant(direction, 'long') && marketNodeLists.trigger.above) {
|
|
1518
|
+
for (const node of marketNodeLists.trigger.above.getGenerator()) {
|
|
1519
|
+
if (isVariant(node.order.direction, 'short')) {
|
|
1520
|
+
yield node;
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1523
|
+
} else if (isVariant(direction, 'short') && marketNodeLists.trigger.below) {
|
|
1524
|
+
for (const node of marketNodeLists.trigger.below.getGenerator()) {
|
|
1525
|
+
if (isVariant(node.order.direction, 'long')) {
|
|
1526
|
+
yield node;
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
|
|
1532
|
+
public *getTakeProfitMarkets(
|
|
1533
|
+
marketIndex: number,
|
|
1534
|
+
marketType: MarketType,
|
|
1535
|
+
direction: PositionDirection
|
|
1536
|
+
): Generator<DLOBNode> {
|
|
1537
|
+
for (const node of this.getTakeProfits(
|
|
1538
|
+
marketIndex,
|
|
1539
|
+
marketType,
|
|
1540
|
+
direction
|
|
1541
|
+
)) {
|
|
1542
|
+
if (isVariant(node.order.orderType, 'triggerMarket')) {
|
|
1543
|
+
yield node;
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
public *getTakeProfitLimits(
|
|
1549
|
+
marketIndex: number,
|
|
1550
|
+
marketType: MarketType,
|
|
1551
|
+
direction: PositionDirection
|
|
1552
|
+
): Generator<DLOBNode> {
|
|
1553
|
+
for (const node of this.getTakeProfits(
|
|
1554
|
+
marketIndex,
|
|
1555
|
+
marketType,
|
|
1556
|
+
direction
|
|
1557
|
+
)) {
|
|
1558
|
+
if (isVariant(node.order.orderType, 'triggerLimit')) {
|
|
1559
|
+
yield node;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1467
1564
|
public findNodesToTrigger(
|
|
1468
1565
|
marketIndex: number,
|
|
1469
1566
|
slot: number,
|
|
@@ -1512,32 +1609,25 @@ export class DLOB {
|
|
|
1512
1609
|
return nodesToTrigger;
|
|
1513
1610
|
}
|
|
1514
1611
|
|
|
1515
|
-
public
|
|
1516
|
-
sdkConfig: any,
|
|
1612
|
+
public printTop(
|
|
1517
1613
|
driftClient: DriftClient,
|
|
1518
1614
|
slotSubscriber: SlotSubscriber,
|
|
1519
1615
|
marketIndex: number,
|
|
1520
1616
|
marketType: MarketType
|
|
1521
1617
|
) {
|
|
1522
1618
|
if (isVariant(marketType, 'perp')) {
|
|
1523
|
-
const market = driftClient.getPerpMarketAccount(marketIndex);
|
|
1524
|
-
|
|
1525
1619
|
const slot = slotSubscriber.getSlot();
|
|
1526
1620
|
const oraclePriceData =
|
|
1527
1621
|
driftClient.getOracleDataForPerpMarket(marketIndex);
|
|
1528
|
-
const fallbackAsk = calculateAskPrice(market, oraclePriceData);
|
|
1529
|
-
const fallbackBid = calculateBidPrice(market, oraclePriceData);
|
|
1530
1622
|
|
|
1531
1623
|
const bestAsk = this.getBestAsk(
|
|
1532
1624
|
marketIndex,
|
|
1533
|
-
fallbackAsk,
|
|
1534
1625
|
slot,
|
|
1535
1626
|
marketType,
|
|
1536
1627
|
oraclePriceData
|
|
1537
1628
|
);
|
|
1538
1629
|
const bestBid = this.getBestBid(
|
|
1539
1630
|
marketIndex,
|
|
1540
|
-
fallbackBid,
|
|
1541
1631
|
slot,
|
|
1542
1632
|
marketType,
|
|
1543
1633
|
oraclePriceData
|
|
@@ -1555,7 +1645,10 @@ export class DLOB {
|
|
|
1555
1645
|
1) *
|
|
1556
1646
|
100.0;
|
|
1557
1647
|
|
|
1558
|
-
|
|
1648
|
+
const name = decodeName(
|
|
1649
|
+
driftClient.getPerpMarketAccount(marketIndex).name
|
|
1650
|
+
);
|
|
1651
|
+
console.log(`Market ${name} Orders`);
|
|
1559
1652
|
console.log(
|
|
1560
1653
|
` Ask`,
|
|
1561
1654
|
convertToNumber(bestAsk, PRICE_PRECISION).toFixed(3),
|
|
@@ -1574,14 +1667,12 @@ export class DLOB {
|
|
|
1574
1667
|
|
|
1575
1668
|
const bestAsk = this.getBestAsk(
|
|
1576
1669
|
marketIndex,
|
|
1577
|
-
undefined,
|
|
1578
1670
|
slot,
|
|
1579
1671
|
marketType,
|
|
1580
1672
|
oraclePriceData
|
|
1581
1673
|
);
|
|
1582
1674
|
const bestBid = this.getBestBid(
|
|
1583
1675
|
marketIndex,
|
|
1584
|
-
undefined,
|
|
1585
1676
|
slot,
|
|
1586
1677
|
marketType,
|
|
1587
1678
|
oraclePriceData
|
|
@@ -1599,7 +1690,10 @@ export class DLOB {
|
|
|
1599
1690
|
1) *
|
|
1600
1691
|
100.0;
|
|
1601
1692
|
|
|
1602
|
-
|
|
1693
|
+
const name = decodeName(
|
|
1694
|
+
driftClient.getSpotMarketAccount(marketIndex).name
|
|
1695
|
+
);
|
|
1696
|
+
console.log(`Market ${name} Orders`);
|
|
1603
1697
|
console.log(
|
|
1604
1698
|
` Ask`,
|
|
1605
1699
|
convertToNumber(bestAsk, PRICE_PRECISION).toFixed(3),
|