@drift-labs/sdk 2.26.0-beta.0 → 2.26.0-beta.2
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/examples/phoenix.ts +40 -0
- package/lib/addresses/pda.d.ts +0 -1
- package/lib/adminClient.d.ts +0 -1
- package/lib/constants/numericConstants.d.ts +59 -61
- package/lib/constants/spotMarkets.d.ts +0 -1
- package/lib/dlob/DLOB.d.ts +38 -3
- package/lib/dlob/DLOB.js +69 -0
- package/lib/dlob/DLOBApiClient.js +1 -1
- package/lib/dlob/DLOBNode.d.ts +0 -1
- package/lib/dlob/DLOBSubscriber.d.ts +34 -0
- package/lib/dlob/DLOBSubscriber.js +100 -0
- package/lib/dlob/NodeList.d.ts +0 -1
- package/lib/dlob/orderBookLevels.d.ts +44 -0
- package/lib/dlob/orderBookLevels.js +137 -0
- package/lib/dlob/types.d.ts +2 -0
- package/lib/driftClient.d.ts +28 -11
- package/lib/driftClient.js +158 -55
- package/lib/driftClientConfig.d.ts +3 -0
- package/lib/factory/bigNum.d.ts +7 -8
- package/lib/idl/drift.json +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +3 -0
- package/lib/math/amm.d.ts +1 -2
- package/lib/math/auction.d.ts +0 -1
- package/lib/math/conversion.d.ts +1 -2
- package/lib/math/funding.d.ts +0 -1
- package/lib/math/insurance.d.ts +0 -1
- package/lib/math/margin.d.ts +0 -1
- package/lib/math/market.d.ts +0 -1
- package/lib/math/oracles.d.ts +0 -1
- package/lib/math/orders.d.ts +0 -1
- package/lib/math/position.d.ts +0 -1
- package/lib/math/repeg.d.ts +0 -1
- package/lib/math/spotBalance.d.ts +0 -1
- package/lib/math/spotMarket.d.ts +0 -1
- package/lib/math/spotPosition.d.ts +0 -1
- package/lib/math/trade.d.ts +0 -1
- package/lib/math/utils.d.ts +0 -1
- package/lib/oracles/pythClient.d.ts +1 -2
- package/lib/oracles/types.d.ts +0 -1
- package/lib/orderParams.d.ts +0 -1
- package/lib/phoenix/phoenixFulfillmentConfigMap.d.ts +10 -0
- package/lib/phoenix/phoenixFulfillmentConfigMap.js +17 -0
- package/lib/phoenix/phoenixSubscriber.d.ts +34 -0
- package/lib/phoenix/phoenixSubscriber.js +79 -0
- package/lib/serum/serumSubscriber.d.ts +5 -2
- package/lib/serum/serumSubscriber.js +22 -0
- package/lib/tokenFaucet.d.ts +0 -1
- package/lib/types.d.ts +1 -1
- package/lib/user.d.ts +0 -1
- package/package.json +1 -1
- package/src/assert/assert.js +9 -0
- package/src/dlob/DLOB.ts +177 -17
- package/src/dlob/DLOBApiClient.ts +3 -1
- package/src/dlob/DLOBSubscriber.ts +141 -0
- package/src/dlob/orderBookLevels.ts +243 -0
- package/src/dlob/types.ts +2 -0
- package/src/driftClient.ts +231 -66
- package/src/driftClientConfig.ts +3 -0
- package/src/idl/drift.json +1 -1
- package/src/index.ts +3 -0
- package/src/phoenix/phoenixFulfillmentConfigMap.ts +26 -0
- package/src/phoenix/phoenixSubscriber.ts +156 -0
- package/src/serum/serumSubscriber.ts +27 -1
- package/src/token/index.js +38 -0
- package/src/types.ts +1 -0
- package/src/util/computeUnits.js +27 -0
- package/src/util/getTokenAddress.js +9 -0
- package/src/util/promiseTimeout.js +14 -0
- package/src/util/tps.js +27 -0
- package/tests/dlob/helpers.ts +3 -0
package/lib/index.d.ts
CHANGED
|
@@ -53,6 +53,8 @@ export * from './config';
|
|
|
53
53
|
export * from './constants/numericConstants';
|
|
54
54
|
export * from './serum/serumSubscriber';
|
|
55
55
|
export * from './serum/serumFulfillmentConfigMap';
|
|
56
|
+
export * from './phoenix/phoenixSubscriber';
|
|
57
|
+
export * from './phoenix/phoenixFulfillmentConfigMap';
|
|
56
58
|
export * from './tx/retryTxSender';
|
|
57
59
|
export * from './util/computeUnits';
|
|
58
60
|
export * from './util/tps';
|
|
@@ -66,6 +68,7 @@ export * from './dlob/DLOBOrders';
|
|
|
66
68
|
export * from './dlob/NodeList';
|
|
67
69
|
export * from './dlob/DLOBSubscriber';
|
|
68
70
|
export * from './dlob/types';
|
|
71
|
+
export * from './dlob/orderBookLevels';
|
|
69
72
|
export * from './userMap/userMap';
|
|
70
73
|
export * from './userMap/userStatsMap';
|
|
71
74
|
export * from './math/bankruptcy';
|
package/lib/index.js
CHANGED
|
@@ -77,6 +77,8 @@ __exportStar(require("./config"), exports);
|
|
|
77
77
|
__exportStar(require("./constants/numericConstants"), exports);
|
|
78
78
|
__exportStar(require("./serum/serumSubscriber"), exports);
|
|
79
79
|
__exportStar(require("./serum/serumFulfillmentConfigMap"), exports);
|
|
80
|
+
__exportStar(require("./phoenix/phoenixSubscriber"), exports);
|
|
81
|
+
__exportStar(require("./phoenix/phoenixFulfillmentConfigMap"), exports);
|
|
80
82
|
__exportStar(require("./tx/retryTxSender"), exports);
|
|
81
83
|
__exportStar(require("./util/computeUnits"), exports);
|
|
82
84
|
__exportStar(require("./util/tps"), exports);
|
|
@@ -90,6 +92,7 @@ __exportStar(require("./dlob/DLOBOrders"), exports);
|
|
|
90
92
|
__exportStar(require("./dlob/NodeList"), exports);
|
|
91
93
|
__exportStar(require("./dlob/DLOBSubscriber"), exports);
|
|
92
94
|
__exportStar(require("./dlob/types"), exports);
|
|
95
|
+
__exportStar(require("./dlob/orderBookLevels"), exports);
|
|
93
96
|
__exportStar(require("./userMap/userMap"), exports);
|
|
94
97
|
__exportStar(require("./userMap/userStatsMap"), exports);
|
|
95
98
|
__exportStar(require("./math/bankruptcy"), exports);
|
package/lib/math/amm.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
import { BN } from '@coral-xyz/anchor';
|
|
3
2
|
import { AMM, PositionDirection, SwapDirection, PerpMarketAccount } from '../types';
|
|
4
3
|
import { OraclePriceData } from '../oracles/types';
|
|
@@ -87,7 +86,7 @@ export declare function getSwapDirection(inputAssetType: AssetType, positionDire
|
|
|
87
86
|
* @param market
|
|
88
87
|
* @returns cost : Precision PRICE_PRECISION
|
|
89
88
|
*/
|
|
90
|
-
export declare function calculateTerminalPrice(market: PerpMarketAccount):
|
|
89
|
+
export declare function calculateTerminalPrice(market: PerpMarketAccount): any;
|
|
91
90
|
export declare function calculateMaxBaseAssetAmountToTrade(amm: AMM, limit_price: BN, direction: PositionDirection, oraclePriceData?: OraclePriceData, now?: BN): [BN, PositionDirection];
|
|
92
91
|
export declare function calculateQuoteAssetAmountSwapped(quoteAssetReserves: BN, pegMultiplier: BN, swapDirection: SwapDirection): BN;
|
|
93
92
|
export declare function calculateMaxBaseAssetAmountFillable(amm: AMM, orderDirection: PositionDirection): BN;
|
package/lib/math/auction.d.ts
CHANGED
package/lib/math/conversion.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const convertToNumber: (bigNumber: BN, precision?: BN) => number;
|
|
1
|
+
export declare const convertToNumber: (bigNumber: BN, precision?: BN) => any;
|
package/lib/math/funding.d.ts
CHANGED
package/lib/math/insurance.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
import { BN } from '../index';
|
|
3
2
|
export declare function stakeAmountToShares(amount: BN, totalIfShares: BN, insuranceFundVaultBalance: BN): BN;
|
|
4
3
|
export declare function unstakeSharesToAmount(nShares: BN, totalIfShares: BN, insuranceFundVaultBalance: BN): BN;
|
package/lib/math/margin.d.ts
CHANGED
package/lib/math/market.d.ts
CHANGED
package/lib/math/oracles.d.ts
CHANGED
package/lib/math/orders.d.ts
CHANGED
package/lib/math/position.d.ts
CHANGED
package/lib/math/repeg.d.ts
CHANGED
package/lib/math/spotMarket.d.ts
CHANGED
package/lib/math/trade.d.ts
CHANGED
package/lib/math/utils.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
/// <reference types="node" />
|
|
3
2
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
4
3
|
import { OracleClient, OraclePriceData } from './types';
|
|
@@ -7,7 +6,7 @@ export declare class PythClient implements OracleClient {
|
|
|
7
6
|
private connection;
|
|
8
7
|
private multiple;
|
|
9
8
|
private stableCoin;
|
|
10
|
-
constructor(connection: Connection, multiple?:
|
|
9
|
+
constructor(connection: Connection, multiple?: any, stableCoin?: boolean);
|
|
11
10
|
getOraclePriceData(pricePublicKey: PublicKey): Promise<OraclePriceData>;
|
|
12
11
|
getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData;
|
|
13
12
|
}
|
package/lib/oracles/types.d.ts
CHANGED
package/lib/orderParams.d.ts
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { PhoenixV1FulfillmentConfigAccount } from '../types';
|
|
3
|
+
import { DriftClient } from '../driftClient';
|
|
4
|
+
export declare class PhoenixFulfillmentConfigMap {
|
|
5
|
+
driftClient: DriftClient;
|
|
6
|
+
map: Map<number, PhoenixV1FulfillmentConfigAccount>;
|
|
7
|
+
constructor(driftClient: DriftClient);
|
|
8
|
+
add(marketIndex: number, phoenixMarketAddress: PublicKey): Promise<void>;
|
|
9
|
+
get(marketIndex: number): PhoenixV1FulfillmentConfigAccount;
|
|
10
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PhoenixFulfillmentConfigMap = void 0;
|
|
4
|
+
class PhoenixFulfillmentConfigMap {
|
|
5
|
+
constructor(driftClient) {
|
|
6
|
+
this.map = new Map();
|
|
7
|
+
this.driftClient = driftClient;
|
|
8
|
+
}
|
|
9
|
+
async add(marketIndex, phoenixMarketAddress) {
|
|
10
|
+
const account = await this.driftClient.getPhoenixV1FulfillmentConfig(phoenixMarketAddress);
|
|
11
|
+
this.map.set(marketIndex, account);
|
|
12
|
+
}
|
|
13
|
+
get(marketIndex) {
|
|
14
|
+
return this.map.get(marketIndex);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.PhoenixFulfillmentConfigMap = PhoenixFulfillmentConfigMap;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Connection, PublicKey } from '@solana/web3.js';
|
|
2
|
+
import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
|
|
3
|
+
import { MarketData, Client } from '@ellipsis-labs/phoenix-sdk';
|
|
4
|
+
import { BN } from '@coral-xyz/anchor';
|
|
5
|
+
export type PhoenixMarketSubscriberConfig = {
|
|
6
|
+
connection: Connection;
|
|
7
|
+
programId: PublicKey;
|
|
8
|
+
marketAddress: PublicKey;
|
|
9
|
+
accountSubscription: {
|
|
10
|
+
type: 'polling';
|
|
11
|
+
accountLoader: BulkAccountLoader;
|
|
12
|
+
} | {
|
|
13
|
+
type: 'websocket';
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
export declare class PhoenixSubscriber {
|
|
17
|
+
connection: Connection;
|
|
18
|
+
client: Client;
|
|
19
|
+
programId: PublicKey;
|
|
20
|
+
marketAddress: PublicKey;
|
|
21
|
+
subscriptionType: 'polling' | 'websocket';
|
|
22
|
+
accountLoader: BulkAccountLoader | undefined;
|
|
23
|
+
market: MarketData;
|
|
24
|
+
marketCallbackId: string | number;
|
|
25
|
+
clockCallbackId: string | number;
|
|
26
|
+
subscribed: boolean;
|
|
27
|
+
lastSlot: number;
|
|
28
|
+
lastUnixTimestamp: number;
|
|
29
|
+
constructor(config: PhoenixMarketSubscriberConfig);
|
|
30
|
+
subscribe(): Promise<void>;
|
|
31
|
+
getBestBid(): BN;
|
|
32
|
+
getBestAsk(): BN;
|
|
33
|
+
unsubscribe(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PhoenixSubscriber = void 0;
|
|
4
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
5
|
+
const phoenix_sdk_1 = require("@ellipsis-labs/phoenix-sdk");
|
|
6
|
+
const numericConstants_1 = require("../constants/numericConstants");
|
|
7
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
8
|
+
class PhoenixSubscriber {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.connection = config.connection;
|
|
11
|
+
this.programId = config.programId;
|
|
12
|
+
this.marketAddress = config.marketAddress;
|
|
13
|
+
if (config.accountSubscription.type === 'polling') {
|
|
14
|
+
this.subscriptionType = 'polling';
|
|
15
|
+
this.accountLoader = config.accountSubscription.accountLoader;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
this.subscriptionType = 'websocket';
|
|
19
|
+
}
|
|
20
|
+
this.lastSlot = 0;
|
|
21
|
+
this.lastUnixTimestamp = 0;
|
|
22
|
+
}
|
|
23
|
+
async subscribe() {
|
|
24
|
+
if (this.subscribed) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
this.market = (0, phoenix_sdk_1.deserializeMarketData)((await this.connection.getAccountInfo(this.marketAddress, 'confirmed'))
|
|
28
|
+
.data);
|
|
29
|
+
const clock = (0, phoenix_sdk_1.deserializeClockData)((await this.connection.getAccountInfo(web3_js_1.SYSVAR_CLOCK_PUBKEY, 'confirmed'))
|
|
30
|
+
.data);
|
|
31
|
+
this.lastUnixTimestamp = (0, phoenix_sdk_1.toNum)(clock.unixTimestamp);
|
|
32
|
+
if (this.subscriptionType === 'websocket') {
|
|
33
|
+
this.marketCallbackId = this.connection.onAccountChange(this.marketAddress, (accountInfo, _ctx) => {
|
|
34
|
+
this.market = (0, phoenix_sdk_1.deserializeMarketData)(accountInfo.data);
|
|
35
|
+
});
|
|
36
|
+
this.clockCallbackId = this.connection.onAccountChange(web3_js_1.SYSVAR_CLOCK_PUBKEY, (accountInfo, ctx) => {
|
|
37
|
+
this.lastSlot = ctx.slot;
|
|
38
|
+
const clock = (0, phoenix_sdk_1.deserializeClockData)(accountInfo.data);
|
|
39
|
+
this.lastUnixTimestamp = (0, phoenix_sdk_1.toNum)(clock.unixTimestamp);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
this.marketCallbackId = await this.accountLoader.addAccount(this.marketAddress, (buffer, slot) => {
|
|
44
|
+
this.lastSlot = slot;
|
|
45
|
+
this.market = (0, phoenix_sdk_1.deserializeMarketData)(buffer);
|
|
46
|
+
});
|
|
47
|
+
this.clockCallbackId = await this.accountLoader.addAccount(web3_js_1.SYSVAR_CLOCK_PUBKEY, (buffer, slot) => {
|
|
48
|
+
this.lastSlot = slot;
|
|
49
|
+
const clock = (0, phoenix_sdk_1.deserializeClockData)(buffer);
|
|
50
|
+
this.lastUnixTimestamp = (0, phoenix_sdk_1.toNum)(clock.unixTimestamp);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
this.subscribed = true;
|
|
54
|
+
}
|
|
55
|
+
getBestBid() {
|
|
56
|
+
const ladder = (0, phoenix_sdk_1.getMarketUiLadder)(this.market, this.lastSlot, this.lastUnixTimestamp, 1);
|
|
57
|
+
return new anchor_1.BN(Math.floor(ladder.bids[0][0] * numericConstants_1.PRICE_PRECISION.toNumber()));
|
|
58
|
+
}
|
|
59
|
+
getBestAsk() {
|
|
60
|
+
const ladder = (0, phoenix_sdk_1.getMarketUiLadder)(this.market, this.lastSlot, this.lastUnixTimestamp, 1);
|
|
61
|
+
return new anchor_1.BN(Math.floor(ladder.asks[0][0] * numericConstants_1.PRICE_PRECISION.toNumber()));
|
|
62
|
+
}
|
|
63
|
+
async unsubscribe() {
|
|
64
|
+
if (!this.subscribed) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// remove listeners
|
|
68
|
+
if (this.subscriptionType === 'websocket') {
|
|
69
|
+
await this.connection.removeAccountChangeListener(this.marketCallbackId);
|
|
70
|
+
await this.connection.removeAccountChangeListener(this.clockCallbackId);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
this.accountLoader.removeAccount(this.marketAddress, this.marketCallbackId);
|
|
74
|
+
this.accountLoader.removeAccount(web3_js_1.SYSVAR_CLOCK_PUBKEY, this.clockCallbackId);
|
|
75
|
+
}
|
|
76
|
+
this.subscribed = false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.PhoenixSubscriber = PhoenixSubscriber;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
2
|
import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
|
|
4
3
|
import { Market, Orderbook } from '@project-serum/serum';
|
|
5
4
|
import { SerumMarketSubscriberConfig } from './types';
|
|
6
5
|
import { BN } from '@coral-xyz/anchor';
|
|
7
|
-
|
|
6
|
+
import { L2Level, L2OrderBookGenerator } from '../dlob/orderBookLevels';
|
|
7
|
+
export declare class SerumSubscriber implements L2OrderBookGenerator {
|
|
8
8
|
connection: Connection;
|
|
9
9
|
programId: PublicKey;
|
|
10
10
|
marketAddress: PublicKey;
|
|
@@ -24,5 +24,8 @@ export declare class SerumSubscriber {
|
|
|
24
24
|
subscribe(): Promise<void>;
|
|
25
25
|
getBestBid(): BN | undefined;
|
|
26
26
|
getBestAsk(): BN | undefined;
|
|
27
|
+
getL2Bids(): Generator<L2Level>;
|
|
28
|
+
getL2Asks(): Generator<L2Level>;
|
|
29
|
+
getL2Levels(side: 'bids' | 'asks'): Generator<L2Level>;
|
|
27
30
|
unsubscribe(): Promise<void>;
|
|
28
31
|
}
|
|
@@ -66,6 +66,28 @@ class SerumSubscriber {
|
|
|
66
66
|
}
|
|
67
67
|
return new anchor_1.BN(bestAsk[0] * numericConstants_1.PRICE_PRECISION.toNumber());
|
|
68
68
|
}
|
|
69
|
+
getL2Bids() {
|
|
70
|
+
return this.getL2Levels('bids');
|
|
71
|
+
}
|
|
72
|
+
getL2Asks() {
|
|
73
|
+
return this.getL2Levels('asks');
|
|
74
|
+
}
|
|
75
|
+
*getL2Levels(side) {
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
const basePrecision = Math.pow(10, this.market._baseSplTokenDecimals);
|
|
78
|
+
const pricePrecision = numericConstants_1.PRICE_PRECISION.toNumber();
|
|
79
|
+
for (let { price, size } of this[side].items(side === 'bids')) {
|
|
80
|
+
price = new anchor_1.BN(price * pricePrecision);
|
|
81
|
+
size = new anchor_1.BN(size * basePrecision);
|
|
82
|
+
yield {
|
|
83
|
+
price,
|
|
84
|
+
size,
|
|
85
|
+
sources: {
|
|
86
|
+
serum: size,
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
69
91
|
async unsubscribe() {
|
|
70
92
|
if (!this.subscribed) {
|
|
71
93
|
return;
|
package/lib/tokenFaucet.d.ts
CHANGED
package/lib/types.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference types="bn.js" />
|
|
2
1
|
import { PublicKey, Transaction } from '@solana/web3.js';
|
|
3
2
|
import { BN } from '.';
|
|
4
3
|
export declare enum ExchangeStatus {
|
|
@@ -661,6 +660,7 @@ export type HistoricalIndexData = {
|
|
|
661
660
|
export type SpotMarketAccount = {
|
|
662
661
|
status: MarketStatus;
|
|
663
662
|
assetTier: AssetTier;
|
|
663
|
+
name: number[];
|
|
664
664
|
marketIndex: number;
|
|
665
665
|
pubkey: PublicKey;
|
|
666
666
|
mint: PublicKey;
|
package/lib/user.d.ts
CHANGED
package/package.json
CHANGED
package/src/dlob/DLOB.ts
CHANGED
|
@@ -1,37 +1,48 @@
|
|
|
1
1
|
import { getOrderSignature, getVammNodeGenerator, NodeList } from './NodeList';
|
|
2
2
|
import {
|
|
3
|
-
MarketType,
|
|
4
3
|
BN,
|
|
5
4
|
calculateAskPrice,
|
|
6
5
|
calculateBidPrice,
|
|
7
|
-
DriftClient,
|
|
8
6
|
convertToNumber,
|
|
9
|
-
|
|
7
|
+
DLOBNode,
|
|
8
|
+
DLOBNodeType,
|
|
9
|
+
DriftClient,
|
|
10
|
+
getLimitPrice,
|
|
11
|
+
getVariant,
|
|
12
|
+
isFallbackAvailableLiquiditySource,
|
|
10
13
|
isOneOfVariant,
|
|
14
|
+
isOrderExpired,
|
|
15
|
+
isRestingLimitOrder,
|
|
16
|
+
isTakingOrder,
|
|
17
|
+
isTriggered,
|
|
11
18
|
isVariant,
|
|
12
|
-
|
|
19
|
+
MarketType,
|
|
20
|
+
MarketTypeStr,
|
|
21
|
+
mustBeTriggered,
|
|
22
|
+
OraclePriceData,
|
|
13
23
|
Order,
|
|
14
|
-
|
|
15
|
-
|
|
24
|
+
OrderActionRecord,
|
|
25
|
+
OrderRecord,
|
|
16
26
|
PerpMarketAccount,
|
|
17
|
-
|
|
27
|
+
PRICE_PRECISION,
|
|
18
28
|
SlotSubscriber,
|
|
19
|
-
|
|
29
|
+
SpotMarketAccount,
|
|
20
30
|
StateAccount,
|
|
21
|
-
|
|
22
|
-
isTriggered,
|
|
23
|
-
getLimitPrice,
|
|
31
|
+
TriggerOrderNode,
|
|
24
32
|
UserMap,
|
|
25
|
-
OrderRecord,
|
|
26
|
-
OrderActionRecord,
|
|
27
|
-
isRestingLimitOrder,
|
|
28
|
-
isTakingOrder,
|
|
29
|
-
isFallbackAvailableLiquiditySource,
|
|
30
33
|
} from '..';
|
|
31
34
|
import { PublicKey } from '@solana/web3.js';
|
|
32
|
-
import { DLOBNode, DLOBNodeType, TriggerOrderNode } from '..';
|
|
33
35
|
import { ammPaused, exchangePaused, fillPaused } from '../math/exchangeStatus';
|
|
34
36
|
import { DLOBOrders } from './DLOBOrders';
|
|
37
|
+
import {
|
|
38
|
+
createL2Levels,
|
|
39
|
+
getL2GeneratorFromDLOBNodes,
|
|
40
|
+
L2OrderBook,
|
|
41
|
+
L2OrderBookGenerator,
|
|
42
|
+
L3Level,
|
|
43
|
+
L3OrderBook,
|
|
44
|
+
mergeL2LevelGenerators,
|
|
45
|
+
} from './orderBookLevels';
|
|
35
46
|
|
|
36
47
|
export type MarketNodeLists = {
|
|
37
48
|
restingLimit: {
|
|
@@ -1689,4 +1700,153 @@ export class DLOB {
|
|
|
1689
1700
|
yield nodeLists.trigger.below;
|
|
1690
1701
|
}
|
|
1691
1702
|
}
|
|
1703
|
+
|
|
1704
|
+
/**
|
|
1705
|
+
* Get an L2 view of the order book for a given market.
|
|
1706
|
+
*
|
|
1707
|
+
* @param marketIndex
|
|
1708
|
+
* @param marketType
|
|
1709
|
+
* @param slot
|
|
1710
|
+
* @param oraclePriceData
|
|
1711
|
+
* @param depth how many levels of the order book to return
|
|
1712
|
+
* @param fallbackAsk best ask for fallback liquidity, only relevant for perps
|
|
1713
|
+
* @param fallbackBid best bid for fallback liquidity, only relevant for perps
|
|
1714
|
+
* @param fallbackL2Generators L2 generators for fallback liquidity e.g. vAMM {@link getVammL2Generator}, openbook {@link SerumSubscriber}
|
|
1715
|
+
*/
|
|
1716
|
+
public getL2({
|
|
1717
|
+
marketIndex,
|
|
1718
|
+
marketType,
|
|
1719
|
+
slot,
|
|
1720
|
+
oraclePriceData,
|
|
1721
|
+
depth,
|
|
1722
|
+
fallbackAsk,
|
|
1723
|
+
fallbackBid,
|
|
1724
|
+
fallbackL2Generators = [],
|
|
1725
|
+
}: {
|
|
1726
|
+
marketIndex: number;
|
|
1727
|
+
marketType: MarketType;
|
|
1728
|
+
slot: number;
|
|
1729
|
+
oraclePriceData: OraclePriceData;
|
|
1730
|
+
depth: number;
|
|
1731
|
+
fallbackAsk?: BN;
|
|
1732
|
+
fallbackBid?: BN;
|
|
1733
|
+
fallbackL2Generators?: L2OrderBookGenerator[];
|
|
1734
|
+
}): L2OrderBook {
|
|
1735
|
+
const makerAskL2LevelGenerator = getL2GeneratorFromDLOBNodes(
|
|
1736
|
+
this.getMakerLimitAsks(
|
|
1737
|
+
marketIndex,
|
|
1738
|
+
slot,
|
|
1739
|
+
marketType,
|
|
1740
|
+
oraclePriceData,
|
|
1741
|
+
fallbackBid
|
|
1742
|
+
),
|
|
1743
|
+
oraclePriceData,
|
|
1744
|
+
slot
|
|
1745
|
+
);
|
|
1746
|
+
|
|
1747
|
+
const fallbackAskGenerators = fallbackL2Generators.map(
|
|
1748
|
+
(fallbackL2Generator) => {
|
|
1749
|
+
return fallbackL2Generator.getL2Asks();
|
|
1750
|
+
}
|
|
1751
|
+
);
|
|
1752
|
+
|
|
1753
|
+
const askL2LevelGenerator = mergeL2LevelGenerators(
|
|
1754
|
+
[makerAskL2LevelGenerator, ...fallbackAskGenerators],
|
|
1755
|
+
(a, b) => {
|
|
1756
|
+
return a.price.lt(b.price);
|
|
1757
|
+
}
|
|
1758
|
+
);
|
|
1759
|
+
|
|
1760
|
+
const asks = createL2Levels(askL2LevelGenerator, depth);
|
|
1761
|
+
|
|
1762
|
+
const makerBidGenerator = getL2GeneratorFromDLOBNodes(
|
|
1763
|
+
this.getMakerLimitBids(
|
|
1764
|
+
marketIndex,
|
|
1765
|
+
slot,
|
|
1766
|
+
marketType,
|
|
1767
|
+
oraclePriceData,
|
|
1768
|
+
fallbackAsk
|
|
1769
|
+
),
|
|
1770
|
+
oraclePriceData,
|
|
1771
|
+
slot
|
|
1772
|
+
);
|
|
1773
|
+
|
|
1774
|
+
const fallbackBidGenerators = fallbackL2Generators.map((fallbackOrders) => {
|
|
1775
|
+
return fallbackOrders.getL2Bids();
|
|
1776
|
+
});
|
|
1777
|
+
|
|
1778
|
+
const bidL2LevelGenerator = mergeL2LevelGenerators(
|
|
1779
|
+
[makerBidGenerator, ...fallbackBidGenerators],
|
|
1780
|
+
(a, b) => {
|
|
1781
|
+
return a.price.gt(b.price);
|
|
1782
|
+
}
|
|
1783
|
+
);
|
|
1784
|
+
|
|
1785
|
+
const bids = createL2Levels(bidL2LevelGenerator, depth);
|
|
1786
|
+
|
|
1787
|
+
return {
|
|
1788
|
+
bids,
|
|
1789
|
+
asks,
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
/**
|
|
1794
|
+
* Get an L3 view of the order book for a given market. Does not include fallback liquidity sources
|
|
1795
|
+
*
|
|
1796
|
+
* @param marketIndex
|
|
1797
|
+
* @param marketType
|
|
1798
|
+
* @param slot
|
|
1799
|
+
* @param oraclePriceData
|
|
1800
|
+
*/
|
|
1801
|
+
public getL3({
|
|
1802
|
+
marketIndex,
|
|
1803
|
+
marketType,
|
|
1804
|
+
slot,
|
|
1805
|
+
oraclePriceData,
|
|
1806
|
+
}: {
|
|
1807
|
+
marketIndex: number;
|
|
1808
|
+
marketType: MarketType;
|
|
1809
|
+
slot: number;
|
|
1810
|
+
oraclePriceData: OraclePriceData;
|
|
1811
|
+
}): L3OrderBook {
|
|
1812
|
+
const bids: L3Level[] = [];
|
|
1813
|
+
const asks: L3Level[] = [];
|
|
1814
|
+
|
|
1815
|
+
const restingAsks = this.getRestingLimitAsks(
|
|
1816
|
+
marketIndex,
|
|
1817
|
+
slot,
|
|
1818
|
+
marketType,
|
|
1819
|
+
oraclePriceData
|
|
1820
|
+
);
|
|
1821
|
+
|
|
1822
|
+
for (const ask of restingAsks) {
|
|
1823
|
+
asks.push({
|
|
1824
|
+
price: ask.getPrice(oraclePriceData, slot),
|
|
1825
|
+
size: ask.order.baseAssetAmount.sub(ask.order.baseAssetAmountFilled),
|
|
1826
|
+
maker: ask.userAccount,
|
|
1827
|
+
orderId: ask.order.orderId,
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
const restingBids = this.getRestingLimitBids(
|
|
1832
|
+
marketIndex,
|
|
1833
|
+
slot,
|
|
1834
|
+
marketType,
|
|
1835
|
+
oraclePriceData
|
|
1836
|
+
);
|
|
1837
|
+
|
|
1838
|
+
for (const bid of restingBids) {
|
|
1839
|
+
bids.push({
|
|
1840
|
+
price: bid.getPrice(oraclePriceData, slot),
|
|
1841
|
+
size: bid.order.baseAssetAmount.sub(bid.order.baseAssetAmountFilled),
|
|
1842
|
+
maker: bid.userAccount,
|
|
1843
|
+
orderId: bid.order.orderId,
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
return {
|
|
1848
|
+
bids,
|
|
1849
|
+
asks,
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1692
1852
|
}
|
|
@@ -19,7 +19,9 @@ export class DLOBApiClient {
|
|
|
19
19
|
public async getDLOB(slot: number): Promise<DLOB> {
|
|
20
20
|
const r = await fetch(this.url);
|
|
21
21
|
if (!r.ok) {
|
|
22
|
-
throw new Error(
|
|
22
|
+
throw new Error(
|
|
23
|
+
`Failed to fetch DLOB from ${this.url}. Status: ${r.status}, ${r.statusText}`
|
|
24
|
+
);
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
const resp = await r.json();
|