@drift-labs/sdk 0.2.0-master.1 → 0.2.0-master.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/lib/math/amm.js CHANGED
@@ -1,25 +1,58 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = void 0;
3
+ exports.calculateQuoteAssetAmountSwapped = exports.calculateMaxBaseAssetAmountToTrade = exports.calculateTerminalPrice = exports.getSwapDirection = exports.calculateSwapOutput = exports.calculateSpreadReserves = exports.calculateSpread = exports.calculateSpreadBN = exports.calculateMaxSpread = exports.calculateEffectiveLeverage = exports.calculateAmmReservesAfterSwap = exports.calculatePrice = exports.calculateBidAskPrice = exports.calculateUpdatedAMMSpreadReserves = exports.calculateUpdatedAMM = exports.calculateNewAmm = exports.calculateOptimalPegAndBudget = exports.calculatePegFromTargetPrice = void 0;
4
4
  const anchor_1 = require("@project-serum/anchor");
5
5
  const numericConstants_1 = require("../constants/numericConstants");
6
6
  const types_1 = require("../types");
7
7
  const assert_1 = require("../assert/assert");
8
8
  const __1 = require("..");
9
9
  const repeg_1 = require("./repeg");
10
- function calculateNewAmm(amm, oraclePriceData) {
11
- let pKNumer = new anchor_1.BN(1);
12
- let pKDenom = new anchor_1.BN(1);
10
+ function calculatePegFromTargetPrice(targetPrice, baseAssetReserve, quoteAssetReserve) {
11
+ return targetPrice
12
+ .mul(baseAssetReserve)
13
+ .div(quoteAssetReserve)
14
+ .add(numericConstants_1.PRICE_DIV_PEG.div(new anchor_1.BN(2)))
15
+ .div(numericConstants_1.PRICE_DIV_PEG);
16
+ }
17
+ exports.calculatePegFromTargetPrice = calculatePegFromTargetPrice;
18
+ function calculateOptimalPegAndBudget(amm, oraclePriceData) {
19
+ const markPriceBefore = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
13
20
  const targetPrice = oraclePriceData.price;
14
- let newPeg = targetPrice
15
- .mul(amm.baseAssetReserve)
16
- .div(amm.quoteAssetReserve)
17
- .add(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION).div(new anchor_1.BN(2)))
18
- .div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
19
- let prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
21
+ const newPeg = calculatePegFromTargetPrice(targetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
22
+ const prePegCost = (0, repeg_1.calculateRepegCost)(amm, newPeg);
20
23
  const totalFeeLB = amm.totalExchangeFee.div(new anchor_1.BN(2));
21
24
  const budget = anchor_1.BN.max(numericConstants_1.ZERO, amm.totalFeeMinusDistributions.sub(totalFeeLB));
22
- if (prePegCost.gt(budget)) {
25
+ if (budget.lt(prePegCost)) {
26
+ const maxPriceSpread = new anchor_1.BN(amm.maxSpread)
27
+ .mul(targetPrice)
28
+ .div(numericConstants_1.BID_ASK_SPREAD_PRECISION);
29
+ let newTargetPrice;
30
+ let newOptimalPeg;
31
+ let newBudget;
32
+ const targetPriceGap = markPriceBefore.sub(targetPrice);
33
+ if (targetPriceGap.abs().gt(maxPriceSpread)) {
34
+ const markAdj = targetPriceGap.abs().sub(maxPriceSpread);
35
+ if (targetPriceGap.lt(new anchor_1.BN(0))) {
36
+ newTargetPrice = markPriceBefore.add(markAdj);
37
+ }
38
+ else {
39
+ newTargetPrice = markPriceBefore.sub(markAdj);
40
+ }
41
+ newOptimalPeg = calculatePegFromTargetPrice(newTargetPrice, amm.baseAssetReserve, amm.quoteAssetReserve);
42
+ newBudget = (0, repeg_1.calculateRepegCost)(amm, newOptimalPeg);
43
+ return [newTargetPrice, newOptimalPeg, newBudget, false];
44
+ }
45
+ }
46
+ return [targetPrice, newPeg, budget, true];
47
+ }
48
+ exports.calculateOptimalPegAndBudget = calculateOptimalPegAndBudget;
49
+ function calculateNewAmm(amm, oraclePriceData) {
50
+ let pKNumer = new anchor_1.BN(1);
51
+ let pKDenom = new anchor_1.BN(1);
52
+ const [targetPrice, _newPeg, budget, checkLowerBound] = calculateOptimalPegAndBudget(amm, oraclePriceData);
53
+ let prePegCost = (0, repeg_1.calculateRepegCost)(amm, _newPeg);
54
+ let newPeg = _newPeg;
55
+ if (prePegCost.gt(budget) && checkLowerBound) {
23
56
  [pKNumer, pKDenom] = [new anchor_1.BN(999), new anchor_1.BN(1000)];
24
57
  const deficitMadeup = (0, repeg_1.calculateAdjustKCost)(amm, pKNumer, pKDenom);
25
58
  (0, assert_1.assert)(deficitMadeup.lte(new anchor_1.BN(0)));
@@ -73,8 +106,14 @@ function calculateUpdatedAMMSpreadReserves(amm, direction, oraclePriceData) {
73
106
  return result;
74
107
  }
75
108
  exports.calculateUpdatedAMMSpreadReserves = calculateUpdatedAMMSpreadReserves;
76
- function calculateBidAskPrice(amm, oraclePriceData) {
77
- const newAmm = calculateUpdatedAMM(amm, oraclePriceData);
109
+ function calculateBidAskPrice(amm, oraclePriceData, withUpdate = true) {
110
+ let newAmm;
111
+ if (withUpdate) {
112
+ newAmm = calculateUpdatedAMM(amm, oraclePriceData);
113
+ }
114
+ else {
115
+ newAmm = amm;
116
+ }
78
117
  const askReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.LONG, oraclePriceData);
79
118
  const bidReserves = calculateSpreadReserves(newAmm, types_1.PositionDirection.SHORT, oraclePriceData);
80
119
  const askPrice = calculatePrice(askReserves.baseAssetReserve, askReserves.quoteAssetReserve, newAmm.pegMultiplier);
@@ -126,6 +165,67 @@ function calculateAmmReservesAfterSwap(amm, inputAssetType, swapAmount, swapDire
126
165
  return [newQuoteAssetReserve, newBaseAssetReserve];
127
166
  }
128
167
  exports.calculateAmmReservesAfterSwap = calculateAmmReservesAfterSwap;
168
+ function calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
169
+ // inventory skew
170
+ const netBaseAssetValue = quoteAssetReserve
171
+ .sub(terminalQuoteAssetReserve)
172
+ .mul(pegMultiplier)
173
+ .div(numericConstants_1.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO);
174
+ const localBaseAssetValue = netBaseAssetAmount
175
+ .mul(markPrice)
176
+ .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
177
+ const effectiveLeverage = localBaseAssetValue.sub(netBaseAssetValue).toNumber() /
178
+ (Math.max(0, totalFeeMinusDistributions.toNumber()) + 1) +
179
+ 1 / numericConstants_1.QUOTE_PRECISION.toNumber();
180
+ return effectiveLeverage;
181
+ }
182
+ exports.calculateEffectiveLeverage = calculateEffectiveLeverage;
183
+ function calculateMaxSpread(marginRatioInitial) {
184
+ const maxTargetSpread = new anchor_1.BN(marginRatioInitial)
185
+ .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION.div(numericConstants_1.MARGIN_PRECISION))
186
+ .toNumber();
187
+ return maxTargetSpread;
188
+ }
189
+ exports.calculateMaxSpread = calculateMaxSpread;
190
+ function calculateSpreadBN(baseSpread, lastOracleMarkSpreadPct, lastOracleConfPct, maxSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions) {
191
+ let longSpread = baseSpread / 2;
192
+ let shortSpread = baseSpread / 2;
193
+ if (lastOracleMarkSpreadPct.gt(numericConstants_1.ZERO)) {
194
+ shortSpread = Math.max(shortSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
195
+ }
196
+ else if (lastOracleMarkSpreadPct.lt(numericConstants_1.ZERO)) {
197
+ longSpread = Math.max(longSpread, lastOracleMarkSpreadPct.abs().toNumber() + lastOracleConfPct.toNumber());
198
+ }
199
+ const maxTargetSpread = maxSpread;
200
+ const MAX_INVENTORY_SKEW = 5;
201
+ const effectiveLeverage = calculateEffectiveLeverage(baseSpread, quoteAssetReserve, terminalQuoteAssetReserve, pegMultiplier, netBaseAssetAmount, markPrice, totalFeeMinusDistributions);
202
+ if (totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
203
+ const spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
204
+ if (netBaseAssetAmount.gt(numericConstants_1.ZERO)) {
205
+ longSpread *= spreadScale;
206
+ }
207
+ else {
208
+ shortSpread *= spreadScale;
209
+ }
210
+ }
211
+ else {
212
+ longSpread *= MAX_INVENTORY_SKEW;
213
+ shortSpread *= MAX_INVENTORY_SKEW;
214
+ }
215
+ const totalSpread = longSpread + shortSpread;
216
+ if (totalSpread > maxTargetSpread) {
217
+ if (longSpread > shortSpread) {
218
+ longSpread = Math.min(longSpread, maxTargetSpread);
219
+ shortSpread = maxTargetSpread - longSpread;
220
+ }
221
+ else {
222
+ shortSpread = Math.min(shortSpread, maxTargetSpread);
223
+ longSpread = maxTargetSpread - shortSpread;
224
+ }
225
+ }
226
+ return [longSpread, shortSpread];
227
+ }
228
+ exports.calculateSpreadBN = calculateSpreadBN;
129
229
  function calculateSpread(amm, direction, oraclePriceData) {
130
230
  let spread = amm.baseSpread / 2;
131
231
  if (amm.baseSpread == 0 || amm.curveUpdateIntensity == 0) {
@@ -133,14 +233,18 @@ function calculateSpread(amm, direction, oraclePriceData) {
133
233
  }
134
234
  const markPrice = calculatePrice(amm.baseAssetReserve, amm.quoteAssetReserve, amm.pegMultiplier);
135
235
  const targetPrice = (oraclePriceData === null || oraclePriceData === void 0 ? void 0 : oraclePriceData.price) || markPrice;
236
+ const confInterval = oraclePriceData.confidence || numericConstants_1.ZERO;
136
237
  const targetMarkSpreadPct = markPrice
137
238
  .sub(targetPrice)
138
239
  .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
139
240
  .div(markPrice);
241
+ const confIntervalPct = confInterval
242
+ .mul(numericConstants_1.BID_ASK_SPREAD_PRECISION)
243
+ .div(markPrice);
140
244
  // oracle retreat
141
245
  if (((0, types_1.isVariant)(direction, 'long') && targetMarkSpreadPct.lt(numericConstants_1.ZERO)) ||
142
246
  ((0, types_1.isVariant)(direction, 'short') && targetMarkSpreadPct.gt(numericConstants_1.ZERO))) {
143
- spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber());
247
+ spread = Math.max(spread, targetMarkSpreadPct.abs().toNumber() + confIntervalPct.abs().toNumber());
144
248
  }
145
249
  // inventory skew
146
250
  const MAX_INVENTORY_SKEW = 5;
@@ -161,9 +265,16 @@ function calculateSpread(amm, direction, oraclePriceData) {
161
265
  if (amm.totalFeeMinusDistributions.gt(numericConstants_1.ZERO)) {
162
266
  effectiveLeverage =
163
267
  localPnl.sub(netPnl).toNumber() /
164
- amm.totalFeeMinusDistributions.toNumber();
268
+ (amm.totalFeeMinusDistributions.toNumber() + 1);
269
+ }
270
+ let spreadScale = Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
271
+ const maxTargetSpread = numericConstants_1.BID_ASK_SPREAD_PRECISION.toNumber() / 50; // 2%
272
+ // cap the scale to attempt to only scale up to maxTargetSpread
273
+ // always let the oracle retreat methods go through 100%
274
+ if (spreadScale * spread > maxTargetSpread) {
275
+ spreadScale = Math.max(1.05, maxTargetSpread / spread);
165
276
  }
166
- spread *= Math.min(MAX_INVENTORY_SKEW, 1 + effectiveLeverage);
277
+ spread *= spreadScale;
167
278
  }
168
279
  return spread;
169
280
  }
package/lib/math/repeg.js CHANGED
@@ -107,7 +107,7 @@ function calculateBudgetedPeg(amm, cost, targetPrice) {
107
107
  const targetPeg = targetPrice
108
108
  .mul(amm.baseAssetReserve)
109
109
  .div(amm.quoteAssetReserve)
110
- .div(numericConstants_1.MARK_PRICE_PRECISION.div(numericConstants_1.PEG_PRECISION));
110
+ .div(numericConstants_1.PRICE_DIV_PEG);
111
111
  const k = amm.sqrtK.mul(amm.sqrtK);
112
112
  const x = amm.baseAssetReserve;
113
113
  const y = amm.quoteAssetReserve;
package/lib/orders.d.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  /// <reference types="bn.js" />
2
2
  import { MarketAccount, Order, UserAccount, UserPosition } from './types';
3
- import { BN, ClearingHouseUser } from '.';
3
+ import { BN } from '.';
4
4
  import { OraclePriceData } from '.';
5
5
  export declare function calculateNewStateAfterOrder(userAccount: UserAccount, userPosition: UserPosition, market: MarketAccount, order: Order): [UserAccount, UserPosition, MarketAccount] | null;
6
6
  export declare function calculateBaseAssetAmountMarketCanExecute(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
7
7
  export declare function calculateAmountToTradeForLimit(market: MarketAccount, order: Order, oraclePriceData?: OraclePriceData): BN;
8
8
  export declare function calculateAmountToTradeForTriggerLimit(market: MarketAccount, order: Order): BN;
9
- export declare function calculateBaseAssetAmountUserCanExecute(market: MarketAccount, order: Order, user: ClearingHouseUser, oraclePriceData?: OraclePriceData): BN;
package/lib/orders.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.calculateBaseAssetAmountUserCanExecute = exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
3
+ exports.calculateAmountToTradeForTriggerLimit = exports.calculateAmountToTradeForLimit = exports.calculateBaseAssetAmountMarketCanExecute = exports.calculateNewStateAfterOrder = void 0;
4
4
  const types_1 = require("./types");
5
5
  const _1 = require(".");
6
6
  const market_1 = require("./math/market");
@@ -88,7 +88,6 @@ function calculateBaseAssetAmountMarketCanExecute(market, order, oraclePriceData
88
88
  return calculateAmountToTradeForTriggerLimit(market, order);
89
89
  }
90
90
  else if ((0, types_1.isVariant)(order.orderType, 'market')) {
91
- // should never be a market order queued
92
91
  return numericConstants_1.ZERO;
93
92
  }
94
93
  else {
@@ -125,11 +124,8 @@ function calculateAmountToTradeForLimit(market, order, oraclePriceData) {
125
124
  }
126
125
  exports.calculateAmountToTradeForLimit = calculateAmountToTradeForLimit;
127
126
  function calculateAmountToTradeForTriggerLimit(market, order) {
128
- if (order.baseAssetAmountFilled.eq(numericConstants_1.ZERO)) {
129
- const baseAssetAmount = calculateAmountToTradeForTriggerMarket(market, order);
130
- if (baseAssetAmount.eq(numericConstants_1.ZERO)) {
131
- return numericConstants_1.ZERO;
132
- }
127
+ if (!order.triggered) {
128
+ return numericConstants_1.ZERO;
133
129
  }
134
130
  return calculateAmountToTradeForLimit(market, order);
135
131
  }
@@ -139,75 +135,8 @@ function isSameDirection(firstDirection, secondDirection) {
139
135
  ((0, types_1.isVariant)(firstDirection, 'short') && (0, types_1.isVariant)(secondDirection, 'short')));
140
136
  }
141
137
  function calculateAmountToTradeForTriggerMarket(market, order) {
142
- return isTriggerConditionSatisfied(market, order)
143
- ? order.baseAssetAmount
144
- : numericConstants_1.ZERO;
145
- }
146
- function isTriggerConditionSatisfied(market, order, oraclePriceData) {
147
- const markPrice = (0, market_1.calculateMarkPrice)(market, oraclePriceData);
148
- if ((0, types_1.isVariant)(order.triggerCondition, 'above')) {
149
- return markPrice.gt(order.triggerPrice);
150
- }
151
- else {
152
- return markPrice.lt(order.triggerPrice);
153
- }
154
- }
155
- function calculateBaseAssetAmountUserCanExecute(market, order, user, oraclePriceData) {
156
- const maxLeverage = user.getMaxLeverage(order.marketIndex, 'Initial');
157
- const freeCollateral = user.getFreeCollateral();
158
- let quoteAssetAmount;
159
- if ((0, _1.isOrderRiskIncreasingInSameDirection)(user, order)) {
160
- quoteAssetAmount = freeCollateral.mul(maxLeverage).div(_1.TEN_THOUSAND);
161
- }
162
- else {
163
- const position = user.getUserPosition(order.marketIndex) ||
164
- user.getEmptyPosition(order.marketIndex);
165
- const positionValue = (0, _1.calculateBaseAssetValue)(market, position, oraclePriceData);
166
- quoteAssetAmount = freeCollateral
167
- .mul(maxLeverage)
168
- .div(_1.TEN_THOUSAND)
169
- .add(positionValue.mul(numericConstants_1.TWO));
170
- }
171
- if (quoteAssetAmount.lte(numericConstants_1.ZERO)) {
138
+ if (!order.triggered) {
172
139
  return numericConstants_1.ZERO;
173
140
  }
174
- const swapDirection = (0, types_1.isVariant)(order.direction, 'long')
175
- ? types_1.SwapDirection.ADD
176
- : types_1.SwapDirection.REMOVE;
177
- const useSpread = !order.postOnly;
178
- let amm;
179
- if (useSpread) {
180
- const { baseAssetReserve, quoteAssetReserve } = (0, _1.calculateSpreadReserves)(market.amm, order.direction, oraclePriceData);
181
- amm = {
182
- baseAssetReserve,
183
- quoteAssetReserve,
184
- sqrtK: market.amm.sqrtK,
185
- pegMultiplier: market.amm.pegMultiplier,
186
- };
187
- }
188
- else {
189
- amm = market.amm;
190
- }
191
- const baseAssetReservesBefore = amm.baseAssetReserve;
192
- const [_, baseAssetReservesAfter] = (0, _1.calculateAmmReservesAfterSwap)(amm, 'quote', quoteAssetAmount, swapDirection);
193
- let baseAssetAmount = baseAssetReservesBefore
194
- .sub(baseAssetReservesAfter)
195
- .abs();
196
- if (order.reduceOnly) {
197
- const position = user.getUserPosition(order.marketIndex) ||
198
- user.getEmptyPosition(order.marketIndex);
199
- if ((0, types_1.isVariant)(order.direction, 'long') &&
200
- position.baseAssetAmount.gte(numericConstants_1.ZERO)) {
201
- baseAssetAmount = numericConstants_1.ZERO;
202
- }
203
- else if ((0, types_1.isVariant)(order.direction, 'short') &&
204
- position.baseAssetAmount.lte(numericConstants_1.ZERO)) {
205
- baseAssetAmount = numericConstants_1.ZERO;
206
- }
207
- else {
208
- _1.BN.min(baseAssetAmount, position.baseAssetAmount.abs());
209
- }
210
- }
211
- return baseAssetAmount;
141
+ return order.baseAssetAmount;
212
142
  }
213
- exports.calculateBaseAssetAmountUserCanExecute = calculateBaseAssetAmountUserCanExecute;
package/lib/types.d.ts CHANGED
@@ -88,6 +88,9 @@ export declare class OrderAction {
88
88
  static readonly FILL: {
89
89
  fill: {};
90
90
  };
91
+ static readonly TRIGGER: {
92
+ trigger: {};
93
+ };
91
94
  }
92
95
  export declare class OrderTriggerCondition {
93
96
  static readonly ABOVE: {
@@ -304,6 +307,7 @@ export declare type AMM = {
304
307
  lastAskPriceTwap: BN;
305
308
  longSpread: BN;
306
309
  shortSpread: BN;
310
+ maxSpread: number;
307
311
  };
308
312
  export declare type UserPosition = {
309
313
  baseAssetAmount: BN;
@@ -356,6 +360,7 @@ export declare type Order = {
356
360
  reduceOnly: boolean;
357
361
  triggerPrice: BN;
358
362
  triggerCondition: OrderTriggerCondition;
363
+ triggered: boolean;
359
364
  discountTier: OrderDiscountTier;
360
365
  existingPositionDirection: PositionDirection;
361
366
  referrer: PublicKey;
package/lib/types.js CHANGED
@@ -50,6 +50,7 @@ OrderAction.PLACE = { place: {} };
50
50
  OrderAction.CANCEL = { cancel: {} };
51
51
  OrderAction.EXPIRE = { expire: {} };
52
52
  OrderAction.FILL = { fill: {} };
53
+ OrderAction.TRIGGER = { trigger: {} };
53
54
  class OrderTriggerCondition {
54
55
  }
55
56
  exports.OrderTriggerCondition = OrderTriggerCondition;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.2.0-master.1",
3
+ "version": "0.2.0-master.2",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
package/src/admin.ts CHANGED
@@ -444,6 +444,19 @@ export class Admin extends ClearingHouse {
444
444
  });
445
445
  }
446
446
 
447
+ public async updateMarketMaxSpread(
448
+ marketIndex: BN,
449
+ maxSpread: number
450
+ ): Promise<TransactionSignature> {
451
+ return await this.program.rpc.updateMarketMaxSpread(maxSpread, {
452
+ accounts: {
453
+ admin: this.wallet.publicKey,
454
+ state: await this.getStatePublicKey(),
455
+ market: await getMarketPublicKey(this.program.programId, marketIndex),
456
+ },
457
+ });
458
+ }
459
+
447
460
  public async updatePartialLiquidationClosePercentage(
448
461
  numerator: BN,
449
462
  denominator: BN
@@ -914,7 +914,7 @@ export class ClearingHouse {
914
914
  });
915
915
  }
916
916
 
917
- public async cancelOrder(orderId: BN): Promise<TransactionSignature> {
917
+ public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
918
918
  const { txSig } = await this.txSender.send(
919
919
  wrapInTx(await this.getCancelOrderIx(orderId)),
920
920
  [],
@@ -923,20 +923,16 @@ export class ClearingHouse {
923
923
  return txSig;
924
924
  }
925
925
 
926
- public async getCancelOrderIx(orderId: BN): Promise<TransactionInstruction> {
926
+ public async getCancelOrderIx(orderId?: BN): Promise<TransactionInstruction> {
927
927
  const userAccountPublicKey = await this.getUserAccountPublicKey();
928
928
 
929
- const order = this.getOrder(orderId);
930
- const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
931
-
932
929
  const remainingAccounts = this.getRemainingAccounts({});
933
930
 
934
- return await this.program.instruction.cancelOrder(orderId, {
931
+ return await this.program.instruction.cancelOrder(orderId ?? null, {
935
932
  accounts: {
936
933
  state: await this.getStatePublicKey(),
937
934
  user: userAccountPublicKey,
938
935
  authority: this.wallet.publicKey,
939
- oracle,
940
936
  },
941
937
  remainingAccounts,
942
938
  });
@@ -1066,7 +1062,7 @@ export class ClearingHouse {
1066
1062
  public async fillOrder(
1067
1063
  userAccountPublicKey: PublicKey,
1068
1064
  user: UserAccount,
1069
- order: Order,
1065
+ order?: Order,
1070
1066
  makerInfo?: MakerInfo
1071
1067
  ): Promise<TransactionSignature> {
1072
1068
  const { txSig } = await this.txSender.send(
@@ -1156,6 +1152,84 @@ export class ClearingHouse {
1156
1152
  });
1157
1153
  }
1158
1154
 
1155
+ public async triggerOrder(
1156
+ userAccountPublicKey: PublicKey,
1157
+ user: UserAccount,
1158
+ order: Order
1159
+ ): Promise<TransactionSignature> {
1160
+ const { txSig } = await this.txSender.send(
1161
+ wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
1162
+ [],
1163
+ this.opts
1164
+ );
1165
+ return txSig;
1166
+ }
1167
+
1168
+ public async getTriggerOrderIx(
1169
+ userAccountPublicKey: PublicKey,
1170
+ userAccount: UserAccount,
1171
+ order: Order
1172
+ ): Promise<TransactionInstruction> {
1173
+ const fillerPublicKey = await this.getUserAccountPublicKey();
1174
+
1175
+ const marketIndex = order.marketIndex;
1176
+ const marketAccount = this.getMarketAccount(marketIndex);
1177
+
1178
+ const bankAccountInfos = [
1179
+ {
1180
+ pubkey: this.getQuoteAssetBankAccount().pubkey,
1181
+ isSigner: false,
1182
+ isWritable: true,
1183
+ },
1184
+ ];
1185
+ const marketAccountInfos = [
1186
+ {
1187
+ pubkey: marketAccount.pubkey,
1188
+ isWritable: true,
1189
+ isSigner: false,
1190
+ },
1191
+ ];
1192
+ const oracleAccountInfos = [
1193
+ {
1194
+ pubkey: marketAccount.amm.oracle,
1195
+ isWritable: false,
1196
+ isSigner: false,
1197
+ },
1198
+ ];
1199
+ for (const position of userAccount.positions) {
1200
+ if (
1201
+ !positionIsAvailable(position) &&
1202
+ !position.marketIndex.eq(order.marketIndex)
1203
+ ) {
1204
+ const market = this.getMarketAccount(position.marketIndex);
1205
+ marketAccountInfos.push({
1206
+ pubkey: market.pubkey,
1207
+ isWritable: false,
1208
+ isSigner: false,
1209
+ });
1210
+ oracleAccountInfos.push({
1211
+ pubkey: market.amm.oracle,
1212
+ isWritable: false,
1213
+ isSigner: false,
1214
+ });
1215
+ }
1216
+ }
1217
+ const remainingAccounts = oracleAccountInfos.concat(
1218
+ bankAccountInfos.concat(marketAccountInfos)
1219
+ );
1220
+
1221
+ const orderId = order.orderId;
1222
+ return await this.program.instruction.triggerOrder(orderId, {
1223
+ accounts: {
1224
+ state: await this.getStatePublicKey(),
1225
+ filler: fillerPublicKey,
1226
+ user: userAccountPublicKey,
1227
+ authority: this.wallet.publicKey,
1228
+ },
1229
+ remainingAccounts,
1230
+ });
1231
+ }
1232
+
1159
1233
  public async placeAndTake(
1160
1234
  orderParams: OrderParams,
1161
1235
  makerInfo?: MakerInfo
package/src/config.ts CHANGED
@@ -28,7 +28,7 @@ export const configs: { [key in DriftEnv]: DriftConfig } = {
28
28
  devnet: {
29
29
  ENV: 'devnet',
30
30
  PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
31
- CLEARING_HOUSE_PROGRAM_ID: 'GCuH76fb1rXc7bjFXNcnNvWSekLgzpsnMbc1Ng4FsGSs',
31
+ CLEARING_HOUSE_PROGRAM_ID: '9jwr5nC2f9yAraXrg4UzHXmCX3vi9FQkjD6p9e8bRqNa',
32
32
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
33
33
  MARKETS: DevnetMarkets,
34
34
  BANKS: DevnetBanks,
@@ -43,6 +43,7 @@ export const BASE_PRECISION_EXP = AMM_RESERVE_PRECISION_EXP;
43
43
 
44
44
  export const AMM_TO_QUOTE_PRECISION_RATIO =
45
45
  AMM_RESERVE_PRECISION.div(QUOTE_PRECISION); // 10^7
46
+ export const PRICE_DIV_PEG = MARK_PRICE_PRECISION.div(PEG_PRECISION); //10^7
46
47
  export const PRICE_TO_QUOTE_PRECISION =
47
48
  MARK_PRICE_PRECISION.div(QUOTE_PRECISION);
48
49
  export const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO =
@@ -234,8 +234,14 @@ export class BigNum {
234
234
  return printString;
235
235
  }
236
236
 
237
- public prettyPrint(): string {
238
- const [leftSide, rightSide] = this.printShort().split(BigNum.delim);
237
+ public prettyPrint(
238
+ useTradePrecision?: boolean,
239
+ precisionOverride?: number
240
+ ): string {
241
+ const [leftSide, rightSide] = this.printShort(
242
+ useTradePrecision,
243
+ precisionOverride
244
+ ).split(BigNum.delim);
239
245
 
240
246
  let formattedLeftSide = leftSide;
241
247
 
@@ -374,13 +380,24 @@ export class BigNum {
374
380
  return this.toPrecision(6, true);
375
381
  }
376
382
 
377
- public toNotional(): string {
378
- return `${this.lt(BigNum.zero()) ? `-` : ``}$${BigNum.fromPrint(
379
- this.toFixed(2),
380
- new BN(2)
381
- )
382
- .prettyPrint()
383
- .replace('-', '')}`;
383
+ /**
384
+ * Print dollar formatted value. Defaults to fixed decimals two unless a given precision is given.
385
+ * @param useTradePrecision
386
+ * @param precisionOverride
387
+ * @returns
388
+ */
389
+ public toNotional(
390
+ useTradePrecision?: boolean,
391
+ precisionOverride?: number
392
+ ): string {
393
+ const prefix = `${this.lt(BigNum.zero()) ? `-` : ``}$`;
394
+
395
+ const val =
396
+ useTradePrecision || precisionOverride
397
+ ? this.prettyPrint(useTradePrecision, precisionOverride)
398
+ : BigNum.fromPrint(this.toFixed(2), new BN(2)).prettyPrint();
399
+
400
+ return `${prefix}${val.replace('-', '')}`;
384
401
  }
385
402
 
386
403
  public toMillified(precision = 3): string {