@drift-labs/sdk 0.2.0-master.36 → 0.2.0-master.38

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.
@@ -38,7 +38,7 @@ async function getUserAccountPublicKeyAndNonce(programId, authority, subAccountI
38
38
  return web3_js_1.PublicKey.findProgramAddress([
39
39
  Buffer.from(anchor.utils.bytes.utf8.encode('user')),
40
40
  authority.toBuffer(),
41
- Uint8Array.from([subAccountId]),
41
+ new anchor.BN(subAccountId).toArrayLike(Buffer, 'le', 2),
42
42
  ], programId);
43
43
  }
44
44
  exports.getUserAccountPublicKeyAndNonce = getUserAccountPublicKeyAndNonce;
@@ -50,7 +50,7 @@ function getUserAccountPublicKeySync(programId, authority, subAccountId = 0) {
50
50
  return web3_js_1.PublicKey.findProgramAddressSync([
51
51
  Buffer.from(anchor.utils.bytes.utf8.encode('user')),
52
52
  authority.toBuffer(),
53
- Uint8Array.from([subAccountId]),
53
+ new anchor.BN(subAccountId).toArrayLike(Buffer, 'le', 2),
54
54
  ], programId)[0];
55
55
  }
56
56
  exports.getUserAccountPublicKeySync = getUserAccountPublicKeySync;
package/lib/admin.d.ts CHANGED
@@ -5,9 +5,9 @@ import { BN } from '@project-serum/anchor';
5
5
  import { ClearingHouse } from './clearingHouse';
6
6
  export declare class Admin extends ClearingHouse {
7
7
  initialize(usdcMint: PublicKey, _adminControlsPrices: boolean): Promise<[TransactionSignature]>;
8
- initializeSpotMarket(mint: PublicKey, optimalUtilization: number, optimalRate: number, maxRate: number, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: BN, maintenanceAssetWeight: BN, initialLiabilityWeight: BN, maintenanceLiabilityWeight: BN, imfFactor?: BN, liquidationFee?: BN, activeStatus?: boolean): Promise<TransactionSignature>;
8
+ initializeSpotMarket(mint: PublicKey, optimalUtilization: number, optimalRate: number, maxRate: number, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number, liquidationFee?: number, activeStatus?: boolean): Promise<TransactionSignature>;
9
9
  initializeSerumFulfillmentConfig(marketIndex: number, serumMarket: PublicKey, serumProgram: PublicKey): Promise<TransactionSignature>;
10
- initializePerpMarket(priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioMaintenance?: number, liquidationFee?: BN, activeStatus?: boolean, name?: string): Promise<TransactionSignature>;
10
+ initializePerpMarket(priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioMaintenance?: number, liquidationFee?: number, activeStatus?: boolean, name?: string): Promise<TransactionSignature>;
11
11
  moveAmmPrice(perpMarketIndex: number, baseAssetReserve: BN, quoteAssetReserve: BN, sqrtK?: BN): Promise<TransactionSignature>;
12
12
  updateK(perpMarketIndex: number, sqrtK: BN): Promise<TransactionSignature>;
13
13
  updatePerpMarketConcentrationScale(perpMarketIndex: number, concentrationScale: BN): Promise<TransactionSignature>;
@@ -36,12 +36,15 @@ export declare class Admin extends ClearingHouse {
36
36
  updatePerpMarketOracle(perpMarketIndex: number, oracle: PublicKey, oracleSource: OracleSource): Promise<TransactionSignature>;
37
37
  updatePerpMarketStepSizeAndTickSize(perpMarketIndex: number, stepSize: BN, tickSize: BN): Promise<TransactionSignature>;
38
38
  updatePerpMarketMinOrderSize(perpMarketIndex: number, orderSize: BN): Promise<TransactionSignature>;
39
+ updateSpotMarketStepSizeAndTickSize(spotMarketIndex: number, stepSize: BN, tickSize: BN): Promise<TransactionSignature>;
40
+ updateSpotMarketMinOrderSize(spotMarketIndex: number, orderSize: BN): Promise<TransactionSignature>;
39
41
  updatePerpMarketExpiry(perpMarketIndex: number, expiryTs: BN): Promise<TransactionSignature>;
40
42
  updateSpotMarketOracle(spotMarketIndex: number, oracle: PublicKey, oracleSource: OracleSource): Promise<TransactionSignature>;
41
43
  updateSpotMarketExpiry(spotMarketIndex: number, expiryTs: BN): Promise<TransactionSignature>;
42
44
  updateWhitelistMint(whitelistMint?: PublicKey): Promise<TransactionSignature>;
43
45
  updateDiscountMint(discountMint: PublicKey): Promise<TransactionSignature>;
44
- updateSpotMarketMarginWeights(spotMarketIndex: number, initialAssetWeight: BN, maintenanceAssetWeight: BN, initialLiabilityWeight: BN, maintenanceLiabilityWeight: BN, imfFactor?: BN): Promise<TransactionSignature>;
46
+ updateSpotMarketMarginWeights(spotMarketIndex: number, initialAssetWeight: number, maintenanceAssetWeight: number, initialLiabilityWeight: number, maintenanceLiabilityWeight: number, imfFactor?: number): Promise<TransactionSignature>;
47
+ updateSpotMarketBorrowRate(spotMarketIndex: number, optimalUtilization: number, optimalBorrowRate: number, optimalMaxRate: number): Promise<TransactionSignature>;
45
48
  updateSpotMarketAssetTier(spotMarketIndex: number, assetTier: AssetTier): Promise<TransactionSignature>;
46
49
  updateSpotMarketStatus(spotMarketIndex: number, marketStatus: MarketStatus): Promise<TransactionSignature>;
47
50
  updatePerpMarketStatus(perpMarketIndex: number, marketStatus: MarketStatus): Promise<TransactionSignature>;
package/lib/admin.js CHANGED
@@ -57,7 +57,7 @@ class Admin extends clearingHouse_1.ClearingHouse {
57
57
  const { txSig: initializeTxSig } = await this.txSender.send(initializeTx, [], this.opts);
58
58
  return [initializeTxSig];
59
59
  }
60
- async initializeSpotMarket(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = new anchor_1.BN(0), liquidationFee = numericConstants_1.ZERO, activeStatus = true) {
60
+ async initializeSpotMarket(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = 0, liquidationFee = 0, activeStatus = true) {
61
61
  const spotMarketIndex = this.getStateAccount().numberOfSpotMarkets;
62
62
  const spotMarket = await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex);
63
63
  const spotMarketVault = await (0, pda_1.getSpotMarketVaultPublicKey)(this.program.programId, spotMarketIndex);
@@ -104,7 +104,7 @@ class Admin extends clearingHouse_1.ClearingHouse {
104
104
  },
105
105
  });
106
106
  }
