@drift-labs/sdk 2.17.0 → 2.18.0-beta.1
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/lib/constants/perpMarkets.js +10 -0
- package/lib/dlob/DLOB.d.ts +32 -26
- package/lib/dlob/DLOB.js +246 -173
- package/lib/dlob/DLOBNode.d.ts +11 -5
- package/lib/dlob/DLOBNode.js +13 -5
- package/lib/driftClient.js +5 -10
- package/lib/examples/loadDlob.js +1 -1
- package/lib/factory/oracleClient.js +4 -0
- package/lib/idl/drift.json +4 -1
- package/lib/math/auction.d.ts +1 -0
- package/lib/math/auction.js +9 -2
- package/lib/math/orders.d.ts +2 -0
- package/lib/math/orders.js +11 -2
- package/lib/math/spotBalance.js +1 -1
- package/lib/math/trade.d.ts +6 -0
- package/lib/math/trade.js +6 -0
- package/lib/oracles/pythClient.d.ts +4 -3
- package/lib/oracles/pythClient.js +8 -7
- package/lib/types.d.ts +4 -1
- package/lib/types.js +1 -0
- package/lib/user.js +8 -9
- package/package.json +1 -1
- package/src/constants/perpMarkets.ts +10 -0
- package/src/dlob/DLOB.ts +387 -183
- package/src/dlob/DLOBNode.ts +20 -7
- package/src/driftClient.ts +5 -10
- package/src/examples/loadDlob.ts +1 -1
- package/src/factory/oracleClient.ts +5 -0
- package/src/idl/drift.json +4 -1
- package/src/math/auction.ts +13 -1
- package/src/math/orders.ts +14 -1
- package/src/math/spotBalance.ts +1 -1
- package/src/math/trade.ts +6 -0
- package/src/oracles/pythClient.ts +27 -8
- package/src/types.ts +2 -1
- package/src/user.ts +7 -8
- package/tests/dlob/test.ts +800 -82
package/src/dlob/DLOBNode.ts
CHANGED
|
@@ -77,9 +77,18 @@ export abstract class OrderNode implements DLOBNode {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
export class
|
|
81
|
-
next?:
|
|
82
|
-
previous?:
|
|
80
|
+
export class TakingLimitOrderNode extends OrderNode {
|
|
81
|
+
next?: TakingLimitOrderNode;
|
|
82
|
+
previous?: TakingLimitOrderNode;
|
|
83
|
+
|
|
84
|
+
getSortValue(order: Order): BN {
|
|
85
|
+
return order.slot;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class RestingLimitOrderNode extends OrderNode {
|
|
90
|
+
next?: RestingLimitOrderNode;
|
|
91
|
+
previous?: RestingLimitOrderNode;
|
|
83
92
|
|
|
84
93
|
getSortValue(order: Order): BN {
|
|
85
94
|
return order.price;
|
|
@@ -114,14 +123,16 @@ export class TriggerOrderNode extends OrderNode {
|
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
export type DLOBNodeMap = {
|
|
117
|
-
|
|
126
|
+
restingLimit: RestingLimitOrderNode;
|
|
127
|
+
takingLimit: TakingLimitOrderNode;
|
|
118
128
|
floatingLimit: FloatingLimitOrderNode;
|
|
119
129
|
market: MarketOrderNode;
|
|
120
130
|
trigger: TriggerOrderNode;
|
|
121
131
|
};
|
|
122
132
|
|
|
123
133
|
export type DLOBNodeType =
|
|
124
|
-
| '
|
|
134
|
+
| 'restingLimit'
|
|
135
|
+
| 'takingLimit'
|
|
125
136
|
| 'floatingLimit'
|
|
126
137
|
| 'market'
|
|
127
138
|
| ('trigger' & keyof DLOBNodeMap);
|
|
@@ -134,8 +145,10 @@ export function createNode<T extends DLOBNodeType>(
|
|
|
134
145
|
switch (nodeType) {
|
|
135
146
|
case 'floatingLimit':
|
|
136
147
|
return new FloatingLimitOrderNode(order, userAccount);
|
|
137
|
-
case '
|
|
138
|
-
return new
|
|
148
|
+
case 'restingLimit':
|
|
149
|
+
return new RestingLimitOrderNode(order, userAccount);
|
|
150
|
+
case 'takingLimit':
|
|
151
|
+
return new TakingLimitOrderNode(order, userAccount);
|
|
139
152
|
case 'market':
|
|
140
153
|
return new MarketOrderNode(order, userAccount);
|
|
141
154
|
case 'trigger':
|
package/src/driftClient.ts
CHANGED
|
@@ -1046,9 +1046,8 @@ export class DriftClient {
|
|
|
1046
1046
|
): Promise<TransactionSignature> {
|
|
1047
1047
|
const tx = new Transaction();
|
|
1048
1048
|
tx.add(
|
|
1049
|
-
ComputeBudgetProgram.
|
|
1049
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
1050
1050
|
units: 600_000,
|
|
1051
|
-
additionalFee: 0,
|
|
1052
1051
|
})
|
|
1053
1052
|
);
|
|
1054
1053
|
|
|
@@ -1394,9 +1393,8 @@ export class DriftClient {
|
|
|
1394
1393
|
): Promise<TransactionSignature> {
|
|
1395
1394
|
const tx = new Transaction();
|
|
1396
1395
|
tx.add(
|
|
1397
|
-
ComputeBudgetProgram.
|
|
1396
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
1398
1397
|
units: 600_000,
|
|
1399
|
-
additionalFee: 0,
|
|
1400
1398
|
})
|
|
1401
1399
|
);
|
|
1402
1400
|
|
|
@@ -3174,9 +3172,8 @@ export class DriftClient {
|
|
|
3174
3172
|
|
|
3175
3173
|
const tx = new Transaction();
|
|
3176
3174
|
tx.add(
|
|
3177
|
-
ComputeBudgetProgram.
|
|
3175
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
3178
3176
|
units: 1_000_000,
|
|
3179
|
-
additionalFee: 0,
|
|
3180
3177
|
})
|
|
3181
3178
|
);
|
|
3182
3179
|
tx.add(cancelOrderIx);
|
|
@@ -3286,9 +3283,8 @@ export class DriftClient {
|
|
|
3286
3283
|
|
|
3287
3284
|
const tx = new Transaction();
|
|
3288
3285
|
tx.add(
|
|
3289
|
-
ComputeBudgetProgram.
|
|
3286
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
3290
3287
|
units: 1_000_000,
|
|
3291
|
-
additionalFee: 0,
|
|
3292
3288
|
})
|
|
3293
3289
|
);
|
|
3294
3290
|
tx.add(cancelOrderIx);
|
|
@@ -3325,9 +3321,8 @@ export class DriftClient {
|
|
|
3325
3321
|
|
|
3326
3322
|
const tx = new Transaction()
|
|
3327
3323
|
.add(
|
|
3328
|
-
ComputeBudgetProgram.
|
|
3324
|
+
ComputeBudgetProgram.setComputeUnitLimit({
|
|
3329
3325
|
units: 1_000_000,
|
|
3330
|
-
additionalFee: 0,
|
|
3331
3326
|
})
|
|
3332
3327
|
)
|
|
3333
3328
|
.add(...ixs);
|
package/src/examples/loadDlob.ts
CHANGED
|
@@ -64,7 +64,7 @@ const main = async () => {
|
|
|
64
64
|
|
|
65
65
|
console.log('Loading dlob from user map...');
|
|
66
66
|
const dlob = new DLOB();
|
|
67
|
-
await dlob.initFromUserMap(userMap);
|
|
67
|
+
await dlob.initFromUserMap(userMap, bulkAccountLoader.mostRecentSlot);
|
|
68
68
|
|
|
69
69
|
console.log('number of orders', dlob.getDLOBOrders().length);
|
|
70
70
|
|
|
@@ -4,6 +4,7 @@ import { OracleClient } from '../oracles/types';
|
|
|
4
4
|
import { PythClient } from '../oracles/pythClient';
|
|
5
5
|
// import { SwitchboardClient } from '../oracles/switchboardClient';
|
|
6
6
|
import { QuoteAssetOracleClient } from '../oracles/quoteAssetOracleClient';
|
|
7
|
+
import { BN } from '@project-serum/anchor';
|
|
7
8
|
|
|
8
9
|
export function getOracleClient(
|
|
9
10
|
oracleSource: OracleSource,
|
|
@@ -13,6 +14,10 @@ export function getOracleClient(
|
|
|
13
14
|
return new PythClient(connection);
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
if (isVariant(oracleSource, 'pyth1000')) {
|
|
18
|
+
return new PythClient(connection, new BN(1000));
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
// if (isVariant(oracleSource, 'switchboard')) {
|
|
17
22
|
// return new SwitchboardClient(connection);
|
|
18
23
|
// }
|
package/src/idl/drift.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.
|
|
2
|
+
"version": "2.18.0-beta.1",
|
|
3
3
|
"name": "drift",
|
|
4
4
|
"instructions": [
|
|
5
5
|
{
|
|
@@ -6237,6 +6237,9 @@
|
|
|
6237
6237
|
{
|
|
6238
6238
|
"name": "Pyth"
|
|
6239
6239
|
},
|
|
6240
|
+
{
|
|
6241
|
+
"name": "Pyth1000"
|
|
6242
|
+
},
|
|
6240
6243
|
{
|
|
6241
6244
|
"name": "Switchboard"
|
|
6242
6245
|
},
|
package/src/math/auction.ts
CHANGED
|
@@ -9,12 +9,24 @@ export function isAuctionComplete(order: Order, slot: number): boolean {
|
|
|
9
9
|
return new BN(slot).sub(order.slot).gt(new BN(order.auctionDuration));
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
export function isFallbackAvailableLiquiditySource(
|
|
13
|
+
order: Order,
|
|
14
|
+
minAuctionDuration: number,
|
|
15
|
+
slot: number
|
|
16
|
+
): boolean {
|
|
17
|
+
if (minAuctionDuration === 0) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return new BN(slot).sub(order.slot).gt(new BN(minAuctionDuration));
|
|
22
|
+
}
|
|
23
|
+
|
|
12
24
|
export function getAuctionPrice(
|
|
13
25
|
order: Order,
|
|
14
26
|
slot: number,
|
|
15
27
|
oraclePrice: BN
|
|
16
28
|
): BN {
|
|
17
|
-
if (isOneOfVariant(order.orderType, ['market', 'triggerMarket'])) {
|
|
29
|
+
if (isOneOfVariant(order.orderType, ['market', 'triggerMarket', 'limit'])) {
|
|
18
30
|
return getAuctionPriceForFixedAuction(order, slot);
|
|
19
31
|
} else if (isVariant(order.orderType, 'oracle')) {
|
|
20
32
|
return getAuctionPriceForOracleOffsetAuction(order, slot, oraclePrice);
|
package/src/math/orders.ts
CHANGED
|
@@ -153,7 +153,10 @@ export function hasLimitPrice(order: Order, slot: number): boolean {
|
|
|
153
153
|
}
|
|
154
154
|
|
|
155
155
|
export function hasAuctionPrice(order: Order, slot: number): boolean {
|
|
156
|
-
return
|
|
156
|
+
return (
|
|
157
|
+
!isAuctionComplete(order, slot) &&
|
|
158
|
+
(!order.auctionStartPrice.eq(ZERO) || !order.auctionEndPrice.eq(ZERO))
|
|
159
|
+
);
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
export function isFillableByVAMM(
|
|
@@ -280,3 +283,13 @@ export function isTriggered(order: Order): boolean {
|
|
|
280
283
|
'triggeredBelow',
|
|
281
284
|
]);
|
|
282
285
|
}
|
|
286
|
+
|
|
287
|
+
export function isRestingLimitOrder(order: Order, slot: number): boolean {
|
|
288
|
+
return (
|
|
289
|
+
isLimitOrder(order) && (order.postOnly || isAuctionComplete(order, slot))
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export function isTakingOrder(order: Order, slot: number): boolean {
|
|
294
|
+
return isMarketOrder(order) || !isRestingLimitOrder(order, slot);
|
|
295
|
+
}
|
package/src/math/spotBalance.ts
CHANGED
|
@@ -331,7 +331,7 @@ export function calculateWithdrawLimit(
|
|
|
331
331
|
BN.min(
|
|
332
332
|
BN.max(
|
|
333
333
|
marketDepositTokenAmount.div(new BN(6)),
|
|
334
|
-
borrowTokenTwapLive.add(
|
|
334
|
+
borrowTokenTwapLive.add(marketDepositTokenAmount.div(new BN(10)))
|
|
335
335
|
),
|
|
336
336
|
marketDepositTokenAmount.sub(marketDepositTokenAmount.div(new BN(5)))
|
|
337
337
|
)
|
package/src/math/trade.ts
CHANGED
|
@@ -52,6 +52,9 @@ export type PriceImpactUnit =
|
|
|
52
52
|
|
|
53
53
|
/**
|
|
54
54
|
* Calculates avg/max slippage (price impact) for candidate trade
|
|
55
|
+
*
|
|
56
|
+
* @deprecated use calculateEstimatedPerpEntryPrice instead
|
|
57
|
+
*
|
|
55
58
|
* @param direction
|
|
56
59
|
* @param amount
|
|
57
60
|
* @param market
|
|
@@ -200,6 +203,9 @@ export function calculateTradeAcquiredAmounts(
|
|
|
200
203
|
/**
|
|
201
204
|
* calculateTargetPriceTrade
|
|
202
205
|
* simple function for finding arbitraging trades
|
|
206
|
+
*
|
|
207
|
+
* @deprecated
|
|
208
|
+
*
|
|
203
209
|
* @param market
|
|
204
210
|
* @param targetPrice
|
|
205
211
|
* @param pct optional default is 100% gap filling, can set smaller.
|
|
@@ -2,13 +2,15 @@ import { parsePriceData } from '@pythnetwork/client';
|
|
|
2
2
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { OracleClient, OraclePriceData } from './types';
|
|
4
4
|
import { BN } from '@project-serum/anchor';
|
|
5
|
-
import { PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
5
|
+
import { ONE, PRICE_PRECISION, TEN } from '../constants/numericConstants';
|
|
6
6
|
|
|
7
7
|
export class PythClient implements OracleClient {
|
|
8
8
|
private connection: Connection;
|
|
9
|
+
private multiple: BN;
|
|
9
10
|
|
|
10
|
-
public constructor(connection: Connection) {
|
|
11
|
+
public constructor(connection: Connection, multiple = ONE) {
|
|
11
12
|
this.connection = connection;
|
|
13
|
+
this.multiple = multiple;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
public async getOraclePriceData(
|
|
@@ -21,22 +23,39 @@ export class PythClient implements OracleClient {
|
|
|
21
23
|
public getOraclePriceDataFromBuffer(buffer: Buffer): OraclePriceData {
|
|
22
24
|
const priceData = parsePriceData(buffer);
|
|
23
25
|
return {
|
|
24
|
-
price: convertPythPrice(
|
|
26
|
+
price: convertPythPrice(
|
|
27
|
+
priceData.aggregate.price,
|
|
28
|
+
priceData.exponent,
|
|
29
|
+
this.multiple
|
|
30
|
+
),
|
|
25
31
|
slot: new BN(priceData.lastSlot.toString()),
|
|
26
|
-
confidence: convertPythPrice(
|
|
27
|
-
|
|
32
|
+
confidence: convertPythPrice(
|
|
33
|
+
priceData.confidence,
|
|
34
|
+
priceData.exponent,
|
|
35
|
+
this.multiple
|
|
36
|
+
),
|
|
37
|
+
twap: convertPythPrice(
|
|
38
|
+
priceData.twap.value,
|
|
39
|
+
priceData.exponent,
|
|
40
|
+
this.multiple
|
|
41
|
+
),
|
|
28
42
|
twapConfidence: convertPythPrice(
|
|
29
43
|
priceData.twac.value,
|
|
30
|
-
priceData.exponent
|
|
44
|
+
priceData.exponent,
|
|
45
|
+
this.multiple
|
|
31
46
|
),
|
|
32
47
|
hasSufficientNumberOfDataPoints: true,
|
|
33
48
|
};
|
|
34
49
|
}
|
|
35
50
|
}
|
|
36
51
|
|
|
37
|
-
export function convertPythPrice(
|
|
52
|
+
export function convertPythPrice(
|
|
53
|
+
price: number,
|
|
54
|
+
exponent: number,
|
|
55
|
+
multiple: BN
|
|
56
|
+
): BN {
|
|
38
57
|
exponent = Math.abs(exponent);
|
|
39
|
-
const pythPrecision = TEN.pow(new BN(exponent).abs());
|
|
58
|
+
const pythPrecision = TEN.pow(new BN(exponent).abs()).div(multiple);
|
|
40
59
|
return new BN(price * Math.pow(10, exponent))
|
|
41
60
|
.mul(PRICE_PRECISION)
|
|
42
61
|
.div(pythPrecision);
|
package/src/types.ts
CHANGED
|
@@ -76,6 +76,7 @@ export class DepositDirection {
|
|
|
76
76
|
|
|
77
77
|
export class OracleSource {
|
|
78
78
|
static readonly PYTH = { pyth: {} };
|
|
79
|
+
static readonly PYTH_1000 = { pyth1000: {} };
|
|
79
80
|
// static readonly SWITCHBOARD = { switchboard: {} };
|
|
80
81
|
static readonly QUOTE_ASSET = { quoteAsset: {} };
|
|
81
82
|
}
|
|
@@ -222,7 +223,7 @@ export type NewUserRecord = {
|
|
|
222
223
|
ts: BN;
|
|
223
224
|
userAuthority: PublicKey;
|
|
224
225
|
user: PublicKey;
|
|
225
|
-
|
|
226
|
+
subAccountId: number;
|
|
226
227
|
name: number[];
|
|
227
228
|
referrer: PublicKey;
|
|
228
229
|
};
|
package/src/user.ts
CHANGED
|
@@ -697,10 +697,12 @@ export class User {
|
|
|
697
697
|
);
|
|
698
698
|
}
|
|
699
699
|
|
|
700
|
-
if (
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
700
|
+
if (marketIndex === undefined || marketIndex === QUOTE_SPOT_MARKET_INDEX) {
|
|
701
|
+
if (netQuoteValue.gt(ZERO)) {
|
|
702
|
+
totalAssetValue = totalAssetValue.add(netQuoteValue);
|
|
703
|
+
} else {
|
|
704
|
+
totalLiabilityValue = totalLiabilityValue.add(netQuoteValue.abs());
|
|
705
|
+
}
|
|
704
706
|
}
|
|
705
707
|
|
|
706
708
|
return { totalAssetValue, totalLiabilityValue };
|
|
@@ -1771,10 +1773,7 @@ export class User {
|
|
|
1771
1773
|
}
|
|
1772
1774
|
}
|
|
1773
1775
|
|
|
1774
|
-
|
|
1775
|
-
// => to avoid rounding errors when taking max leverage
|
|
1776
|
-
const oneMilli = maxPositionSize.div(QUOTE_PRECISION);
|
|
1777
|
-
return maxPositionSize.sub(oneMilli);
|
|
1776
|
+
return maxPositionSize;
|
|
1778
1777
|
}
|
|
1779
1778
|
|
|
1780
1779
|
/**
|