@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.
@@ -77,9 +77,18 @@ export abstract class OrderNode implements DLOBNode {
77
77
  }
78
78
  }
79
79
 
80
- export class LimitOrderNode extends OrderNode {
81
- next?: LimitOrderNode;
82
- previous?: LimitOrderNode;
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
- limit: LimitOrderNode;
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
- | 'limit'
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 'limit':
138
- return new LimitOrderNode(order, userAccount);
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':
@@ -1046,9 +1046,8 @@ export class DriftClient {
1046
1046
  ): Promise<TransactionSignature> {
1047
1047
  const tx = new Transaction();
1048
1048
  tx.add(
1049
- ComputeBudgetProgram.requestUnits({
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.requestUnits({
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.requestUnits({
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.requestUnits({
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.requestUnits({
3324
+ ComputeBudgetProgram.setComputeUnitLimit({
3329
3325
  units: 1_000_000,
3330
- additionalFee: 0,
3331
3326
  })
3332
3327
  )
3333
3328
  .add(...ixs);
@@ -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
  // }
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.17.0",
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
  },
@@ -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);
@@ -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 isMarketOrder(order) && !isAuctionComplete(order, slot);
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
+ }
@@ -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(borrowTokenTwapLive.div(new BN(5)))
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(priceData.aggregate.price, priceData.exponent),
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(priceData.confidence, priceData.exponent),
27
- twap: convertPythPrice(priceData.twap.value, priceData.exponent),
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(price: number, exponent: number): BN {
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
- subAccount: number;
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 (netQuoteValue.gt(ZERO)) {
701
- totalAssetValue = totalAssetValue.add(netQuoteValue);
702
- } else {
703
- totalLiabilityValue = totalLiabilityValue.add(netQuoteValue.abs());
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
- // subtract oneMillionth of maxPositionSize
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
  /**