107
- async initializePerpMarket(priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioMaintenance = 500, liquidationFee = numericConstants_1.ZERO, activeStatus = true, name = userName_1.DEFAULT_MARKET_NAME) {
107
+ async initializePerpMarket(priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioMaintenance = 500, liquidationFee = 0, activeStatus = true, name = userName_1.DEFAULT_MARKET_NAME) {
108
108
  const perpMarketPublicKey = await (0, pda_1.getPerpMarketPublicKey)(this.program.programId, this.getStateAccount().numberOfMarkets);
109
109
  const nameBuffer = (0, userName_1.encodeName)(name);
110
110
  const initializeMarketTx = await this.program.transaction.initializePerpMarket(baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, oracleSource, marginRatioInitial, marginRatioMaintenance, liquidationFee, activeStatus, nameBuffer, {
@@ -401,6 +401,24 @@ class Admin extends clearingHouse_1.ClearingHouse {
401
401
  },
402
402
  });
403
403
  }
404
+ async updateSpotMarketStepSizeAndTickSize(spotMarketIndex, stepSize, tickSize) {
405
+ return await this.program.rpc.updateSpotMarketStepSizeAndTickSize(stepSize, tickSize, {
406
+ accounts: {
407
+ admin: this.wallet.publicKey,
408
+ state: await this.getStatePublicKey(),
409
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
410
+ },
411
+ });
412
+ }
413
+ async updateSpotMarketMinOrderSize(spotMarketIndex, orderSize) {
414
+ return await this.program.rpc.updateSpotMarketMinOrderSize(orderSize, {
415
+ accounts: {
416
+ admin: this.wallet.publicKey,
417
+ state: await this.getStatePublicKey(),
418
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
419
+ },
420
+ });
421
+ }
404
422
  async updatePerpMarketExpiry(perpMarketIndex, expiryTs) {
405
423
  return await this.program.rpc.updatePerpMarketExpiry(expiryTs, {
406
424
  accounts: {
@@ -445,7 +463,7 @@ class Admin extends clearingHouse_1.ClearingHouse {
445
463
  },
446
464
  });
447
465
  }
448
- async updateSpotMarketMarginWeights(spotMarketIndex, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = new anchor_1.BN(0)) {
466
+ async updateSpotMarketMarginWeights(spotMarketIndex, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = 0) {
449
467
  return await this.program.rpc.updateSpotMarketMarginWeights(initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor, {
450
468
  accounts: {
451
469
  admin: this.wallet.publicKey,
@@ -454,6 +472,15 @@ class Admin extends clearingHouse_1.ClearingHouse {
454
472
  },
455
473
  });
456
474
  }
475
+ async updateSpotMarketBorrowRate(spotMarketIndex, optimalUtilization, optimalBorrowRate, optimalMaxRate) {
476
+ return await this.program.rpc.updateSpotMarketBorrowRate(optimalUtilization, optimalBorrowRate, optimalMaxRate, {
477
+ accounts: {
478
+ admin: this.wallet.publicKey,
479
+ state: await this.getStatePublicKey(),
480
+ spotMarket: await (0, pda_1.getSpotMarketPublicKey)(this.program.programId, spotMarketIndex),
481
+ },
482
+ });
483
+ }
457
484
  async updateSpotMarketAssetTier(spotMarketIndex, assetTier) {
458
485
  return await this.program.rpc.updateSpotMarketAssetTier(assetTier, {
459
486
  accounts: {
@@ -19,7 +19,7 @@ declare type RemainingAccountParams = {
19
19
  writablePerpMarketIndexes?: number[];
20
20
  writableSpotMarketIndexes?: number[];
21
21
  readablePerpMarketIndex?: number;
22
- readableSpotMarketIndex?: number;
22
+ readableSpotMarketIndexes?: number[];
23
23
  useMarketLastSlotCache?: boolean;
24
24
  };
25
25
  /**
@@ -40,7 +40,8 @@ export declare class ClearingHouse {
40
40
  eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
41
41
  _isSubscribed: boolean;
42
42
  txSender: TxSender;
43
- marketLastSlotCache: Map<number, number>;
43
+ perpMarketLastSlotCache: Map<number, number>;
44
+ spotMarketLastSlotCache: Map<number, number>;
44
45
  authority: PublicKey;
45
46
  get isSubscribed(): boolean;
46
47
  set isSubscribed(val: boolean);
@@ -167,6 +168,7 @@ export declare class ClearingHouse {
167
168
  getPlaceSpotOrderIx(orderParams: OptionalOrderParams): Promise<TransactionInstruction>;
168
169
  fillSpotOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
169
170
  getFillSpotOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order?: Order, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
171
+ addSpotFulfillmentAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig?: SerumV3FulfillmentConfigAccount): void;
170
172
  addSerumRemainingAccounts(marketIndex: number, remainingAccounts: AccountMeta[], fulfillmentConfig: SerumV3FulfillmentConfigAccount): void;
171
173
  triggerOrder(userAccountPublicKey: PublicKey, user: UserAccount, order: Order): Promise<TransactionSignature>;
172
174
  getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
@@ -176,22 +178,31 @@ export declare class ClearingHouse {
176
178
  getPlaceAndMakePerpOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
177
179
  placeAndTakeSpotOrder(orderParams: OptionalOrderParams, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
178
180
  getPlaceAndTakeSpotOrderIx(orderParams: OptionalOrderParams, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
179
- placeAndMakeSpotOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
180
- getPlaceAndMakeSpotOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
181
+ placeAndMakeSpotOrder(orderParams: OptionalOrderParams, takerInfo: TakerInfo, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
182
+ getPlaceAndMakeSpotOrderIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, fulfillmentConfig?: SerumV3FulfillmentConfigAccount, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
181
183
  /**
182
184
  * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
183
185
  * @param marketIndex
184
186
  * @returns
185
187
  */
186
188
  closePosition(marketIndex: number, limitPrice?: BN): Promise<TransactionSignature>;
189
+ /**
190
+ * Modifies an open order by closing it and replacing it with a new order.
191
+ * @param orderId: The open order to modify
192
+ * @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
193
+ * @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
194
+ * @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
195
+ * @returns
196
+ */
197
+ modifyPerpOrder(orderId: number, newBaseAmount?: BN, newLimitPrice?: BN, newOraclePriceOffset?: number): Promise<TransactionSignature>;
187
198
  settlePNLs(users: {
188
199
  settleeUserAccountPublicKey: PublicKey;
189
200
  settleeUserAccount: UserAccount;
190
201
  }[], marketIndex: number): Promise<TransactionSignature>;
191
202
  settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number): Promise<TransactionSignature>;
192
203
  settlePNLIx(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: number): Promise<TransactionInstruction>;
193
- liquidatePerp(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN): Promise<TransactionSignature>;
194
- getLiquidatePerpIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN): Promise<TransactionInstruction>;
204
+ liquidatePerp(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN, limitPrice?: BN): Promise<TransactionSignature>;
205
+ getLiquidatePerpIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: number, maxBaseAssetAmount: BN, limitPrice?: BN): Promise<TransactionInstruction>;
195
206
  liquidateSpot(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN): Promise<TransactionSignature>;
196
207
  getLiquidateSpotIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN): Promise<TransactionInstruction>;
197
208
  liquidateBorrowForPerpPnl(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: number, liabilityMarketIndex: number, maxLiabilityTransfer: BN): Promise<TransactionSignature>;
@@ -57,7 +57,8 @@ class ClearingHouse {
57
57
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
58
58
  this.users = new Map();
59
59
  this._isSubscribed = false;
60
- this.marketLastSlotCache = new Map();
60
+ this.perpMarketLastSlotCache = new Map();
61
+ this.spotMarketLastSlotCache = new Map();
61
62
  this.connection = config.connection;
62
63
  this.wallet = config.wallet;
63
64
  this.opts = config.opts || anchor_1.AnchorProvider.defaultOptions();
@@ -404,11 +405,11 @@ class ClearingHouse {
404
405
  var _a;
405
406
  const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } = this.getRemainingAccountMapsForUsers(params.userAccounts);
406
407
  if (params.useMarketLastSlotCache) {
407
- const lastUserPositionsSlot = (_a = this.getUserAccountAndSlot()) === null || _a === void 0 ? void 0 : _a.slot;
408
- for (const [marketIndex, slot] of this.marketLastSlotCache.entries()) {
408
+ const lastUserSlot = (_a = this.getUserAccountAndSlot()) === null || _a === void 0 ? void 0 : _a.slot;
409
+ for (const [marketIndex, slot,] of this.perpMarketLastSlotCache.entries()) {
409
410
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
410
411
  // otherwise remove from slot
411
- if (slot > lastUserPositionsSlot) {
412
+ if (slot > lastUserSlot) {
412
413
  const marketAccount = this.getPerpMarketAccount(marketIndex);
413
414
  perpMarketAccountMap.set(marketIndex, {
414
415
  pubkey: marketAccount.pubkey,
@@ -422,7 +423,29 @@ class ClearingHouse {
422
423
  });
423
424
  }
424
425
  else {
425
- this.marketLastSlotCache.delete(marketIndex);
426
+ this.perpMarketLastSlotCache.delete(marketIndex);
427
+ }
428
+ }
429
+ for (const [marketIndex, slot,] of this.spotMarketLastSlotCache.entries()) {
430
+ // if cache has more recent slot than user positions account slot, add market to remaining accounts
431
+ // otherwise remove from slot
432
+ if (slot > lastUserSlot) {
433
+ const marketAccount = this.getSpotMarketAccount(marketIndex);
434
+ spotMarketAccountMap.set(marketIndex, {
435
+ pubkey: marketAccount.pubkey,
436
+ isSigner: false,
437
+ isWritable: false,
438
+ });
439
+ if (!marketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
440
+ oracleAccountMap.set(marketAccount.oracle.toString(), {
441
+ pubkey: marketAccount.oracle,
442
+ isSigner: false,
443
+ isWritable: false,
444
+ });
445
+ }
446
+ }
447
+ else {
448
+ this.spotMarketLastSlotCache.delete(marketIndex);
426
449
  }
427
450
  }
428
451
  }
@@ -454,19 +477,21 @@ class ClearingHouse {
454
477
  });
455
478
  }
456
479
  }
457
- if (params.readableSpotMarketIndex !== undefined) {
458
- const spotMarketAccount = this.getSpotMarketAccount(params.readableSpotMarketIndex);
459
- spotMarketAccountMap.set(params.readableSpotMarketIndex, {
460
- pubkey: spotMarketAccount.pubkey,
461
- isSigner: false,
462
- isWritable: false,
463
- });
464
- if (spotMarketAccount.marketIndex !== 0) {
465
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
466
- pubkey: spotMarketAccount.oracle,
480
+ if (params.readableSpotMarketIndexes !== undefined) {
481
+ for (const readableSpotMarketIndex of params.readableSpotMarketIndexes) {
482
+ const spotMarketAccount = this.getSpotMarketAccount(readableSpotMarketIndex);
483
+ spotMarketAccountMap.set(readableSpotMarketIndex, {
484
+ pubkey: spotMarketAccount.pubkey,
467
485
  isSigner: false,
468
486
  isWritable: false,
469
487
  });
488
+ if (spotMarketAccount.marketIndex !== 0) {
489
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
490
+ pubkey: spotMarketAccount.oracle,
491
+ isSigner: false,
492
+ isWritable: false,
493
+ });
494
+ }
470
495
  }
471
496
  }
472
497
  if (params.writableSpotMarketIndexes !== undefined) {
@@ -512,6 +537,14 @@ class ClearingHouse {
512
537
  isWritable: false,
513
538
  });
514
539
  }
540
+ if (!spotPosition.openAsks.eq(numericConstants_1.ZERO) ||
541
+ !spotPosition.openBids.eq(numericConstants_1.ZERO)) {
542
+ spotMarketAccountMap.set(spotPosition.marketIndex, {
543
+ pubkey: this.getQuoteSpotMarketAccount().pubkey,
544
+ isSigner: false,
545
+ isWritable: false,
546
+ });
547
+ }
515
548
  }
516
549
  }
517
550
  for (const position of userAccount.perpPositions) {
@@ -569,7 +602,8 @@ class ClearingHouse {
569
602
  if (createWSOLTokenAccount) {
570
603
  tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, collateralAccountPublicKey, authority, authority, []));
571
604
  }
572
- const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
605
+ const { txSig, slot } = await this.txSender.send(tx, additionalSigners, this.opts);
606
+ this.spotMarketLastSlotCache.set(marketIndex, slot);
573
607
  return txSig;
574
608
  }
575
609
  async getDepositInstruction(amount, marketIndex, userTokenAccount, subAccountId, reduceOnly = false, userInitialized = true) {
@@ -679,7 +713,8 @@ class ClearingHouse {
679
713
  if (createWSOLTokenAccount) {
680
714
  tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
681
715
  }
682
- const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
716
+ const { txSig, slot } = await this.txSender.send(tx, additionalSigners, this.opts);
717
+ this.spotMarketLastSlotCache.set(marketIndex, slot);
683
718
  return [txSig, userAccountPublicKey];
684
719
  }
685
720
  async initializeUserAccountForDevnet(subAccountId = 0, name = userName_1.DEFAULT_USER_NAME, marketIndex, tokenFaucet, amount, referrerInfo) {
@@ -726,7 +761,8 @@ class ClearingHouse {
726
761
  if (createWSOLTokenAccount) {
727
762
  tx.add(spl_token_1.Token.createCloseAccountInstruction(spl_token_1.TOKEN_PROGRAM_ID, userTokenAccount, authority, authority, []));
728
763
  }
729
- const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
764
+ const { txSig, slot } = await this.txSender.send(tx, additionalSigners, this.opts);
765
+ this.spotMarketLastSlotCache.set(marketIndex, slot);
730
766
  return txSig;
731
767
  }
732
768
  async getWithdrawIx(amount, marketIndex, userTokenAccount, reduceOnly = false) {
@@ -735,6 +771,7 @@ class ClearingHouse {
735
771
  userAccounts: [this.getUserAccount()],
736
772
  useMarketLastSlotCache: true,
737
773
  writableSpotMarketIndexes: [marketIndex],
774
+ readableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
738
775
  });
739
776
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
740
777
  return await this.program.instruction.withdraw(marketIndex, amount, reduceOnly, {
@@ -753,7 +790,11 @@ class ClearingHouse {
753
790
  });
754
791
  }
755
792
  async transferDeposit(amount, marketIndex, fromSubAccountId, toSubAccountId) {
756
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, marketIndex, fromSubAccountId, toSubAccountId)), [], this.opts);
793
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTransferDepositIx(amount, marketIndex, fromSubAccountId, toSubAccountId)), [], this.opts);
794
+ if (fromSubAccountId === this.activeSubAccountId ||
795
+ toSubAccountId === this.activeSubAccountId) {
796
+ this.spotMarketLastSlotCache.set(marketIndex, slot);
797
+ }
757
798
  return txSig;
758
799
  }
759
800
  async getTransferDepositIx(amount, marketIndex, fromSubAccountId, toSubAccountId) {
@@ -783,6 +824,7 @@ class ClearingHouse {
783
824
  toUser,
784
825
  userStats: this.getUserStatsAccountPublicKey(),
785
826
  state: await this.getStatePublicKey(),
827
+ spotMarketVault: this.getQuoteSpotMarketAccount().vault,
786
828
  },
787
829
  remainingAccounts,
788
830
  });
@@ -871,7 +913,7 @@ class ClearingHouse {
871
913
  }
872
914
  async addPerpLpShares(amount, marketIndex) {
873
915
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getAddPerpLpSharesIx(amount, marketIndex)), [], this.opts);
874
- this.marketLastSlotCache.set(marketIndex, slot);
916
+ this.perpMarketLastSlotCache.set(marketIndex, slot);
875
917
  return txSig;
876
918
  }
877
919
  async getAddPerpLpSharesIx(amount, marketIndex) {
@@ -926,12 +968,12 @@ class ClearingHouse {
926
968
  fillTx.feePayer = userAccount.authority;
927
969
  const [signedMarketOrderTx, signedFillTx] = await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
928
970
  const { txSig, slot } = await this.txSender.send(signedMarketOrderTx, [], this.opts, true);
929
- this.marketLastSlotCache.set(orderParams.marketIndex, slot);
971
+ this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
930
972
  return { txSig, signedFillTx };
931
973
  }
932
974
  async placePerpOrder(orderParams) {
933
975
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlacePerpOrderIx(orderParams)), [], this.opts);
934
- this.marketLastSlotCache.set(orderParams.marketIndex, slot);
976
+ this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
935
977
  return txSig;
936
978
  }
937
979
  getOrderParams(optionalOrderParams, marketType) {
@@ -1158,7 +1200,9 @@ class ClearingHouse {
1158
1200
  });
1159
1201
  }
1160
1202
  async placeSpotOrder(orderParams) {
1161
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams)), [], this.opts);
1203
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceSpotOrderIx(orderParams)), [], this.opts);
1204
+ this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
1205
+ this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
1162
1206
  return txSig;
1163
1207
  }
1164
1208
  async getPlaceSpotOrderIx(orderParams) {
@@ -1167,7 +1211,10 @@ class ClearingHouse {
1167
1211
  const remainingAccounts = this.getRemainingAccounts({
1168
1212
  userAccounts: [this.getUserAccount()],
1169
1213
  useMarketLastSlotCache: true,
1170
- readableSpotMarketIndex: orderParams.marketIndex,
1214
+ readableSpotMarketIndexes: [
1215
+ orderParams.marketIndex,
1216
+ numericConstants_1.QUOTE_SPOT_MARKET_INDEX,
1217
+ ],
1171
1218
  });
1172
1219
  return await this.program.instruction.placeSpotOrder(orderParams, {
1173
1220
  accounts: {
@@ -1224,9 +1271,7 @@ class ClearingHouse {
1224
1271
  }
1225
1272
  const orderId = order.orderId;
1226
1273
  const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1227
- if (fulfillmentConfig) {
1228
- this.addSerumRemainingAccounts(marketIndex, remainingAccounts, fulfillmentConfig);
1229
- }
1274
+ this.addSpotFulfillmentAccounts(marketIndex, remainingAccounts, fulfillmentConfig);
1230
1275
  return await this.program.instruction.fillSpotOrder(orderId, fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null, makerOrderId, {
1231
1276
  accounts: {
1232
1277
  state: await this.getStatePublicKey(),
@@ -1239,6 +1284,23 @@ class ClearingHouse {
1239
1284
  remainingAccounts,
1240
1285
  });
1241
1286
  }
1287
+ addSpotFulfillmentAccounts(marketIndex, remainingAccounts, fulfillmentConfig) {
1288
+ if (fulfillmentConfig) {
1289
+ this.addSerumRemainingAccounts(marketIndex, remainingAccounts, fulfillmentConfig);
1290
+ }
1291
+ else {
1292
+ remainingAccounts.push({
1293
+ pubkey: this.getSpotMarketAccount(marketIndex).vault,
1294
+ isWritable: false,
1295
+ isSigner: false,
1296
+ });
1297
+ remainingAccounts.push({
1298
+ pubkey: this.getQuoteSpotMarketAccount().vault,
1299
+ isWritable: false,
1300
+ isSigner: false,
1301
+ });
1302
+ }
1303
+ }
1242
1304
  addSerumRemainingAccounts(marketIndex, remainingAccounts, fulfillmentConfig) {
1243
1305
  remainingAccounts.push({
1244
1306
  pubkey: fulfillmentConfig.pubkey,
@@ -1354,7 +1416,7 @@ class ClearingHouse {
1354
1416
  }
1355
1417
  async placeAndTakePerpOrder(orderParams, makerInfo, referrerInfo) {
1356
1418
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
1357
- this.marketLastSlotCache.set(orderParams.marketIndex, slot);
1419
+ this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1358
1420
  return txSig;
1359
1421
  }
1360
1422
  async getPlaceAndTakePerpOrderIx(orderParams, makerInfo, referrerInfo) {
@@ -1408,7 +1470,7 @@ class ClearingHouse {
1408
1470
  }
1409
1471
  async placeAndMakePerpOrder(orderParams, takerInfo, referrerInfo) {
1410
1472
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakePerpOrderIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
1411
- this.marketLastSlotCache.set(orderParams.marketIndex, slot);
1473
+ this.perpMarketLastSlotCache.set(orderParams.marketIndex, slot);
1412
1474
  return txSig;
1413
1475
  }
1414
1476
  async getPlaceAndMakePerpOrderIx(orderParams, takerInfo, referrerInfo) {
@@ -1446,7 +1508,9 @@ class ClearingHouse {
1446
1508
  });
1447
1509
  }
1448
1510
  async placeAndTakeSpotOrder(orderParams, fulfillmentConfig, makerInfo, referrerInfo) {
1449
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeSpotOrderIx(orderParams, fulfillmentConfig, makerInfo, referrerInfo)), [], this.opts);
1511
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeSpotOrderIx(orderParams, fulfillmentConfig, makerInfo, referrerInfo)), [], this.opts);
1512
+ this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
1513
+ this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
1450
1514
  return txSig;
1451
1515
  }
1452
1516
  async getPlaceAndTakeSpotOrderIx(orderParams, fulfillmentConfig, makerInfo, referrerInfo) {
@@ -1491,9 +1555,7 @@ class ClearingHouse {
1491
1555
  isSigner: false,
1492
1556
  });
1493
1557
  }
1494
- if (fulfillmentConfig) {
1495
- this.addSerumRemainingAccounts(orderParams.marketIndex, remainingAccounts, fulfillmentConfig);
1496
- }
1558
+ this.addSpotFulfillmentAccounts(orderParams.marketIndex, remainingAccounts, fulfillmentConfig);
1497
1559
  return await this.program.instruction.placeAndTakeSpotOrder(orderParams, fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null, makerOrderId, {
1498
1560
  accounts: {
1499
1561
  state: await this.getStatePublicKey(),
@@ -1504,11 +1566,13 @@ class ClearingHouse {
1504
1566
  remainingAccounts,
1505
1567
  });
1506
1568
  }
1507
- async placeAndMakeSpotOrder(orderParams, takerInfo, referrerInfo) {
1508
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeSpotOrderIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
1569
+ async placeAndMakeSpotOrder(orderParams, takerInfo, fulfillmentConfig, referrerInfo) {
1570
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeSpotOrderIx(orderParams, takerInfo, fulfillmentConfig, referrerInfo)), [], this.opts);
1571
+ this.spotMarketLastSlotCache.set(orderParams.marketIndex, slot);
1572
+ this.spotMarketLastSlotCache.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, slot);
1509
1573
  return txSig;
1510
1574
  }
1511
- async getPlaceAndMakeSpotOrderIx(orderParams, takerInfo, referrerInfo) {
1575
+ async getPlaceAndMakeSpotOrderIx(orderParams, takerInfo, fulfillmentConfig, referrerInfo) {
1512
1576
  orderParams = this.getOrderParams(orderParams, types_1.MarketType.SPOT);
1513
1577
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1514
1578
  const userAccountPublicKey = await this.getUserAccountPublicKey();
@@ -1532,8 +1596,9 @@ class ClearingHouse {
1532
1596
  isSigner: false,
1533
1597
  });
1534
1598
  }
1599
+ this.addSpotFulfillmentAccounts(orderParams.marketIndex, remainingAccounts, fulfillmentConfig);
1535
1600
  const takerOrderId = takerInfo.order.orderId;
1536
- return await this.program.instruction.placeAndMakeSpotOrder(orderParams, takerOrderId, {
1601
+ return await this.program.instruction.placeAndMakeSpotOrder(orderParams, takerOrderId, fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null, {
1537
1602
  accounts: {
1538
1603
  state: await this.getStatePublicKey(),
1539
1604
  user: userAccountPublicKey,
@@ -1564,6 +1629,53 @@ class ClearingHouse {
1564
1629
  price: limitPrice,
1565
1630
  });
1566
1631
  }
1632
+ /**
1633
+ * Modifies an open order by closing it and replacing it with a new order.
1634
+ * @param orderId: The open order to modify
1635
+ * @param newBaseAmount: The new base amount for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
1636
+ * @param newLimitPice: The new limit price for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
1637
+ * @param newOraclePriceOffset: The new oracle price offset for the order. One of [newBaseAmount|newLimitPrice|newOraclePriceOffset] must be provided.
1638
+ * @returns
1639
+ */
1640
+ async modifyPerpOrder(orderId, newBaseAmount, newLimitPrice, newOraclePriceOffset) {
1641
+ if (!newBaseAmount && !newLimitPrice && !newOraclePriceOffset) {
1642
+ throw new Error(`Must provide newBaseAmount or newLimitPrice or newOraclePriceOffset to modify order`);
1643
+ }
1644
+ const openOrder = this.getUser().getOrder(orderId);
1645
+ if (!openOrder) {
1646
+ throw new Error(`No open order with id ${orderId.toString()}`);
1647
+ }
1648
+ const cancelOrderIx = await this.getCancelOrderIx(orderId);
1649
+ const newOrderParams = {
1650
+ orderType: openOrder.orderType,
1651
+ marketType: openOrder.marketType,
1652
+ direction: openOrder.direction,
1653
+ baseAssetAmount: newBaseAmount || openOrder.baseAssetAmount,
1654
+ price: newLimitPrice || openOrder.price,
1655
+ marketIndex: openOrder.marketIndex,
1656
+ reduceOnly: openOrder.reduceOnly,
1657
+ postOnly: openOrder.postOnly,
1658
+ immediateOrCancel: openOrder.immediateOrCancel,
1659
+ triggerPrice: openOrder.triggerPrice,
1660
+ triggerCondition: openOrder.triggerCondition,
1661
+ oraclePriceOffset: newOraclePriceOffset || openOrder.oraclePriceOffset,
1662
+ auctionDuration: openOrder.auctionDuration,
1663
+ maxTs: openOrder.maxTs,
1664
+ auctionStartPrice: openOrder.auctionStartPrice,
1665
+ auctionEndPrice: openOrder.auctionEndPrice,
1666
+ };
1667
+ const placeOrderIx = await this.getPlacePerpOrderIx(newOrderParams);
1668
+ const tx = new web3_js_1.Transaction();
1669
+ tx.add(web3_js_1.ComputeBudgetProgram.requestUnits({
1670
+ units: 1000000,
1671
+ additionalFee: 0,
1672
+ }));
1673
+ tx.add(cancelOrderIx);
1674
+ tx.add(placeOrderIx);
1675
+ const { txSig, slot } = await this.txSender.send(tx, [], this.opts);
1676
+ this.perpMarketLastSlotCache.set(newOrderParams.marketIndex, slot);
1677
+ return txSig;
1678
+ }
1567
1679
  async settlePNLs(users, marketIndex) {
1568
1680
  const ixs = [];
1569
1681
  for (const { settleeUserAccountPublicKey, settleeUserAccount } of users) {
@@ -1593,16 +1705,17 @@ class ClearingHouse {
1593
1705
  state: await this.getStatePublicKey(),
1594
1706
  authority: this.wallet.publicKey,
1595
1707
  user: settleeUserAccountPublicKey,
1708
+ spotMarketVault: this.getQuoteSpotMarketAccount().vault,
1596
1709
  },
1597
1710
  remainingAccounts: remainingAccounts,
1598
1711
  });
1599
1712
  }
1600
- async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
1601
- const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount)), [], this.opts);
1602
- this.marketLastSlotCache.set(marketIndex, slot);
1713
+ async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount, limitPrice) {
1714
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount, limitPrice)), [], this.opts);
1715
+ this.perpMarketLastSlotCache.set(marketIndex, slot);
1603
1716
  return txSig;
1604
1717
  }
1605
- async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
1718
+ async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount, limitPrice) {
1606
1719
  const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1607
1720
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1608
1721
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
@@ -1611,7 +1724,7 @@ class ClearingHouse {
1611
1724
  useMarketLastSlotCache: true,
1612
1725
  writablePerpMarketIndexes: [marketIndex],
1613
1726
  });
1614
- return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
1727
+ return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, limitPrice !== null && limitPrice !== void 0 ? limitPrice : null, {
1615
1728
  accounts: {
1616
1729
  state: await this.getStatePublicKey(),
1617
1730
  authority: this.wallet.publicKey,
@@ -1624,7 +1737,9 @@ class ClearingHouse {
1624
1737
  });
1625
1738
  }
1626
1739
  async liquidateSpot(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1627
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1740
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1741
+ this.spotMarketLastSlotCache.set(assetMarketIndex, slot);
1742
+ this.spotMarketLastSlotCache.set(liabilityMarketIndex, slot);
1628
1743
  return txSig;
1629
1744
  }
1630
1745
  async getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
@@ -1650,7 +1765,8 @@ class ClearingHouse {
1650
1765
  }
1651
1766
  async liquidateBorrowForPerpPnl(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1652
1767
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1653
- this.marketLastSlotCache.set(perpMarketIndex, slot);
1768
+ this.perpMarketLastSlotCache.set(perpMarketIndex, slot);
1769
+ this.spotMarketLastSlotCache.set(liabilityMarketIndex, slot);
1654
1770
  return txSig;
1655
1771
  }
1656
1772
  async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
@@ -1676,7 +1792,8 @@ class ClearingHouse {
1676
1792
  }
1677
1793
  async liquidatePerpPnlForDeposit(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
1678
1794
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer)), [], this.opts);
1679
- this.marketLastSlotCache.set(perpMarketIndex, slot);
1795
+ this.perpMarketLastSlotCache.set(perpMarketIndex, slot);
1796
+ this.spotMarketLastSlotCache.set(assetMarketIndex, slot);
1680
1797
  return txSig;
1681
1798
  }
1682
1799
  async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {